Browse Source

ASN.1 changes required fo future ECC enhancements

Karel Miko 8 years ago
parent
commit
f155d3c530

+ 11 - 1
src/headers/tomcrypt_pk.h

@@ -529,6 +529,10 @@ typedef struct ltc_asn1_list_ {
    unsigned long size;
    unsigned long size;
    /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
    /** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
    int           used;
    int           used;
+   /** Flag used to indicate optional items in ASN.1 sequences */
+   int           optional;
+   /** Flag used to indicate context specific tags on ASN.1 sequence items */
+   unsigned char tag;
    /** prev/next entry in the list */
    /** prev/next entry in the list */
    struct ltc_asn1_list_ *prev, *next, *child, *parent;
    struct ltc_asn1_list_ *prev, *next, *child, *parent;
 } ltc_asn1_list;
 } ltc_asn1_list;
@@ -541,6 +545,8 @@ typedef struct ltc_asn1_list_ {
       LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data);  \
       LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data);  \
       LTC_MACRO_list[LTC_MACRO_temp].size = (Size);  \
       LTC_MACRO_list[LTC_MACRO_temp].size = (Size);  \
       LTC_MACRO_list[LTC_MACRO_temp].used = 0;       \
       LTC_MACRO_list[LTC_MACRO_temp].used = 0;       \
+      LTC_MACRO_list[LTC_MACRO_temp].tag = 0;        \
+      LTC_MACRO_list[LTC_MACRO_temp].optional = 0;   \
    } while (0)
    } while (0)
 
 
 /* SEQUENCE */
 /* SEQUENCE */
@@ -557,7 +563,6 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
 int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
 int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
                         unsigned long *outlen);
                         unsigned long *outlen);
 
 
-
 #ifdef LTC_SOURCE
 #ifdef LTC_SOURCE
 /* internal helper functions */
 /* internal helper functions */
 int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
 int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
@@ -570,6 +575,11 @@ int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen
 int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
 int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
         unsigned int algorithm, void* public_key, unsigned long* public_key_len,
         unsigned int algorithm, void* public_key, unsigned long* public_key_len,
         unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
         unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
+
+int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen,
+        unsigned int algorithm, void* public_key, unsigned long* public_key_len,
+        unsigned long parameters_type, void* parameters, unsigned long parameters_len,
+        unsigned long *parameters_outsize);
 #endif /* LTC_SOURCE */
 #endif /* LTC_SOURCE */
 
 
 /* SET */
 /* SET */

+ 31 - 17
src/pk/asn1/der/sequence/der_decode_sequence_ex.c

@@ -94,11 +94,25 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
           break;
           break;
        }
        }
 
 
+       /* handle context specific tags - just skip the tag + len bytes */
+       z = 0;
+       if (list[i].tag > 0 && list[i].tag == in[x + z++]) {
+         if (in[x+z] & 0x80) {
+            y = in[x + z++] & 0x7F;
+            if (y == 0 || y > 2) { return CRYPT_INVALID_PACKET; }
+            z += y;
+         } else {
+            z++;
+         }
+         x     += z;
+         inlen -= z;
+       }
+
        switch (type) {
        switch (type) {
            case LTC_ASN1_BOOLEAN:
            case LTC_ASN1_BOOLEAN:
                z = inlen;
                z = inlen;
                if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
                if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
-                   if (!ordered) { continue; }
+                   if (!ordered || list[i].optional) { continue; }
                    goto LBL_ERR;
                    goto LBL_ERR;
                }
                }
                if ((err = der_length_boolean(&z)) != CRYPT_OK) {
                if ((err = der_length_boolean(&z)) != CRYPT_OK) {
@@ -109,7 +123,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_INTEGER:
            case LTC_ASN1_INTEGER:
                z = inlen;
                z = inlen;
                if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
                if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
-                  if (!ordered) {  continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
                if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
@@ -120,7 +134,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_SHORT_INTEGER:
            case LTC_ASN1_SHORT_INTEGER:
                z = inlen;
                z = inlen;
                if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
                if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
                if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
@@ -132,7 +146,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_BIT_STRING:
            case LTC_ASN1_BIT_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -144,7 +158,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_RAW_BIT_STRING:
            case LTC_ASN1_RAW_BIT_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -156,7 +170,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_OCTET_STRING:
            case LTC_ASN1_OCTET_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -167,7 +181,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
 
 
            case LTC_ASN1_NULL:
            case LTC_ASN1_NULL:
                if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
                if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   err = CRYPT_INVALID_PACKET;
                   err = CRYPT_INVALID_PACKET;
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
@@ -177,7 +191,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_OBJECT_IDENTIFIER:
            case LTC_ASN1_OBJECT_IDENTIFIER:
                z = inlen;
                z = inlen;
                if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -189,7 +203,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_TELETEX_STRING:
            case LTC_ASN1_TELETEX_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -201,7 +215,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_IA5_STRING:
            case LTC_ASN1_IA5_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -214,7 +228,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_PRINTABLE_STRING:
            case LTC_ASN1_PRINTABLE_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -226,7 +240,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_UTF8_STRING:
            case LTC_ASN1_UTF8_STRING:
                z = inlen;
                z = inlen;
                if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
                if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                list[i].size = size;
                list[i].size = size;
@@ -238,7 +252,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_UTCTIME:
            case LTC_ASN1_UTCTIME:
                z = inlen;
                z = inlen;
                if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
                if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                break;
                break;
@@ -254,7 +268,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_SET:
            case LTC_ASN1_SET:
                z = inlen;
                z = inlen;
                if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
                if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
@@ -272,7 +286,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
 
 
                z = inlen;
                z = inlen;
                if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
                if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
@@ -284,7 +298,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
                z = inlen;
                z = inlen;
                if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
                if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
-                  if (!ordered) { continue; }
+                  if (!ordered || list[i].optional) { continue; }
                   goto LBL_ERR;
                   goto LBL_ERR;
                }
                }
                break;
                break;
@@ -305,7 +319,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
    }
    }
 
 
    for (i = 0; i < (int)outlen; i++) {
    for (i = 0; i < (int)outlen; i++) {
-      if (list[i].used == 0) {
+      if (list[i].used == 0 && list[i].optional == 0) {
           err = CRYPT_INVALID_PACKET;
           err = CRYPT_INVALID_PACKET;
           goto LBL_ERR;
           goto LBL_ERR;
       }
       }

+ 11 - 0
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c

@@ -39,6 +39,15 @@
 int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
 int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
         unsigned int algorithm, void* public_key, unsigned long* public_key_len,
         unsigned int algorithm, void* public_key, unsigned long* public_key_len,
         unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
         unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
+{
+   return der_decode_subject_public_key_info_ex(in, inlen, algorithm, public_key, public_key_len,
+                                                parameters_type, parameters, parameters_len, NULL);
+}
+
+int der_decode_subject_public_key_info_ex(const unsigned char *in, unsigned long inlen,
+        unsigned int algorithm, void* public_key, unsigned long* public_key_len,
+        unsigned long parameters_type, void* parameters, unsigned long parameters_len,
+        unsigned long *parameters_outsize)
 {
 {
    int err;
    int err;
    unsigned long len;
    unsigned long len;
@@ -79,6 +88,8 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
            goto LBL_ERR;
            goto LBL_ERR;
    }
    }
 
 
+   if (parameters_outsize) *parameters_outsize = alg_id[1].size;
+
    if ((alg_id[0].size != oid.OIDlen) ||
    if ((alg_id[0].size != oid.OIDlen) ||
         XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
         XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
         /* OID mismatch */
         /* OID mismatch */

+ 29 - 0
src/pk/asn1/der/sequence/der_encode_sequence_ex.c

@@ -31,6 +31,7 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
    int           err;
    int           err;
    ltc_asn1_type type;
    ltc_asn1_type type;
    unsigned long size, x, y, z, i;
    unsigned long size, x, y, z, i;
+   unsigned char tmptag[6];
    void          *data;
    void          *data;
 
 
    LTC_ARGCHK(list    != NULL);
    LTC_ARGCHK(list    != NULL);
@@ -200,6 +201,34 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                goto LBL_ERR;
                goto LBL_ERR;
        }
        }
 
 
+       if (list[i].tag > 0) {
+         tmptag[0] = list[i].tag;
+         y = 0;
+         if (z < 128) {
+            tmptag[1] = (unsigned char)z;
+            y = 2;
+         } else if (z < 256) {
+            tmptag[1] = 0x81;
+            tmptag[2] = (unsigned char)z;
+            y = 3;
+         } else if (z < 65536UL) {
+            tmptag[1] = 0x82;
+            tmptag[2] = (unsigned char)((z>>8UL)&255);
+            tmptag[3] = (unsigned char)(z&255);
+            y = 4;
+         } else if (z < 16777216UL) {
+            tmptag[1] = 0x83;
+            tmptag[2] = (unsigned char)((z>>16UL)&255);
+            tmptag[3] = (unsigned char)((z>>8UL)&255);
+            tmptag[4] = (unsigned char)(z&255);
+            y = 5;
+         }
+         XMEMMOVE(out + x + y, out + x, z);
+         XMEMCPY(out + x, tmptag, y);
+
+         z += y;
+       }
+
        x       += z;
        x       += z;
        *outlen -= z;
        *outlen -= z;
    }
    }

+ 19 - 0
src/pk/asn1/der/sequence/der_length_sequence.c

@@ -50,6 +50,9 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
           break;
           break;
        }
        }
 
 
+       /* some items may be optional during import */
+       if (!list[i].used && list[i].optional) continue;
+
        switch (type) {
        switch (type) {
            case LTC_ASN1_BOOLEAN:
            case LTC_ASN1_BOOLEAN:
               if ((err = der_length_boolean(&x)) != CRYPT_OK) {
               if ((err = der_length_boolean(&x)) != CRYPT_OK) {
@@ -157,6 +160,22 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                err = CRYPT_INVALID_ARG;
                err = CRYPT_INVALID_ARG;
                goto LBL_ERR;
                goto LBL_ERR;
        }
        }
+
+       /* handle context specific tags size */
+       if (list[i].tag > 0) {
+         if (x < 128) {
+            y += 2;
+         } else if (x < 256) {
+            y += 3;
+         } else if (x < 65536UL) {
+            y += 4;
+         } else if (x < 16777216UL) {
+            y += 5;
+         } else {
+            err = CRYPT_INVALID_ARG;
+            goto LBL_ERR;
+         }
+       }
    }
    }
 
 
    /* calc header size */
    /* calc header size */