~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to agent/minip12.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* minip12.c - A minimal pkcs-12 implementation.
 
2
 *      Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GnuPG.
 
5
 *
 
6
 * GnuPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GnuPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#include <assert.h>
 
28
#include <gcrypt.h>
 
29
 
 
30
#ifdef TEST
 
31
#include <sys/stat.h>
 
32
#include <unistd.h>
 
33
#include <errno.h>
 
34
#endif
 
35
 
 
36
#include "../jnlib/logging.h"
 
37
#include "minip12.h"
 
38
 
 
39
#ifndef DIM
 
40
#define DIM(v)               (sizeof(v)/sizeof((v)[0]))
 
41
#endif
 
42
 
 
43
enum
 
44
{
 
45
  UNIVERSAL = 0,
 
46
  APPLICATION = 1,
 
47
  CONTEXT = 2,
 
48
  PRIVATE = 3
 
49
};
 
50
 
 
51
 
 
52
enum
 
53
{
 
54
  TAG_NONE = 0,
 
55
  TAG_BOOLEAN = 1,
 
56
  TAG_INTEGER = 2,
 
57
  TAG_BIT_STRING = 3,
 
58
  TAG_OCTET_STRING = 4,
 
59
  TAG_NULL = 5,
 
60
  TAG_OBJECT_ID = 6,
 
61
  TAG_OBJECT_DESCRIPTOR = 7,
 
62
  TAG_EXTERNAL = 8,
 
63
  TAG_REAL = 9,
 
64
  TAG_ENUMERATED = 10,
 
65
  TAG_EMBEDDED_PDV = 11,
 
66
  TAG_UTF8_STRING = 12,
 
67
  TAG_REALTIVE_OID = 13,
 
68
  TAG_SEQUENCE = 16,
 
69
  TAG_SET = 17,
 
70
  TAG_NUMERIC_STRING = 18,
 
71
  TAG_PRINTABLE_STRING = 19,
 
72
  TAG_TELETEX_STRING = 20,
 
73
  TAG_VIDEOTEX_STRING = 21,
 
74
  TAG_IA5_STRING = 22,
 
75
  TAG_UTC_TIME = 23,
 
76
  TAG_GENERALIZED_TIME = 24,
 
77
  TAG_GRAPHIC_STRING = 25,
 
78
  TAG_VISIBLE_STRING = 26,
 
79
  TAG_GENERAL_STRING = 27,
 
80
  TAG_UNIVERSAL_STRING = 28,
 
81
  TAG_CHARACTER_STRING = 29,
 
82
  TAG_BMP_STRING = 30
 
83
};
 
84
 
 
85
 
 
86
static unsigned char const oid_data[9] = {
 
87
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
 
88
static unsigned char const oid_encryptedData[9] = {
 
89
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 };
 
90
static unsigned char const oid_pkcs_12_pkcs_8ShroudedKeyBag[11] = {
 
91
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x02 };
 
92
static unsigned char const oid_pkcs_12_CertBag[11] = {
 
93
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x03 };
 
94
static unsigned char const oid_pkcs_12_CrlBag[11] = {
 
95
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x0A, 0x01, 0x04 };
 
96
 
 
97
static unsigned char const oid_pbeWithSHAAnd3_KeyTripleDES_CBC[10] = {
 
98
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03 };
 
99
static unsigned char const oid_pbeWithSHAAnd40BitRC2_CBC[10] = {
 
100
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06 };
 
101
static unsigned char const oid_x509Certificate_for_pkcs_12[10] = {
 
102
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01 };
 
103
 
 
104
 
 
105
static unsigned char const oid_rsaEncryption[9] = {
 
106
  0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };
 
107
 
 
108
 
 
109
static unsigned char const data_3desiter2048[30] = {
 
110
  0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86,
 
111
  0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x03, 0x30, 0x0E, 
 
112
  0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 
113
  0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 };
 
114
#define DATA_3DESITER2048_SALT_OFF  18
 
115
 
 
116
static unsigned char const data_rc2iter2048[30] = {
 
117
  0x30, 0x1C, 0x06, 0x0A, 0x2A, 0x86, 0x48, 0x86,
 
118
  0xF7, 0x0D, 0x01, 0x0C, 0x01, 0x06, 0x30, 0x0E, 
 
119
  0x04, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 
120
  0xFF, 0xFF, 0x02, 0x02, 0x08, 0x00 };
 
121
#define DATA_RC2ITER2048_SALT_OFF  18
 
122
 
 
123
 
 
124
struct buffer_s 
 
125
{
 
126
  unsigned char *buffer;
 
127
  size_t length;
 
128
};  
 
129
 
 
130
 
 
131
struct tag_info 
 
132
{
 
133
  int class;
 
134
  int is_constructed;
 
135
  unsigned long tag;
 
136
  unsigned long length;  /* length part of the TLV */
 
137
  int nhdr;
 
138
  int ndef;              /* It is an indefinite length */
 
139
};
 
140
 
 
141
 
 
142
/* Parse the buffer at the address BUFFER which is of SIZE and return
 
143
   the tag and the length part from the TLV triplet.  Update BUFFER
 
144
   and SIZE on success. */
 
145
static int 
 
146
parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti)
 
147
{
 
148
  int c;
 
149
  unsigned long tag;
 
150
  const unsigned char *buf = *buffer;
 
151
  size_t length = *size;
 
152
 
 
153
  ti->length = 0;
 
154
  ti->ndef = 0;
 
155
  ti->nhdr = 0;
 
156
 
 
157
  /* Get the tag */
 
158
  if (!length)
 
159
    return -1; /* premature eof */
 
160
  c = *buf++; length--;
 
161
  ti->nhdr++;
 
162
 
 
163
  ti->class = (c & 0xc0) >> 6;
 
164
  ti->is_constructed = !!(c & 0x20);
 
165
  tag = c & 0x1f;
 
166
 
 
167
  if (tag == 0x1f)
 
168
    {
 
169
      tag = 0;
 
170
      do
 
171
        {
 
172
          tag <<= 7;
 
173
          if (!length)
 
174
            return -1; /* premature eof */
 
175
          c = *buf++; length--;
 
176
          ti->nhdr++;
 
177
          tag |= c & 0x7f;
 
178
        }
 
179
      while (c & 0x80);
 
180
    }
 
181
  ti->tag = tag;
 
182
 
 
183
  /* Get the length */
 
184
  if (!length)
 
185
    return -1; /* prematureeof */
 
186
  c = *buf++; length--;
 
187
  ti->nhdr++;
 
188
 
 
189
  if ( !(c & 0x80) )
 
190
    ti->length = c;
 
191
  else if (c == 0x80)
 
192
    ti->ndef = 1;
 
193
  else if (c == 0xff)
 
194
    return -1; /* forbidden length value */
 
195
  else
 
196
    {
 
197
      unsigned long len = 0;
 
198
      int count = c & 0x7f;
 
199
 
 
200
      for (; count; count--)
 
201
        {
 
202
          len <<= 8;
 
203
          if (!length)
 
204
            return -1; /* premature_eof */
 
205
          c = *buf++; length--;
 
206
          ti->nhdr++;
 
207
          len |= c & 0xff;
 
208
        }
 
209
      ti->length = len;
 
210
    }
 
211
  
 
212
  if (ti->class == UNIVERSAL && !ti->tag)
 
213
    ti->length = 0;
 
214
 
 
215
  if (ti->length > length)
 
216
    return -1; /* data larger than buffer. */
 
217
  
 
218
  *buffer = buf;
 
219
  *size = length;
 
220
  return 0;
 
221
}
 
222
 
 
223
 
 
224
static int 
 
225
string_to_key (int id, char *salt, int iter, const char *pw,
 
226
               int req_keylen, unsigned char *keybuf)
 
227
{
 
228
  int rc, i, j;
 
229
  gcry_md_hd_t md;
 
230
  gcry_mpi_t num_b1 = NULL;
 
231
  int pwlen;
 
232
  unsigned char hash[20], buf_b[64], buf_i[128], *p;
 
233
  size_t cur_keylen;
 
234
  size_t n;
 
235
 
 
236
  cur_keylen = 0;
 
237
  pwlen = strlen (pw);
 
238
  if (pwlen > 63/2)
 
239
    {
 
240
      log_error ("password too long\n");
 
241
      return -1;
 
242
    }
 
243
 
 
244
  /* Store salt and password in BUF_I */
 
245
  p = buf_i;
 
246
  for(i=0; i < 64; i++)
 
247
    *p++ = salt [i%8];
 
248
  for(i=j=0; i < 64; i += 2)
 
249
    {
 
250
      *p++ = 0;
 
251
      *p++ = pw[j];
 
252
      if (++j > pwlen) /* Note, that we include the trailing zero */
 
253
        j = 0;
 
254
    }
 
255
 
 
256
  for (;;)
 
257
    {
 
258
      rc = gcry_md_open (&md, GCRY_MD_SHA1, 0);
 
259
      if (rc)
 
260
        {
 
261
          log_error ( "gcry_md_open failed: %s\n", gpg_strerror (rc));
 
262
          return rc;
 
263
        }
 
264
      for(i=0; i < 64; i++)
 
265
        gcry_md_putc (md, id);
 
266
      gcry_md_write (md, buf_i, 128);
 
267
      memcpy (hash, gcry_md_read (md, 0), 20);
 
268
      gcry_md_close (md);
 
269
      for (i=1; i < iter; i++)
 
270
        gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20);
 
271
 
 
272
      for (i=0; i < 20 && cur_keylen < req_keylen; i++)
 
273
        keybuf[cur_keylen++] = hash[i];
 
274
      if (cur_keylen == req_keylen)
 
275
        {
 
276
          gcry_mpi_release (num_b1);
 
277
          return 0; /* ready */
 
278
        }
 
279
      
 
280
      /* need more bytes. */
 
281
      for(i=0; i < 64; i++)
 
282
        buf_b[i] = hash[i % 20];
 
283
      rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, 64, &n);
 
284
      if (rc)
 
285
        {
 
286
          log_error ( "gcry_mpi_scan failed: %s\n", gpg_strerror (rc));
 
287
          return -1;
 
288
        }
 
289
      gcry_mpi_add_ui (num_b1, num_b1, 1);
 
290
      for (i=0; i < 128; i += 64)
 
291
        {
 
292
          gcry_mpi_t num_ij;
 
293
 
 
294
          rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, 64, &n);
 
295
          if (rc)
 
296
            {
 
297
              log_error ( "gcry_mpi_scan failed: %s\n",
 
298
                       gpg_strerror (rc));
 
299
              return -1;
 
300
            }
 
301
          gcry_mpi_add (num_ij, num_ij, num_b1);
 
302
          gcry_mpi_clear_highbit (num_ij, 64*8);
 
303
          rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, 64, &n, num_ij);
 
304
          if (rc)
 
305
            {
 
306
              log_error ( "gcry_mpi_print failed: %s\n",
 
307
                          gpg_strerror (rc));
 
308
              return -1;
 
309
            }
 
310
          gcry_mpi_release (num_ij);
 
311
        }
 
312
    }
 
313
}
 
314
 
 
315
 
 
316
static int 
 
317
set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw,
 
318
            int keybytes)
 
319
{
 
320
  unsigned char keybuf[24];
 
321
  int rc;
 
322
 
 
323
  assert (keybytes == 5 || keybytes == 24);
 
324
  if (string_to_key (1, salt, iter, pw, keybytes, keybuf))
 
325
    return -1;
 
326
  rc = gcry_cipher_setkey (chd, keybuf, keybytes);
 
327
  if (rc)
 
328
    {
 
329
      log_error ( "gcry_cipher_setkey failed: %s\n", gpg_strerror (rc));
 
330
      return -1;
 
331
    }
 
332
 
 
333
  if (string_to_key (2, salt, iter, pw, 8, keybuf))
 
334
    return -1;
 
335
  rc = gcry_cipher_setiv (chd, keybuf, 8);
 
336
  if (rc)
 
337
    {
 
338
      log_error ("gcry_cipher_setiv failed: %s\n", gpg_strerror (rc));
 
339
      return -1;
 
340
    }
 
341
  return 0;
 
342
}
 
343
 
 
344
 
 
345
static void
 
346
crypt_block (unsigned char *buffer, size_t length, char *salt, int iter,
 
347
             const char *pw, int cipher_algo, int encrypt)
 
348
{
 
349
  gcry_cipher_hd_t chd;
 
350
  int rc;
 
351
 
 
352
  rc = gcry_cipher_open (&chd, cipher_algo, GCRY_CIPHER_MODE_CBC, 0); 
 
353
  if (rc)
 
354
    {
 
355
      log_error ( "gcry_cipher_open failed: %s\n", gpg_strerror(rc));
 
356
      wipememory (buffer, length);
 
357
      return;
 
358
    }
 
359
  if (set_key_iv (chd, salt, iter, pw,
 
360
                  cipher_algo == GCRY_CIPHER_RFC2268_40? 5:24))
 
361
    {
 
362
      wipememory (buffer, length);
 
363
      goto leave;
 
364
    }
 
365
 
 
366
  rc = encrypt? gcry_cipher_encrypt (chd, buffer, length, NULL, 0)
 
367
              : gcry_cipher_decrypt (chd, buffer, length, NULL, 0);
 
368
 
 
369
  if (rc)
 
370
    {
 
371
      wipememory (buffer, length);
 
372
      log_error ( "en/de-crytion failed: %s\n", gpg_strerror (rc));
 
373
      goto leave;
 
374
    }
 
375
 
 
376
 leave:
 
377
  gcry_cipher_close (chd);
 
378
}
 
379
  
 
380
 
 
381
 
 
382
static int
 
383
parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
 
384
                          int startoffset, const char *pw,
 
385
                          void (*certcb)(void*, const unsigned char*, size_t),
 
386
                          void *certcbarg)
 
387
{
 
388
  struct tag_info ti;
 
389
  const unsigned char *p = buffer;
 
390
  size_t n = length;
 
391
  const char *where;
 
392
  char salt[8];
 
393
  unsigned int iter;
 
394
  unsigned char *plain = NULL;
 
395
  int bad_pass = 0;
 
396
  
 
397
  where = "start";
 
398
  if (parse_tag (&p, &n, &ti))
 
399
    goto bailout;
 
400
  if (ti.class != CONTEXT || ti.tag)
 
401
    goto bailout;
 
402
  if (parse_tag (&p, &n, &ti))
 
403
    goto bailout;
 
404
  if (ti.tag != TAG_SEQUENCE)
 
405
    goto bailout;
 
406
 
 
407
  where = "bag.encryptedData.version";
 
408
  if (parse_tag (&p, &n, &ti))
 
409
    goto bailout;
 
410
  if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 0)
 
411
    goto bailout;
 
412
  p++; n--;
 
413
  if (parse_tag (&p, &n, &ti))
 
414
    goto bailout;
 
415
  if (ti.tag != TAG_SEQUENCE)
 
416
    goto bailout;
 
417
 
 
418
  where = "bag.encryptedData.data";
 
419
  if (parse_tag (&p, &n, &ti))
 
420
    goto bailout;
 
421
  if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data)
 
422
      || memcmp (p, oid_data, DIM(oid_data)))
 
423
    goto bailout;
 
424
  p += DIM(oid_data);
 
425
  n -= DIM(oid_data);
 
426
 
 
427
  where = "bag.encryptedData.keyinfo";
 
428
  if (parse_tag (&p, &n, &ti))
 
429
    goto bailout;
 
430
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
431
    goto bailout;
 
432
  if (parse_tag (&p, &n, &ti))
 
433
    goto bailout;
 
434
  if (!ti.class && ti.tag == TAG_OBJECT_ID 
 
435
      && ti.length == DIM(oid_pbeWithSHAAnd40BitRC2_CBC)
 
436
      && !memcmp (p, oid_pbeWithSHAAnd40BitRC2_CBC,
 
437
                  DIM(oid_pbeWithSHAAnd40BitRC2_CBC)))
 
438
    {
 
439
      p += DIM(oid_pbeWithSHAAnd40BitRC2_CBC);
 
440
      n -= DIM(oid_pbeWithSHAAnd40BitRC2_CBC);
 
441
    }
 
442
  else
 
443
    goto bailout;
 
444
 
 
445
  where = "rc2-params";
 
446
  if (parse_tag (&p, &n, &ti))
 
447
    goto bailout;
 
448
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
449
    goto bailout;
 
450
  if (parse_tag (&p, &n, &ti))
 
451
    goto bailout;
 
452
  if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 )
 
453
    goto bailout;
 
454
  memcpy (salt, p, 8);
 
455
  p += 8;
 
456
  n -= 8;
 
457
  if (parse_tag (&p, &n, &ti))
 
458
    goto bailout;
 
459
  if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
 
460
    goto bailout;
 
461
  for (iter=0; ti.length; ti.length--)
 
462
    {
 
463
      iter <<= 8;
 
464
      iter |= (*p++) & 0xff; 
 
465
      n--;
 
466
    }
 
467
  
 
468
  where = "rc2-ciphertext";
 
469
  if (parse_tag (&p, &n, &ti))
 
470
    goto bailout;
 
471
  if (ti.class != CONTEXT || ti.tag != 0 || !ti.length )
 
472
    goto bailout;
 
473
  
 
474
  log_info ("%lu bytes of RC2 encrypted text\n", ti.length);
 
475
 
 
476
  plain = gcry_malloc_secure (ti.length);
 
477
  if (!plain)
 
478
    {
 
479
      log_error ("error allocating decryption buffer\n");
 
480
      goto bailout;
 
481
    }
 
482
  memcpy (plain, p, ti.length);
 
483
  crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_RFC2268_40, 0);
 
484
  n = ti.length;
 
485
  startoffset = 0;
 
486
  buffer = p = plain;
 
487
 
 
488
/*   { */
 
489
/*     FILE *fp = fopen ("tmp-rc2-plain.der", "wb"); */
 
490
/*     if (!fp || fwrite (p, n, 1, fp) != 1) */
 
491
/*       exit (2); */
 
492
/*     fclose (fp); */
 
493
/*   } */
 
494
 
 
495
  where = "outer.outer.seq";
 
496
  if (parse_tag (&p, &n, &ti))
 
497
    {
 
498
      bad_pass = 1;
 
499
      goto bailout;
 
500
    }
 
501
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
502
    {
 
503
      bad_pass = 1;
 
504
      goto bailout;
 
505
    }
 
506
 
 
507
  if (parse_tag (&p, &n, &ti))
 
508
    {
 
509
      bad_pass = 1;
 
510
      goto bailout;
 
511
    }
 
512
 
 
513
  /* Loop over all certificates inside the bab. */
 
514
  while (n)
 
515
    {
 
516
      int isbag = 0;
 
517
 
 
518
      where = "certbag.nextcert";
 
519
      if (ti.class || ti.tag != TAG_SEQUENCE)
 
520
        goto bailout;
 
521
 
 
522
      where = "certbag.objectidentifier";
 
523
      if (parse_tag (&p, &n, &ti))
 
524
        goto bailout;
 
525
      if (ti.class || ti.tag != TAG_OBJECT_ID)
 
526
        goto bailout;
 
527
      if ( ti.length == DIM(oid_pkcs_12_CertBag)
 
528
           && !memcmp (p, oid_pkcs_12_CertBag, DIM(oid_pkcs_12_CertBag)))
 
529
        {
 
530
          p += DIM(oid_pkcs_12_CertBag);
 
531
          n -= DIM(oid_pkcs_12_CertBag);
 
532
        }
 
533
      else if ( ti.length == DIM(oid_pkcs_12_CrlBag)
 
534
           && !memcmp (p, oid_pkcs_12_CrlBag, DIM(oid_pkcs_12_CrlBag)))
 
535
        {
 
536
          p += DIM(oid_pkcs_12_CrlBag);
 
537
          n -= DIM(oid_pkcs_12_CrlBag);
 
538
          isbag = 1;
 
539
        }
 
540
      else
 
541
        goto bailout;
 
542
 
 
543
      where = "certbag.before.certheader";
 
544
      if (parse_tag (&p, &n, &ti))
 
545
        goto bailout;
 
546
      if (ti.class != CONTEXT || ti.tag)
 
547
        goto bailout;
 
548
      if (isbag)
 
549
        {
 
550
          log_info ("skipping unsupported crlBag\n");
 
551
          p += ti.length;
 
552
          n -= ti.length;
 
553
        }
 
554
      else
 
555
        {
 
556
          if (parse_tag (&p, &n, &ti))
 
557
            goto bailout;
 
558
          if (ti.class || ti.tag != TAG_SEQUENCE)
 
559
            goto bailout;
 
560
          if (parse_tag (&p, &n, &ti))
 
561
            goto bailout;
 
562
          if (ti.class || ti.tag != TAG_OBJECT_ID
 
563
              || ti.length != DIM(oid_x509Certificate_for_pkcs_12)
 
564
              || memcmp (p, oid_x509Certificate_for_pkcs_12,
 
565
                         DIM(oid_x509Certificate_for_pkcs_12)))
 
566
            goto bailout;
 
567
          p += DIM(oid_x509Certificate_for_pkcs_12);
 
568
          n -= DIM(oid_x509Certificate_for_pkcs_12);
 
569
          
 
570
          where = "certbag.before.octetstring";
 
571
          if (parse_tag (&p, &n, &ti))
 
572
            goto bailout;
 
573
          if (ti.class != CONTEXT || ti.tag)
 
574
            goto bailout;
 
575
          if (parse_tag (&p, &n, &ti))
 
576
            goto bailout;
 
577
          if (ti.class || ti.tag != TAG_OCTET_STRING || ti.ndef)
 
578
            goto bailout;
 
579
          
 
580
          /* Return the certificate. */
 
581
          if (certcb)
 
582
            certcb (certcbarg, p, ti.length);
 
583
   
 
584
          p += ti.length;
 
585
          n -= ti.length;
 
586
        }
 
587
 
 
588
      /* Ugly hack to cope with the padding: Forget about the rest if
 
589
         that it is less than the cipher's block length. */
 
590
      if (n < 8)
 
591
        n = 0;  
 
592
 
 
593
      /* Skip the optional SET with the pkcs12 cert attributes. */
 
594
      if (n)
 
595
        {
 
596
          where = "bag.attributes";
 
597
          if (parse_tag (&p, &n, &ti))
 
598
            goto bailout;
 
599
          if (!ti.class && ti.tag == TAG_SEQUENCE)
 
600
            ; /* No attributes. */
 
601
          else if (!ti.class && ti.tag == TAG_SET && !ti.ndef)
 
602
            { /* The optional SET. */
 
603
              p += ti.length;
 
604
              n -= ti.length;
 
605
              if (n < 8)
 
606
                n = 0;
 
607
              if (n && parse_tag (&p, &n, &ti))
 
608
                goto bailout;
 
609
            }
 
610
          else
 
611
            goto bailout;
 
612
        }
 
613
    }
 
614
  
 
615
  gcry_free (plain);
 
616
 
 
617
  return 0;
 
618
 bailout:
 
619
  gcry_free (plain);
 
620
  log_error ("encryptedData error at \"%s\", offset %u\n",
 
621
             where, (p - buffer)+startoffset);
 
622
  if (bad_pass)
 
623
    {
 
624
      /* Note, that the following string might be used by other programs
 
625
         to check for a bad passphrase; it should therefore not be
 
626
         translated or changed. */
 
627
      log_error ("possibly bad passphrase given\n");
 
628
    }
 
629
  return -1;
 
630
}
 
631
 
 
632
static gcry_mpi_t *
 
633
parse_bag_data (const unsigned char *buffer, size_t length, int startoffset,
 
634
                const char *pw)
 
635
{
 
636
  int rc;
 
637
  struct tag_info ti;
 
638
  const unsigned char *p = buffer;
 
639
  size_t n = length;
 
640
  const char *where;
 
641
  char salt[8];
 
642
  unsigned int iter;
 
643
  int len;
 
644
  unsigned char *plain = NULL;
 
645
  gcry_mpi_t *result = NULL;
 
646
  int result_count, i;
 
647
 
 
648
  where = "start";
 
649
  if (parse_tag (&p, &n, &ti))
 
650
    goto bailout;
 
651
  if (ti.class != CONTEXT || ti.tag)
 
652
    goto bailout;
 
653
  if (parse_tag (&p, &n, &ti))
 
654
    goto bailout;
 
655
  if (ti.class || ti.tag != TAG_OCTET_STRING)
 
656
    goto bailout;
 
657
 
 
658
  where = "data.outerseqs";
 
659
  if (parse_tag (&p, &n, &ti))
 
660
    goto bailout;
 
661
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
662
    goto bailout;
 
663
  if (parse_tag (&p, &n, &ti))
 
664
    goto bailout;
 
665
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
666
    goto bailout;
 
667
 
 
668
  where = "data.objectidentifier";
 
669
  if (parse_tag (&p, &n, &ti))
 
670
    goto bailout;
 
671
  if (ti.class || ti.tag != TAG_OBJECT_ID
 
672
      || ti.length != DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag)
 
673
      || memcmp (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
 
674
                 DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag)))
 
675
    goto bailout;
 
676
  p += DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag);
 
677
  n -= DIM(oid_pkcs_12_pkcs_8ShroudedKeyBag);
 
678
 
 
679
  where = "shrouded,outerseqs";
 
680
  if (parse_tag (&p, &n, &ti))
 
681
    goto bailout;
 
682
  if (ti.class != CONTEXT || ti.tag)
 
683
    goto bailout;
 
684
  if (parse_tag (&p, &n, &ti))
 
685
    goto bailout;
 
686
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
687
    goto bailout;
 
688
  if (parse_tag (&p, &n, &ti))
 
689
    goto bailout;
 
690
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
691
    goto bailout;
 
692
  if (parse_tag (&p, &n, &ti))
 
693
    goto bailout;
 
694
  if (ti.class || ti.tag != TAG_OBJECT_ID
 
695
      || ti.length != DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)
 
696
      || memcmp (p, oid_pbeWithSHAAnd3_KeyTripleDES_CBC,
 
697
                 DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC)))
 
698
    goto bailout;
 
699
  p += DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
 
700
  n -= DIM(oid_pbeWithSHAAnd3_KeyTripleDES_CBC);
 
701
 
 
702
  where = "3des-params";
 
703
  if (parse_tag (&p, &n, &ti))
 
704
    goto bailout;
 
705
  if (ti.class || ti.tag != TAG_SEQUENCE)
 
706
    goto bailout;
 
707
  if (parse_tag (&p, &n, &ti))
 
708
    goto bailout;
 
709
  if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 )
 
710
    goto bailout;
 
711
  memcpy (salt, p, 8);
 
712
  p += 8;
 
713
  n -= 8;
 
714
  if (parse_tag (&p, &n, &ti))
 
715
    goto bailout;
 
716
  if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
 
717
    goto bailout;
 
718
  for (iter=0; ti.length; ti.length--)
 
719
    {
 
720
      iter <<= 8;
 
721
      iter |= (*p++) & 0xff; 
 
722
      n--;
 
723
    }
 
724
  
 
725
  where = "3des-ciphertext";
 
726
  if (parse_tag (&p, &n, &ti))
 
727
    goto bailout;
 
728
  if (ti.class || ti.tag != TAG_OCTET_STRING || !ti.length )
 
729
    goto bailout;
 
730
  
 
731
  log_info ("%lu bytes of 3DES encrypted text\n", ti.length);
 
732
  
 
733
  plain = gcry_malloc_secure (ti.length);
 
734
  if (!plain)
 
735
    {
 
736
      log_error ("error allocating decryption buffer\n");
 
737
      goto bailout;
 
738
    }
 
739
  memcpy (plain, p, ti.length);
 
740
  crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_3DES, 0);
 
741
  n = ti.length;
 
742
  startoffset = 0;
 
743
  buffer = p = plain;
 
744
 
 
745
  where = "decrypted-text";
 
746
  if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
 
747
    goto bailout;
 
748
  if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER
 
749
      || ti.length != 1 || *p)
 
750
    goto bailout;
 
751
  p++; n--;
 
752
  if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
 
753
    goto bailout;
 
754
  len = ti.length;
 
755
  if (parse_tag (&p, &n, &ti))
 
756
    goto bailout;
 
757
  if (len < ti.nhdr)
 
758
    goto bailout;
 
759
  len -= ti.nhdr;
 
760
  if (ti.class || ti.tag != TAG_OBJECT_ID
 
761
      || ti.length != DIM(oid_rsaEncryption)
 
762
      || memcmp (p, oid_rsaEncryption,
 
763
                 DIM(oid_rsaEncryption)))
 
764
    goto bailout;
 
765
  p += DIM (oid_rsaEncryption);
 
766
  n -= DIM (oid_rsaEncryption);
 
767
  if (len < ti.length)
 
768
    goto bailout;
 
769
  len -= ti.length;
 
770
  if (n < len)
 
771
    goto bailout;
 
772
  p += len;
 
773
  n -= len;
 
774
  if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_OCTET_STRING)
 
775
    goto bailout;
 
776
  if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
 
777
    goto bailout;
 
778
  len = ti.length;
 
779
 
 
780
  result = gcry_calloc (10, sizeof *result);
 
781
  if (!result)
 
782
    {
 
783
      log_error ( "error allocating result array\n");
 
784
      goto bailout;
 
785
    }
 
786
  result_count = 0;
 
787
 
 
788
  where = "reading.key-parameters";
 
789
  for (result_count=0; len && result_count < 9;)
 
790
    {
 
791
      if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_INTEGER)
 
792
        goto bailout;
 
793
      if (len < ti.nhdr)
 
794
        goto bailout;
 
795
      len -= ti.nhdr;
 
796
      if (len < ti.length)
 
797
        goto bailout;
 
798
      len -= ti.length;
 
799
      if (!result_count && ti.length == 1 && !*p)
 
800
        ; /* ignore the very first one if it is a 0 */
 
801
      else 
 
802
        {
 
803
          rc = gcry_mpi_scan (result+result_count, GCRYMPI_FMT_USG, p,
 
804
                              ti.length, NULL);
 
805
          if (rc)
 
806
            {
 
807
              log_error ("error parsing key parameter: %s\n",
 
808
                         gpg_strerror (rc));
 
809
              goto bailout;
 
810
            }
 
811
          result_count++;
 
812
        }
 
813
      p += ti.length;
 
814
      n -= ti.length;
 
815
    }
 
816
  if (len)
 
817
    goto bailout;
 
818
 
 
819
  return result;
 
820
 
 
821
 bailout:
 
822
  gcry_free (plain);
 
823
  if (result)
 
824
    {
 
825
      for (i=0; result[i]; i++)
 
826
        gcry_mpi_release (result[i]);
 
827
      gcry_free (result);
 
828
    }
 
829
  log_error ( "data error at \"%s\", offset %u\n",
 
830
              where, (p - buffer) + startoffset);
 
831
  return NULL;
 
832
}
 
833
 
 
834
 
 
835
/* Parse a PKCS12 object and return an array of MPI representing the
 
836
   secret key parameters.  This is a very limited implementation in
 
837
   that it is only able to look for 3DES encoded encryptedData and
 
838
   tries to extract the first private key object it finds.  In case of
 
839
   an error NULL is returned. CERTCB and CERRTCBARG are used to pass
 
840
   X.509 certificates back to the caller. */
 
841
gcry_mpi_t *
 
842
p12_parse (const unsigned char *buffer, size_t length, const char *pw,
 
843
           void (*certcb)(void*, const unsigned char*, size_t),
 
844
           void *certcbarg)
 
845
{
 
846
  struct tag_info ti;
 
847
  const unsigned char *p = buffer;
 
848
  size_t n = length;
 
849
  const char *where;
 
850
  int bagseqlength, len;
 
851
 
 
852
  where = "pfx";
 
853
  if (parse_tag (&p, &n, &ti))
 
854
    goto bailout;
 
855
  if (ti.tag != TAG_SEQUENCE)
 
856
    goto bailout;
 
857
 
 
858
  where = "pfxVersion";
 
859
  if (parse_tag (&p, &n, &ti))
 
860
    goto bailout;
 
861
  if (ti.tag != TAG_INTEGER || ti.length != 1 || *p != 3)
 
862
    goto bailout;
 
863
  p++; n--;
 
864
  
 
865
  where = "authSave";
 
866
  if (parse_tag (&p, &n, &ti))
 
867
    goto bailout;
 
868
  if (ti.tag != TAG_SEQUENCE)
 
869
    goto bailout;
 
870
  if (parse_tag (&p, &n, &ti))
 
871
    goto bailout;
 
872
  if (ti.tag != TAG_OBJECT_ID || ti.length != DIM(oid_data)
 
873
      || memcmp (p, oid_data, DIM(oid_data)))
 
874
    goto bailout;
 
875
  p += DIM(oid_data);
 
876
  n -= DIM(oid_data);
 
877
 
 
878
  if (parse_tag (&p, &n, &ti))
 
879
    goto bailout;
 
880
  if (ti.class != CONTEXT || ti.tag)
 
881
    goto bailout;
 
882
  if (parse_tag (&p, &n, &ti))
 
883
    goto bailout;
 
884
  if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING)
 
885
    goto bailout;
 
886
 
 
887
  where = "bags";
 
888
  if (parse_tag (&p, &n, &ti))
 
889
    goto bailout;
 
890
  if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
 
891
    goto bailout;
 
892
  bagseqlength = ti.length;
 
893
  while (bagseqlength)
 
894
    {
 
895
      /*log_debug ( "at offset %u\n", (p - buffer));*/
 
896
      where = "bag-sequence";
 
897
      if (parse_tag (&p, &n, &ti))
 
898
        goto bailout;
 
899
      if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
 
900
        goto bailout;
 
901
 
 
902
      if (bagseqlength < ti.nhdr)
 
903
        goto bailout;
 
904
      bagseqlength -= ti.nhdr;
 
905
      if (bagseqlength < ti.length)
 
906
        goto bailout;
 
907
      bagseqlength -= ti.length;
 
908
      len = ti.length;
 
909
 
 
910
      if (parse_tag (&p, &n, &ti))
 
911
        goto bailout;
 
912
      len -= ti.nhdr;
 
913
      if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData)
 
914
          && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData)))
 
915
        {
 
916
          p += DIM(oid_encryptedData);
 
917
          n -= DIM(oid_encryptedData);
 
918
          len -= DIM(oid_encryptedData);
 
919
          where = "bag.encryptedData";
 
920
          if (parse_bag_encrypted_data (p, n, (p - buffer), pw,
 
921
                                        certcb, certcbarg))
 
922
            goto bailout;
 
923
        }
 
924
      else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
 
925
          && !memcmp (p, oid_data, DIM(oid_data)))
 
926
        {
 
927
          p += DIM(oid_data);
 
928
          n -= DIM(oid_data);
 
929
          len -= DIM(oid_data);
 
930
          return parse_bag_data (p, n, (p-buffer), pw);
 
931
        }
 
932
      else
 
933
        log_info ( "unknown bag type - skipped\n");
 
934
 
 
935
      if (len < 0 || len > n)
 
936
        goto bailout;
 
937
      p += len;
 
938
      n -= len;
 
939
    }
 
940
  
 
941
  return NULL;
 
942
 bailout:
 
943
  log_error ("error at \"%s\", offset %u\n", where, (p - buffer));
 
944
  return NULL;
 
945
}
 
946
 
 
947
 
 
948
 
 
949
static size_t
 
950
compute_tag_length (size_t n)
 
951
{     
 
952
  int needed = 0;
 
953
 
 
954
  if (n < 128)
 
955
    needed += 2; /* tag and one length byte */
 
956
  else if (n < 256)
 
957
    needed += 3; /* tag, number of length bytes, 1 length byte */
 
958
  else if (n < 65536)
 
959
    needed += 4; /* tag, number of length bytes, 2 length bytes */
 
960
  else
 
961
    {
 
962
      log_error ("object too larger to encode\n");
 
963
      return 0;
 
964
    }
 
965
  return needed;
 
966
}
 
967
 
 
968
static unsigned char *
 
969
store_tag_length (unsigned char *p, int tag, size_t n)
 
970
{     
 
971
  if (tag == TAG_SEQUENCE)
 
972
    tag |= 0x20; /* constructed */
 
973
 
 
974
  *p++ = tag;
 
975
  if (n < 128)
 
976
    *p++ = n;
 
977
  else if (n < 256)
 
978
    {
 
979
      *p++ = 0x81;
 
980
      *p++ = n;
 
981
    }
 
982
  else if (n < 65536)
 
983
    {
 
984
      *p++ = 0x82;
 
985
      *p++ = n >> 8;
 
986
      *p++ = n;
 
987
    }
 
988
 
 
989
  return p;
 
990
}
 
991
 
 
992
 
 
993
/* Create the final PKCS-12 object from the sequences contained in
 
994
   SEQLIST.  That array is terminated with an NULL object */
 
995
static unsigned char *
 
996
create_final (struct buffer_s *sequences, size_t *r_length)
 
997
{
 
998
  int i;
 
999
  size_t needed = 0;
 
1000
  size_t len[8], n;
 
1001
  unsigned char *result, *p;
 
1002
  size_t resultlen;
 
1003
 
 
1004
  /* 8 steps to create the pkcs#12 Krampf. */
 
1005
 
 
1006
  /* 7. All the buffers. */
 
1007
  for (i=0; sequences[i].buffer; i++)
 
1008
    needed += sequences[i].length;
 
1009
 
 
1010
  /* 6. This goes into a sequences. */
 
1011
  len[6] = needed;
 
1012
  n = compute_tag_length (needed);
 
1013
  needed += n;
 
1014
 
 
1015
  /* 5. Encapsulate all in an octet string. */
 
1016
  len[5] = needed;
 
1017
  n = compute_tag_length (needed);
 
1018
  needed += n;
 
1019
 
 
1020
  /* 4. And tag it with [0]. */
 
1021
  len[4] = needed;
 
1022
  n = compute_tag_length (needed);
 
1023
  needed += n;
 
1024
 
 
1025
  /* 3. Prepend an data OID. */
 
1026
  needed += 2 + DIM (oid_data);
 
1027
 
 
1028
  /* 2. Put all into a sequences. */
 
1029
  len[2] = needed;
 
1030
  n = compute_tag_length (needed);
 
1031
  needed += n;
 
1032
 
 
1033
  /* 1. Prepend the version integer 3. */
 
1034
  needed += 3;
 
1035
 
 
1036
  /* 0. And the final outer sequence. */
 
1037
  len[0] = needed;
 
1038
  n = compute_tag_length (needed);
 
1039
  needed += n;
 
1040
 
 
1041
  /* Allocate a buffer. */
 
1042
  result = gcry_malloc (needed);
 
1043
  if (!result)
 
1044
    {
 
1045
      log_error ("error allocating buffer\n");
 
1046
      return NULL;
 
1047
    }
 
1048
  p = result;
 
1049
 
 
1050
  /* 0. Store the very outer sequence. */
 
1051
  p = store_tag_length (p, TAG_SEQUENCE, len[0]);
 
1052
 
 
1053
  /* 1. Store the version integer 3. */
 
1054
  *p++ = TAG_INTEGER;
 
1055
  *p++ = 1; 
 
1056
  *p++ = 3;
 
1057
 
 
1058
  /* 2. Store another sequence. */
 
1059
  p = store_tag_length (p, TAG_SEQUENCE, len[2]);
 
1060
 
 
1061
  /* 3. Store the data OID. */
 
1062
  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
 
1063
  memcpy (p, oid_data, DIM (oid_data)); 
 
1064
  p += DIM (oid_data); 
 
1065
 
 
1066
  /* 4. Next comes a context tag. */
 
1067
  p = store_tag_length (p, 0xa0, len[4]);
 
1068
 
 
1069
  /* 5. And an octet string. */
 
1070
  p = store_tag_length (p, TAG_OCTET_STRING, len[5]);
 
1071
 
 
1072
  /* 6. And the inner sequence. */
 
1073
  p = store_tag_length (p, TAG_SEQUENCE, len[6]);
 
1074
 
 
1075
  /* 7. Append all the buffers. */
 
1076
  for (i=0; sequences[i].buffer; i++)
 
1077
    {
 
1078
      memcpy (p, sequences[i].buffer, sequences[i].length);
 
1079
      p += sequences[i].length;
 
1080
    }
 
1081
 
 
1082
  /* Ready. */
 
1083
  resultlen = p - result;
 
1084
  if (needed != resultlen)
 
1085
    log_debug ("length mismatch: %u, %u\n", needed, resultlen);
 
1086
 
 
1087
  *r_length = resultlen;
 
1088
  return result;
 
1089
}
 
1090
 
 
1091
 
 
1092
/* Build a DER encoded SEQUENCE with the key:
 
1093
 
 
1094
   SEQUENCE {
 
1095
     INTEGER 0
 
1096
     SEQUENCE {
 
1097
       OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
 
1098
       NULL
 
1099
       }
 
1100
     OCTET STRING, encapsulates {
 
1101
       SEQUENCE {
 
1102
         INTEGER 0
 
1103
         INTEGER
 
1104
         INTEGER 
 
1105
         INTEGER
 
1106
         INTEGER
 
1107
         INTEGER
 
1108
         INTEGER
 
1109
         INTEGER
 
1110
         INTEGER
 
1111
         }
 
1112
       }
 
1113
     }
 
1114
*/  
 
1115
  
 
1116
static unsigned char * 
 
1117
build_key_sequence (gcry_mpi_t *kparms, size_t *r_length)
 
1118
{
 
1119
  int rc, i;
 
1120
  size_t needed, n;
 
1121
  unsigned char *plain, *p;
 
1122
  size_t plainlen;
 
1123
  size_t outseqlen, oidseqlen, octstrlen, inseqlen;
 
1124
 
 
1125
  needed = 3; /* The version(?) integer of value 0. */
 
1126
  for (i=0; kparms[i]; i++)
 
1127
    {
 
1128
      n = 0;
 
1129
      rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
 
1130
      if (rc)
 
1131
        {
 
1132
          log_error ("error formatting parameter: %s\n", gpg_strerror (rc));
 
1133
          return NULL;
 
1134
        }
 
1135
      needed += n;
 
1136
      n = compute_tag_length (n);
 
1137
      if (!n)
 
1138
        return NULL;
 
1139
      needed += n;
 
1140
    }
 
1141
  if (i != 8)
 
1142
    {
 
1143
      log_error ("invalid paramters for p12_build\n");
 
1144
      return NULL;
 
1145
    }
 
1146
  /* Now this all goes into a sequence. */
 
1147
  inseqlen = needed;
 
1148
  n = compute_tag_length (needed);
 
1149
  if (!n)
 
1150
    return NULL;
 
1151
  needed += n;
 
1152
  /* Encapsulate all into an octet string. */
 
1153
  octstrlen = needed;
 
1154
  n = compute_tag_length (needed);
 
1155
  if (!n)
 
1156
    return NULL;
 
1157
  needed += n;
 
1158
  /* Prepend the object identifier sequence. */
 
1159
  oidseqlen = 2 + DIM (oid_rsaEncryption) + 2;
 
1160
  needed += 2 + oidseqlen;
 
1161
  /* The version number. */
 
1162
  needed += 3;
 
1163
  /* And finally put the whole thing into a sequence. */
 
1164
  outseqlen = needed;
 
1165
  n = compute_tag_length (needed);
 
1166
  if (!n)
 
1167
    return NULL;
 
1168
  needed += n;
 
1169
  
 
1170
  /* allocate 8 extra bytes for padding */
 
1171
  plain = gcry_malloc_secure (needed+8);
 
1172
  if (!plain)
 
1173
    {
 
1174
      log_error ("error allocating encryption buffer\n");
 
1175
      return NULL;
 
1176
    }
 
1177
  
 
1178
  /* And now fill the plaintext buffer. */
 
1179
  p = plain;
 
1180
  p = store_tag_length (p, TAG_SEQUENCE, outseqlen);
 
1181
  /* Store version. */
 
1182
  *p++ = TAG_INTEGER;
 
1183
  *p++ = 1;
 
1184
  *p++ = 0;
 
1185
  /* Store object identifier sequence. */
 
1186
  p = store_tag_length (p, TAG_SEQUENCE, oidseqlen);
 
1187
  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_rsaEncryption));
 
1188
  memcpy (p, oid_rsaEncryption, DIM (oid_rsaEncryption)); 
 
1189
  p += DIM (oid_rsaEncryption); 
 
1190
  *p++ = TAG_NULL;
 
1191
  *p++ = 0;
 
1192
  /* Start with the octet string. */
 
1193
  p = store_tag_length (p, TAG_OCTET_STRING, octstrlen);
 
1194
  p = store_tag_length (p, TAG_SEQUENCE, inseqlen);
 
1195
  /* Store the key parameters. */
 
1196
  *p++ = TAG_INTEGER;
 
1197
  *p++ = 1;
 
1198
  *p++ = 0;
 
1199
  for (i=0; kparms[i]; i++)
 
1200
    {
 
1201
      n = 0;
 
1202
      rc = gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &n, kparms[i]);
 
1203
      if (rc)
 
1204
        {
 
1205
          log_error ("oops: error formatting parameter: %s\n",
 
1206
                     gpg_strerror (rc));
 
1207
          gcry_free (plain);
 
1208
          return NULL;
 
1209
        }
 
1210
      p = store_tag_length (p, TAG_INTEGER, n);
 
1211
      
 
1212
      n = plain + needed - p;
 
1213
      rc = gcry_mpi_print (GCRYMPI_FMT_STD, p, n, &n, kparms[i]);
 
1214
      if (rc)
 
1215
        {
 
1216
          log_error ("oops: error storing parameter: %s\n",
 
1217
                     gpg_strerror (rc));
 
1218
          gcry_free (plain);
 
1219
          return NULL;
 
1220
        }
 
1221
      p += n;
 
1222
    }
 
1223
 
 
1224
  plainlen = p - plain;
 
1225
  assert (needed == plainlen);
 
1226
  /* Append some pad characters; we already allocated extra space. */
 
1227
  n = 8 - plainlen % 8;
 
1228
  for (;(plainlen % 8); plainlen++)
 
1229
    *p++ = n;
 
1230
 
 
1231
  *r_length = plainlen;
 
1232
  return plain;
 
1233
}
 
1234
 
 
1235
 
 
1236
 
 
1237
static unsigned char *
 
1238
build_key_bag (unsigned char *buffer, size_t buflen, char *salt,
 
1239
               size_t *r_length)
 
1240
{
 
1241
  size_t len[11], needed;
 
1242
  unsigned char *p, *keybag;
 
1243
  size_t keybaglen;
 
1244
 
 
1245
  /* Walk 11 steps down to collect the info: */
 
1246
 
 
1247
  /* 10. The data goes into an octet string. */
 
1248
  needed = compute_tag_length (buflen);
 
1249
  needed += buflen;
 
1250
 
 
1251
  /* 9. Prepend the algorithm identifier. */
 
1252
  needed += DIM (data_3desiter2048);
 
1253
 
 
1254
  /* 8. Put a sequence around. */
 
1255
  len[8] = needed;
 
1256
  needed += compute_tag_length (needed);
 
1257
 
 
1258
  /* 7. Prepend a [0] tag. */
 
1259
  len[7] = needed;
 
1260
  needed += compute_tag_length (needed);
 
1261
 
 
1262
  /* 6. Prepend the shroudedKeyBag OID. */
 
1263
  needed += 2 + DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag);
 
1264
 
 
1265
  /* 5+4. Put all into two sequences. */
 
1266
  len[5] = needed;
 
1267
  needed += compute_tag_length ( needed);
 
1268
  len[4] = needed;
 
1269
  needed += compute_tag_length (needed);
 
1270
 
 
1271
  /* 3. This all goes into an octet string. */
 
1272
  len[3] = needed;
 
1273
  needed += compute_tag_length (needed);
 
1274
 
 
1275
  /* 2. Prepend another [0] tag. */
 
1276
  len[2] = needed;
 
1277
  needed += compute_tag_length (needed);
 
1278
 
 
1279
  /* 1. Prepend the data OID. */
 
1280
  needed += 2 + DIM (oid_data);
 
1281
 
 
1282
  /* 0. Prepend another sequence. */
 
1283
  len[0] = needed;
 
1284
  needed += compute_tag_length (needed);
 
1285
 
 
1286
  /* Now that we have all length information, allocate a buffer. */
 
1287
  p = keybag = gcry_malloc (needed);
 
1288
  if (!keybag)
 
1289
    {
 
1290
      log_error ("error allocating buffer\n");
 
1291
      return NULL;
 
1292
    }
 
1293
 
 
1294
  /* Walk 11 steps up to store the data. */
 
1295
 
 
1296
  /* 0. Store the first sequence. */
 
1297
  p = store_tag_length (p, TAG_SEQUENCE, len[0]);
 
1298
 
 
1299
  /* 1. Store the data OID. */
 
1300
  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
 
1301
  memcpy (p, oid_data, DIM (oid_data)); 
 
1302
  p += DIM (oid_data); 
 
1303
 
 
1304
  /* 2. Store a [0] tag. */
 
1305
  p = store_tag_length (p, 0xa0, len[2]);
 
1306
 
 
1307
  /* 3. And an octet string. */
 
1308
  p = store_tag_length (p, TAG_OCTET_STRING, len[3]);
 
1309
 
 
1310
  /* 4+5. Two sequences. */
 
1311
  p = store_tag_length (p, TAG_SEQUENCE, len[4]);
 
1312
  p = store_tag_length (p, TAG_SEQUENCE, len[5]);
 
1313
 
 
1314
  /* 6. Store the shroudedKeyBag OID. */
 
1315
  p = store_tag_length (p, TAG_OBJECT_ID,
 
1316
                        DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag));
 
1317
  memcpy (p, oid_pkcs_12_pkcs_8ShroudedKeyBag,
 
1318
          DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag)); 
 
1319
  p += DIM (oid_pkcs_12_pkcs_8ShroudedKeyBag); 
 
1320
 
 
1321
  /* 7. Store a [0] tag. */
 
1322
  p = store_tag_length (p, 0xa0, len[7]);
 
1323
 
 
1324
  /* 8. Store a sequence. */
 
1325
  p = store_tag_length (p, TAG_SEQUENCE, len[8]);
 
1326
 
 
1327
  /* 9. Now for the pre-encoded algorithm identifier and the salt. */
 
1328
  memcpy (p, data_3desiter2048, DIM (data_3desiter2048));
 
1329
  memcpy (p + DATA_3DESITER2048_SALT_OFF, salt, 8);
 
1330
  p += DIM (data_3desiter2048);
 
1331
 
 
1332
  /* 10. And finally the octet string with the encrypted data. */
 
1333
  p = store_tag_length (p, TAG_OCTET_STRING, buflen);
 
1334
  memcpy (p, buffer, buflen);
 
1335
  p += buflen;
 
1336
  keybaglen = p - keybag;
 
1337
  
 
1338
  if (needed != keybaglen)
 
1339
    log_debug ("length mismatch: %u, %u\n", needed, keybaglen);
 
1340
  
 
1341
  *r_length = keybaglen;
 
1342
  return keybag;
 
1343
}
 
1344
 
 
1345
 
 
1346
static unsigned char *
 
1347
build_cert_bag (unsigned char *buffer, size_t buflen, char *salt,
 
1348
                size_t *r_length)
 
1349
{
 
1350
  size_t len[9], needed;
 
1351
  unsigned char *p, *certbag;
 
1352
  size_t certbaglen;
 
1353
 
 
1354
  /* Walk 9 steps down to collect the info: */
 
1355
 
 
1356
  /* 8. The data goes into an octet string. */
 
1357
  needed = compute_tag_length (buflen);
 
1358
  needed += buflen;
 
1359
 
 
1360
  /* 7. The algorithm identifier. */
 
1361
  needed += DIM (data_rc2iter2048);
 
1362
 
 
1363
  /* 6. The data OID. */
 
1364
  needed += 2 + DIM (oid_data);
 
1365
 
 
1366
  /* 5. A sequence. */
 
1367
  len[5] = needed;
 
1368
  needed += compute_tag_length ( needed);
 
1369
 
 
1370
  /* 4. An integer. */
 
1371
  needed += 3;
 
1372
 
 
1373
  /* 3. A sequence. */
 
1374
  len[3] = needed;
 
1375
  needed += compute_tag_length (needed);
 
1376
 
 
1377
  /* 2.  A [0] tag. */
 
1378
  len[2] = needed;
 
1379
  needed += compute_tag_length (needed);
 
1380
 
 
1381
  /* 1. The encryptedData OID. */
 
1382
  needed += 2 + DIM (oid_encryptedData);
 
1383
 
 
1384
  /* 0. The first sequence. */
 
1385
  len[0] = needed;
 
1386
  needed += compute_tag_length (needed);
 
1387
 
 
1388
  /* Now that we have all length information, allocate a buffer. */
 
1389
  p = certbag = gcry_malloc (needed);
 
1390
  if (!certbag)
 
1391
    {
 
1392
      log_error ("error allocating buffer\n");
 
1393
      return NULL;
 
1394
    }
 
1395
 
 
1396
  /* Walk 9 steps up to store the data. */
 
1397
 
 
1398
  /* 0. Store the first sequence. */
 
1399
  p = store_tag_length (p, TAG_SEQUENCE, len[0]);
 
1400
 
 
1401
  /* 1. Store the encryptedData OID. */
 
1402
  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_encryptedData));
 
1403
  memcpy (p, oid_encryptedData, DIM (oid_encryptedData)); 
 
1404
  p += DIM (oid_encryptedData); 
 
1405
 
 
1406
  /* 2. Store a [0] tag. */
 
1407
  p = store_tag_length (p, 0xa0, len[2]);
 
1408
 
 
1409
  /* 3. Store a sequence. */
 
1410
  p = store_tag_length (p, TAG_SEQUENCE, len[3]);
 
1411
 
 
1412
  /* 4. Store the integer 0. */
 
1413
  *p++ = TAG_INTEGER;
 
1414
  *p++ = 1; 
 
1415
  *p++ = 0;
 
1416
 
 
1417
  /* 5. Store a sequence. */
 
1418
  p = store_tag_length (p, TAG_SEQUENCE, len[5]);
 
1419
 
 
1420
  /* 6. Store the data OID. */
 
1421
  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_data));
 
1422
  memcpy (p, oid_data, DIM (oid_data)); 
 
1423
  p += DIM (oid_data); 
 
1424
 
 
1425
  /* 7. Now for the pre-encoded algorithm identifier and the salt. */
 
1426
  memcpy (p, data_rc2iter2048, DIM (data_rc2iter2048));
 
1427
  memcpy (p + DATA_RC2ITER2048_SALT_OFF, salt, 8);
 
1428
  p += DIM (data_rc2iter2048);
 
1429
 
 
1430
  /* 8. And finally the [0] tag with the encrypted data. */
 
1431
  p = store_tag_length (p, 0xa0, buflen);
 
1432
  memcpy (p, buffer, buflen);
 
1433
  p += buflen;
 
1434
  certbaglen = p - certbag;
 
1435
  
 
1436
  if (needed != certbaglen)
 
1437
    log_debug ("length mismatch: %u, %u\n", needed, certbaglen);
 
1438
 
 
1439
  *r_length = certbaglen;
 
1440
  return certbag;
 
1441
}
 
1442
 
 
1443
 
 
1444
static unsigned char *
 
1445
build_cert_sequence (unsigned char *buffer, size_t buflen, size_t *r_length)
 
1446
{
 
1447
  size_t len[8], needed, n;
 
1448
  unsigned char *p, *certseq;
 
1449
  size_t certseqlen;
 
1450
 
 
1451
  /* Walk 8 steps down to collect the info: */
 
1452
 
 
1453
  /* 7. The data goes into an octet string. */
 
1454
  needed = compute_tag_length (buflen);
 
1455
  needed += buflen;
 
1456
 
 
1457
  /* 6. A [0] tag. */
 
1458
  len[6] = needed;
 
1459
  needed += compute_tag_length (needed);
 
1460
 
 
1461
  /* 5. An OID. */
 
1462
  needed += 2 + DIM (oid_x509Certificate_for_pkcs_12);
 
1463
 
 
1464
  /* 4. A sequence. */
 
1465
  len[4] = needed;
 
1466
  needed += compute_tag_length (needed);
 
1467
 
 
1468
  /* 3. A [0] tag. */
 
1469
  len[3] = needed;
 
1470
  needed += compute_tag_length (needed);
 
1471
 
 
1472
  /* 2. An OID. */
 
1473
  needed += 2 + DIM (oid_pkcs_12_CertBag);
 
1474
 
 
1475
  /* 1. A sequence. */
 
1476
  len[1] = needed;
 
1477
  needed += compute_tag_length (needed);
 
1478
 
 
1479
  /* 0. The first sequence. */
 
1480
  len[0] = needed;
 
1481
  needed += compute_tag_length (needed);
 
1482
 
 
1483
  /* Now that we have all length information, allocate a buffer. */
 
1484
  p = certseq = gcry_malloc (needed + 8 /*(for padding)*/);
 
1485
  if (!certseq)
 
1486
    {
 
1487
      log_error ("error allocating buffer\n");
 
1488
      return NULL;
 
1489
    }
 
1490
 
 
1491
  /* Walk 8 steps up to store the data. */
 
1492
 
 
1493
  /* 0. Store the first sequence. */
 
1494
  p = store_tag_length (p, TAG_SEQUENCE, len[0]);
 
1495
 
 
1496
  /* 1. Store the second sequence. */
 
1497
  p = store_tag_length (p, TAG_SEQUENCE, len[1]);
 
1498
 
 
1499
  /* 2. Store the pkcs12-cert-bag OID. */
 
1500
  p = store_tag_length (p, TAG_OBJECT_ID, DIM (oid_pkcs_12_CertBag));
 
1501
  memcpy (p, oid_pkcs_12_CertBag, DIM (oid_pkcs_12_CertBag)); 
 
1502
  p += DIM (oid_pkcs_12_CertBag); 
 
1503
 
 
1504
  /* 3. Store a [0] tag. */
 
1505
  p = store_tag_length (p, 0xa0, len[3]);
 
1506
 
 
1507
  /* 4. Store a sequence. */
 
1508
  p = store_tag_length (p, TAG_SEQUENCE, len[4]);
 
1509
 
 
1510
  /* 5. Store the x509Certificate OID. */
 
1511
  p = store_tag_length (p, TAG_OBJECT_ID,
 
1512
                        DIM (oid_x509Certificate_for_pkcs_12));
 
1513
  memcpy (p, oid_x509Certificate_for_pkcs_12,
 
1514
          DIM (oid_x509Certificate_for_pkcs_12)); 
 
1515
  p += DIM (oid_x509Certificate_for_pkcs_12); 
 
1516
 
 
1517
  /* 6. Store a [0] tag. */
 
1518
  p = store_tag_length (p, 0xa0, len[6]);
 
1519
 
 
1520
  /* 7. And finally the octet string with the actual certificate. */
 
1521
  p = store_tag_length (p, TAG_OCTET_STRING, buflen);
 
1522
  memcpy (p, buffer, buflen);
 
1523
  p += buflen;
 
1524
  certseqlen = p - certseq;
 
1525
  
 
1526
  if (needed != certseqlen)
 
1527
    log_debug ("length mismatch: %u, %u\n", needed, certseqlen);
 
1528
  
 
1529
  /* Append some pad characters; we already allocated extra space. */
 
1530
  n = 8 - certseqlen % 8;
 
1531
  for (;(certseqlen % 8); certseqlen++)
 
1532
    *p++ = n;
 
1533
  
 
1534
  *r_length = certseqlen;
 
1535
  return certseq;
 
1536
}
 
1537
 
 
1538
 
 
1539
/* Expect the RSA key parameters in KPARMS and a password in
 
1540
   PW. Create a PKCS structure from it and return it as well as the
 
1541
   length in R_LENGTH; return NULL in case of an error. */
 
1542
unsigned char * 
 
1543
p12_build (gcry_mpi_t *kparms, unsigned char *cert, size_t certlen,
 
1544
           const char *pw, size_t *r_length)
 
1545
{
 
1546
  unsigned char *buffer;
 
1547
  size_t n, buflen;
 
1548
  char salt[8];
 
1549
  struct buffer_s seqlist[2];
 
1550
  int seqlistidx = 0;
 
1551
 
 
1552
  if (cert && certlen)
 
1553
    {
 
1554
      /* Encode the certificate. */
 
1555
      buffer = build_cert_sequence (cert, certlen, &buflen);
 
1556
      if (!buffer)
 
1557
        goto failure;
 
1558
 
 
1559
      /* Encrypt it. */
 
1560
      gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
 
1561
      crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_RFC2268_40, 1);
 
1562
      
 
1563
      /* Encode the encrypted stuff into a bag. */
 
1564
      seqlist[seqlistidx].buffer = build_cert_bag (buffer, buflen, salt, &n);
 
1565
      seqlist[seqlistidx].length = n;
 
1566
      gcry_free (buffer);
 
1567
      buffer = NULL;
 
1568
      if (!seqlist[seqlistidx].buffer)
 
1569
        goto failure;
 
1570
      seqlistidx++;
 
1571
    }
 
1572
 
 
1573
  if (kparms)
 
1574
    {
 
1575
      /* Encode the key. */
 
1576
      buffer = build_key_sequence (kparms, &buflen);
 
1577
      if (!buffer)
 
1578
        goto failure;
 
1579
      
 
1580
      /* Encrypt it. */
 
1581
      gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
 
1582
      crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_3DES, 1);
 
1583
 
 
1584
      /* Encode the encrypted stuff into a bag. */
 
1585
      seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, &n);
 
1586
      seqlist[seqlistidx].length = n;
 
1587
      gcry_free (buffer);
 
1588
      buffer = NULL;
 
1589
      if (!seqlist[seqlistidx].buffer)
 
1590
        goto failure;
 
1591
      seqlistidx++;
 
1592
    }
 
1593
 
 
1594
  seqlist[seqlistidx].buffer = NULL;
 
1595
  seqlist[seqlistidx].length = 0;
 
1596
 
 
1597
  buffer = create_final (seqlist, &buflen);
 
1598
 
 
1599
 failure:
 
1600
  for ( ; seqlistidx; seqlistidx--)
 
1601
    gcry_free (seqlist[seqlistidx].buffer);
 
1602
 
 
1603
  *r_length = buffer? buflen : 0;
 
1604
  return buffer;
 
1605
}
 
1606
 
 
1607
 
 
1608
#ifdef TEST
 
1609
 
 
1610
static void 
 
1611
cert_cb (void *opaque, const unsigned char *cert, size_t certlen)
 
1612
{
 
1613
  printf ("got a certificate of %u bytes length\n", certlen);
 
1614
}
 
1615
 
 
1616
int
 
1617
main (int argc, char **argv)
 
1618
{
 
1619
  FILE *fp;
 
1620
  struct stat st;
 
1621
  unsigned char *buf;
 
1622
  size_t buflen;
 
1623
  gcry_mpi_t *result;
 
1624
 
 
1625
  if (argc != 3)
 
1626
    {
 
1627
      fprintf (stderr, "usage: testp12 file passphrase\n");
 
1628
      return 1;
 
1629
    }
 
1630
 
 
1631
  gcry_control (GCRYCTL_DISABLE_SECMEM, NULL);
 
1632
  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL);
 
1633
 
 
1634
  fp = fopen (argv[1], "rb");
 
1635
  if (!fp)
 
1636
    {
 
1637
      fprintf (stderr, "can't open `%s': %s\n", argv[1], strerror (errno));
 
1638
      return 1;
 
1639
    }
 
1640
  
 
1641
  if (fstat (fileno(fp), &st))
 
1642
    {
 
1643
      fprintf (stderr, "can't stat `%s': %s\n", argv[1], strerror (errno));
 
1644
      return 1;
 
1645
    }
 
1646
 
 
1647
  buflen = st.st_size;
 
1648
  buf = gcry_malloc (buflen+1);
 
1649
  if (!buf || fread (buf, buflen, 1, fp) != 1)
 
1650
    {
 
1651
      fprintf (stderr, "error reading `%s': %s\n", argv[1], strerror (errno));
 
1652
      return 1;
 
1653
    }
 
1654
  fclose (fp);
 
1655
 
 
1656
  result = p12_parse (buf, buflen, argv[2], cert_cb, NULL);
 
1657
  if (result)
 
1658
    {
 
1659
      int i, rc;
 
1660
      unsigned char *tmpbuf;
 
1661
 
 
1662
      for (i=0; result[i]; i++)
 
1663
        {
 
1664
          rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &tmpbuf,
 
1665
                                NULL, result[i]);
 
1666
          if (rc)
 
1667
            printf ("%d: [error printing number: %s]\n",
 
1668
                    i, gpg_strerror (rc));
 
1669
          else
 
1670
            {
 
1671
              printf ("%d: %s\n", i, tmpbuf);
 
1672
              gcry_free (tmpbuf);
 
1673
            }
 
1674
        }
 
1675
    }
 
1676
 
 
1677
  return 0;
 
1678
 
 
1679
}
 
1680
 
 
1681
/*
 
1682
Local Variables:
 
1683
compile-command: "gcc -Wall -O -g -DTEST=1 -o minip12 minip12.c ../jnlib/libjnlib.a -L /usr/local/lib -lgcrypt -lgpg-error"
 
1684
End:
 
1685
*/
 
1686
#endif /* TEST */