Fix regression in gpg's mail address parsing.
[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 (GNUPG_INVALID_FD, 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   u16 desired_csum;
381   int skeyidx = 0;
382   struct seckey_info *ski;
383
384   top_list = gcry_sexp_find_token (s_pgp, "openpgp-private-key", 0);
385   if (!top_list)
386     goto bad_seckey;
387
388   list = gcry_sexp_find_token (top_list, "version", 0);
389   if (!list)
390     goto bad_seckey;
391   value = gcry_sexp_nth_data (list, 1, &valuelen);
392   if (!value || valuelen != 1 || !(value[0] == '3' || value[0] == '4'))
393     goto bad_seckey;
394   is_v4 = (value[0] == '4');
395
396   gcry_sexp_release (list);
397   list = gcry_sexp_find_token (top_list, "protection", 0);
398   if (!list)
399     goto bad_seckey;
400   value = gcry_sexp_nth_data (list, 1, &valuelen);
401   if (!value)
402     goto bad_seckey;
403   if (valuelen == 4 && !memcmp (value, "sha1", 4))
404     is_protected = 2;
405   else if (valuelen == 3 && !memcmp (value, "sum", 3))
406     is_protected = 1;
407   else if (valuelen == 4 && !memcmp (value, "none", 4))
408     is_protected = 0;
409   else
410     goto bad_seckey;
411   if (is_protected)
412     {
413       string = gcry_sexp_nth_string (list, 2);
414       if (!string)
415         goto bad_seckey;
416       protect_algo = gcry_cipher_map_name (string);
417       xfree (string);
418
419       value = gcry_sexp_nth_data (list, 3, &valuelen);
420       if (!value || !valuelen || valuelen > sizeof iv)
421         goto bad_seckey;
422       memcpy (iv, value, valuelen);
423       ivlen = valuelen;
424
425       string = gcry_sexp_nth_string (list, 4);
426       if (!string)
427         goto bad_seckey;
428       s2k_mode = strtol (string, NULL, 10);
429       xfree (string);
430
431       string = gcry_sexp_nth_string (list, 5);
432       if (!string)
433         goto bad_seckey;
434       s2k_algo = gcry_md_map_name (string);
435       xfree (string);
436
437       value = gcry_sexp_nth_data (list, 6, &valuelen);
438       if (!value || !valuelen || valuelen > sizeof s2k_salt)
439         goto bad_seckey;
440       memcpy (s2k_salt, value, valuelen);
441
442       string = gcry_sexp_nth_string (list, 7);
443       if (!string)
444         goto bad_seckey;
445       s2k_count = strtoul (string, NULL, 10);
446       xfree (string);
447     }
448
449   gcry_sexp_release (list);
450   list = gcry_sexp_find_token (top_list, "algo", 0);
451   if (!list)
452     goto bad_seckey;
453   string = gcry_sexp_nth_string (list, 1);
454   if (!string)
455     goto bad_seckey;
456   pubkey_algo = gcry_pk_map_name (string);
457   xfree (string);
458
459   if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey)
460       || gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey)
461       || !npkey || npkey >= nskey || nskey > PUBKEY_MAX_NSKEY)
462     goto bad_seckey;
463   pubkey_algo = map_pk_gcry_to_openpgp (pubkey_algo);
464
465   gcry_sexp_release (list);
466   list = gcry_sexp_find_token (top_list, "skey", 0);
467   if (!list)
468     goto bad_seckey;
469   for (idx=0;;)
470     {
471       int is_enc;
472
473       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
474       if (!value && skeyidx >= npkey)
475         break;  /* Ready.  */
476
477       /* Check for too many parameters.  Note that depending on the
478          protection mode and version number we may see less than NSKEY
479          (but at least NPKEY+1) parameters.  */
480       if (idx >= 2*nskey)
481         goto bad_seckey;
482       if (skeyidx >= DIM (skey)-1)
483         goto bad_seckey;
484
485       if (!value || valuelen != 1 || !(value[0] == '_' || value[0] == 'e'))
486         goto bad_seckey;
487       is_enc = (value[0] == 'e');
488       value = gcry_sexp_nth_data (list, ++idx, &valuelen);
489       if (!value || !valuelen)
490         goto bad_seckey;
491       if (is_enc)
492         {
493           void *p = xtrymalloc (valuelen);
494           if (!p)
495             goto outofmem;
496           memcpy (p, value, valuelen);
497           skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8);
498           if (!skey[skeyidx])
499             goto outofmem;
500         }
501       else
502         {
503           if (gcry_mpi_scan (skey + skeyidx, GCRYMPI_FMT_STD,
504                              value, valuelen, NULL))
505             goto bad_seckey;
506         }
507       skeyidx++;
508     }
509   skey[skeyidx++] = NULL;
510
511   gcry_sexp_release (list);
512   list = gcry_sexp_find_token (top_list, "csum", 0);
513   if (list)
514     {
515       string = gcry_sexp_nth_string (list, 1);
516       if (!string)
517         goto bad_seckey;
518       desired_csum = strtoul (string, NULL, 10);
519       xfree (string);
520     }
521   else
522     desired_csum = 0;
523
524
525   gcry_sexp_release (list); list = NULL;
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 || pubkey_algo == PUBKEY_ALGO_ECDH)
565     {
566       gcry_sexp_t s_pubkey;
567       const char *curvename, *curveoidstr;
568       gcry_mpi_t mpi;
569
570       /* We build an S-expression with the public key parameters and
571          ask Libgcrypt to return the matching curve name.  */
572       if (npkey != 6 || !skey[0] || !skey[1] || !skey[2]
573           || !skey[3] || !skey[4] || !skey[5]
574           || !skey[6] || skey[7])
575         {
576           err = gpg_error (GPG_ERR_INTERNAL);
577           goto leave;
578         }
579       err = gcry_sexp_build (&s_pubkey, NULL,
580                              "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))",
581                              skey[0], skey[1], skey[2], skey[3], skey[4]);
582       if (err)
583         goto leave;
584       curvename = gcry_pk_get_curve (s_pubkey, 0, NULL);
585       gcry_sexp_release (s_pubkey);
586       curveoidstr = gpg_curve_to_oid (curvename, NULL);
587       if (!curveoidstr)
588         {
589           log_error ("no OID known for curve `%s'\n", curvename);
590           err = gpg_error (GPG_ERR_UNKNOWN_NAME);
591           goto leave;
592         }
593       err = openpgp_oid_from_str (curveoidstr, &mpi);
594       if (err)
595         goto leave;
596
597       /* Now replace the curve parameters by the OID and shift the
598          rest of the parameters.  */
599       gcry_mpi_release (skey[0]);
600       skey[0] = mpi;
601       for (idx=1; idx <= 4; idx++)
602         gcry_mpi_release (skey[idx]);
603       skey[1] = skey[5];
604       skey[2] = skey[6];
605       for (idx=3; idx <= 6; idx++)
606         skey[idx] = NULL;
607
608       /* Fixup the NPKEY and NSKEY to match OpenPGP reality.  */
609       npkey = 2;
610       nskey = 3;
611
612       /* for (idx=0; skey[idx]; idx++) */
613       /*   { */
614       /*     log_info ("YYY skey[%d]:", idx); */
615       /*     if (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE)) */
616       /*       { */
617       /*         void *p; */
618       /*         unsigned int nbits; */
619       /*         p = gcry_mpi_get_opaque (skey[idx], &nbits); */
620       /*         log_printhex (NULL, p, (nbits+7)/8); */
621       /*       } */
622       /*     else */
623       /*       gcry_mpi_dump (skey[idx]); */
624       /*     log_printf ("\n"); */
625       /*   } */
626     }
627
628   /* Do some sanity checks.  */
629   if (s2k_count <= 1024)
630     {
631       /* The count must be larger so that encode_s2k_iterations does
632          not fall into a backward compatibility mode.  */
633       err = gpg_error (GPG_ERR_INV_DATA);
634       goto leave;
635     }
636   if (canon_pubkey_algo (pubkey_algo) != canon_pubkey_algo (pk->pubkey_algo))
637     {
638       err = gpg_error (GPG_ERR_PUBKEY_ALGO);
639       goto leave;
640     }
641   err = openpgp_cipher_test_algo (protect_algo);
642   if (err)
643     goto leave;
644   err = openpgp_md_test_algo (s2k_algo);
645   if (err)
646     goto leave;
647
648   /* Check that the public key parameters match.  Note that since
649      Libgcrypt 1.5 gcry_mpi_cmp handles opaque MPI correctly.  */
650   for (idx=0; idx < npkey; idx++)
651     if (gcry_mpi_cmp (pk->pkey[idx], skey[idx]))
652       {
653         err = gpg_error (GPG_ERR_BAD_PUBKEY);
654         goto leave;
655       }
656
657   /* Check that the first secret key parameter in SKEY is encrypted
658      and that there are no more secret key parameters.  The latter is
659      guaranteed by the v4 packet format.  */
660   if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE))
661     goto bad_seckey;
662   if (npkey+1 < DIM (skey) && skey[npkey+1])
663     goto bad_seckey;
664
665   /* Check that the secret key parameters in PK are all set to NULL. */
666   for (idx=npkey; idx < nskey; idx++)
667     if (pk->pkey[idx])
668       goto bad_seckey;
669
670   /* Now build the protection info. */
671   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
672   if (!ski)
673     {
674       err = gpg_error_from_syserror ();
675       goto leave;
676     }
677
678   ski->is_protected = 1;
679   ski->sha1chk = 1;
680   ski->algo = protect_algo;
681   ski->s2k.mode = s2k_mode;
682   ski->s2k.hash_algo = s2k_algo;
683   assert (sizeof ski->s2k.salt == sizeof s2k_salt);
684   memcpy (ski->s2k.salt, s2k_salt, sizeof s2k_salt);
685   ski->s2k.count = encode_s2k_iterations (s2k_count);
686   assert (ivlen <= sizeof ski->iv);
687   memcpy (ski->iv, iv, ivlen);
688   ski->ivlen = ivlen;
689
690   /* Store the protected secret key parameter.  */
691   pk->pkey[npkey] = skey[npkey];
692   skey[npkey] = NULL;
693
694   /* That's it.  */
695
696  leave:
697   gcry_sexp_release (list);
698   gcry_sexp_release (top_list);
699   for (idx=0; idx < skeyidx; idx++)
700     gcry_mpi_release (skey[idx]);
701   return err;
702
703  bad_seckey:
704   err = gpg_error (GPG_ERR_BAD_SECKEY);
705   goto leave;
706
707  outofmem:
708   err = gpg_error (GPG_ERR_ENOMEM);
709   goto leave;
710 }
711
712 /* Export the keys identified by the list of strings in USERS to the
713    stream OUT.  If Secret is false public keys will be exported.  With
714    secret true secret keys will be exported; in this case 1 means the
715    entire secret keyblock and 2 only the subkeys.  OPTIONS are the
716    export options to apply.  If KEYBLOCK_OUT is not NULL, AND the exit
717    code is zero, a pointer to the first keyblock found and exported
718    will be stored at this address; no other keyblocks are exported in
719    this case.  The caller must free it the returned keyblock.  If any
720    key has been exported true is stored at ANY. */
721 static int
722 do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
723                   kbnode_t *keyblock_out, unsigned int options, int *any)
724 {
725   gpg_error_t err = 0;
726   PACKET pkt;
727   KBNODE keyblock = NULL;
728   KBNODE kbctx, node;
729   size_t ndesc, descindex;
730   KEYDB_SEARCH_DESC *desc = NULL;
731   subkey_list_t subkey_list = NULL;  /* Track already processed subkeys. */
732   KEYDB_HANDLE kdbhd;
733   strlist_t sl;
734   int indent = 0;
735   gcry_cipher_hd_t cipherhd = NULL;
736
737   *any = 0;
738   init_packet (&pkt);
739   kdbhd = keydb_new ();
740
741   if (!users)
742     {
743       ndesc = 1;
744       desc = xcalloc (ndesc, sizeof *desc);
745       desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
746     }
747   else
748     {
749       for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
750         ;
751       desc = xmalloc ( ndesc * sizeof *desc);
752
753       for (ndesc=0, sl=users; sl; sl = sl->next)
754         {
755           if (!(err=classify_user_id (sl->d, desc+ndesc, 1)))
756             ndesc++;
757           else
758             log_error (_("key \"%s\" not found: %s\n"),
759                        sl->d, gpg_strerror (err));
760         }
761
762       /* It would be nice to see which of the given users did actually
763          match one in the keyring.  To implement this we need to have
764          a found flag for each entry in desc.  To set this flag we
765          must check all those entries after a match to mark all
766          matched one - currently we stop at the first match.  To do
767          this we need an extra flag to enable this feature.  */
768     }
769
770 #ifdef ENABLE_SELINUX_HACKS
771   if (secret)
772     {
773       log_error (_("exporting secret keys not allowed\n"));
774       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
775       goto leave;
776     }
777 #endif
778
779   /* For secret key export we need to setup a decryption context.  */
780   if (secret)
781     {
782       void *kek = NULL;
783       size_t keklen;
784
785       err = agent_keywrap_key (ctrl, 1, &kek, &keklen);
786       if (err)
787         {
788           log_error ("error getting the KEK: %s\n", gpg_strerror (err));
789           goto leave;
790         }
791
792       /* Prepare a cipher context.  */
793       err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
794                               GCRY_CIPHER_MODE_AESWRAP, 0);
795       if (!err)
796         err = gcry_cipher_setkey (cipherhd, kek, keklen);
797       if (err)
798         {
799           log_error ("error setting up an encryption context: %s\n",
800                      gpg_strerror (err));
801           goto leave;
802         }
803       xfree (kek);
804       kek = NULL;
805     }
806
807   while (!(err = keydb_search2 (kdbhd, desc, ndesc, &descindex)))
808     {
809       int skip_until_subkey = 0;
810       u32 keyid[2];
811       PKT_public_key *pk;
812
813       if (!users)
814         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
815
816       /* Read the keyblock. */
817       release_kbnode (keyblock);
818       keyblock = NULL;
819       err = keydb_get_keyblock (kdbhd, &keyblock);
820       if (err)
821         {
822           log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
823           goto leave;
824         }
825
826       node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
827       if (!node)
828         {
829           log_error ("public key packet not found in keyblock - skipped\n");
830           continue;
831         }
832       pk = node->pkt->pkt.public_key;
833       keyid_from_pk (pk, keyid);
834
835       /* If a secret key export is required we need to check whether
836          we have a secret key at all and if so create the seckey_info
837          structure.  */
838       if (secret)
839         {
840           if (agent_probe_any_secret_key (ctrl, keyblock))
841             continue;  /* No secret key (neither primary nor subkey).  */
842
843           /* No v3 keys with GNU mode 1001. */
844           if (secret == 2 && pk->version == 3)
845             {
846               log_info (_("key %s: PGP 2.x style key - skipped\n"),
847                         keystr (keyid));
848               continue;
849             }
850
851           /* The agent does not yet allow to export v3 packets.  It is
852              actually questionable whether we should allow them at
853              all.  */
854           if (pk->version == 3)
855             {
856               log_info ("key %s: PGP 2.x style key (v3) export "
857                         "not yet supported - skipped\n", keystr (keyid));
858               continue;
859             }
860         }
861
862       /* Always do the cleaning on the public key part if requested.
863          Note that we don't yet set this option if we are exporting
864          secret keys.  Note that both export-clean and export-minimal
865          only apply to UID sigs (0x10, 0x11, 0x12, and 0x13).  A
866          designated revocation is never stripped, even with
867          export-minimal set.  */
868       if ((options & EXPORT_CLEAN))
869         clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
870
871       /* And write it. */
872       for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
873         {
874           if (skip_until_subkey)
875             {
876               if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
877                 skip_until_subkey = 0;
878               else
879                 continue;
880             }
881
882           /* We used to use comment packets, but not any longer.  In
883              case we still have comments on a key, strip them here
884              before we call build_packet(). */
885           if (node->pkt->pkttype == PKT_COMMENT)
886             continue;
887
888           /* Make sure that ring_trust packets never get exported. */
889           if (node->pkt->pkttype == PKT_RING_TRUST)
890             continue;
891
892           /* If exact is set, then we only export what was requested
893              (plus the primary key, if the user didn't specifically
894              request it). */
895           if (desc[descindex].exact
896               && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
897             {
898               if (!exact_subkey_match_p (desc+descindex, node))
899                 {
900                   /* Before skipping this subkey, check whether any
901                      other description wants an exact match on a
902                      subkey and include that subkey into the output
903                      too.  Need to add this subkey to a list so that
904                      it won't get processed a second time.
905
906                      So the first step here is to check that list and
907                      skip in any case if the key is in that list.
908
909                      We need this whole mess because the import
910                      function of GnuPG < 2.1 is not able to merge
911                      secret keys and thus it is useless to output them
912                      as two separate keys and have import merge them.  */
913                   if (subkey_in_list_p (subkey_list, node))
914                     skip_until_subkey = 1; /* Already processed this one. */
915                   else
916                     {
917                       size_t j;
918
919                       for (j=0; j < ndesc; j++)
920                         if (j != descindex && desc[j].exact
921                             && exact_subkey_match_p (desc+j, node))
922                           break;
923                       if (!(j < ndesc))
924                         skip_until_subkey = 1; /* No other one matching. */
925                     }
926                 }
927
928               if(skip_until_subkey)
929                 continue;
930
931               /* Mark this one as processed. */
932               {
933                 subkey_list_t tmp = new_subkey_list_item (node);
934                 tmp->next = subkey_list;
935                 subkey_list = tmp;
936               }
937             }
938
939           if (node->pkt->pkttype == PKT_SIGNATURE)
940             {
941               /* Do not export packets which are marked as not
942                  exportable.  */
943               if (!(options&EXPORT_LOCAL_SIGS)
944                   && !node->pkt->pkt.signature->flags.exportable)
945                 continue; /* not exportable */
946
947               /* Do not export packets with a "sensitive" revocation
948                  key unless the user wants us to.  Note that we do
949                  export these when issuing the actual revocation
950                  (see revoke.c). */
951               if (!(options&EXPORT_SENSITIVE_REVKEYS)
952                   && node->pkt->pkt.signature->revkey)
953                 {
954                   int i;
955
956                   for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
957                     if ( (node->pkt->pkt.signature->revkey[i]->class & 0x40))
958                       break;
959
960                   if (i < node->pkt->pkt.signature->numrevkeys)
961                     continue;
962                 }
963             }
964
965           /* Don't export attribs? */
966           if (!(options&EXPORT_ATTRIBUTES)
967               && node->pkt->pkttype == PKT_USER_ID
968               && node->pkt->pkt.user_id->attrib_data )
969             {
970               /* Skip until we get to something that is not an attrib
971                  or a signature on an attrib */
972               while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
973                 kbctx = kbctx->next;
974
975               continue;
976             }
977
978           if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
979                          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
980             {
981               u32 subkidbuf[2], *subkid;
982               char *hexgrip, *serialno;
983
984               pk = node->pkt->pkt.public_key;
985               if (node->pkt->pkttype == PKT_PUBLIC_KEY)
986                 subkid = NULL;
987               else
988                 {
989                   keyid_from_pk (pk, subkidbuf);
990                   subkid = subkidbuf;
991                 }
992
993               if (pk->seckey_info)
994                 {
995                   log_error ("key %s: oops: seckey_info already set"
996                              " - skipped\n", keystr_with_sub (keyid, subkid));
997                   skip_until_subkey = 1;
998                   continue;
999                 }
1000
1001               err = hexkeygrip_from_pk (pk, &hexgrip);
1002               if (err)
1003                 {
1004                   log_error ("key %s: error computing keygrip: %s"
1005                              " - skipped\n", keystr_with_sub (keyid, subkid),
1006                              gpg_strerror (err));
1007                   skip_until_subkey = 1;
1008                   err = 0;
1009                   continue;
1010                 }
1011
1012               if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
1013                 {
1014                   /* We are asked not to export the secret parts of
1015                      the primary key.  Make up an error code to create
1016                      the stub.  */
1017                   err = GPG_ERR_NOT_FOUND;
1018                   serialno = NULL;
1019                 }
1020               else
1021                 err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
1022
1023               if ((!err && serialno)
1024                   && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
1025                 {
1026                   /* It does not make sense to export a key with its
1027                      primary key on card using a non-key stub.  Thus
1028                      we skip those keys when used with
1029                      --export-secret-subkeys. */
1030                   log_info (_("key %s: key material on-card - skipped\n"),
1031                             keystr_with_sub (keyid, subkid));
1032                   skip_until_subkey = 1;
1033                 }
1034               else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
1035                        || (!err && serialno))
1036                 {
1037                   /* Create a key stub.  */
1038                   struct seckey_info *ski;
1039                   const char *s;
1040
1041                   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
1042                   if (!ski)
1043                     {
1044                       err = gpg_error_from_syserror ();
1045                       xfree (hexgrip);
1046                       goto leave;
1047                     }
1048
1049                   ski->is_protected = 1;
1050                   if (err)
1051                     ski->s2k.mode = 1001; /* GNU dummy (no secret key).  */
1052                   else
1053                     {
1054                       ski->s2k.mode = 1002; /* GNU-divert-to-card.  */
1055                       for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
1056                            ski->ivlen++, s += 2)
1057                         ski->iv[ski->ivlen] = xtoi_2 (s);
1058                     }
1059
1060                   if ((options&EXPORT_SEXP_FORMAT))
1061                     err = build_sexp (out, node->pkt, &indent);
1062                   else
1063                     err = build_packet (out, node->pkt);
1064                 }
1065               else if (!err)
1066                 {
1067                   /* FIXME: Move this spaghetti code into a separate
1068                      function.  */
1069                   unsigned char *wrappedkey = NULL;
1070                   size_t wrappedkeylen;
1071                   unsigned char *key = NULL;
1072                   size_t keylen, realkeylen;
1073                   gcry_sexp_t s_skey;
1074
1075                   if (opt.verbose)
1076                     log_info ("key %s: asking agent for the secret parts\n",
1077                               keystr_with_sub (keyid, subkid));
1078
1079                   err = agent_export_key (ctrl, hexgrip, "Key foo", NULL,
1080                                           &wrappedkey, &wrappedkeylen);
1081                   if (err)
1082                     goto unwraperror;
1083                   if (wrappedkeylen < 24)
1084                     {
1085                       err = gpg_error (GPG_ERR_INV_LENGTH);
1086                       goto unwraperror;
1087                     }
1088                   keylen = wrappedkeylen - 8;
1089                   key = xtrymalloc_secure (keylen);
1090                   if (!key)
1091                     {
1092                       err = gpg_error_from_syserror ();
1093                       goto unwraperror;
1094                     }
1095                   err = gcry_cipher_decrypt (cipherhd, key, keylen,
1096                                              wrappedkey, wrappedkeylen);
1097                   if (err)
1098                     goto unwraperror;
1099                   realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
1100                   if (!realkeylen)
1101                     goto unwraperror; /* Invalid csexp.  */
1102
1103                   err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
1104                   xfree (key);
1105                   key = NULL;
1106                   if (err)
1107                     goto unwraperror;
1108                   err = transfer_format_to_openpgp (s_skey, pk);
1109                   gcry_sexp_release (s_skey);
1110                   if (err)
1111                     goto unwraperror;
1112
1113                   if ((options&EXPORT_SEXP_FORMAT))
1114                     err = build_sexp (out, node->pkt, &indent);
1115                   else
1116                     err = build_packet (out, node->pkt);
1117                   goto unwraperror_leave;
1118
1119                 unwraperror:
1120                   xfree (wrappedkey);
1121                   xfree (key);
1122                   if (err)
1123                     {
1124                       log_error ("key %s: error receiving key from agent:"
1125                                  " %s%s\n",
1126                                  keystr_with_sub (keyid, subkid),
1127                                  gpg_strerror (err),
1128                                  gpg_err_code (err) == GPG_ERR_FULLY_CANCELED?
1129                                  "":_(" - skipped"));
1130                       if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
1131                         goto leave;
1132                       skip_until_subkey = 1;
1133                       err = 0;
1134                     }
1135                 unwraperror_leave:
1136                   ;
1137                 }
1138               else
1139                 {
1140                   log_error ("key %s: error getting keyinfo from agent: %s"
1141                              " - skipped\n", keystr_with_sub (keyid, subkid),
1142                              gpg_strerror (err));
1143                   skip_until_subkey = 1;
1144                   err = 0;
1145                 }
1146
1147               xfree (pk->seckey_info);
1148               pk->seckey_info = NULL;
1149               xfree (hexgrip);
1150             }
1151           else
1152             {
1153               if ((options&EXPORT_SEXP_FORMAT))
1154                 err = build_sexp (out, node->pkt, &indent);
1155               else
1156                 err = build_packet (out, node->pkt);
1157             }
1158
1159           if (err)
1160             {
1161               log_error ("build_packet(%d) failed: %s\n",
1162                          node->pkt->pkttype, gpg_strerror (err));
1163               goto leave;
1164             }
1165
1166           if (!skip_until_subkey)
1167             *any = 1;
1168         }
1169
1170       if ((options&EXPORT_SEXP_FORMAT) && indent)
1171         {
1172           for (; indent; indent--)
1173             iobuf_put (out, ')');
1174           iobuf_put (out, '\n');
1175         }
1176
1177       if (keyblock_out)
1178         {
1179           *keyblock_out = keyblock;
1180           break;
1181         }
1182     }
1183   if ((options&EXPORT_SEXP_FORMAT) && indent)
1184     {
1185       for (; indent; indent--)
1186         iobuf_put (out, ')');
1187       iobuf_put (out, '\n');
1188     }
1189   if (err == -1)
1190     err = 0;
1191
1192  leave:
1193   gcry_cipher_close (cipherhd);
1194   release_subkey_list (subkey_list);
1195   xfree(desc);
1196   keydb_release (kdbhd);
1197   if (err || !keyblock_out)
1198     release_kbnode( keyblock );
1199   if( !*any )
1200     log_info(_("WARNING: nothing exported\n"));
1201   return err;
1202 }
1203
1204
1205
1206 /* static int */
1207 /* write_sexp_line (iobuf_t out, int *indent, const char *text) */
1208 /* { */
1209 /*   int i; */
1210
1211 /*   for (i=0; i < *indent; i++) */
1212 /*     iobuf_put (out, ' '); */
1213 /*   iobuf_writestr (out, text); */
1214 /*   return 0; */
1215 /* } */
1216
1217 /* static int */
1218 /* write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) */
1219 /* { */
1220 /*   int rc; */
1221 /*   unsigned char *buffer; */
1222
1223 /*   write_sexp_line (out, indent, "("); */
1224 /*   iobuf_writestr (out, name); */
1225 /*   iobuf_writestr (out, " #"); */
1226
1227 /*   rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); */
1228 /*   assert (!rc); */
1229 /*   iobuf_writestr (out, buffer); */
1230 /*   iobuf_writestr (out, "#)"); */
1231 /*   gcry_free (buffer); */
1232 /*   return 0; */
1233 /* } */
1234
1235 static int
1236 build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
1237 {
1238   (void)out;
1239   (void)pkt;
1240   (void)indent;
1241
1242   /* FIXME: Not yet implemented.  */
1243   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1244   /* PKT_secret_key *sk = pkt->pkt.secret_key; */
1245   /* char tmpbuf[100]; */
1246
1247   /* if (pkt->pkttype == PKT_SECRET_KEY) */
1248   /*   { */
1249   /*     iobuf_writestr (out, "(openpgp-key\n"); */
1250   /*     (*indent)++; */
1251   /*   } */
1252   /* else */
1253   /*   { */
1254   /*     iobuf_writestr (out, " (subkey\n"); */
1255   /*     (*indent)++; */
1256   /*   } */
1257   /* (*indent)++; */
1258   /* write_sexp_line (out, indent, "(private-key\n"); */
1259   /* (*indent)++; */
1260   /* if (is_RSA (sk->pubkey_algo) && !sk->is_protected) */
1261   /*   { */
1262   /*     write_sexp_line (out, indent, "(rsa\n"); */
1263   /*     (*indent)++; */
1264   /*     write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n'); */
1265   /*     write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n'); */
1266   /*     write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n'); */
1267   /*     write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n'); */
1268   /*     write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n'); */
1269   /*     write_sexp_keyparm (out, indent, "u", sk->skey[5]);  */
1270   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1271   /*     (*indent)--; */
1272   /*   } */
1273   /* else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected) */
1274   /*   { */
1275   /*     write_sexp_line (out, indent, "(dsa\n"); */
1276   /*     (*indent)++; */
1277   /*     write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
1278   /*     write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n'); */
1279   /*     write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
1280   /*     write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
1281   /*     write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
1282   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1283   /*     (*indent)--; */
1284   /*   } */
1285   /* else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) */
1286   /*   { */
1287   /*     write_sexp_line (out, indent, "(ecdsa\n"); */
1288   /*     (*indent)++;  */
1289   /*     write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); */
1290   /*     write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); */
1291   /*     write_sexp_keyparm (out, indent, "d", sk->skey[7]); */
1292   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1293   /*     (*indent)--; */
1294   /*   } */
1295   /* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
1296   /*   { */
1297   /*     write_sexp_line (out, indent, "(elg\n"); */
1298   /*     (*indent)++; */
1299   /*     write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
1300   /*     write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
1301   /*     write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
1302   /*     write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
1303   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1304   /*     (*indent)--; */
1305   /*   } */
1306   /* write_sexp_line (out, indent,  "(attrib\n"); (*indent)++; */
1307   /* sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp); */
1308   /* write_sexp_line (out, indent, tmpbuf); */
1309   /* iobuf_put (out,')'); (*indent)--; /\* close created *\/ */
1310   /* iobuf_put (out,')'); (*indent)--; /\* close attrib *\/ */
1311   /* iobuf_put (out,')'); (*indent)--; /\* close private-key *\/ */
1312   /* if (pkt->pkttype != PKT_SECRET_KEY) */
1313   /*   iobuf_put (out,')'), (*indent)--; /\* close subkey *\/ */
1314   /* iobuf_put (out,'\n'); */
1315
1316   /* return 0; */
1317 }
1318
1319
1320 /* For some packet types we write them in a S-expression format.  This
1321    is still EXPERIMENTAL and subject to change.  */
1322 static int
1323 build_sexp (iobuf_t out, PACKET *pkt, int *indent)
1324 {
1325   int rc;
1326
1327   switch (pkt->pkttype)
1328     {
1329     case PKT_SECRET_KEY:
1330     case PKT_SECRET_SUBKEY:
1331       rc = build_sexp_seckey (out, pkt, indent);
1332       break;
1333     default:
1334       rc = 0;
1335       break;
1336     }
1337   return rc;
1338 }