1 /* export.c - Export certificates and private keys.
2 * Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
39 /* A table to store a fingerprint as used in a duplicates table. We
40 don't need to hash here because a fingerprint is alrady a perfect
41 hash value. This we use the most significant bits to index the
42 table and then use a linked list for the overflow. Possible
43 enhancement for very large number of certictates: Add a second
44 level table and then resort to a linked list. */
47 struct duptable_s
*next
;
49 /* Note that we only need to store 19 bytes because the first byte
50 is implictly given by the table index (we require at least 8
52 unsigned char fpr
[19];
54 typedef struct duptable_s
*duptable_t
;
55 #define DUPTABLE_BITS 12
56 #define DUPTABLE_SIZE (1 << DUPTABLE_BITS)
59 static void print_short_info (ksba_cert_t cert
, FILE *fp
, estream_t stream
);
60 static gpg_error_t
export_p12 (ctrl_t ctrl
,
61 const unsigned char *certimg
, size_t certimglen
,
62 const char *prompt
, const char *keygrip
,
66 /* Create a table used to indetify duplicated certificates. */
68 create_duptable (void)
70 return xtrycalloc (DUPTABLE_SIZE
, sizeof (duptable_t
));
74 destroy_duptable (duptable_t
*table
)
81 for (idx
=0; idx
< DUPTABLE_SIZE
; idx
++)
82 for (t
= table
[idx
]; t
; t
= t2
)
91 /* Insert the 20 byte fingerprint FPR into TABLE. Sets EXITS to true
92 if the fingerprint already exists in the table. */
94 insert_duptable (duptable_t
*table
, unsigned char *fpr
, int *exists
)
101 #if DUPTABLE_BITS > 16 || DUPTABLE_BITS < 8
102 #error cannot handle a table larger than 16 bits or smaller than 8 bits
103 #elif DUPTABLE_BITS > 8
104 idx
<<= (DUPTABLE_BITS
- 8);
105 idx
|= (fpr
[1] & ~(~0 << 4));
108 for (t
= table
[idx
]; t
; t
= t
->next
)
109 if (!memcmp (t
->fpr
, fpr
+1, 19))
116 /* Insert that fingerprint. */
117 t
= xtrymalloc (sizeof *t
);
119 return gpg_error_from_syserror ();
120 memcpy (t
->fpr
, fpr
+1, 19);
121 t
->next
= table
[idx
];
129 /* Export all certificates or just those given in NAMES. If STREAM is
130 not NULL the output is send to this extended stream. */
132 gpgsm_export (ctrl_t ctrl
, strlist_t names
, FILE *fp
, estream_t stream
)
134 KEYDB_HANDLE hd
= NULL
;
135 KEYDB_SEARCH_DESC
*desc
= NULL
;
137 Base64Context b64writer
= NULL
;
138 ksba_writer_t writer
;
140 ksba_cert_t cert
= NULL
;
147 dtable
= create_duptable ();
150 log_error ("creating duplicates table failed: %s\n", strerror (errno
));
157 log_error ("keydb_new failed\n");
165 for (sl
=names
, ndesc
=0; sl
; sl
= sl
->next
, ndesc
++)
169 desc
= xtrycalloc (ndesc
, sizeof *desc
);
172 log_error ("allocating memory for export failed: %s\n",
173 gpg_strerror (out_of_core ()));
178 desc
[0].mode
= KEYDB_SEARCH_MODE_FIRST
;
181 for (ndesc
=0, sl
=names
; sl
; sl
= sl
->next
)
183 rc
= keydb_classify_name (sl
->d
, desc
+ndesc
);
186 log_error ("key `%s' not found: %s\n",
187 sl
->d
, gpg_strerror (rc
));
195 /* If all specifications are done by fingerprint, we switch to
196 ephemeral mode so that _all_ currently available and matching
197 certificates are exported.
199 fixme: we should in this case keep a list of certificates to
200 avoid accidential export of duplicate certificates. */
204 && (desc
[i
].mode
== KEYDB_SEARCH_MODE_FPR
205 || desc
[i
].mode
== KEYDB_SEARCH_MODE_FPR20
206 || desc
[i
].mode
== KEYDB_SEARCH_MODE_FPR16
)); i
++)
209 keydb_set_ephemeral (hd
, 1);
212 while (!(rc
= keydb_search (hd
, desc
, ndesc
)))
214 unsigned char fpr
[20];
218 desc
[0].mode
= KEYDB_SEARCH_MODE_NEXT
;
220 rc
= keydb_get_cert (hd
, &cert
);
223 log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc
));
227 gpgsm_get_fingerprint (cert
, 0, fpr
, NULL
);
228 rc
= insert_duptable (dtable
, fpr
, &exists
);
231 log_error ("inserting into duplicates table fauiled: %s\n",
236 if (!exists
&& count
&& !ctrl
->create_pem
)
238 log_info ("exporting more than one certificate "
239 "is not possible in binary mode\n");
240 log_info ("ignoring other certificates\n");
246 const unsigned char *image
;
249 image
= ksba_cert_get_image (cert
, &imagelen
);
252 log_error ("ksba_cert_get_image failed\n");
257 if (ctrl
->create_pem
)
262 es_putc ('\n', stream
);
266 print_short_info (cert
, fp
, stream
);
268 es_putc ('\n', stream
);
276 ctrl
->pem_name
= "CERTIFICATE";
277 rc
= gpgsm_create_writer (&b64writer
, ctrl
, fp
, stream
, &writer
);
280 log_error ("can't create writer: %s\n", gpg_strerror (rc
));
285 rc
= ksba_writer_write (writer
, image
, imagelen
);
288 log_error ("write error: %s\n", gpg_strerror (rc
));
292 if (ctrl
->create_pem
)
294 /* We want one certificate per PEM block */
295 rc
= gpgsm_finish_writer (b64writer
);
298 log_error ("write failed: %s\n", gpg_strerror (rc
));
301 gpgsm_destroy_writer (b64writer
);
306 ksba_cert_release (cert
);
310 log_error ("keydb_search failed: %s\n", gpg_strerror (rc
));
313 rc
= gpgsm_finish_writer (b64writer
);
316 log_error ("write failed: %s\n", gpg_strerror (rc
));
322 gpgsm_destroy_writer (b64writer
);
323 ksba_cert_release (cert
);
326 destroy_duptable (dtable
);
330 /* Export a certificates and its private key. */
332 gpgsm_p12_export (ctrl_t ctrl
, const char *name
, FILE *fp
)
335 KEYDB_SEARCH_DESC
*desc
= NULL
;
336 Base64Context b64writer
= NULL
;
337 ksba_writer_t writer
;
338 ksba_cert_t cert
= NULL
;
340 const unsigned char *image
;
342 char *keygrip
= NULL
;
352 log_error ("keydb_new failed\n");
356 desc
= xtrycalloc (1, sizeof *desc
);
359 log_error ("allocating memory for export failed: %s\n",
360 gpg_strerror (out_of_core ()));
364 rc
= keydb_classify_name (name
, desc
);
367 log_error ("key `%s' not found: %s\n",
368 name
, gpg_strerror (rc
));
372 /* Lookup the certificate an make sure that it is unique. */
373 rc
= keydb_search (hd
, desc
, 1);
376 rc
= keydb_get_cert (hd
, &cert
);
379 log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc
));
384 rc
= keydb_search (hd
, desc
, 1);
387 ksba_cert_t cert2
= NULL
;
389 if (!keydb_get_cert (hd
, &cert2
))
391 if (gpgsm_certs_identical_p (cert
, cert2
))
393 ksba_cert_release (cert2
);
396 ksba_cert_release (cert2
);
398 rc
= gpg_error (GPG_ERR_AMBIGUOUS_NAME
);
400 else if (rc
== -1 || gpg_err_code (rc
) == GPG_ERR_EOF
)
404 log_error ("key `%s' not found: %s\n",
405 name
, gpg_strerror (rc
));
410 keygrip
= gpgsm_get_keygrip_hexstring (cert
);
411 if (!keygrip
|| gpgsm_agent_havekey (ctrl
, keygrip
))
413 /* Note, that the !keygrip case indicates a bad certificate. */
414 rc
= gpg_error (GPG_ERR_NO_SECKEY
);
415 log_error ("can't export key `%s': %s\n", name
, gpg_strerror (rc
));
419 image
= ksba_cert_get_image (cert
, &imagelen
);
422 log_error ("ksba_cert_get_image failed\n");
426 if (ctrl
->create_pem
)
428 print_short_info (cert
, fp
, NULL
);
432 if (opt
.p12_charset
&& ctrl
->create_pem
)
434 fprintf (fp
, "The passphrase is %s encoded.\n\n",
438 ctrl
->pem_name
= "PKCS12";
439 rc
= gpgsm_create_writer (&b64writer
, ctrl
, fp
, NULL
, &writer
);
442 log_error ("can't create writer: %s\n", gpg_strerror (rc
));
447 prompt
= gpgsm_format_keydesc (cert
);
448 rc
= export_p12 (ctrl
, image
, imagelen
, prompt
, keygrip
, &datafp
);
453 while ( (nread
= fread (buffer
, 1, sizeof buffer
, datafp
)) > 0 )
454 if ((rc
= ksba_writer_write (writer
, buffer
, nread
)))
456 log_error ("write failed: %s\n", gpg_strerror (rc
));
461 rc
= gpg_error_from_errno (rc
);
462 log_error ("error reading temporary file: %s\n", gpg_strerror (rc
));
466 if (ctrl
->create_pem
)
468 /* We want one certificate per PEM block */
469 rc
= gpgsm_finish_writer (b64writer
);
472 log_error ("write failed: %s\n", gpg_strerror (rc
));
475 gpgsm_destroy_writer (b64writer
);
479 ksba_cert_release (cert
);
485 gpgsm_destroy_writer (b64writer
);
486 ksba_cert_release (cert
);
492 /* Call either es_putc or the plain putc. */
494 do_putc (int value
, FILE *fp
, estream_t stream
)
497 es_putc (value
, stream
);
502 /* Call either es_fputs or the plain fputs. */
504 do_fputs (const char *string
, FILE *fp
, estream_t stream
)
507 es_fputs (string
, stream
);
513 /* Print some info about the certifciate CERT to FP or STREAM */
515 print_short_info (ksba_cert_t cert
, FILE *fp
, estream_t stream
)
521 for (idx
=0; (p
= ksba_cert_get_issuer (cert
, idx
)); idx
++)
525 : "\n aka ...: "), fp
, stream
);
527 gpgsm_es_print_name (stream
, p
);
529 gpgsm_print_name (fp
, p
);
532 do_putc ('\n', fp
, stream
);
534 do_fputs ("Serial ...: ", fp
, stream
);
535 sexp
= ksba_cert_get_serial (cert
);
539 const unsigned char *s
= sexp
;
544 for (len
=0; *s
&& *s
!= ':' && digitp (s
); s
++)
545 len
= len
*10 + atoi_1 (s
);
549 es_write_hexstring (stream
, s
+1, len
, 0, NULL
);
551 print_hexstring (fp
, s
+1, len
, 0);
556 do_putc ('\n', fp
, stream
);
558 for (idx
=0; (p
= ksba_cert_get_subject (cert
, idx
)); idx
++)
562 : "\n aka ..: "), fp
, stream
);
564 gpgsm_es_print_name (stream
, p
);
566 gpgsm_print_name (fp
, p
);
569 do_putc ('\n', fp
, stream
);
574 popen_protect_tool (const char *pgmname
,
575 FILE *infile
, FILE *outfile
, FILE **statusfile
,
576 const char *prompt
, const char *keygrip
,
579 const char *argv
[20];
582 argv
[i
++] = "--homedir";
583 argv
[i
++] = opt
.homedir
;
584 argv
[i
++] = "--p12-export";
585 argv
[i
++] = "--have-cert";
586 argv
[i
++] = "--prompt";
587 argv
[i
++] = prompt
?prompt
:"";
588 argv
[i
++] = "--enable-status-msg";
591 argv
[i
++] = "--p12-charset";
592 argv
[i
++] = opt
.p12_charset
;
597 assert (i
< sizeof argv
);
599 return gnupg_spawn_process (pgmname
, argv
, infile
, outfile
,
600 setup_pinentry_env
, 128,
606 export_p12 (ctrl_t ctrl
, const unsigned char *certimg
, size_t certimglen
,
607 const char *prompt
, const char *keygrip
,
611 gpg_error_t err
= 0, child_err
= 0;
614 FILE *infp
= NULL
, *outfp
= NULL
, *fp
= NULL
;
619 if (!opt
.protect_tool_program
|| !*opt
.protect_tool_program
)
620 pgmname
= gnupg_module_name (GNUPG_MODULE_NAME_PROTECT_TOOL
);
622 pgmname
= opt
.protect_tool_program
;
624 infp
= gnupg_tmpfile ();
627 err
= gpg_error_from_syserror ();
628 log_error (_("error creating temporary file: %s\n"), strerror (errno
));
632 if (fwrite (certimg
, certimglen
, 1, infp
) != 1)
634 err
= gpg_error_from_syserror ();
635 log_error (_("error writing to temporary file: %s\n"),
640 outfp
= gnupg_tmpfile ();
643 err
= gpg_error_from_syserror ();
644 log_error (_("error creating temporary file: %s\n"), strerror (errno
));
648 err
= popen_protect_tool (pgmname
, infp
, outfp
, &fp
, prompt
, keygrip
, &pid
);
657 /* Read stderr of the protect tool. */
660 while ((c
=getc (fp
)) != EOF
)
662 /* fixme: We could here grep for status information of the
663 protect tool to figure out better error codes for
666 if (pos
>= sizeof buffer
- 5 || c
== '\n')
668 buffer
[pos
- (c
== '\n')] = 0;
670 log_printf ("%s", buffer
);
673 if (!strncmp (buffer
, "gpg-protect-tool: [PROTECT-TOOL:] ",34))
678 pend
= strchr (p
, ' ');
681 if ( !strcmp (p
, "bad-passphrase"))
685 log_info ("%s", buffer
);
688 cont_line
= (c
!= '\n');
696 log_printf ("%s\n", buffer
);
698 log_info ("%s\n", buffer
);
703 /* If we found no error in the output of the child, setup a suitable
704 error code, which will later be reset if the exit status of the
707 child_err
= gpg_error (GPG_ERR_DECRYPT_FAILED
);
716 if (!gnupg_wait_process (pgmname
, pid
, NULL
))
730 /* During export this is the passphrase used to unprotect the
731 key and not the pkcs#12 thing as in export. Therefore we can
732 issue the regular passphrase status. FIXME: replace the all
733 zero keyid by a regular one. */
734 gpgsm_status (ctrl
, STATUS_BAD_PASSPHRASE
, "0000000000000000");