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