Bläddra i källkod

Merge branch 'fix/asn1' into develop

This closes #49

[skip ci]
Steffen Jaeckel 11 år sedan
förälder
incheckning
c342cb5a21

+ 3 - 3
src/headers/tomcrypt_pk.h

@@ -435,7 +435,7 @@ int dsa_shared_secret(void          *private_key, void *base,
 #ifdef LTC_DER
 /* DER handling */
 
-enum {
+typedef enum ltc_asn1_type_ {
  LTC_ASN1_EOL,
  LTC_ASN1_BOOLEAN,
  LTC_ASN1_INTEGER,
@@ -455,12 +455,12 @@ enum {
  LTC_ASN1_RAW_BIT_STRING,
  LTC_ASN1_TELETEX_STRING,
  LTC_ASN1_CONSTRUCTED,
-};
+} ltc_asn1_type;
 
 /** A LTC ASN.1 list type */
 typedef struct ltc_asn1_list_ {
    /** The LTC ASN.1 enumerated type identifier */
-   int           type;
+   ltc_asn1_type type;
    /** The data to encode or place for decoding */
    void         *data;
    /** The size of the input or resulting output */

+ 35 - 1
src/pk/asn1/der/choice/der_decode_choice.c

@@ -51,6 +51,16 @@ int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
        data = list[x].data;
 
        switch (list[x].type) {
+           case LTC_ASN1_BOOLEAN:
+               if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) {
+                  if (der_length_boolean(&z) == CRYPT_OK) {
+                      list[x].used = 1;
+                      *inlen       = z;
+                      return CRYPT_OK;
+                  }
+               }
+               break;
+
            case LTC_ASN1_INTEGER:
                if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
                   if (der_length_integer(data, &z) == CRYPT_OK) {
@@ -82,6 +92,17 @@ int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
                }
                break;
 
+           case LTC_ASN1_RAW_BIT_STRING:
+               if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_bit_string(size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
            case LTC_ASN1_OCTET_STRING:
                if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
                   if (der_length_octet_string(size, &z) == CRYPT_OK) {
@@ -112,6 +133,17 @@ int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
                }
                break;
 
+           case LTC_ASN1_TELETEX_STRING:
+               if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) {
+                  if (der_length_teletex_string(data, size, &z) == CRYPT_OK) {
+                     list[x].used = 1;
+                     list[x].size = size;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
            case LTC_ASN1_IA5_STRING:
                if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
                   if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
@@ -166,7 +198,9 @@ int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
                }
                break;
 
-           default:
+           case LTC_ASN1_CHOICE:
+           case LTC_ASN1_CONSTRUCTED:
+           case LTC_ASN1_EOL:
                return CRYPT_INVALID_ARG;
        }
    }

+ 16 - 2
src/pk/asn1/der/sequence/der_decode_sequence_ex.c

@@ -31,7 +31,8 @@
 int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
                            ltc_asn1_list *list,     unsigned long  outlen, int ordered)
 {
-   int           err, type, i;
+   int           err, i;
+   ltc_asn1_type type;
    unsigned long size, x, y, z, blksize;
    void          *data;
 
@@ -187,6 +188,18 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
                }
                break;
 
+           case LTC_ASN1_TELETEX_STRING:
+               z = inlen;
+               if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
+                  if (!ordered) { continue; }
+                  goto LBL_ERR;
+               }
+               list[i].size = size;
+               if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               break;
+
            case LTC_ASN1_IA5_STRING:
                z = inlen;
                if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
@@ -270,7 +283,8 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
                }
                break;
 
-           default:
+           case LTC_ASN1_CONSTRUCTED:
+           case LTC_ASN1_EOL:
                err = CRYPT_INVALID_ARG;
                goto LBL_ERR;
        }

+ 15 - 3
src/pk/asn1/der/sequence/der_decode_sequence_flexi.c

@@ -65,7 +65,7 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
    ltc_asn1_list *l;
    unsigned long err, type, len, totlen, x, y;
    void          *realloc_tmp;
-   int           isConstructed;
+   int           is_constructed;
 
    LTC_ARGCHK(in    != NULL);
    LTC_ARGCHK(inlen != NULL);
@@ -103,12 +103,16 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
          l = l->next;
       }
 
-      if ((isConstructed = ((type & 0xE0) == 0xA0 ? 1 : 0))) {
+      if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
+         is_constructed = 1;
          /* constructed, use the 'used' field to store the original tag number */
          l->used = (type & 0x1F);
          /* treat constructed elements like SETs */
          type = 0x31;
       }
+      else {
+         is_constructed = 0;
+      }
 
      /* now switch on type */
       switch (type) {
@@ -332,7 +336,15 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
          case 0x31: /* SET */
 
              /* init field */
-             l->type = (isConstructed ? LTC_ASN1_CONSTRUCTED : ((type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET));
+             if (is_constructed) {
+                l->type = LTC_ASN1_CONSTRUCTED;
+             }
+             else if (type == 0x30) {
+                l->type = LTC_ASN1_SEQUENCE;
+             }
+             else {
+                l->type = LTC_ASN1_SET;
+             }
 
              /* we have to decode the SEQUENCE header and get it's length */
 

+ 14 - 13
src/pk/asn1/der/sequence/der_decode_sequence_multi.c

@@ -28,7 +28,8 @@
 */
 int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
 {
-   int           err, type;
+   int           err;
+   ltc_asn1_type type;
    unsigned long size, x;
    void          *data;
    va_list       args;
@@ -40,7 +41,7 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
    va_start(args, inlen);
    x = 0;
    for (;;) {
-       type = va_arg(args, int);
+       type = va_arg(args, ltc_asn1_type);
        size = va_arg(args, unsigned long);
        data = va_arg(args, void*);
 
@@ -64,10 +65,13 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
            case LTC_ASN1_SETOF:
            case LTC_ASN1_SEQUENCE:
            case LTC_ASN1_CHOICE:
+           case LTC_ASN1_RAW_BIT_STRING:
+           case LTC_ASN1_TELETEX_STRING:
                 ++x;
                 break;
 
-           default:
+           case LTC_ASN1_EOL:
+           case LTC_ASN1_CONSTRUCTED:
                va_end(args);
                return CRYPT_INVALID_ARG;
        }
@@ -88,7 +92,7 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
    va_start(args, inlen);
    x = 0;
    for (;;) {
-       type = va_arg(args, int);
+       type = va_arg(args, ltc_asn1_type);
        size = va_arg(args, unsigned long);
        data = va_arg(args, void*);
 
@@ -112,21 +116,18 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
            case LTC_ASN1_SET:
            case LTC_ASN1_SETOF:
            case LTC_ASN1_CHOICE:
-                list[x].type   = type;
-                list[x].size   = size;
-                list[x++].data = data;
+           case LTC_ASN1_RAW_BIT_STRING:
+           case LTC_ASN1_TELETEX_STRING:
+                LTC_SET_ASN1(list, x++, type, data, size);
+                break;
+           case LTC_ASN1_EOL:
+           case LTC_ASN1_CONSTRUCTED:
                 break;
-
-           default:
-               va_end(args);
-               err = CRYPT_INVALID_ARG;
-               goto LBL_ERR;
        }
    }
    va_end(args);
 
    err = der_decode_sequence(in, inlen, list, x);
-LBL_ERR:
    XFREE(list);
    return err;
 }

+ 10 - 2
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c

@@ -46,6 +46,7 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
 
    LTC_ARGCHK(in    != NULL);
    LTC_ARGCHK(inlen != 0);
+   LTC_ARGCHK(public_key_len != NULL);
 
    err = pk_get_oid(algorithm, &oid);
    if (err != CRYPT_OK) {
@@ -63,8 +64,8 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
    LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
    LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
 
-   /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
-      then proceed to convert bit to octet
+   /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey
+    * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet
     */
    LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, 2);
    LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
@@ -74,6 +75,13 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
            goto LBL_ERR;
    }
 
+   if ((alg_id[0].size != oid.OIDlen) ||
+       memcmp(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
+        /* OID mismatch */
+        err = CRYPT_PK_INVALID_TYPE;
+        goto LBL_ERR;
+   }
+
    len = subject_pubkey[1].size/8;
    if (*public_key_len > len) {
        memcpy(public_key, subject_pubkey[1].data, len);

+ 10 - 3
src/pk/asn1/der/sequence/der_encode_sequence_ex.c

@@ -31,7 +31,8 @@
 int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                            unsigned char *out,  unsigned long *outlen, int type_of)
 {
-   int           err, type;
+   int           err;
+   ltc_asn1_type type;
    unsigned long size, x, y, z, i;
    void          *data;
 
@@ -135,7 +136,10 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                y += x;
                break;
 
-           default:
+           case LTC_ASN1_CHOICE:
+           case LTC_ASN1_CONSTRUCTED:
+           case LTC_ASN1_EOL:
+           case LTC_ASN1_TELETEX_STRING:
                err = CRYPT_INVALID_ARG;
                goto LBL_ERR;
        }
@@ -330,7 +334,10 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                *outlen -= z;
                break;
 
-           default:
+           case LTC_ASN1_CHOICE:
+           case LTC_ASN1_CONSTRUCTED:
+           case LTC_ASN1_EOL:
+           case LTC_ASN1_TELETEX_STRING:
                err = CRYPT_INVALID_ARG;
                goto LBL_ERR;
        }

+ 13 - 8
src/pk/asn1/der/sequence/der_encode_sequence_multi.c

@@ -28,7 +28,8 @@
 */
 int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
 {
-   int           err, type;
+   int           err;
+   ltc_asn1_type type;
    unsigned long size, x;
    void          *data;
    va_list       args;
@@ -41,7 +42,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
    va_start(args, outlen);
    x = 0;
    for (;;) {
-       type = va_arg(args, int);
+       type = va_arg(args, ltc_asn1_type);
        size = va_arg(args, unsigned long);
        data = va_arg(args, void*);
 
@@ -68,7 +69,10 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
                 ++x;
                 break;
 
-           default:
+           case LTC_ASN1_CHOICE:
+           case LTC_ASN1_CONSTRUCTED:
+           case LTC_ASN1_EOL:
+           case LTC_ASN1_TELETEX_STRING:
                va_end(args);
                return CRYPT_INVALID_ARG;
        }
@@ -89,7 +93,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
    va_start(args, outlen);
    x = 0;
    for (;;) {
-       type = va_arg(args, int);
+       type = va_arg(args, ltc_asn1_type);
        size = va_arg(args, unsigned long);
        data = va_arg(args, void*);
 
@@ -113,12 +117,13 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
            case LTC_ASN1_SET:
            case LTC_ASN1_SETOF:
            case LTC_ASN1_RAW_BIT_STRING:
-                list[x].type   = type;
-                list[x].size   = size;
-                list[x++].data = data;
+                LTC_SET_ASN1(list, x++, type, data, size);
                 break;
 
-           default:
+           case LTC_ASN1_CHOICE:
+           case LTC_ASN1_CONSTRUCTED:
+           case LTC_ASN1_EOL:
+           case LTC_ASN1_TELETEX_STRING:
                va_end(args);
                err = CRYPT_INVALID_ARG;
                goto LBL_ERR;

+ 2 - 7
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c

@@ -49,13 +49,8 @@ int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen
         return err;
    }
 
-   alg_id[0].data = oid.OID;
-   alg_id[0].size = oid.OIDlen;
-   alg_id[0].type = LTC_ASN1_OBJECT_IDENTIFIER;
-
-   alg_id[1].data = parameters;
-   alg_id[1].size = parameters_len;
-   alg_id[1].type = parameters_type;
+   LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID,    oid.OIDlen);
+   LTC_SET_ASN1(alg_id, 1, parameters_type,            parameters, parameters_len);
 
    return der_encode_sequence_multi(out, outlen,
         LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,

+ 24 - 19
src/pk/asn1/der/set/der_encode_set.c

@@ -18,35 +18,40 @@
 #ifdef LTC_DER
 
 /* LTC define to ASN.1 TAG */
-static int ltc_to_asn1(int v)
+static int ltc_to_asn1(ltc_asn1_type v)
 {
    switch (v) {
       case LTC_ASN1_BOOLEAN:                 return 0x01;
       case LTC_ASN1_INTEGER:
       case LTC_ASN1_SHORT_INTEGER:           return 0x02;
+      case LTC_ASN1_RAW_BIT_STRING:
       case LTC_ASN1_BIT_STRING:              return 0x03;
       case LTC_ASN1_OCTET_STRING:            return 0x04;
       case LTC_ASN1_NULL:                    return 0x05;
       case LTC_ASN1_OBJECT_IDENTIFIER:       return 0x06;
       case LTC_ASN1_UTF8_STRING:             return 0x0C;
       case LTC_ASN1_PRINTABLE_STRING:        return 0x13;
+      case LTC_ASN1_TELETEX_STRING:          return 0x14;
       case LTC_ASN1_IA5_STRING:              return 0x16;
       case LTC_ASN1_UTCTIME:                 return 0x17;
       case LTC_ASN1_SEQUENCE:                return 0x30;
       case LTC_ASN1_SET:
       case LTC_ASN1_SETOF:                   return 0x31;
-      default: return -1;
+      case LTC_ASN1_CHOICE:
+      case LTC_ASN1_CONSTRUCTED:
+      case LTC_ASN1_EOL:                     return -1;
    }
-}         
-      
+   return -1;
+}
+
 
 static int qsort_helper(const void *a, const void *b)
 {
    ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;
    int            r;
-   
+
    r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type);
-   
+
    /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC.  So we force it to be :-) */
    if (r == 0) {
       /* their order in the original list now determines the position */
@@ -54,13 +59,13 @@ static int qsort_helper(const void *a, const void *b)
    } else {
       return r;
    }
-}   
+}
 
 /*
    Encode a SET type
    @param list      The list of items to encode
    @param inlen     The number of items in the list
-   @param out       [out] The destination 
+   @param out       [out] The destination
    @param outlen    [in/out] The size of the output
    @return CRYPT_OK on success
 */
@@ -70,30 +75,30 @@ int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
    ltc_asn1_list  *copy;
    unsigned long   x;
    int             err;
-   
+
    /* make copy of list */
    copy = XCALLOC(inlen, sizeof(*copy));
    if (copy == NULL) {
       return CRYPT_MEM;
-   }      
-   
+   }
+
    /* fill in used member with index so we can fully sort it */
    for (x = 0; x < inlen; x++) {
        copy[x]      = list[x];
        copy[x].used = x;
-   }       
-   
+   }
+
    /* sort it by the "type" field */
-   XQSORT(copy, inlen, sizeof(*copy), &qsort_helper);   
-   
+   XQSORT(copy, inlen, sizeof(*copy), &qsort_helper);
+
    /* call der_encode_sequence_ex() */
-   err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);   
-   
+   err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
+
    /* free list */
    XFREE(copy);
-   
+
    return err;
-}                   
+}
 
 
 #endif

+ 2 - 2
src/pk/asn1/der/teletex_string/der_decode_teletex_string.c

@@ -40,7 +40,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
       return CRYPT_INVALID_PACKET;
    }
 
-   /* check for 0x13 */
+   /* check for 0x14 */
    if ((in[0] & 0x1F) != 0x14) {
       return CRYPT_INVALID_PACKET;
    }
@@ -87,7 +87,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
 
    return CRYPT_OK;
 }
- 
+
 #endif
 
 /* $Source$ */

+ 6 - 27
testprof/der_tests.c

@@ -22,7 +22,6 @@ static void der_set_test(void)
 
    unsigned char strs[10][10], outbuf[128];
    unsigned long x, val, outlen;
-   int           err;
 
    /* make structure and encode it */
    LTC_SET_ASN1(list, 0, LTC_ASN1_OCTET_STRING,  oct_str, sizeof(oct_str));
@@ -31,21 +30,14 @@ static void der_set_test(void)
 
    /* encode it */
    outlen = sizeof(outbuf);
-   if ((err = der_encode_set(list, 3, outbuf, &outlen)) != CRYPT_OK) {
-      fprintf(stderr, "error encoding set: %s\n", error_to_string(err));
-      exit(EXIT_FAILURE);
-   }
-
+   DO(der_encode_set(list, 3, outbuf, &outlen));
 
    /* first let's test the set_decoder out of order to see what happens, we should get all the fields we expect even though they're in a diff order */
    LTC_SET_ASN1(list, 0, LTC_ASN1_BIT_STRING,    strs[1], sizeof(strs[1]));
    LTC_SET_ASN1(list, 1, LTC_ASN1_SHORT_INTEGER, &val, 1);
    LTC_SET_ASN1(list, 2, LTC_ASN1_OCTET_STRING,  strs[0], sizeof(strs[0]));
 
-   if ((err = der_decode_set(outbuf, outlen, list, 3)) != CRYPT_OK) {
-      fprintf(stderr, "error decoding set using der_decode_set: %s\n", error_to_string(err));
-      exit(EXIT_FAILURE);
-   }
+   DO(der_decode_set(outbuf, outlen, list, 3));
 
    /* now compare the items */
    if (memcmp(strs[0], oct_str, sizeof(oct_str))) {
@@ -79,20 +71,14 @@ static void der_set_test(void)
    }
 
    outlen = sizeof(outbuf);
-   if ((err = der_encode_setof(list, 10, outbuf, &outlen)) != CRYPT_OK) {
-      fprintf(stderr, "error encoding SET OF: %s\n", error_to_string(err));
-      exit(EXIT_FAILURE);
-   }
+   DO(der_encode_setof(list, 10, outbuf, &outlen));
 
    for (x = 0; x < 10; x++) {
        LTC_SET_ASN1(list, x, LTC_ASN1_PRINTABLE_STRING, strs[x], sizeof(strs[x]) - 1);
    }
    XMEMSET(strs, 0, sizeof(strs));
 
-   if ((err = der_decode_set(outbuf, outlen, list, 10)) != CRYPT_OK) {
-      fprintf(stderr, "error decoding SET OF: %s\n", error_to_string(err));
-      exit(EXIT_FAILURE);
-   }
+   DO(der_decode_set(outbuf, outlen, list, 10));
 
    /* now compare */
    for (x = 1; x < 10; x++) {
@@ -143,7 +129,6 @@ static void der_flexi_test(void)
 
    unsigned char encode_buf[192];
    unsigned long encode_buf_len, decode_len;
-   int           err;
 
    ltc_asn1_list static_list[5][3], *decoded_list, *l;
 
@@ -169,10 +154,7 @@ static void der_flexi_test(void)
 
    /* encode it */
    encode_buf_len = sizeof(encode_buf);
-   if ((err = der_encode_sequence(&static_list[0][0], 3, encode_buf, &encode_buf_len)) != CRYPT_OK) {
-      fprintf(stderr, "Encoding static_list: %s\n", error_to_string(err));
-      exit(EXIT_FAILURE);
-   }
+   DO(der_encode_sequence(&static_list[0][0], 3, encode_buf, &encode_buf_len));
 
 #if 0
    {
@@ -185,10 +167,7 @@ static void der_flexi_test(void)
 
    /* decode with flexi */
    decode_len = encode_buf_len;
-   if ((err = der_decode_sequence_flexi(encode_buf, &decode_len, &decoded_list)) != CRYPT_OK) {
-      fprintf(stderr, "decoding static_list: %s\n", error_to_string(err));
-      exit(EXIT_FAILURE);
-   }
+   DO(der_decode_sequence_flexi(encode_buf, &decode_len, &decoded_list));
 
    if (decode_len != encode_buf_len) {
       fprintf(stderr, "Decode len of %lu does not match encode len of %lu \n", decode_len, encode_buf_len);