* gpg.texi (GPG Configuration Options): Make http_proxy option
[gnupg.git] / g10 / export.c
blob78def573dccae6a0cb940c589dbe41ac1bc9aaaf
1 /* export.c
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 * 2005 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20 * USA.
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
30 #include "gpg.h"
31 #include "options.h"
32 #include "packet.h"
33 #include "errors.h"
34 #include "keydb.h"
35 #include "util.h"
36 #include "main.h"
37 #include "i18n.h"
38 #include "trustdb.h"
41 /* An object to keep track of subkeys. */
42 struct subkey_list_s
44 struct subkey_list_s *next;
45 u32 kid[2];
47 typedef struct subkey_list_s *subkey_list_t;
50 static int do_export( strlist_t users, int secret, unsigned int options );
51 static int do_export_stream( IOBUF out, strlist_t users, int secret,
52 KBNODE *keyblock_out, unsigned int options,
53 int *any );
54 static int build_sexp (iobuf_t out, PACKET *pkt, int *indent);
57 int
58 parse_export_options(char *str,unsigned int *options,int noisy)
60 struct parse_options export_opts[]=
62 {"export-local-sigs",EXPORT_LOCAL_SIGS,NULL,
63 N_("export signatures that are marked as local-only")},
64 {"export-attributes",EXPORT_ATTRIBUTES,NULL,
65 N_("export attribute user IDs (generally photo IDs)")},
66 {"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
67 N_("export revocation keys marked as \"sensitive\"")},
68 {"export-reset-subkey-passwd",EXPORT_RESET_SUBKEY_PASSWD,NULL,
69 N_("remove the passphrase from exported subkeys")},
70 {"export-clean",EXPORT_CLEAN,NULL,
71 N_("remove unusable parts from key during export")},
72 {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
73 N_("remove as much as possible from key during export")},
74 {"export-sexp-format",EXPORT_SEXP_FORMAT, NULL,
75 N_("export keys in an S-expression based format")},
76 /* Aliases for backward compatibility */
77 {"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
78 {"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
79 {"include-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,NULL},
80 /* dummy */
81 {"export-unusable-sigs",0,NULL,NULL},
82 {"export-clean-sigs",0,NULL,NULL},
83 {"export-clean-uids",0,NULL,NULL},
84 {NULL,0,NULL,NULL}
85 /* add tags for include revoked and disabled? */
88 return parse_options(str,options,export_opts,noisy);
92 /****************
93 * Export the public keys (to standard out or --output).
94 * Depending on opt.armor the output is armored.
95 * options are defined in main.h.
96 * If USERS is NULL, the complete ring will be exported. */
97 int
98 export_pubkeys( strlist_t users, unsigned int options )
100 return do_export( users, 0, options );
103 /****************
104 * Export to an already opened stream; return -1 if no keys have
105 * been exported
108 export_pubkeys_stream( IOBUF out, strlist_t users,
109 KBNODE *keyblock_out, unsigned int options )
111 int any, rc;
113 rc = do_export_stream( out, users, 0, keyblock_out, options, &any );
114 if( !rc && !any )
115 rc = -1;
116 return rc;
120 export_seckeys( strlist_t users )
122 /* Use only relevant options for the secret key. */
123 unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
124 return do_export( users, 1, options );
128 export_secsubkeys( strlist_t users )
130 /* Use only relevant options for the secret key. */
131 unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
132 return do_export( users, 2, options );
135 static int
136 do_export( strlist_t users, int secret, unsigned int options )
138 IOBUF out = NULL;
139 int any, rc;
140 armor_filter_context_t *afx = NULL;
141 compress_filter_context_t zfx;
143 memset( &zfx, 0, sizeof zfx);
145 rc = open_outfile( NULL, 0, &out );
146 if (rc)
147 return rc;
149 if (!(options & EXPORT_SEXP_FORMAT))
151 if ( opt.armor )
153 afx = new_armor_context ();
154 afx->what = secret? 5 : 1;
155 push_armor_filter (afx, out);
157 if ( opt.compress_keys )
158 push_compress_filter (out,&zfx,default_compress_algo());
161 rc = do_export_stream ( out, users, secret, NULL, options, &any );
163 if ( rc || !any )
164 iobuf_cancel (out);
165 else
166 iobuf_close (out);
167 release_armor_context (afx);
168 return rc;
173 /* Release an entire subkey list. */
174 static void
175 release_subkey_list (subkey_list_t list)
177 while (list)
179 subkey_list_t tmp = list->next;;
180 xfree (list);
181 list = tmp;
186 /* Returns true if NODE is a subkey and contained in LIST. */
187 static int
188 subkey_in_list_p (subkey_list_t list, KBNODE node)
190 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
191 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
193 u32 kid[2];
195 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
196 keyid_from_pk (node->pkt->pkt.public_key, kid);
197 else
198 keyid_from_sk (node->pkt->pkt.secret_key, kid);
200 for (; list; list = list->next)
201 if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
202 return 1;
204 return 0;
207 /* Allocate a new subkey list item from NODE. */
208 static subkey_list_t
209 new_subkey_list_item (KBNODE node)
211 subkey_list_t list = xcalloc (1, sizeof *list);
213 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
214 keyid_from_pk (node->pkt->pkt.public_key, list->kid);
215 else if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
216 keyid_from_sk (node->pkt->pkt.secret_key, list->kid);
218 return list;
222 /* Helper function to check whether the subkey at NODE actually
223 matches the description at DESC. The function returns true if the
224 key under question has been specified by an exact specification
225 (keyID or fingerprint) and does match the one at NODE. It is
226 assumed that the packet at NODE is either a public or secret
227 subkey. */
228 static int
229 exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
231 u32 kid[2];
232 byte fpr[MAX_FINGERPRINT_LEN];
233 size_t fprlen;
234 int result = 0;
236 switch(desc->mode)
238 case KEYDB_SEARCH_MODE_SHORT_KID:
239 case KEYDB_SEARCH_MODE_LONG_KID:
240 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
241 keyid_from_pk (node->pkt->pkt.public_key, kid);
242 else
243 keyid_from_sk (node->pkt->pkt.secret_key, kid);
244 break;
246 case KEYDB_SEARCH_MODE_FPR16:
247 case KEYDB_SEARCH_MODE_FPR20:
248 case KEYDB_SEARCH_MODE_FPR:
249 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
250 fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
251 else
252 fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
253 break;
255 default:
256 break;
259 switch(desc->mode)
261 case KEYDB_SEARCH_MODE_SHORT_KID:
262 if (desc->u.kid[1] == kid[1])
263 result = 1;
264 break;
266 case KEYDB_SEARCH_MODE_LONG_KID:
267 if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
268 result = 1;
269 break;
271 case KEYDB_SEARCH_MODE_FPR16:
272 if (!memcmp (desc->u.fpr, fpr, 16))
273 result = 1;
274 break;
276 case KEYDB_SEARCH_MODE_FPR20:
277 case KEYDB_SEARCH_MODE_FPR:
278 if (!memcmp (desc->u.fpr, fpr, 20))
279 result = 1;
280 break;
282 default:
283 break;
286 return result;
290 /* If keyblock_out is non-NULL, AND the exit code is zero, then it
291 contains a pointer to the first keyblock found and exported. No
292 other keyblocks are exported. The caller must free it. */
293 static int
294 do_export_stream( IOBUF out, strlist_t users, int secret,
295 KBNODE *keyblock_out, unsigned int options, int *any )
297 int rc = 0;
298 PACKET pkt;
299 KBNODE keyblock = NULL;
300 KBNODE kbctx, node;
301 size_t ndesc, descindex;
302 KEYDB_SEARCH_DESC *desc = NULL;
303 subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */
304 KEYDB_HANDLE kdbhd;
305 strlist_t sl;
306 int indent = 0;
308 *any = 0;
309 init_packet( &pkt );
310 kdbhd = keydb_new (secret);
312 if (!users) {
313 ndesc = 1;
314 desc = xcalloc ( ndesc, sizeof *desc );
315 desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
317 else {
318 for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
320 desc = xmalloc ( ndesc * sizeof *desc);
322 for (ndesc=0, sl=users; sl; sl = sl->next) {
323 if (classify_user_id (sl->d, desc+ndesc))
324 ndesc++;
325 else
326 log_error (_("key \"%s\" not found: %s\n"),
327 sl->d, g10_errstr (G10ERR_INV_USER_ID));
330 /* It would be nice to see which of the given users did
331 actually match one in the keyring. To implement this we
332 need to have a found flag for each entry in desc and to set
333 this we must check all those entries after a match to mark
334 all matched one - currently we stop at the first match. To
335 do this we need an extra flag to enable this feature so */
338 #ifdef ENABLE_SELINUX_HACKS
339 if (secret) {
340 log_error (_("exporting secret keys not allowed\n"));
341 rc = G10ERR_GENERAL;
342 goto leave;
344 #endif
346 while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) {
347 int sha1_warned=0,skip_until_subkey=0;
348 u32 sk_keyid[2];
350 if (!users)
351 desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
353 /* Read the keyblock. */
354 rc = keydb_get_keyblock (kdbhd, &keyblock );
355 if( rc ) {
356 log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
357 goto leave;
360 if((node=find_kbnode(keyblock,PKT_SECRET_KEY)))
362 PKT_secret_key *sk=node->pkt->pkt.secret_key;
364 keyid_from_sk(sk,sk_keyid);
366 /* We can't apply GNU mode 1001 on an unprotected key. */
367 if( secret == 2 && !sk->is_protected )
369 log_info(_("key %s: not protected - skipped\n"),
370 keystr(sk_keyid));
371 continue;
374 /* No v3 keys with GNU mode 1001. */
375 if( secret == 2 && sk->version == 3 )
377 log_info(_("key %s: PGP 2.x style key - skipped\n"),
378 keystr(sk_keyid));
379 continue;
382 /* It does not make sense to export a key with a primary
383 key on card using a non-key stub. We simply skip those
384 keys when used with --export-secret-subkeys. */
385 if (secret == 2 && sk->is_protected
386 && sk->protect.s2k.mode == 1002 )
388 log_info(_("key %s: key material on-card - skipped\n"),
389 keystr(sk_keyid));
390 continue;
393 else
395 /* It's a public key export, so do the cleaning if
396 requested. Note that both export-clean and
397 export-minimal only apply to UID sigs (0x10, 0x11,
398 0x12, and 0x13). A designated revocation is never
399 stripped, even with export-minimal set. */
401 if(options&EXPORT_CLEAN)
402 clean_key(keyblock,opt.verbose,options&EXPORT_MINIMAL,NULL,NULL);
405 /* And write it. */
406 for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
407 if( skip_until_subkey )
409 if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY
410 || node->pkt->pkttype==PKT_SECRET_SUBKEY)
411 skip_until_subkey=0;
412 else
413 continue;
416 /* We used to use comment packets, but not any longer. In
417 case we still have comments on a key, strip them here
418 before we call build_packet(). */
419 if( node->pkt->pkttype == PKT_COMMENT )
420 continue;
422 /* Make sure that ring_trust packets never get exported. */
423 if (node->pkt->pkttype == PKT_RING_TRUST)
424 continue;
426 /* If exact is set, then we only export what was requested
427 (plus the primary key, if the user didn't specifically
428 request it). */
429 if(desc[descindex].exact
430 && (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
431 || node->pkt->pkttype==PKT_SECRET_SUBKEY))
433 if (!exact_subkey_match_p (desc+descindex, node))
435 /* Before skipping this subkey, check whether any
436 other description wants an exact match on a
437 subkey and include that subkey into the output
438 too. Need to add this subkey to a list so that
439 it won't get processed a second time.
441 So the first step here is to check that list and
442 skip in any case if the key is in that list.
444 We need this whole mess because the import
445 function is not able to merge secret keys and
446 thus it is useless to output them as two
447 separate keys and have import merge them. */
448 if (subkey_in_list_p (subkey_list, node))
449 skip_until_subkey = 1; /* Already processed this one. */
450 else
452 size_t j;
454 for (j=0; j < ndesc; j++)
455 if (j != descindex && desc[j].exact
456 && exact_subkey_match_p (desc+j, node))
457 break;
458 if (!(j < ndesc))
459 skip_until_subkey = 1; /* No other one matching. */
463 if(skip_until_subkey)
464 continue;
466 /* Mark this one as processed. */
468 subkey_list_t tmp = new_subkey_list_item (node);
469 tmp->next = subkey_list;
470 subkey_list = tmp;
474 if(node->pkt->pkttype==PKT_SIGNATURE)
476 /* do not export packets which are marked as not
477 exportable */
478 if(!(options&EXPORT_LOCAL_SIGS)
479 && !node->pkt->pkt.signature->flags.exportable)
480 continue; /* not exportable */
482 /* Do not export packets with a "sensitive" revocation
483 key unless the user wants us to. Note that we do
484 export these when issuing the actual revocation
485 (see revoke.c). */
486 if(!(options&EXPORT_SENSITIVE_REVKEYS)
487 && node->pkt->pkt.signature->revkey)
489 int i;
491 for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
492 if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
493 break;
495 if(i<node->pkt->pkt.signature->numrevkeys)
496 continue;
500 /* Don't export attribs? */
501 if( !(options&EXPORT_ATTRIBUTES) &&
502 node->pkt->pkttype == PKT_USER_ID &&
503 node->pkt->pkt.user_id->attrib_data ) {
504 /* Skip until we get to something that is not an attrib
505 or a signature on an attrib */
506 while(kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE) {
507 kbctx=kbctx->next;
510 continue;
513 if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY )
515 /* We don't want to export the secret parts of the
516 * primary key, this is done by using GNU protection mode 1001
518 int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
519 node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
520 if ((options&EXPORT_SEXP_FORMAT))
521 rc = build_sexp (out, node->pkt, &indent);
522 else
523 rc = build_packet (out, node->pkt);
524 node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
526 else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY
527 && (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
529 /* If the subkey is protected reset the passphrase to
530 export an unprotected subkey. This feature is
531 useful in cases of a subkey copied to an unattended
532 machine where a passphrase is not required. */
533 PKT_secret_key *sk_save, *sk;
535 sk_save = node->pkt->pkt.secret_key;
536 sk = copy_secret_key (NULL, sk_save);
537 node->pkt->pkt.secret_key = sk;
539 log_info (_("about to export an unprotected subkey\n"));
540 switch (is_secret_key_protected (sk))
542 case -1:
543 rc = G10ERR_PUBKEY_ALGO;
544 break;
545 case 0:
546 break;
547 default:
548 if (sk->protect.s2k.mode == 1001)
549 ; /* No secret parts. */
550 else if( sk->protect.s2k.mode == 1002 )
551 ; /* Card key stub. */
552 else
554 rc = check_secret_key( sk, 0 );
556 break;
558 if (rc)
560 node->pkt->pkt.secret_key = sk_save;
561 free_secret_key (sk);
562 log_error (_("failed to unprotect the subkey: %s\n"),
563 g10_errstr (rc));
564 goto leave;
567 rc = build_packet (out, node->pkt);
569 node->pkt->pkt.secret_key = sk_save;
570 free_secret_key (sk);
572 else
574 /* Warn the user if the secret key or any of the secret
575 subkeys are protected with SHA1 and we have
576 simple_sk_checksum set. */
577 if(!sha1_warned && opt.simple_sk_checksum &&
578 (node->pkt->pkttype==PKT_SECRET_KEY ||
579 node->pkt->pkttype==PKT_SECRET_SUBKEY) &&
580 node->pkt->pkt.secret_key->protect.sha1chk)
582 /* I hope this warning doesn't confuse people. */
583 log_info(_("WARNING: secret key %s does not have a "
584 "simple SK checksum\n"),keystr(sk_keyid));
586 sha1_warned=1;
589 if ((options&EXPORT_SEXP_FORMAT))
590 rc = build_sexp (out, node->pkt, &indent);
591 else
592 rc = build_packet (out, node->pkt);
595 if( rc ) {
596 log_error("build_packet(%d) failed: %s\n",
597 node->pkt->pkttype, g10_errstr(rc) );
598 goto leave;
602 if ((options&EXPORT_SEXP_FORMAT) && indent)
604 for (; indent; indent--)
605 iobuf_put (out, ')');
606 iobuf_put (out, '\n');
609 ++*any;
610 if(keyblock_out)
612 *keyblock_out=keyblock;
613 break;
616 if ((options&EXPORT_SEXP_FORMAT) && indent)
618 for (; indent; indent--)
619 iobuf_put (out, ')');
620 iobuf_put (out, '\n');
622 if( rc == -1 )
623 rc = 0;
625 leave:
626 release_subkey_list (subkey_list);
627 xfree(desc);
628 keydb_release (kdbhd);
629 if(rc || keyblock_out==NULL)
630 release_kbnode( keyblock );
631 if( !*any )
632 log_info(_("WARNING: nothing exported\n"));
633 return rc;
638 static int
639 write_sexp_line (iobuf_t out, int *indent, const char *text)
641 int i;
643 for (i=0; i < *indent; i++)
644 iobuf_put (out, ' ');
645 iobuf_writestr (out, text);
646 return 0;
649 static int
650 write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a)
652 int rc;
653 unsigned char *buffer;
655 write_sexp_line (out, indent, "(");
656 iobuf_writestr (out, name);
657 iobuf_writestr (out, " #");
659 rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a);
660 assert (!rc);
661 iobuf_writestr (out, buffer);
662 iobuf_writestr (out, "#)");
663 gcry_free (buffer);
664 return 0;
667 static int
668 build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
670 PKT_secret_key *sk = pkt->pkt.secret_key;
671 char tmpbuf[100];
673 if (pkt->pkttype == PKT_SECRET_KEY)
675 iobuf_writestr (out, "(openpgp-key\n");
676 (*indent)++;
678 else
680 iobuf_writestr (out, " (subkey\n");
681 (*indent)++;
683 (*indent)++;
684 write_sexp_line (out, indent, "(private-key\n");
685 (*indent)++;
686 if (is_RSA (sk->pubkey_algo) && !sk->is_protected)
688 write_sexp_line (out, indent, "(rsa\n");
689 (*indent)++;
690 write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n');
691 write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n');
692 write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n');
693 write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n');
694 write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n');
695 write_sexp_keyparm (out, indent, "u", sk->skey[5]);
696 iobuf_put (out,')'); iobuf_put (out,'\n');
697 (*indent)--;
699 else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected)
701 write_sexp_line (out, indent, "(dsa\n");
702 (*indent)++;
703 write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n');
704 write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n');
705 write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n');
706 write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n');
707 write_sexp_keyparm (out, indent, "x", sk->skey[4]);
708 iobuf_put (out,')'); iobuf_put (out,'\n');
709 (*indent)--;
711 else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected)
713 write_sexp_line (out, indent, "(elg\n");
714 (*indent)++;
715 write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n');
716 write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n');
717 write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n');
718 write_sexp_keyparm (out, indent, "x", sk->skey[4]);
719 iobuf_put (out,')'); iobuf_put (out,'\n');
720 (*indent)--;
722 write_sexp_line (out, indent, "(attrib\n"); (*indent)++;
723 sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp);
724 write_sexp_line (out, indent, tmpbuf);
725 iobuf_put (out,')'); (*indent)--; /* close created */
726 iobuf_put (out,')'); (*indent)--; /* close attrib */
727 iobuf_put (out,')'); (*indent)--; /* close private-key */
728 if (pkt->pkttype != PKT_SECRET_KEY)
729 iobuf_put (out,')'), (*indent)--; /* close subkey */
730 iobuf_put (out,'\n');
732 return 0;
736 /* For some packet types we write them in a S-expression format. This
737 is still EXPERIMENTAL and subject to change. */
738 static int
739 build_sexp (iobuf_t out, PACKET *pkt, int *indent)
741 int rc;
743 switch (pkt->pkttype)
745 case PKT_SECRET_KEY:
746 case PKT_SECRET_SUBKEY:
747 rc = build_sexp_seckey (out, pkt, indent);
748 break;
749 default:
750 rc = 0;
751 break;
753 return rc;