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 <https://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 ();
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 (ctrl, 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 0 : hd = keydb_new ();
342 0 : if (!hd)
343 : {
344 0 : log_error ("keydb_new failed\n");
345 0 : goto leave;
346 : }
347 :
348 0 : desc = xtrycalloc (1, sizeof *desc);
349 0 : if (!desc)
350 : {
351 0 : log_error ("allocating memory for export failed: %s\n",
352 : gpg_strerror (out_of_core ()));
353 0 : goto leave;
354 : }
355 :
356 0 : err = classify_user_id (name, desc, 0);
357 0 : if (err)
358 : {
359 0 : log_error ("key '%s' not found: %s\n",
360 : name, gpg_strerror (err));
361 0 : goto leave;
362 : }
363 :
364 : /* Lookup the certificate and make sure that it is unique. */
365 0 : err = keydb_search (ctrl, hd, desc, 1);
366 0 : if (!err)
367 : {
368 0 : err = keydb_get_cert (hd, &cert);
369 0 : if (err)
370 : {
371 0 : log_error ("keydb_get_cert failed: %s\n", gpg_strerror (err));
372 0 : goto leave;
373 : }
374 :
375 : next_ambiguous:
376 0 : err = keydb_search (ctrl, hd, desc, 1);
377 0 : if (!err)
378 : {
379 0 : ksba_cert_t cert2 = NULL;
380 :
381 0 : if (!keydb_get_cert (hd, &cert2))
382 : {
383 0 : if (gpgsm_certs_identical_p (cert, cert2))
384 : {
385 0 : ksba_cert_release (cert2);
386 0 : goto next_ambiguous;
387 : }
388 0 : ksba_cert_release (cert2);
389 : }
390 0 : err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
391 : }
392 0 : else if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
393 0 : err = 0;
394 0 : if (err)
395 : {
396 0 : log_error ("key '%s' not found: %s\n",
397 : name, gpg_strerror (err));
398 0 : goto leave;
399 : }
400 : }
401 :
402 0 : keygrip = gpgsm_get_keygrip_hexstring (cert);
403 0 : if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip))
404 : {
405 : /* Note, that the !keygrip case indicates a bad certificate. */
406 0 : err = gpg_error (GPG_ERR_NO_SECKEY);
407 0 : log_error ("can't export key '%s': %s\n", name, gpg_strerror (err));
408 0 : goto leave;
409 : }
410 :
411 0 : image = ksba_cert_get_image (cert, &imagelen);
412 0 : if (!image)
413 : {
414 0 : log_error ("ksba_cert_get_image failed\n");
415 0 : goto leave;
416 : }
417 :
418 0 : if (ctrl->create_pem)
419 : {
420 0 : print_short_info (cert, stream);
421 0 : es_putc ('\n', stream);
422 : }
423 :
424 0 : if (opt.p12_charset && ctrl->create_pem && !rawmode)
425 : {
426 0 : es_fprintf (stream, "The passphrase is %s encoded.\n\n",
427 : opt.p12_charset);
428 : }
429 :
430 0 : if (rawmode == 0)
431 0 : ctrl->pem_name = "PKCS12";
432 0 : else if (rawmode == 1)
433 0 : ctrl->pem_name = "PRIVATE KEY";
434 : else
435 0 : ctrl->pem_name = "RSA PRIVATE KEY";
436 0 : err = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
437 0 : if (err)
438 : {
439 0 : log_error ("can't create writer: %s\n", gpg_strerror (err));
440 0 : goto leave;
441 : }
442 :
443 0 : prompt = gpgsm_format_keydesc (cert);
444 0 : err = export_p12 (ctrl, image, imagelen, prompt, keygrip, rawmode,
445 : &data, &datalen);
446 0 : xfree (prompt);
447 0 : if (err)
448 0 : goto leave;
449 0 : err = ksba_writer_write (writer, data, datalen);
450 0 : xfree (data);
451 0 : if (err)
452 : {
453 0 : log_error ("write failed: %s\n", gpg_strerror (err));
454 0 : goto leave;
455 : }
456 :
457 0 : if (ctrl->create_pem)
458 : {
459 : /* We want one certificate per PEM block */
460 0 : err = gpgsm_finish_writer (b64writer);
461 0 : if (err)
462 : {
463 0 : log_error ("write failed: %s\n", gpg_strerror (err));
464 0 : goto leave;
465 : }
466 0 : gpgsm_destroy_writer (b64writer);
467 0 : b64writer = NULL;
468 : }
469 :
470 0 : ksba_cert_release (cert);
471 0 : cert = NULL;
472 :
473 : leave:
474 0 : gpgsm_destroy_writer (b64writer);
475 0 : ksba_cert_release (cert);
476 0 : xfree (desc);
477 0 : keydb_release (hd);
478 0 : }
479 :
480 :
481 : /* Print some info about the certifciate CERT to FP or STREAM */
482 : static void
483 0 : print_short_info (ksba_cert_t cert, estream_t stream)
484 : {
485 : char *p;
486 : ksba_sexp_t sexp;
487 : int idx;
488 :
489 0 : for (idx=0; (p = ksba_cert_get_issuer (cert, idx)); idx++)
490 : {
491 0 : es_fputs ((!idx
492 : ? "Issuer ...: "
493 : : "\n aka ...: "), stream);
494 0 : gpgsm_es_print_name (stream, p);
495 0 : xfree (p);
496 : }
497 0 : es_putc ('\n', stream);
498 :
499 0 : es_fputs ("Serial ...: ", stream);
500 0 : sexp = ksba_cert_get_serial (cert);
501 0 : if (sexp)
502 : {
503 : int len;
504 0 : const unsigned char *s = sexp;
505 :
506 0 : if (*s == '(')
507 : {
508 0 : s++;
509 0 : for (len=0; *s && *s != ':' && digitp (s); s++)
510 0 : len = len*10 + atoi_1 (s);
511 0 : if (*s == ':')
512 0 : es_write_hexstring (stream, s+1, len, 0, NULL);
513 : }
514 0 : xfree (sexp);
515 : }
516 0 : es_putc ('\n', stream);
517 :
518 0 : for (idx=0; (p = ksba_cert_get_subject (cert, idx)); idx++)
519 : {
520 0 : es_fputs ((!idx
521 : ? "Subject ..: "
522 : : "\n aka ..: "), stream);
523 0 : gpgsm_es_print_name (stream, p);
524 0 : xfree (p);
525 : }
526 0 : es_putc ('\n', stream);
527 :
528 0 : p = gpgsm_get_keygrip_hexstring (cert);
529 0 : if (p)
530 : {
531 0 : es_fprintf (stream, "Keygrip ..: %s\n", p);
532 0 : xfree (p);
533 : }
534 0 : }
535 :
536 :
537 :
538 : /* Parse a private key S-expression and return a malloced array with
539 : the RSA parameters in pkcs#12 order. The caller needs to
540 : deep-release this array. */
541 : static gcry_mpi_t *
542 0 : sexp_to_kparms (gcry_sexp_t sexp)
543 : {
544 : gcry_sexp_t list, l2;
545 : const char *name;
546 : const char *s;
547 : size_t n;
548 : int idx;
549 : const char *elems;
550 : gcry_mpi_t *array;
551 :
552 0 : list = gcry_sexp_find_token (sexp, "private-key", 0 );
553 0 : if(!list)
554 0 : return NULL;
555 0 : l2 = gcry_sexp_cadr (list);
556 0 : gcry_sexp_release (list);
557 0 : list = l2;
558 0 : name = gcry_sexp_nth_data (list, 0, &n);
559 0 : if(!name || n != 3 || memcmp (name, "rsa", 3))
560 : {
561 0 : gcry_sexp_release (list);
562 0 : return NULL;
563 : }
564 :
565 : /* Parameter names used with RSA in the pkcs#12 order. */
566 0 : elems = "nedqp--u";
567 0 : array = xtrycalloc (strlen(elems) + 1, sizeof *array);
568 0 : if (!array)
569 : {
570 0 : gcry_sexp_release (list);
571 0 : return NULL;
572 : }
573 0 : for (idx=0, s=elems; *s; s++, idx++ )
574 : {
575 0 : if (*s == '-')
576 0 : continue; /* Computed below */
577 0 : l2 = gcry_sexp_find_token (list, s, 1);
578 0 : if (l2)
579 : {
580 0 : array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
581 0 : gcry_sexp_release (l2);
582 : }
583 0 : if (!array[idx]) /* Required parameter not found or invalid. */
584 : {
585 0 : for (idx=0; array[idx]; idx++)
586 0 : gcry_mpi_release (array[idx]);
587 0 : xfree (array);
588 0 : gcry_sexp_release (list);
589 0 : return NULL;
590 : }
591 : }
592 0 : gcry_sexp_release (list);
593 :
594 0 : array[5] = gcry_mpi_snew (0); /* compute d mod (q-1) */
595 0 : gcry_mpi_sub_ui (array[5], array[3], 1);
596 0 : gcry_mpi_mod (array[5], array[2], array[5]);
597 :
598 0 : array[6] = gcry_mpi_snew (0); /* compute d mod (p-1) */
599 0 : gcry_mpi_sub_ui (array[6], array[4], 1);
600 0 : gcry_mpi_mod (array[6], array[3], array[6]);
601 :
602 0 : return array;
603 : }
604 :
605 :
606 : static gpg_error_t
607 0 : export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen,
608 : const char *prompt, const char *keygrip, int rawmode,
609 : void **r_result, size_t *r_resultlen)
610 : {
611 0 : gpg_error_t err = 0;
612 0 : void *kek = NULL;
613 : size_t keklen;
614 0 : unsigned char *wrappedkey = NULL;
615 : size_t wrappedkeylen;
616 0 : gcry_cipher_hd_t cipherhd = NULL;
617 0 : gcry_sexp_t s_skey = NULL;
618 0 : gcry_mpi_t *kparms = NULL;
619 0 : unsigned char *key = NULL;
620 : size_t keylen;
621 0 : char *passphrase = NULL;
622 0 : unsigned char *result = NULL;
623 : size_t resultlen;
624 : int i;
625 :
626 0 : *r_result = NULL;
627 :
628 : /* Get the current KEK. */
629 0 : err = gpgsm_agent_keywrap_key (ctrl, 1, &kek, &keklen);
630 0 : if (err)
631 : {
632 0 : log_error ("error getting the KEK: %s\n", gpg_strerror (err));
633 0 : goto leave;
634 : }
635 :
636 : /* Receive the wrapped key from the agent. */
637 0 : err = gpgsm_agent_export_key (ctrl, keygrip, prompt,
638 : &wrappedkey, &wrappedkeylen);
639 0 : if (err)
640 0 : goto leave;
641 :
642 :
643 : /* Unwrap the key. */
644 0 : err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
645 : GCRY_CIPHER_MODE_AESWRAP, 0);
646 0 : if (err)
647 0 : goto leave;
648 0 : err = gcry_cipher_setkey (cipherhd, kek, keklen);
649 0 : if (err)
650 0 : goto leave;
651 0 : xfree (kek);
652 0 : kek = NULL;
653 :
654 0 : if (wrappedkeylen < 24)
655 : {
656 0 : err = gpg_error (GPG_ERR_INV_LENGTH);
657 0 : goto leave;
658 : }
659 0 : keylen = wrappedkeylen - 8;
660 0 : key = xtrymalloc_secure (keylen);
661 0 : if (!key)
662 : {
663 0 : err = gpg_error_from_syserror ();
664 0 : goto leave;
665 : }
666 0 : err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
667 0 : if (err)
668 0 : goto leave;
669 0 : xfree (wrappedkey);
670 0 : wrappedkey = NULL;
671 0 : gcry_cipher_close (cipherhd);
672 0 : cipherhd = NULL;
673 :
674 :
675 : /* Convert to a gcrypt S-expression. */
676 0 : err = gcry_sexp_create (&s_skey, key, keylen, 0, xfree_fnc);
677 0 : if (err)
678 0 : goto leave;
679 0 : key = NULL; /* Key is now owned by S_KEY. */
680 :
681 : /* Get the parameters from the S-expression. */
682 0 : kparms = sexp_to_kparms (s_skey);
683 0 : gcry_sexp_release (s_skey);
684 0 : s_skey = NULL;
685 0 : if (!kparms)
686 : {
687 0 : log_error ("error converting key parameters\n");
688 0 : err = GPG_ERR_BAD_SECKEY;
689 0 : goto leave;
690 : }
691 :
692 0 : if (rawmode)
693 : {
694 : /* Export in raw mode, that is only the pkcs#1/#8 private key. */
695 0 : result = p12_raw_build (kparms, rawmode, &resultlen);
696 0 : if (!result)
697 0 : err = gpg_error (GPG_ERR_GENERAL);
698 : }
699 : else
700 : {
701 0 : err = gpgsm_agent_ask_passphrase
702 : (ctrl,
703 : i18n_utf8 ("Please enter the passphrase to protect the "
704 : "new PKCS#12 object."),
705 : 1, &passphrase);
706 0 : if (err)
707 0 : goto leave;
708 :
709 0 : result = p12_build (kparms, certimg, certimglen, passphrase,
710 : opt.p12_charset, &resultlen);
711 0 : xfree (passphrase);
712 0 : passphrase = NULL;
713 0 : if (!result)
714 0 : err = gpg_error (GPG_ERR_GENERAL);
715 : }
716 :
717 : leave:
718 0 : xfree (key);
719 0 : gcry_sexp_release (s_skey);
720 0 : if (kparms)
721 : {
722 0 : for (i=0; kparms[i]; i++)
723 0 : gcry_mpi_release (kparms[i]);
724 0 : xfree (kparms);
725 : }
726 0 : gcry_cipher_close (cipherhd);
727 0 : xfree (wrappedkey);
728 0 : xfree (kek);
729 :
730 0 : if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE)
731 : {
732 : /* During export this is the passphrase used to unprotect the
733 : key and not the pkcs#12 thing as in export. Therefore we can
734 : issue the regular passphrase status. FIXME: replace the all
735 : zero keyid by a regular one. */
736 0 : gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000");
737 : }
738 :
739 0 : if (err)
740 : {
741 0 : xfree (result);
742 : }
743 : else
744 : {
745 0 : *r_result = result;
746 0 : *r_resultlen = resultlen;
747 : }
748 0 : return err;
749 : }
|