Changes needed to support smartcards. Well, only _support_. There is
[gnupg.git] / agent / protect.c
1 /* protect.c - Un/Protect a secret key
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
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>
30
31 #include "agent.h"
32
33 #define PROT_CIPHER        GCRY_CIPHER_AES
34 #define PROT_CIPHER_STRING "aes"
35 #define PROT_CIPHER_KEYLEN (128/8)
36
37
38 /* A table containing the information needed to create a protected
39    private key */
40 static struct {
41   const char *algo;
42   const char *parmlist;
43   int prot_from, prot_to;
44 } protect_info[] = {
45   { "rsa",  "nedpqu", 2, 5 },
46   { NULL }
47 };
48
49
50 static int
51 hash_passphrase (const char *passphrase, int hashalgo,
52                  int s2kmode,
53                  const unsigned char *s2ksalt, unsigned long s2kcount,
54                  unsigned char *key, size_t keylen);
55
56
57
58 /* Return the length of the next S-Exp part and update the pointer to
59    the first data byte.  0 is return on error */
60 static size_t
61 snext (unsigned char const **buf)
62 {
63   const unsigned char *s;
64   int n;
65
66   s = *buf;
67   for (n=0; *s && *s != ':' && digitp (s); s++)
68     n = n*10 + atoi_1 (s);
69   if (!n || *s != ':')
70     return 0; /* we don't allow empty lengths */
71   *buf = s+1;
72   return n;
73 }
74
75 /* Skip over the S-Expression BUF points to and update BUF to point to
76    the chacter right behind.  DEPTH gives the initial number of open
77    lists and may be passed as a positive number to skip over the
78    remainder of an S-Expression if the current position is somewhere
79    in an S-Expression.  The function may return an error code if it
80    encounters an impossible conditions */
81 static int
82 sskip (unsigned char const **buf, int *depth)
83 {
84   const unsigned char *s = *buf;
85   size_t n;
86   int d = *depth;
87   
88   while (d > 0)
89     {
90       if (*s == '(')
91         {
92           d++;
93           s++;
94         }
95       else if (*s == ')')
96         {
97           d--;
98           s++;
99         }
100       else
101         {
102           if (!d)
103             return GNUPG_Invalid_Sexp;
104           n = snext (&s);
105           if (!n)
106             return GNUPG_Invalid_Sexp; 
107           s += n;
108         }
109     }
110   *buf = s;
111   *depth = d;
112   return 0;
113 }
114
115
116 /* Check whether the the string at the address BUF points to matches
117    the token.  Return true on match and update BUF to point behind the
118    token. */
119 static int
120 smatch (unsigned char const **buf, size_t buflen, const char *token)
121 {
122   size_t toklen = strlen (token);
123
124   if (buflen != toklen || memcmp (*buf, token, toklen))
125     return 0;
126   *buf += toklen;
127   return 1;
128 }
129
130
131 \f
132 /* Calculate the MIC for a private key S-Exp. SHA1HASH should pint to
133    a 20 byte buffer.  This function is suitable for any algorithms. */
134 static int 
135 calculate_mic (const unsigned char *plainkey, unsigned char *sha1hash)
136 {
137   const unsigned char *hash_begin, *hash_end;
138   const unsigned char *s;
139   size_t n;
140
141   s = plainkey;
142   if (*s != '(')
143     return GNUPG_Invalid_Sexp;
144   s++;
145   n = snext (&s);
146   if (!n)
147     return GNUPG_Invalid_Sexp; 
148   if (!smatch (&s, n, "private-key"))
149     return GNUPG_Unknown_Sexp; 
150   if (*s != '(')
151     return GNUPG_Unknown_Sexp;
152   hash_begin = s;
153   s++;
154   n = snext (&s);
155   if (!n)
156     return GNUPG_Invalid_Sexp; 
157   s += n; /* skip over the algorithm name */
158
159   while (*s == '(')
160     {
161       s++;
162       n = snext (&s);
163       if (!n)
164         return GNUPG_Invalid_Sexp; 
165       s += n;
166       n = snext (&s);
167       if (!n)
168         return GNUPG_Invalid_Sexp; 
169       s += n;
170       if ( *s != ')' )
171         return GNUPG_Invalid_Sexp; 
172       s++;
173     }
174   if (*s != ')')
175     return GNUPG_Invalid_Sexp; 
176   s++;
177   hash_end = s;
178
179   gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash,
180                        hash_begin, hash_end - hash_begin);
181
182   return 0;
183 }
184
185
186 \f
187 /* Encrypt the parameter block starting at PROTBEGIN with length
188    PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
189    encrypted block in RESULT or ereturn with an error code.  SHA1HASH
190    is the 20 byte SHA-1 hash required for the integrity code.
191
192    The parameter block is expected to be an incomplete S-Expression of
193    the form (example in advanced format):
194
195      (d #046129F..[some bytes not shown]..81#)
196      (p #00e861b..[some bytes not shown]..f1#)
197      (q #00f7a7c..[some bytes not shown]..61#)
198      (u #304559a..[some bytes not shown]..9b#) 
199
200    the returned block is the S-Expression:
201
202     (protected mode (parms) encrypted_octet_string)
203
204 */
205 static int
206 do_encryption (const char *protbegin, size_t protlen, 
207                const char *passphrase,  const unsigned char *sha1hash,
208                unsigned char **result, size_t *resultlen)
209 {
210   GCRY_CIPHER_HD hd;
211   const char *modestr = "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc";
212   int blklen, enclen, outlen;
213   char *iv = NULL;
214   int rc = 0;
215   char *outbuf = NULL;
216   char *p;
217   int saltpos, ivpos, encpos;
218
219   hd = gcry_cipher_open (PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
220                          GCRY_CIPHER_SECURE);
221   if (!hd)
222     return map_gcry_err (gcry_errno());
223
224
225   /* We need to work on a copy of the data because this makes it
226      easier to add the trailer and the padding and more important we
227      have to prefix the text with 2 parenthesis, so we have to
228      allocate enough space for:
229
230      ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
231
232      We always append a full block of random bytes as padding but
233      encrypt only what is needed for a full blocksize */
234   blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
235   outlen = 2 + protlen + 2 + 6 + 6 + 23 + 2 + blklen;
236   enclen = outlen/blklen * blklen;
237   outbuf = gcry_malloc_secure (outlen);
238   if (!outbuf)
239     rc = GNUPG_Out_Of_Core;
240   if (!rc)
241     {
242       /* allocate random bytes to be used as IV, padding and s2k salt*/
243       iv = gcry_random_bytes (blklen*2+8, GCRY_WEAK_RANDOM);
244       if (!iv)
245         rc = GNUPG_Out_Of_Core;
246       else
247         rc = gcry_cipher_setiv (hd, iv, blklen);
248     }
249   if (!rc)
250     {
251       unsigned char *key;
252       size_t keylen = PROT_CIPHER_KEYLEN;
253       
254       key = gcry_malloc_secure (keylen);
255       if (!key)
256         rc = GNUPG_Out_Of_Core;
257       else
258         {
259           rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
260                                 3, iv+2*blklen, 96, key, keylen);
261           if (!rc)
262             rc = gcry_cipher_setkey (hd, key, keylen);
263           xfree (key);
264         }
265     }
266   if (!rc)
267     {
268       p = outbuf;
269       *p++ = '(';
270       *p++ = '(';
271       memcpy (p, protbegin, protlen);
272       p += protlen;
273       memcpy (p, ")(4:hash4:sha120:", 17);
274       p += 17;
275       memcpy (p, sha1hash, 20);
276       p += 20;
277       *p++ = ')';
278       *p++ = ')';
279       memcpy (p, iv+blklen, blklen); 
280       p += blklen;
281       assert ( p - outbuf == outlen);
282       rc = gcry_cipher_encrypt (hd, outbuf, enclen, NULL, 0);
283     }
284   gcry_cipher_close (hd);
285   if (rc)
286     {
287       xfree (iv);
288       xfree (outbuf);
289       return rc;
290     }
291
292   /* Now allocate the buffer we want to return.  This is
293
294      (protected openpgp-s2k3-sha1-aes-cbc
295        ((sha1 salt no_of_iterations) 16byte_iv)
296        encrypted_octet_string)
297        
298      in canoncical format of course.  We use asprintf and %n modifier
299      and spaces as palceholders.  */
300   asprintf (&p,
301             "(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
302             (int)strlen (modestr), modestr,
303             &saltpos, 
304             blklen, &ivpos, blklen, "",
305             enclen, &encpos, enclen, "");
306   if (p)
307     { /* asprintf does not use out malloc system */
308       char *psave = p;
309       p = xtrymalloc (strlen (psave)+1);
310       if (p)
311         strcpy (p, psave);
312       free (psave);
313     }
314   if (!p)
315     {
316       xfree (iv);
317       xfree (outbuf);
318       return GNUPG_Out_Of_Core;
319     }
320   *resultlen = strlen (p);
321   *result = p;
322   memcpy (p+saltpos, iv+2*blklen, 8);
323   memcpy (p+ivpos, iv, blklen);
324   memcpy (p+encpos, outbuf, enclen);
325   xfree (iv);
326   xfree (outbuf);
327   return 0;
328 }
329
330
331
332 /* Protect the key encoded in canonical format in plainkey.  We assume
333    a valid S-Exp here. */
334 int 
335 agent_protect (const unsigned char *plainkey, const char *passphrase,
336                unsigned char **result, size_t *resultlen)
337 {
338   int rc;
339   const unsigned char *s;
340   const unsigned char *hash_begin, *hash_end;
341   const unsigned char *prot_begin, *prot_end, *real_end;
342   size_t n;
343   int c, infidx, i;
344   unsigned char hashvalue[20];
345   unsigned char *protected;
346   size_t protectedlen;
347   int depth = 0;
348   unsigned char *p;
349
350   s = plainkey;
351   if (*s != '(')
352     return GNUPG_Invalid_Sexp;
353   depth++;
354   s++;
355   n = snext (&s);
356   if (!n)
357     return GNUPG_Invalid_Sexp; 
358   if (!smatch (&s, n, "private-key"))
359     return GNUPG_Unknown_Sexp; 
360   if (*s != '(')
361     return GNUPG_Unknown_Sexp;
362   depth++;
363   hash_begin = s;
364   s++;
365   n = snext (&s);
366   if (!n)
367     return GNUPG_Invalid_Sexp; 
368
369   for (infidx=0; protect_info[infidx].algo
370               && !smatch (&s, n, protect_info[infidx].algo); infidx++)
371     ;
372   if (!protect_info[infidx].algo)
373     return GNUPG_Unsupported_Algorithm; 
374
375   prot_begin = prot_end = NULL;
376   for (i=0; (c=protect_info[infidx].parmlist[i]); i++)
377     {
378       if (i == protect_info[infidx].prot_from)
379         prot_begin = s;
380       if (*s != '(')
381         return GNUPG_Invalid_Sexp;
382       depth++;
383       s++;
384       n = snext (&s);
385       if (!n)
386         return GNUPG_Invalid_Sexp; 
387       if (n != 1 || c != *s)
388         return GNUPG_Invalid_Sexp; 
389       s += n;
390       n = snext (&s);
391       if (!n)
392         return GNUPG_Invalid_Sexp; 
393       s +=n; /* skip value */
394       if (*s != ')')
395         return GNUPG_Invalid_Sexp; 
396       depth--;
397       if (i == protect_info[infidx].prot_to)
398         prot_end = s;
399       s++;
400     }
401   if (*s != ')' || !prot_begin || !prot_end )
402     return GNUPG_Invalid_Sexp; 
403   depth--;
404   hash_end = s;
405   s++;
406   /* skip to the end of the S-exp */
407   assert (depth == 1);
408   rc = sskip (&s, &depth);
409   if (rc)
410     return rc;
411   assert (!depth);
412   real_end = s-1;
413
414   gcry_md_hash_buffer (GCRY_MD_SHA1, hashvalue,
415                        hash_begin, hash_end - hash_begin + 1);
416
417   rc = do_encryption (prot_begin, prot_end - prot_begin + 1,
418                       passphrase,  hashvalue,
419                       &protected, &protectedlen);
420   if (rc)
421     return rc;
422
423   /* Now create the protected version of the key.  Note that the 10
424      extra bytes are for for the inserted "protected-" string (the
425      beginning of the plaintext reads: "((11:private-key(" ). */
426   *resultlen = (10
427                 + (prot_begin-plainkey)
428                 + protectedlen
429                 + (real_end-prot_end));
430   *result = p = xtrymalloc (*resultlen);
431   if (!p)
432     {
433       xfree (protected);
434       return GNUPG_Out_Of_Core;
435     }
436   memcpy (p, "(21:protected-", 14);
437   p += 14;
438   memcpy (p, plainkey+4, prot_begin - plainkey - 4);
439   p += prot_begin - plainkey - 4;
440   memcpy (p, protected, protectedlen);
441   p += protectedlen;
442   memcpy (p, prot_end+1, real_end - prot_end);
443   p += real_end - prot_end;
444   assert ( p - *result == *resultlen);
445   xfree (protected);
446   return 0;
447 }
448
449 \f
450 /* Do the actual decryption and check the return list for consistency.  */
451 static int
452 do_decryption (const unsigned char *protected, size_t protectedlen, 
453                const char *passphrase, 
454                const unsigned char *s2ksalt, unsigned long s2kcount,
455                const unsigned char *iv, size_t ivlen,
456                unsigned char **result)
457 {
458   int rc = 0;
459   int blklen;
460   GCRY_CIPHER_HD hd;
461   unsigned char *outbuf;
462   size_t reallen;
463
464   blklen = gcry_cipher_get_algo_blklen (PROT_CIPHER);
465   if (protectedlen < 4 || (protectedlen%blklen))
466     return GNUPG_Corrupted_Protection;
467
468   hd = gcry_cipher_open (PROT_CIPHER, GCRY_CIPHER_MODE_CBC,
469                          GCRY_CIPHER_SECURE);
470   if (!hd)
471     return map_gcry_err (gcry_errno());
472
473   outbuf = gcry_malloc_secure (protectedlen);
474   if (!outbuf)
475     rc = GNUPG_Out_Of_Core;
476   if (!rc)
477     rc = gcry_cipher_setiv (hd, iv, ivlen);
478   if (!rc)
479     {
480       unsigned char *key;
481       size_t keylen = PROT_CIPHER_KEYLEN;
482       
483       key = gcry_malloc_secure (keylen);
484       if (!key)
485         rc = GNUPG_Out_Of_Core;
486       else
487         {
488           rc = hash_passphrase (passphrase, GCRY_MD_SHA1,
489                                 3, s2ksalt, s2kcount, key, keylen);
490           if (!rc)
491             rc = gcry_cipher_setkey (hd, key, keylen);
492           xfree (key);
493         }
494     }
495   if (!rc)
496     rc = gcry_cipher_decrypt (hd, outbuf, protectedlen,
497                               protected, protectedlen);
498   gcry_cipher_close (hd);
499   if (rc)
500     {
501       xfree (outbuf);
502       return rc;
503     }
504   /* do a quick check first */
505   if (*outbuf != '(' && outbuf[1] != '(')
506     {
507       xfree (outbuf);
508       return GNUPG_Bad_Passphrase;
509     }
510   /* check that we have a consistent S-Exp */
511   reallen = gcry_sexp_canon_len (outbuf, protectedlen, NULL, NULL);
512   if (!reallen || (reallen + blklen < protectedlen) )
513     {
514       xfree (outbuf);
515       return GNUPG_Bad_Passphrase;
516     }
517   *result = outbuf;
518   return 0;
519 }
520
521
522 /* Merge the parameter list contained in CLEARTEXT with the original
523    protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
524    Return the new list in RESULT and the MIC value in the 20 byte
525    buffer SHA1HASH. */
526 static int
527 merge_lists (const unsigned char *protectedkey,
528              size_t replacepos, 
529              const unsigned char *cleartext,
530              unsigned char *sha1hash, unsigned char **result)
531 {
532   size_t n, newlistlen;
533   unsigned char *newlist, *p;
534   const unsigned char *s;
535   const unsigned char *startpos, *endpos;
536   int i, rc;
537   
538   if (replacepos < 26)
539     return GNUPG_Bug;
540
541   /* Estimate the required size of the resulting list.  We have a large
542      safety margin of >20 bytes (MIC hash from CLEARTEXT and the
543      removed "protected-" */
544   newlistlen = gcry_sexp_canon_len (protectedkey, 0, NULL, NULL);
545   if (!newlistlen)
546     return GNUPG_Bug;
547   n = gcry_sexp_canon_len (cleartext, 0, NULL, NULL);
548   if (!n)
549     return GNUPG_Bug;
550   newlistlen += n;
551   newlist = gcry_malloc_secure (newlistlen);
552   if (!newlist)
553     return GNUPG_Out_Of_Core;
554
555   /* Copy the initial segment */
556   strcpy (newlist, "(11:private-key");
557   p = newlist + 15;
558   memcpy (p, protectedkey+15+10, replacepos-15-10);
559   p += replacepos-15-10;
560
561   /* copy the cleartext */
562   s = cleartext;
563   if (*s != '(' && s[1] != '(')
564     return GNUPG_Bug;  /*we already checked this */
565   s += 2;
566   startpos = s;
567   while ( *s == '(' )
568     {
569       s++;
570       n = snext (&s);
571       if (!n)
572         goto invalid_sexp;
573       s += n;
574       n = snext (&s);
575       if (!n)
576         goto invalid_sexp;
577       s += n;
578       if ( *s != ')' )
579         goto invalid_sexp;
580       s++;
581     }
582   if ( *s != ')' )
583     goto invalid_sexp;
584   endpos = s;
585   s++;
586   /* short intermezzo: Get the MIC */
587   if (*s != '(')
588     goto invalid_sexp;
589   s++;
590   n = snext (&s);
591   if (!smatch (&s, n, "hash"))
592     goto invalid_sexp;
593   n = snext (&s);
594   if (!smatch (&s, n, "sha1"))
595     goto invalid_sexp; 
596   n = snext (&s);
597   if (n != 20)
598     goto invalid_sexp;
599   memcpy (sha1hash, s, 20);
600   s += n;
601   if (*s != ')')
602     goto invalid_sexp;
603   /* end intermezzo */
604
605   /* append the parameter list */
606   memcpy (p, startpos, endpos - startpos);
607   p += endpos - startpos;
608   
609   /* skip overt the protected list element in the original list */
610   s = protectedkey + replacepos;
611   assert (*s == '(');
612   s++;
613   i = 1;
614   rc = sskip (&s, &i);
615   if (rc)
616     goto failure;
617   startpos = s;
618   i = 2; /* we are inside this level */
619   rc = sskip (&s, &i);
620   if (rc)
621     goto failure;
622   assert (s[-1] == ')');
623   endpos = s; /* one behind the end of the list */
624
625   /* append the rest */
626   memcpy (p, startpos, endpos - startpos);
627   p += endpos - startpos;
628
629   /* ready */
630   *result = newlist;
631   return 0;
632
633  failure:
634   xfree (newlist);
635   return rc;
636
637  invalid_sexp:
638   xfree (newlist);
639   return GNUPG_Invalid_Sexp;
640 }
641
642
643
644 /* Unprotect the key encoded in canonical format.  We assume a valid
645    S-Exp here. */
646 int 
647 agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
648                  unsigned char **result, size_t *resultlen)
649 {
650   int rc;
651   const unsigned char *s;
652   size_t n;
653   int infidx, i;
654   unsigned char sha1hash[20], sha1hash2[20];
655   const unsigned char *s2ksalt;
656   unsigned long s2kcount;
657   const unsigned char *iv;
658   const unsigned char *prot_begin;
659   unsigned char *cleartext;
660   unsigned char *final;
661
662   s = protectedkey;
663   if (*s != '(')
664     return GNUPG_Invalid_Sexp;
665   s++;
666   n = snext (&s);
667   if (!n)
668     return GNUPG_Invalid_Sexp; 
669   if (!smatch (&s, n, "protected-private-key"))
670     return GNUPG_Unknown_Sexp; 
671   if (*s != '(')
672     return GNUPG_Unknown_Sexp;
673   s++;
674   n = snext (&s);
675   if (!n)
676     return GNUPG_Invalid_Sexp; 
677
678   for (infidx=0; protect_info[infidx].algo
679               && !smatch (&s, n, protect_info[infidx].algo); infidx++)
680     ;
681   if (!protect_info[infidx].algo)
682     return GNUPG_Unsupported_Algorithm; 
683
684   /* now find the list with the protected information.  Here is an
685      example for such a list:
686      (protected openpgp-s2k3-sha1-aes-cbc 
687         ((sha1 <salt> <count>) <Initialization_Vector>)
688         <encrypted_data>)
689    */
690   for (;;)
691     {
692       if (*s != '(')
693         return GNUPG_Invalid_Sexp;
694       prot_begin = s;
695       s++;
696       n = snext (&s);
697       if (!n)
698         return GNUPG_Invalid_Sexp; 
699       if (smatch (&s, n, "protected"))
700         break;
701       s += n;
702       i = 1;
703       rc = sskip (&s, &i);
704       if (rc)
705         return rc;
706     }
707   /* found */
708   n = snext (&s);
709   if (!n)
710     return GNUPG_Invalid_Sexp; 
711   if (!smatch (&s, n, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING "-cbc"))
712     return GNUPG_Unsupported_Protection;
713   if (*s != '(' || s[1] != '(')
714     return GNUPG_Invalid_Sexp;
715   s += 2;
716   n = snext (&s);
717   if (!n)
718     return GNUPG_Invalid_Sexp; 
719   if (!smatch (&s, n, "sha1"))
720     return GNUPG_Unsupported_Protection;
721   n = snext (&s);
722   if (n != 8)
723     return GNUPG_Corrupted_Protection;
724   s2ksalt = s;
725   s += n;
726   n = snext (&s);
727   if (!n)
728     return GNUPG_Corrupted_Protection;
729   /* We expect a list close as next, so we can simply use strtoul()
730      here.  We might want to check that we only have digits - but this
731      is nothing we should worry about */
732   if (s[n] != ')' )
733     return GNUPG_Invalid_Sexp;
734   s2kcount = strtoul (s, NULL, 10);
735   if (!s2kcount)
736     return GNUPG_Corrupted_Protection;
737   s += n;
738   s++; /* skip list end */
739
740   n = snext (&s);
741   if (n != 16) /* Wrong blocksize for IV (we support ony aes-128) */
742     return GNUPG_Corrupted_Protection;
743   iv = s;
744   s += n;
745   if (*s != ')' )
746     return GNUPG_Invalid_Sexp;
747   s++;
748   n = snext (&s);
749   if (!n)
750     return GNUPG_Invalid_Sexp; 
751   
752   rc = do_decryption (s, n,
753                       passphrase, s2ksalt, s2kcount,
754                       iv, 16,
755                       &cleartext);
756   if (rc)
757     return rc;
758
759   rc = merge_lists (protectedkey, prot_begin-protectedkey, cleartext,
760                     sha1hash, &final);
761   xfree (cleartext);
762   if (rc)
763     return rc;
764
765   rc = calculate_mic (final, sha1hash2);
766   if (!rc && memcmp (sha1hash, sha1hash2, 20))
767     rc = GNUPG_Corrupted_Protection;
768   if (rc)
769     {
770       xfree (final);
771       return rc;
772     }
773
774   *result = final;
775   *resultlen = gcry_sexp_canon_len (final, 0, NULL, NULL);
776   return 0;
777 }
778
779 /* Check the type of the private key, this is one of the constants:
780    PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
781    value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
782    PRIVATE_KEY_PROTECTED for an protected private key or
783    PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
784    elsewhere. */
785 int
786 agent_private_key_type (const unsigned char *privatekey)
787 {
788   const unsigned char *s;
789   size_t n;
790
791   s = privatekey;
792   if (*s != '(')
793     return PRIVATE_KEY_UNKNOWN;
794   s++;
795   n = snext (&s);
796   if (!n)
797     return PRIVATE_KEY_UNKNOWN;
798   if (smatch (&s, n, "protected-private-key"))
799     return PRIVATE_KEY_PROTECTED;
800   if (smatch (&s, n, "shadowed-private-key"))
801     return PRIVATE_KEY_SHADOWED;
802   if (smatch (&s, n, "private-key"))
803     return PRIVATE_KEY_CLEAR;
804   return PRIVATE_KEY_UNKNOWN;
805 }
806
807
808 \f
809 /* Transform a passphrase into a suitable key of length KEYLEN and
810    store this key in the caller provided buffer KEY.  The caller must
811    provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
812    that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
813    value is 96).
814   
815    Returns an error code on failure.  */
816 static int
817 hash_passphrase (const char *passphrase, int hashalgo,
818                  int s2kmode,
819                  const unsigned char *s2ksalt,
820                  unsigned long s2kcount,
821                  unsigned char *key, size_t keylen)
822 {
823   GCRY_MD_HD md;
824   int pass, i;
825   int used = 0;
826   int pwlen = strlen (passphrase);
827
828   if ( (s2kmode != 0 && s2kmode != 1 && s2kmode != 3)
829       || !hashalgo || !keylen || !key || !passphrase)
830     return GNUPG_Invalid_Value;
831   if ((s2kmode == 1 ||s2kmode == 3) && !s2ksalt)
832     return GNUPG_Invalid_Value;
833   
834   md = gcry_md_open (hashalgo, GCRY_MD_FLAG_SECURE);
835   if (!md)
836     return map_gcry_err (gcry_errno());
837
838   for (pass=0; used < keylen; pass++)
839     {
840       if (pass)
841         {
842           gcry_md_reset (md);
843           for (i=0; i < pass; i++) /* preset the hash context */
844             gcry_md_putc (md, 0);
845         }
846
847       if (s2kmode == 1 || s2kmode == 3)
848         {
849           int len2 = pwlen + 8;
850           unsigned long count = len2;
851
852           if (s2kmode == 3)
853             {
854               count = (16ul + (s2kcount & 15)) << ((s2kcount >> 4) + 6);
855               if (count < len2)
856                 count = len2;
857             }
858
859           while (count > len2)
860             {
861               gcry_md_write (md, s2ksalt, 8);
862               gcry_md_write (md, passphrase, pwlen);
863               count -= len2;
864             }
865           if (count < 8)
866             gcry_md_write (md, s2ksalt, count);
867           else 
868             {
869               gcry_md_write (md, s2ksalt, 8);
870               count -= 8;
871               gcry_md_write (md, passphrase, count);
872             }
873         }
874       else
875         gcry_md_write (md, passphrase, pwlen);
876       
877       gcry_md_final (md);
878       i = gcry_md_get_algo_dlen (hashalgo);
879       if (i > keylen - used)
880         i = keylen - used;
881       memcpy  (key+used, gcry_md_read (md, hashalgo), i);
882       used += i;
883     }
884   gcry_md_close(md);
885   return 0;
886 }
887
888
889 \f
890 /* Create a shadow key from a public key.  We use the shadow protocol
891   "ti-v1" and insert the S-expressionn SHADOW_INFO.  The resulting
892   S-expression is returned in an allocated buffer RESULT will point
893   to. The input parameters are expected to be valid canonilized
894   S-expressions */
895 int 
896 agent_shadow_key (const unsigned char *pubkey,
897                   const unsigned char *shadow_info,
898                   unsigned char **result)
899 {
900   const unsigned char *s;
901   const unsigned char *point;
902   size_t n;
903   int depth = 0;
904   unsigned char *p;
905   size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
906   size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
907
908   if (!pubkey_len || !shadow_info_len)
909     return GNUPG_Invalid_Value;
910   s = pubkey;
911   if (*s != '(')
912     return GNUPG_Invalid_Sexp;
913   depth++;
914   s++;
915   n = snext (&s);
916   if (!n)
917     return GNUPG_Invalid_Sexp; 
918   if (!smatch (&s, n, "public-key"))
919     return GNUPG_Unknown_Sexp; 
920   if (*s != '(')
921     return GNUPG_Unknown_Sexp;
922   depth++;
923   s++;
924   n = snext (&s); 
925   if (!n)
926     return GNUPG_Invalid_Sexp; 
927   s += n; /* skip over the algorithm name */
928
929   while (*s != ')')
930     {
931       if (*s != '(')
932         return GNUPG_Invalid_Sexp;
933       depth++;
934       s++;
935       n = snext (&s);
936       if (!n) 
937         return GNUPG_Invalid_Sexp; 
938       s += n;
939       n = snext (&s);
940       if (!n)
941         return GNUPG_Invalid_Sexp; 
942       s +=n; /* skip value */
943       if (*s != ')')
944         return GNUPG_Invalid_Sexp; 
945       depth--;
946       s++;
947     }
948   point = s; /* insert right before the point */
949   depth--;
950   s++;
951   assert (depth == 1);
952
953   /* calculate required length by taking in account: the "shadowed-"
954      prefix, the "shadowed", "t1-v1" as well as some parenthesis */
955   n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
956   *result = p = xtrymalloc (n);
957   if (!p)
958       return GNUPG_Out_Of_Core;
959   p = stpcpy (p, "(20:shadowed-private-key");
960   /* (10:public-key ...)*/
961   memcpy (p, pubkey+14, point - (pubkey+14));
962   p += point - (pubkey+14);
963   p = stpcpy (p, "(8:shadowed5:t1-v1");
964   memcpy (p, shadow_info, shadow_info_len);
965   p += shadow_info_len;
966   *p++ = ')';
967   memcpy (p, point, pubkey_len - (point - pubkey));
968   p += pubkey_len - (point - pubkey);
969
970   return 0;
971 }
972
973 /* Parse a canonical encoded shadowed key and return a pointer to the
974    inner list with the shadow_info */
975 int 
976 agent_get_shadow_info (const unsigned char *shadowkey,
977                        unsigned char const **shadow_info)
978 {
979   const unsigned char *s;
980   size_t n;
981   int depth = 0;
982
983   s = shadowkey;
984   if (*s != '(')
985     return GNUPG_Invalid_Sexp;
986   depth++;
987   s++;
988   n = snext (&s);
989   if (!n)
990     return GNUPG_Invalid_Sexp; 
991   if (!smatch (&s, n, "shadowed-private-key"))
992     return GNUPG_Unknown_Sexp; 
993   if (*s != '(')
994     return GNUPG_Unknown_Sexp;
995   depth++;
996   s++;
997   n = snext (&s); 
998   if (!n)
999     return GNUPG_Invalid_Sexp; 
1000   s += n; /* skip over the algorithm name */
1001
1002   for (;;)
1003     {
1004       if (*s == ')')
1005         return GNUPG_Unknown_Sexp;
1006       if (*s != '(')
1007         return GNUPG_Invalid_Sexp;
1008       depth++;
1009       s++;
1010       n = snext (&s);
1011       if (!n) 
1012         return GNUPG_Invalid_Sexp; 
1013       if (smatch (&s, n, "shadowed"))
1014         break;
1015       s += n;
1016       n = snext (&s);
1017       if (!n)
1018         return GNUPG_Invalid_Sexp; 
1019       s +=n; /* skip value */
1020       if (*s != ')')
1021         return GNUPG_Invalid_Sexp; 
1022       depth--;
1023       s++;
1024     }
1025   /* found the shadowed list, s points to the protocol */
1026   n = snext (&s);
1027   if (!n) 
1028     return GNUPG_Invalid_Sexp; 
1029   if (smatch (&s, n, "t1-v1"))
1030     {
1031       if (*s != '(')
1032         return GNUPG_Invalid_Sexp;
1033       *shadow_info = s;
1034     }
1035   else
1036     return GNUPG_Unsupported_Protocol;
1037   return 0;
1038 }
1039