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