Line data Source code
1 : /* cvt-openpgp.c - Convert an OpenPGP key to our internal format.
2 : * Copyright (C) 1998-2002, 2006, 2009, 2010 Free Software Foundation, Inc.
3 : * Copyright (C) 2013, 2014 Werner Koch
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 <assert.h>
26 :
27 : #include "agent.h"
28 : #include "i18n.h"
29 : #include "cvt-openpgp.h"
30 : #include "host2net.h"
31 :
32 :
33 : /* Helper to pass data via the callback to do_unprotect. */
34 : struct try_do_unprotect_arg_s
35 : {
36 : int is_v4;
37 : int is_protected;
38 : int pubkey_algo;
39 : const char *curve;
40 : int protect_algo;
41 : char *iv;
42 : int ivlen;
43 : int s2k_mode;
44 : int s2k_algo;
45 : byte *s2k_salt;
46 : u32 s2k_count;
47 : u16 desired_csum;
48 : gcry_mpi_t *skey;
49 : size_t skeysize;
50 : int skeyidx;
51 : gcry_sexp_t *r_key;
52 : };
53 :
54 :
55 :
56 : /* Compute the keygrip from the public key and store it at GRIP. */
57 : static gpg_error_t
58 29 : get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey,
59 : unsigned char *grip)
60 : {
61 : gpg_error_t err;
62 29 : gcry_sexp_t s_pkey = NULL;
63 :
64 29 : switch (pubkey_algo)
65 : {
66 : case GCRY_PK_DSA:
67 9 : err = gcry_sexp_build (&s_pkey, NULL,
68 : "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
69 9 : pkey[0], pkey[1], pkey[2], pkey[3]);
70 3 : break;
71 :
72 : case GCRY_PK_ELG:
73 6 : err = gcry_sexp_build (&s_pkey, NULL,
74 : "(public-key(elg(p%m)(g%m)(y%m)))",
75 6 : pkey[0], pkey[1], pkey[2]);
76 3 : break;
77 :
78 : case GCRY_PK_RSA:
79 5 : err = gcry_sexp_build (&s_pkey, NULL,
80 5 : "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]);
81 5 : break;
82 :
83 : case GCRY_PK_ECC:
84 18 : if (!curve)
85 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
86 : else
87 : {
88 : const char *format;
89 :
90 18 : if (!strcmp (curve, "Ed25519"))
91 0 : format = "(public-key(ecc(curve %s)(flags eddsa)(q%m)))";
92 18 : else if (!strcmp (curve, "Curve25519"))
93 0 : format = "(public-key(ecc(curve %s)(flags djb-tweak)(q%m)))";
94 : else
95 18 : format = "(public-key(ecc(curve %s)(q%m)))";
96 :
97 18 : err = gcry_sexp_build (&s_pkey, NULL, format, curve, pkey[0]);
98 : }
99 18 : break;
100 :
101 : default:
102 0 : err = gpg_error (GPG_ERR_PUBKEY_ALGO);
103 0 : break;
104 : }
105 :
106 29 : if (!err && !gcry_pk_get_keygrip (s_pkey, grip))
107 0 : err = gpg_error (GPG_ERR_INTERNAL);
108 :
109 29 : gcry_sexp_release (s_pkey);
110 29 : return err;
111 : }
112 :
113 :
114 : /* Convert a secret key given as algorithm id and an array of key
115 : parameters into our s-expression based format. Note that
116 : PUBKEY_ALGO has an gcrypt algorithm number. */
117 : static gpg_error_t
118 8 : convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
119 : const char *curve)
120 : {
121 : gpg_error_t err;
122 8 : gcry_sexp_t s_skey = NULL;
123 :
124 8 : *r_key = NULL;
125 :
126 8 : switch (pubkey_algo)
127 : {
128 : case GCRY_PK_DSA:
129 0 : err = gcry_sexp_build (&s_skey, NULL,
130 : "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
131 0 : skey[0], skey[1], skey[2], skey[3], skey[4]);
132 0 : break;
133 :
134 : case GCRY_PK_ELG:
135 : case GCRY_PK_ELG_E:
136 0 : err = gcry_sexp_build (&s_skey, NULL,
137 : "(private-key(elg(p%m)(g%m)(y%m)(x%m)))",
138 0 : skey[0], skey[1], skey[2], skey[3]);
139 0 : break;
140 :
141 :
142 : case GCRY_PK_RSA:
143 : case GCRY_PK_RSA_E:
144 : case GCRY_PK_RSA_S:
145 10 : err = gcry_sexp_build (&s_skey, NULL,
146 : "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
147 8 : skey[0], skey[1], skey[2], skey[3], skey[4],
148 2 : skey[5]);
149 2 : break;
150 :
151 : case GCRY_PK_ECC:
152 6 : if (!curve)
153 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
154 : else
155 : {
156 : const char *format;
157 :
158 6 : if (!strcmp (curve, "Ed25519"))
159 : /* Do not store the OID as name but the real name and the
160 : EdDSA flag. */
161 0 : format = "(private-key(ecc(curve %s)(flags eddsa)(q%m)(d%m)))";
162 6 : else if (!strcmp (curve, "Curve25519"))
163 0 : format = "(private-key(ecc(curve %s)(flags djb-tweak)(q%m)(d%m)))";
164 : else
165 6 : format = "(private-key(ecc(curve %s)(q%m)(d%m)))";
166 :
167 6 : err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], skey[1]);
168 : }
169 6 : break;
170 :
171 : default:
172 0 : err = gpg_error (GPG_ERR_PUBKEY_ALGO);
173 0 : break;
174 : }
175 :
176 8 : if (!err)
177 8 : *r_key = s_skey;
178 8 : return err;
179 : }
180 :
181 :
182 : /* Convert a secret key given as algorithm id, an array of key
183 : parameters, and an S-expression of the original OpenPGP transfer
184 : key into our s-expression based format. This is a variant of
185 : convert_secret_key which is used for the openpgp-native protection
186 : mode. Note that PUBKEY_ALGO has an gcrypt algorithm number. */
187 : static gpg_error_t
188 19 : convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey,
189 : const char *curve, gcry_sexp_t transfer_key)
190 : {
191 : gpg_error_t err;
192 19 : gcry_sexp_t s_skey = NULL;
193 :
194 19 : *r_key = NULL;
195 :
196 19 : switch (pubkey_algo)
197 : {
198 : case GCRY_PK_DSA:
199 6 : err = gcry_sexp_build
200 : (&s_skey, NULL,
201 : "(protected-private-key(dsa(p%m)(q%m)(g%m)(y%m)"
202 : "(protected openpgp-native%S)))",
203 6 : skey[0], skey[1], skey[2], skey[3], transfer_key);
204 2 : break;
205 :
206 : case GCRY_PK_ELG:
207 4 : err = gcry_sexp_build
208 : (&s_skey, NULL,
209 : "(protected-private-key(elg(p%m)(g%m)(y%m)"
210 : "(protected openpgp-native%S)))",
211 4 : skey[0], skey[1], skey[2], transfer_key);
212 2 : break;
213 :
214 :
215 : case GCRY_PK_RSA:
216 3 : err = gcry_sexp_build
217 : (&s_skey, NULL,
218 : "(protected-private-key(rsa(n%m)(e%m)"
219 : "(protected openpgp-native%S)))",
220 3 : skey[0], skey[1], transfer_key );
221 3 : break;
222 :
223 : case GCRY_PK_ECC:
224 12 : if (!curve)
225 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
226 : else
227 : {
228 : const char *format;
229 :
230 12 : if (!strcmp (curve, "Ed25519"))
231 : /* Do not store the OID as name but the real name and the
232 : EdDSA flag. */
233 0 : format = "(protected-private-key(ecc(curve %s)(flags eddsa)(q%m)"
234 : "(protected openpgp-native%S)))";
235 12 : else if (!strcmp (curve, "Curve25519"))
236 0 : format = "(protected-private-key(ecc(curve %s)(flags djb-tweak)(q%m)"
237 : "(protected openpgp-native%S)))";
238 : else
239 12 : format = "(protected-private-key(ecc(curve %s)(q%m)"
240 : "(protected openpgp-native%S)))";
241 :
242 12 : err = gcry_sexp_build (&s_skey, NULL, format, curve, skey[0], transfer_key);
243 : }
244 12 : break;
245 :
246 : default:
247 0 : err = gpg_error (GPG_ERR_PUBKEY_ALGO);
248 0 : break;
249 : }
250 :
251 19 : if (!err)
252 19 : *r_key = s_skey;
253 19 : return err;
254 : }
255 :
256 :
257 : /* Hash the passphrase and set the key. */
258 : static gpg_error_t
259 8 : hash_passphrase_and_set_key (const char *passphrase,
260 : gcry_cipher_hd_t hd, int protect_algo,
261 : int s2k_mode, int s2k_algo,
262 : byte *s2k_salt, u32 s2k_count)
263 : {
264 : gpg_error_t err;
265 : unsigned char *key;
266 : size_t keylen;
267 :
268 8 : keylen = gcry_cipher_get_algo_keylen (protect_algo);
269 8 : if (!keylen)
270 0 : return gpg_error (GPG_ERR_INTERNAL);
271 :
272 8 : key = xtrymalloc_secure (keylen);
273 8 : if (!key)
274 0 : return gpg_error_from_syserror ();
275 :
276 8 : err = s2k_hash_passphrase (passphrase,
277 : s2k_algo, s2k_mode, s2k_salt, s2k_count,
278 : key, keylen);
279 8 : if (!err)
280 8 : err = gcry_cipher_setkey (hd, key, keylen);
281 :
282 8 : xfree (key);
283 8 : return err;
284 : }
285 :
286 :
287 : static u16
288 8 : checksum (const unsigned char *p, unsigned int n)
289 : {
290 : u16 a;
291 :
292 664 : for (a=0; n; n-- )
293 656 : a += *p++;
294 8 : return a;
295 : }
296 :
297 :
298 : /* Return the number of expected key parameters. */
299 : static void
300 56 : get_npkey_nskey (int pubkey_algo, size_t *npkey, size_t *nskey)
301 : {
302 56 : switch (pubkey_algo)
303 : {
304 10 : case GCRY_PK_RSA: *npkey = 2; *nskey = 6; break;
305 5 : case GCRY_PK_ELG: *npkey = 3; *nskey = 4; break;
306 0 : case GCRY_PK_ELG_E: *npkey = 3; *nskey = 4; break;
307 5 : case GCRY_PK_DSA: *npkey = 4; *nskey = 5; break;
308 36 : case GCRY_PK_ECC: *npkey = 1; *nskey = 2; break;
309 0 : default: *npkey = 0; *nskey = 0; break;
310 : }
311 56 : }
312 :
313 :
314 : /* Helper for do_unprotect. PUBKEY_ALOGO is the gcrypt algo number.
315 : On success R_NPKEY and R_NSKEY receive the number or parameters for
316 : the algorithm PUBKEY_ALGO and R_SKEYLEN the used length of
317 : SKEY. */
318 : static int
319 27 : prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize,
320 : int s2k_mode,
321 : unsigned int *r_npkey, unsigned int *r_nskey,
322 : unsigned int *r_skeylen)
323 : {
324 : size_t npkey, nskey, skeylen;
325 : int i;
326 :
327 : /* Count the actual number of MPIs is in the array and set the
328 : remainder to NULL for easier processing later on. */
329 27 : for (skeylen = 0; skey[skeylen]; skeylen++)
330 : ;
331 216 : for (i=skeylen; i < skeysize; i++)
332 189 : skey[i] = NULL;
333 :
334 : /* Check some args. */
335 27 : if (s2k_mode == 1001)
336 : {
337 : /* Stub key. */
338 0 : log_info (_("secret key parts are not available\n"));
339 0 : return gpg_error (GPG_ERR_UNUSABLE_SECKEY);
340 : }
341 :
342 27 : if (gcry_pk_test_algo (pubkey_algo))
343 : {
344 0 : log_info (_("public key algorithm %d (%s) is not supported\n"),
345 : pubkey_algo, gcry_pk_algo_name (pubkey_algo));
346 0 : return gpg_error (GPG_ERR_PUBKEY_ALGO);
347 : }
348 :
349 : /* Get properties of the public key algorithm and do some
350 : consistency checks. Note that we need at least NPKEY+1 elements
351 : in the SKEY array. */
352 27 : get_npkey_nskey (pubkey_algo, &npkey, &nskey);
353 27 : if (!npkey || !nskey || npkey >= nskey)
354 0 : return gpg_error (GPG_ERR_INTERNAL);
355 27 : if (skeylen <= npkey)
356 0 : return gpg_error (GPG_ERR_MISSING_VALUE);
357 27 : if (nskey+1 >= skeysize)
358 0 : return gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
359 :
360 : /* Check that the public key parameters are all available and not
361 : encrypted. */
362 69 : for (i=0; i < npkey; i++)
363 : {
364 42 : if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
365 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
366 : }
367 :
368 27 : if (r_npkey)
369 8 : *r_npkey = npkey;
370 27 : if (r_nskey)
371 8 : *r_nskey = nskey;
372 27 : if (r_skeylen)
373 8 : *r_skeylen = skeylen;
374 27 : return 0;
375 : }
376 :
377 :
378 : /* Note that this function modifies SKEY. SKEYSIZE is the allocated
379 : size of the array including the NULL item; this is used for a
380 : bounds check. On success a converted key is stored at R_KEY. */
381 : static int
382 8 : do_unprotect (const char *passphrase,
383 : int pkt_version, int pubkey_algo, int is_protected,
384 : const char *curve, gcry_mpi_t *skey, size_t skeysize,
385 : int protect_algo, void *protect_iv, size_t protect_ivlen,
386 : int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count,
387 : u16 desired_csum, gcry_sexp_t *r_key)
388 : {
389 : gpg_error_t err;
390 : unsigned int npkey, nskey, skeylen;
391 8 : gcry_cipher_hd_t cipher_hd = NULL;
392 : u16 actual_csum;
393 : size_t nbytes;
394 : int i;
395 : gcry_mpi_t tmpmpi;
396 :
397 8 : *r_key = NULL;
398 :
399 8 : err = prepare_unprotect (pubkey_algo, skey, skeysize, s2k_mode,
400 : &npkey, &nskey, &skeylen);
401 8 : if (err)
402 0 : return err;
403 :
404 : /* Check whether SKEY is at all protected. If it is not protected
405 : merely verify the checksum. */
406 8 : if (!is_protected)
407 : {
408 2 : actual_csum = 0;
409 10 : for (i=npkey; i < nskey; i++)
410 : {
411 8 : if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1))
412 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
413 :
414 8 : if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
415 : {
416 : unsigned int nbits;
417 : const unsigned char *buffer;
418 0 : buffer = gcry_mpi_get_opaque (skey[i], &nbits);
419 0 : nbytes = (nbits+7)/8;
420 0 : actual_csum += checksum (buffer, nbytes);
421 : }
422 : else
423 : {
424 : unsigned char *buffer;
425 :
426 8 : err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, &buffer, &nbytes,
427 8 : skey[i]);
428 8 : if (!err)
429 8 : actual_csum += checksum (buffer, nbytes);
430 8 : xfree (buffer);
431 : }
432 8 : if (err)
433 0 : return err;
434 : }
435 :
436 2 : if (actual_csum != desired_csum)
437 0 : return gpg_error (GPG_ERR_CHECKSUM);
438 :
439 2 : goto do_convert;
440 : }
441 :
442 :
443 6 : if (gcry_cipher_test_algo (protect_algo))
444 : {
445 : /* The algorithm numbers are Libgcrypt numbers but fortunately
446 : the OpenPGP algorithm numbers map one-to-one to the Libgcrypt
447 : numbers. */
448 0 : log_info (_("protection algorithm %d (%s) is not supported\n"),
449 : protect_algo, gnupg_cipher_algo_name (protect_algo));
450 0 : return gpg_error (GPG_ERR_CIPHER_ALGO);
451 : }
452 :
453 6 : if (gcry_md_test_algo (s2k_algo))
454 : {
455 0 : log_info (_("protection hash algorithm %d (%s) is not supported\n"),
456 : s2k_algo, gcry_md_algo_name (s2k_algo));
457 0 : return gpg_error (GPG_ERR_DIGEST_ALGO);
458 : }
459 :
460 6 : err = gcry_cipher_open (&cipher_hd, protect_algo,
461 : GCRY_CIPHER_MODE_CFB,
462 : (GCRY_CIPHER_SECURE
463 : | (protect_algo >= 100 ?
464 : 0 : GCRY_CIPHER_ENABLE_SYNC)));
465 6 : if (err)
466 : {
467 0 : log_error ("failed to open cipher_algo %d: %s\n",
468 : protect_algo, gpg_strerror (err));
469 0 : return err;
470 : }
471 :
472 6 : err = hash_passphrase_and_set_key (passphrase, cipher_hd, protect_algo,
473 : s2k_mode, s2k_algo, s2k_salt, s2k_count);
474 6 : if (err)
475 : {
476 0 : gcry_cipher_close (cipher_hd);
477 0 : return err;
478 : }
479 :
480 6 : gcry_cipher_setiv (cipher_hd, protect_iv, protect_ivlen);
481 :
482 6 : actual_csum = 0;
483 6 : if (pkt_version >= 4)
484 : {
485 : int ndata;
486 : unsigned int ndatabits;
487 : const unsigned char *p;
488 : unsigned char *data;
489 6 : u16 csum_pgp7 = 0;
490 :
491 6 : if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE ))
492 : {
493 0 : gcry_cipher_close (cipher_hd);
494 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
495 : }
496 6 : p = gcry_mpi_get_opaque (skey[npkey], &ndatabits);
497 6 : ndata = (ndatabits+7)/8;
498 :
499 6 : if (ndata > 1)
500 6 : csum_pgp7 = buf16_to_u16 (p+ndata-2);
501 6 : data = xtrymalloc_secure (ndata);
502 6 : if (!data)
503 : {
504 0 : err = gpg_error_from_syserror ();
505 0 : gcry_cipher_close (cipher_hd);
506 0 : return err;
507 : }
508 6 : gcry_cipher_decrypt (cipher_hd, data, ndata, p, ndata);
509 :
510 6 : p = data;
511 6 : if (is_protected == 2)
512 : {
513 : /* This is the new SHA1 checksum method to detect tampering
514 : with the key as used by the Klima/Rosa attack. */
515 6 : desired_csum = 0;
516 6 : actual_csum = 1; /* Default to bad checksum. */
517 :
518 6 : if (ndata < 20)
519 0 : log_error ("not enough bytes for SHA-1 checksum\n");
520 : else
521 : {
522 : gcry_md_hd_t h;
523 :
524 6 : if (gcry_md_open (&h, GCRY_MD_SHA1, 1))
525 0 : BUG(); /* Algo not available. */
526 6 : gcry_md_write (h, data, ndata - 20);
527 6 : gcry_md_final (h);
528 6 : if (!memcmp (gcry_md_read (h, GCRY_MD_SHA1), data+ndata-20, 20))
529 6 : actual_csum = 0; /* Digest does match. */
530 6 : gcry_md_close (h);
531 : }
532 : }
533 : else
534 : {
535 : /* Old 16 bit checksum method. */
536 0 : if (ndata < 2)
537 : {
538 0 : log_error ("not enough bytes for checksum\n");
539 0 : desired_csum = 0;
540 0 : actual_csum = 1; /* Mark checksum bad. */
541 : }
542 : else
543 : {
544 0 : desired_csum = buf16_to_u16 (data+ndata-2);
545 0 : actual_csum = checksum (data, ndata-2);
546 0 : if (desired_csum != actual_csum)
547 : {
548 : /* This is a PGP 7.0.0 workaround */
549 0 : desired_csum = csum_pgp7; /* Take the encrypted one. */
550 : }
551 : }
552 : }
553 :
554 : /* Better check it here. Otherwise the gcry_mpi_scan would fail
555 : because the length may have an arbitrary value. */
556 6 : if (desired_csum == actual_csum)
557 : {
558 12 : for (i=npkey; i < nskey; i++ )
559 : {
560 6 : if (gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_PGP, p, ndata, &nbytes))
561 : {
562 : /* Checksum was okay, but not correctly decrypted. */
563 0 : desired_csum = 0;
564 0 : actual_csum = 1; /* Mark checksum bad. */
565 0 : break;
566 : }
567 6 : gcry_mpi_release (skey[i]);
568 6 : skey[i] = tmpmpi;
569 6 : ndata -= nbytes;
570 6 : p += nbytes;
571 : }
572 6 : skey[i] = NULL;
573 6 : skeylen = i;
574 6 : assert (skeylen <= skeysize);
575 :
576 : /* Note: at this point NDATA should be 2 for a simple
577 : checksum or 20 for the sha1 digest. */
578 : }
579 6 : xfree(data);
580 : }
581 : else /* Packet version <= 3. */
582 : {
583 : unsigned char *buffer;
584 :
585 0 : for (i = npkey; i < nskey; i++)
586 : {
587 : const unsigned char *p;
588 : size_t ndata;
589 : unsigned int ndatabits;
590 :
591 0 : if (!skey[i] || !gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE))
592 : {
593 0 : gcry_cipher_close (cipher_hd);
594 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
595 : }
596 0 : p = gcry_mpi_get_opaque (skey[i], &ndatabits);
597 0 : ndata = (ndatabits+7)/8;
598 :
599 0 : if (!(ndata >= 2) || !(ndata == (buf16_to_ushort (p) + 7)/8 + 2))
600 : {
601 0 : gcry_cipher_close (cipher_hd);
602 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
603 : }
604 :
605 0 : buffer = xtrymalloc_secure (ndata);
606 0 : if (!buffer)
607 : {
608 0 : err = gpg_error_from_syserror ();
609 0 : gcry_cipher_close (cipher_hd);
610 0 : return err;
611 : }
612 :
613 0 : gcry_cipher_sync (cipher_hd);
614 0 : buffer[0] = p[0];
615 0 : buffer[1] = p[1];
616 0 : gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2, p+2, ndata-2);
617 0 : actual_csum += checksum (buffer, ndata);
618 0 : err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_PGP, buffer, ndata, &ndata);
619 0 : xfree (buffer);
620 0 : if (err)
621 : {
622 : /* Checksum was okay, but not correctly decrypted. */
623 0 : desired_csum = 0;
624 0 : actual_csum = 1; /* Mark checksum bad. */
625 0 : break;
626 : }
627 0 : gcry_mpi_release (skey[i]);
628 0 : skey[i] = tmpmpi;
629 : }
630 : }
631 6 : gcry_cipher_close (cipher_hd);
632 :
633 : /* Now let's see whether we have used the correct passphrase. */
634 6 : if (actual_csum != desired_csum)
635 0 : return gpg_error (GPG_ERR_BAD_PASSPHRASE);
636 :
637 : do_convert:
638 8 : if (nskey != skeylen)
639 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
640 : else
641 8 : err = convert_secret_key (r_key, pubkey_algo, skey, curve);
642 8 : if (err)
643 0 : return err;
644 :
645 : /* The checksum may fail, thus we also check the key itself. */
646 8 : err = gcry_pk_testkey (*r_key);
647 8 : if (err)
648 : {
649 0 : gcry_sexp_release (*r_key);
650 0 : *r_key = NULL;
651 0 : return gpg_error (GPG_ERR_BAD_PASSPHRASE);
652 : }
653 :
654 8 : return 0;
655 : }
656 :
657 :
658 : /* Callback function to try the unprotection from the passphrase query
659 : code. */
660 : static gpg_error_t
661 8 : try_do_unprotect_cb (struct pin_entry_info_s *pi)
662 : {
663 : gpg_error_t err;
664 8 : struct try_do_unprotect_arg_s *arg = pi->check_cb_arg;
665 :
666 40 : err = do_unprotect (pi->pin,
667 8 : arg->is_v4? 4:3,
668 : arg->pubkey_algo, arg->is_protected,
669 : arg->curve,
670 : arg->skey, arg->skeysize,
671 16 : arg->protect_algo, arg->iv, arg->ivlen,
672 : arg->s2k_mode, arg->s2k_algo,
673 : arg->s2k_salt, arg->s2k_count,
674 8 : arg->desired_csum, arg->r_key);
675 : /* SKEY may be modified now, thus we need to re-compute SKEYIDX. */
676 40 : for (arg->skeyidx = 0; (arg->skeyidx < arg->skeysize
677 56 : && arg->skey[arg->skeyidx]); arg->skeyidx++)
678 : ;
679 8 : return err;
680 : }
681 :
682 :
683 : /* See convert_from_openpgp for the core of the description. This
684 : function adds an optional PASSPHRASE argument and uses this to
685 : silently decrypt the key; CACHE_NONCE and R_PASSPHRASE must both be
686 : NULL in this mode. */
687 : static gpg_error_t
688 29 : convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
689 : unsigned char *grip, const char *prompt,
690 : const char *cache_nonce, const char *passphrase,
691 : unsigned char **r_key, char **r_passphrase)
692 : {
693 : gpg_error_t err;
694 : int unattended;
695 : int from_native;
696 : gcry_sexp_t top_list;
697 29 : gcry_sexp_t list = NULL;
698 : const char *value;
699 : size_t valuelen;
700 : char *string;
701 : int idx;
702 : int is_v4, is_protected;
703 : int pubkey_algo;
704 29 : int protect_algo = 0;
705 : char iv[16];
706 29 : int ivlen = 0;
707 29 : int s2k_mode = 0;
708 29 : int s2k_algo = 0;
709 : byte s2k_salt[8];
710 29 : u32 s2k_count = 0;
711 : size_t npkey, nskey;
712 : gcry_mpi_t skey[10]; /* We support up to 9 parameters. */
713 29 : char *curve = NULL;
714 : u16 desired_csum;
715 29 : int skeyidx = 0;
716 29 : gcry_sexp_t s_skey = NULL;
717 :
718 29 : *r_key = NULL;
719 29 : if (r_passphrase)
720 0 : *r_passphrase = NULL;
721 29 : unattended = !r_passphrase;
722 29 : from_native = (!cache_nonce && passphrase && !r_passphrase);
723 :
724 29 : top_list = gcry_sexp_find_token (s_pgp, "openpgp-private-key", 0);
725 29 : if (!top_list)
726 0 : goto bad_seckey;
727 :
728 29 : list = gcry_sexp_find_token (top_list, "version", 0);
729 29 : if (!list)
730 0 : goto bad_seckey;
731 29 : value = gcry_sexp_nth_data (list, 1, &valuelen);
732 29 : if (!value || valuelen != 1 || !(value[0] == '3' || value[0] == '4'))
733 : goto bad_seckey;
734 29 : is_v4 = (value[0] == '4');
735 :
736 29 : gcry_sexp_release (list);
737 29 : list = gcry_sexp_find_token (top_list, "protection", 0);
738 29 : if (!list)
739 0 : goto bad_seckey;
740 29 : value = gcry_sexp_nth_data (list, 1, &valuelen);
741 29 : if (!value)
742 0 : goto bad_seckey;
743 29 : if (valuelen == 4 && !memcmp (value, "sha1", 4))
744 25 : is_protected = 2;
745 4 : else if (valuelen == 3 && !memcmp (value, "sum", 3))
746 0 : is_protected = 1;
747 4 : else if (valuelen == 4 && !memcmp (value, "none", 4))
748 4 : is_protected = 0;
749 : else
750 : goto bad_seckey;
751 :
752 29 : if (is_protected)
753 : {
754 25 : string = gcry_sexp_nth_string (list, 2);
755 25 : if (!string)
756 0 : goto bad_seckey;
757 25 : protect_algo = gcry_cipher_map_name (string);
758 25 : xfree (string);
759 :
760 25 : value = gcry_sexp_nth_data (list, 3, &valuelen);
761 25 : if (!value || !valuelen || valuelen > sizeof iv)
762 : goto bad_seckey;
763 25 : memcpy (iv, value, valuelen);
764 25 : ivlen = valuelen;
765 :
766 25 : string = gcry_sexp_nth_string (list, 4);
767 25 : if (!string)
768 0 : goto bad_seckey;
769 25 : s2k_mode = strtol (string, NULL, 10);
770 25 : xfree (string);
771 :
772 25 : string = gcry_sexp_nth_string (list, 5);
773 25 : if (!string)
774 0 : goto bad_seckey;
775 25 : s2k_algo = gcry_md_map_name (string);
776 25 : xfree (string);
777 :
778 25 : value = gcry_sexp_nth_data (list, 6, &valuelen);
779 25 : if (!value || !valuelen || valuelen > sizeof s2k_salt)
780 : goto bad_seckey;
781 25 : memcpy (s2k_salt, value, valuelen);
782 :
783 25 : string = gcry_sexp_nth_string (list, 7);
784 25 : if (!string)
785 0 : goto bad_seckey;
786 25 : s2k_count = strtoul (string, NULL, 10);
787 25 : xfree (string);
788 : }
789 :
790 29 : gcry_sexp_release (list);
791 29 : list = gcry_sexp_find_token (top_list, "algo", 0);
792 29 : if (!list)
793 0 : goto bad_seckey;
794 29 : string = gcry_sexp_nth_string (list, 1);
795 29 : if (!string)
796 0 : goto bad_seckey;
797 29 : pubkey_algo = gcry_pk_map_name (string);
798 29 : xfree (string);
799 :
800 29 : get_npkey_nskey (pubkey_algo, &npkey, &nskey);
801 29 : if (!npkey || !nskey || npkey >= nskey)
802 : goto bad_seckey;
803 :
804 29 : if (npkey == 1) /* This is ECC */
805 : {
806 18 : gcry_sexp_release (list);
807 18 : list = gcry_sexp_find_token (top_list, "curve", 0);
808 18 : if (!list)
809 0 : goto bad_seckey;
810 18 : curve = gcry_sexp_nth_string (list, 1);
811 18 : if (!curve)
812 0 : goto bad_seckey;
813 : }
814 :
815 29 : gcry_sexp_release (list);
816 29 : list = gcry_sexp_find_token (top_list, "skey", 0);
817 29 : if (!list)
818 0 : goto bad_seckey;
819 29 : for (idx=0;;)
820 : {
821 : int is_enc;
822 :
823 119 : value = gcry_sexp_nth_data (list, ++idx, &valuelen);
824 119 : if (!value && skeyidx >= npkey)
825 29 : break; /* Ready. */
826 :
827 : /* Check for too many parameters. Note that depending on the
828 : protection mode and version number we may see less than NSKEY
829 : (but at least NPKEY+1) parameters. */
830 90 : if (idx >= 2*nskey)
831 0 : goto bad_seckey;
832 90 : if (skeyidx >= DIM (skey)-1)
833 0 : goto bad_seckey;
834 :
835 90 : if (!value || valuelen != 1 || !(value[0] == '_' || value[0] == 'e'))
836 : goto bad_seckey;
837 90 : is_enc = (value[0] == 'e');
838 90 : value = gcry_sexp_nth_data (list, ++idx, &valuelen);
839 90 : if (!value || !valuelen)
840 : goto bad_seckey;
841 90 : if (is_enc)
842 : {
843 : /* Encrypted parameters need to be stored as opaque. */
844 25 : skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8);
845 25 : if (!skey[skeyidx])
846 0 : goto outofmem;
847 25 : gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1);
848 : }
849 : else
850 : {
851 65 : if (gcry_mpi_scan (skey + skeyidx, GCRYMPI_FMT_STD,
852 : value, valuelen, NULL))
853 0 : goto bad_seckey;
854 : }
855 90 : skeyidx++;
856 90 : }
857 29 : skey[skeyidx++] = NULL;
858 :
859 29 : gcry_sexp_release (list);
860 29 : list = gcry_sexp_find_token (top_list, "csum", 0);
861 29 : if (list)
862 : {
863 29 : string = gcry_sexp_nth_string (list, 1);
864 29 : if (!string)
865 0 : goto bad_seckey;
866 29 : desired_csum = strtoul (string, NULL, 10);
867 29 : xfree (string);
868 : }
869 : else
870 0 : desired_csum = 0;
871 :
872 :
873 29 : gcry_sexp_release (list); list = NULL;
874 29 : gcry_sexp_release (top_list); top_list = NULL;
875 :
876 : #if 0
877 : log_debug ("XXX is_v4=%d\n", is_v4);
878 : log_debug ("XXX pubkey_algo=%d\n", pubkey_algo);
879 : log_debug ("XXX is_protected=%d\n", is_protected);
880 : log_debug ("XXX protect_algo=%d\n", protect_algo);
881 : log_printhex ("XXX iv", iv, ivlen);
882 : log_debug ("XXX ivlen=%d\n", ivlen);
883 : log_debug ("XXX s2k_mode=%d\n", s2k_mode);
884 : log_debug ("XXX s2k_algo=%d\n", s2k_algo);
885 : log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt);
886 : log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count);
887 : log_debug ("XXX curve='%s'\n", curve);
888 : for (idx=0; skey[idx]; idx++)
889 : gcry_log_debugmpi (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_USER1)
890 : ? "skey(e)" : "skey(_)", skey[idx]);
891 : #endif /*0*/
892 :
893 29 : err = get_keygrip (pubkey_algo, curve, skey, grip);
894 29 : if (err)
895 0 : goto leave;
896 :
897 29 : if (!dontcare_exist && !from_native && !agent_key_available (grip))
898 : {
899 2 : err = gpg_error (GPG_ERR_EEXIST);
900 2 : goto leave;
901 : }
902 :
903 27 : if (unattended && !from_native)
904 : {
905 19 : err = prepare_unprotect (pubkey_algo, skey, DIM(skey), s2k_mode,
906 : NULL, NULL, NULL);
907 19 : if (err)
908 0 : goto leave;
909 :
910 19 : err = convert_transfer_key (&s_skey, pubkey_algo, skey, curve, s_pgp);
911 38 : if (err)
912 0 : goto leave;
913 : }
914 : else
915 : {
916 : struct pin_entry_info_s *pi;
917 : struct try_do_unprotect_arg_s pi_arg;
918 :
919 8 : pi = xtrycalloc_secure (1, sizeof (*pi) + MAX_PASSPHRASE_LEN + 1);
920 8 : if (!pi)
921 0 : return gpg_error_from_syserror ();
922 8 : pi->max_length = MAX_PASSPHRASE_LEN + 1;
923 8 : pi->min_digits = 0; /* We want a real passphrase. */
924 8 : pi->max_digits = 16;
925 8 : pi->max_tries = 3;
926 8 : pi->check_cb = try_do_unprotect_cb;
927 8 : pi->check_cb_arg = &pi_arg;
928 8 : pi_arg.is_v4 = is_v4;
929 8 : pi_arg.is_protected = is_protected;
930 8 : pi_arg.pubkey_algo = pubkey_algo;
931 8 : pi_arg.curve = curve;
932 8 : pi_arg.protect_algo = protect_algo;
933 8 : pi_arg.iv = iv;
934 8 : pi_arg.ivlen = ivlen;
935 8 : pi_arg.s2k_mode = s2k_mode;
936 8 : pi_arg.s2k_algo = s2k_algo;
937 8 : pi_arg.s2k_salt = s2k_salt;
938 8 : pi_arg.s2k_count = s2k_count;
939 8 : pi_arg.desired_csum = desired_csum;
940 8 : pi_arg.skey = skey;
941 8 : pi_arg.skeysize = DIM (skey);
942 8 : pi_arg.skeyidx = skeyidx;
943 8 : pi_arg.r_key = &s_skey;
944 :
945 8 : err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
946 8 : if (!is_protected)
947 : {
948 2 : err = try_do_unprotect_cb (pi);
949 : }
950 6 : else if (cache_nonce)
951 : {
952 : char *cache_value;
953 :
954 0 : cache_value = agent_get_cache (cache_nonce, CACHE_MODE_NONCE);
955 0 : if (cache_value)
956 : {
957 0 : if (strlen (cache_value) < pi->max_length)
958 0 : strcpy (pi->pin, cache_value);
959 0 : xfree (cache_value);
960 : }
961 0 : if (*pi->pin)
962 0 : err = try_do_unprotect_cb (pi);
963 : }
964 6 : else if (from_native)
965 : {
966 6 : if (strlen (passphrase) < pi->max_length)
967 6 : strcpy (pi->pin, passphrase);
968 6 : err = try_do_unprotect_cb (pi);
969 : }
970 8 : if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE && !from_native)
971 0 : err = agent_askpin (ctrl, prompt, NULL, NULL, pi, NULL, 0);
972 8 : skeyidx = pi_arg.skeyidx;
973 8 : if (!err && r_passphrase && is_protected)
974 : {
975 0 : *r_passphrase = xtrystrdup (pi->pin);
976 0 : if (!*r_passphrase)
977 0 : err = gpg_error_from_syserror ();
978 : }
979 8 : xfree (pi);
980 8 : if (err)
981 0 : goto leave;
982 : }
983 :
984 : /* Save some memory and get rid of the SKEY array now. */
985 127 : for (idx=0; idx < skeyidx; idx++)
986 100 : gcry_mpi_release (skey[idx]);
987 27 : skeyidx = 0;
988 :
989 : /* Note that the padding is not required - we use it only because
990 : that function allows us to create the result in secure memory. */
991 27 : err = make_canon_sexp_pad (s_skey, 1, r_key, NULL);
992 :
993 : leave:
994 29 : xfree (curve);
995 29 : gcry_sexp_release (s_skey);
996 29 : gcry_sexp_release (list);
997 29 : gcry_sexp_release (top_list);
998 40 : for (idx=0; idx < skeyidx; idx++)
999 11 : gcry_mpi_release (skey[idx]);
1000 29 : if (err && r_passphrase)
1001 : {
1002 0 : xfree (*r_passphrase);
1003 0 : *r_passphrase = NULL;
1004 : }
1005 29 : return err;
1006 :
1007 : bad_seckey:
1008 0 : err = gpg_error (GPG_ERR_BAD_SECKEY);
1009 0 : goto leave;
1010 :
1011 : outofmem:
1012 0 : err = gpg_error (GPG_ERR_ENOMEM);
1013 0 : goto leave;
1014 :
1015 : }
1016 :
1017 :
1018 : /* Convert an OpenPGP transfer key into our internal format. Before
1019 : asking for a passphrase we check whether the key already exists in
1020 : our key storage. S_PGP is the OpenPGP key in transfer format. If
1021 : CACHE_NONCE is given the passphrase will be looked up in the cache.
1022 : On success R_KEY will receive a canonical encoded S-expression with
1023 : the unprotected key in our internal format; the caller needs to
1024 : release that memory. The passphrase used to decrypt the OpenPGP
1025 : key will be returned at R_PASSPHRASE; the caller must release this
1026 : passphrase. If R_PASSPHRASE is NULL the unattended conversion mode
1027 : will be used which uses the openpgp-native protection format for
1028 : the key. The keygrip will be stored at the 20 byte buffer pointed
1029 : to by GRIP. On error NULL is stored at all return arguments. */
1030 : gpg_error_t
1031 21 : convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, int dontcare_exist,
1032 : unsigned char *grip, const char *prompt,
1033 : const char *cache_nonce,
1034 : unsigned char **r_key, char **r_passphrase)
1035 : {
1036 21 : return convert_from_openpgp_main (ctrl, s_pgp, dontcare_exist, grip, prompt,
1037 : cache_nonce, NULL,
1038 : r_key, r_passphrase);
1039 : }
1040 :
1041 : /* This function is called by agent_unprotect to re-protect an
1042 : openpgp-native protected private-key into the standard private-key
1043 : protection format. */
1044 : gpg_error_t
1045 8 : convert_from_openpgp_native (ctrl_t ctrl,
1046 : gcry_sexp_t s_pgp, const char *passphrase,
1047 : unsigned char **r_key)
1048 : {
1049 : gpg_error_t err;
1050 : unsigned char grip[20];
1051 :
1052 8 : if (!passphrase)
1053 0 : return gpg_error (GPG_ERR_INTERNAL);
1054 :
1055 8 : err = convert_from_openpgp_main (ctrl, s_pgp, 0, grip, NULL,
1056 : NULL, passphrase,
1057 : r_key, NULL);
1058 :
1059 : /* On success try to re-write the key. */
1060 8 : if (!err)
1061 : {
1062 8 : if (*passphrase)
1063 : {
1064 6 : unsigned char *protectedkey = NULL;
1065 : size_t protectedkeylen;
1066 :
1067 6 : if (!agent_protect (*r_key, passphrase,
1068 : &protectedkey, &protectedkeylen,
1069 : ctrl->s2k_count, -1))
1070 6 : agent_write_private_key (grip, protectedkey, protectedkeylen, 1);
1071 6 : xfree (protectedkey);
1072 : }
1073 : else
1074 : {
1075 : /* Empty passphrase: write key without protection. */
1076 2 : agent_write_private_key (grip,
1077 : *r_key,
1078 : gcry_sexp_canon_len (*r_key, 0, NULL,NULL),
1079 : 1);
1080 : }
1081 : }
1082 :
1083 8 : return err;
1084 : }
1085 :
1086 :
1087 : /* Given an ARRAY of mpis with the key parameters, protect the secret
1088 : parameters in that array and replace them by one opaque encoded
1089 : mpi. NPKEY is the number of public key parameters and NSKEY is
1090 : the number of secret key parameters (including the public ones).
1091 : On success the array will have NPKEY+1 elements. */
1092 : static gpg_error_t
1093 2 : apply_protection (gcry_mpi_t *array, int npkey, int nskey,
1094 : const char *passphrase,
1095 : int protect_algo, void *protect_iv, size_t protect_ivlen,
1096 : int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count)
1097 : {
1098 : gpg_error_t err;
1099 : int i, j;
1100 : gcry_cipher_hd_t cipherhd;
1101 : unsigned char *bufarr[10];
1102 : size_t narr[10];
1103 : unsigned int nbits[10];
1104 : int ndata;
1105 : unsigned char *p, *data;
1106 :
1107 2 : assert (npkey < nskey);
1108 2 : assert (nskey < DIM (bufarr));
1109 :
1110 : /* Collect only the secret key parameters into BUFARR et al and
1111 : compute the required size of the data buffer. */
1112 2 : ndata = 20; /* Space for the SHA-1 checksum. */
1113 4 : for (i = npkey, j = 0; i < nskey; i++, j++ )
1114 : {
1115 2 : err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufarr+j, narr+j, array[i]);
1116 2 : if (err)
1117 : {
1118 0 : for (i = 0; i < j; i++)
1119 0 : xfree (bufarr[i]);
1120 0 : return err;
1121 : }
1122 2 : nbits[j] = gcry_mpi_get_nbits (array[i]);
1123 2 : ndata += 2 + narr[j];
1124 : }
1125 :
1126 : /* Allocate data buffer and stuff it with the secret key parameters. */
1127 2 : data = xtrymalloc_secure (ndata);
1128 2 : if (!data)
1129 : {
1130 0 : err = gpg_error_from_syserror ();
1131 0 : for (i = 0; i < (nskey-npkey); i++ )
1132 0 : xfree (bufarr[i]);
1133 0 : return err;
1134 : }
1135 2 : p = data;
1136 4 : for (i = 0; i < (nskey-npkey); i++ )
1137 : {
1138 2 : *p++ = nbits[i] >> 8 ;
1139 2 : *p++ = nbits[i];
1140 2 : memcpy (p, bufarr[i], narr[i]);
1141 2 : p += narr[i];
1142 2 : xfree (bufarr[i]);
1143 2 : bufarr[i] = NULL;
1144 : }
1145 2 : assert (p == data + ndata - 20);
1146 :
1147 : /* Append a hash of the secret key parameters. */
1148 2 : gcry_md_hash_buffer (GCRY_MD_SHA1, p, data, ndata - 20);
1149 :
1150 : /* Encrypt it. */
1151 2 : err = gcry_cipher_open (&cipherhd, protect_algo,
1152 : GCRY_CIPHER_MODE_CFB, GCRY_CIPHER_SECURE);
1153 2 : if (!err)
1154 2 : err = hash_passphrase_and_set_key (passphrase, cipherhd, protect_algo,
1155 : s2k_mode, s2k_algo, s2k_salt, s2k_count);
1156 2 : if (!err)
1157 2 : err = gcry_cipher_setiv (cipherhd, protect_iv, protect_ivlen);
1158 2 : if (!err)
1159 2 : err = gcry_cipher_encrypt (cipherhd, data, ndata, NULL, 0);
1160 2 : gcry_cipher_close (cipherhd);
1161 2 : if (err)
1162 : {
1163 0 : xfree (data);
1164 0 : return err;
1165 : }
1166 :
1167 : /* Replace the secret key parameters in the array by one opaque value. */
1168 4 : for (i = npkey; i < nskey; i++ )
1169 : {
1170 2 : gcry_mpi_release (array[i]);
1171 2 : array[i] = NULL;
1172 : }
1173 2 : array[npkey] = gcry_mpi_set_opaque (NULL, data, ndata*8);
1174 2 : return 0;
1175 : }
1176 :
1177 :
1178 : /*
1179 : * Examining S_KEY in S-Expression and extract data.
1180 : * When REQ_PRIVATE_KEY_DATA == 1, S_KEY's CAR should be 'private-key',
1181 : * but it also allows shadowed or protected versions.
1182 : * On success, it returns 0, otherwise error number.
1183 : * R_ALGONAME is static string which is no need to free by caller.
1184 : * R_NPKEY is pointer to number of public key data.
1185 : * R_NSKEY is pointer to number of private key data.
1186 : * R_ELEMS is static string which is no need to free by caller.
1187 : * ARRAY contains public and private key data.
1188 : * ARRAYSIZE is the allocated size of the array for cross-checking.
1189 : * R_CURVE is pointer to S-Expression of the curve (can be NULL).
1190 : * R_FLAGS is pointer to S-Expression of the flags (can be NULL).
1191 : */
1192 : gpg_error_t
1193 13 : extract_private_key (gcry_sexp_t s_key, int req_private_key_data,
1194 : const char **r_algoname, int *r_npkey, int *r_nskey,
1195 : const char **r_elems,
1196 : gcry_mpi_t *array, int arraysize,
1197 : gcry_sexp_t *r_curve, gcry_sexp_t *r_flags)
1198 : {
1199 : gpg_error_t err;
1200 : gcry_sexp_t list, l2;
1201 : char *name;
1202 : const char *algoname, *format;
1203 : int npkey, nskey;
1204 13 : gcry_sexp_t curve = NULL;
1205 13 : gcry_sexp_t flags = NULL;
1206 :
1207 13 : *r_curve = NULL;
1208 13 : *r_flags = NULL;
1209 :
1210 13 : if (!req_private_key_data)
1211 : {
1212 11 : list = gcry_sexp_find_token (s_key, "shadowed-private-key", 0 );
1213 11 : if (!list)
1214 11 : list = gcry_sexp_find_token (s_key, "protected-private-key", 0 );
1215 11 : if (!list)
1216 0 : list = gcry_sexp_find_token (s_key, "private-key", 0 );
1217 : }
1218 : else
1219 2 : list = gcry_sexp_find_token (s_key, "private-key", 0);
1220 :
1221 13 : if (!list)
1222 : {
1223 0 : log_error ("invalid private key format\n");
1224 0 : return gpg_error (GPG_ERR_BAD_SECKEY);
1225 : }
1226 :
1227 13 : l2 = gcry_sexp_cadr (list);
1228 13 : gcry_sexp_release (list);
1229 13 : list = l2;
1230 13 : name = gcry_sexp_nth_string (list, 0);
1231 13 : if (!name)
1232 : {
1233 0 : gcry_sexp_release (list);
1234 0 : return gpg_error (GPG_ERR_INV_OBJ); /* Invalid structure of object. */
1235 : }
1236 :
1237 13 : if (arraysize < 7)
1238 0 : BUG ();
1239 :
1240 : /* Map NAME to a name as used by Libgcrypt. We do not use the
1241 : Libgcrypt function here because we need a lowercase name and
1242 : require special treatment for some algorithms. */
1243 13 : strlwr (name);
1244 13 : if (!strcmp (name, "rsa"))
1245 : {
1246 4 : algoname = "rsa";
1247 4 : format = "ned?p?q?u?";
1248 4 : npkey = 2;
1249 4 : nskey = 6;
1250 4 : err = gcry_sexp_extract_param (list, NULL, format,
1251 : array+0, array+1, array+2, array+3,
1252 : array+4, array+5, NULL);
1253 : }
1254 9 : else if (!strcmp (name, "elg"))
1255 : {
1256 1 : algoname = "elg";
1257 1 : format = "pgyx?";
1258 1 : npkey = 3;
1259 1 : nskey = 4;
1260 1 : err = gcry_sexp_extract_param (list, NULL, format,
1261 : array+0, array+1, array+2, array+3,
1262 : NULL);
1263 : }
1264 8 : else if (!strcmp (name, "dsa"))
1265 : {
1266 5 : algoname = "dsa";
1267 5 : format = "pqgyx?";
1268 5 : npkey = 4;
1269 5 : nskey = 5;
1270 5 : err = gcry_sexp_extract_param (list, NULL, format,
1271 : array+0, array+1, array+2, array+3,
1272 : array+4, NULL);
1273 : }
1274 3 : else if (!strcmp (name, "ecc") || !strcmp (name, "ecdsa"))
1275 : {
1276 3 : algoname = "ecc";
1277 3 : format = "qd?";
1278 3 : npkey = 1;
1279 3 : nskey = 2;
1280 3 : curve = gcry_sexp_find_token (list, "curve", 0);
1281 3 : flags = gcry_sexp_find_token (list, "flags", 0);
1282 3 : err = gcry_sexp_extract_param (list, NULL, format,
1283 : array+0, array+1, NULL);
1284 : }
1285 : else
1286 : {
1287 0 : err = gpg_error (GPG_ERR_PUBKEY_ALGO);
1288 : }
1289 13 : xfree (name);
1290 13 : gcry_sexp_release (list);
1291 13 : if (err)
1292 : {
1293 0 : gcry_sexp_release (curve);
1294 0 : gcry_sexp_release (flags);
1295 0 : return err;
1296 : }
1297 : else
1298 : {
1299 13 : *r_algoname = algoname;
1300 13 : if (r_elems)
1301 11 : *r_elems = format;
1302 13 : *r_npkey = npkey;
1303 13 : if (r_nskey)
1304 2 : *r_nskey = nskey;
1305 13 : *r_curve = curve;
1306 13 : *r_flags = flags;
1307 :
1308 13 : return 0;
1309 : }
1310 : }
1311 :
1312 : /* Convert our key S_KEY into an OpenPGP key transfer format. On
1313 : success a canonical encoded S-expression is stored at R_TRANSFERKEY
1314 : and its length at R_TRANSFERKEYLEN; this S-expression is also
1315 : padded to a multiple of 64 bits. */
1316 : gpg_error_t
1317 2 : convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase,
1318 : unsigned char **r_transferkey, size_t *r_transferkeylen)
1319 : {
1320 : gpg_error_t err;
1321 : const char *algoname;
1322 : int npkey, nskey;
1323 : gcry_mpi_t array[10];
1324 2 : gcry_sexp_t curve = NULL;
1325 2 : gcry_sexp_t flags = NULL;
1326 : char protect_iv[16];
1327 : char salt[8];
1328 : unsigned long s2k_count;
1329 : int i, j;
1330 :
1331 : (void)ctrl;
1332 :
1333 2 : *r_transferkey = NULL;
1334 :
1335 22 : for (i=0; i < DIM (array); i++)
1336 20 : array[i] = NULL;
1337 :
1338 2 : err = extract_private_key (s_key, 1, &algoname, &npkey, &nskey, NULL,
1339 : array, DIM (array), &curve, &flags);
1340 2 : if (err)
1341 0 : return err;
1342 :
1343 2 : gcry_create_nonce (protect_iv, sizeof protect_iv);
1344 2 : gcry_create_nonce (salt, sizeof salt);
1345 : /* We need to use the encoded S2k count. It is not possible to
1346 : encode it after it has been used because the encoding procedure
1347 : may round the value up. */
1348 2 : s2k_count = get_standard_s2k_count_rfc4880 ();
1349 2 : err = apply_protection (array, npkey, nskey, passphrase,
1350 : GCRY_CIPHER_AES, protect_iv, sizeof protect_iv,
1351 : 3, GCRY_MD_SHA1, salt, s2k_count);
1352 : /* Turn it into the transfer key S-expression. Note that we always
1353 : return a protected key. */
1354 2 : if (!err)
1355 : {
1356 : char countbuf[35];
1357 : membuf_t mbuf;
1358 : void *format_args[10+2];
1359 : gcry_sexp_t tmpkey;
1360 2 : gcry_sexp_t tmpsexp = NULL;
1361 :
1362 2 : snprintf (countbuf, sizeof countbuf, "%lu", s2k_count);
1363 :
1364 2 : init_membuf (&mbuf, 50);
1365 2 : put_membuf_str (&mbuf, "(skey");
1366 9 : for (i=j=0; i < npkey; i++)
1367 : {
1368 7 : put_membuf_str (&mbuf, " _ %m");
1369 7 : format_args[j++] = array + i;
1370 : }
1371 2 : put_membuf_str (&mbuf, " e %m");
1372 2 : format_args[j++] = array + npkey;
1373 2 : put_membuf_str (&mbuf, ")\n");
1374 2 : put_membuf (&mbuf, "", 1);
1375 :
1376 2 : tmpkey = NULL;
1377 : {
1378 2 : char *format = get_membuf (&mbuf, NULL);
1379 2 : if (!format)
1380 0 : err = gpg_error_from_syserror ();
1381 : else
1382 2 : err = gcry_sexp_build_array (&tmpkey, NULL, format, format_args);
1383 2 : xfree (format);
1384 : }
1385 2 : if (!err)
1386 2 : err = gcry_sexp_build (&tmpsexp, NULL,
1387 : "(openpgp-private-key\n"
1388 : " (version 1:4)\n"
1389 : " (algo %s)\n"
1390 : " %S%S\n"
1391 : " (protection sha1 aes %b 1:3 sha1 %b %s))\n",
1392 : algoname,
1393 : curve,
1394 : tmpkey,
1395 : (int)sizeof protect_iv, protect_iv,
1396 : (int)sizeof salt, salt,
1397 : countbuf);
1398 2 : gcry_sexp_release (tmpkey);
1399 2 : if (!err)
1400 2 : err = make_canon_sexp_pad (tmpsexp, 0, r_transferkey, r_transferkeylen);
1401 2 : gcry_sexp_release (tmpsexp);
1402 : }
1403 :
1404 22 : for (i=0; i < DIM (array); i++)
1405 20 : gcry_mpi_release (array[i]);
1406 2 : gcry_sexp_release (curve);
1407 2 : gcry_sexp_release (flags);
1408 :
1409 2 : return err;
1410 : }
|