Fixed EOF detection for encrypted packets.
[gnupg.git] / g10 / export.c
blob9b87e5924022478afb6343a5440f7e26cd481114
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 3 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, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
28 #include "gpg.h"
29 #include "options.h"
30 #include "packet.h"
31 #include "status.h"
32 #include "keydb.h"
33 #include "util.h"
34 #include "main.h"
35 #include "i18n.h"
36 #include "trustdb.h"
39 /* An object to keep track of subkeys. */
40 struct subkey_list_s
42 struct subkey_list_s *next;
43 u32 kid[2];
45 typedef struct subkey_list_s *subkey_list_t;
48 static int do_export( strlist_t users, int secret, unsigned int options );
49 static int do_export_stream( IOBUF out, strlist_t users, int secret,
50 KBNODE *keyblock_out, unsigned int options,
51 int *any );
52 static int build_sexp (iobuf_t out, PACKET *pkt, int *indent);
55 int
56 parse_export_options(char *str,unsigned int *options,int noisy)
58 struct parse_options export_opts[]=
60 {"export-local-sigs",EXPORT_LOCAL_SIGS,NULL,
61 N_("export signatures that are marked as local-only")},
62 {"export-attributes",EXPORT_ATTRIBUTES,NULL,
63 N_("export attribute user IDs (generally photo IDs)")},
64 {"export-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,
65 N_("export revocation keys marked as \"sensitive\"")},
66 {"export-reset-subkey-passwd",EXPORT_RESET_SUBKEY_PASSWD,NULL,
67 N_("remove the passphrase from exported subkeys")},
68 {"export-clean",EXPORT_CLEAN,NULL,
69 N_("remove unusable parts from key during export")},
70 {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
71 N_("remove as much as possible from key during export")},
72 {"export-sexp-format",EXPORT_SEXP_FORMAT, NULL,
73 N_("export keys in an S-expression based format")},
74 /* Aliases for backward compatibility */
75 {"include-local-sigs",EXPORT_LOCAL_SIGS,NULL,NULL},
76 {"include-attributes",EXPORT_ATTRIBUTES,NULL,NULL},
77 {"include-sensitive-revkeys",EXPORT_SENSITIVE_REVKEYS,NULL,NULL},
78 /* dummy */
79 {"export-unusable-sigs",0,NULL,NULL},
80 {"export-clean-sigs",0,NULL,NULL},
81 {"export-clean-uids",0,NULL,NULL},
82 {NULL,0,NULL,NULL}
83 /* add tags for include revoked and disabled? */
86 return parse_options(str,options,export_opts,noisy);
90 /****************
91 * Export the public keys (to standard out or --output).
92 * Depending on opt.armor the output is armored.
93 * options are defined in main.h.
94 * If USERS is NULL, the complete ring will be exported. */
95 int
96 export_pubkeys( strlist_t users, unsigned int options )
98 return do_export( users, 0, options );
101 /****************
102 * Export to an already opened stream; return -1 if no keys have
103 * been exported
106 export_pubkeys_stream( IOBUF out, strlist_t users,
107 KBNODE *keyblock_out, unsigned int options )
109 int any, rc;
111 rc = do_export_stream( out, users, 0, keyblock_out, options, &any );
112 if( !rc && !any )
113 rc = -1;
114 return rc;
118 export_seckeys( strlist_t users )
120 /* Use only relevant options for the secret key. */
121 unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
122 return do_export( users, 1, options );
126 export_secsubkeys( strlist_t users )
128 /* Use only relevant options for the secret key. */
129 unsigned int options = (opt.export_options & EXPORT_SEXP_FORMAT);
130 return do_export( users, 2, options );
133 static int
134 do_export( strlist_t users, int secret, unsigned int options )
136 IOBUF out = NULL;
137 int any, rc;
138 armor_filter_context_t *afx = NULL;
139 compress_filter_context_t zfx;
141 memset( &zfx, 0, sizeof zfx);
143 rc = open_outfile (GNUPG_INVALID_FD, NULL, 0, &out );
144 if (rc)
145 return rc;
147 if (!(options & EXPORT_SEXP_FORMAT))
149 if ( opt.armor )
151 afx = new_armor_context ();
152 afx->what = secret? 5 : 1;
153 push_armor_filter (afx, out);
155 if ( opt.compress_keys )
156 push_compress_filter (out,&zfx,default_compress_algo());
159 rc = do_export_stream ( out, users, secret, NULL, options, &any );
161 if ( rc || !any )
162 iobuf_cancel (out);
163 else
164 iobuf_close (out);
165 release_armor_context (afx);
166 return rc;
171 /* Release an entire subkey list. */
172 static void
173 release_subkey_list (subkey_list_t list)
175 while (list)
177 subkey_list_t tmp = list->next;;
178 xfree (list);
179 list = tmp;
184 /* Returns true if NODE is a subkey and contained in LIST. */
185 static int
186 subkey_in_list_p (subkey_list_t list, KBNODE node)
188 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
189 || node->pkt->pkttype == PKT_SECRET_SUBKEY )
191 u32 kid[2];
193 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
194 keyid_from_pk (node->pkt->pkt.public_key, kid);
195 else
196 keyid_from_sk (node->pkt->pkt.secret_key, kid);
198 for (; list; list = list->next)
199 if (list->kid[0] == kid[0] && list->kid[1] == kid[1])
200 return 1;
202 return 0;
205 /* Allocate a new subkey list item from NODE. */
206 static subkey_list_t
207 new_subkey_list_item (KBNODE node)
209 subkey_list_t list = xcalloc (1, sizeof *list);
211 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
212 keyid_from_pk (node->pkt->pkt.public_key, list->kid);
213 else if (node->pkt->pkttype == PKT_SECRET_SUBKEY)
214 keyid_from_sk (node->pkt->pkt.secret_key, list->kid);
216 return list;
220 /* Helper function to check whether the subkey at NODE actually
221 matches the description at DESC. The function returns true if the
222 key under question has been specified by an exact specification
223 (keyID or fingerprint) and does match the one at NODE. It is
224 assumed that the packet at NODE is either a public or secret
225 subkey. */
226 static int
227 exact_subkey_match_p (KEYDB_SEARCH_DESC *desc, KBNODE node)
229 u32 kid[2];
230 byte fpr[MAX_FINGERPRINT_LEN];
231 size_t fprlen;
232 int result = 0;
234 switch(desc->mode)
236 case KEYDB_SEARCH_MODE_SHORT_KID:
237 case KEYDB_SEARCH_MODE_LONG_KID:
238 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
239 keyid_from_pk (node->pkt->pkt.public_key, kid);
240 else
241 keyid_from_sk (node->pkt->pkt.secret_key, kid);
242 break;
244 case KEYDB_SEARCH_MODE_FPR16:
245 case KEYDB_SEARCH_MODE_FPR20:
246 case KEYDB_SEARCH_MODE_FPR:
247 if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
248 fingerprint_from_pk (node->pkt->pkt.public_key, fpr,&fprlen);
249 else
250 fingerprint_from_sk (node->pkt->pkt.secret_key, fpr,&fprlen);
251 break;
253 default:
254 break;
257 switch(desc->mode)
259 case KEYDB_SEARCH_MODE_SHORT_KID:
260 if (desc->u.kid[1] == kid[1])
261 result = 1;
262 break;
264 case KEYDB_SEARCH_MODE_LONG_KID:
265 if (desc->u.kid[0] == kid[0] && desc->u.kid[1] == kid[1])
266 result = 1;
267 break;
269 case KEYDB_SEARCH_MODE_FPR16:
270 if (!memcmp (desc->u.fpr, fpr, 16))
271 result = 1;
272 break;
274 case KEYDB_SEARCH_MODE_FPR20:
275 case KEYDB_SEARCH_MODE_FPR:
276 if (!memcmp (desc->u.fpr, fpr, 20))
277 result = 1;
278 break;
280 default:
281 break;
284 return result;
288 /* If keyblock_out is non-NULL, AND the exit code is zero, then it
289 contains a pointer to the first keyblock found and exported. No
290 other keyblocks are exported. The caller must free it. */
291 static int
292 do_export_stream( IOBUF out, strlist_t users, int secret,
293 KBNODE *keyblock_out, unsigned int options, int *any )
295 int rc = 0;
296 PACKET pkt;
297 KBNODE keyblock = NULL;
298 KBNODE kbctx, node;
299 size_t ndesc, descindex;
300 KEYDB_SEARCH_DESC *desc = NULL;
301 subkey_list_t subkey_list = NULL; /* Track alreay processed subkeys. */
302 KEYDB_HANDLE kdbhd;
303 strlist_t sl;
304 int indent = 0;
306 *any = 0;
307 init_packet( &pkt );
308 kdbhd = keydb_new (secret);
310 if (!users) {
311 ndesc = 1;
312 desc = xcalloc ( ndesc, sizeof *desc );
313 desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
315 else {
316 for (ndesc=0, sl=users; sl; sl = sl->next, ndesc++)
318 desc = xmalloc ( ndesc * sizeof *desc);
320 for (ndesc=0, sl=users; sl; sl = sl->next) {
321 if (classify_user_id (sl->d, desc+ndesc))
322 ndesc++;
323 else
324 log_error (_("key \"%s\" not found: %s\n"),
325 sl->d, g10_errstr (G10ERR_INV_USER_ID));
328 /* It would be nice to see which of the given users did
329 actually match one in the keyring. To implement this we
330 need to have a found flag for each entry in desc and to set
331 this we must check all those entries after a match to mark
332 all matched one - currently we stop at the first match. To
333 do this we need an extra flag to enable this feature so */
336 #ifdef ENABLE_SELINUX_HACKS
337 if (secret) {
338 log_error (_("exporting secret keys not allowed\n"));
339 rc = G10ERR_GENERAL;
340 goto leave;
342 #endif
344 while (!(rc = keydb_search2 (kdbhd, desc, ndesc, &descindex))) {
345 int sha1_warned=0,skip_until_subkey=0;
346 u32 sk_keyid[2];
348 if (!users)
349 desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
351 /* Read the keyblock. */
352 rc = keydb_get_keyblock (kdbhd, &keyblock );
353 if( rc ) {
354 log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) );
355 goto leave;
358 if((node=find_kbnode(keyblock,PKT_SECRET_KEY)))
360 PKT_secret_key *sk=node->pkt->pkt.secret_key;
362 keyid_from_sk(sk,sk_keyid);
364 /* We can't apply GNU mode 1001 on an unprotected key. */
365 if( secret == 2 && !sk->is_protected )
367 log_info(_("key %s: not protected - skipped\n"),
368 keystr(sk_keyid));
369 continue;
372 /* No v3 keys with GNU mode 1001. */
373 if( secret == 2 && sk->version == 3 )
375 log_info(_("key %s: PGP 2.x style key - skipped\n"),
376 keystr(sk_keyid));
377 continue;
380 /* It does not make sense to export a key with a primary
381 key on card using a non-key stub. We simply skip those
382 keys when used with --export-secret-subkeys. */
383 if (secret == 2 && sk->is_protected
384 && sk->protect.s2k.mode == 1002 )
386 log_info(_("key %s: key material on-card - skipped\n"),
387 keystr(sk_keyid));
388 continue;
391 else
393 /* It's a public key export, so do the cleaning if
394 requested. Note that both export-clean and
395 export-minimal only apply to UID sigs (0x10, 0x11,
396 0x12, and 0x13). A designated revocation is never
397 stripped, even with export-minimal set. */
399 if(options&EXPORT_CLEAN)
400 clean_key(keyblock,opt.verbose,options&EXPORT_MINIMAL,NULL,NULL);
403 /* And write it. */
404 for( kbctx=NULL; (node = walk_kbnode( keyblock, &kbctx, 0 )); ) {
405 if( skip_until_subkey )
407 if(node->pkt->pkttype==PKT_PUBLIC_SUBKEY
408 || node->pkt->pkttype==PKT_SECRET_SUBKEY)
409 skip_until_subkey=0;
410 else
411 continue;
414 /* We used to use comment packets, but not any longer. In
415 case we still have comments on a key, strip them here
416 before we call build_packet(). */
417 if( node->pkt->pkttype == PKT_COMMENT )
418 continue;
420 /* Make sure that ring_trust packets never get exported. */
421 if (node->pkt->pkttype == PKT_RING_TRUST)
422 continue;
424 /* If exact is set, then we only export what was requested
425 (plus the primary key, if the user didn't specifically
426 request it). */
427 if(desc[descindex].exact
428 && (node->pkt->pkttype==PKT_PUBLIC_SUBKEY
429 || node->pkt->pkttype==PKT_SECRET_SUBKEY))
431 if (!exact_subkey_match_p (desc+descindex, node))
433 /* Before skipping this subkey, check whether any
434 other description wants an exact match on a
435 subkey and include that subkey into the output
436 too. Need to add this subkey to a list so that
437 it won't get processed a second time.
439 So the first step here is to check that list and
440 skip in any case if the key is in that list.
442 We need this whole mess because the import
443 function is not able to merge secret keys and
444 thus it is useless to output them as two
445 separate keys and have import merge them. */
446 if (subkey_in_list_p (subkey_list, node))
447 skip_until_subkey = 1; /* Already processed this one. */
448 else
450 size_t j;
452 for (j=0; j < ndesc; j++)
453 if (j != descindex && desc[j].exact
454 && exact_subkey_match_p (desc+j, node))
455 break;
456 if (!(j < ndesc))
457 skip_until_subkey = 1; /* No other one matching. */
461 if(skip_until_subkey)
462 continue;
464 /* Mark this one as processed. */
466 subkey_list_t tmp = new_subkey_list_item (node);
467 tmp->next = subkey_list;
468 subkey_list = tmp;
472 if(node->pkt->pkttype==PKT_SIGNATURE)
474 /* do not export packets which are marked as not
475 exportable */
476 if(!(options&EXPORT_LOCAL_SIGS)
477 && !node->pkt->pkt.signature->flags.exportable)
478 continue; /* not exportable */
480 /* Do not export packets with a "sensitive" revocation
481 key unless the user wants us to. Note that we do
482 export these when issuing the actual revocation
483 (see revoke.c). */
484 if(!(options&EXPORT_SENSITIVE_REVKEYS)
485 && node->pkt->pkt.signature->revkey)
487 int i;
489 for(i=0;i<node->pkt->pkt.signature->numrevkeys;i++)
490 if(node->pkt->pkt.signature->revkey[i]->class & 0x40)
491 break;
493 if(i<node->pkt->pkt.signature->numrevkeys)
494 continue;
498 /* Don't export attribs? */
499 if( !(options&EXPORT_ATTRIBUTES) &&
500 node->pkt->pkttype == PKT_USER_ID &&
501 node->pkt->pkt.user_id->attrib_data ) {
502 /* Skip until we get to something that is not an attrib
503 or a signature on an attrib */
504 while(kbctx->next && kbctx->next->pkt->pkttype==PKT_SIGNATURE) {
505 kbctx=kbctx->next;
508 continue;
511 if( secret == 2 && node->pkt->pkttype == PKT_SECRET_KEY )
513 /* We don't want to export the secret parts of the
514 * primary key, this is done by using GNU protection mode 1001
516 int save_mode = node->pkt->pkt.secret_key->protect.s2k.mode;
517 node->pkt->pkt.secret_key->protect.s2k.mode = 1001;
518 if ((options&EXPORT_SEXP_FORMAT))
519 rc = build_sexp (out, node->pkt, &indent);
520 else
521 rc = build_packet (out, node->pkt);
522 node->pkt->pkt.secret_key->protect.s2k.mode = save_mode;
524 else if (secret == 2 && node->pkt->pkttype == PKT_SECRET_SUBKEY
525 && (opt.export_options&EXPORT_RESET_SUBKEY_PASSWD))
527 /* If the subkey is protected reset the passphrase to
528 export an unprotected subkey. This feature is
529 useful in cases of a subkey copied to an unattended
530 machine where a passphrase is not required. */
531 PKT_secret_key *sk_save, *sk;
533 sk_save = node->pkt->pkt.secret_key;
534 sk = copy_secret_key (NULL, sk_save);
535 node->pkt->pkt.secret_key = sk;
537 log_info (_("about to export an unprotected subkey\n"));
538 switch (is_secret_key_protected (sk))
540 case -1:
541 rc = G10ERR_PUBKEY_ALGO;
542 break;
543 case 0:
544 break;
545 default:
546 if (sk->protect.s2k.mode == 1001)
547 ; /* No secret parts. */
548 else if( sk->protect.s2k.mode == 1002 )
549 ; /* Card key stub. */
550 else
552 rc = check_secret_key( sk, 0 );
554 break;
556 if (rc)
558 node->pkt->pkt.secret_key = sk_save;
559 free_secret_key (sk);
560 log_error (_("failed to unprotect the subkey: %s\n"),
561 g10_errstr (rc));
562 goto leave;
565 if ((options&EXPORT_SEXP_FORMAT))
566 rc = build_sexp (out, node->pkt, &indent);
567 else
568 rc = build_packet (out, node->pkt);
570 node->pkt->pkt.secret_key = sk_save;
571 free_secret_key (sk);
573 else
575 /* Warn the user if the secret key or any of the secret
576 subkeys are protected with SHA1 and we have
577 simple_sk_checksum set. */
578 if(!sha1_warned && opt.simple_sk_checksum &&
579 (node->pkt->pkttype==PKT_SECRET_KEY ||
580 node->pkt->pkttype==PKT_SECRET_SUBKEY) &&
581 node->pkt->pkt.secret_key->protect.sha1chk)
583 /* I hope this warning doesn't confuse people. */
584 log_info(_("WARNING: secret key %s does not have a "
585 "simple SK checksum\n"),keystr(sk_keyid));
587 sha1_warned=1;
590 if ((options&EXPORT_SEXP_FORMAT))
591 rc = build_sexp (out, node->pkt, &indent);
592 else
593 rc = build_packet (out, node->pkt);
596 if( rc ) {
597 log_error("build_packet(%d) failed: %s\n",
598 node->pkt->pkttype, g10_errstr(rc) );
599 goto leave;
603 if ((options&EXPORT_SEXP_FORMAT) && indent)
605 for (; indent; indent--)
606 iobuf_put (out, ')');
607 iobuf_put (out, '\n');
610 ++*any;
611 if(keyblock_out)
613 *keyblock_out=keyblock;
614 break;
617 if ((options&EXPORT_SEXP_FORMAT) && indent)
619 for (; indent; indent--)
620 iobuf_put (out, ')');
621 iobuf_put (out, '\n');
623 if( rc == -1 )
624 rc = 0;
626 leave:
627 release_subkey_list (subkey_list);
628 xfree(desc);
629 keydb_release (kdbhd);
630 if(rc || keyblock_out==NULL)
631 release_kbnode( keyblock );
632 if( !*any )
633 log_info(_("WARNING: nothing exported\n"));
634 return rc;
639 static int
640 write_sexp_line (iobuf_t out, int *indent, const char *text)
642 int i;
644 for (i=0; i < *indent; i++)
645 iobuf_put (out, ' ');
646 iobuf_writestr (out, text);
647 return 0;
650 static int
651 write_sexp_keyparm (iobuf_t out, int *indent, const char *name, gcry_mpi_t a)
653 int rc;
654 unsigned char *buffer;
656 write_sexp_line (out, indent, "(");
657 iobuf_writestr (out, name);
658 iobuf_writestr (out, " #");
660 rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a);
661 assert (!rc);
662 iobuf_writestr (out, buffer);
663 iobuf_writestr (out, "#)");
664 gcry_free (buffer);
665 return 0;
668 static int
669 build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent)
671 PKT_secret_key *sk = pkt->pkt.secret_key;
672 char tmpbuf[100];
674 if (pkt->pkttype == PKT_SECRET_KEY)
676 iobuf_writestr (out, "(openpgp-key\n");
677 (*indent)++;
679 else
681 iobuf_writestr (out, " (subkey\n");
682 (*indent)++;
684 (*indent)++;
685 write_sexp_line (out, indent, "(private-key\n");
686 (*indent)++;
687 if (is_RSA (sk->pubkey_algo) && !sk->is_protected)
689 write_sexp_line (out, indent, "(rsa\n");
690 (*indent)++;
691 write_sexp_keyparm (out, indent, "n", sk->skey[0]); iobuf_put (out,'\n');
692 write_sexp_keyparm (out, indent, "e", sk->skey[1]); iobuf_put (out,'\n');
693 write_sexp_keyparm (out, indent, "d", sk->skey[2]); iobuf_put (out,'\n');
694 write_sexp_keyparm (out, indent, "p", sk->skey[3]); iobuf_put (out,'\n');
695 write_sexp_keyparm (out, indent, "q", sk->skey[4]); iobuf_put (out,'\n');
696 write_sexp_keyparm (out, indent, "u", sk->skey[5]);
697 iobuf_put (out,')'); iobuf_put (out,'\n');
698 (*indent)--;
700 else if (sk->pubkey_algo == PUBKEY_ALGO_DSA && !sk->is_protected)
702 write_sexp_line (out, indent, "(dsa\n");
703 (*indent)++;
704 write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n');
705 write_sexp_keyparm (out, indent, "q", sk->skey[1]); iobuf_put (out,'\n');
706 write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n');
707 write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n');
708 write_sexp_keyparm (out, indent, "x", sk->skey[4]);
709 iobuf_put (out,')'); iobuf_put (out,'\n');
710 (*indent)--;
712 else if (is_ELGAMAL (sk->pubkey_algo) && !sk->is_protected)
714 write_sexp_line (out, indent, "(elg\n");
715 (*indent)++;
716 write_sexp_keyparm (out, indent, "p", sk->skey[0]); iobuf_put (out,'\n');
717 write_sexp_keyparm (out, indent, "g", sk->skey[2]); iobuf_put (out,'\n');
718 write_sexp_keyparm (out, indent, "y", sk->skey[3]); iobuf_put (out,'\n');
719 write_sexp_keyparm (out, indent, "x", sk->skey[4]);
720 iobuf_put (out,')'); iobuf_put (out,'\n');
721 (*indent)--;
723 write_sexp_line (out, indent, "(attrib\n"); (*indent)++;
724 sprintf (tmpbuf, "(created \"%lu\"", (unsigned long)sk->timestamp);
725 write_sexp_line (out, indent, tmpbuf);
726 iobuf_put (out,')'); (*indent)--; /* close created */
727 iobuf_put (out,')'); (*indent)--; /* close attrib */
728 iobuf_put (out,')'); (*indent)--; /* close private-key */
729 if (pkt->pkttype != PKT_SECRET_KEY)
730 iobuf_put (out,')'), (*indent)--; /* close subkey */
731 iobuf_put (out,'\n');
733 return 0;
737 /* For some packet types we write them in a S-expression format. This
738 is still EXPERIMENTAL and subject to change. */
739 static int
740 build_sexp (iobuf_t out, PACKET *pkt, int *indent)
742 int rc;
744 switch (pkt->pkttype)
746 case PKT_SECRET_KEY:
747 case PKT_SECRET_SUBKEY:
748 rc = build_sexp_seckey (out, pkt, indent);
749 break;
750 default:
751 rc = 0;
752 break;
754 return rc;