25a38b9c81fc211527e0d19fd19e8c2f72636a7c
[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[20];
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 > 20 )
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, (unsigned int)((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[20];
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 > 20)
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, (unsigned int)((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",
1313              where, (unsigned int)(p - p_start));
1314   if (result)
1315     {
1316       int i;
1317
1318       for (i=0; result[i]; i++)
1319         gcry_mpi_release (result[i]);
1320       gcry_free (result);
1321     }
1322   gcry_free (cram_buffer);
1323   return NULL;
1324 }
1325
1326
1327 \f
1328 static size_t
1329 compute_tag_length (size_t n)
1330 {     
1331   int needed = 0;
1332
1333   if (n < 128)
1334     needed += 2; /* tag and one length byte */
1335   else if (n < 256)
1336     needed += 3; /* tag, number of length bytes, 1 length byte */
1337   else if (n < 65536)
1338     needed += 4; /* tag, number of length bytes, 2 length bytes */
1339   else
1340     {
1341       log_error ("object too larger to encode\n");
1342       return 0;
1343     }
1344   return needed;
1345 }
1346
1347 static unsigned char *
1348 store_tag_length (unsigned char *p, int tag, size_t n)
1349 {     
1350   if (tag == TAG_SEQUENCE)
1351     tag |= 0x20; /* constructed */
1352
1353   *p++ = tag;
1354   if (n < 128)
1355     *p++ = n;
1356   else if (n < 256)
1357     {
1358       *p++ = 0x81;
1359       *p++ = n;
1360     }
1361   else if (n < 65536)
1362     {
1363       *p++ = 0x82;
1364       *p++ = n >> 8;
1365       *p++ = n;
1366     }
1367
1368   return p;
1369 }
1370
1371
1372 /* Create the final PKCS-12 object from the sequences contained in
1373    SEQLIST.  PW is the password. That array is terminated with an NULL
1374    object. */
1375 static unsigned char *
1376 create_final (struct buffer_s *sequences, const char *pw, size_t *r_length)
1377 {
1378   int i;
1379   size_t needed = 0;
1380   size_t len[8], n;
1381   unsigned char *macstart;
1382   size_t maclen;
1383   unsigned char *result, *p;
1384   size_t resultlen;
1385   char salt[8];
1386   unsigned char keybuf[20];
1387   gcry_md_hd_t md;
1388   int rc;
1389   int with_mac = 1;
1390
1391
1392   /* 9 steps to create the pkcs#12 Krampf. */
1393
1394   /* 8. The MAC. */
1395   /* We add this at step 0. */
1396
1397   /* 7. All the buffers. */
1398   for (i=0; sequences[i].buffer; i++)
1399     needed += sequences[i].length;
1400
1401   /* 6. This goes into a sequences. */
1402   len[6] = needed;
1403   n = compute_tag_length (needed);
1404   needed += n;
1405
1406   /* 5. Encapsulate all in an octet string. */
1407   len[5] = needed;
1408   n = compute_tag_length (needed);
1409   needed += n;
1410
1411   /* 4. And tag it with [0]. */
1412   len[4] = needed;
1413   n = compute_tag_length (needed);
1414   needed += n;
1415
1416   /* 3. Prepend an data OID. */
1417   needed += 2 + DIM (oid_data);
1418
1419   /* 2. Put all into a sequences. */
1420   len[2] = needed;
1421   n = compute_tag_length (needed);
1422   needed += n;
1423
1424   /* 1. Prepend the version integer 3. */
1425   needed += 3;
1426
1427   /* 0. And the final outer sequence. */
1428   if (with_mac)
1429     needed += DIM (data_mactemplate);
1430   len[0] = needed;
1431   n = compute_tag_length (needed);
1432   needed += n;
1433
1434   /* Allocate a buffer. */
1435   result = gcry_malloc (needed);
1436   if (!result)
1437     {
1438       log_error ("error allocating buffer\n");
1439       return NULL;
1440     }
1441   p = result;
1442
1443   /* 0. Store the very outer sequence. */
1444   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1445
1446   /* 1. Store the version integer 3. */
1447   *p++ = TAG_INTEGER;
1448   *p++ = 1; 
1449   *p++ = 3;
1450
1451   /* 2. Store another sequence. */
1452   p = store_tag_length (p, TAG_SEQUENCE, len[2]);
1453
1454   /* 3. Store the data OID. */
1455   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
1456   memcpy (p, oid_data, DIM (oid_data)); 
1457   p += DIM (oid_data); 
1458
1459   /* 4. Next comes a context tag. */
1460   p = store_tag_length (p, 0xa0, len[4]);
1461
1462   /* 5. And an octet string. */
1463   p = store_tag_length (p, TAG_OCTET_STRING, len[5]);
1464
1465   /* 6. And the inner sequence. */
1466   macstart = p;
1467   p = store_tag_length (p, TAG_SEQUENCE, len[6]);
1468
1469   /* 7. Append all the buffers. */
1470   for (i=0; sequences[i].buffer; i++)
1471     {
1472       memcpy (p, sequences[i].buffer, sequences[i].length);
1473       p += sequences[i].length;
1474     }
1475
1476   if (with_mac)
1477     {
1478       /* Intermezzo to compute the MAC. */
1479       maclen = p - macstart;
1480       gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
1481       if (string_to_key (3, salt, 8, 2048, pw, 20, keybuf))
1482         {
1483           gcry_free (result);
1484           return NULL;
1485         }
1486       rc = gcry_md_open (&md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
1487       if (rc)
1488         {
1489           log_error ("gcry_md_open failed: %s\n", gpg_strerror (rc));
1490           gcry_free (result);
1491           return NULL;
1492         }
1493       rc = gcry_md_setkey (md, keybuf, 20);
1494       if (rc)
1495         {
1496           log_error ("gcry_md_setkey failed: %s\n", gpg_strerror (rc));
1497           gcry_md_close (md);
1498           gcry_free (result);
1499           return NULL;
1500         }
1501       gcry_md_write (md, macstart, maclen);
1502
1503       /* 8. Append the MAC template and fix it up. */
1504       memcpy (p, data_mactemplate, DIM (data_mactemplate));
1505       memcpy (p + DATA_MACTEMPLATE_SALT_OFF, salt, 8);
1506       memcpy (p + DATA_MACTEMPLATE_MAC_OFF, gcry_md_read (md, 0), 20);
1507       p += DIM (data_mactemplate);
1508       gcry_md_close (md);
1509     }
1510
1511   /* Ready. */
1512   resultlen = p - result;
1513   if (needed != resultlen)
1514     log_debug ("length mismatch: %lu, %lu\n",
1515                (unsigned long)needed, (unsigned long)resultlen);
1516
1517   *r_length = resultlen;
1518   return result;
1519 }
1520
1521
1522 /* Build a DER encoded SEQUENCE with the key:
1523
1524    SEQUENCE {
1525      INTEGER 0
1526      SEQUENCE {
1527        OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
1528        NULL
1529        }
1530      OCTET STRING, encapsulates {
1531        SEQUENCE {
1532          INTEGER 0
1533          INTEGER
1534          INTEGER 
1535          INTEGER
1536          INTEGER
1537          INTEGER
1538          INTEGER
1539          INTEGER
1540          INTEGER
1541          }
1542        }
1543      }
1544 */  
1545   
1546 static unsigned char * 
1547 build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
1548 {
1549   int rc, i;
1550   size_t needed, n;
1551   unsigned char *plain, *p;
1552   size_t plainlen;
1553   size_t outseqlen, oidseqlen, octstrlen, inseqlen;
1554
1555   needed = 3; /* The version(?) integer of value 0. */
1556   for (i=0; kparms[i]; i++)
1557     {
1558       n = 0;
1559       rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
1560       if (rc)
1561         {
1562           log_error ("error formatting parameter: %s\n", gpg_strerror (rc));
1563           return NULL;
1564         }
1565       needed += n;
1566       n = compute_tag_length (n);
1567       if (!n)
1568         return NULL;
1569       needed += n;
1570     }
1571   if (i != 8)
1572     {
1573       log_error ("invalid paramters for p12_build\n");
1574       return NULL;
1575     }
1576   /* Now this all goes into a sequence. */
1577   inseqlen = needed;
1578   n = compute_tag_length (needed);
1579   if (!n)
1580     return NULL;
1581   needed += n;
1582   /* Encapsulate all into an octet string. */
1583   octstrlen = needed;
1584   n = compute_tag_length (needed);
1585   if (!n)
1586     return NULL;
1587   needed += n;
1588   /* Prepend the object identifier sequence. */
1589   oidseqlen = 2 + DIM (oid_rsaEncryption) + 2;
1590   needed += 2 + oidseqlen;
1591   /* The version number. */
1592   needed += 3;
1593   /* And finally put the whole thing into a sequence. */
1594   outseqlen = needed;
1595   n = compute_tag_length (needed);
1596   if (!n)
1597     return NULL;
1598   needed += n;
1599   
1600   /* allocate 8 extra bytes for padding */
1601   plain = gcry_malloc_secure (needed+8);
1602   if (!plain)
1603     {
1604       log_error ("error allocating encryption buffer\n");
1605       return NULL;
1606     }
1607   
1608   /* And now fill the plaintext buffer. */
1609   p = plain;
1610   p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
1611   /* Store version. */
1612   *p++ = TAG_INTEGER;
1613   *p++ = 1;
1614   *p++ = 0;
1615   /* Store object identifier sequence. */
1616   p = store_tag_length (p, TAG_SEQUENCE, oidseqlen);
1617   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption));
1618   memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption)); 
1619   p += DIM (oid_rsaEncryption); 
1620   *p++ = TAG_NULL;
1621   *p++ = 0;
1622   /* Start with the octet string. */
1623   p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
1624   p = store_tag_length (p, TAG_SEQUENCE, inseqlen);
1625   /* Store the key parameters. */
1626   *p++ = TAG_INTEGER;
1627   *p++ = 1;
1628   *p++ = 0;
1629   for (i=0; kparms[i]; i++)
1630     {
1631       n = 0;
1632       rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
1633       if (rc)
1634         {
1635           log_error ("oops: error formatting parameter: %s\n",
1636                      gpg_strerror (rc));
1637           gcry_free (plain);
1638           return NULL;
1639         }
1640       p = store_tag_length (p, TAG_INTEGER, n);
1641       
1642       n = plain + needed - p;
1643       rc = gcry_mpi_print (GCRYMPI_FMT_STD, p, n, &n, kparms[i]);
1644       if (rc)
1645         {
1646           log_error ("oops: error storing parameter: %s\n",
1647                      gpg_strerror (rc));
1648           gcry_free (plain);
1649           return NULL;
1650         }
1651       p += n;
1652     }
1653
1654   plainlen = p - plain;
1655   assert (needed == plainlen);
1656   /* Append some pad characters; we already allocated extra space. */
1657   n = 8 - plainlen % 8;
1658   for (i=0; i < n; i++, plainlen++)
1659     *p++ = n;
1660
1661   *r_length = plainlen;
1662   return plain;
1663 }
1664
1665
1666
1667 static unsigned char *
1668 build_key_bag (unsigned char *buffer, size_t buflen, char *salt,
1669                const unsigned char *sha1hash, const char *keyidstr,
1670                size_t *r_length)
1671 {
1672   size_t len[11], needed;
1673   unsigned char *p, *keybag;
1674   size_t keybaglen;
1675
1676   /* Walk 11 steps down to collect the info: */
1677
1678   /* 10. The data goes into an octet string. */
1679   needed = compute_tag_length (buflen);
1680   needed += buflen;
1681
1682   /* 9. Prepend the algorithm identifier. */
1683   needed += DIM (data_3desiter2048);
1684
1685   /* 8. Put a sequence around. */
1686   len[8] = needed;
1687   needed += compute_tag_length (needed);
1688
1689   /* 7. Prepend a [0] tag. */
1690   len[7] = needed;
1691   needed += compute_tag_length (needed);
1692
1693   /* 6b. The attributes which are appended at the end. */
1694   if (sha1hash)
1695     needed += DIM (data_attrtemplate) + 20;
1696
1697   /* 6. Prepend the shroudedKeyBag OID. */
1698   needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag);
1699
1700   /* 5+4. Put all into two sequences. */
1701   len[5] = needed;
1702   needed += compute_tag_length ( needed);
1703   len[4] = needed;
1704   needed += compute_tag_length (needed);
1705
1706   /* 3. This all goes into an octet string. */
1707   len[3] = needed;
1708   needed += compute_tag_length (needed);
1709
1710   /* 2. Prepend another [0] tag. */
1711   len[2] = needed;
1712   needed += compute_tag_length (needed);
1713
1714   /* 1. Prepend the data OID. */
1715   needed += 2 + DIM (oid_data);
1716
1717   /* 0. Prepend another sequence. */
1718   len[0] = needed;
1719   needed += compute_tag_length (needed);
1720
1721   /* Now that we have all length information, allocate a buffer. */
1722   p = keybag = gcry_malloc (needed);
1723   if (!keybag)
1724     {
1725       log_error ("error allocating buffer\n");
1726       return NULL;
1727     }
1728
1729   /* Walk 11 steps up to store the data. */
1730
1731   /* 0. Store the first sequence. */
1732   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1733
1734   /* 1. Store the data OID. */
1735   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
1736   memcpy (p, oid_data, DIM (oid_data)); 
1737   p += DIM (oid_data); 
1738
1739   /* 2. Store a [0] tag. */
1740   p = store_tag_length (p, 0xa0, len[2]);
1741
1742   /* 3. And an octet string. */
1743   p = store_tag_length (p, TAG_OCTET_STRING, len[3]);
1744
1745   /* 4+5. Two sequences. */
1746   p = store_tag_length (p, TAG_SEQUENCE, len[4]);
1747   p = store_tag_length (p, TAG_SEQUENCE, len[5]);
1748
1749   /* 6. Store the shroudedKeyBag OID. */
1750   p = store_tag_length (p, TAG_OBJECT_ID,
1751                         DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag));
1752   memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
1753           DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); 
1754   p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); 
1755
1756   /* 7. Store a [0] tag. */
1757   p = store_tag_length (p, 0xa0, len[7]);
1758
1759   /* 8. Store a sequence. */
1760   p = store_tag_length (p, TAG_SEQUENCE, len[8]);
1761
1762   /* 9. Now for the pre-encoded algorithm identifier and the salt. */
1763   memcpy (p, data_3desiter2048, DIM (data_3desiter2048));
1764   memcpy (p + DATA_3DESITER2048_SALT_OFF, salt, 8);
1765   p += DIM (data_3desiter2048);
1766
1767   /* 10. And the octet string with the encrypted data. */
1768   p = store_tag_length (p, TAG_OCTET_STRING, buflen);
1769   memcpy (p, buffer, buflen);
1770   p += buflen;
1771
1772   /* Append the attributes whose length we calculated at step 2b. */
1773   if (sha1hash)
1774     {
1775       int i;
1776
1777       memcpy (p, data_attrtemplate, DIM (data_attrtemplate));
1778       for (i=0; i < 8; i++)
1779         p[DATA_ATTRTEMPLATE_KEYID_OFF+2*i+1] = keyidstr[i];
1780       p += DIM (data_attrtemplate);
1781       memcpy (p, sha1hash, 20);
1782       p += 20;
1783     }
1784
1785
1786   keybaglen = p - keybag;
1787   if (needed != keybaglen)
1788     log_debug ("length mismatch: %lu, %lu\n",
1789                (unsigned long)needed, (unsigned long)keybaglen);
1790   
1791   *r_length = keybaglen;
1792   return keybag;
1793 }
1794
1795
1796 static unsigned char *
1797 build_cert_bag (unsigned char *buffer, size_t buflen, char *salt,
1798                 size_t *r_length)
1799 {
1800   size_t len[9], needed;
1801   unsigned char *p, *certbag;
1802   size_t certbaglen;
1803
1804   /* Walk 9 steps down to collect the info: */
1805
1806   /* 8. The data goes into an octet string. */
1807   needed = compute_tag_length (buflen);
1808   needed += buflen;
1809
1810   /* 7. The algorithm identifier. */
1811   needed += DIM (data_rc2iter2048);
1812
1813   /* 6. The data OID. */
1814   needed += 2 + DIM (oid_data);
1815
1816   /* 5. A sequence. */
1817   len[5] = needed;
1818   needed += compute_tag_length ( needed);
1819
1820   /* 4. An integer. */
1821   needed += 3;
1822
1823   /* 3. A sequence. */
1824   len[3] = needed;
1825   needed += compute_tag_length (needed);
1826
1827   /* 2.  A [0] tag. */
1828   len[2] = needed;
1829   needed += compute_tag_length (needed);
1830
1831   /* 1. The encryptedData OID. */
1832   needed += 2 + DIM (oid_encryptedData);
1833
1834   /* 0. The first sequence. */
1835   len[0] = needed;
1836   needed += compute_tag_length (needed);
1837
1838   /* Now that we have all length information, allocate a buffer. */
1839   p = certbag = gcry_malloc (needed);
1840   if (!certbag)
1841     {
1842       log_error ("error allocating buffer\n");
1843       return NULL;
1844     }
1845
1846   /* Walk 9 steps up to store the data. */
1847
1848   /* 0. Store the first sequence. */
1849   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1850
1851   /* 1. Store the encryptedData OID. */
1852   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_encryptedData));
1853   memcpy (p, oid_encryptedData, DIM (oid_encryptedData)); 
1854   p += DIM (oid_encryptedData); 
1855
1856   /* 2. Store a [0] tag. */
1857   p = store_tag_length (p, 0xa0, len[2]);
1858
1859   /* 3. Store a sequence. */
1860   p = store_tag_length (p, TAG_SEQUENCE, len[3]);
1861
1862   /* 4. Store the integer 0. */
1863   *p++ = TAG_INTEGER;
1864   *p++ = 1; 
1865   *p++ = 0;
1866
1867   /* 5. Store a sequence. */
1868   p = store_tag_length (p, TAG_SEQUENCE, len[5]);
1869
1870   /* 6. Store the data OID. */
1871   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
1872   memcpy (p, oid_data, DIM (oid_data)); 
1873   p += DIM (oid_data); 
1874
1875   /* 7. Now for the pre-encoded algorithm identifier and the salt. */
1876   memcpy (p, data_rc2iter2048, DIM (data_rc2iter2048));
1877   memcpy (p + DATA_RC2ITER2048_SALT_OFF, salt, 8);
1878   p += DIM (data_rc2iter2048);
1879
1880   /* 8. And finally the [0] tag with the encrypted data. */
1881   p = store_tag_length (p, 0x80, buflen);
1882   memcpy (p, buffer, buflen);
1883   p += buflen;
1884   certbaglen = p - certbag;
1885   
1886   if (needed != certbaglen)
1887     log_debug ("length mismatch: %lu, %lu\n",
1888                (unsigned long)needed, (unsigned long)certbaglen);
1889
1890   *r_length = certbaglen;
1891   return certbag;
1892 }
1893
1894
1895 static unsigned char *
1896 build_cert_sequence (unsigned char *buffer, size_t buflen, 
1897                      const unsigned char *sha1hash, const char *keyidstr,
1898                      size_t *r_length)
1899 {
1900   size_t len[8], needed, n;
1901   unsigned char *p, *certseq;
1902   size_t certseqlen;
1903   int i;
1904
1905   assert (strlen (keyidstr) == 8);
1906
1907   /* Walk 8 steps down to collect the info: */
1908
1909   /* 7. The data goes into an octet string. */
1910   needed = compute_tag_length (buflen);
1911   needed += buflen;
1912
1913   /* 6. A [0] tag. */
1914   len[6] = needed;
1915   needed += compute_tag_length (needed);
1916
1917   /* 5. An OID. */
1918   needed += 2 + DIM (oid_x509Certificate_for_pkcs_12);
1919
1920   /* 4. A sequence. */
1921   len[4] = needed;
1922   needed += compute_tag_length (needed);
1923
1924   /* 3. A [0] tag. */
1925   len[3] = needed;
1926   needed += compute_tag_length (needed);
1927
1928   /* 2b. The attributes which are appended at the end. */
1929   if (sha1hash)
1930     needed += DIM (data_attrtemplate) + 20;
1931
1932   /* 2. An OID. */
1933   needed += 2 + DIM (oid_pkcs_12_CertBag);
1934
1935   /* 1. A sequence. */
1936   len[1] = needed;
1937   needed += compute_tag_length (needed);
1938
1939   /* 0. The first sequence. */
1940   len[0] = needed;
1941   needed += compute_tag_length (needed);
1942
1943   /* Now that we have all length information, allocate a buffer. */
1944   p = certseq = gcry_malloc (needed + 8 /*(for padding)*/);
1945   if (!certseq)
1946     {
1947       log_error ("error allocating buffer\n");
1948       return NULL;
1949     }
1950
1951   /* Walk 8 steps up to store the data. */
1952
1953   /* 0. Store the first sequence. */
1954   p = store_tag_length (p, TAG_SEQUENCE, len[0]);
1955
1956   /* 1. Store the second sequence. */
1957   p = store_tag_length (p, TAG_SEQUENCE, len[1]);
1958
1959   /* 2. Store the pkcs12-cert-bag OID. */
1960   p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_pkcs_12_CertBag));
1961   memcpy (p, oid_pkcs_12_CertBag, DIM (oid_pkcs_12_CertBag)); 
1962   p += DIM (oid_pkcs_12_CertBag); 
1963
1964   /* 3. Store a [0] tag. */
1965   p = store_tag_length (p, 0xa0, len[3]);
1966
1967   /* 4. Store a sequence. */
1968   p = store_tag_length (p, TAG_SEQUENCE, len[4]);
1969
1970   /* 5. Store the x509Certificate OID. */
1971   p = store_tag_length (p, TAG_OBJECT_ID,
1972                         DIM (oid_x509Certificate_for_pkcs_12));
1973   memcpy (p, oid_x509Certificate_for_pkcs_12,
1974           DIM (oid_x509Certificate_for_pkcs_12)); 
1975   p += DIM (oid_x509Certificate_for_pkcs_12); 
1976
1977   /* 6. Store a [0] tag. */
1978   p = store_tag_length (p, 0xa0, len[6]);
1979
1980   /* 7. And the octet string with the actual certificate. */
1981   p = store_tag_length (p, TAG_OCTET_STRING, buflen);
1982   memcpy (p, buffer, buflen);
1983   p += buflen;
1984   
1985   /* Append the attributes whose length we calculated at step 2b. */
1986   if (sha1hash)
1987     {
1988       memcpy (p, data_attrtemplate, DIM (data_attrtemplate));
1989       for (i=0; i < 8; i++)
1990         p[DATA_ATTRTEMPLATE_KEYID_OFF+2*i+1] = keyidstr[i];
1991       p += DIM (data_attrtemplate);
1992       memcpy (p, sha1hash, 20);
1993       p += 20;
1994     }
1995
1996   certseqlen = p - certseq;
1997   if (needed != certseqlen)
1998     log_debug ("length mismatch: %lu, %lu\n",
1999                (unsigned long)needed, (unsigned long)certseqlen);
2000
2001   /* Append some pad characters; we already allocated extra space. */
2002   n = 8 - certseqlen % 8;
2003   for (i=0; i < n; i++, certseqlen++)
2004     *p++ = n;
2005   
2006   *r_length = certseqlen;
2007   return certseq;
2008 }
2009
2010
2011 /* Expect the RSA key parameters in KPARMS and a password in
2012    PW. Create a PKCS structure from it and return it as well as the
2013    length in R_LENGTH; return NULL in case of an error. */
2014 unsigned char * 
2015 p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen,
2016            const char *pw, size_t *r_length)
2017 {
2018   unsigned char *buffer;
2019   size_t n, buflen;
2020   char salt[8];
2021   struct buffer_s seqlist[3];
2022   int seqlistidx = 0;
2023   unsigned char sha1hash[20];
2024   char keyidstr[8+1];
2025
2026   n = buflen = 0; /* (avoid compiler warning). */
2027   memset (sha1hash, 0, 20);
2028   *keyidstr = 0;
2029
2030   if (cert && certlen)
2031     {
2032       /* Calculate the hash value we need for the bag attributes. */
2033       gcry_md_hash_buffer (GCRY_MD_SHA1, sha1hash, cert, certlen);
2034       sprintf (keyidstr, "%02x%02x%02x%02x",
2035                sha1hash[16], sha1hash[17], sha1hash[18], sha1hash[19]);
2036
2037       /* Encode the certificate. */
2038       buffer = build_cert_sequence (cert, certlen, sha1hash, keyidstr,
2039                                     &buflen);
2040       if (!buffer)
2041         goto failure;
2042
2043       /* Encrypt it. */
2044       gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
2045       crypt_block (buffer, buflen, salt, 8, 2048, pw,
2046                    GCRY_CIPHER_RFC2268_40, 1);
2047       
2048       /* Encode the encrypted stuff into a bag. */
2049       seqlist[seqlistidx].buffer = build_cert_bag (buffer, buflen, salt, &n);
2050       seqlist[seqlistidx].length = n;
2051       gcry_free (buffer);
2052       buffer = NULL;
2053       if (!seqlist[seqlistidx].buffer)
2054         goto failure;
2055       seqlistidx++;
2056     }
2057
2058
2059   if (kparms)
2060     {
2061       /* Encode the key. */
2062       buffer = build_key_sequence (kparms, &buflen);
2063       if (!buffer)
2064         goto failure;
2065       
2066       /* Encrypt it. */
2067       gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
2068       crypt_block (buffer, buflen, salt, 8, 2048, pw, GCRY_CIPHER_3DES, 1);
2069
2070       /* Encode the encrypted stuff into a bag. */
2071       if (cert && certlen)
2072         seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, 
2073                                                     sha1hash, keyidstr, &n);
2074       else
2075         seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt,
2076                                                     NULL, NULL, &n);
2077       seqlist[seqlistidx].length = n;
2078       gcry_free (buffer);
2079       buffer = NULL;
2080       if (!seqlist[seqlistidx].buffer)
2081         goto failure;
2082       seqlistidx++;
2083     }
2084
2085   seqlist[seqlistidx].buffer = NULL;
2086   seqlist[seqlistidx].length = 0;
2087
2088   buffer = create_final (seqlist, pw, &buflen);
2089
2090  failure:
2091   for ( ; seqlistidx; seqlistidx--)
2092     gcry_free (seqlist[seqlistidx].buffer);
2093
2094   *r_length = buffer? buflen : 0;
2095   return buffer;
2096 }
2097
2098
2099 #ifdef TEST
2100
2101 static void 
2102 cert_cb (void *opaque, const unsigned char *cert, size_t certlen)
2103 {
2104   printf ("got a certificate of %u bytes length\n", certlen);
2105 }
2106
2107 int
2108 main (int argc, char **argv)
2109 {
2110   FILE *fp;
2111   struct stat st;
2112   unsigned char *buf;
2113   size_t buflen;
2114   gcry_mpi_t *result;
2115
2116   if (argc != 3)
2117     {
2118       fprintf (stderr, "usage: testp12 file passphrase\n");
2119       return 1;
2120     }
2121
2122   gcry_control (GCRYCTL_DISABLE_SECMEM, NULL);
2123   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL);
2124
2125   fp = fopen (argv[1], "rb");
2126   if (!fp)
2127     {
2128       fprintf (stderr, "can't open `%s': %s\n", argv[1], strerror (errno));
2129       return 1;
2130     }
2131   
2132   if (fstat (fileno(fp), &st))
2133     {
2134       fprintf (stderr, "can't stat `%s': %s\n", argv[1], strerror (errno));
2135       return 1;
2136     }
2137
2138   buflen = st.st_size;
2139   buf = gcry_malloc (buflen+1);
2140   if (!buf || fread (buf, buflen, 1, fp) != 1)
2141     {
2142       fprintf (stderr, "error reading `%s': %s\n", argv[1], strerror (errno));
2143       return 1;
2144     }
2145   fclose (fp);
2146
2147   result = p12_parse (buf, buflen, argv[2], cert_cb, NULL);
2148   if (result)
2149     {
2150       int i, rc;
2151       unsigned char *tmpbuf;
2152
2153       for (i=0; result[i]; i++)
2154         {
2155           rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &tmpbuf,
2156                                 NULL, result[i]);
2157           if (rc)
2158             printf ("%d: [error printing number: %s]\n",
2159                     i, gpg_strerror (rc));
2160           else
2161             {
2162               printf ("%d: %s\n", i, tmpbuf);
2163               gcry_free (tmpbuf);
2164             }
2165         }
2166     }
2167
2168   return 0;
2169
2170 }
2171
2172 /*
2173 Local Variables:
2174 compile-command: "gcc -Wall -O0 -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error"
2175 End:
2176 */
2177 #endif /* TEST */