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