1 /* export.c - Export certificates and private keys.
2 * Copyright (C) 2002, 2003, 2004, 2007, 2009,
3 * 2010 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/>.
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 already 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 certificates: 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, 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,
63 void **r_result, size_t *r_resultlen);
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];
127 /* Export all certificates or just those given in NAMES. The output
128 is written to STREAM. */
130 gpgsm_export (ctrl_t ctrl, strlist_t names, estream_t stream)
132 KEYDB_HANDLE hd = NULL;
133 KEYDB_SEARCH_DESC *desc = NULL;
135 Base64Context b64writer = NULL;
136 ksba_writer_t writer;
138 ksba_cert_t cert = NULL;
145 dtable = create_duptable ();
148 log_error ("creating duplicates table failed: %s\n", strerror (errno));
155 log_error ("keydb_new failed\n");
163 for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
167 desc = xtrycalloc (ndesc, sizeof *desc);
170 log_error ("allocating memory for export failed: %s\n",
171 gpg_strerror (out_of_core ()));
176 desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
179 for (ndesc=0, sl=names; sl; sl = sl->next)
181 rc = classify_user_id (sl->d, desc+ndesc, 0);
184 log_error ("key `%s' not found: %s\n",
185 sl->d, gpg_strerror (rc));
193 /* If all specifications are done by fingerprint or keygrip, we
194 switch to ephemeral mode so that _all_ currently available and
195 matching certificates are exported. */
199 && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
200 || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
201 || desc[i].mode == KEYDB_SEARCH_MODE_FPR16
202 || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
205 keydb_set_ephemeral (hd, 1);
208 while (!(rc = keydb_search (hd, desc, ndesc)))
210 unsigned char fpr[20];
214 desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
216 rc = keydb_get_cert (hd, &cert);
219 log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
223 gpgsm_get_fingerprint (cert, 0, fpr, NULL);
224 rc = insert_duptable (dtable, fpr, &exists);
227 log_error ("inserting into duplicates table failed: %s\n",
232 if (!exists && count && !ctrl->create_pem)
234 log_info ("exporting more than one certificate "
235 "is not possible in binary mode\n");
236 log_info ("ignoring other certificates\n");
242 const unsigned char *image;
245 image = ksba_cert_get_image (cert, &imagelen);
248 log_error ("ksba_cert_get_image failed\n");
253 if (ctrl->create_pem)
256 es_putc ('\n', stream);
257 print_short_info (cert, stream);
258 es_putc ('\n', stream);
264 ctrl->pem_name = "CERTIFICATE";
265 rc = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
268 log_error ("can't create writer: %s\n", gpg_strerror (rc));
273 rc = ksba_writer_write (writer, image, imagelen);
276 log_error ("write error: %s\n", gpg_strerror (rc));
280 if (ctrl->create_pem)
282 /* We want one certificate per PEM block */
283 rc = gpgsm_finish_writer (b64writer);
286 log_error ("write failed: %s\n", gpg_strerror (rc));
289 gpgsm_destroy_writer (b64writer);
294 ksba_cert_release (cert);
298 log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
301 rc = gpgsm_finish_writer (b64writer);
304 log_error ("write failed: %s\n", gpg_strerror (rc));
310 gpgsm_destroy_writer (b64writer);
311 ksba_cert_release (cert);
314 destroy_duptable (dtable);
318 /* Export a certificate and its private key. */
320 gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream)
324 KEYDB_SEARCH_DESC *desc = NULL;
325 Base64Context b64writer = NULL;
326 ksba_writer_t writer;
327 ksba_cert_t cert = NULL;
328 const unsigned char *image;
330 char *keygrip = NULL;
339 log_error ("keydb_new failed\n");
343 desc = xtrycalloc (1, sizeof *desc);
346 log_error ("allocating memory for export failed: %s\n",
347 gpg_strerror (out_of_core ()));
351 err = classify_user_id (name, desc, 0);
354 log_error ("key `%s' not found: %s\n",
355 name, gpg_strerror (err));
359 /* Lookup the certificate and make sure that it is unique. */
360 err = keydb_search (hd, desc, 1);
363 err = keydb_get_cert (hd, &cert);
366 log_error ("keydb_get_cert failed: %s\n", gpg_strerror (err));
371 err = keydb_search (hd, desc, 1);
374 ksba_cert_t cert2 = NULL;
376 if (!keydb_get_cert (hd, &cert2))
378 if (gpgsm_certs_identical_p (cert, cert2))
380 ksba_cert_release (cert2);
383 ksba_cert_release (cert2);
385 err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
387 else if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
391 log_error ("key `%s' not found: %s\n",
392 name, gpg_strerror (err));
397 keygrip = gpgsm_get_keygrip_hexstring (cert);
398 if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip))
400 /* Note, that the !keygrip case indicates a bad certificate. */
401 err = gpg_error (GPG_ERR_NO_SECKEY);
402 log_error ("can't export key `%s': %s\n", name, gpg_strerror (err));
406 image = ksba_cert_get_image (cert, &imagelen);
409 log_error ("ksba_cert_get_image failed\n");
413 if (ctrl->create_pem)
415 print_short_info (cert, stream);
416 es_putc ('\n', stream);
419 if (opt.p12_charset && ctrl->create_pem)
421 es_fprintf (stream, "The passphrase is %s encoded.\n\n",
425 ctrl->pem_name = "PKCS12";
426 err = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
429 log_error ("can't create writer: %s\n", gpg_strerror (err));
433 prompt = gpgsm_format_keydesc (cert);
434 err = export_p12 (ctrl, image, imagelen, prompt, keygrip, &data, &datalen);
438 err = ksba_writer_write (writer, data, datalen);
442 log_error ("write failed: %s\n", gpg_strerror (err));
446 if (ctrl->create_pem)
448 /* We want one certificate per PEM block */
449 err = gpgsm_finish_writer (b64writer);
452 log_error ("write failed: %s\n", gpg_strerror (err));
455 gpgsm_destroy_writer (b64writer);
459 ksba_cert_release (cert);
463 gpgsm_destroy_writer (b64writer);
464 ksba_cert_release (cert);
470 /* Print some info about the certifciate CERT to FP or STREAM */
472 print_short_info (ksba_cert_t cert, estream_t stream)
478 for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
482 : "\n aka ...: "), stream);
483 gpgsm_es_print_name (stream, p);
486 es_putc ('\n', stream);
488 es_fputs ("Serial ...: ", stream);
489 sexp = ksba_cert_get_serial (cert);
493 const unsigned char *s = sexp;
498 for (len=0; *s && *s != ':' && digitp (s); s++)
499 len = len*10 + atoi_1 (s);
501 es_write_hexstring (stream, s+1, len, 0, NULL);
505 es_putc ('\n', stream);
507 for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
511 : "\n aka ..: "), stream);
512 gpgsm_es_print_name (stream, p);
515 es_putc ('\n', stream);
520 /* Parse a private key S-expression and retutn a malloced array with
521 the RSA paramaters in pkcs#12 order. The caller needs to
522 deep-release this array. */
524 sexp_to_kparms (gcry_sexp_t sexp)
526 gcry_sexp_t list, l2;
534 list = gcry_sexp_find_token (sexp, "private-key", 0 );
537 l2 = gcry_sexp_cadr (list);
538 gcry_sexp_release (list);
540 name = gcry_sexp_nth_data (list, 0, &n);
541 if(!name || n != 3 || memcmp (name, "rsa", 3))
543 gcry_sexp_release (list);
547 /* Parameter names used with RSA in the pkcs#12 order. */
549 array = xtrycalloc (strlen(elems) + 1, sizeof *array);
552 gcry_sexp_release (list);
555 for (idx=0, s=elems; *s; s++, idx++ )
558 continue; /* Computed below */
559 l2 = gcry_sexp_find_token (list, s, 1);
562 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
563 gcry_sexp_release (l2);
565 if (!array[idx]) /* Required parameter not found or invalid. */
567 for (idx=0; array[idx]; idx++)
568 gcry_mpi_release (array[idx]);
570 gcry_sexp_release (list);
574 gcry_sexp_release (list);
576 array[5] = gcry_mpi_snew (0); /* compute d mod (q-1) */
577 gcry_mpi_sub_ui (array[5], array[3], 1);
578 gcry_mpi_mod (array[5], array[2], array[5]);
580 array[6] = gcry_mpi_snew (0); /* compute d mod (p-1) */
581 gcry_mpi_sub_ui (array[6], array[4], 1);
582 gcry_mpi_mod (array[6], array[3], array[6]);
589 export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
590 const char *prompt, const char *keygrip,
591 void **r_result, size_t *r_resultlen)
596 unsigned char *wrappedkey = NULL;
597 size_t wrappedkeylen;
598 gcry_cipher_hd_t cipherhd = NULL;
599 gcry_sexp_t s_skey = NULL;
600 gcry_mpi_t *kparms = NULL;
601 unsigned char *key = NULL;
603 char *passphrase = NULL;
604 unsigned char *result = NULL;
610 /* Get the current KEK. */
611 err = gpgsm_agent_keywrap_key (ctrl, 1, &kek, &keklen);
614 log_error ("error getting the KEK: %s\n", gpg_strerror (err));
618 /* Receive the wrapped key from the agent. */
619 err = gpgsm_agent_export_key (ctrl, keygrip, prompt,
620 &wrappedkey, &wrappedkeylen);
625 /* Unwrap the key. */
626 err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
627 GCRY_CIPHER_MODE_AESWRAP, 0);
630 err = gcry_cipher_setkey (cipherhd, kek, keklen);
636 if (wrappedkeylen < 24)
638 err = gpg_error (GPG_ERR_INV_LENGTH);
641 keylen = wrappedkeylen - 8;
642 key = xtrymalloc_secure (keylen);
645 err = gpg_error_from_syserror ();
648 err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
653 gcry_cipher_close (cipherhd);
657 /* Convert to a gcrypt S-expression. */
658 err = gcry_sexp_create (&s_skey, key, keylen, 0, xfree_fnc);
661 key = NULL; /* Key is now owned by S_KEY. */
663 /* Get the parameters from the S-expression. */
664 kparms = sexp_to_kparms (s_skey);
665 gcry_sexp_release (s_skey);
669 log_error ("error converting key parameters\n");
670 err = GPG_ERR_BAD_SECKEY;
674 err = gpgsm_agent_ask_passphrase
676 i18n_utf8 ("Please enter the passphrase to protect the "
677 "new PKCS#12 object."),
682 result = p12_build (kparms, certimg, certimglen, passphrase,
683 opt.p12_charset, &resultlen);
687 err = gpg_error (GPG_ERR_GENERAL);
691 gcry_sexp_release (s_skey);
694 for (i=0; kparms[i]; i++)
695 gcry_mpi_release (kparms[i]);
698 gcry_cipher_close (cipherhd);
702 if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
704 /* During export this is the passphrase used to unprotect the
705 key and not the pkcs#12 thing as in export. Therefore we can
706 issue the regular passphrase status. FIXME: replace the all
707 zero keyid by a regular one. */
708 gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000");
718 *r_resultlen = resultlen;