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