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