~ubuntu-branches/ubuntu/precise/gnupg2/precise-proposed

« back to all changes in this revision

Viewing changes to agent/minip12.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Urlichs
  • Date: 2006-01-24 04:31:42 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060124043142-pbg192or6qxv3yk2
Tags: 1.9.20-1
* New Upstream version. Closes:#306890,#344530
  * Closes:#320490: gpg-protect-tool fails to decrypt PKCS-12 files 
* Depend on libopensc2-dev, not -1-. Closes:#348106

Show diffs side-by-side

added added

removed removed

Lines of Context:
141
141
 
142
142
/* Parse the buffer at the address BUFFER which is of SIZE and return
143
143
   the tag and the length part from the TLV triplet.  Update BUFFER
144
 
   and SIZE on success. */
 
144
   and SIZE on success.  Checks that the encoded length does not
 
145
   exhaust the length of the provided buffer. */
145
146
static int 
146
147
parse_tag (unsigned char const **buffer, size_t *size, struct tag_info *ti)
147
148
{
221
222
}
222
223
 
223
224
 
 
225
/* Given an ASN.1 chunk of a structure like:
 
226
 
 
227
     24 NDEF:       OCTET STRING  -- This is not passed to us
 
228
     04    1:         OCTET STRING  -- INPUT point s to here
 
229
            :           30
 
230
     04    1:         OCTET STRING
 
231
            :           80
 
232
          [...]
 
233
     04    2:         OCTET STRING
 
234
            :           00 00
 
235
            :         } -- This denotes a Null tag and are the last 
 
236
                        -- two bytes in INPUT.
 
237
   
 
238
   Create a new buffer with the content of that octet string.  INPUT
 
239
   is the orginal buffer with a length as stored at LENGTH.  Returns
 
240
   NULL on error or a new malloced buffer with the length of this new
 
241
   buffer stored at LENGTH and the number of bytes parsed from input
 
242
   are added to the value stored at INPUT_CONSUMED.  INPUT_CONSUMED is
 
243
   allowed to be passed as NULL if the caller is not interested in
 
244
   this value. */
 
245
static unsigned char *
 
246
cram_octet_string (const unsigned char *input, size_t *length,
 
247
                   size_t *input_consumed)
 
248
{
 
249
  const unsigned char *s = input;
 
250
  size_t n = *length;
 
251
  unsigned char *output, *d;
 
252
  struct tag_info ti;
 
253
 
 
254
  /* Allocate output buf.  We know that it won't be longer than the
 
255
     input buffer. */
 
256
  d = output = gcry_malloc (n);
 
257
  if (!output)
 
258
    goto bailout;
 
259
 
 
260
  for (;;)
 
261
    {
 
262
      if (parse_tag (&s, &n, &ti))
 
263
        goto bailout;
 
264
      if (ti.class == UNIVERSAL && ti.tag == TAG_OCTET_STRING 
 
265
          && !ti.ndef && !ti.is_constructed)
 
266
        {
 
267
          memcpy (d, s, ti.length);
 
268
          s += ti.length;
 
269
          d += ti.length;
 
270
          n -= ti.length;
 
271
        }
 
272
      else if (ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed)
 
273
        break; /* Ready */ 
 
274
      else
 
275
        goto bailout;
 
276
    }
 
277
 
 
278
 
 
279
  *length = d - output;
 
280
  if (input_consumed)
 
281
    *input_consumed += s - input;
 
282
  return output;
 
283
 
 
284
 bailout:
 
285
  if (input_consumed)
 
286
    *input_consumed += s - input;
 
287
  gcry_free (output);
 
288
  return NULL;
 
289
}
 
290
 
 
291
 
 
292
 
224
293
static int 
225
 
string_to_key (int id, char *salt, int iter, const char *pw,
 
294
string_to_key (int id, char *salt, size_t saltlen, int iter, const char *pw,
226
295
               int req_keylen, unsigned char *keybuf)
227
296
{
228
297
  int rc, i, j;
241
310
      return -1;
242
311
    }
243
312
 
 
313
  if (saltlen < 8)
 
314
    {
 
315
      log_error ("salt too short\n");
 
316
      return -1;
 
317
    }
 
318
  
244
319
  /* Store salt and password in BUF_I */
245
320
  p = buf_i;
246
321
  for(i=0; i < 64; i++)
247
 
    *p++ = salt [i%8];
 
322
    *p++ = salt [i%saltlen];
248
323
  for(i=j=0; i < 64; i += 2)
249
324
    {
250
325
      *p++ = 0;
314
389
 
315
390
 
316
391
static int 
317
 
set_key_iv (gcry_cipher_hd_t chd, char *salt, int iter, const char *pw,
318
 
            int keybytes)
 
392
set_key_iv (gcry_cipher_hd_t chd, char *salt, size_t saltlen, int iter,
 
393
            const char *pw, int keybytes)
319
394
{
320
395
  unsigned char keybuf[24];
321
396
  int rc;
322
397
 
323
398
  assert (keybytes == 5 || keybytes == 24);
324
 
  if (string_to_key (1, salt, iter, pw, keybytes, keybuf))
 
399
  if (string_to_key (1, salt, saltlen, iter, pw, keybytes, keybuf))
325
400
    return -1;
326
401
  rc = gcry_cipher_setkey (chd, keybuf, keybytes);
327
402
  if (rc)
330
405
      return -1;
331
406
    }
332
407
 
333
 
  if (string_to_key (2, salt, iter, pw, 8, keybuf))
 
408
  if (string_to_key (2, salt, saltlen, iter, pw, 8, keybuf))
334
409
    return -1;
335
410
  rc = gcry_cipher_setiv (chd, keybuf, 8);
336
411
  if (rc)
343
418
 
344
419
 
345
420
static void
346
 
crypt_block (unsigned char *buffer, size_t length, char *salt, int iter,
347
 
             const char *pw, int cipher_algo, int encrypt)
 
421
crypt_block (unsigned char *buffer, size_t length, char *salt, size_t saltlen,
 
422
             int iter, const char *pw, int cipher_algo, int encrypt)
348
423
{
349
424
  gcry_cipher_hd_t chd;
350
425
  int rc;
356
431
      wipememory (buffer, length);
357
432
      return;
358
433
    }
359
 
  if (set_key_iv (chd, salt, iter, pw,
 
434
  if (set_key_iv (chd, salt, saltlen, iter, pw,
360
435
                  cipher_algo == GCRY_CIPHER_RFC2268_40? 5:24))
361
436
    {
362
437
      wipememory (buffer, length);
381
456
 
382
457
static int
383
458
parse_bag_encrypted_data (const unsigned char *buffer, size_t length,
384
 
                          int startoffset, const char *pw,
 
459
                          int startoffset, size_t *r_consumed, const char *pw,
385
460
                          void (*certcb)(void*, const unsigned char*, size_t),
386
461
                          void *certcbarg)
387
462
{
388
463
  struct tag_info ti;
389
464
  const unsigned char *p = buffer;
 
465
  const unsigned char *p_start = buffer;
390
466
  size_t n = length;
391
467
  const char *where;
392
 
  char salt[8];
 
468
  char salt[16];
 
469
  size_t saltlen;
393
470
  unsigned int iter;
394
471
  unsigned char *plain = NULL;
395
472
  int bad_pass = 0;
 
473
  unsigned char *cram_buffer = NULL;
 
474
  size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */
396
475
  
397
476
  where = "start";
398
477
  if (parse_tag (&p, &n, &ti))
449
528
    goto bailout;
450
529
  if (parse_tag (&p, &n, &ti))
451
530
    goto bailout;
452
 
  if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 )
 
531
  if (ti.class || ti.tag != TAG_OCTET_STRING
 
532
      || ti.length < 8 || ti.length > 16 )
453
533
    goto bailout;
454
 
  memcpy (salt, p, 8);
455
 
  p += 8;
456
 
  n -= 8;
 
534
  saltlen = ti.length;
 
535
  memcpy (salt, p, saltlen);
 
536
  p += saltlen;
 
537
  n -= saltlen;
457
538
  if (parse_tag (&p, &n, &ti))
458
539
    goto bailout;
459
540
  if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
468
549
  where = "rc2-ciphertext";
469
550
  if (parse_tag (&p, &n, &ti))
470
551
    goto bailout;
471
 
  if (ti.class != CONTEXT || ti.tag != 0 || !ti.length )
 
552
 
 
553
  consumed = p - p_start;
 
554
  if (ti.class == CONTEXT && ti.tag == 0 && ti.is_constructed && ti.ndef)
 
555
    {
 
556
      /* Mozilla exported certs now come with single byte chunks of
 
557
         octect strings.  (Mozilla Firefox 1.0.4).  Arghh. */
 
558
      where = "cram-rc2-ciphertext";
 
559
      cram_buffer = cram_octet_string ( p, &n, &consumed);
 
560
      if (!cram_buffer)
 
561
        goto bailout;
 
562
      p = p_start = cram_buffer;
 
563
      if (r_consumed)
 
564
        *r_consumed = consumed;
 
565
      r_consumed = NULL; /* Ugly hack to not update that value any further. */
 
566
      ti.length = n;
 
567
    }
 
568
  else if (ti.class == CONTEXT && ti.tag == 0 && ti.length )
 
569
    ;
 
570
  else
472
571
    goto bailout;
473
572
  
474
573
  log_info ("%lu bytes of RC2 encrypted text\n", ti.length);
480
579
      goto bailout;
481
580
    }
482
581
  memcpy (plain, p, ti.length);
483
 
  crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_RFC2268_40, 0);
 
582
  crypt_block (plain, ti.length, salt, saltlen,
 
583
               iter, pw, GCRY_CIPHER_RFC2268_40, 0);
484
584
  n = ti.length;
485
585
  startoffset = 0;
486
 
  buffer = p = plain;
 
586
  p_start = p = plain;
487
587
 
488
588
/*   { */
489
589
/* #  warning debug code is enabled */
511
611
      goto bailout;
512
612
    }
513
613
 
514
 
  /* Loop over all certificates inside the bab. */
 
614
  /* Loop over all certificates inside the bag. */
515
615
  while (n)
516
616
    {
517
617
      int isbag = 0;
615
715
        }
616
716
    }
617
717
  
 
718
  if (r_consumed)
 
719
    *r_consumed = consumed;
618
720
  gcry_free (plain);
 
721
  gcry_free (cram_buffer);
 
722
  return 0;
619
723
 
620
 
  return 0;
621
724
 bailout:
 
725
  if (r_consumed)
 
726
    *r_consumed = consumed;
622
727
  gcry_free (plain);
 
728
  gcry_free (cram_buffer);
623
729
  log_error ("encryptedData error at \"%s\", offset %u\n",
624
 
             where, (p - buffer)+startoffset);
 
730
             where, (p - p_start)+startoffset);
625
731
  if (bad_pass)
626
732
    {
627
733
      /* Note, that the following string might be used by other programs
634
740
 
635
741
static gcry_mpi_t *
636
742
parse_bag_data (const unsigned char *buffer, size_t length, int startoffset,
637
 
                const char *pw)
 
743
                size_t *r_consumed, const char *pw)
638
744
{
639
745
  int rc;
640
746
  struct tag_info ti;
641
747
  const unsigned char *p = buffer;
 
748
  const unsigned char *p_start = buffer;
642
749
  size_t n = length;
643
750
  const char *where;
644
 
  char salt[8];
 
751
  char salt[16];
 
752
  size_t saltlen;
645
753
  unsigned int iter;
646
754
  int len;
647
755
  unsigned char *plain = NULL;
648
756
  gcry_mpi_t *result = NULL;
649
757
  int result_count, i;
 
758
  unsigned char *cram_buffer = NULL;
 
759
  size_t consumed = 0; /* Number of bytes consumed from the orginal buffer. */
650
760
 
651
761
  where = "start";
652
762
  if (parse_tag (&p, &n, &ti))
658
768
  if (ti.class || ti.tag != TAG_OCTET_STRING)
659
769
    goto bailout;
660
770
 
 
771
  consumed = p - p_start;
 
772
  if (ti.is_constructed && ti.ndef)
 
773
    {
 
774
      /* Mozilla exported certs now come with single byte chunks of
 
775
         octect strings.  (Mozilla Firefox 1.0.4).  Arghh. */
 
776
      where = "cram-data.outersegs";
 
777
      cram_buffer = cram_octet_string ( p, &n, &consumed);
 
778
      if (!cram_buffer)
 
779
        goto bailout;
 
780
      p = p_start = cram_buffer;
 
781
      if (r_consumed)
 
782
        *r_consumed = consumed;
 
783
      r_consumed = NULL; /* Ugly hack to not update that value any further. */
 
784
    }
 
785
  
 
786
 
661
787
  where = "data.outerseqs";
662
788
  if (parse_tag (&p, &n, &ti))
663
789
    goto bailout;
709
835
    goto bailout;
710
836
  if (parse_tag (&p, &n, &ti))
711
837
    goto bailout;
712
 
  if (ti.class || ti.tag != TAG_OCTET_STRING || ti.length != 8 )
 
838
  if (ti.class || ti.tag != TAG_OCTET_STRING
 
839
      || ti.length < 8 || ti.length > 16)
713
840
    goto bailout;
714
 
  memcpy (salt, p, 8);
715
 
  p += 8;
716
 
  n -= 8;
 
841
  saltlen = ti.length;
 
842
  memcpy (salt, p, saltlen);
 
843
  p += saltlen;
 
844
  n -= saltlen;
717
845
  if (parse_tag (&p, &n, &ti))
718
846
    goto bailout;
719
847
  if (ti.class || ti.tag != TAG_INTEGER || !ti.length )
740
868
      goto bailout;
741
869
    }
742
870
  memcpy (plain, p, ti.length);
743
 
  crypt_block (plain, ti.length, salt, iter, pw, GCRY_CIPHER_3DES, 0);
 
871
  consumed += p - p_start + ti.length;
 
872
  crypt_block (plain, ti.length, salt, saltlen, iter, pw, GCRY_CIPHER_3DES, 0);
744
873
  n = ti.length;
745
874
  startoffset = 0;
746
 
  buffer = p = plain;
 
875
  p_start = p = plain;
 
876
 
 
877
/*   { */
 
878
/* #  warning debug code is enabled */
 
879
/*     FILE *fp = fopen ("tmp-rc2-plain-key.der", "wb"); */
 
880
/*     if (!fp || fwrite (p, n, 1, fp) != 1) */
 
881
/*       exit (2); */
 
882
/*     fclose (fp); */
 
883
/*   } */
 
884
 
747
885
 
748
886
  where = "decrypted-text";
749
887
  if (parse_tag (&p, &n, &ti) || ti.class || ti.tag != TAG_SEQUENCE)
819
957
  if (len)
820
958
    goto bailout;
821
959
 
 
960
  gcry_free (cram_buffer);
 
961
  if (r_consumed)
 
962
    *r_consumed = consumed;
822
963
  return result;
823
964
 
824
965
 bailout:
829
970
        gcry_mpi_release (result[i]);
830
971
      gcry_free (result);
831
972
    }
 
973
  gcry_free (cram_buffer);
832
974
  log_error ( "data error at \"%s\", offset %u\n",
833
975
              where, (p - buffer) + startoffset);
 
976
  if (r_consumed)
 
977
    *r_consumed = consumed;
834
978
  return NULL;
835
979
}
836
980
 
848
992
{
849
993
  struct tag_info ti;
850
994
  const unsigned char *p = buffer;
 
995
  const unsigned char *p_start = buffer;
851
996
  size_t n = length;
852
997
  const char *where;
853
998
  int bagseqlength, len;
 
999
  int bagseqndef, lenndef;
 
1000
  gcry_mpi_t *result = NULL;
 
1001
  unsigned char *cram_buffer = NULL;
854
1002
 
855
1003
  where = "pfx";
856
1004
  if (parse_tag (&p, &n, &ti))
887
1035
  if (ti.class != UNIVERSAL || ti.tag != TAG_OCTET_STRING)
888
1036
    goto bailout;
889
1037
 
 
1038
  if (ti.is_constructed && ti.ndef)
 
1039
    {
 
1040
      /* Mozilla exported certs now come with single byte chunks of
 
1041
         octect strings.  (Mozilla Firefox 1.0.4).  Arghh. */
 
1042
      where = "cram-bags";
 
1043
      cram_buffer = cram_octet_string ( p, &n, NULL);
 
1044
      if (!cram_buffer)
 
1045
        goto bailout;
 
1046
      p = p_start = cram_buffer;
 
1047
    }
 
1048
 
890
1049
  where = "bags";
891
1050
  if (parse_tag (&p, &n, &ti))
892
1051
    goto bailout;
893
1052
  if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
894
1053
    goto bailout;
 
1054
  bagseqndef = ti.ndef;
895
1055
  bagseqlength = ti.length;
896
 
  while (bagseqlength)
 
1056
  while (bagseqlength || bagseqndef)
897
1057
    {
898
 
      /*log_debug ( "at offset %u\n", (p - buffer));*/
 
1058
      log_debug ( "at offset %u\n", (p - p_start));
899
1059
      where = "bag-sequence";
900
1060
      if (parse_tag (&p, &n, &ti))
901
1061
        goto bailout;
 
1062
      if (bagseqndef && ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed)
 
1063
        break; /* Ready */ 
902
1064
      if (ti.class != UNIVERSAL || ti.tag != TAG_SEQUENCE)
903
1065
        goto bailout;
904
1066
 
905
 
      if (bagseqlength < ti.nhdr)
906
 
        goto bailout;
907
 
      bagseqlength -= ti.nhdr;
908
 
      if (bagseqlength < ti.length)
909
 
        goto bailout;
910
 
      bagseqlength -= ti.length;
 
1067
      if (!bagseqndef)
 
1068
        {
 
1069
          if (bagseqlength < ti.nhdr)
 
1070
            goto bailout;
 
1071
          bagseqlength -= ti.nhdr;
 
1072
          if (bagseqlength < ti.length)
 
1073
            goto bailout;
 
1074
          bagseqlength -= ti.length;
 
1075
        }
 
1076
      lenndef = ti.ndef;
911
1077
      len = ti.length;
912
1078
 
913
1079
      if (parse_tag (&p, &n, &ti))
914
1080
        goto bailout;
915
 
      len -= ti.nhdr;
 
1081
      if (lenndef)
 
1082
        len = ti.nhdr; 
 
1083
      else
 
1084
        len -= ti.nhdr; 
 
1085
 
916
1086
      if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_encryptedData)
917
1087
          && !memcmp (p, oid_encryptedData, DIM(oid_encryptedData)))
918
1088
        {
 
1089
          size_t consumed = 0;
 
1090
 
919
1091
          p += DIM(oid_encryptedData);
920
1092
          n -= DIM(oid_encryptedData);
921
 
          len -= DIM(oid_encryptedData);
 
1093
          if (!lenndef)
 
1094
            len -= DIM(oid_encryptedData);
922
1095
          where = "bag.encryptedData";
923
 
          if (parse_bag_encrypted_data (p, n, (p - buffer), pw,
 
1096
          if (parse_bag_encrypted_data (p, n, (p - p_start), &consumed, pw,
924
1097
                                        certcb, certcbarg))
925
1098
            goto bailout;
 
1099
          if (lenndef)
 
1100
            len += consumed;
926
1101
        }
927
1102
      else if (ti.tag == TAG_OBJECT_ID && ti.length == DIM(oid_data)
928
 
          && !memcmp (p, oid_data, DIM(oid_data)))
 
1103
               && !memcmp (p, oid_data, DIM(oid_data)))
929
1104
        {
930
 
          p += DIM(oid_data);
931
 
          n -= DIM(oid_data);
932
 
          len -= DIM(oid_data);
933
 
          return parse_bag_data (p, n, (p-buffer), pw);
 
1105
          if (result)
 
1106
            {
 
1107
              log_info ("already got an data object, skipping next one\n");
 
1108
              p += ti.length;
 
1109
              n -= ti.length;
 
1110
            }
 
1111
          else
 
1112
            {
 
1113
              size_t consumed = 0;
 
1114
 
 
1115
              p += DIM(oid_data);
 
1116
              n -= DIM(oid_data);
 
1117
              if (!lenndef)
 
1118
                len -= DIM(oid_data);
 
1119
              result = parse_bag_data (p, n, (p - p_start), &consumed, pw);
 
1120
              if (!result)
 
1121
                goto bailout;
 
1122
              if (lenndef)
 
1123
                len += consumed;
 
1124
            }
934
1125
        }
935
1126
      else
936
 
        log_info ( "unknown bag type - skipped\n");
 
1127
        {
 
1128
          log_info ("unknown bag type - skipped\n");
 
1129
          p += ti.length;
 
1130
          n -= ti.length;
 
1131
        }
937
1132
 
938
1133
      if (len < 0 || len > n)
939
1134
        goto bailout;
940
1135
      p += len;
941
1136
      n -= len;
 
1137
      if (lenndef)
 
1138
        {
 
1139
          /* Need to skip the Null Tag. */
 
1140
          if (parse_tag (&p, &n, &ti))
 
1141
            goto bailout;
 
1142
          if (!(ti.class == UNIVERSAL && !ti.tag && !ti.is_constructed))
 
1143
            goto bailout;
 
1144
        }
942
1145
    }
943
1146
  
944
 
  return NULL;
 
1147
  gcry_free (cram_buffer);
 
1148
  return result;
945
1149
 bailout:
946
 
  log_error ("error at \"%s\", offset %u\n", where, (p - buffer));
 
1150
  log_error ("error at \"%s\", offset %u\n", where, (p - p_start));
 
1151
  /* fixme: need to release RESULT. */
 
1152
  gcry_free (cram_buffer);
947
1153
  return NULL;
948
1154
}
949
1155
 
1229
1435
  assert (needed == plainlen);
1230
1436
  /* Append some pad characters; we already allocated extra space. */
1231
1437
  n = 8 - plainlen % 8;
1232
 
  for (;(plainlen % 8); plainlen++)
 
1438
  for (i=0; i < n; i++, plainlen++)
1233
1439
    *p++ = n;
1234
1440
 
1235
1441
  *r_length = plainlen;
1453
1659
  size_t len[8], needed, n;
1454
1660
  unsigned char *p, *certseq;
1455
1661
  size_t certseqlen;
 
1662
  int i;
1456
1663
 
1457
1664
  /* Walk 8 steps down to collect the info: */
1458
1665
 
1535
1742
  
1536
1743
  /* Append some pad characters; we already allocated extra space. */
1537
1744
  n = 8 - certseqlen % 8;
1538
 
  for (;(certseqlen % 8); certseqlen++)
 
1745
  for (i=0; i < n; i++, certseqlen++)
1539
1746
    *p++ = n;
1540
1747
  
1541
1748
  *r_length = certseqlen;
1567
1774
 
1568
1775
      /* Encrypt it. */
1569
1776
      gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
1570
 
      crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_RFC2268_40, 1);
 
1777
      crypt_block (buffer, buflen, salt, 8, 2048, pw,
 
1778
                   GCRY_CIPHER_RFC2268_40, 1);
1571
1779
      
1572
1780
      /* Encode the encrypted stuff into a bag. */
1573
1781
      seqlist[seqlistidx].buffer = build_cert_bag (buffer, buflen, salt, &n);
1588
1796
      
1589
1797
      /* Encrypt it. */
1590
1798
      gcry_randomize (salt, 8, GCRY_STRONG_RANDOM);
1591
 
      crypt_block (buffer, buflen, salt, 2048, pw, GCRY_CIPHER_3DES, 1);
 
1799
      crypt_block (buffer, buflen, salt, 8, 2048, pw, GCRY_CIPHER_3DES, 1);
1592
1800
 
1593
1801
      /* Encode the encrypted stuff into a bag. */
1594
1802
      seqlist[seqlistidx].buffer = build_key_bag (buffer, buflen, salt, &n);