62802d394887deba573bda558587a301fe6dd96b
[platform/upstream/gpg2.git] / g10 / export.c
1 /* export.c - Export keys in the OpenPGP defined format.
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3  *               2005, 2010 Free Software Foundation, Inc.
4  * Copyright (C) 2014  Werner Koch
5  *
6  * This file is part of GnuPG.
7  *
8  * GnuPG is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * GnuPG is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28
29 #include "gpg.h"
30 #include "options.h"
31 #include "packet.h"
32 #include "status.h"
33 #include "keydb.h"
34 #include "util.h"
35 #include "main.h"
36 #include "i18n.h"
37 #include "trustdb.h"
38 #include "call-agent.h"
39
40 /* An object to keep track of subkeys. */
41 struct subkey_list_s
42 {
43   struct subkey_list_s *next;
44   u32 kid[2];
45 };
46 typedef struct subkey_list_s *subkey_list_t;
47
48
49 static int do_export (ctrl_t ctrl,
50                       strlist_t users, int secret, unsigned int options );
51 static int do_export_stream (ctrl_t ctrl, iobuf_t out,
52                              strlist_t users, int secret,
53                              kbnode_t *keyblock_out, unsigned int options,
54                              int *any);
55 static int build_sexp (iobuf_t out, PACKET *pkt, int *indent);
56
57
58 int
59 parse_export_options(char *str,unsigned int *options,int noisy)
60 {
61   struct parse_options export_opts[]=
62     {
63       {"export-local-sigs",EXPORT_LOCAL_SIGS,NULL,
64        N_("export signatures that are marked as local-only")},
65       {"export-attributes",EXPORT_ATTRIBUTES,NULL,
66        N_("export attribute user IDs (generally photo IDs)")},
67       {"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
68        N_("export revocation keys marked as \"sensitive\"")},
69       {"export-clean",EXPORT_CLEAN,NULL,
70        N_("remove unusable parts from key during export")},
71       {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
72        N_("remove as much as possible from key during export")},
73       {"export-sexp-format",EXPORT_SEXP_FORMAT, NULL,
74        N_("export keys in an S-expression based format")},
75       /* Aliases for backward compatibility */
76       {"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
77       {"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
78       {"include-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,NULL},
79       /* dummy */
80       {"export-unusable-sigs",0,NULL,NULL},
81       {"export-clean-sigs",0,NULL,NULL},
82       {"export-clean-uids",0,NULL,NULL},
83       {NULL,0,NULL,NULL}
84       /* add tags for include revoked and disabled? */
85     };
86
87   return parse_options(str,options,export_opts,noisy);
88 }
89
90
91 /****************
92  * Export the public keys (to standard out or --output).
93  * Depending on opt.armor the output is armored.
94  * options are defined in main.h.
95  * If USERS is NULL, the complete ring will be exported.  */
96 int
97 export_pubkeys (ctrl_t ctrl, strlist_t users, unsigned int options )
98 {
99   return do_export (ctrl, users, 0, options );
100 }
101
102 /****************
103  * Export to an already opened stream; return -1 if no keys have
104  * been exported
105  */
106 int
107 export_pubkeys_stream (ctrl_t ctrl, iobuf_t out, strlist_t users,
108                        kbnode_t *keyblock_out, unsigned int options )
109 {
110   int any, rc;
111
112   rc = do_export_stream (ctrl, out, users, 0, keyblock_out, options, &any);
113   if (!rc && !any)
114     rc = -1;
115   return rc;
116 }
117
118
119 /*
120  * Export a single key into a memory buffer.
121  */
122 gpg_error_t
123 export_pubkey_buffer (ctrl_t ctrl, const char *keyspec, unsigned int options,
124                       kbnode_t *r_keyblock, void **r_data, size_t *r_datalen)
125 {
126   gpg_error_t err;
127   iobuf_t iobuf;
128   int any;
129   strlist_t helplist;
130
131   *r_keyblock = NULL;
132   *r_data = NULL;
133   *r_datalen = 0;
134
135   helplist = NULL;
136   if (!add_to_strlist_try (&helplist, keyspec))
137     return gpg_error_from_syserror ();
138
139   iobuf = iobuf_temp ();
140   err = do_export_stream (ctrl, iobuf, helplist, 0, r_keyblock, options, &any);
141   if (!err && !any)
142     err = gpg_error (GPG_ERR_NOT_FOUND);
143   if (!err)
144     {
145       const void *src;
146       size_t datalen;
147
148       iobuf_flush_temp (iobuf);
149       src = iobuf_get_temp_buffer (iobuf);
150       datalen = iobuf_get_temp_length (iobuf);
151       if (!datalen)
152         err = gpg_error (GPG_ERR_NO_PUBKEY);
153       else if (!(*r_data = xtrymalloc (datalen)))
154         err = gpg_error_from_syserror ();
155       else
156         {
157           memcpy (*r_data, src, datalen);
158           *r_datalen = datalen;
159         }
160     }
161   iobuf_close (iobuf);
162   free_strlist (helplist);
163   if (err && *r_keyblock)
164     {
165       release_kbnode (*r_keyblock);
166       *r_keyblock = NULL;
167     }
168   return err;
169 }
170
171
172 int
173 export_seckeys (ctrl_t ctrl, strlist_t users )
174 {
175   /* Use only relevant options for the secret key. */
176   unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
177   return do_export (ctrl, users, 1, options);
178 }
179
180 int
181 export_secsubkeys (ctrl_t ctrl, strlist_t users )
182 {
183   /* Use only relevant options for the secret key. */
184   unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
185   return do_export (ctrl, users, 2, options);
186 }
187
188
189 /* Export the keys identified by the list of strings in USERS.  If
190    Secret is false public keys will be exported.  With secret true
191    secret keys will be exported; in this case 1 means the entire
192    secret keyblock and 2 only the subkeys.  OPTIONS are the export
193    options to apply.  */
194 static int
195 do_export (ctrl_t ctrl, strlist_t users, int secret, unsigned int options )
196 {
197   IOBUF out = NULL;
198   int any, rc;
199   armor_filter_context_t *afx = NULL;
200   compress_filter_context_t zfx;
201
202   memset( &zfx, 0, sizeof zfx);
203
204   rc = open_outfile (-1, NULL, 0, !!secret, &out );
205   if (rc)
206     return rc;
207
208   if (!(options & EXPORT_SEXP_FORMAT))
209     {
210       if ( opt.armor )
211         {
212           afx = new_armor_context ();
213           afx->what = secret? 5 : 1;
214           push_armor_filter (afx, out);
215         }
216     }
217
218   rc = do_export_stream (ctrl, out, users, secret, NULL, options, &any );
219
220   if ( rc || !any )
221     iobuf_cancel (out);
222   else
223     iobuf_close (out);
224   release_armor_context (afx);
225   return rc;
226 }
227
228
229
230 /* Release an entire subkey list. */
231 static void
232 release_subkey_list (subkey_list_t list)
233 {
234   while (list)
235     {
236       subkey_list_t tmp = list->next;;
237       xfree (list);
238       list = tmp;
239     }
240 }
241
242
243 /* Returns true if NODE is a subkey and contained in LIST. */
244 static int
245 subkey_in_list_p (subkey_list_t list, KBNODE node)
246 {
247   if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
248       || node->pkt->pkttype == PKT_SECRET_SUBKEY )
249     {
250       u32 kid[2];
251
252       keyid_from_pk (node->pkt->pkt.public_key, kid);
253
254       for (; list; list = list->next)
255         if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
256           return 1;
257     }
258   return 0;
259 }
260
261 /* Allocate a new subkey list item from NODE. */
262 static subkey_list_t
263 new_subkey_list_item (KBNODE node)
264 {
265   subkey_list_t list = xcalloc (1, sizeof *list);
266
267   if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
268       || node->pkt->pkttype == PKT_SECRET_SUBKEY)
269     keyid_from_pk (node->pkt->pkt.public_key, list->kid);
270
271   return list;
272 }
273
274
275 /* Helper function to check whether the subkey at NODE actually
276    matches the description at DESC.  The function returns true if the
277    key under question has been specified by an exact specification
278    (keyID or fingerprint) and does match the one at NODE.  It is
279    assumed that the packet at NODE is either a public or secret
280    subkey. */
281 static int
282 exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
283 {
284   u32 kid[2];
285   byte fpr[MAX_FINGERPRINT_LEN];
286   size_t fprlen;
287   int result = 0;
288
289   switch(desc->mode)
290     {
291     case KEYDB_SEARCH_MODE_SHORT_KID:
292     case KEYDB_SEARCH_MODE_LONG_KID:
293       keyid_from_pk (node->pkt->pkt.public_key, kid);
294       break;
295
296     case KEYDB_SEARCH_MODE_FPR16:
297     case KEYDB_SEARCH_MODE_FPR20:
298     case KEYDB_SEARCH_MODE_FPR:
299       fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
300       break;
301
302     default:
303       break;
304     }
305
306   switch(desc->mode)
307     {
308     case KEYDB_SEARCH_MODE_SHORT_KID:
309       if (desc->u.kid[1] == kid[1])
310         result = 1;
311       break;
312
313     case KEYDB_SEARCH_MODE_LONG_KID:
314       if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
315         result = 1;
316       break;
317
318     case KEYDB_SEARCH_MODE_FPR16:
319       if (!memcmp (desc->u.fpr, fpr, 16))
320         result = 1;
321       break;
322
323     case KEYDB_SEARCH_MODE_FPR20:
324     case KEYDB_SEARCH_MODE_FPR:
325       if (!memcmp (desc->u.fpr, fpr, 20))
326         result = 1;
327       break;
328
329     default:
330       break;
331     }
332
333   return result;
334 }
335
336
337 /* Return a canonicalized public key algoithms.  This is used to
338    compare different flavors of algorithms (e.g. ELG and ELG_E are
339    considered the same).  */
340 static enum gcry_pk_algos
341 canon_pk_algo (enum gcry_pk_algos algo)
342 {
343   switch (algo)
344     {
345     case GCRY_PK_RSA:
346     case GCRY_PK_RSA_E:
347     case GCRY_PK_RSA_S: return GCRY_PK_RSA;
348     case GCRY_PK_ELG:
349     case GCRY_PK_ELG_E: return GCRY_PK_ELG;
350     case GCRY_PK_ECC:
351     case GCRY_PK_ECDSA:
352     case GCRY_PK_ECDH: return GCRY_PK_ECC;
353     default: return algo;
354     }
355 }
356
357
358 /* Use the key transfer format given in S_PGP to create the secinfo
359    structure in PK and change the parameter array in PK to include the
360    secret parameters.  */
361 static gpg_error_t
362 transfer_format_to_openpgp (gcry_sexp_t s_pgp, PKT_public_key *pk)
363 {
364   gpg_error_t err;
365   gcry_sexp_t top_list;
366   gcry_sexp_t list = NULL;
367   char *curve = NULL;
368   const char *value;
369   size_t valuelen;
370   char *string;
371   int  idx;
372   int  is_v4, is_protected;
373   enum gcry_pk_algos pk_algo;
374   int  protect_algo = 0;
375   char iv[16];
376   int  ivlen = 0;
377   int  s2k_mode = 0;
378   int  s2k_algo = 0;
379   byte s2k_salt[8];
380   u32  s2k_count = 0;
381   int  is_ecdh = 0;
382   size_t npkey, nskey;
383   gcry_mpi_t skey[10];  /* We support up to 9 parameters.  */
384   int skeyidx = 0;
385   struct seckey_info *ski;
386
387   /* gcry_log_debugsxp ("transferkey", s_pgp); */
388   top_list = gcry_sexp_find_token (s_pgp, "openpgp-private-key", 0);
389   if (!top_list)
390     goto bad_seckey;
391
392   list = gcry_sexp_find_token (top_list, "version", 0);
393   if (!list)
394     goto bad_seckey;
395   value = gcry_sexp_nth_data (list, 1, &valuelen);
396   if (!value || valuelen != 1 || !(value[0] == '3' || value[0] == '4'))
397     goto bad_seckey;
398   is_v4 = (value[0] == '4');
399
400   gcry_sexp_release (list);
401   list = gcry_sexp_find_token (top_list, "protection", 0);
402   if (!list)
403     goto bad_seckey;
404   value = gcry_sexp_nth_data (list, 1, &valuelen);
405   if (!value)
406     goto bad_seckey;
407   if (valuelen == 4 && !memcmp (value, "sha1", 4))
408     is_protected = 2;
409   else if (valuelen == 3 && !memcmp (value, "sum", 3))
410     is_protected = 1;
411   else if (valuelen == 4 && !memcmp (value, "none", 4))
412     is_protected = 0;
413   else
414     goto bad_seckey;
415   if (is_protected)
416     {
417       string = gcry_sexp_nth_string (list, 2);
418       if (!string)
419         goto bad_seckey;
420       protect_algo = gcry_cipher_map_name (string);
421       xfree (string);
422
423       value = gcry_sexp_nth_data (list, 3, &valuelen);
424       if (!value || !valuelen || valuelen > sizeof iv)
425         goto bad_seckey;
426       memcpy (iv, value, valuelen);
427       ivlen = valuelen;
428
429       string = gcry_sexp_nth_string (list, 4);
430       if (!string)
431         goto bad_seckey;
432       s2k_mode = strtol (string, NULL, 10);
433       xfree (string);
434
435       string = gcry_sexp_nth_string (list, 5);
436       if (!string)
437         goto bad_seckey;
438       s2k_algo = gcry_md_map_name (string);
439       xfree (string);
440
441       value = gcry_sexp_nth_data (list, 6, &valuelen);
442       if (!value || !valuelen || valuelen > sizeof s2k_salt)
443         goto bad_seckey;
444       memcpy (s2k_salt, value, valuelen);
445
446       string = gcry_sexp_nth_string (list, 7);
447       if (!string)
448         goto bad_seckey;
449       s2k_count = strtoul (string, NULL, 10);
450       xfree (string);
451     }
452
453   /* Parse the gcrypt PK algo and check that it is okay.  */
454   gcry_sexp_release (list);
455   list = gcry_sexp_find_token (top_list, "algo", 0);
456   if (!list)
457     goto bad_seckey;
458   string = gcry_sexp_nth_string (list, 1);
459   if (!string)
460     goto bad_seckey;
461   pk_algo = gcry_pk_map_name (string);
462   xfree (string); string = NULL;
463   if (gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
464       || gcry_pk_algo_info (pk_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
465       || !npkey || npkey >= nskey)
466     goto bad_seckey;
467
468   /* Check that the pubkey algo matches the one from the public key.  */
469   switch (canon_pk_algo (pk_algo))
470     {
471     case GCRY_PK_RSA:
472       if (!is_RSA (pk->pubkey_algo))
473         pk_algo = 0;  /* Does not match.  */
474       break;
475     case GCRY_PK_DSA:
476       if (!is_DSA (pk->pubkey_algo))
477         pk_algo = 0;  /* Does not match.  */
478       break;
479     case GCRY_PK_ELG:
480       if (!is_ELGAMAL (pk->pubkey_algo))
481         pk_algo = 0;  /* Does not match.  */
482       break;
483     case GCRY_PK_ECC:
484       if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA)
485         ;
486       else if (pk->pubkey_algo == PUBKEY_ALGO_ECDH)
487         is_ecdh = 1;
488       else if (pk->pubkey_algo == PUBKEY_ALGO_EDDSA)
489         ;
490       else
491         pk_algo = 0;  /* Does not match.  */
492       /* For ECC we do not have the domain parameters thus fix our info.  */
493       npkey = 1;
494       nskey = 2;
495       break;
496     default:
497       pk_algo = 0;   /* Oops.  */
498       break;
499     }
500   if (!pk_algo)
501     {
502       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
503       goto leave;
504     }
505
506   /* This check has to go after the ecc adjustments. */
507   if (nskey > PUBKEY_MAX_NSKEY)
508     goto bad_seckey;
509
510   /* Parse the key parameters.  */
511   gcry_sexp_release (list);
512   list = gcry_sexp_find_token (top_list, "skey", 0);
513   if (!list)
514     goto bad_seckey;
515   for (idx=0;;)
516     {
517       int is_enc;
518
519       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
520       if (!value && skeyidx >= npkey)
521         break;  /* Ready.  */
522
523       /* Check for too many parameters.  Note that depending on the
524          protection mode and version number we may see less than NSKEY
525          (but at least NPKEY+1) parameters.  */
526       if (idx >= 2*nskey)
527         goto bad_seckey;
528       if (skeyidx >= DIM (skey)-1)
529         goto bad_seckey;
530
531       if (!value || valuelen != 1 || !(value[0] == '_' || value[0] == 'e'))
532         goto bad_seckey;
533       is_enc = (value[0] == 'e');
534       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
535       if (!value || !valuelen)
536         goto bad_seckey;
537       if (is_enc)
538         {
539           void *p = xtrymalloc (valuelen);
540           if (!p)
541             goto outofmem;
542           memcpy (p, value, valuelen);
543           skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8);
544           if (!skey[skeyidx])
545             goto outofmem;
546         }
547       else
548         {
549           if (gcry_mpi_scan (skey + skeyidx, GCRYMPI_FMT_STD,
550                              value, valuelen, NULL))
551             goto bad_seckey;
552         }
553       skeyidx++;
554     }
555   skey[skeyidx++] = NULL;
556
557   gcry_sexp_release (list); list = NULL;
558
559   /* We have no need for the CSUM value thus we don't parse it.  */
560   /* list = gcry_sexp_find_token (top_list, "csum", 0); */
561   /* if (list) */
562   /*   { */
563   /*     string = gcry_sexp_nth_string (list, 1); */
564   /*     if (!string) */
565   /*       goto bad_seckey; */
566   /*     desired_csum = strtoul (string, NULL, 10); */
567   /*     xfree (string); */
568   /*   } */
569   /* else */
570   /*   desired_csum = 0; */
571   /* gcry_sexp_release (list); list = NULL; */
572
573   /* Get the curve name if any,  */
574   list = gcry_sexp_find_token (top_list, "curve", 0);
575   if (list)
576     {
577       curve = gcry_sexp_nth_string (list, 1);
578       gcry_sexp_release (list); list = NULL;
579     }
580
581   gcry_sexp_release (top_list); top_list = NULL;
582
583   /* log_debug ("XXX is_v4=%d\n", is_v4); */
584   /* log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); */
585   /* log_debug ("XXX is_protected=%d\n", is_protected); */
586   /* log_debug ("XXX protect_algo=%d\n", protect_algo); */
587   /* log_printhex ("XXX iv", iv, ivlen); */
588   /* log_debug ("XXX ivlen=%d\n", ivlen); */
589   /* log_debug ("XXX s2k_mode=%d\n", s2k_mode); */
590   /* log_debug ("XXX s2k_algo=%d\n", s2k_algo); */
591   /* log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); */
592   /* log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); */
593   /* for (idx=0; skey[idx]; idx++) */
594   /*   { */
595   /*     int is_enc = gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE); */
596   /*     log_info ("XXX skey[%d]%s:", idx, is_enc? " (enc)":""); */
597   /*     if (is_enc) */
598   /*       { */
599   /*         void *p; */
600   /*         unsigned int nbits; */
601   /*         p = gcry_mpi_get_opaque (skey[idx], &nbits); */
602   /*         log_printhex (NULL, p, (nbits+7)/8); */
603   /*       } */
604   /*     else */
605   /*       gcry_mpi_dump (skey[idx]); */
606   /*     log_printf ("\n"); */
607   /*   } */
608
609   if (!is_v4 || is_protected != 2 )
610     {
611       /* We only support the v4 format and a SHA-1 checksum.  */
612       err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
613       goto leave;
614     }
615
616   /* We need to change the received parameters for ECC algorithms.
617      The transfer format has the curve name and the parameters
618      separate.  We put them all into the SKEY array.  */
619   if (canon_pk_algo (pk_algo) == GCRY_PK_ECC)
620     {
621       const char *oidstr;
622
623       /* Assert that all required parameters are available.  We also
624          check that the array does not contain more parameters than
625          needed (this was used by some beta versions of 2.1.  */
626       if (!curve || !skey[0] || !skey[1] || skey[2])
627         {
628           err = gpg_error (GPG_ERR_INTERNAL);
629           goto leave;
630         }
631
632       oidstr = openpgp_curve_to_oid (curve, NULL);
633       if (!oidstr)
634         {
635           log_error ("no OID known for curve '%s'\n", curve);
636           err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
637           goto leave;
638         }
639       /* Put the curve's OID into into the MPI array.  This requires
640          that we shift Q and D.  For ECDH also insert the KDF parms. */
641       if (is_ecdh)
642         {
643           skey[4] = NULL;
644           skey[3] = skey[1];
645           skey[2] = gcry_mpi_copy (pk->pkey[2]);
646         }
647       else
648         {
649           skey[3] = NULL;
650           skey[2] = skey[1];
651         }
652       skey[1] = skey[0];
653       skey[0] = NULL;
654       err = openpgp_oid_from_str (oidstr, skey + 0);
655       if (err)
656         goto leave;
657       /* Fixup the NPKEY and NSKEY to match OpenPGP reality.  */
658       npkey = 2 + is_ecdh;
659       nskey = 3 + is_ecdh;
660
661       /* for (idx=0; skey[idx]; idx++) */
662       /*   { */
663       /*     log_info ("YYY skey[%d]:", idx); */
664       /*     if (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)) */
665       /*       { */
666       /*         void *p; */
667       /*         unsigned int nbits; */
668       /*         p = gcry_mpi_get_opaque (skey[idx], &nbits); */
669       /*         log_printhex (NULL, p, (nbits+7)/8); */
670       /*       } */
671       /*     else */
672       /*       gcry_mpi_dump (skey[idx]); */
673       /*     log_printf ("\n"); */
674       /*   } */
675     }
676
677   /* Do some sanity checks.  */
678   if (s2k_count > 255)
679     {
680       /* We expect an already encoded S2K count.  */
681       err = gpg_error (GPG_ERR_INV_DATA);
682       goto leave;
683     }
684   err = openpgp_cipher_test_algo (protect_algo);
685   if (err)
686     goto leave;
687   err = openpgp_md_test_algo (s2k_algo);
688   if (err)
689     goto leave;
690
691   /* Check that the public key parameters match.  Note that since
692      Libgcrypt 1.5 gcry_mpi_cmp handles opaque MPI correctly.  */
693   for (idx=0; idx < npkey; idx++)
694     if (gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
695       {
696         err = gpg_error (GPG_ERR_BAD_PUBKEY);
697         goto leave;
698       }
699
700   /* Check that the first secret key parameter in SKEY is encrypted
701      and that there are no more secret key parameters.  The latter is
702      guaranteed by the v4 packet format.  */
703   if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE))
704     goto bad_seckey;
705   if (npkey+1 < DIM (skey) && skey[npkey+1])
706     goto bad_seckey;
707
708   /* Check that the secret key parameters in PK are all set to NULL. */
709   for (idx=npkey; idx < nskey; idx++)
710     if (pk->pkey[idx])
711       goto bad_seckey;
712
713   /* Now build the protection info. */
714   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
715   if (!ski)
716     {
717       err = gpg_error_from_syserror ();
718       goto leave;
719     }
720
721   ski->is_protected = 1;
722   ski->sha1chk = 1;
723   ski->algo = protect_algo;
724   ski->s2k.mode = s2k_mode;
725   ski->s2k.hash_algo = s2k_algo;
726   assert (sizeof ski->s2k.salt == sizeof s2k_salt);
727   memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
728   ski->s2k.count = s2k_count;
729   assert (ivlen <= sizeof ski->iv);
730   memcpy (ski->iv, iv, ivlen);
731   ski->ivlen = ivlen;
732
733   /* Store the protected secret key parameter.  */
734   pk->pkey[npkey] = skey[npkey];
735   skey[npkey] = NULL;
736
737   /* That's it.  */
738
739  leave:
740   gcry_free (curve);
741   gcry_sexp_release (list);
742   gcry_sexp_release (top_list);
743   for (idx=0; idx < skeyidx; idx++)
744     gcry_mpi_release (skey[idx]);
745   return err;
746
747  bad_seckey:
748   err = gpg_error (GPG_ERR_BAD_SECKEY);
749   goto leave;
750
751  outofmem:
752   err = gpg_error (GPG_ERR_ENOMEM);
753   goto leave;
754 }
755
756 /* Export the keys identified by the list of strings in USERS to the
757    stream OUT.  If Secret is false public keys will be exported.  With
758    secret true secret keys will be exported; in this case 1 means the
759    entire secret keyblock and 2 only the subkeys.  OPTIONS are the
760    export options to apply.  If KEYBLOCK_OUT is not NULL, AND the exit
761    code is zero, a pointer to the first keyblock found and exported
762    will be stored at this address; no other keyblocks are exported in
763    this case.  The caller must free it the returned keyblock.  If any
764    key has been exported true is stored at ANY. */
765 static int
766 do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
767                   kbnode_t *keyblock_out, unsigned int options, int *any)
768 {
769   gpg_error_t err = 0;
770   PACKET pkt;
771   KBNODE keyblock = NULL;
772   KBNODE kbctx, node;
773   size_t ndesc, descindex;
774   KEYDB_SEARCH_DESC *desc = NULL;
775   subkey_list_t subkey_list = NULL;  /* Track already processed subkeys. */
776   KEYDB_HANDLE kdbhd;
777   strlist_t sl;
778   int indent = 0;
779   gcry_cipher_hd_t cipherhd = NULL;
780   char *cache_nonce = NULL;
781
782   *any = 0;
783   init_packet (&pkt);
784   kdbhd = keydb_new ();
785
786   if (!users)
787     {
788       ndesc = 1;
789       desc = xcalloc (ndesc, sizeof *desc);
790       desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
791     }
792   else
793     {
794       for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
795         ;
796       desc = xmalloc ( ndesc * sizeof *desc);
797
798       for (ndesc=0, sl=users; sl; sl = sl->next)
799         {
800           if (!(err=classify_user_id (sl->d, desc+ndesc, 1)))
801             ndesc++;
802           else
803             log_error (_("key \"%s\" not found: %s\n"),
804                        sl->d, gpg_strerror (err));
805         }
806
807       keydb_disable_caching (kdbhd);  /* We are looping the search.  */
808
809       /* It would be nice to see which of the given users did actually
810          match one in the keyring.  To implement this we need to have
811          a found flag for each entry in desc.  To set this flag we
812          must check all those entries after a match to mark all
813          matched one - currently we stop at the first match.  To do
814          this we need an extra flag to enable this feature.  */
815     }
816
817 #ifdef ENABLE_SELINUX_HACKS
818   if (secret)
819     {
820       log_error (_("exporting secret keys not allowed\n"));
821       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
822       goto leave;
823     }
824 #endif
825
826   /* For secret key export we need to setup a decryption context.  */
827   if (secret)
828     {
829       void *kek = NULL;
830       size_t keklen;
831
832       err = agent_keywrap_key (ctrl, 1, &kek, &keklen);
833       if (err)
834         {
835           log_error ("error getting the KEK: %s\n", gpg_strerror (err));
836           goto leave;
837         }
838
839       /* Prepare a cipher context.  */
840       err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
841                               GCRY_CIPHER_MODE_AESWRAP, 0);
842       if (!err)
843         err = gcry_cipher_setkey (cipherhd, kek, keklen);
844       if (err)
845         {
846           log_error ("error setting up an encryption context: %s\n",
847                      gpg_strerror (err));
848           goto leave;
849         }
850       xfree (kek);
851       kek = NULL;
852     }
853
854   for (;;)
855     {
856       int skip_until_subkey = 0;
857       u32 keyid[2];
858       PKT_public_key *pk;
859
860       err = keydb_search (kdbhd, desc, ndesc, &descindex);
861       if (!users)
862         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
863       if (gpg_err_code (err) == GPG_ERR_LEGACY_KEY)
864         continue;  /* Skip PGP2 keys.  */
865       if (err)
866         break;
867
868       /* Read the keyblock. */
869       release_kbnode (keyblock);
870       keyblock = NULL;
871       err = keydb_get_keyblock (kdbhd, &keyblock);
872       if (gpg_err_code (err) == GPG_ERR_LEGACY_KEY)
873         continue;  /* Skip PGP2 keys.  */
874       if (err)
875         {
876           log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
877           goto leave;
878         }
879
880       node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
881       if (!node)
882         {
883           log_error ("public key packet not found in keyblock - skipped\n");
884           continue;
885         }
886       setup_main_keyids (keyblock);  /* gpg_format_keydesc needs it.  */
887       pk = node->pkt->pkt.public_key;
888       keyid_from_pk (pk, keyid);
889
890       /* If a secret key export is required we need to check whether
891          we have a secret key at all and if so create the seckey_info
892          structure.  */
893       if (secret)
894         {
895           if (agent_probe_any_secret_key (ctrl, keyblock))
896             continue;  /* No secret key (neither primary nor subkey).  */
897
898           /* No v3 keys with GNU mode 1001. */
899           if (secret == 2 && pk->version == 3)
900             {
901               log_info (_("key %s: PGP 2.x style key - skipped\n"),
902                         keystr (keyid));
903               continue;
904             }
905
906           /* The agent does not yet allow to export v3 packets.  It is
907              actually questionable whether we should allow them at
908              all.  */
909           if (pk->version == 3)
910             {
911               log_info ("key %s: PGP 2.x style key (v3) export "
912                         "not yet supported - skipped\n", keystr (keyid));
913               continue;
914             }
915         }
916
917       /* Always do the cleaning on the public key part if requested.
918          Note that we don't yet set this option if we are exporting
919          secret keys.  Note that both export-clean and export-minimal
920          only apply to UID sigs (0x10, 0x11, 0x12, and 0x13).  A
921          designated revocation is never stripped, even with
922          export-minimal set.  */
923       if ((options & EXPORT_CLEAN))
924         clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
925
926       /* And write it. */
927       xfree (cache_nonce);
928       cache_nonce = NULL;
929       for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
930         {
931           if (skip_until_subkey)
932             {
933               if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
934                 skip_until_subkey = 0;
935               else
936                 continue;
937             }
938
939           /* We used to use comment packets, but not any longer.  In
940              case we still have comments on a key, strip them here
941              before we call build_packet(). */
942           if (node->pkt->pkttype == PKT_COMMENT)
943             continue;
944
945           /* Make sure that ring_trust packets never get exported. */
946           if (node->pkt->pkttype == PKT_RING_TRUST)
947             continue;
948
949           /* If exact is set, then we only export what was requested
950              (plus the primary key, if the user didn't specifically
951              request it). */
952           if (desc[descindex].exact
953               && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
954             {
955               if (!exact_subkey_match_p (desc+descindex, node))
956                 {
957                   /* Before skipping this subkey, check whether any
958                      other description wants an exact match on a
959                      subkey and include that subkey into the output
960                      too.  Need to add this subkey to a list so that
961                      it won't get processed a second time.
962
963                      So the first step here is to check that list and
964                      skip in any case if the key is in that list.
965
966                      We need this whole mess because the import
967                      function of GnuPG < 2.1 is not able to merge
968                      secret keys and thus it is useless to output them
969                      as two separate keys and have import merge them.  */
970                   if (subkey_in_list_p (subkey_list, node))
971                     skip_until_subkey = 1; /* Already processed this one. */
972                   else
973                     {
974                       size_t j;
975
976                       for (j=0; j < ndesc; j++)
977                         if (j != descindex && desc[j].exact
978                             && exact_subkey_match_p (desc+j, node))
979                           break;
980                       if (!(j < ndesc))
981                         skip_until_subkey = 1; /* No other one matching. */
982                     }
983                 }
984
985               if(skip_until_subkey)
986                 continue;
987
988               /* Mark this one as processed. */
989               {
990                 subkey_list_t tmp = new_subkey_list_item (node);
991                 tmp->next = subkey_list;
992                 subkey_list = tmp;
993               }
994             }
995
996           if (node->pkt->pkttype == PKT_SIGNATURE)
997             {
998               /* Do not export packets which are marked as not
999                  exportable.  */
1000               if (!(options&EXPORT_LOCAL_SIGS)
1001                   && !node->pkt->pkt.signature->flags.exportable)
1002                 continue; /* not exportable */
1003
1004               /* Do not export packets with a "sensitive" revocation
1005                  key unless the user wants us to.  Note that we do
1006                  export these when issuing the actual revocation
1007                  (see revoke.c). */
1008               if (!(options&EXPORT_SENSITIVE_REVKEYS)
1009                   && node->pkt->pkt.signature->revkey)
1010                 {
1011                   int i;
1012
1013                   for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
1014                     if ( (node->pkt->pkt.signature->revkey[i].class & 0x40))
1015                       break;
1016
1017                   if (i < node->pkt->pkt.signature->numrevkeys)
1018                     continue;
1019                 }
1020             }
1021
1022           /* Don't export attribs? */
1023           if (!(options&EXPORT_ATTRIBUTES)
1024               && node->pkt->pkttype == PKT_USER_ID
1025               && node->pkt->pkt.user_id->attrib_data )
1026             {
1027               /* Skip until we get to something that is not an attrib
1028                  or a signature on an attrib */
1029               while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
1030                 kbctx = kbctx->next;
1031
1032               continue;
1033             }
1034
1035           if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
1036                          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
1037             {
1038               u32 subkidbuf[2], *subkid;
1039               char *hexgrip, *serialno;
1040
1041               pk = node->pkt->pkt.public_key;
1042               if (node->pkt->pkttype == PKT_PUBLIC_KEY)
1043                 subkid = NULL;
1044               else
1045                 {
1046                   keyid_from_pk (pk, subkidbuf);
1047                   subkid = subkidbuf;
1048                 }
1049
1050               if (pk->seckey_info)
1051                 {
1052                   log_error ("key %s: oops: seckey_info already set"
1053                              " - skipped\n", keystr_with_sub (keyid, subkid));
1054                   skip_until_subkey = 1;
1055                   continue;
1056                 }
1057
1058               err = hexkeygrip_from_pk (pk, &hexgrip);
1059               if (err)
1060                 {
1061                   log_error ("key %s: error computing keygrip: %s"
1062                              " - skipped\n", keystr_with_sub (keyid, subkid),
1063                              gpg_strerror (err));
1064                   skip_until_subkey = 1;
1065                   err = 0;
1066                   continue;
1067                 }
1068
1069               if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
1070                 {
1071                   /* We are asked not to export the secret parts of
1072                      the primary key.  Make up an error code to create
1073                      the stub.  */
1074                   err = GPG_ERR_NOT_FOUND;
1075                   serialno = NULL;
1076                 }
1077               else
1078                 err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
1079
1080               if ((!err && serialno)
1081                   && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
1082                 {
1083                   /* It does not make sense to export a key with its
1084                      primary key on card using a non-key stub.  Thus
1085                      we skip those keys when used with
1086                      --export-secret-subkeys. */
1087                   log_info (_("key %s: key material on-card - skipped\n"),
1088                             keystr_with_sub (keyid, subkid));
1089                   skip_until_subkey = 1;
1090                 }
1091               else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
1092                        || (!err && serialno))
1093                 {
1094                   /* Create a key stub.  */
1095                   struct seckey_info *ski;
1096                   const char *s;
1097
1098                   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
1099                   if (!ski)
1100                     {
1101                       err = gpg_error_from_syserror ();
1102                       xfree (hexgrip);
1103                       goto leave;
1104                     }
1105
1106                   ski->is_protected = 1;
1107                   if (err)
1108                     ski->s2k.mode = 1001; /* GNU dummy (no secret key).  */
1109                   else
1110                     {
1111                       ski->s2k.mode = 1002; /* GNU-divert-to-card.  */
1112                       for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
1113                            ski->ivlen++, s += 2)
1114                         ski->iv[ski->ivlen] = xtoi_2 (s);
1115                     }
1116
1117                   if ((options&EXPORT_SEXP_FORMAT))
1118                     err = build_sexp (out, node->pkt, &indent);
1119                   else
1120                     err = build_packet (out, node->pkt);
1121                 }
1122               else if (!err)
1123                 {
1124                   /* FIXME: Move this spaghetti code into a separate
1125                      function.  */
1126                   unsigned char *wrappedkey = NULL;
1127                   size_t wrappedkeylen;
1128                   unsigned char *key = NULL;
1129                   size_t keylen, realkeylen;
1130                   gcry_sexp_t s_skey;
1131
1132                   if (opt.verbose)
1133                     log_info ("key %s: asking agent for the secret parts\n",
1134                               keystr_with_sub (keyid, subkid));
1135
1136                   {
1137                     char *prompt = gpg_format_keydesc (pk,
1138                                                        FORMAT_KEYDESC_EXPORT,1);
1139                     err = agent_export_key (ctrl, hexgrip, prompt, &cache_nonce,
1140                                             &wrappedkey, &wrappedkeylen);
1141                     xfree (prompt);
1142                   }
1143                   if (err)
1144                     goto unwraperror;
1145                   if (wrappedkeylen < 24)
1146                     {
1147                       err = gpg_error (GPG_ERR_INV_LENGTH);
1148                       goto unwraperror;
1149                     }
1150                   keylen = wrappedkeylen - 8;
1151                   key = xtrymalloc_secure (keylen);
1152                   if (!key)
1153                     {
1154                       err = gpg_error_from_syserror ();
1155                       goto unwraperror;
1156                     }
1157                   err = gcry_cipher_decrypt (cipherhd, key, keylen,
1158                                              wrappedkey, wrappedkeylen);
1159                   if (err)
1160                     goto unwraperror;
1161                   realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
1162                   if (!realkeylen)
1163                     goto unwraperror; /* Invalid csexp.  */
1164
1165                   err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
1166                   xfree (key);
1167                   key = NULL;
1168                   if (err)
1169                     goto unwraperror;
1170                   err = transfer_format_to_openpgp (s_skey, pk);
1171                   gcry_sexp_release (s_skey);
1172                   if (err)
1173                     goto unwraperror;
1174
1175                   if ((options&EXPORT_SEXP_FORMAT))
1176                     err = build_sexp (out, node->pkt, &indent);
1177                   else
1178                     err = build_packet (out, node->pkt);
1179                   goto unwraperror_leave;
1180
1181                 unwraperror:
1182                   xfree (wrappedkey);
1183                   xfree (key);
1184                   if (err)
1185                     {
1186                       log_error ("key %s: error receiving key from agent:"
1187                                  " %s%s\n",
1188                                  keystr_with_sub (keyid, subkid),
1189                                  gpg_strerror (err),
1190                                  gpg_err_code (err) == GPG_ERR_FULLY_CANCELED?
1191                                  "":_(" - skipped"));
1192                       if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
1193                         goto leave;
1194                       skip_until_subkey = 1;
1195                       err = 0;
1196                     }
1197                 unwraperror_leave:
1198                   ;
1199                 }
1200               else
1201                 {
1202                   log_error ("key %s: error getting keyinfo from agent: %s"
1203                              " - skipped\n", keystr_with_sub (keyid, subkid),
1204                              gpg_strerror (err));
1205                   skip_until_subkey = 1;
1206                   err = 0;
1207                 }
1208
1209               xfree (pk->seckey_info);
1210               pk->seckey_info = NULL;
1211               xfree (hexgrip);
1212             }
1213           else
1214             {
1215               if ((options&EXPORT_SEXP_FORMAT))
1216                 err = build_sexp (out, node->pkt, &indent);
1217               else
1218                 err = build_packet (out, node->pkt);
1219             }
1220
1221           if (err)
1222             {
1223               log_error ("build_packet(%d) failed: %s\n",
1224                          node->pkt->pkttype, gpg_strerror (err));
1225               goto leave;
1226             }
1227
1228           if (!skip_until_subkey)
1229             *any = 1;
1230         }
1231
1232       if ((options&EXPORT_SEXP_FORMAT) && indent)
1233         {
1234           for (; indent; indent--)
1235             iobuf_put (out, ')');
1236           iobuf_put (out, '\n');
1237         }
1238
1239       if (keyblock_out)
1240         {
1241           *keyblock_out = keyblock;
1242           break;
1243         }
1244     }
1245   if ((options&EXPORT_SEXP_FORMAT) && indent)
1246     {
1247       for (; indent; indent--)
1248         iobuf_put (out, ')');
1249       iobuf_put (out, '\n');
1250     }
1251   if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
1252     err = 0;
1253
1254  leave:
1255   gcry_cipher_close (cipherhd);
1256   release_subkey_list (subkey_list);
1257   xfree(desc);
1258   keydb_release (kdbhd);
1259   if (err || !keyblock_out)
1260     release_kbnode( keyblock );
1261   xfree (cache_nonce);
1262   if( !*any )
1263     log_info(_("WARNING: nothing exported\n"));
1264   return err;
1265 }
1266
1267
1268
1269 /* static int */
1270 /* write_sexp_line (iobuf_t out, int *indent, const char *text) */
1271 /* { */
1272 /*   int i; */
1273
1274 /*   for (i=0; i < *indent; i++) */
1275 /*     iobuf_put (out, ' '); */
1276 /*   iobuf_writestr (out, text); */
1277 /*   return 0; */
1278 /* } */
1279
1280 /* static int */
1281 /* write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) */
1282 /* { */
1283 /*   int rc; */
1284 /*   unsigned char *buffer; */
1285
1286 /*   write_sexp_line (out, indent, "("); */
1287 /*   iobuf_writestr (out, name); */
1288 /*   iobuf_writestr (out, " #"); */
1289
1290 /*   rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); */
1291 /*   assert (!rc); */
1292 /*   iobuf_writestr (out, buffer); */
1293 /*   iobuf_writestr (out, "#)"); */
1294 /*   gcry_free (buffer); */
1295 /*   return 0; */
1296 /* } */
1297
1298 static int
1299 build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
1300 {
1301   (void)out;
1302   (void)pkt;
1303   (void)indent;
1304
1305   /* FIXME: Not yet implemented.  */
1306   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1307   /* PKT_secret_key *sk = pkt->pkt.secret_key; */
1308   /* char tmpbuf[100]; */
1309
1310   /* if (pkt->pkttype == PKT_SECRET_KEY) */
1311   /*   { */
1312   /*     iobuf_writestr (out, "(openpgp-key\n"); */
1313   /*     (*indent)++; */
1314   /*   } */
1315   /* else */
1316   /*   { */
1317   /*     iobuf_writestr (out, " (subkey\n"); */
1318   /*     (*indent)++; */
1319   /*   } */
1320   /* (*indent)++; */
1321   /* write_sexp_line (out, indent, "(private-key\n"); */
1322   /* (*indent)++; */
1323   /* if (is_RSA (sk->pubkey_algo) && !sk->is_protected) */
1324   /*   { */
1325   /*     write_sexp_line (out, indent, "(rsa\n"); */
1326   /*     (*indent)++; */
1327   /*     write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n'); */
1328   /*     write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n'); */
1329   /*     write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n'); */
1330   /*     write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n'); */
1331   /*     write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n'); */
1332   /*     write_sexp_keyparm (out, indent, "u", sk->skey[5]);  */
1333   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1334   /*     (*indent)--; */
1335   /*   } */
1336   /* else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected) */
1337   /*   { */
1338   /*     write_sexp_line (out, indent, "(dsa\n"); */
1339   /*     (*indent)++; */
1340   /*     write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
1341   /*     write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n'); */
1342   /*     write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
1343   /*     write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
1344   /*     write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
1345   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1346   /*     (*indent)--; */
1347   /*   } */
1348   /* else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) */
1349   /*   { */
1350   /*     write_sexp_line (out, indent, "(ecdsa\n"); */
1351   /*     (*indent)++;  */
1352   /*     write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); */
1353   /*     write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); */
1354   /*     write_sexp_keyparm (out, indent, "d", sk->skey[7]); */
1355   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1356   /*     (*indent)--; */
1357   /*   } */
1358   /* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
1359   /*   { */
1360   /*     write_sexp_line (out, indent, "(elg\n"); */
1361   /*     (*indent)++; */
1362   /*     write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
1363   /*     write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
1364   /*     write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
1365   /*     write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
1366   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1367   /*     (*indent)--; */
1368   /*   } */
1369   /* write_sexp_line (out, indent,  "(attrib\n"); (*indent)++; */
1370   /* sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp); */
1371   /* write_sexp_line (out, indent, tmpbuf); */
1372   /* iobuf_put (out,')'); (*indent)--; /\* close created *\/ */
1373   /* iobuf_put (out,')'); (*indent)--; /\* close attrib *\/ */
1374   /* iobuf_put (out,')'); (*indent)--; /\* close private-key *\/ */
1375   /* if (pkt->pkttype != PKT_SECRET_KEY) */
1376   /*   iobuf_put (out,')'), (*indent)--; /\* close subkey *\/ */
1377   /* iobuf_put (out,'\n'); */
1378
1379   /* return 0; */
1380 }
1381
1382
1383 /* For some packet types we write them in a S-expression format.  This
1384    is still EXPERIMENTAL and subject to change.  */
1385 static int
1386 build_sexp (iobuf_t out, PACKET *pkt, int *indent)
1387 {
1388   int rc;
1389
1390   switch (pkt->pkttype)
1391     {
1392     case PKT_SECRET_KEY:
1393     case PKT_SECRET_SUBKEY:
1394       rc = build_sexp_seckey (out, pkt, indent);
1395       break;
1396     default:
1397       rc = 0;
1398       break;
1399     }
1400   return rc;
1401 }