Line data Source code
1 : /* export.c - Export certificates and private keys.
2 : * Copyright (C) 2002, 2003, 2004, 2007, 2009,
3 : * 2010 Free Software Foundation, Inc.
4 : *
5 : * This file is part of GnuPG.
6 : *
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.
11 : *
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.
16 : *
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/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 : #include <time.h>
27 : #include <assert.h>
28 :
29 : #include "gpgsm.h"
30 : #include <gcrypt.h>
31 : #include <ksba.h>
32 :
33 : #include "keydb.h"
34 : #include "exechelp.h"
35 : #include "i18n.h"
36 : #include "sysutils.h"
37 : #include "minip12.h"
38 :
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. */
45 : struct duptable_s
46 : {
47 : struct duptable_s *next;
48 :
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
51 : bits). */
52 : unsigned char fpr[19];
53 : };
54 : typedef struct duptable_s *duptable_t;
55 : #define DUPTABLE_BITS 12
56 : #define DUPTABLE_SIZE (1 << DUPTABLE_BITS)
57 :
58 :
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 : int rawmode,
64 : void **r_result, size_t *r_resultlen);
65 :
66 :
67 : /* Create a table used to indetify duplicated certificates. */
68 : static duptable_t *
69 0 : create_duptable (void)
70 : {
71 0 : return xtrycalloc (DUPTABLE_SIZE, sizeof (duptable_t));
72 : }
73 :
74 : static void
75 0 : destroy_duptable (duptable_t *table)
76 : {
77 : int idx;
78 : duptable_t t, t2;
79 :
80 0 : if (table)
81 : {
82 0 : for (idx=0; idx < DUPTABLE_SIZE; idx++)
83 0 : for (t = table[idx]; t; t = t2)
84 : {
85 0 : t2 = t->next;
86 0 : xfree (t);
87 : }
88 0 : xfree (table);
89 : }
90 0 : }
91 :
92 : /* Insert the 20 byte fingerprint FPR into TABLE. Sets EXITS to true
93 : if the fingerprint already exists in the table. */
94 : static gpg_error_t
95 0 : insert_duptable (duptable_t *table, unsigned char *fpr, int *exists)
96 : {
97 : size_t idx;
98 : duptable_t t;
99 :
100 0 : *exists = 0;
101 0 : idx = fpr[0];
102 : #if DUPTABLE_BITS > 16 || DUPTABLE_BITS < 8
103 : #error cannot handle a table larger than 16 bits or smaller than 8 bits
104 : #elif DUPTABLE_BITS > 8
105 0 : idx <<= (DUPTABLE_BITS - 8);
106 0 : idx |= (fpr[1] & ~(~0U << 4));
107 : #endif
108 :
109 0 : for (t = table[idx]; t; t = t->next)
110 0 : if (!memcmp (t->fpr, fpr+1, 19))
111 0 : break;
112 0 : if (t)
113 : {
114 0 : *exists = 1;
115 0 : return 0;
116 : }
117 : /* Insert that fingerprint. */
118 0 : t = xtrymalloc (sizeof *t);
119 0 : if (!t)
120 0 : return gpg_error_from_syserror ();
121 0 : memcpy (t->fpr, fpr+1, 19);
122 0 : t->next = table[idx];
123 0 : table[idx] = t;
124 0 : return 0;
125 : }
126 :
127 :
128 : /* Export all certificates or just those given in NAMES. The output
129 : is written to STREAM. */
130 : void
131 0 : gpgsm_export (ctrl_t ctrl, strlist_t names, estream_t stream)
132 : {
133 0 : KEYDB_HANDLE hd = NULL;
134 0 : KEYDB_SEARCH_DESC *desc = NULL;
135 : int ndesc;
136 0 : Base64Context b64writer = NULL;
137 : ksba_writer_t writer;
138 : strlist_t sl;
139 0 : ksba_cert_t cert = NULL;
140 0 : int rc=0;
141 0 : int count = 0;
142 : int i;
143 : duptable_t *dtable;
144 :
145 :
146 0 : dtable = create_duptable ();
147 0 : if (!dtable)
148 : {
149 0 : log_error ("creating duplicates table failed: %s\n", strerror (errno));
150 0 : goto leave;
151 : }
152 :
153 0 : hd = keydb_new (0);
154 0 : if (!hd)
155 : {
156 0 : log_error ("keydb_new failed\n");
157 0 : goto leave;
158 : }
159 :
160 0 : if (!names)
161 0 : ndesc = 1;
162 : else
163 : {
164 0 : for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
165 : ;
166 : }
167 :
168 0 : desc = xtrycalloc (ndesc, sizeof *desc);
169 0 : if (!ndesc)
170 : {
171 0 : log_error ("allocating memory for export failed: %s\n",
172 : gpg_strerror (out_of_core ()));
173 0 : goto leave;
174 : }
175 :
176 0 : if (!names)
177 0 : desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
178 : else
179 : {
180 0 : for (ndesc=0, sl=names; sl; sl = sl->next)
181 : {
182 0 : rc = classify_user_id (sl->d, desc+ndesc, 0);
183 0 : if (rc)
184 : {
185 0 : log_error ("key '%s' not found: %s\n",
186 0 : sl->d, gpg_strerror (rc));
187 0 : rc = 0;
188 : }
189 : else
190 0 : ndesc++;
191 : }
192 : }
193 :
194 : /* If all specifications are done by fingerprint or keygrip, we
195 : switch to ephemeral mode so that _all_ currently available and
196 : matching certificates are exported. */
197 0 : if (names && ndesc)
198 : {
199 0 : for (i=0; (i < ndesc
200 0 : && (desc[i].mode == KEYDB_SEARCH_MODE_FPR
201 0 : || desc[i].mode == KEYDB_SEARCH_MODE_FPR20
202 0 : || desc[i].mode == KEYDB_SEARCH_MODE_FPR16
203 0 : || desc[i].mode == KEYDB_SEARCH_MODE_KEYGRIP)); i++)
204 : ;
205 0 : if (i == ndesc)
206 0 : keydb_set_ephemeral (hd, 1);
207 : }
208 :
209 0 : while (!(rc = keydb_search (hd, desc, ndesc)))
210 : {
211 : unsigned char fpr[20];
212 : int exists;
213 :
214 0 : if (!names)
215 0 : desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
216 :
217 0 : rc = keydb_get_cert (hd, &cert);
218 0 : if (rc)
219 : {
220 0 : log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
221 0 : goto leave;
222 : }
223 :
224 0 : gpgsm_get_fingerprint (cert, 0, fpr, NULL);
225 0 : rc = insert_duptable (dtable, fpr, &exists);
226 0 : if (rc)
227 : {
228 0 : log_error ("inserting into duplicates table failed: %s\n",
229 : gpg_strerror (rc));
230 0 : goto leave;
231 : }
232 :
233 0 : if (!exists && count && !ctrl->create_pem)
234 : {
235 0 : log_info ("exporting more than one certificate "
236 : "is not possible in binary mode\n");
237 0 : log_info ("ignoring other certificates\n");
238 0 : break;
239 : }
240 :
241 0 : if (!exists)
242 : {
243 : const unsigned char *image;
244 : size_t imagelen;
245 :
246 0 : image = ksba_cert_get_image (cert, &imagelen);
247 0 : if (!image)
248 : {
249 0 : log_error ("ksba_cert_get_image failed\n");
250 0 : goto leave;
251 : }
252 :
253 :
254 0 : if (ctrl->create_pem)
255 : {
256 0 : if (count)
257 0 : es_putc ('\n', stream);
258 0 : print_short_info (cert, stream);
259 0 : es_putc ('\n', stream);
260 : }
261 0 : count++;
262 :
263 0 : if (!b64writer)
264 : {
265 0 : ctrl->pem_name = "CERTIFICATE";
266 0 : rc = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
267 0 : if (rc)
268 : {
269 0 : log_error ("can't create writer: %s\n", gpg_strerror (rc));
270 0 : goto leave;
271 : }
272 : }
273 :
274 0 : rc = ksba_writer_write (writer, image, imagelen);
275 0 : if (rc)
276 : {
277 0 : log_error ("write error: %s\n", gpg_strerror (rc));
278 0 : goto leave;
279 : }
280 :
281 0 : if (ctrl->create_pem)
282 : {
283 : /* We want one certificate per PEM block */
284 0 : rc = gpgsm_finish_writer (b64writer);
285 0 : if (rc)
286 : {
287 0 : log_error ("write failed: %s\n", gpg_strerror (rc));
288 0 : goto leave;
289 : }
290 0 : gpgsm_destroy_writer (b64writer);
291 0 : b64writer = NULL;
292 : }
293 : }
294 :
295 0 : ksba_cert_release (cert);
296 0 : cert = NULL;
297 : }
298 0 : if (rc && rc != -1)
299 0 : log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
300 0 : else if (b64writer)
301 : {
302 0 : rc = gpgsm_finish_writer (b64writer);
303 0 : if (rc)
304 : {
305 0 : log_error ("write failed: %s\n", gpg_strerror (rc));
306 0 : goto leave;
307 : }
308 : }
309 :
310 : leave:
311 0 : gpgsm_destroy_writer (b64writer);
312 0 : ksba_cert_release (cert);
313 0 : xfree (desc);
314 0 : keydb_release (hd);
315 0 : destroy_duptable (dtable);
316 0 : }
317 :
318 :
319 : /* Export a certificate and its private key. RAWMODE controls the
320 : actual output:
321 : 0 - Private key and certifciate in PKCS#12 format
322 : 1 - Only unencrypted private key in PKCS#8 format
323 : 2 - Only unencrypted private key in PKCS#1 format
324 : */
325 : void
326 0 : gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream, int rawmode)
327 : {
328 0 : gpg_error_t err = 0;
329 : KEYDB_HANDLE hd;
330 0 : KEYDB_SEARCH_DESC *desc = NULL;
331 0 : Base64Context b64writer = NULL;
332 : ksba_writer_t writer;
333 0 : ksba_cert_t cert = NULL;
334 : const unsigned char *image;
335 : size_t imagelen;
336 0 : char *keygrip = NULL;
337 : char *prompt;
338 : void *data;
339 : size_t datalen;
340 :
341 :
342 0 : hd = keydb_new (0);
343 0 : if (!hd)
344 : {
345 0 : log_error ("keydb_new failed\n");
346 0 : goto leave;
347 : }
348 :
349 0 : desc = xtrycalloc (1, sizeof *desc);
350 0 : if (!desc)
351 : {
352 0 : log_error ("allocating memory for export failed: %s\n",
353 : gpg_strerror (out_of_core ()));
354 0 : goto leave;
355 : }
356 :
357 0 : err = classify_user_id (name, desc, 0);
358 0 : if (err)
359 : {
360 0 : log_error ("key '%s' not found: %s\n",
361 : name, gpg_strerror (err));
362 0 : goto leave;
363 : }
364 :
365 : /* Lookup the certificate and make sure that it is unique. */
366 0 : err = keydb_search (hd, desc, 1);
367 0 : if (!err)
368 : {
369 0 : err = keydb_get_cert (hd, &cert);
370 0 : if (err)
371 : {
372 0 : log_error ("keydb_get_cert failed: %s\n", gpg_strerror (err));
373 0 : goto leave;
374 : }
375 :
376 : next_ambiguous:
377 0 : err = keydb_search (hd, desc, 1);
378 0 : if (!err)
379 : {
380 0 : ksba_cert_t cert2 = NULL;
381 :
382 0 : if (!keydb_get_cert (hd, &cert2))
383 : {
384 0 : if (gpgsm_certs_identical_p (cert, cert2))
385 : {
386 0 : ksba_cert_release (cert2);
387 0 : goto next_ambiguous;
388 : }
389 0 : ksba_cert_release (cert2);
390 : }
391 0 : err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
392 : }
393 0 : else if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
394 0 : err = 0;
395 0 : if (err)
396 : {
397 0 : log_error ("key '%s' not found: %s\n",
398 : name, gpg_strerror (err));
399 0 : goto leave;
400 : }
401 : }
402 :
403 0 : keygrip = gpgsm_get_keygrip_hexstring (cert);
404 0 : if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip))
405 : {
406 : /* Note, that the !keygrip case indicates a bad certificate. */
407 0 : err = gpg_error (GPG_ERR_NO_SECKEY);
408 0 : log_error ("can't export key '%s': %s\n", name, gpg_strerror (err));
409 0 : goto leave;
410 : }
411 :
412 0 : image = ksba_cert_get_image (cert, &imagelen);
413 0 : if (!image)
414 : {
415 0 : log_error ("ksba_cert_get_image failed\n");
416 0 : goto leave;
417 : }
418 :
419 0 : if (ctrl->create_pem)
420 : {
421 0 : print_short_info (cert, stream);
422 0 : es_putc ('\n', stream);
423 : }
424 :
425 0 : if (opt.p12_charset && ctrl->create_pem && !rawmode)
426 : {
427 0 : es_fprintf (stream, "The passphrase is %s encoded.\n\n",
428 : opt.p12_charset);
429 : }
430 :
431 0 : if (rawmode == 0)
432 0 : ctrl->pem_name = "PKCS12";
433 0 : else if (rawmode == 1)
434 0 : ctrl->pem_name = "PRIVATE KEY";
435 : else
436 0 : ctrl->pem_name = "RSA PRIVATE KEY";
437 0 : err = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
438 0 : if (err)
439 : {
440 0 : log_error ("can't create writer: %s\n", gpg_strerror (err));
441 0 : goto leave;
442 : }
443 :
444 0 : prompt = gpgsm_format_keydesc (cert);
445 0 : err = export_p12 (ctrl, image, imagelen, prompt, keygrip, rawmode,
446 : &data, &datalen);
447 0 : xfree (prompt);
448 0 : if (err)
449 0 : goto leave;
450 0 : err = ksba_writer_write (writer, data, datalen);
451 0 : xfree (data);
452 0 : if (err)
453 : {
454 0 : log_error ("write failed: %s\n", gpg_strerror (err));
455 0 : goto leave;
456 : }
457 :
458 0 : if (ctrl->create_pem)
459 : {
460 : /* We want one certificate per PEM block */
461 0 : err = gpgsm_finish_writer (b64writer);
462 0 : if (err)
463 : {
464 0 : log_error ("write failed: %s\n", gpg_strerror (err));
465 0 : goto leave;
466 : }
467 0 : gpgsm_destroy_writer (b64writer);
468 0 : b64writer = NULL;
469 : }
470 :
471 0 : ksba_cert_release (cert);
472 0 : cert = NULL;
473 :
474 : leave:
475 0 : gpgsm_destroy_writer (b64writer);
476 0 : ksba_cert_release (cert);
477 0 : xfree (desc);
478 0 : keydb_release (hd);
479 0 : }
480 :
481 :
482 : /* Print some info about the certifciate CERT to FP or STREAM */
483 : static void
484 0 : print_short_info (ksba_cert_t cert, estream_t stream)
485 : {
486 : char *p;
487 : ksba_sexp_t sexp;
488 : int idx;
489 :
490 0 : for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
491 : {
492 0 : es_fputs ((!idx
493 : ? "Issuer ...: "
494 : : "\n aka ...: "), stream);
495 0 : gpgsm_es_print_name (stream, p);
496 0 : xfree (p);
497 : }
498 0 : es_putc ('\n', stream);
499 :
500 0 : es_fputs ("Serial ...: ", stream);
501 0 : sexp = ksba_cert_get_serial (cert);
502 0 : if (sexp)
503 : {
504 : int len;
505 0 : const unsigned char *s = sexp;
506 :
507 0 : if (*s == '(')
508 : {
509 0 : s++;
510 0 : for (len=0; *s && *s != ':' && digitp (s); s++)
511 0 : len = len*10 + atoi_1 (s);
512 0 : if (*s == ':')
513 0 : es_write_hexstring (stream, s+1, len, 0, NULL);
514 : }
515 0 : xfree (sexp);
516 : }
517 0 : es_putc ('\n', stream);
518 :
519 0 : for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
520 : {
521 0 : es_fputs ((!idx
522 : ? "Subject ..: "
523 : : "\n aka ..: "), stream);
524 0 : gpgsm_es_print_name (stream, p);
525 0 : xfree (p);
526 : }
527 0 : es_putc ('\n', stream);
528 :
529 0 : p = gpgsm_get_keygrip_hexstring (cert);
530 0 : if (p)
531 : {
532 0 : es_fprintf (stream, "Keygrip ..: %s\n", p);
533 0 : xfree (p);
534 : }
535 0 : }
536 :
537 :
538 :
539 : /* Parse a private key S-expression and return a malloced array with
540 : the RSA parameters in pkcs#12 order. The caller needs to
541 : deep-release this array. */
542 : static gcry_mpi_t *
543 0 : sexp_to_kparms (gcry_sexp_t sexp)
544 : {
545 : gcry_sexp_t list, l2;
546 : const char *name;
547 : const char *s;
548 : size_t n;
549 : int idx;
550 : const char *elems;
551 : gcry_mpi_t *array;
552 :
553 0 : list = gcry_sexp_find_token (sexp, "private-key", 0 );
554 0 : if(!list)
555 0 : return NULL;
556 0 : l2 = gcry_sexp_cadr (list);
557 0 : gcry_sexp_release (list);
558 0 : list = l2;
559 0 : name = gcry_sexp_nth_data (list, 0, &n);
560 0 : if(!name || n != 3 || memcmp (name, "rsa", 3))
561 : {
562 0 : gcry_sexp_release (list);
563 0 : return NULL;
564 : }
565 :
566 : /* Parameter names used with RSA in the pkcs#12 order. */
567 0 : elems = "nedqp--u";
568 0 : array = xtrycalloc (strlen(elems) + 1, sizeof *array);
569 0 : if (!array)
570 : {
571 0 : gcry_sexp_release (list);
572 0 : return NULL;
573 : }
574 0 : for (idx=0, s=elems; *s; s++, idx++ )
575 : {
576 0 : if (*s == '-')
577 0 : continue; /* Computed below */
578 0 : l2 = gcry_sexp_find_token (list, s, 1);
579 0 : if (l2)
580 : {
581 0 : array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
582 0 : gcry_sexp_release (l2);
583 : }
584 0 : if (!array[idx]) /* Required parameter not found or invalid. */
585 : {
586 0 : for (idx=0; array[idx]; idx++)
587 0 : gcry_mpi_release (array[idx]);
588 0 : xfree (array);
589 0 : gcry_sexp_release (list);
590 0 : return NULL;
591 : }
592 : }
593 0 : gcry_sexp_release (list);
594 :
595 0 : array[5] = gcry_mpi_snew (0); /* compute d mod (q-1) */
596 0 : gcry_mpi_sub_ui (array[5], array[3], 1);
597 0 : gcry_mpi_mod (array[5], array[2], array[5]);
598 :
599 0 : array[6] = gcry_mpi_snew (0); /* compute d mod (p-1) */
600 0 : gcry_mpi_sub_ui (array[6], array[4], 1);
601 0 : gcry_mpi_mod (array[6], array[3], array[6]);
602 :
603 0 : return array;
604 : }
605 :
606 :
607 : static gpg_error_t
608 0 : export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
609 : const char *prompt, const char *keygrip, int rawmode,
610 : void **r_result, size_t *r_resultlen)
611 : {
612 0 : gpg_error_t err = 0;
613 0 : void *kek = NULL;
614 : size_t keklen;
615 0 : unsigned char *wrappedkey = NULL;
616 : size_t wrappedkeylen;
617 0 : gcry_cipher_hd_t cipherhd = NULL;
618 0 : gcry_sexp_t s_skey = NULL;
619 0 : gcry_mpi_t *kparms = NULL;
620 0 : unsigned char *key = NULL;
621 : size_t keylen;
622 0 : char *passphrase = NULL;
623 0 : unsigned char *result = NULL;
624 : size_t resultlen;
625 : int i;
626 :
627 0 : *r_result = NULL;
628 :
629 : /* Get the current KEK. */
630 0 : err = gpgsm_agent_keywrap_key (ctrl, 1, &kek, &keklen);
631 0 : if (err)
632 : {
633 0 : log_error ("error getting the KEK: %s\n", gpg_strerror (err));
634 0 : goto leave;
635 : }
636 :
637 : /* Receive the wrapped key from the agent. */
638 0 : err = gpgsm_agent_export_key (ctrl, keygrip, prompt,
639 : &wrappedkey, &wrappedkeylen);
640 0 : if (err)
641 0 : goto leave;
642 :
643 :
644 : /* Unwrap the key. */
645 0 : err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
646 : GCRY_CIPHER_MODE_AESWRAP, 0);
647 0 : if (err)
648 0 : goto leave;
649 0 : err = gcry_cipher_setkey (cipherhd, kek, keklen);
650 0 : if (err)
651 0 : goto leave;
652 0 : xfree (kek);
653 0 : kek = NULL;
654 :
655 0 : if (wrappedkeylen < 24)
656 : {
657 0 : err = gpg_error (GPG_ERR_INV_LENGTH);
658 0 : goto leave;
659 : }
660 0 : keylen = wrappedkeylen - 8;
661 0 : key = xtrymalloc_secure (keylen);
662 0 : if (!key)
663 : {
664 0 : err = gpg_error_from_syserror ();
665 0 : goto leave;
666 : }
667 0 : err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
668 0 : if (err)
669 0 : goto leave;
670 0 : xfree (wrappedkey);
671 0 : wrappedkey = NULL;
672 0 : gcry_cipher_close (cipherhd);
673 0 : cipherhd = NULL;
674 :
675 :
676 : /* Convert to a gcrypt S-expression. */
677 0 : err = gcry_sexp_create (&s_skey, key, keylen, 0, xfree_fnc);
678 0 : if (err)
679 0 : goto leave;
680 0 : key = NULL; /* Key is now owned by S_KEY. */
681 :
682 : /* Get the parameters from the S-expression. */
683 0 : kparms = sexp_to_kparms (s_skey);
684 0 : gcry_sexp_release (s_skey);
685 0 : s_skey = NULL;
686 0 : if (!kparms)
687 : {
688 0 : log_error ("error converting key parameters\n");
689 0 : err = GPG_ERR_BAD_SECKEY;
690 0 : goto leave;
691 : }
692 :
693 0 : if (rawmode)
694 : {
695 : /* Export in raw mode, that is only the pkcs#1/#8 private key. */
696 0 : result = p12_raw_build (kparms, rawmode, &resultlen);
697 0 : if (!result)
698 0 : err = gpg_error (GPG_ERR_GENERAL);
699 : }
700 : else
701 : {
702 0 : err = gpgsm_agent_ask_passphrase
703 : (ctrl,
704 : i18n_utf8 ("Please enter the passphrase to protect the "
705 : "new PKCS#12 object."),
706 : 1, &passphrase);
707 0 : if (err)
708 0 : goto leave;
709 :
710 0 : result = p12_build (kparms, certimg, certimglen, passphrase,
711 : opt.p12_charset, &resultlen);
712 0 : xfree (passphrase);
713 0 : passphrase = NULL;
714 0 : if (!result)
715 0 : err = gpg_error (GPG_ERR_GENERAL);
716 : }
717 :
718 : leave:
719 0 : xfree (key);
720 0 : gcry_sexp_release (s_skey);
721 0 : if (kparms)
722 : {
723 0 : for (i=0; kparms[i]; i++)
724 0 : gcry_mpi_release (kparms[i]);
725 0 : xfree (kparms);
726 : }
727 0 : gcry_cipher_close (cipherhd);
728 0 : xfree (wrappedkey);
729 0 : xfree (kek);
730 :
731 0 : if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
732 : {
733 : /* During export this is the passphrase used to unprotect the
734 : key and not the pkcs#12 thing as in export. Therefore we can
735 : issue the regular passphrase status. FIXME: replace the all
736 : zero keyid by a regular one. */
737 0 : gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000");
738 : }
739 :
740 0 : if (err)
741 : {
742 0 : xfree (result);
743 : }
744 : else
745 : {
746 0 : *r_result = result;
747 0 : *r_resultlen = resultlen;
748 : }
749 0 : return err;
750 : }
|