gpg: Write a status line for a failed --send-keys.
[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   char *cache_nonce = NULL;
781
782   *any = 0;
783   init_packet (&pkt);
784   kdbhd = keydb_new ();
785
786   if (!users)
787     {
788       ndesc = 1;
789       desc = xcalloc (ndesc, sizeof *desc);
790       desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
791     }
792   else
793     {
794       for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
795         ;
796       desc = xmalloc ( ndesc * sizeof *desc);
797
798       for (ndesc=0, sl=users; sl; sl = sl->next)
799         {
800           if (!(err=classify_user_id (sl->d, desc+ndesc, 1)))
801             ndesc++;
802           else
803             log_error (_("key \"%s\" not found: %s\n"),
804                        sl->d, gpg_strerror (err));
805         }
806
807       keydb_disable_caching (kdbhd);  /* We are looping the search.  */
808
809       /* It would be nice to see which of the given users did actually
810          match one in the keyring.  To implement this we need to have
811          a found flag for each entry in desc.  To set this flag we
812          must check all those entries after a match to mark all
813          matched one - currently we stop at the first match.  To do
814          this we need an extra flag to enable this feature.  */
815     }
816
817 #ifdef ENABLE_SELINUX_HACKS
818   if (secret)
819     {
820       log_error (_("exporting secret keys not allowed\n"));
821       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
822       goto leave;
823     }
824 #endif
825
826   /* For secret key export we need to setup a decryption context.  */
827   if (secret)
828     {
829       void *kek = NULL;
830       size_t keklen;
831
832       err = agent_keywrap_key (ctrl, 1, &kek, &keklen);
833       if (err)
834         {
835           log_error ("error getting the KEK: %s\n", gpg_strerror (err));
836           goto leave;
837         }
838
839       /* Prepare a cipher context.  */
840       err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
841                               GCRY_CIPHER_MODE_AESWRAP, 0);
842       if (!err)
843         err = gcry_cipher_setkey (cipherhd, kek, keklen);
844       if (err)
845         {
846           log_error ("error setting up an encryption context: %s\n",
847                      gpg_strerror (err));
848           goto leave;
849         }
850       xfree (kek);
851       kek = NULL;
852     }
853
854   while (!(err = keydb_search (kdbhd, desc, ndesc, &descindex)))
855     {
856       int skip_until_subkey = 0;
857       u32 keyid[2];
858       PKT_public_key *pk;
859
860       if (!users)
861         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
862
863       /* Read the keyblock. */
864       release_kbnode (keyblock);
865       keyblock = NULL;
866       err = keydb_get_keyblock (kdbhd, &keyblock);
867       if (err)
868         {
869           log_error (_("error reading keyblock: %s\n"), gpg_strerror (err));
870           goto leave;
871         }
872
873       node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
874       if (!node)
875         {
876           log_error ("public key packet not found in keyblock - skipped\n");
877           continue;
878         }
879       setup_main_keyids (keyblock);  /* gpg_format_keydesc needs it.  */
880       pk = node->pkt->pkt.public_key;
881       keyid_from_pk (pk, keyid);
882
883       /* If a secret key export is required we need to check whether
884          we have a secret key at all and if so create the seckey_info
885          structure.  */
886       if (secret)
887         {
888           if (agent_probe_any_secret_key (ctrl, keyblock))
889             continue;  /* No secret key (neither primary nor subkey).  */
890
891           /* No v3 keys with GNU mode 1001. */
892           if (secret == 2 && pk->version == 3)
893             {
894               log_info (_("key %s: PGP 2.x style key - skipped\n"),
895                         keystr (keyid));
896               continue;
897             }
898
899           /* The agent does not yet allow to export v3 packets.  It is
900              actually questionable whether we should allow them at
901              all.  */
902           if (pk->version == 3)
903             {
904               log_info ("key %s: PGP 2.x style key (v3) export "
905                         "not yet supported - skipped\n", keystr (keyid));
906               continue;
907             }
908         }
909
910       /* Always do the cleaning on the public key part if requested.
911          Note that we don't yet set this option if we are exporting
912          secret keys.  Note that both export-clean and export-minimal
913          only apply to UID sigs (0x10, 0x11, 0x12, and 0x13).  A
914          designated revocation is never stripped, even with
915          export-minimal set.  */
916       if ((options & EXPORT_CLEAN))
917         clean_key (keyblock, opt.verbose, (options&EXPORT_MINIMAL), NULL, NULL);
918
919       /* And write it. */
920       xfree (cache_nonce);
921       cache_nonce = NULL;
922       for (kbctx=NULL; (node = walk_kbnode (keyblock, &kbctx, 0)); )
923         {
924           if (skip_until_subkey)
925             {
926               if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
927                 skip_until_subkey = 0;
928               else
929                 continue;
930             }
931
932           /* We used to use comment packets, but not any longer.  In
933              case we still have comments on a key, strip them here
934              before we call build_packet(). */
935           if (node->pkt->pkttype == PKT_COMMENT)
936             continue;
937
938           /* Make sure that ring_trust packets never get exported. */
939           if (node->pkt->pkttype == PKT_RING_TRUST)
940             continue;
941
942           /* If exact is set, then we only export what was requested
943              (plus the primary key, if the user didn't specifically
944              request it). */
945           if (desc[descindex].exact
946               && node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
947             {
948               if (!exact_subkey_match_p (desc+descindex, node))
949                 {
950                   /* Before skipping this subkey, check whether any
951                      other description wants an exact match on a
952                      subkey and include that subkey into the output
953                      too.  Need to add this subkey to a list so that
954                      it won't get processed a second time.
955
956                      So the first step here is to check that list and
957                      skip in any case if the key is in that list.
958
959                      We need this whole mess because the import
960                      function of GnuPG < 2.1 is not able to merge
961                      secret keys and thus it is useless to output them
962                      as two separate keys and have import merge them.  */
963                   if (subkey_in_list_p (subkey_list, node))
964                     skip_until_subkey = 1; /* Already processed this one. */
965                   else
966                     {
967                       size_t j;
968
969                       for (j=0; j < ndesc; j++)
970                         if (j != descindex && desc[j].exact
971                             && exact_subkey_match_p (desc+j, node))
972                           break;
973                       if (!(j < ndesc))
974                         skip_until_subkey = 1; /* No other one matching. */
975                     }
976                 }
977
978               if(skip_until_subkey)
979                 continue;
980
981               /* Mark this one as processed. */
982               {
983                 subkey_list_t tmp = new_subkey_list_item (node);
984                 tmp->next = subkey_list;
985                 subkey_list = tmp;
986               }
987             }
988
989           if (node->pkt->pkttype == PKT_SIGNATURE)
990             {
991               /* Do not export packets which are marked as not
992                  exportable.  */
993               if (!(options&EXPORT_LOCAL_SIGS)
994                   && !node->pkt->pkt.signature->flags.exportable)
995                 continue; /* not exportable */
996
997               /* Do not export packets with a "sensitive" revocation
998                  key unless the user wants us to.  Note that we do
999                  export these when issuing the actual revocation
1000                  (see revoke.c). */
1001               if (!(options&EXPORT_SENSITIVE_REVKEYS)
1002                   && node->pkt->pkt.signature->revkey)
1003                 {
1004                   int i;
1005
1006                   for (i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
1007                     if ( (node->pkt->pkt.signature->revkey[i]->class & 0x40))
1008                       break;
1009
1010                   if (i < node->pkt->pkt.signature->numrevkeys)
1011                     continue;
1012                 }
1013             }
1014
1015           /* Don't export attribs? */
1016           if (!(options&EXPORT_ATTRIBUTES)
1017               && node->pkt->pkttype == PKT_USER_ID
1018               && node->pkt->pkt.user_id->attrib_data )
1019             {
1020               /* Skip until we get to something that is not an attrib
1021                  or a signature on an attrib */
1022               while (kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE)
1023                 kbctx = kbctx->next;
1024
1025               continue;
1026             }
1027
1028           if (secret && (node->pkt->pkttype == PKT_PUBLIC_KEY
1029                          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY))
1030             {
1031               u32 subkidbuf[2], *subkid;
1032               char *hexgrip, *serialno;
1033
1034               pk = node->pkt->pkt.public_key;
1035               if (node->pkt->pkttype == PKT_PUBLIC_KEY)
1036                 subkid = NULL;
1037               else
1038                 {
1039                   keyid_from_pk (pk, subkidbuf);
1040                   subkid = subkidbuf;
1041                 }
1042
1043               if (pk->seckey_info)
1044                 {
1045                   log_error ("key %s: oops: seckey_info already set"
1046                              " - skipped\n", keystr_with_sub (keyid, subkid));
1047                   skip_until_subkey = 1;
1048                   continue;
1049                 }
1050
1051               err = hexkeygrip_from_pk (pk, &hexgrip);
1052               if (err)
1053                 {
1054                   log_error ("key %s: error computing keygrip: %s"
1055                              " - skipped\n", keystr_with_sub (keyid, subkid),
1056                              gpg_strerror (err));
1057                   skip_until_subkey = 1;
1058                   err = 0;
1059                   continue;
1060                 }
1061
1062               if (secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
1063                 {
1064                   /* We are asked not to export the secret parts of
1065                      the primary key.  Make up an error code to create
1066                      the stub.  */
1067                   err = GPG_ERR_NOT_FOUND;
1068                   serialno = NULL;
1069                 }
1070               else
1071                 err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
1072
1073               if ((!err && serialno)
1074                   && secret == 2 && node->pkt->pkttype == PKT_PUBLIC_KEY)
1075                 {
1076                   /* It does not make sense to export a key with its
1077                      primary key on card using a non-key stub.  Thus
1078                      we skip those keys when used with
1079                      --export-secret-subkeys. */
1080                   log_info (_("key %s: key material on-card - skipped\n"),
1081                             keystr_with_sub (keyid, subkid));
1082                   skip_until_subkey = 1;
1083                 }
1084               else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND
1085                        || (!err && serialno))
1086                 {
1087                   /* Create a key stub.  */
1088                   struct seckey_info *ski;
1089                   const char *s;
1090
1091                   pk->seckey_info = ski = xtrycalloc (1, sizeof *ski);
1092                   if (!ski)
1093                     {
1094                       err = gpg_error_from_syserror ();
1095                       xfree (hexgrip);
1096                       goto leave;
1097                     }
1098
1099                   ski->is_protected = 1;
1100                   if (err)
1101                     ski->s2k.mode = 1001; /* GNU dummy (no secret key).  */
1102                   else
1103                     {
1104                       ski->s2k.mode = 1002; /* GNU-divert-to-card.  */
1105                       for (s=serialno; sizeof (ski->ivlen) && *s && s[1];
1106                            ski->ivlen++, s += 2)
1107                         ski->iv[ski->ivlen] = xtoi_2 (s);
1108                     }
1109
1110                   if ((options&EXPORT_SEXP_FORMAT))
1111                     err = build_sexp (out, node->pkt, &indent);
1112                   else
1113                     err = build_packet (out, node->pkt);
1114                 }
1115               else if (!err)
1116                 {
1117                   /* FIXME: Move this spaghetti code into a separate
1118                      function.  */
1119                   unsigned char *wrappedkey = NULL;
1120                   size_t wrappedkeylen;
1121                   unsigned char *key = NULL;
1122                   size_t keylen, realkeylen;
1123                   gcry_sexp_t s_skey;
1124
1125                   if (opt.verbose)
1126                     log_info ("key %s: asking agent for the secret parts\n",
1127                               keystr_with_sub (keyid, subkid));
1128
1129                   {
1130                     char *prompt = gpg_format_keydesc (pk,
1131                                                        FORMAT_KEYDESC_EXPORT,1);
1132                     err = agent_export_key (ctrl, hexgrip, prompt, &cache_nonce,
1133                                             &wrappedkey, &wrappedkeylen);
1134                     xfree (prompt);
1135                   }
1136                   if (err)
1137                     goto unwraperror;
1138                   if (wrappedkeylen < 24)
1139                     {
1140                       err = gpg_error (GPG_ERR_INV_LENGTH);
1141                       goto unwraperror;
1142                     }
1143                   keylen = wrappedkeylen - 8;
1144                   key = xtrymalloc_secure (keylen);
1145                   if (!key)
1146                     {
1147                       err = gpg_error_from_syserror ();
1148                       goto unwraperror;
1149                     }
1150                   err = gcry_cipher_decrypt (cipherhd, key, keylen,
1151                                              wrappedkey, wrappedkeylen);
1152                   if (err)
1153                     goto unwraperror;
1154                   realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
1155                   if (!realkeylen)
1156                     goto unwraperror; /* Invalid csexp.  */
1157
1158                   err = gcry_sexp_sscan (&s_skey, NULL, key, realkeylen);
1159                   xfree (key);
1160                   key = NULL;
1161                   if (err)
1162                     goto unwraperror;
1163                   err = transfer_format_to_openpgp (s_skey, pk);
1164                   gcry_sexp_release (s_skey);
1165                   if (err)
1166                     goto unwraperror;
1167
1168                   if ((options&EXPORT_SEXP_FORMAT))
1169                     err = build_sexp (out, node->pkt, &indent);
1170                   else
1171                     err = build_packet (out, node->pkt);
1172                   goto unwraperror_leave;
1173
1174                 unwraperror:
1175                   xfree (wrappedkey);
1176                   xfree (key);
1177                   if (err)
1178                     {
1179                       log_error ("key %s: error receiving key from agent:"
1180                                  " %s%s\n",
1181                                  keystr_with_sub (keyid, subkid),
1182                                  gpg_strerror (err),
1183                                  gpg_err_code (err) == GPG_ERR_FULLY_CANCELED?
1184                                  "":_(" - skipped"));
1185                       if (gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
1186                         goto leave;
1187                       skip_until_subkey = 1;
1188                       err = 0;
1189                     }
1190                 unwraperror_leave:
1191                   ;
1192                 }
1193               else
1194                 {
1195                   log_error ("key %s: error getting keyinfo from agent: %s"
1196                              " - skipped\n", keystr_with_sub (keyid, subkid),
1197                              gpg_strerror (err));
1198                   skip_until_subkey = 1;
1199                   err = 0;
1200                 }
1201
1202               xfree (pk->seckey_info);
1203               pk->seckey_info = NULL;
1204               xfree (hexgrip);
1205             }
1206           else
1207             {
1208               if ((options&EXPORT_SEXP_FORMAT))
1209                 err = build_sexp (out, node->pkt, &indent);
1210               else
1211                 err = build_packet (out, node->pkt);
1212             }
1213
1214           if (err)
1215             {
1216               log_error ("build_packet(%d) failed: %s\n",
1217                          node->pkt->pkttype, gpg_strerror (err));
1218               goto leave;
1219             }
1220
1221           if (!skip_until_subkey)
1222             *any = 1;
1223         }
1224
1225       if ((options&EXPORT_SEXP_FORMAT) && indent)
1226         {
1227           for (; indent; indent--)
1228             iobuf_put (out, ')');
1229           iobuf_put (out, '\n');
1230         }
1231
1232       if (keyblock_out)
1233         {
1234           *keyblock_out = keyblock;
1235           break;
1236         }
1237     }
1238   if ((options&EXPORT_SEXP_FORMAT) && indent)
1239     {
1240       for (; indent; indent--)
1241         iobuf_put (out, ')');
1242       iobuf_put (out, '\n');
1243     }
1244   if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
1245     err = 0;
1246
1247  leave:
1248   gcry_cipher_close (cipherhd);
1249   release_subkey_list (subkey_list);
1250   xfree(desc);
1251   keydb_release (kdbhd);
1252   if (err || !keyblock_out)
1253     release_kbnode( keyblock );
1254   xfree (cache_nonce);
1255   if( !*any )
1256     log_info(_("WARNING: nothing exported\n"));
1257   return err;
1258 }
1259
1260
1261
1262 /* static int */
1263 /* write_sexp_line (iobuf_t out, int *indent, const char *text) */
1264 /* { */
1265 /*   int i; */
1266
1267 /*   for (i=0; i < *indent; i++) */
1268 /*     iobuf_put (out, ' '); */
1269 /*   iobuf_writestr (out, text); */
1270 /*   return 0; */
1271 /* } */
1272
1273 /* static int */
1274 /* write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a) */
1275 /* { */
1276 /*   int rc; */
1277 /*   unsigned char *buffer; */
1278
1279 /*   write_sexp_line (out, indent, "("); */
1280 /*   iobuf_writestr (out, name); */
1281 /*   iobuf_writestr (out, " #"); */
1282
1283 /*   rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a); */
1284 /*   assert (!rc); */
1285 /*   iobuf_writestr (out, buffer); */
1286 /*   iobuf_writestr (out, "#)"); */
1287 /*   gcry_free (buffer); */
1288 /*   return 0; */
1289 /* } */
1290
1291 static int
1292 build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
1293 {
1294   (void)out;
1295   (void)pkt;
1296   (void)indent;
1297
1298   /* FIXME: Not yet implemented.  */
1299   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1300   /* PKT_secret_key *sk = pkt->pkt.secret_key; */
1301   /* char tmpbuf[100]; */
1302
1303   /* if (pkt->pkttype == PKT_SECRET_KEY) */
1304   /*   { */
1305   /*     iobuf_writestr (out, "(openpgp-key\n"); */
1306   /*     (*indent)++; */
1307   /*   } */
1308   /* else */
1309   /*   { */
1310   /*     iobuf_writestr (out, " (subkey\n"); */
1311   /*     (*indent)++; */
1312   /*   } */
1313   /* (*indent)++; */
1314   /* write_sexp_line (out, indent, "(private-key\n"); */
1315   /* (*indent)++; */
1316   /* if (is_RSA (sk->pubkey_algo) && !sk->is_protected) */
1317   /*   { */
1318   /*     write_sexp_line (out, indent, "(rsa\n"); */
1319   /*     (*indent)++; */
1320   /*     write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n'); */
1321   /*     write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n'); */
1322   /*     write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n'); */
1323   /*     write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n'); */
1324   /*     write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n'); */
1325   /*     write_sexp_keyparm (out, indent, "u", sk->skey[5]);  */
1326   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1327   /*     (*indent)--; */
1328   /*   } */
1329   /* else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected) */
1330   /*   { */
1331   /*     write_sexp_line (out, indent, "(dsa\n"); */
1332   /*     (*indent)++; */
1333   /*     write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
1334   /*     write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n'); */
1335   /*     write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
1336   /*     write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
1337   /*     write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
1338   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1339   /*     (*indent)--; */
1340   /*   } */
1341   /* else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) */
1342   /*   { */
1343   /*     write_sexp_line (out, indent, "(ecdsa\n"); */
1344   /*     (*indent)++;  */
1345   /*     write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); */
1346   /*     write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); */
1347   /*     write_sexp_keyparm (out, indent, "d", sk->skey[7]); */
1348   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1349   /*     (*indent)--; */
1350   /*   } */
1351   /* else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected) */
1352   /*   { */
1353   /*     write_sexp_line (out, indent, "(elg\n"); */
1354   /*     (*indent)++; */
1355   /*     write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n'); */
1356   /*     write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n'); */
1357   /*     write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n'); */
1358   /*     write_sexp_keyparm (out, indent, "x", sk->skey[4]); */
1359   /*     iobuf_put (out,')'); iobuf_put (out,'\n'); */
1360   /*     (*indent)--; */
1361   /*   } */
1362   /* write_sexp_line (out, indent,  "(attrib\n"); (*indent)++; */
1363   /* sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp); */
1364   /* write_sexp_line (out, indent, tmpbuf); */
1365   /* iobuf_put (out,')'); (*indent)--; /\* close created *\/ */
1366   /* iobuf_put (out,')'); (*indent)--; /\* close attrib *\/ */
1367   /* iobuf_put (out,')'); (*indent)--; /\* close private-key *\/ */
1368   /* if (pkt->pkttype != PKT_SECRET_KEY) */
1369   /*   iobuf_put (out,')'), (*indent)--; /\* close subkey *\/ */
1370   /* iobuf_put (out,'\n'); */
1371
1372   /* return 0; */
1373 }
1374
1375
1376 /* For some packet types we write them in a S-expression format.  This
1377    is still EXPERIMENTAL and subject to change.  */
1378 static int
1379 build_sexp (iobuf_t out, PACKET *pkt, int *indent)
1380 {
1381   int rc;
1382
1383   switch (pkt->pkttype)
1384     {
1385     case PKT_SECRET_KEY:
1386     case PKT_SECRET_SUBKEY:
1387       rc = build_sexp_seckey (out, pkt, indent);
1388       break;
1389     default:
1390       rc = 0;
1391       break;
1392     }
1393   return rc;
1394 }