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