Rename encode.c to encrypt.c.
[gnupg.git] / agent / protect.c
blobd6457ad2a1760cebada21a55617ad8d891795407
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 else
181 gcry_create_nonce (iv, blklen*2+8);
182 rc = gcry_cipher_setiv (hd, iv, blklen);
185 if (!rc)
187 unsigned char *key;
188 size_t keylen = PROT_CIPHER_KEYLEN;
190 key = gcry_malloc_secure (keylen);
191 if (!key)
192 rc = out_of_core ();
193 else
195 rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
196 3, iv+2*blklen, 96, key, keylen);
197 if (!rc)
198 rc = gcry_cipher_setkey (hd, key, keylen);
199 xfree (key);
202 if (!rc)
204 p = outbuf;
205 *p++ = '(';
206 *p++ = '(';
207 memcpy (p, protbegin, protlen);
208 p += protlen;
209 memcpy (p, ")(4:hash4:sha120:", 17);
210 p += 17;
211 memcpy (p, sha1hash, 20);
212 p += 20;
213 *p++ = ')';
214 *p++ = ')';
215 memcpy (p, iv+blklen, blklen);
216 p += blklen;
217 assert ( p - outbuf == outlen);
218 rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
220 gcry_cipher_close (hd);
221 if (rc)
223 xfree (iv);
224 xfree (outbuf);
225 return rc;
228 /* Now allocate the buffer we want to return. This is
230 (protected openpgp-s2k3-sha1-aes-cbc
231 ((sha1 salt no_of_iterations) 16byte_iv)
232 encrypted_octet_string)
234 in canoncical format of course. We use asprintf and %n modifier
235 and dummy values as placeholders. */
236 p = xtryasprintf
237 ("(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
238 (int)strlen (modestr), modestr,
239 &saltpos,
240 blklen, &ivpos, blklen, "",
241 enclen, &encpos, enclen, "");
242 if (!p)
244 gpg_error_t tmperr = out_of_core ();
245 xfree (iv);
246 xfree (outbuf);
247 return tmperr;
249 *resultlen = strlen (p);
250 *result = (unsigned char*)p;
251 memcpy (p+saltpos, iv+2*blklen, 8);
252 memcpy (p+ivpos, iv, blklen);
253 memcpy (p+encpos, outbuf, enclen);
254 xfree (iv);
255 xfree (outbuf);
256 return 0;
261 /* Protect the key encoded in canonical format in PLAINKEY. We assume
262 a valid S-Exp here. */
263 int
264 agent_protect (const unsigned char *plainkey, const char *passphrase,
265 unsigned char **result, size_t *resultlen)
267 int rc;
268 const unsigned char *s;
269 const unsigned char *hash_begin, *hash_end;
270 const unsigned char *prot_begin, *prot_end, *real_end;
271 size_t n;
272 int c, infidx, i;
273 unsigned char hashvalue[20];
274 char timestamp_exp[35];
275 unsigned char *protected;
276 size_t protectedlen;
277 int depth = 0;
278 unsigned char *p;
279 gcry_md_hd_t md;
281 /* Create an S-expression with the procted-at timestamp. */
282 memcpy (timestamp_exp, "(12:protected-at15:", 19);
283 gnupg_get_isotime (timestamp_exp+19);
284 timestamp_exp[19+15] = ')';
286 /* Parse original key. */
287 s = plainkey;
288 if (*s != '(')
289 return gpg_error (GPG_ERR_INV_SEXP);
290 depth++;
291 s++;
292 n = snext (&s);
293 if (!n)
294 return gpg_error (GPG_ERR_INV_SEXP);
295 if (!smatch (&s, n, "private-key"))
296 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
297 if (*s != '(')
298 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
299 depth++;
300 hash_begin = s;
301 s++;
302 n = snext (&s);
303 if (!n)
304 return gpg_error (GPG_ERR_INV_SEXP);
306 for (infidx=0; protect_info[infidx].algo
307 && !smatch (&s, n, protect_info[infidx].algo); infidx++)
309 if (!protect_info[infidx].algo)
310 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
312 prot_begin = prot_end = NULL;
313 for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
315 if (i == protect_info[infidx].prot_from)
316 prot_begin = s;
317 if (*s != '(')
318 return gpg_error (GPG_ERR_INV_SEXP);
319 depth++;
320 s++;
321 n = snext (&s);
322 if (!n)
323 return gpg_error (GPG_ERR_INV_SEXP);
324 if (n != 1 || c != *s)
325 return gpg_error (GPG_ERR_INV_SEXP);
326 s += n;
327 n = snext (&s);
328 if (!n)
329 return gpg_error (GPG_ERR_INV_SEXP);
330 s +=n; /* skip value */
331 if (*s != ')')
332 return gpg_error (GPG_ERR_INV_SEXP);
333 depth--;
334 if (i == protect_info[infidx].prot_to)
335 prot_end = s;
336 s++;
338 if (*s != ')' || !prot_begin || !prot_end )
339 return gpg_error (GPG_ERR_INV_SEXP);
340 depth--;
341 hash_end = s;
342 s++;
343 /* skip to the end of the S-exp */
344 assert (depth == 1);
345 rc = sskip (&s, &depth);
346 if (rc)
347 return rc;
348 assert (!depth);
349 real_end = s-1;
352 /* Hash the stuff. Because the timestamp_exp won't get protected,
353 we can't simply hash a continuous buffer but need to use several
354 md_writes. */
355 rc = gcry_md_open (&md, GCRY_MD_SHA1, 0 );
356 if (rc)
357 return rc;
358 gcry_md_write (md, hash_begin, hash_end - hash_begin);
359 gcry_md_write (md, timestamp_exp, 35);
360 gcry_md_write (md, ")", 1);
361 memcpy (hashvalue, gcry_md_read (md, GCRY_MD_SHA1), 20);
362 gcry_md_close (md);
364 rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
365 passphrase, hashvalue,
366 &protected, &protectedlen);
367 if (rc)
368 return rc;
370 /* Now create the protected version of the key. Note that the 10
371 extra bytes are for for the inserted "protected-" string (the
372 beginning of the plaintext reads: "((11:private-key(" ). The 35
373 term is the space for (12:protected-at15:<timestamp>). */
374 *resultlen = (10
375 + (prot_begin-plainkey)
376 + protectedlen
377 + 35
378 + (real_end-prot_end));
379 *result = p = xtrymalloc (*resultlen);
380 if (!p)
382 gpg_error_t tmperr = out_of_core ();
383 xfree (protected);
384 return tmperr;
386 memcpy (p, "(21:protected-", 14);
387 p += 14;
388 memcpy (p, plainkey+4, prot_begin - plainkey - 4);
389 p += prot_begin - plainkey - 4;
390 memcpy (p, protected, protectedlen);
391 p += protectedlen;
393 memcpy (p, timestamp_exp, 35);
394 p += 35;
396 memcpy (p, prot_end+1, real_end - prot_end);
397 p += real_end - prot_end;
398 assert ( p - *result == *resultlen);
399 xfree (protected);
401 return 0;
405 /* Do the actual decryption and check the return list for consistency. */
406 static int
407 do_decryption (const unsigned char *protected, size_t protectedlen,
408 const char *passphrase,
409 const unsigned char *s2ksalt, unsigned long s2kcount,
410 const unsigned char *iv, size_t ivlen,
411 unsigned char **result)
413 int rc = 0;
414 int blklen;
415 gcry_cipher_hd_t hd;
416 unsigned char *outbuf;
417 size_t reallen;
419 blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
420 if (protectedlen < 4 || (protectedlen%blklen))
421 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
423 rc = gcry_cipher_open (&hd, PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
424 GCRY_CIPHER_SECURE);
425 if (rc)
426 return rc;
428 outbuf = gcry_malloc_secure (protectedlen);
429 if (!outbuf)
430 rc = out_of_core ();
431 if (!rc)
432 rc = gcry_cipher_setiv (hd, iv, ivlen);
433 if (!rc)
435 unsigned char *key;
436 size_t keylen = PROT_CIPHER_KEYLEN;
438 key = gcry_malloc_secure (keylen);
439 if (!key)
440 rc = out_of_core ();
441 else
443 rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
444 3, s2ksalt, s2kcount, key, keylen);
445 if (!rc)
446 rc = gcry_cipher_setkey (hd, key, keylen);
447 xfree (key);
450 if (!rc)
451 rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
452 protected, protectedlen);
453 gcry_cipher_close (hd);
454 if (rc)
456 xfree (outbuf);
457 return rc;
459 /* Do a quick check first. */
460 if (*outbuf != '(' && outbuf[1] != '(')
462 xfree (outbuf);
463 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
465 /* Check that we have a consistent S-Exp. */
466 reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
467 if (!reallen || (reallen + blklen < protectedlen) )
469 xfree (outbuf);
470 return gpg_error (GPG_ERR_BAD_PASSPHRASE);
472 *result = outbuf;
473 return 0;
477 /* Merge the parameter list contained in CLEARTEXT with the original
478 protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
479 Return the new list in RESULT and the MIC value in the 20 byte
480 buffer SHA1HASH. CUTOFF and CUTLEN will receive the offset and the
481 length of the resulting list which should go into the MIC
482 calculation but then be removed. */
483 static int
484 merge_lists (const unsigned char *protectedkey,
485 size_t replacepos,
486 const unsigned char *cleartext,
487 unsigned char *sha1hash,
488 unsigned char **result, size_t *resultlen,
489 size_t *cutoff, size_t *cutlen)
491 size_t n, newlistlen;
492 unsigned char *newlist, *p;
493 const unsigned char *s;
494 const unsigned char *startpos, *endpos;
495 int i, rc;
497 *result = NULL;
498 *resultlen = 0;
499 *cutoff = 0;
500 *cutlen = 0;
502 if (replacepos < 26)
503 return gpg_error (GPG_ERR_BUG);
505 /* Estimate the required size of the resulting list. We have a large
506 safety margin of >20 bytes (MIC hash from CLEARTEXT and the
507 removed "protected-" */
508 newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
509 if (!newlistlen)
510 return gpg_error (GPG_ERR_BUG);
511 n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
512 if (!n)
513 return gpg_error (GPG_ERR_BUG);
514 newlistlen += n;
515 newlist = gcry_malloc_secure (newlistlen);
516 if (!newlist)
517 return out_of_core ();
519 /* Copy the initial segment */
520 strcpy ((char*)newlist, "(11:private-key");
521 p = newlist + 15;
522 memcpy (p, protectedkey+15+10, replacepos-15-10);
523 p += replacepos-15-10;
525 /* copy the cleartext */
526 s = cleartext;
527 if (*s != '(' && s[1] != '(')
528 return gpg_error (GPG_ERR_BUG); /*we already checked this */
529 s += 2;
530 startpos = s;
531 while ( *s == '(' )
533 s++;
534 n = snext (&s);
535 if (!n)
536 goto invalid_sexp;
537 s += n;
538 n = snext (&s);
539 if (!n)
540 goto invalid_sexp;
541 s += n;
542 if ( *s != ')' )
543 goto invalid_sexp;
544 s++;
546 if ( *s != ')' )
547 goto invalid_sexp;
548 endpos = s;
549 s++;
550 /* Intermezzo: Get the MIC */
551 if (*s != '(')
552 goto invalid_sexp;
553 s++;
554 n = snext (&s);
555 if (!smatch (&s, n, "hash"))
556 goto invalid_sexp;
557 n = snext (&s);
558 if (!smatch (&s, n, "sha1"))
559 goto invalid_sexp;
560 n = snext (&s);
561 if (n != 20)
562 goto invalid_sexp;
563 memcpy (sha1hash, s, 20);
564 s += n;
565 if (*s != ')')
566 goto invalid_sexp;
567 /* End intermezzo */
569 /* append the parameter list */
570 memcpy (p, startpos, endpos - startpos);
571 p += endpos - startpos;
573 /* Skip over the protected list element in the original list. */
574 s = protectedkey + replacepos;
575 assert (*s == '(');
576 s++;
577 i = 1;
578 rc = sskip (&s, &i);
579 if (rc)
580 goto failure;
581 /* Record the position of the optional protected-at expression. */
582 if (*s == '(')
584 const unsigned char *save_s = s;
585 s++;
586 n = snext (&s);
587 if (smatch (&s, n, "protected-at"))
589 i = 1;
590 rc = sskip (&s, &i);
591 if (rc)
592 goto failure;
593 *cutlen = s - save_s;
595 s = save_s;
597 startpos = s;
598 i = 2; /* we are inside this level */
599 rc = sskip (&s, &i);
600 if (rc)
601 goto failure;
602 assert (s[-1] == ')');
603 endpos = s; /* one behind the end of the list */
605 /* Append the rest. */
606 if (*cutlen)
607 *cutoff = p - newlist;
608 memcpy (p, startpos, endpos - startpos);
609 p += endpos - startpos;
612 /* ready */
613 *result = newlist;
614 *resultlen = newlistlen;
615 return 0;
617 failure:
618 wipememory (newlist, newlistlen);
619 xfree (newlist);
620 return rc;
622 invalid_sexp:
623 wipememory (newlist, newlistlen);
624 xfree (newlist);
625 return gpg_error (GPG_ERR_INV_SEXP);
630 /* Unprotect the key encoded in canonical format. We assume a valid
631 S-Exp here. If a protected-at item is available, its value will
632 be stored at protocted_at unless this is NULL. */
633 int
634 agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
635 gnupg_isotime_t protected_at,
636 unsigned char **result, size_t *resultlen)
638 int rc;
639 const unsigned char *s;
640 const unsigned char *protect_list;
641 size_t n;
642 int infidx, i;
643 unsigned char sha1hash[20], sha1hash2[20];
644 const unsigned char *s2ksalt;
645 unsigned long s2kcount;
646 const unsigned char *iv;
647 const unsigned char *prot_begin;
648 unsigned char *cleartext;
649 unsigned char *final;
650 size_t finallen;
651 size_t cutoff, cutlen;
653 if (protected_at)
654 *protected_at = 0;
656 s = protectedkey;
657 if (*s != '(')
658 return gpg_error (GPG_ERR_INV_SEXP);
659 s++;
660 n = snext (&s);
661 if (!n)
662 return gpg_error (GPG_ERR_INV_SEXP);
663 if (!smatch (&s, n, "protected-private-key"))
664 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
665 if (*s != '(')
666 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
667 s++;
668 n = snext (&s);
669 if (!n)
670 return gpg_error (GPG_ERR_INV_SEXP);
672 for (infidx=0; protect_info[infidx].algo
673 && !smatch (&s, n, protect_info[infidx].algo); infidx++)
675 if (!protect_info[infidx].algo)
676 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
679 /* See wether we have a protected-at timestamp. */
680 protect_list = s; /* Save for later. */
681 if (protected_at)
683 while (*s == '(')
685 prot_begin = s;
686 s++;
687 n = snext (&s);
688 if (!n)
689 return gpg_error (GPG_ERR_INV_SEXP);
690 if (smatch (&s, n, "protected-at"))
692 n = snext (&s);
693 if (!n)
694 return gpg_error (GPG_ERR_INV_SEXP);
695 if (n != 15)
696 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
697 memcpy (protected_at, s, 15);
698 protected_at[15] = 0;
699 break;
701 s += n;
702 i = 1;
703 rc = sskip (&s, &i);
704 if (rc)
705 return rc;
709 /* Now find the list with the protected information. Here is an
710 example for such a list:
711 (protected openpgp-s2k3-sha1-aes-cbc
712 ((sha1 <salt> <count>) <Initialization_Vector>)
713 <encrypted_data>)
715 s = protect_list;
716 for (;;)
718 if (*s != '(')
719 return gpg_error (GPG_ERR_INV_SEXP);
720 prot_begin = s;
721 s++;
722 n = snext (&s);
723 if (!n)
724 return gpg_error (GPG_ERR_INV_SEXP);
725 if (smatch (&s, n, "protected"))
726 break;
727 s += n;
728 i = 1;
729 rc = sskip (&s, &i);
730 if (rc)
731 return rc;
733 /* found */
734 n = snext (&s);
735 if (!n)
736 return gpg_error (GPG_ERR_INV_SEXP);
737 if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
738 return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
739 if (*s != '(' || s[1] != '(')
740 return gpg_error (GPG_ERR_INV_SEXP);
741 s += 2;
742 n = snext (&s);
743 if (!n)
744 return gpg_error (GPG_ERR_INV_SEXP);
745 if (!smatch (&s, n, "sha1"))
746 return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION);
747 n = snext (&s);
748 if (n != 8)
749 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
750 s2ksalt = s;
751 s += n;
752 n = snext (&s);
753 if (!n)
754 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
755 /* We expect a list close as next, so we can simply use strtoul()
756 here. We might want to check that we only have digits - but this
757 is nothing we should worry about */
758 if (s[n] != ')' )
759 return gpg_error (GPG_ERR_INV_SEXP);
760 s2kcount = strtoul ((const char*)s, NULL, 10);
761 if (!s2kcount)
762 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
763 s += n;
764 s++; /* skip list end */
766 n = snext (&s);
767 if (n != 16) /* Wrong blocksize for IV (we support only aes-128). */
768 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
769 iv = s;
770 s += n;
771 if (*s != ')' )
772 return gpg_error (GPG_ERR_INV_SEXP);
773 s++;
774 n = snext (&s);
775 if (!n)
776 return gpg_error (GPG_ERR_INV_SEXP);
778 rc = do_decryption (s, n,
779 passphrase, s2ksalt, s2kcount,
780 iv, 16,
781 &cleartext);
782 if (rc)
783 return rc;
785 rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
786 sha1hash, &final, &finallen, &cutoff, &cutlen);
787 /* Albeit cleartext has been allocated in secure memory and thus
788 xfree will wipe it out, we do an extra wipe just in case
789 somethings goes badly wrong. */
790 wipememory (cleartext, n);
791 xfree (cleartext);
792 if (rc)
793 return rc;
795 rc = calculate_mic (final, sha1hash2);
796 if (!rc && memcmp (sha1hash, sha1hash2, 20))
797 rc = gpg_error (GPG_ERR_CORRUPTED_PROTECTION);
798 if (rc)
800 wipememory (final, finallen);
801 xfree (final);
802 return rc;
804 /* Now remove tha part which is included in the MIC but should not
805 go into the final thing. */
806 if (cutlen)
808 memmove (final+cutoff, final+cutoff+cutlen, finallen-cutoff-cutlen);
809 finallen -= cutlen;
812 *result = final;
813 *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
814 return 0;
817 /* Check the type of the private key, this is one of the constants:
818 PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
819 value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
820 PRIVATE_KEY_PROTECTED for an protected private key or
821 PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
822 elsewhere. */
824 agent_private_key_type (const unsigned char *privatekey)
826 const unsigned char *s;
827 size_t n;
829 s = privatekey;
830 if (*s != '(')
831 return PRIVATE_KEY_UNKNOWN;
832 s++;
833 n = snext (&s);
834 if (!n)
835 return PRIVATE_KEY_UNKNOWN;
836 if (smatch (&s, n, "protected-private-key"))
837 return PRIVATE_KEY_PROTECTED;
838 if (smatch (&s, n, "shadowed-private-key"))
839 return PRIVATE_KEY_SHADOWED;
840 if (smatch (&s, n, "private-key"))
841 return PRIVATE_KEY_CLEAR;
842 return PRIVATE_KEY_UNKNOWN;
847 /* Transform a passphrase into a suitable key of length KEYLEN and
848 store this key in the caller provided buffer KEY. The caller must
849 provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
850 that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
851 value is 96).
853 Returns an error code on failure. */
854 static int
855 hash_passphrase (const char *passphrase, int hashalgo,
856 int s2kmode,
857 const unsigned char *s2ksalt,
858 unsigned long s2kcount,
859 unsigned char *key, size_t keylen)
861 int rc;
862 gcry_md_hd_t md;
863 int pass, i;
864 int used = 0;
865 int pwlen = strlen (passphrase);
867 if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
868 || !hashalgo || !keylen || !key || !passphrase)
869 return gpg_error (GPG_ERR_INV_VALUE);
870 if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
871 return gpg_error (GPG_ERR_INV_VALUE);
873 rc = gcry_md_open (&md, hashalgo, GCRY_MD_FLAG_SECURE);
874 if (rc)
875 return rc;
877 for (pass=0; used < keylen; pass++)
879 if (pass)
881 gcry_md_reset (md);
882 for (i=0; i < pass; i++) /* preset the hash context */
883 gcry_md_putc (md, 0);
886 if (s2kmode == 1 || s2kmode == 3)
888 int len2 = pwlen + 8;
889 unsigned long count = len2;
891 if (s2kmode == 3)
893 count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
894 if (count < len2)
895 count = len2;
898 while (count > len2)
900 gcry_md_write (md, s2ksalt, 8);
901 gcry_md_write (md, passphrase, pwlen);
902 count -= len2;
904 if (count < 8)
905 gcry_md_write (md, s2ksalt, count);
906 else
908 gcry_md_write (md, s2ksalt, 8);
909 count -= 8;
910 gcry_md_write (md, passphrase, count);
913 else
914 gcry_md_write (md, passphrase, pwlen);
916 gcry_md_final (md);
917 i = gcry_md_get_algo_dlen (hashalgo);
918 if (i > keylen - used)
919 i = keylen - used;
920 memcpy (key+used, gcry_md_read (md, hashalgo), i);
921 used += i;
923 gcry_md_close(md);
924 return 0;
930 /* Create an canonical encoded S-expression with the shadow info from
931 a card's SERIALNO and the IDSTRING. */
932 unsigned char *
933 make_shadow_info (const char *serialno, const char *idstring)
935 const char *s;
936 char *info, *p;
937 char numbuf[20];
938 size_t n;
940 for (s=serialno, n=0; *s && s[1]; s += 2)
941 n++;
943 info = p = xtrymalloc (1 + sizeof numbuf + n
944 + sizeof numbuf + strlen (idstring) + 1 + 1);
945 if (!info)
946 return NULL;
947 *p++ = '(';
948 p = stpcpy (p, smklen (numbuf, sizeof numbuf, n, NULL));
949 for (s=serialno; *s && s[1]; s += 2)
950 *(unsigned char *)p++ = xtoi_2 (s);
951 p = stpcpy (p, smklen (numbuf, sizeof numbuf, strlen (idstring), NULL));
952 p = stpcpy (p, idstring);
953 *p++ = ')';
954 *p = 0;
955 return (unsigned char *)info;
960 /* Create a shadow key from a public key. We use the shadow protocol
961 "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
962 S-expression is returned in an allocated buffer RESULT will point
963 to. The input parameters are expected to be valid canonicalized
964 S-expressions */
965 int
966 agent_shadow_key (const unsigned char *pubkey,
967 const unsigned char *shadow_info,
968 unsigned char **result)
970 const unsigned char *s;
971 const unsigned char *point;
972 size_t n;
973 int depth = 0;
974 char *p;
975 size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
976 size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
978 if (!pubkey_len || !shadow_info_len)
979 return gpg_error (GPG_ERR_INV_VALUE);
980 s = pubkey;
981 if (*s != '(')
982 return gpg_error (GPG_ERR_INV_SEXP);
983 depth++;
984 s++;
985 n = snext (&s);
986 if (!n)
987 return gpg_error (GPG_ERR_INV_SEXP);
988 if (!smatch (&s, n, "public-key"))
989 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
990 if (*s != '(')
991 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
992 depth++;
993 s++;
994 n = snext (&s);
995 if (!n)
996 return gpg_error (GPG_ERR_INV_SEXP);
997 s += n; /* skip over the algorithm name */
999 while (*s != ')')
1001 if (*s != '(')
1002 return gpg_error (GPG_ERR_INV_SEXP);
1003 depth++;
1004 s++;
1005 n = snext (&s);
1006 if (!n)
1007 return gpg_error (GPG_ERR_INV_SEXP);
1008 s += n;
1009 n = snext (&s);
1010 if (!n)
1011 return gpg_error (GPG_ERR_INV_SEXP);
1012 s +=n; /* skip value */
1013 if (*s != ')')
1014 return gpg_error (GPG_ERR_INV_SEXP);
1015 depth--;
1016 s++;
1018 point = s; /* insert right before the point */
1019 depth--;
1020 s++;
1021 assert (depth == 1);
1023 /* Calculate required length by taking in account: the "shadowed-"
1024 prefix, the "shadowed", "t1-v1" as well as some parenthesis */
1025 n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
1026 *result = xtrymalloc (n);
1027 p = (char*)*result;
1028 if (!p)
1029 return out_of_core ();
1030 p = stpcpy (p, "(20:shadowed-private-key");
1031 /* (10:public-key ...)*/
1032 memcpy (p, pubkey+14, point - (pubkey+14));
1033 p += point - (pubkey+14);
1034 p = stpcpy (p, "(8:shadowed5:t1-v1");
1035 memcpy (p, shadow_info, shadow_info_len);
1036 p += shadow_info_len;
1037 *p++ = ')';
1038 memcpy (p, point, pubkey_len - (point - pubkey));
1039 p += pubkey_len - (point - pubkey);
1041 return 0;
1044 /* Parse a canonical encoded shadowed key and return a pointer to the
1045 inner list with the shadow_info */
1046 int
1047 agent_get_shadow_info (const unsigned char *shadowkey,
1048 unsigned char const **shadow_info)
1050 const unsigned char *s;
1051 size_t n;
1052 int depth = 0;
1054 s = shadowkey;
1055 if (*s != '(')
1056 return gpg_error (GPG_ERR_INV_SEXP);
1057 depth++;
1058 s++;
1059 n = snext (&s);
1060 if (!n)
1061 return gpg_error (GPG_ERR_INV_SEXP);
1062 if (!smatch (&s, n, "shadowed-private-key"))
1063 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1064 if (*s != '(')
1065 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1066 depth++;
1067 s++;
1068 n = snext (&s);
1069 if (!n)
1070 return gpg_error (GPG_ERR_INV_SEXP);
1071 s += n; /* skip over the algorithm name */
1073 for (;;)
1075 if (*s == ')')
1076 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1077 if (*s != '(')
1078 return gpg_error (GPG_ERR_INV_SEXP);
1079 depth++;
1080 s++;
1081 n = snext (&s);
1082 if (!n)
1083 return gpg_error (GPG_ERR_INV_SEXP);
1084 if (smatch (&s, n, "shadowed"))
1085 break;
1086 s += n;
1087 n = snext (&s);
1088 if (!n)
1089 return gpg_error (GPG_ERR_INV_SEXP);
1090 s +=n; /* skip value */
1091 if (*s != ')')
1092 return gpg_error (GPG_ERR_INV_SEXP);
1093 depth--;
1094 s++;
1096 /* Found the shadowed list, S points to the protocol */
1097 n = snext (&s);
1098 if (!n)
1099 return gpg_error (GPG_ERR_INV_SEXP);
1100 if (smatch (&s, n, "t1-v1"))
1102 if (*s != '(')
1103 return gpg_error (GPG_ERR_INV_SEXP);
1104 *shadow_info = s;
1106 else
1107 return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
1108 return 0;
1112 /* Parse the canonical encoded SHADOW_INFO S-expression. On success
1113 the hex encoded serial number is returned as a malloced strings at
1114 R_HEXSN and the Id string as a malloced string at R_IDSTR. On
1115 error an error code is returned and NULL is stored at the result
1116 parameters addresses. If the serial number or the ID string is not
1117 required, NULL may be passed for them. */
1118 gpg_error_t
1119 parse_shadow_info (const unsigned char *shadow_info,
1120 char **r_hexsn, char **r_idstr)
1122 const unsigned char *s;
1123 size_t n;
1125 if (r_hexsn)
1126 *r_hexsn = NULL;
1127 if (r_idstr)
1128 *r_idstr = NULL;
1130 s = shadow_info;
1131 if (*s != '(')
1132 return gpg_error (GPG_ERR_INV_SEXP);
1133 s++;
1134 n = snext (&s);
1135 if (!n)
1136 return gpg_error (GPG_ERR_INV_SEXP);
1138 if (r_hexsn)
1140 *r_hexsn = bin2hex (s, n, NULL);
1141 if (!*r_hexsn)
1142 return gpg_error_from_syserror ();
1144 s += n;
1146 n = snext (&s);
1147 if (!n)
1149 if (r_hexsn)
1151 xfree (*r_hexsn);
1152 *r_hexsn = NULL;
1154 return gpg_error (GPG_ERR_INV_SEXP);
1157 if (r_idstr)
1159 *r_idstr = xtrymalloc (n+1);
1160 if (!*r_idstr)
1162 if (r_hexsn)
1164 xfree (*r_hexsn);
1165 *r_hexsn = NULL;
1167 return gpg_error_from_syserror ();
1169 memcpy (*r_idstr, s, n);
1170 (*r_idstr)[n] = 0;
1173 return 0;