app-openpgp changes
[gnupg.git] / agent / protect.c
blob8b022ecfbaa66096d8faa152c9adc8087e20e957
1 /* protect.c - Un/Protect a secret key
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3 * 2003, 2007, 2009 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/>.
21 #include <config.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
31 #include "agent.h"
33 #include "sexp-parse.h"
35 #define PROT_CIPHER GCRY_CIPHER_AES
36 #define PROT_CIPHER_STRING "aes"
37 #define PROT_CIPHER_KEYLEN (128/8)
40 /* A table containing the information needed to create a protected
41 private key */
42 static struct {
43 const char *algo;
44 const char *parmlist;
45 int prot_from, prot_to;
46 } protect_info[] = {
47 { "rsa", "nedpqu", 2, 5 },
48 { "dsa", "pqgyx", 4, 4 },
49 { "elg", "pgyx", 3, 3 },
50 { NULL }
54 static int
55 hash_passphrase (const char *passphrase, int hashalgo,
56 int s2kmode,
57 const unsigned char *s2ksalt, unsigned long s2kcount,
58 unsigned char *key, size_t keylen);
62 /* Calculate the MIC for a private key S-Exp. SHA1HASH should point to
63 a 20 byte buffer. This function is suitable for any algorithms. */
64 static int
65 calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
67 const unsigned char *hash_begin, *hash_end;
68 const unsigned char *s;
69 size_t n;
71 s = plainkey;
72 if (*s != '(')
73 return gpg_error (GPG_ERR_INV_SEXP);
74 s++;
75 n = snext (&s);
76 if (!n)
77 return gpg_error (GPG_ERR_INV_SEXP);
78 if (!smatch (&s, n, "private-key"))
79 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
80 if (*s != '(')
81 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
82 hash_begin = s;
83 s++;
84 n = snext (&s);
85 if (!n)
86 return gpg_error (GPG_ERR_INV_SEXP);
87 s += n; /* skip over the algorithm name */
89 while (*s == '(')
91 s++;
92 n = snext (&s);
93 if (!n)
94 return gpg_error (GPG_ERR_INV_SEXP);
95 s += n;
96 n = snext (&s);
97 if (!n)
98 return gpg_error (GPG_ERR_INV_SEXP);
99 s += n;
100 if ( *s != ')' )
101 return gpg_error (GPG_ERR_INV_SEXP);
102 s++;
104 if (*s != ')')
105 return gpg_error (GPG_ERR_INV_SEXP);
106 s++;
107 hash_end = s;
109 gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash,
110 hash_begin, hash_end - hash_begin);
112 return 0;
117 /* Encrypt the parameter block starting at PROTBEGIN with length
118 PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
119 encrypted block in RESULT or return with an error code. SHA1HASH
120 is the 20 byte SHA-1 hash required for the integrity code.
122 The parameter block is expected to be an incomplete S-Expression of
123 the form (example in advanced format):
125 (d #046129F..[some bytes not shown]..81#)
126 (p #00e861b..[some bytes not shown]..f1#)
127 (q #00f7a7c..[some bytes not shown]..61#)
128 (u #304559a..[some bytes not shown]..9b#)
130 the returned block is the S-Expression:
132 (protected mode (parms) encrypted_octet_string)
135 static int
136 do_encryption (const unsigned char *protbegin, size_t protlen,
137 const char *passphrase, const unsigned char *sha1hash,
138 unsigned char **result, size_t *resultlen)
140 gcry_cipher_hd_t hd;
141 const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc";
142 int blklen, enclen, outlen;
143 unsigned char *iv = NULL;
144 int rc;
145 char *outbuf = NULL;
146 char *p;
147 int saltpos, ivpos, encpos;
149 *resultlen = 0;
150 *result = NULL;
152 rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
153 GCRY_CIPHER_SECURE);
154 if (rc)
155 return rc;
158 /* We need to work on a copy of the data because this makes it
159 easier to add the trailer and the padding and more important we
160 have to prefix the text with 2 parenthesis, so we have to
161 allocate enough space for:
163 ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
165 We always append a full block of random bytes as padding but
166 encrypt only what is needed for a full blocksize. */
167 blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
168 outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
169 enclen = outlen/blklen * blklen;
170 outbuf = gcry_malloc_secure (outlen);
171 if (!outbuf)
172 rc = out_of_core ();
173 if (!rc)
175 /* Allocate random bytes to be used as IV, padding and s2k salt. */
176 iv = xtrymalloc (blklen*2+8);
177 if (!iv)
178 rc = gpg_error (GPG_ERR_ENOMEM);
179 gcry_create_nonce (iv, blklen*2+8);
180 rc = gcry_cipher_setiv (hd, iv, blklen);
182 if (!rc)
184 unsigned char *key;
185 size_t keylen = PROT_CIPHER_KEYLEN;
187 key = gcry_malloc_secure (keylen);
188 if (!key)
189 rc = out_of_core ();
190 else
192 rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
193 3, iv+2*blklen, 96, key, keylen);
194 if (!rc)
195 rc = gcry_cipher_setkey (hd, key, keylen);
196 xfree (key);
199 if (!rc)
201 p = outbuf;
202 *p++ = '(';
203 *p++ = '(';
204 memcpy (p, protbegin, protlen);
205 p += protlen;
206 memcpy (p, ")(4:hash4:sha120:", 17);
207 p += 17;
208 memcpy (p, sha1hash, 20);
209 p += 20;
210 *p++ = ')';
211 *p++ = ')';
212 memcpy (p, iv+blklen, blklen);
213 p += blklen;
214 assert ( p - outbuf == outlen);
215 rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
217 gcry_cipher_close (hd);
218 if (rc)
220 xfree (iv);
221 xfree (outbuf);
222 return rc;
225 /* Now allocate the buffer we want to return. This is
227 (protected openpgp-s2k3-sha1-aes-cbc
228 ((sha1 salt no_of_iterations) 16byte_iv)
229 encrypted_octet_string)
231 in canoncical format of course. We use asprintf and %n modifier
232 and dummy values as placeholders. */
233 p = xtryasprintf
234 ("(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
235 (int)strlen (modestr), modestr,
236 &saltpos,
237 blklen, &ivpos, blklen, "",
238 enclen, &encpos, enclen, "");
239 if (!p)
241 gpg_error_t tmperr = out_of_core ();
242 xfree (iv);
243 xfree (outbuf);
244 return tmperr;
246 *resultlen = strlen (p);
247 *result = (unsigned char*)p;
248 memcpy (p+saltpos, iv+2*blklen, 8);
249 memcpy (p+ivpos, iv, blklen);
250 memcpy (p+encpos, outbuf, enclen);
251 xfree (iv);
252 xfree (outbuf);
253 return 0;
258 /* Protect the key encoded in canonical format in PLAINKEY. We assume
259 a valid S-Exp here. */
260 int
261 agent_protect (const unsigned char *plainkey, const char *passphrase,
262 unsigned char **result, size_t *resultlen)
264 int rc;
265 const unsigned char *s;
266 const unsigned char *hash_begin, *hash_end;
267 const unsigned char *prot_begin, *prot_end, *real_end;
268 size_t n;
269 int c, infidx, i;
270 unsigned char hashvalue[20];
271 char timestamp_exp[35];
272 unsigned char *protected;
273 size_t protectedlen;
274 int depth = 0;
275 unsigned char *p;
276 gcry_md_hd_t md;
278 /* Create an S-expression with the procted-at timestamp. */
279 memcpy (timestamp_exp, "(12:protected-at15:", 19);
280 gnupg_get_isotime (timestamp_exp+19);
281 timestamp_exp[19+15] = ')';
283 /* Parse original key. */
284 s = plainkey;
285 if (*s != '(')
286 return gpg_error (GPG_ERR_INV_SEXP);
287 depth++;
288 s++;
289 n = snext (&s);
290 if (!n)
291 return gpg_error (GPG_ERR_INV_SEXP);
292 if (!smatch (&s, n, "private-key"))
293 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
294 if (*s != '(')
295 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
296 depth++;
297 hash_begin = s;
298 s++;
299 n = snext (&s);
300 if (!n)
301 return gpg_error (GPG_ERR_INV_SEXP);
303 for (infidx=0; protect_info[infidx].algo
304 && !smatch (&s, n, protect_info[infidx].algo); infidx++)
306 if (!protect_info[infidx].algo)
307 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
309 prot_begin = prot_end = NULL;
310 for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
312 if (i == protect_info[infidx].prot_from)
313 prot_begin = s;
314 if (*s != '(')
315 return gpg_error (GPG_ERR_INV_SEXP);
316 depth++;
317 s++;
318 n = snext (&s);
319 if (!n)
320 return gpg_error (GPG_ERR_INV_SEXP);
321 if (n != 1 || c != *s)
322 return gpg_error (GPG_ERR_INV_SEXP);
323 s += n;
324 n = snext (&s);
325 if (!n)
326 return gpg_error (GPG_ERR_INV_SEXP);
327 s +=n; /* skip value */
328 if (*s != ')')
329 return gpg_error (GPG_ERR_INV_SEXP);
330 depth--;
331 if (i == protect_info[infidx].prot_to)
332 prot_end = s;
333 s++;
335 if (*s != ')' || !prot_begin || !prot_end )
336 return gpg_error (GPG_ERR_INV_SEXP);
337 depth--;
338 hash_end = s;
339 s++;
340 /* skip to the end of the S-exp */
341 assert (depth == 1);
342 rc = sskip (&s, &depth);
343 if (rc)
344 return rc;
345 assert (!depth);
346 real_end = s-1;
349 /* Hash the stuff. Because the timestamp_exp won't get protected,
350 we can't simply hash a continuous buffer but need to use several
351 md_writes. */
352 rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
353 if (rc)
354 return rc;
355 gcry_md_write (md, hash_begin, hash_end - hash_begin);
356 gcry_md_write (md, timestamp_exp, 35);
357 gcry_md_write (md, ")", 1);
358 memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
359 gcry_md_close (md);
361 rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
362 passphrase, hashvalue,
363 &protected, &protectedlen);
364 if (rc)
365 return rc;
367 /* Now create the protected version of the key. Note that the 10
368 extra bytes are for for the inserted "protected-" string (the
369 beginning of the plaintext reads: "((11:private-key(" ). The 35
370 term is the space for (12:protected-at15:<timestamp>). */
371 *resultlen = (10
372 + (prot_begin-plainkey)
373 + protectedlen
374 + 35
375 + (real_end-prot_end));
376 *result = p = xtrymalloc (*resultlen);
377 if (!p)
379 gpg_error_t tmperr = out_of_core ();
380 xfree (protected);
381 return tmperr;
383 memcpy (p, "(21:protected-", 14);
384 p += 14;
385 memcpy (p, plainkey+4, prot_begin - plainkey - 4);
386 p += prot_begin - plainkey - 4;
387 memcpy (p, protected, protectedlen);
388 p += protectedlen;
390 memcpy (p, timestamp_exp, 35);
391 p += 35;
393 memcpy (p, prot_end+1, real_end - prot_end);
394 p += real_end - prot_end;
395 assert ( p - *result == *resultlen);
396 xfree (protected);
398 return 0;
402 /* Do the actual decryption and check the return list for consistency. */
403 static int
404 do_decryption (const unsigned char *protected, size_t protectedlen,
405 const char *passphrase,
406 const unsigned char *s2ksalt, unsigned long s2kcount,
407 const unsigned char *iv, size_t ivlen,
408 unsigned char **result)
410 int rc = 0;
411 int blklen;
412 gcry_cipher_hd_t hd;
413 unsigned char *outbuf;
414 size_t reallen;
416 blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
417 if (protectedlen < 4 || (protectedlen%blklen))
418 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
420 rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
421 GCRY_CIPHER_SECURE);
422 if (rc)
423 return rc;
425 outbuf = gcry_malloc_secure (protectedlen);
426 if (!outbuf)
427 rc = out_of_core ();
428 if (!rc)
429 rc = gcry_cipher_setiv (hd, iv, ivlen);
430 if (!rc)
432 unsigned char *key;
433 size_t keylen = PROT_CIPHER_KEYLEN;
435 key = gcry_malloc_secure (keylen);
436 if (!key)
437 rc = out_of_core ();
438 else
440 rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
441 3, s2ksalt, s2kcount, key, keylen);
442 if (!rc)
443 rc = gcry_cipher_setkey (hd, key, keylen);
444 xfree (key);
447 if (!rc)
448 rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
449 protected, protectedlen);
450 gcry_cipher_close (hd);
451 if (rc)
453 xfree (outbuf);
454 return rc;
456 /* Do a quick check first. */
457 if (*outbuf != '(' && outbuf[1] != '(')
459 xfree (outbuf);
460 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
462 /* Check that we have a consistent S-Exp. */
463 reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
464 if (!reallen || (reallen + blklen < protectedlen) )
466 xfree (outbuf);
467 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
469 *result = outbuf;
470 return 0;
474 /* Merge the parameter list contained in CLEARTEXT with the original
475 protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
476 Return the new list in RESULT and the MIC value in the 20 byte
477 buffer SHA1HASH. CUTOFF and CUTLEN will receive the offset and the
478 length of the resulting list which should go into the MIC
479 calculation but then be removed. */
480 static int
481 merge_lists (const unsigned char *protectedkey,
482 size_t replacepos,
483 const unsigned char *cleartext,
484 unsigned char *sha1hash,
485 unsigned char **result, size_t *resultlen,
486 size_t *cutoff, size_t *cutlen)
488 size_t n, newlistlen;
489 unsigned char *newlist, *p;
490 const unsigned char *s;
491 const unsigned char *startpos, *endpos;
492 int i, rc;
494 *result = NULL;
495 *resultlen = 0;
496 *cutoff = 0;
497 *cutlen = 0;
499 if (replacepos < 26)
500 return gpg_error (GPG_ERR_BUG);
502 /* Estimate the required size of the resulting list. We have a large
503 safety margin of >20 bytes (MIC hash from CLEARTEXT and the
504 removed "protected-" */
505 newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
506 if (!newlistlen)
507 return gpg_error (GPG_ERR_BUG);
508 n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
509 if (!n)
510 return gpg_error (GPG_ERR_BUG);
511 newlistlen += n;
512 newlist = gcry_malloc_secure (newlistlen);
513 if (!newlist)
514 return out_of_core ();
516 /* Copy the initial segment */
517 strcpy ((char*)newlist, "(11:private-key");
518 p = newlist + 15;
519 memcpy (p, protectedkey+15+10, replacepos-15-10);
520 p += replacepos-15-10;
522 /* copy the cleartext */
523 s = cleartext;
524 if (*s != '(' && s[1] != '(')
525 return gpg_error (GPG_ERR_BUG); /*we already checked this */
526 s += 2;
527 startpos = s;
528 while ( *s == '(' )
530 s++;
531 n = snext (&s);
532 if (!n)
533 goto invalid_sexp;
534 s += n;
535 n = snext (&s);
536 if (!n)
537 goto invalid_sexp;
538 s += n;
539 if ( *s != ')' )
540 goto invalid_sexp;
541 s++;
543 if ( *s != ')' )
544 goto invalid_sexp;
545 endpos = s;
546 s++;
547 /* Intermezzo: Get the MIC */
548 if (*s != '(')
549 goto invalid_sexp;
550 s++;
551 n = snext (&s);
552 if (!smatch (&s, n, "hash"))
553 goto invalid_sexp;
554 n = snext (&s);
555 if (!smatch (&s, n, "sha1"))
556 goto invalid_sexp;
557 n = snext (&s);
558 if (n != 20)
559 goto invalid_sexp;
560 memcpy (sha1hash, s, 20);
561 s += n;
562 if (*s != ')')
563 goto invalid_sexp;
564 /* End intermezzo */
566 /* append the parameter list */
567 memcpy (p, startpos, endpos - startpos);
568 p += endpos - startpos;
570 /* Skip over the protected list element in the original list. */
571 s = protectedkey + replacepos;
572 assert (*s == '(');
573 s++;
574 i = 1;
575 rc = sskip (&s, &i);
576 if (rc)
577 goto failure;
578 /* Record the position of the optional protected-at expression. */
579 if (*s == '(')
581 const unsigned char *save_s = s;
582 s++;
583 n = snext (&s);
584 if (smatch (&s, n, "protected-at"))
586 i = 1;
587 rc = sskip (&s, &i);
588 if (rc)
589 goto failure;
590 *cutlen = s - save_s;
592 s = save_s;
594 startpos = s;
595 i = 2; /* we are inside this level */
596 rc = sskip (&s, &i);
597 if (rc)
598 goto failure;
599 assert (s[-1] == ')');
600 endpos = s; /* one behind the end of the list */
602 /* Append the rest. */
603 if (*cutlen)
604 *cutoff = p - newlist;
605 memcpy (p, startpos, endpos - startpos);
606 p += endpos - startpos;
609 /* ready */
610 *result = newlist;
611 *resultlen = newlistlen;
612 return 0;
614 failure:
615 wipememory (newlist, newlistlen);
616 xfree (newlist);
617 return rc;
619 invalid_sexp:
620 wipememory (newlist, newlistlen);
621 xfree (newlist);
622 return gpg_error (GPG_ERR_INV_SEXP);
627 /* Unprotect the key encoded in canonical format. We assume a valid
628 S-Exp here. If a protected-at item is available, its value will
629 be stored at protocted_at unless this is NULL. */
630 int
631 agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
632 gnupg_isotime_t protected_at,
633 unsigned char **result, size_t *resultlen)
635 int rc;
636 const unsigned char *s;
637 const unsigned char *protect_list;
638 size_t n;
639 int infidx, i;
640 unsigned char sha1hash[20], sha1hash2[20];
641 const unsigned char *s2ksalt;
642 unsigned long s2kcount;
643 const unsigned char *iv;
644 const unsigned char *prot_begin;
645 unsigned char *cleartext;
646 unsigned char *final;
647 size_t finallen;
648 size_t cutoff, cutlen;
650 if (protected_at)
651 *protected_at = 0;
653 s = protectedkey;
654 if (*s != '(')
655 return gpg_error (GPG_ERR_INV_SEXP);
656 s++;
657 n = snext (&s);
658 if (!n)
659 return gpg_error (GPG_ERR_INV_SEXP);
660 if (!smatch (&s, n, "protected-private-key"))
661 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
662 if (*s != '(')
663 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
664 s++;
665 n = snext (&s);
666 if (!n)
667 return gpg_error (GPG_ERR_INV_SEXP);
669 for (infidx=0; protect_info[infidx].algo
670 && !smatch (&s, n, protect_info[infidx].algo); infidx++)
672 if (!protect_info[infidx].algo)
673 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
676 /* See wether we have a protected-at timestamp. */
677 protect_list = s; /* Save for later. */
678 if (protected_at)
680 while (*s == '(')
682 prot_begin = s;
683 s++;
684 n = snext (&s);
685 if (!n)
686 return gpg_error (GPG_ERR_INV_SEXP);
687 if (smatch (&s, n, "protected-at"))
689 n = snext (&s);
690 if (!n)
691 return gpg_error (GPG_ERR_INV_SEXP);
692 if (n != 15)
693 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
694 memcpy (protected_at, s, 15);
695 protected_at[15] = 0;
696 break;
698 s += n;
699 i = 1;
700 rc = sskip (&s, &i);
701 if (rc)
702 return rc;
706 /* Now find the list with the protected information. Here is an
707 example for such a list:
708 (protected openpgp-s2k3-sha1-aes-cbc
709 ((sha1 <salt> <count>) <Initialization_Vector>)
710 <encrypted_data>)
712 s = protect_list;
713 for (;;)
715 if (*s != '(')
716 return gpg_error (GPG_ERR_INV_SEXP);
717 prot_begin = s;
718 s++;
719 n = snext (&s);
720 if (!n)
721 return gpg_error (GPG_ERR_INV_SEXP);
722 if (smatch (&s, n, "protected"))
723 break;
724 s += n;
725 i = 1;
726 rc = sskip (&s, &i);
727 if (rc)
728 return rc;
730 /* found */
731 n = snext (&s);
732 if (!n)
733 return gpg_error (GPG_ERR_INV_SEXP);
734 if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
735 return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
736 if (*s != '(' || s[1] != '(')
737 return gpg_error (GPG_ERR_INV_SEXP);
738 s += 2;
739 n = snext (&s);
740 if (!n)
741 return gpg_error (GPG_ERR_INV_SEXP);
742 if (!smatch (&s, n, "sha1"))
743 return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
744 n = snext (&s);
745 if (n != 8)
746 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
747 s2ksalt = s;
748 s += n;
749 n = snext (&s);
750 if (!n)
751 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
752 /* We expect a list close as next, so we can simply use strtoul()
753 here. We might want to check that we only have digits - but this
754 is nothing we should worry about */
755 if (s[n] != ')' )
756 return gpg_error (GPG_ERR_INV_SEXP);
757 s2kcount = strtoul ((const char*)s, NULL, 10);
758 if (!s2kcount)
759 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
760 s += n;
761 s++; /* skip list end */
763 n = snext (&s);
764 if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */
765 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
766 iv = s;
767 s += n;
768 if (*s != ')' )
769 return gpg_error (GPG_ERR_INV_SEXP);
770 s++;
771 n = snext (&s);
772 if (!n)
773 return gpg_error (GPG_ERR_INV_SEXP);
775 rc = do_decryption (s, n,
776 passphrase, s2ksalt, s2kcount,
777 iv, 16,
778 &cleartext);
779 if (rc)
780 return rc;
782 rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
783 sha1hash, &final, &finallen, &cutoff, &cutlen);
784 /* Albeit cleartext has been allocated in secure memory and thus
785 xfree will wipe it out, we do an extra wipe just in case
786 somethings goes badly wrong. */
787 wipememory (cleartext, n);
788 xfree (cleartext);
789 if (rc)
790 return rc;
792 rc = calculate_mic (final, sha1hash2);
793 if (!rc && memcmp (sha1hash, sha1hash2, 20))
794 rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
795 if (rc)
797 wipememory (final, finallen);
798 xfree (final);
799 return rc;
801 /* Now remove tha part which is included in the MIC but should not
802 go into the final thing. */
803 if (cutlen)
805 memmove (final+cutoff, final+cutoff+cutlen, finallen-cutoff-cutlen);
806 finallen -= cutlen;
809 *result = final;
810 *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
811 return 0;
814 /* Check the type of the private key, this is one of the constants:
815 PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
816 value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
817 PRIVATE_KEY_PROTECTED for an protected private key or
818 PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
819 elsewhere. */
821 agent_private_key_type (const unsigned char *privatekey)
823 const unsigned char *s;
824 size_t n;
826 s = privatekey;
827 if (*s != '(')
828 return PRIVATE_KEY_UNKNOWN;
829 s++;
830 n = snext (&s);
831 if (!n)
832 return PRIVATE_KEY_UNKNOWN;
833 if (smatch (&s, n, "protected-private-key"))
834 return PRIVATE_KEY_PROTECTED;
835 if (smatch (&s, n, "shadowed-private-key"))
836 return PRIVATE_KEY_SHADOWED;
837 if (smatch (&s, n, "private-key"))
838 return PRIVATE_KEY_CLEAR;
839 return PRIVATE_KEY_UNKNOWN;
844 /* Transform a passphrase into a suitable key of length KEYLEN and
845 store this key in the caller provided buffer KEY. The caller must
846 provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
847 that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
848 value is 96).
850 Returns an error code on failure. */
851 static int
852 hash_passphrase (const char *passphrase, int hashalgo,
853 int s2kmode,
854 const unsigned char *s2ksalt,
855 unsigned long s2kcount,
856 unsigned char *key, size_t keylen)
858 int rc;
859 gcry_md_hd_t md;
860 int pass, i;
861 int used = 0;
862 int pwlen = strlen (passphrase);
864 if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
865 || !hashalgo || !keylen || !key || !passphrase)
866 return gpg_error (GPG_ERR_INV_VALUE);
867 if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
868 return gpg_error (GPG_ERR_INV_VALUE);
870 rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
871 if (rc)
872 return rc;
874 for (pass=0; used < keylen; pass++)
876 if (pass)
878 gcry_md_reset (md);
879 for (i=0; i < pass; i++) /* preset the hash context */
880 gcry_md_putc (md, 0);
883 if (s2kmode == 1 || s2kmode == 3)
885 int len2 = pwlen + 8;
886 unsigned long count = len2;
888 if (s2kmode == 3)
890 count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
891 if (count < len2)
892 count = len2;
895 while (count > len2)
897 gcry_md_write (md, s2ksalt, 8);
898 gcry_md_write (md, passphrase, pwlen);
899 count -= len2;
901 if (count < 8)
902 gcry_md_write (md, s2ksalt, count);
903 else
905 gcry_md_write (md, s2ksalt, 8);
906 count -= 8;
907 gcry_md_write (md, passphrase, count);
910 else
911 gcry_md_write (md, passphrase, pwlen);
913 gcry_md_final (md);
914 i = gcry_md_get_algo_dlen (hashalgo);
915 if (i > keylen - used)
916 i = keylen - used;
917 memcpy (key+used, gcry_md_read (md, hashalgo), i);
918 used += i;
920 gcry_md_close(md);
921 return 0;
927 /* Create an canonical encoded S-expression with the shadow info from
928 a card's SERIALNO and the IDSTRING. */
929 unsigned char *
930 make_shadow_info (const char *serialno, const char *idstring)
932 const char *s;
933 char *info, *p;
934 char numbuf[20];
935 size_t n;
937 for (s=serialno, n=0; *s && s[1]; s += 2)
938 n++;
940 info = p = xtrymalloc (1 + sizeof numbuf + n
941 + sizeof numbuf + strlen (idstring) + 1 + 1);
942 if (!info)
943 return NULL;
944 *p++ = '(';
945 p = stpcpy (p, smklen (numbuf, sizeof numbuf, n, NULL));
946 for (s=serialno; *s && s[1]; s += 2)
947 *(unsigned char *)p++ = xtoi_2 (s);
948 p = stpcpy (p, smklen (numbuf, sizeof numbuf, strlen (idstring), NULL));
949 p = stpcpy (p, idstring);
950 *p++ = ')';
951 *p = 0;
952 return (unsigned char *)info;
957 /* Create a shadow key from a public key. We use the shadow protocol
958 "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
959 S-expression is returned in an allocated buffer RESULT will point
960 to. The input parameters are expected to be valid canonicalized
961 S-expressions */
962 int
963 agent_shadow_key (const unsigned char *pubkey,
964 const unsigned char *shadow_info,
965 unsigned char **result)
967 const unsigned char *s;
968 const unsigned char *point;
969 size_t n;
970 int depth = 0;
971 char *p;
972 size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
973 size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
975 if (!pubkey_len || !shadow_info_len)
976 return gpg_error (GPG_ERR_INV_VALUE);
977 s = pubkey;
978 if (*s != '(')
979 return gpg_error (GPG_ERR_INV_SEXP);
980 depth++;
981 s++;
982 n = snext (&s);
983 if (!n)
984 return gpg_error (GPG_ERR_INV_SEXP);
985 if (!smatch (&s, n, "public-key"))
986 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
987 if (*s != '(')
988 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
989 depth++;
990 s++;
991 n = snext (&s);
992 if (!n)
993 return gpg_error (GPG_ERR_INV_SEXP);
994 s += n; /* skip over the algorithm name */
996 while (*s != ')')
998 if (*s != '(')
999 return gpg_error (GPG_ERR_INV_SEXP);
1000 depth++;
1001 s++;
1002 n = snext (&s);
1003 if (!n)
1004 return gpg_error (GPG_ERR_INV_SEXP);
1005 s += n;
1006 n = snext (&s);
1007 if (!n)
1008 return gpg_error (GPG_ERR_INV_SEXP);
1009 s +=n; /* skip value */
1010 if (*s != ')')
1011 return gpg_error (GPG_ERR_INV_SEXP);
1012 depth--;
1013 s++;
1015 point = s; /* insert right before the point */
1016 depth--;
1017 s++;
1018 assert (depth == 1);
1020 /* Calculate required length by taking in account: the "shadowed-"
1021 prefix, the "shadowed", "t1-v1" as well as some parenthesis */
1022 n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
1023 *result = xtrymalloc (n);
1024 p = (char*)*result;
1025 if (!p)
1026 return out_of_core ();
1027 p = stpcpy (p, "(20:shadowed-private-key");
1028 /* (10:public-key ...)*/
1029 memcpy (p, pubkey+14, point - (pubkey+14));
1030 p += point - (pubkey+14);
1031 p = stpcpy (p, "(8:shadowed5:t1-v1");
1032 memcpy (p, shadow_info, shadow_info_len);
1033 p += shadow_info_len;
1034 *p++ = ')';
1035 memcpy (p, point, pubkey_len - (point - pubkey));
1036 p += pubkey_len - (point - pubkey);
1038 return 0;
1041 /* Parse a canonical encoded shadowed key and return a pointer to the
1042 inner list with the shadow_info */
1043 int
1044 agent_get_shadow_info (const unsigned char *shadowkey,
1045 unsigned char const **shadow_info)
1047 const unsigned char *s;
1048 size_t n;
1049 int depth = 0;
1051 s = shadowkey;
1052 if (*s != '(')
1053 return gpg_error (GPG_ERR_INV_SEXP);
1054 depth++;
1055 s++;
1056 n = snext (&s);
1057 if (!n)
1058 return gpg_error (GPG_ERR_INV_SEXP);
1059 if (!smatch (&s, n, "shadowed-private-key"))
1060 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1061 if (*s != '(')
1062 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1063 depth++;
1064 s++;
1065 n = snext (&s);
1066 if (!n)
1067 return gpg_error (GPG_ERR_INV_SEXP);
1068 s += n; /* skip over the algorithm name */
1070 for (;;)
1072 if (*s == ')')
1073 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1074 if (*s != '(')
1075 return gpg_error (GPG_ERR_INV_SEXP);
1076 depth++;
1077 s++;
1078 n = snext (&s);
1079 if (!n)
1080 return gpg_error (GPG_ERR_INV_SEXP);
1081 if (smatch (&s, n, "shadowed"))
1082 break;
1083 s += n;
1084 n = snext (&s);
1085 if (!n)
1086 return gpg_error (GPG_ERR_INV_SEXP);
1087 s +=n; /* skip value */
1088 if (*s != ')')
1089 return gpg_error (GPG_ERR_INV_SEXP);
1090 depth--;
1091 s++;
1093 /* Found the shadowed list, S points to the protocol */
1094 n = snext (&s);
1095 if (!n)
1096 return gpg_error (GPG_ERR_INV_SEXP);
1097 if (smatch (&s, n, "t1-v1"))
1099 if (*s != '(')
1100 return gpg_error (GPG_ERR_INV_SEXP);
1101 *shadow_info = s;
1103 else
1104 return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
1105 return 0;
1109 /* Parse the canonical encoded SHADOW_INFO S-expression. On success
1110 the hex encoded serial number is returned as a malloced strings at
1111 R_HEXSN and the Id string as a malloced string at R_IDSTR. On
1112 error an error code is returned and NULL is stored at the result
1113 parameters addresses. If the serial number or the ID string is not
1114 required, NULL may be passed for them. */
1115 gpg_error_t
1116 parse_shadow_info (const unsigned char *shadow_info,
1117 char **r_hexsn, char **r_idstr)
1119 const unsigned char *s;
1120 size_t n;
1122 if (r_hexsn)
1123 *r_hexsn = NULL;
1124 if (r_idstr)
1125 *r_idstr = NULL;
1127 s = shadow_info;
1128 if (*s != '(')
1129 return gpg_error (GPG_ERR_INV_SEXP);
1130 s++;
1131 n = snext (&s);
1132 if (!n)
1133 return gpg_error (GPG_ERR_INV_SEXP);
1135 if (r_hexsn)
1137 *r_hexsn = bin2hex (s, n, NULL);
1138 if (!*r_hexsn)
1139 return gpg_error_from_syserror ();
1141 s += n;
1143 n = snext (&s);
1144 if (!n)
1146 if (r_hexsn)
1148 xfree (*r_hexsn);
1149 *r_hexsn = NULL;
1151 return gpg_error (GPG_ERR_INV_SEXP);
1154 if (r_idstr)
1156 *r_idstr = xtrymalloc (n+1);
1157 if (!*r_idstr)
1159 if (r_hexsn)
1161 xfree (*r_hexsn);
1162 *r_hexsn = NULL;
1164 return gpg_error_from_syserror ();
1166 memcpy (*r_idstr, s, n);
1167 (*r_idstr)[n] = 0;
1170 return 0;