Moved 1.9 branch to trunk
[gnupg.git] / agent / minip12.c
1 /* minip12.c - A minimal pkcs-12 implementation.
2  * Copyright (C) 2002, 2003, 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <gcrypt.h>
30
31 #ifdef TEST
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #endif
36
37 #include "../jnlib/logging.h"
38 #include "minip12.h"
39
40 #ifndef DIM
41 #define DIM(v)               (sizeof(v)/sizeof((v)[0]))
42 #endif
43
44 enum
45 {
46   UNIVERSAL = 0,
47   APPLICATION = 1,
48   CONTEXT = 2,
49   PRIVATE = 3
50 };
51
52
53 enum
54 {
55   TAG_NONE = 0,
56   TAG_BOOLEAN = 1,
57   TAG_INTEGER = 2,
58   TAG_BIT_STRING = 3,
59   TAG_OCTET_STRING = 4,
60   TAG_NULL = 5,
61   TAG_OBJECT_ID = 6,
62   TAG_OBJECT_DESCRIPTOR = 7,
63   TAG_EXTERNAL = 8,
64   TAG_REAL = 9,
65   TAG_ENUMERATED = 10,
66   TAG_EMBEDDED_PDV = 11,
67   TAG_UTF8_STRING = 12,
68   TAG_REALTIVE_OID = 13,
69   TAG_SEQUENCE = 16,
70   TAG_SET = 17,
71   TAG_NUMERIC_STRING = 18,
72   TAG_PRINTABLE_STRING = 19,
73   TAG_TELETEX_STRING = 20,
74   TAG_VIDEOTEX_STRING = 21,
75   TAG_IA5_STRING = 22,
76   TAG_UTC_TIME = 23,
77   TAG_GENERALIZED_TIME = 24,
78   TAG_GRAPHIC_STRING = 25,
79   TAG_VISIBLE_STRING = 26,
80   TAG_GENERAL_STRING = 27,
81   TAG_UNIVERSAL_STRING = 28,
82   TAG_CHARACTER_STRING = 29,
83   TAG_BMP_STRING = 30
84 };
85
86
87 static unsigned char const oid_data[9] = {
88   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
89 static unsigned char const oid_encryptedData[9] = {
90   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 };
91 static unsigned char const oid_pkcs_12_keyBag[11] = {
92   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x01 };
93 static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = {
94   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 };
95 static unsigned char const oid_pkcs_12_CertBag[11] = {
96   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x03 };
97 static unsigned char const oid_pkcs_12_CrlBag[11] = {
98   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x04 };
99
100 static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = {
101   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 };
102 static unsigned char const oid_pbeWithSHAAnd40BitRC2_CBC[10] = {
103   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06 };
104 static unsigned char const oid_x509Certificate_for_pkcs_12[10] = {
105   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01 };
106
107
108 static unsigned char const oid_rsaEncryption[9] = {
109   0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
110
111
112 static unsigned char const data_3desiter2048[30] = {
113   0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86,
114   0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E, 
115   0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116   0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 };
117 #define DATA_3DESITER2048_SALT_OFF  18
118
119 static unsigned char const data_rc2iter2048[30] = {
120   0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86,
121   0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06, 0x30, 0x0E, 
122   0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
123   0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 };
124 #define DATA_RC2ITER2048_SALT_OFF  18
125
126 static unsigned char const data_mactemplate[51] = {
127   0x30, 0x31, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
128   0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
129   0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131   0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x08, 0xff,
132   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02,
133   0x02, 0x08, 0x00 }; 
134 #define DATA_MACTEMPLATE_MAC_OFF 17
135 #define DATA_MACTEMPLATE_SALT_OFF 39
136
137 static unsigned char const data_attrtemplate[106] = {
138   0x31, 0x7c, 0x30, 0x55, 0x06, 0x09, 0x2a, 0x86,
139   0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31,
140   0x48, 0x1e, 0x46, 0x00, 0x47, 0x00, 0x6e, 0x00,
141   0x75, 0x00, 0x50, 0x00, 0x47, 0x00, 0x20, 0x00,
142   0x65, 0x00, 0x78, 0x00, 0x70, 0x00, 0x6f, 0x00,
143   0x72, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00,
144   0x20, 0x00, 0x63, 0x00, 0x65, 0x00, 0x72, 0x00,
145   0x74, 0x00, 0x69, 0x00, 0x66, 0x00, 0x69, 0x00,
146   0x63, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00,
147   0x20, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00,
148   0x66, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00,
149   0x66, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48,
150   0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16,
151   0x04, 0x14 }; /* Need to append SHA-1 digest. */
152 #define DATA_ATTRTEMPLATE_KEYID_OFF 73
153
154 struct buffer_s 
155 {
156   unsigned char *buffer;
157   size_t length;
158 };  
159
160
161 struct tag_info 
162 {
163   int class;
164   int is_constructed;
165   unsigned long tag;
166   unsigned long length;  /* length part of the TLV */
167   int nhdr;
168   int ndef;              /* It is an indefinite length */
169 };
170
171
172 /* Parse the buffer at the address BUFFER which is of SIZE and return
173    the tag and the length part from the TLV triplet.  Update BUFFER
174    and SIZE on success.  Checks that the encoded length does not
175    exhaust the length of the provided buffer. */
176 static int 
177 parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti)
178 {
179   int c;
180   unsigned long tag;
181   const unsigned char *buf = *buffer;
182   size_t length = *size;
183
184   ti->length = 0;
185   ti->ndef = 0;
186   ti->nhdr = 0;
187
188   /* Get the tag */
189   if (!length)
190     return -1; /* premature eof */
191   c = *buf++; length--;
192   ti->nhdr++;
193
194   ti->class = (c & 0xc0) >> 6;
195   ti->is_constructed = !!(c & 0x20);
196   tag = c & 0x1f;
197
198   if (tag == 0x1f)
199     {
200       tag = 0;
201       do
202         {
203           tag <<= 7;
204           if (!length)
205             return -1; /* premature eof */
206           c = *buf++; length--;
207           ti->nhdr++;
208           tag |= c & 0x7f;
209         }
210       while (c & 0x80);
211     }
212   ti->tag = tag;
213
214   /* Get the length */
215   if (!length)
216     return -1; /* prematureeof */
217   c = *buf++; length--;
218   ti->nhdr++;
219
220   if ( !(c & 0x80) )
221     ti->length = c;
222   else if (c == 0x80)
223     ti->ndef = 1;
224   else if (c == 0xff)
225     return -1; /* forbidden length value */
226   else
227     {
228       unsigned long len = 0;
229       int count = c & 0x7f;
230
231       for (; count; count--)
232         {
233           len <<= 8;
234           if (!length)
235             return -1; /* premature_eof */
236           c = *buf++; length--;
237           ti->nhdr++;
238           len |= c & 0xff;
239         }
240       ti->length = len;
241     }
242   
243   if (ti->class == UNIVERSAL && !ti->tag)
244     ti->length = 0;
245
246   if (ti->length > length)
247     return -1; /* data larger than buffer. */
248   
249   *buffer = buf;
250   *size = length;
251   return 0;
252 }
253
254
255 /* Given an ASN.1 chunk of a structure like:
256
257      24 NDEF:       OCTET STRING  -- This is not passed to us
258      04    1:         OCTET STRING  -- INPUT point s to here
259             :           30
260      04    1:         OCTET STRING
261             :           80
262           [...]
263      04    2:         OCTET STRING
264             :           00 00
265             :         } -- This denotes a Null tag and are the last 
266                         -- two bytes in INPUT.
267    
268    Create a new buffer with the content of that octet string.  INPUT
269    is the orginal buffer with a length as stored at LENGTH.  Returns
270    NULL on error or a new malloced buffer with the length of this new
271    buffer stored at LENGTH and the number of bytes parsed from input
272    are added to the value stored at INPUT_CONSUMED.  INPUT_CONSUMED is
273    allowed to be passed as NULL if the caller is not interested in
274    this value. */
275 static unsigned char *
276 cram_octet_string (const unsigned char *input, size_t *length,
277                    size_t *input_consumed)
278 {
279   const unsigned char *s = input;
280   size_t n = *length;
281   unsigned char *output, *d;
282   struct tag_info ti;
283
284   /* Allocate output buf.  We know that it won't be longer than the
285      input buffer. */
286   d = output = gcry_malloc (n);
287   if (!output)
288     goto bailout;
289
290   for (;;)
291     {
292       if (parse_tag (&s, &n, &ti))
293         goto bailout;
294       if (ti.class == UNIVERSAL && ti.tag == TAG_OCTET_STRING 
295           && !ti.ndef && !ti.is_constructed)
296         {
297           memcpy (d, s, ti.length);
298           s += ti.length;
299           d += ti.length;
300           n -= ti.length;
301         }
302       else if (ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed)
303         break; /* Ready */ 
304       else
305         goto bailout;
306     }
307
308
309   *length = d - output;
310   if (input_consumed)
311     *input_consumed += s - input;
312   return output;
313
314  bailout:
315   if (input_consumed)
316     *input_consumed += s - input;
317   gcry_free (output);
318   return NULL;
319 }
320
321
322
323 static int 
324 string_to_key (int id, char *salt, size_t saltlen, int iter, const char *pw,
325                int req_keylen, unsigned char *keybuf)
326 {
327   int rc, i, j;
328   gcry_md_hd_t md;
329   gcry_mpi_t num_b1 = NULL;
330   int pwlen;
331   unsigned char hash[20], buf_b[64], buf_i[128], *p;
332   size_t cur_keylen;
333   size_t n;
334
335   cur_keylen = 0;
336   pwlen = strlen (pw);
337   if (pwlen > 63/2)
338     {
339       log_error ("password too long\n");
340       return -1;
341     }
342
343   if (saltlen < 8)
344     {
345       log_error ("salt too short\n");
346       return -1;
347     }
348   
349   /* Store salt and password in BUF_I */
350   p = buf_i;
351   for(i=0; i < 64; i++)
352     *p++ = salt [i%saltlen];
353   for(i=j=0; i < 64; i += 2)
354     {
355       *p++ = 0;
356       *p++ = pw[j];
357       if (++j > pwlen) /* Note, that we include the trailing zero */
358         j = 0;
359     }
360
361   for (;;)
362     {
363       rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
364       if (rc)
365         {
366           log_error ( "gcry_md_open failed: %s\n", gpg_strerror (rc));
367           return rc;
368         }
369       for(i=0; i < 64; i++)
370         gcry_md_putc (md, id);
371       gcry_md_write (md, buf_i, 128);
372       memcpy (hash, gcry_md_read (md, 0), 20);
373       gcry_md_close (md);
374       for (i=1; i < iter; i++)
375         gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20);
376
377       for (i=0; i < 20 && cur_keylen < req_keylen; i++)
378         keybuf[cur_keylen++] = hash[i];
379       if (cur_keylen == req_keylen)
380         {
381           gcry_mpi_release (num_b1);
382           return 0; /* ready */
383         }
384       
385       /* need more bytes. */
386       for(i=0; i < 64; i++)
387         buf_b[i] = hash[i % 20];
388       rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, 64, &n);
389       if (rc)
390         {
391           log_error ( "gcry_mpi_scan failed: %s\n", gpg_strerror (rc));
392           return -1;
393         }
394       gcry_mpi_add_ui (num_b1, num_b1, 1);
395       for (i=0; i < 128; i += 64)
396         {
397           gcry_mpi_t num_ij;
398
399           rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, 64, &n);
400           if (rc)
401             {
402               log_error ( "gcry_mpi_scan failed: %s\n",
403                        gpg_strerror (rc));
404               return -1;
405             }
406           gcry_mpi_add (num_ij, num_ij, num_b1);
407           gcry_mpi_clear_highbit (num_ij, 64*8);
408           rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, 64, &n, num_ij);
409           if (rc)
410             {
411               log_error ( "gcry_mpi_print failed: %s\n",
412                           gpg_strerror (rc));
413               return -1;
414             }
415           gcry_mpi_release (num_ij);
416         }
417     }
418 }
419
420
421 static int 
422 set_key_iv (gcry_cipher_hd_t chd, char *salt, size_t saltlen, int iter,
423             const char *pw, int keybytes)
424 {
425   unsigned char keybuf[24];
426   int rc;
427
428   assert (keybytes == 5 || keybytes == 24);
429   if (string_to_key (1, salt, saltlen, iter, pw, keybytes, keybuf))
430     return -1;
431   rc = gcry_cipher_setkey (chd, keybuf, keybytes);
432   if (rc)
433     {
434       log_error ( "gcry_cipher_setkey failed: %s\n", gpg_strerror (rc));
435       return -1;
436     }
437
438   if (string_to_key (2, salt, saltlen, iter, pw, 8, keybuf))
439     return -1;
440   rc = gcry_cipher_setiv (chd, keybuf, 8);
441   if (rc)
442     {
443       log_error ("gcry_cipher_setiv failed: %s\n", gpg_strerror (rc));
444       return -1;
445     }
446   return 0;
447 }
448
449
450 static void
451 crypt_block (unsigned char *buffer, size_t length, char *salt, size_t saltlen,
452              int iter, const char *pw, int cipher_algo, int encrypt)
453 {
454   gcry_cipher_hd_t chd;
455   int rc;
456
457   rc = gcry_cipher_open (&chd, cipher_algo, GCRY_CIPHER_MODE_CBC, 0); 
458   if (rc)
459     {
460       log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(rc));
461       wipememory (buffer, length);
462       return;
463     }
464   if (set_key_iv (chd, salt, saltlen, iter, pw,
465                   cipher_algo == GCRY_CIPHER_RFC2268_40? 5:24))
466     {
467       wipememory (buffer, length);
468       goto leave;
469     }
470
471   rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0)
472               : gcry_cipher_decrypt (chd, buffer, length, NULL, 0);
473
474   if (rc)
475     {
476       wipememory (buffer, length);
477       log_error ( "en/de-crytion failed: %s\n", gpg_strerror (rc));
478       goto leave;
479     }
480
481  leave:
482   gcry_cipher_close (chd);
483 }
484   
485
486
487 /* Note: If R_RESULT is passed as NULL, a key object as already be
488    processed and thus we need to skip it here. */
489 static int
490 parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
491                           int startoffset, size_t *r_consumed, const char *pw,
492                           void (*certcb)(void*, const unsigned char*, size_t),
493                           void *certcbarg, gcry_mpi_t **r_result)
494 {
495   struct tag_info ti;
496   const unsigned char *p = buffer;
497   const unsigned char *p_start = buffer;
498   size_t n = length;
499   const char *where;
500   char salt[16];
501   size_t saltlen;
502   unsigned int iter;
503   unsigned char *plain = NULL;
504   int bad_pass = 0;
505   unsigned char *cram_buffer = NULL;
506   size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */
507   int is_3des = 0;
508   gcry_mpi_t *result = NULL;
509   int result_count;
510
511   if (r_result)
512     *r_result = NULL;
513   where = "start";
514   if (parse_tag (&p, &n, &ti))
515     goto bailout;
516   if (ti.class != CONTEXT || ti.tag)
517     goto bailout;
518   if (parse_tag (&p, &n, &ti))
519     goto bailout;
520   if (ti.tag != TAG_SEQUENCE)
521     goto bailout;
522
523   where = "bag.encryptedData.version";
524   if (parse_tag (&p, &n, &ti))
525     goto bailout;
526   if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 0)
527     goto bailout;
528   p++; n--;
529   if (parse_tag (&p, &n, &ti))
530     goto bailout;
531   if (ti.tag != TAG_SEQUENCE)
532     goto bailout;
533
534   where = "bag.encryptedData.data";
535   if (parse_tag (&p, &n, &ti))
536     goto bailout;
537   if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data)
538       || memcmp (p, oid_data, DIM(oid_data)))
539     goto bailout;
540   p += DIM(oid_data);
541   n -= DIM(oid_data);
542
543   where = "bag.encryptedData.keyinfo";
544   if (parse_tag (&p, &n, &ti))
545     goto bailout;
546   if (ti.class || ti.tag != TAG_SEQUENCE)
547     goto bailout;
548   if (parse_tag (&p, &n, &ti))
549     goto bailout;
550   if (!ti.class && ti.tag == TAG_OBJECT_ID 
551       && ti.length == DIM(oid_pbeWithSHAAnd40BitRC2_CBC)
552       && !memcmp (p, oid_pbeWithSHAAnd40BitRC2_CBC,
553                   DIM(oid_pbeWithSHAAnd40BitRC2_CBC)))
554     {
555       p += DIM(oid_pbeWithSHAAnd40BitRC2_CBC);
556       n -= DIM(oid_pbeWithSHAAnd40BitRC2_CBC);
557     }
558   else if (!ti.class && ti.tag == TAG_OBJECT_ID 
559       && ti.length == DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)
560       && !memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC,
561                   DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)))
562     {
563       p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
564       n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
565       is_3des = 1;
566     }
567   else
568     goto bailout;
569
570   where = "rc2or3des-params";
571   if (parse_tag (&p, &n, &ti))
572     goto bailout;
573   if (ti.class || ti.tag != TAG_SEQUENCE)
574     goto bailout;
575   if (parse_tag (&p, &n, &ti))
576     goto bailout;
577   if (ti.class || ti.tag != TAG_OCTET_STRING
578       || ti.length < 8 || ti.length > 16 )
579     goto bailout;
580   saltlen = ti.length;
581   memcpy (salt, p, saltlen);
582   p += saltlen;
583   n -= saltlen;
584   if (parse_tag (&p, &n, &ti))
585     goto bailout;
586   if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
587     goto bailout;
588   for (iter=0; ti.length; ti.length--)
589     {
590       iter <<= 8;
591       iter |= (*p++) & 0xff; 
592       n--;
593     }
594   
595   where = "rc2or3des-ciphertext";
596   if (parse_tag (&p, &n, &ti))
597     goto bailout;
598
599   consumed = p - p_start;
600   if (ti.class == CONTEXT && ti.tag == 0 && ti.is_constructed && ti.ndef)
601     {
602       /* Mozilla exported certs now come with single byte chunks of
603          octect strings.  (Mozilla Firefox 1.0.4).  Arghh. */
604       where = "cram-rc2or3des-ciphertext";
605       cram_buffer = cram_octet_string ( p, &n, &consumed);
606       if (!cram_buffer)
607         goto bailout;
608       p = p_start = cram_buffer;
609       if (r_consumed)
610         *r_consumed = consumed;
611       r_consumed = NULL; /* Ugly hack to not update that value any further. */
612       ti.length = n;
613     }
614   else if (ti.class == CONTEXT && ti.tag == 0 && ti.length )
615     ;
616   else
617     goto bailout;
618   
619   log_info ("%lu bytes of %s encrypted text\n",ti.length,is_3des?"3DES":"RC2");
620
621   plain = gcry_malloc_secure (ti.length);
622   if (!plain)
623     {
624       log_error ("error allocating decryption buffer\n");
625       goto bailout;
626     }
627   memcpy (plain, p, ti.length);
628   crypt_block (plain, ti.length, salt, saltlen,
629                iter, pw, 
630                is_3des? GCRY_CIPHER_3DES : GCRY_CIPHER_RFC2268_40, 
631                0);
632   n = ti.length;
633   startoffset = 0;
634   p_start = p = plain;
635
636 /*   { */
637 /* #  warning debug code is enabled */
638 /*     FILE *fp = fopen ("tmp-rc2-plain.der", "wb"); */
639 /*     if (!fp || fwrite (p, n, 1, fp) != 1) */
640 /*       exit (2); */
641 /*     fclose (fp); */
642 /*   } */
643
644   where = "outer.outer.seq";
645   if (parse_tag (&p, &n, &ti))
646     {
647       bad_pass = 1;
648       goto bailout;
649     }
650   if (ti.class || ti.tag != TAG_SEQUENCE)
651     {
652       bad_pass = 1;
653       goto bailout;
654     }
655
656   if (parse_tag (&p, &n, &ti))
657     {
658       bad_pass = 1;
659       goto bailout;
660     }
661
662   /* Loop over all certificates inside the bag. */
663   while (n)
664     {
665       int iscrlbag = 0;
666       int iskeybag = 0;
667
668       where = "certbag.nextcert";
669       if (ti.class || ti.tag != TAG_SEQUENCE)
670         goto bailout;
671
672       where = "certbag.objectidentifier";
673       if (parse_tag (&p, &n, &ti))
674         goto bailout;
675       if (ti.class || ti.tag != TAG_OBJECT_ID)
676         goto bailout;
677       if ( ti.length == DIM(oid_pkcs_12_CertBag)
678            && !memcmp (p, oid_pkcs_12_CertBag, DIM(oid_pkcs_12_CertBag)))
679         {
680           p += DIM(oid_pkcs_12_CertBag);
681           n -= DIM(oid_pkcs_12_CertBag);
682         }
683       else if ( ti.length == DIM(oid_pkcs_12_CrlBag)
684            && !memcmp (p, oid_pkcs_12_CrlBag, DIM(oid_pkcs_12_CrlBag)))
685         {
686           p += DIM(oid_pkcs_12_CrlBag);
687           n -= DIM(oid_pkcs_12_CrlBag);
688           iscrlbag = 1;
689         }
690       else if ( ti.length == DIM(oid_pkcs_12_keyBag)
691            && !memcmp (p, oid_pkcs_12_keyBag, DIM(oid_pkcs_12_keyBag)))
692         {
693           /* The TrustedMIME plugin for MS Outlook started to create
694              files with just one outer 3DES encrypted container and
695              inside the certificates as well as the key. */
696           p += DIM(oid_pkcs_12_keyBag);
697           n -= DIM(oid_pkcs_12_keyBag);
698           iskeybag = 1;
699         }
700       else
701         goto bailout;
702
703       where = "certbag.before.certheader";
704       if (parse_tag (&p, &n, &ti))
705         goto bailout;
706       if (ti.class != CONTEXT || ti.tag)
707         goto bailout;
708       if (iscrlbag)
709         {
710           log_info ("skipping unsupported crlBag\n");
711           p += ti.length;
712           n -= ti.length;
713         }
714       else if (iskeybag && (result || !r_result))
715         {
716           log_info ("one keyBag already processed; skipping this one\n");
717           p += ti.length;
718           n -= ti.length;
719         }
720       else if (iskeybag)
721         {
722           int len;
723
724           log_info ("processing simple keyBag\n");
725
726           /* Fixme: This code is duplicated from parse_bag_data.  */
727           if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
728             goto bailout;
729           if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER
730               || ti.length != 1 || *p)
731             goto bailout;
732           p++; n--;
733           if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
734             goto bailout;
735           len = ti.length;
736           if (parse_tag (&p, &n, &ti))
737             goto bailout;
738           if (len < ti.nhdr)
739             goto bailout;
740           len -= ti.nhdr;
741           if (ti.class || ti.tag != TAG_OBJECT_ID
742               || ti.length != DIM(oid_rsaEncryption)
743               || memcmp (p, oid_rsaEncryption,
744                          DIM(oid_rsaEncryption)))
745             goto bailout;
746           p += DIM (oid_rsaEncryption);
747           n -= DIM (oid_rsaEncryption);
748           if (len < ti.length)
749             goto bailout;
750           len -= ti.length;
751           if (n < len)
752             goto bailout;
753           p += len;
754           n -= len;
755           if ( parse_tag (&p, &n, &ti)
756                || ti.class || ti.tag != TAG_OCTET_STRING)
757             goto bailout;
758           if ( parse_tag (&p, &n, &ti)
759                || ti.class || ti.tag != TAG_SEQUENCE)
760             goto bailout;
761           len = ti.length;
762
763           result = gcry_calloc (10, sizeof *result);
764           if (!result)
765             {
766               log_error ( "error allocating result array\n");
767               goto bailout;
768             }
769           result_count = 0;
770
771           where = "reading.keybag.key-parameters";
772           for (result_count = 0; len && result_count < 9;)
773             {
774               if ( parse_tag (&p, &n, &ti)
775                    || ti.class || ti.tag != TAG_INTEGER)
776                 goto bailout;
777               if (len < ti.nhdr)
778                 goto bailout;
779               len -= ti.nhdr;
780               if (len < ti.length)
781                 goto bailout;
782               len -= ti.length;
783               if (!result_count && ti.length == 1 && !*p)
784                 ; /* ignore the very first one if it is a 0 */
785               else 
786                 {
787                   int rc;
788
789                   rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p,
790                                       ti.length, NULL);
791                   if (rc)
792                     {
793                       log_error ("error parsing key parameter: %s\n",
794                                  gpg_strerror (rc));
795                       goto bailout;
796                     }
797                   result_count++;
798                 }
799               p += ti.length;
800               n -= ti.length;
801             }
802           if (len)
803             goto bailout;
804         }
805       else
806         {
807           log_info ("processing certBag\n");
808           if (parse_tag (&p, &n, &ti))
809             goto bailout;
810           if (ti.class || ti.tag != TAG_SEQUENCE)
811             goto bailout;
812           if (parse_tag (&p, &n, &ti))
813             goto bailout;
814           if (ti.class || ti.tag != TAG_OBJECT_ID
815               || ti.length != DIM(oid_x509Certificate_for_pkcs_12)
816               || memcmp (p, oid_x509Certificate_for_pkcs_12,
817                          DIM(oid_x509Certificate_for_pkcs_12)))
818             goto bailout;
819           p += DIM(oid_x509Certificate_for_pkcs_12);
820           n -= DIM(oid_x509Certificate_for_pkcs_12);
821           
822           where = "certbag.before.octetstring";
823           if (parse_tag (&p, &n, &ti))
824             goto bailout;
825           if (ti.class != CONTEXT || ti.tag)
826             goto bailout;
827           if (parse_tag (&p, &n, &ti))
828             goto bailout;
829           if (ti.class || ti.tag != TAG_OCTET_STRING || ti.ndef)
830             goto bailout;
831           
832           /* Return the certificate. */
833           if (certcb)
834             certcb (certcbarg, p, ti.length);
835    
836           p += ti.length;
837           n -= ti.length;
838         }
839
840       /* Ugly hack to cope with the padding: Forget about the rest if
841          that is less or equal to the cipher's block length.  We can
842          reasonable assume that all valid data will be longer than
843          just one block. */
844       if (n <= 8)
845         n = 0;  
846
847       /* Skip the optional SET with the pkcs12 cert attributes. */
848       if (n)
849         {
850           where = "bag.attributes";
851           if (parse_tag (&p, &n, &ti))
852             goto bailout;
853           if (!ti.class && ti.tag == TAG_SEQUENCE)
854             ; /* No attributes. */
855           else if (!ti.class && ti.tag == TAG_SET && !ti.ndef)
856             { /* The optional SET. */
857               p += ti.length;
858               n -= ti.length;
859               if (n <= 8)
860                 n = 0;
861               if (n && parse_tag (&p, &n, &ti))
862                 goto bailout;
863             }
864           else
865             goto bailout;
866         }
867     }
868   
869   if (r_consumed)
870     *r_consumed = consumed;
871   gcry_free (plain);
872   gcry_free (cram_buffer);
873   if (r_result)
874     *r_result = result;
875   return 0;
876
877  bailout:
878   if (result)
879     {
880       int i;
881
882       for (i=0; result[i]; i++)
883         gcry_mpi_release (result[i]);
884       gcry_free (result);
885     }
886   if (r_consumed)
887     *r_consumed = consumed;
888   gcry_free (plain);
889   gcry_free (cram_buffer);
890   log_error ("encryptedData error at \"%s\", offset %u\n",
891              where, (p - p_start)+startoffset);
892   if (bad_pass)
893     {
894       /* Note, that the following string might be used by other programs
895          to check for a bad passphrase; it should therefore not be
896          translated or changed. */
897       log_error ("possibly bad passphrase given\n");
898     }
899   return -1;
900 }
901
902 static gcry_mpi_t *
903 parse_bag_data (const unsigned char *buffer, size_t length, int startoffset,
904                 size_t *r_consumed, const char *pw)
905 {
906   int rc;
907   struct tag_info ti;
908   const unsigned char *p = buffer;
909   const unsigned char *p_start = buffer;
910   size_t n = length;
911   const char *where;
912   char salt[16];
913   size_t saltlen;
914   unsigned int iter;
915   int len;
916   unsigned char *plain = NULL;
917   gcry_mpi_t *result = NULL;
918   int result_count, i;
919   unsigned char *cram_buffer = NULL;
920   size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */
921
922   where = "start";
923   if (parse_tag (&p, &n, &ti))
924     goto bailout;
925   if (ti.class != CONTEXT || ti.tag)
926     goto bailout;
927   if (parse_tag (&p, &n, &ti))
928     goto bailout;
929   if (ti.class || ti.tag != TAG_OCTET_STRING)
930     goto bailout;
931
932   consumed = p - p_start;
933   if (ti.is_constructed && ti.ndef)
934     {
935       /* Mozilla exported certs now come with single byte chunks of
936          octect strings.  (Mozilla Firefox 1.0.4).  Arghh. */
937       where = "cram-data.outersegs";
938       cram_buffer = cram_octet_string ( p, &n, &consumed);
939       if (!cram_buffer)
940         goto bailout;
941       p = p_start = cram_buffer;
942       if (r_consumed)
943         *r_consumed = consumed;
944       r_consumed = NULL; /* Ugly hack to not update that value any further. */
945     }
946   
947
948   where = "data.outerseqs";
949   if (parse_tag (&p, &n, &ti))
950     goto bailout;
951   if (ti.class || ti.tag != TAG_SEQUENCE)
952     goto bailout;
953   if (parse_tag (&p, &n, &ti))
954     goto bailout;
955   if (ti.class || ti.tag != TAG_SEQUENCE)
956     goto bailout;
957
958   where = "data.objectidentifier";
959   if (parse_tag (&p, &n, &ti))
960     goto bailout;
961   if (ti.class || ti.tag != TAG_OBJECT_ID
962       || ti.length != DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag)
963       || memcmp (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
964                  DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag)))
965     goto bailout;
966   p += DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag);
967   n -= DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag);
968
969   where = "shrouded,outerseqs";
970   if (parse_tag (&p, &n, &ti))
971     goto bailout;
972   if (ti.class != CONTEXT || ti.tag)
973     goto bailout;
974   if (parse_tag (&p, &n, &ti))
975     goto bailout;
976   if (ti.class || ti.tag != TAG_SEQUENCE)
977     goto bailout;
978   if (parse_tag (&p, &n, &ti))
979     goto bailout;
980   if (ti.class || ti.tag != TAG_SEQUENCE)
981     goto bailout;
982   if (parse_tag (&p, &n, &ti))
983     goto bailout;
984   if (ti.class || ti.tag != TAG_OBJECT_ID
985       || ti.length != DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)
986       || memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC,
987                  DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)))
988     goto bailout;
989   p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
990   n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
991
992   where = "3des-params";
993   if (parse_tag (&p, &n, &ti))
994     goto bailout;
995   if (ti.class || ti.tag != TAG_SEQUENCE)
996     goto bailout;
997   if (parse_tag (&p, &n, &ti))
998     goto bailout;
999   if (ti.class || ti.tag != TAG_OCTET_STRING
1000       || ti.length < 8 || ti.length > 16)
1001     goto bailout;
1002   saltlen = ti.length;
1003   memcpy (salt, p, saltlen);
1004   p += saltlen;
1005   n -= saltlen;
1006   if (parse_tag (&p, &n, &ti))
1007     goto bailout;
1008   if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
1009     goto bailout;
1010   for (iter=0; ti.length; ti.length--)
1011     {
1012       iter <<= 8;
1013       iter |= (*p++) & 0xff; 
1014       n--;
1015     }
1016   
1017   where = "3des-ciphertext";
1018   if (parse_tag (&p, &n, &ti))
1019     goto bailout;
1020   if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length )
1021     goto bailout;
1022   
1023   log_info ("%lu bytes of 3DES encrypted text\n", ti.length);
1024   
1025   plain = gcry_malloc_secure (ti.length);
1026   if (!plain)
1027     {
1028       log_error ("error allocating decryption buffer\n");
1029       goto bailout;
1030     }
1031   memcpy (plain, p, ti.length);
1032   consumed += p - p_start + ti.length;
1033   crypt_block (plain, ti.length, salt, saltlen, iter, pw, GCRY_CIPHER_3DES, 0);
1034   n = ti.length;
1035   startoffset = 0;
1036   p_start = p = plain;
1037
1038 /*   { */
1039 /* #  warning debug code is enabled */
1040 /*     FILE *fp = fopen ("tmp-rc2-plain-key.der", "wb"); */
1041 /*     if (!fp || fwrite (p, n, 1, fp) != 1) */
1042 /*       exit (2); */
1043 /*     fclose (fp); */
1044 /*   } */
1045
1046
1047   where = "decrypted-text";
1048   if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
1049     goto bailout;
1050   if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER
1051       || ti.length != 1 || *p)
1052     goto bailout;
1053   p++; n--;
1054   if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
1055     goto bailout;
1056   len = ti.length;
1057   if (parse_tag (&p, &n, &ti))
1058     goto bailout;
1059   if (len < ti.nhdr)
1060     goto bailout;
1061   len -= ti.nhdr;
1062   if (ti.class || ti.tag != TAG_OBJECT_ID
1063       || ti.length != DIM(oid_rsaEncryption)
1064       || memcmp (p, oid_rsaEncryption,
1065                  DIM(oid_rsaEncryption)))
1066     goto bailout;
1067   p += DIM (oid_rsaEncryption);
1068   n -= DIM (oid_rsaEncryption);
1069   if (len < ti.length)
1070     goto bailout;
1071   len -= ti.length;
1072   if (n < len)
1073     goto bailout;
1074   p += len;
1075   n -= len;
1076   if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_OCTET_STRING)
1077     goto bailout;
1078   if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
1079     goto bailout;
1080   len = ti.length;
1081
1082   result = gcry_calloc (10, sizeof *result);
1083   if (!result)
1084     {
1085       log_error ( "error allocating result array\n");
1086       goto bailout;
1087     }
1088   result_count = 0;
1089
1090   where = "reading.key-parameters";
1091   for (result_count=0; len && result_count < 9;)
1092     {
1093       if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER)
1094         goto bailout;
1095       if (len < ti.nhdr)
1096         goto bailout;
1097       len -= ti.nhdr;
1098       if (len < ti.length)
1099         goto bailout;
1100       len -= ti.length;
1101       if (!result_count && ti.length == 1 && !*p)
1102         ; /* ignore the very first one if it is a 0 */
1103       else 
1104         {
1105           rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p,
1106                               ti.length, NULL);
1107           if (rc)
1108             {
1109               log_error ("error parsing key parameter: %s\n",
1110                          gpg_strerror (rc));
1111               goto bailout;
1112             }
1113           result_count++;
1114         }
1115       p += ti.length;
1116       n -= ti.length;
1117     }
1118   if (len)
1119     goto bailout;
1120
1121   gcry_free (cram_buffer);
1122   if (r_consumed)
1123     *r_consumed = consumed;
1124   return result;
1125
1126  bailout:
1127   gcry_free (plain);
1128   if (result)
1129     {
1130       for (i=0; result[i]; i++)
1131         gcry_mpi_release (result[i]);
1132       gcry_free (result);
1133     }
1134   gcry_free (cram_buffer);
1135   log_error ( "data error at \"%s\", offset %u\n",
1136               where, (p - buffer) + startoffset);
1137   if (r_consumed)
1138     *r_consumed = consumed;
1139   return NULL;
1140 }
1141
1142
1143 /* Parse a PKCS12 object and return an array of MPI representing the
1144    secret key parameters.  This is a very limited implementation in
1145    that it is only able to look for 3DES encoded encryptedData and
1146    tries to extract the first private key object it finds.  In case of
1147    an error NULL is returned. CERTCB and CERRTCBARG are used to pass
1148    X.509 certificates back to the caller. */
1149 gcry_mpi_t *
1150 p12_parse (const unsigned char *buffer, size_t length, const char *pw,
1151            void (*certcb)(void*, const unsigned char*, size_t),
1152            void *certcbarg)
1153 {
1154   struct tag_info ti;
1155   const unsigned char *p = buffer;
1156   const unsigned char *p_start = buffer;
1157   size_t n = length;
1158   const char *where;
1159   int bagseqlength, len;
1160   int bagseqndef, lenndef;
1161   gcry_mpi_t *result = NULL;
1162   unsigned char *cram_buffer = NULL;
1163
1164   where = "pfx";
1165   if (parse_tag (&p, &n, &ti))
1166     goto bailout;
1167   if (ti.tag != TAG_SEQUENCE)
1168     goto bailout;
1169
1170   where = "pfxVersion";
1171   if (parse_tag (&p, &n, &ti))
1172     goto bailout;
1173   if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 3)
1174     goto bailout;
1175   p++; n--;
1176   
1177   where = "authSave";
1178   if (parse_tag (&p, &n, &ti))
1179     goto bailout;
1180   if (ti.tag != TAG_SEQUENCE)
1181     goto bailout;
1182   if (parse_tag (&p, &n, &ti))
1183     goto bailout;
1184   if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data)
1185       || memcmp (p, oid_data, DIM(oid_data)))
1186     goto bailout;
1187   p += DIM(oid_data);
1188   n -= DIM(oid_data);
1189
1190   if (parse_tag (&p, &n, &ti))
1191     goto bailout;
1192   if (ti.class != CONTEXT || ti.tag)
1193     goto bailout;
1194   if (parse_tag (&p, &n, &ti))
1195     goto bailout;
1196   if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING)
1197     goto bailout;
1198
1199   if (ti.is_constructed && ti.ndef)
1200     {
1201       /* Mozilla exported certs now come with single byte chunks of
1202          octect strings.  (Mozilla Firefox 1.0.4).  Arghh. */
1203       where = "cram-bags";
1204       cram_buffer = cram_octet_string ( p, &n, NULL);
1205       if (!cram_buffer)
1206         goto bailout;
1207       p = p_start = cram_buffer;
1208     }
1209
1210   where = "bags";
1211   if (parse_tag (&p, &n, &ti))
1212     goto bailout;
1213   if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
1214     goto bailout;
1215   bagseqndef = ti.ndef;
1216   bagseqlength = ti.length;
1217   while (bagseqlength || bagseqndef)
1218     {
1219 /*       log_debug ( "at offset %u\n", (p - p_start)); */
1220       where = "bag-sequence";
1221       if (parse_tag (&p, &n, &ti))
1222         goto bailout;
1223       if (bagseqndef && ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed)
1224         break; /* Ready */ 
1225       if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
1226         goto bailout;
1227
1228       if (!bagseqndef)
1229         {
1230           if (bagseqlength < ti.nhdr)
1231             goto bailout;
1232           bagseqlength -= ti.nhdr;
1233           if (bagseqlength < ti.length)
1234             goto bailout;
1235           bagseqlength -= ti.length;
1236         }
1237       lenndef = ti.ndef;
1238       len = ti.length;
1239
1240       if (parse_tag (&p, &n, &ti))
1241         goto bailout;
1242       if (lenndef)
1243         len = ti.nhdr; 
1244       else
1245         len -= ti.nhdr; 
1246
1247       if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData)
1248           && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData)))
1249         {
1250           size_t consumed = 0;
1251
1252           p += DIM(oid_encryptedData);
1253           n -= DIM(oid_encryptedData);
1254           if (!lenndef)
1255             len -= DIM(oid_encryptedData);
1256           where = "bag.encryptedData";
1257           if (parse_bag_encrypted_data (p, n, (p - p_start), &consumed, pw,
1258                                         certcb, certcbarg,
1259                                         result? NULL : &result))
1260             goto bailout;
1261           if (lenndef)
1262             len += consumed;
1263         }
1264       else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
1265                && !memcmp (p, oid_data, DIM(oid_data)))
1266         {
1267           if (result)
1268             {
1269               log_info ("already got an key object, skipping this one\n");
1270               p += ti.length;
1271               n -= ti.length;
1272             }
1273           else
1274             {
1275               size_t consumed = 0;
1276
1277               p += DIM(oid_data);
1278               n -= DIM(oid_data);
1279               if (!lenndef)
1280                 len -= DIM(oid_data);
1281               result = parse_bag_data (p, n, (p - p_start), &consumed, pw);
1282               if (!result)
1283                 goto bailout;
1284               if (lenndef)
1285                 len += consumed;
1286             }
1287         }
1288       else
1289         {
1290           log_info ("unknown bag type - skipped\n");
1291           p += ti.length;
1292           n -= ti.length;
1293         }
1294
1295       if (len < 0 || len > n)
1296         goto bailout;
1297       p += len;
1298       n -= len;
1299       if (lenndef)
1300         {
1301           /* Need to skip the Null Tag. */
1302           if (parse_tag (&p, &n, &ti))
1303             goto bailout;
1304           if (!(ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed))
1305             goto bailout;
1306         }
1307     }
1308   
1309   gcry_free (cram_buffer);
1310   return result;
1311  bailout:
1312   log_error ("error at \"%s\", offset %u\n", where, (p - p_start));
1313   if (result)
1314     {
1315       int i;
1316
1317       for (i=0; result[i]; i++)
1318         gcry_mpi_release (result[i]);
1319       gcry_free (result);
1320     }
1321   gcry_free (cram_buffer);
1322   return NULL;
1323 }
1324
1325
1326 \f
1327 static size_t
1328 compute_tag_length (size_t n)
1329 {     
1330   int needed = 0;
1331
1332   if (n < 128)
1333     needed += 2; /* tag and one length byte */
1334   else if (n < 256)
1335     needed += 3; /* tag, number of length bytes, 1 length byte */
1336   else if (n < 65536)
1337     needed += 4; /* tag, number of length bytes, 2 length bytes */
1338   else
1339     {
1340       log_error ("object too larger to encode\n");
1341       return 0;
1342     }
1343   return needed;
1344 }
1345
1346 static unsigned char *
1347 store_tag_length (unsigned char *p, int tag, size_t n)
1348 {     
1349   if (tag == TAG_SEQUENCE)
1350     tag |= 0x20; /* constructed */
1351
1352   *p++ = tag;
1353   if (n < 128)
1354     *p++ = n;
1355   else if (n < 256)
1356     {
1357       *p++ = 0x81;
1358       *p++ = n;
1359     }
1360   else if (n < 65536)
1361     {
1362       *p++ = 0x82;
1363       *p++ = n >> 8;
1364       *p++ = n;
1365     }
1366
1367   return p;
1368 }
1369
1370
1371 /* Create the final PKCS-12 object from the sequences contained in
1372    SEQLIST.  PW is the password. That array is terminated with an NULL
1373    object. */
1374 static unsigned char *
1375 create_final (struct buffer_s *sequences, const char *pw, size_t *r_length)
1376 {
1377   int i;
1378   size_t needed = 0;
1379   size_t len[8], n;
1380   unsigned char *macstart;
1381   size_t maclen;
1382   unsigned char *result, *p;
1383   size_t resultlen;
1384   char salt[8];
1385   unsigned char keybuf[20];
1386   gcry_md_hd_t md;
1387   int rc;
1388   int with_mac = 1;
1389
1390
1391   /* 9 steps to create the pkcs#12 Krampf. */
1392
1393   /* 8. The MAC. */
1394   /* We add this at step 0. */
1395
1396   /* 7. All the buffers. */
1397   for (i=0; sequences[i].buffer; i++)
1398     needed += sequences[i].length;
1399
1400   /* 6. This goes into a sequences. */
1401   len[6] = needed;
1402   n = compute_tag_length (needed);
1403   needed += n;
1404
1405   /* 5. Encapsulate all in an octet string. */
1406   len[5] = needed;
1407   n = compute_tag_length (needed);
1408   needed += n;
1409
1410   /* 4. And tag it with [0]. */
1411   len[4] = needed;
1412   n = compute_tag_length (needed);
1413   needed += n;
1414
1415   /* 3. Prepend an data OID. */
1416   needed += 2 + DIM (oid_data);
1417
1418   /* 2. Put all into a sequences. */
1419   len[2] = needed;
1420   n = compute_tag_length (needed);
1421   needed += n;
1422
1423   /* 1. Prepend the version integer 3. */
1424   needed += 3;
1425
1426   /* 0. And the final outer sequence. */
1427   if (with_mac)
1428     needed += DIM (data_mactemplate);
1429   len[0] = needed;
1430   n = compute_tag_length (needed);
1431   needed += n;
1432
1433   /* Allocate a buffer. */
1434   result = gcry_malloc (needed);
1435   if (!result)
1436     {
1437       log_error ("error allocating buffer\n");
1438       return NULL;
1439     }
1440   p = result;
1441
1442   /* 0. Store the very outer sequence. */
1443   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1444
1445   /* 1. Store the version integer 3. */
1446   *p++ = TAG_INTEGER;
1447   *p++ = 1; 
1448   *p++ = 3;
1449
1450   /* 2. Store another sequence. */
1451   p = store_tag_length (p, TAG_SEQUENCE, len[2]);
1452
1453   /* 3. Store the data OID. */
1454   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
1455   memcpy (p, oid_data, DIM (oid_data)); 
1456   p += DIM (oid_data); 
1457
1458   /* 4. Next comes a context tag. */
1459   p = store_tag_length (p, 0xa0, len[4]);
1460
1461   /* 5. And an octet string. */
1462   p = store_tag_length (p, TAG_OCTET_STRING, len[5]);
1463
1464   /* 6. And the inner sequence. */
1465   macstart = p;
1466   p = store_tag_length (p, TAG_SEQUENCE, len[6]);
1467
1468   /* 7. Append all the buffers. */
1469   for (i=0; sequences[i].buffer; i++)
1470     {
1471       memcpy (p, sequences[i].buffer, sequences[i].length);
1472       p += sequences[i].length;
1473     }
1474
1475   if (with_mac)
1476     {
1477       /* Intermezzo to compute the MAC. */
1478       maclen = p - macstart;
1479       gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
1480       if (string_to_key (3, salt, 8, 2048, pw, 20, keybuf))
1481         {
1482           gcry_free (result);
1483           return NULL;
1484         }
1485       rc = gcry_md_open (&md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
1486       if (rc)
1487         {
1488           log_error ("gcry_md_open failed: %s\n", gpg_strerror (rc));
1489           gcry_free (result);
1490           return NULL;
1491         }
1492       rc = gcry_md_setkey (md, keybuf, 20);
1493       if (rc)
1494         {
1495           log_error ("gcry_md_setkey failed: %s\n", gpg_strerror (rc));
1496           gcry_md_close (md);
1497           gcry_free (result);
1498           return NULL;
1499         }
1500       gcry_md_write (md, macstart, maclen);
1501
1502       /* 8. Append the MAC template and fix it up. */
1503       memcpy (p, data_mactemplate, DIM (data_mactemplate));
1504       memcpy (p + DATA_MACTEMPLATE_SALT_OFF, salt, 8);
1505       memcpy (p + DATA_MACTEMPLATE_MAC_OFF, gcry_md_read (md, 0), 20);
1506       p += DIM (data_mactemplate);
1507       gcry_md_close (md);
1508     }
1509
1510   /* Ready. */
1511   resultlen = p - result;
1512   if (needed != resultlen)
1513     log_debug ("length mismatch: %lu, %lu\n",
1514                (unsigned long)needed, (unsigned long)resultlen);
1515
1516   *r_length = resultlen;
1517   return result;
1518 }
1519
1520
1521 /* Build a DER encoded SEQUENCE with the key:
1522
1523    SEQUENCE {
1524      INTEGER 0
1525      SEQUENCE {
1526        OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
1527        NULL
1528        }
1529      OCTET STRING, encapsulates {
1530        SEQUENCE {
1531          INTEGER 0
1532          INTEGER
1533          INTEGER 
1534          INTEGER
1535          INTEGER
1536          INTEGER
1537          INTEGER
1538          INTEGER
1539          INTEGER
1540          }
1541        }
1542      }
1543 */  
1544   
1545 static unsigned char * 
1546 build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
1547 {
1548   int rc, i;
1549   size_t needed, n;
1550   unsigned char *plain, *p;
1551   size_t plainlen;
1552   size_t outseqlen, oidseqlen, octstrlen, inseqlen;
1553
1554   needed = 3; /* The version(?) integer of value 0. */
1555   for (i=0; kparms[i]; i++)
1556     {
1557       n = 0;
1558       rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
1559       if (rc)
1560         {
1561           log_error ("error formatting parameter: %s\n", gpg_strerror (rc));
1562           return NULL;
1563         }
1564       needed += n;
1565       n = compute_tag_length (n);
1566       if (!n)
1567         return NULL;
1568       needed += n;
1569     }
1570   if (i != 8)
1571     {
1572       log_error ("invalid paramters for p12_build\n");
1573       return NULL;
1574     }
1575   /* Now this all goes into a sequence. */
1576   inseqlen = needed;
1577   n = compute_tag_length (needed);
1578   if (!n)
1579     return NULL;
1580   needed += n;
1581   /* Encapsulate all into an octet string. */
1582   octstrlen = needed;
1583   n = compute_tag_length (needed);
1584   if (!n)
1585     return NULL;
1586   needed += n;
1587   /* Prepend the object identifier sequence. */
1588   oidseqlen = 2 + DIM (oid_rsaEncryption) + 2;
1589   needed += 2 + oidseqlen;
1590   /* The version number. */
1591   needed += 3;
1592   /* And finally put the whole thing into a sequence. */
1593   outseqlen = needed;
1594   n = compute_tag_length (needed);
1595   if (!n)
1596     return NULL;
1597   needed += n;
1598   
1599   /* allocate 8 extra bytes for padding */
1600   plain = gcry_malloc_secure (needed+8);
1601   if (!plain)
1602     {
1603       log_error ("error allocating encryption buffer\n");
1604       return NULL;
1605     }
1606   
1607   /* And now fill the plaintext buffer. */
1608   p = plain;
1609   p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
1610   /* Store version. */
1611   *p++ = TAG_INTEGER;
1612   *p++ = 1;
1613   *p++ = 0;
1614   /* Store object identifier sequence. */
1615   p = store_tag_length (p, TAG_SEQUENCE, oidseqlen);
1616   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption));
1617   memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption)); 
1618   p += DIM (oid_rsaEncryption); 
1619   *p++ = TAG_NULL;
1620   *p++ = 0;
1621   /* Start with the octet string. */
1622   p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
1623   p = store_tag_length (p, TAG_SEQUENCE, inseqlen);
1624   /* Store the key parameters. */
1625   *p++ = TAG_INTEGER;
1626   *p++ = 1;
1627   *p++ = 0;
1628   for (i=0; kparms[i]; i++)
1629     {
1630       n = 0;
1631       rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
1632       if (rc)
1633         {
1634           log_error ("oops: error formatting parameter: %s\n",
1635                      gpg_strerror (rc));
1636           gcry_free (plain);
1637           return NULL;
1638         }
1639       p = store_tag_length (p, TAG_INTEGER, n);
1640       
1641       n = plain + needed - p;
1642       rc = gcry_mpi_print (GCRYMPI_FMT_STD, p, n, &n, kparms[i]);
1643       if (rc)
1644         {
1645           log_error ("oops: error storing parameter: %s\n",
1646                      gpg_strerror (rc));
1647           gcry_free (plain);
1648           return NULL;
1649         }
1650       p += n;
1651     }
1652
1653   plainlen = p - plain;
1654   assert (needed == plainlen);
1655   /* Append some pad characters; we already allocated extra space. */
1656   n = 8 - plainlen % 8;
1657   for (i=0; i < n; i++, plainlen++)
1658     *p++ = n;
1659
1660   *r_length = plainlen;
1661   return plain;
1662 }
1663
1664
1665
1666 static unsigned char *
1667 build_key_bag (unsigned char *buffer, size_t buflen, char *salt,
1668                const unsigned char *sha1hash, const char *keyidstr,
1669                size_t *r_length)
1670 {
1671   size_t len[11], needed;
1672   unsigned char *p, *keybag;
1673   size_t keybaglen;
1674
1675   /* Walk 11 steps down to collect the info: */
1676
1677   /* 10. The data goes into an octet string. */
1678   needed = compute_tag_length (buflen);
1679   needed += buflen;
1680
1681   /* 9. Prepend the algorithm identifier. */
1682   needed += DIM (data_3desiter2048);
1683
1684   /* 8. Put a sequence around. */
1685   len[8] = needed;
1686   needed += compute_tag_length (needed);
1687
1688   /* 7. Prepend a [0] tag. */
1689   len[7] = needed;
1690   needed += compute_tag_length (needed);
1691
1692   /* 6b. The attributes which are appended at the end. */
1693   if (sha1hash)
1694     needed += DIM (data_attrtemplate) + 20;
1695
1696   /* 6. Prepend the shroudedKeyBag OID. */
1697   needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag);
1698
1699   /* 5+4. Put all into two sequences. */
1700   len[5] = needed;
1701   needed += compute_tag_length ( needed);
1702   len[4] = needed;
1703   needed += compute_tag_length (needed);
1704
1705   /* 3. This all goes into an octet string. */
1706   len[3] = needed;
1707   needed += compute_tag_length (needed);
1708
1709   /* 2. Prepend another [0] tag. */
1710   len[2] = needed;
1711   needed += compute_tag_length (needed);
1712
1713   /* 1. Prepend the data OID. */
1714   needed += 2 + DIM (oid_data);
1715
1716   /* 0. Prepend another sequence. */
1717   len[0] = needed;
1718   needed += compute_tag_length (needed);
1719
1720   /* Now that we have all length information, allocate a buffer. */
1721   p = keybag = gcry_malloc (needed);
1722   if (!keybag)
1723     {
1724       log_error ("error allocating buffer\n");
1725       return NULL;
1726     }
1727
1728   /* Walk 11 steps up to store the data. */
1729
1730   /* 0. Store the first sequence. */
1731   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1732
1733   /* 1. Store the data OID. */
1734   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
1735   memcpy (p, oid_data, DIM (oid_data)); 
1736   p += DIM (oid_data); 
1737
1738   /* 2. Store a [0] tag. */
1739   p = store_tag_length (p, 0xa0, len[2]);
1740
1741   /* 3. And an octet string. */
1742   p = store_tag_length (p, TAG_OCTET_STRING, len[3]);
1743
1744   /* 4+5. Two sequences. */
1745   p = store_tag_length (p, TAG_SEQUENCE, len[4]);
1746   p = store_tag_length (p, TAG_SEQUENCE, len[5]);
1747
1748   /* 6. Store the shroudedKeyBag OID. */
1749   p = store_tag_length (p, TAG_OBJECT_ID,
1750                         DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag));
1751   memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
1752           DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); 
1753   p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); 
1754
1755   /* 7. Store a [0] tag. */
1756   p = store_tag_length (p, 0xa0, len[7]);
1757
1758   /* 8. Store a sequence. */
1759   p = store_tag_length (p, TAG_SEQUENCE, len[8]);
1760
1761   /* 9. Now for the pre-encoded algorithm identifier and the salt. */
1762   memcpy (p, data_3desiter2048, DIM (data_3desiter2048));
1763   memcpy (p + DATA_3DESITER2048_SALT_OFF, salt, 8);
1764   p += DIM (data_3desiter2048);
1765
1766   /* 10. And the octet string with the encrypted data. */
1767   p = store_tag_length (p, TAG_OCTET_STRING, buflen);
1768   memcpy (p, buffer, buflen);
1769   p += buflen;
1770
1771   /* Append the attributes whose length we calculated at step 2b. */
1772   if (sha1hash)
1773     {
1774       int i;
1775
1776       memcpy (p, data_attrtemplate, DIM (data_attrtemplate));
1777       for (i=0; i < 8; i++)
1778         p[DATA_ATTRTEMPLATE_KEYID_OFF+2*i+1] = keyidstr[i];
1779       p += DIM (data_attrtemplate);
1780       memcpy (p, sha1hash, 20);
1781       p += 20;
1782     }
1783
1784
1785   keybaglen = p - keybag;
1786   if (needed != keybaglen)
1787     log_debug ("length mismatch: %lu, %lu\n",
1788                (unsigned long)needed, (unsigned long)keybaglen);
1789   
1790   *r_length = keybaglen;
1791   return keybag;
1792 }
1793
1794
1795 static unsigned char *
1796 build_cert_bag (unsigned char *buffer, size_t buflen, char *salt,
1797                 size_t *r_length)
1798 {
1799   size_t len[9], needed;
1800   unsigned char *p, *certbag;
1801   size_t certbaglen;
1802
1803   /* Walk 9 steps down to collect the info: */
1804
1805   /* 8. The data goes into an octet string. */
1806   needed = compute_tag_length (buflen);
1807   needed += buflen;
1808
1809   /* 7. The algorithm identifier. */
1810   needed += DIM (data_rc2iter2048);
1811
1812   /* 6. The data OID. */
1813   needed += 2 + DIM (oid_data);
1814
1815   /* 5. A sequence. */
1816   len[5] = needed;
1817   needed += compute_tag_length ( needed);
1818
1819   /* 4. An integer. */
1820   needed += 3;
1821
1822   /* 3. A sequence. */
1823   len[3] = needed;
1824   needed += compute_tag_length (needed);
1825
1826   /* 2.  A [0] tag. */
1827   len[2] = needed;
1828   needed += compute_tag_length (needed);
1829
1830   /* 1. The encryptedData OID. */
1831   needed += 2 + DIM (oid_encryptedData);
1832
1833   /* 0. The first sequence. */
1834   len[0] = needed;
1835   needed += compute_tag_length (needed);
1836
1837   /* Now that we have all length information, allocate a buffer. */
1838   p = certbag = gcry_malloc (needed);
1839   if (!certbag)
1840     {
1841       log_error ("error allocating buffer\n");
1842       return NULL;
1843     }
1844
1845   /* Walk 9 steps up to store the data. */
1846
1847   /* 0. Store the first sequence. */
1848   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1849
1850   /* 1. Store the encryptedData OID. */
1851   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_encryptedData));
1852   memcpy (p, oid_encryptedData, DIM (oid_encryptedData)); 
1853   p += DIM (oid_encryptedData); 
1854
1855   /* 2. Store a [0] tag. */
1856   p = store_tag_length (p, 0xa0, len[2]);
1857
1858   /* 3. Store a sequence. */
1859   p = store_tag_length (p, TAG_SEQUENCE, len[3]);
1860
1861   /* 4. Store the integer 0. */
1862   *p++ = TAG_INTEGER;
1863   *p++ = 1; 
1864   *p++ = 0;
1865
1866   /* 5. Store a sequence. */
1867   p = store_tag_length (p, TAG_SEQUENCE, len[5]);
1868
1869   /* 6. Store the data OID. */
1870   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
1871   memcpy (p, oid_data, DIM (oid_data)); 
1872   p += DIM (oid_data); 
1873
1874   /* 7. Now for the pre-encoded algorithm identifier and the salt. */
1875   memcpy (p, data_rc2iter2048, DIM (data_rc2iter2048));
1876   memcpy (p + DATA_RC2ITER2048_SALT_OFF, salt, 8);
1877   p += DIM (data_rc2iter2048);
1878
1879   /* 8. And finally the [0] tag with the encrypted data. */
1880   p = store_tag_length (p, 0x80, buflen);
1881   memcpy (p, buffer, buflen);
1882   p += buflen;
1883   certbaglen = p - certbag;
1884   
1885   if (needed != certbaglen)
1886     log_debug ("length mismatch: %lu, %lu\n",
1887                (unsigned long)needed, (unsigned long)certbaglen);
1888
1889   *r_length = certbaglen;
1890   return certbag;
1891 }
1892
1893
1894 static unsigned char *
1895 build_cert_sequence (unsigned char *buffer, size_t buflen, 
1896                      const unsigned char *sha1hash, const char *keyidstr,
1897                      size_t *r_length)
1898 {
1899   size_t len[8], needed, n;
1900   unsigned char *p, *certseq;
1901   size_t certseqlen;
1902   int i;
1903
1904   assert (strlen (keyidstr) == 8);
1905
1906   /* Walk 8 steps down to collect the info: */
1907
1908   /* 7. The data goes into an octet string. */
1909   needed = compute_tag_length (buflen);
1910   needed += buflen;
1911
1912   /* 6. A [0] tag. */
1913   len[6] = needed;
1914   needed += compute_tag_length (needed);
1915
1916   /* 5. An OID. */
1917   needed += 2 + DIM (oid_x509Certificate_for_pkcs_12);
1918
1919   /* 4. A sequence. */
1920   len[4] = needed;
1921   needed += compute_tag_length (needed);
1922
1923   /* 3. A [0] tag. */
1924   len[3] = needed;
1925   needed += compute_tag_length (needed);
1926
1927   /* 2b. The attributes which are appended at the end. */
1928   if (sha1hash)
1929     needed += DIM (data_attrtemplate) + 20;
1930
1931   /* 2. An OID. */
1932   needed += 2 + DIM (oid_pkcs_12_CertBag);
1933
1934   /* 1. A sequence. */
1935   len[1] = needed;
1936   needed += compute_tag_length (needed);
1937
1938   /* 0. The first sequence. */
1939   len[0] = needed;
1940   needed += compute_tag_length (needed);
1941
1942   /* Now that we have all length information, allocate a buffer. */
1943   p = certseq = gcry_malloc (needed + 8 /*(for padding)*/);
1944   if (!certseq)
1945     {
1946       log_error ("error allocating buffer\n");
1947       return NULL;
1948     }
1949
1950   /* Walk 8 steps up to store the data. */
1951
1952   /* 0. Store the first sequence. */
1953   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1954
1955   /* 1. Store the second sequence. */
1956   p = store_tag_length (p, TAG_SEQUENCE, len[1]);
1957
1958   /* 2. Store the pkcs12-cert-bag OID. */
1959   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_pkcs_12_CertBag));
1960   memcpy (p, oid_pkcs_12_CertBag, DIM (oid_pkcs_12_CertBag)); 
1961   p += DIM (oid_pkcs_12_CertBag); 
1962
1963   /* 3. Store a [0] tag. */
1964   p = store_tag_length (p, 0xa0, len[3]);
1965
1966   /* 4. Store a sequence. */
1967   p = store_tag_length (p, TAG_SEQUENCE, len[4]);
1968
1969   /* 5. Store the x509Certificate OID. */
1970   p = store_tag_length (p, TAG_OBJECT_ID,
1971                         DIM (oid_x509Certificate_for_pkcs_12));
1972   memcpy (p, oid_x509Certificate_for_pkcs_12,
1973           DIM (oid_x509Certificate_for_pkcs_12)); 
1974   p += DIM (oid_x509Certificate_for_pkcs_12); 
1975
1976   /* 6. Store a [0] tag. */
1977   p = store_tag_length (p, 0xa0, len[6]);
1978
1979   /* 7. And the octet string with the actual certificate. */
1980   p = store_tag_length (p, TAG_OCTET_STRING, buflen);
1981   memcpy (p, buffer, buflen);
1982   p += buflen;
1983   
1984   /* Append the attributes whose length we calculated at step 2b. */
1985   if (sha1hash)
1986     {
1987       memcpy (p, data_attrtemplate, DIM (data_attrtemplate));
1988       for (i=0; i < 8; i++)
1989         p[DATA_ATTRTEMPLATE_KEYID_OFF+2*i+1] = keyidstr[i];
1990       p += DIM (data_attrtemplate);
1991       memcpy (p, sha1hash, 20);
1992       p += 20;
1993     }
1994
1995   certseqlen = p - certseq;
1996   if (needed != certseqlen)
1997     log_debug ("length mismatch: %lu, %lu\n",
1998                (unsigned long)needed, (unsigned long)certseqlen);
1999
2000   /* Append some pad characters; we already allocated extra space. */
2001   n = 8 - certseqlen % 8;
2002   for (i=0; i < n; i++, certseqlen++)
2003     *p++ = n;
2004   
2005   *r_length = certseqlen;
2006   return certseq;
2007 }
2008
2009
2010 /* Expect the RSA key parameters in KPARMS and a password in
2011    PW. Create a PKCS structure from it and return it as well as the
2012    length in R_LENGTH; return NULL in case of an error. */
2013 unsigned char * 
2014 p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen,
2015            const char *pw, size_t *r_length)
2016 {
2017   unsigned char *buffer;
2018   size_t n, buflen;
2019   char salt[8];
2020   struct buffer_s seqlist[3];
2021   int seqlistidx = 0;
2022   unsigned char sha1hash[20];
2023   char keyidstr[8+1];
2024
2025   n = buflen = 0; /* (avoid compiler warning). */
2026   memset (sha1hash, 0, 20);
2027   *keyidstr = 0;
2028
2029   if (cert && certlen)
2030     {
2031       /* Calculate the hash value we need for the bag attributes. */
2032       gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash, cert, certlen);
2033       sprintf (keyidstr, "%02x%02x%02x%02x",
2034                sha1hash[16], sha1hash[17], sha1hash[18], sha1hash[19]);
2035
2036       /* Encode the certificate. */
2037       buffer = build_cert_sequence (cert, certlen, sha1hash, keyidstr,
2038                                     &buflen);
2039       if (!buffer)
2040         goto failure;
2041
2042       /* Encrypt it. */
2043       gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
2044       crypt_block (buffer, buflen, salt, 8, 2048, pw,
2045                    GCRY_CIPHER_RFC2268_40, 1);
2046       
2047       /* Encode the encrypted stuff into a bag. */
2048       seqlist[seqlistidx].buffer = build_cert_bag (buffer, buflen, salt, &n);
2049       seqlist[seqlistidx].length = n;
2050       gcry_free (buffer);
2051       buffer = NULL;
2052       if (!seqlist[seqlistidx].buffer)
2053         goto failure;
2054       seqlistidx++;
2055     }
2056
2057
2058   if (kparms)
2059     {
2060       /* Encode the key. */
2061       buffer = build_key_sequence (kparms, &buflen);
2062       if (!buffer)
2063         goto failure;
2064       
2065       /* Encrypt it. */
2066       gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
2067       crypt_block (buffer, buflen, salt, 8, 2048, pw, GCRY_CIPHER_3DES, 1);
2068
2069       /* Encode the encrypted stuff into a bag. */
2070       if (cert && certlen)
2071         seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, 
2072                                                     sha1hash, keyidstr, &n);
2073       else
2074         seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt,
2075                                                     NULL, NULL, &n);
2076       seqlist[seqlistidx].length = n;
2077       gcry_free (buffer);
2078       buffer = NULL;
2079       if (!seqlist[seqlistidx].buffer)
2080         goto failure;
2081       seqlistidx++;
2082     }
2083
2084   seqlist[seqlistidx].buffer = NULL;
2085   seqlist[seqlistidx].length = 0;
2086
2087   buffer = create_final (seqlist, pw, &buflen);
2088
2089  failure:
2090   for ( ; seqlistidx; seqlistidx--)
2091     gcry_free (seqlist[seqlistidx].buffer);
2092
2093   *r_length = buffer? buflen : 0;
2094   return buffer;
2095 }
2096
2097
2098 #ifdef TEST
2099
2100 static void 
2101 cert_cb (void *opaque, const unsigned char *cert, size_t certlen)
2102 {
2103   printf ("got a certificate of %u bytes length\n", certlen);
2104 }
2105
2106 int
2107 main (int argc, char **argv)
2108 {
2109   FILE *fp;
2110   struct stat st;
2111   unsigned char *buf;
2112   size_t buflen;
2113   gcry_mpi_t *result;
2114
2115   if (argc != 3)
2116     {
2117       fprintf (stderr, "usage: testp12 file passphrase\n");
2118       return 1;
2119     }
2120
2121   gcry_control (GCRYCTL_DISABLE_SECMEM, NULL);
2122   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL);
2123
2124   fp = fopen (argv[1], "rb");
2125   if (!fp)
2126     {
2127       fprintf (stderr, "can't open `%s': %s\n", argv[1], strerror (errno));
2128       return 1;
2129     }
2130   
2131   if (fstat (fileno(fp), &st))
2132     {
2133       fprintf (stderr, "can't stat `%s': %s\n", argv[1], strerror (errno));
2134       return 1;
2135     }
2136
2137   buflen = st.st_size;
2138   buf = gcry_malloc (buflen+1);
2139   if (!buf || fread (buf, buflen, 1, fp) != 1)
2140     {
2141       fprintf (stderr, "error reading `%s': %s\n", argv[1], strerror (errno));
2142       return 1;
2143     }
2144   fclose (fp);
2145
2146   result = p12_parse (buf, buflen, argv[2], cert_cb, NULL);
2147   if (result)
2148     {
2149       int i, rc;
2150       unsigned char *tmpbuf;
2151
2152       for (i=0; result[i]; i++)
2153         {
2154           rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &tmpbuf,
2155                                 NULL, result[i]);
2156           if (rc)
2157             printf ("%d: [error printing number: %s]\n",
2158                     i, gpg_strerror (rc));
2159           else
2160             {
2161               printf ("%d: %s\n", i, tmpbuf);
2162               gcry_free (tmpbuf);
2163             }
2164         }
2165     }
2166
2167   return 0;
2168
2169 }
2170
2171 /*
2172 Local Variables:
2173 compile-command: "gcc -Wall -O0 -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error"
2174 End:
2175 */
2176 #endif /* TEST */