瀏覽代碼

implement the Custom-type de-/encoders

Steffen Jaeckel 7 年之前
父節點
當前提交
5230977219

+ 10 - 0
src/pk/asn1/der/choice/der_decode_choice.c

@@ -205,6 +205,16 @@ int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
                }
                }
                break;
                break;
 
 
+           case LTC_ASN1_CUSTOM_TYPE:
+               if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) {
+                  if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) {
+                     list[x].used = 1;
+                     *inlen       = z;
+                     return CRYPT_OK;
+                  }
+               }
+               break;
+
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:

+ 8 - 1
src/pk/asn1/der/custom_type/der_decode_custom_type.c

@@ -72,14 +72,21 @@ int der_decode_custom_type(const unsigned char *in, unsigned long  inlen,
    outlen = root->size;
    outlen = root->size;
 
 
    if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
    if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
-      if (der_asn1_type_to_identifier_map[list[0].type] == -1) {
+      if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) ||
+            (der_asn1_type_to_identifier_map[root->used] == -1)) {
          err = CRYPT_INVALID_PACKET;
          err = CRYPT_INVALID_PACKET;
          goto LBL_ERR;
          goto LBL_ERR;
       }
       }
+
+      root->type = (ltc_asn1_type)root->used;
+      list = root;
+      outlen = 1;
+
       x -= 1;
       x -= 1;
       in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
       in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
       blksize = inlen - x;
       blksize = inlen - x;
    } else {
    } else {
+
       y = inlen - x;
       y = inlen - x;
       if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
       if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
          goto LBL_ERR;
          goto LBL_ERR;

+ 10 - 4
src/pk/asn1/der/custom_type/der_encode_custom_type.c

@@ -32,7 +32,7 @@ int der_encode_custom_type(const ltc_asn1_list *root,
 {
 {
    int           err;
    int           err;
    ltc_asn1_type type;
    ltc_asn1_type type;
-   ltc_asn1_list *list;
+   const ltc_asn1_list *list;
    unsigned long size, x, y, z, i, inlen, id_len;
    unsigned long size, x, y, z, i, inlen, id_len;
    void          *data;
    void          *data;
 
 
@@ -57,12 +57,16 @@ int der_encode_custom_type(const ltc_asn1_list *root,
 
 
 
 
    if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
    if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+      list = root;
+      inlen = 1;
       /* In case it's a PRIMITIVE type we encode directly to the output
       /* In case it's a PRIMITIVE type we encode directly to the output
        * but leave space for a potentially longer identifier as it will
        * but leave space for a potentially longer identifier as it will
        * simply be replaced afterwards.
        * simply be replaced afterwards.
        */
        */
       x -= 1;
       x -= 1;
    } else {
    } else {
+      list = root->data;
+      inlen = root->size;
       /* store length, identifier will be added later */
       /* store length, identifier will be added later */
       y = *outlen - x;
       y = *outlen - x;
       if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
       if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
@@ -71,12 +75,14 @@ int der_encode_custom_type(const ltc_asn1_list *root,
       x += y;
       x += y;
    }
    }
 
 
-   list = root->data;
-   inlen = root->size;
    /* store data */
    /* store data */
    *outlen -= x;
    *outlen -= x;
    for (i = 0; i < inlen; i++) {
    for (i = 0; i < inlen; i++) {
-       type = list[i].type;
+       if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+          type = (ltc_asn1_type)list[i].used;
+       } else {
+          type = list[i].type;
+       }
        size = list[i].size;
        size = list[i].size;
        data = list[i].data;
        data = list[i].data;
 
 

+ 13 - 11
src/pk/asn1/der/custom_type/der_length_custom_type.c

@@ -29,7 +29,7 @@
 int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen)
 int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen)
 {
 {
    int           err;
    int           err;
-   ltc_asn1_list *list;
+   const ltc_asn1_list *list;
    ltc_asn1_type type;
    ltc_asn1_type type;
    unsigned long size, x, y, i, inlen, id_len;
    unsigned long size, x, y, i, inlen, id_len;
    void          *data;
    void          *data;
@@ -37,23 +37,25 @@ int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, uns
    LTC_ARGCHK(root    != NULL);
    LTC_ARGCHK(root    != NULL);
    LTC_ARGCHK(outlen  != NULL);
    LTC_ARGCHK(outlen  != NULL);
 
 
-   if ((root->pc == LTC_ASN1_PC_PRIMITIVE) && (root->size != 1)) {
-      /* In case it's a PRIMITIVE element there has to be
-       * exactly one element following.
-       */
-      return CRYPT_INVALID_PACKET;
-   }
-
    /* get size of output that will be required */
    /* get size of output that will be required */
    if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
    if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
       return err;
       return err;
    }
    }
    y = id_len;
    y = id_len;
 
 
-   inlen = root->size;
-   list = root->data;
+   if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+      list = root;
+      inlen = 1;
+   } else {
+      list = root->data;
+      inlen = root->size;
+   }
    for (i = 0; i < inlen; i++) {
    for (i = 0; i < inlen; i++) {
-       type = list[i].type;
+       if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
+          type = (ltc_asn1_type)list[i].used;
+       } else {
+          type = list[i].type;
+       }
        size = list[i].size;
        size = list[i].size;
        data = list[i].data;
        data = list[i].data;
 
 

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

@@ -68,7 +68,8 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
    }
    }
 
 
    /* ok read data */
    /* ok read data */
-   inlen = blksize;
+   blksize = inlen;
+   inlen -= x;
    for (i = 0; i < (int)outlen; i++) {
    for (i = 0; i < (int)outlen; i++) {
        z    = 0;
        z    = 0;
        type = list[i].type;
        type = list[i].type;
@@ -80,20 +81,6 @@ 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;
@@ -280,6 +267,16 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
                }
                }
                break;
                break;
 
 
+           case LTC_ASN1_CUSTOM_TYPE:
+               z = inlen;
+               if ((err = der_decode_custom_type(in + x, z, &list[i])) != CRYPT_OK) {
+                  if (!ordered || list[i].optional) { continue; }
+                  goto LBL_ERR;
+               }
+               if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               break;
 
 
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
                z = inlen;
                z = inlen;
@@ -311,7 +308,7 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long  inlen,
       }
       }
    }
    }
 
 
-   if (inlen == 0) {
+   if (blksize == x) {
       err = CRYPT_OK;
       err = CRYPT_OK;
    } else {
    } else {
       err = CRYPT_INPUT_TOO_LONG;
       err = CRYPT_INPUT_TOO_LONG;

+ 135 - 43
src/pk/asn1/der/sequence/der_decode_sequence_flexi.c

@@ -44,7 +44,7 @@ static int _new_element(ltc_asn1_list **l)
 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
 {
 {
    ltc_asn1_list *l;
    ltc_asn1_list *l;
-   unsigned long err, type, len, totlen, data_offset;
+   unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
    void          *realloc_tmp;
    void          *realloc_tmp;
 
 
    LTC_ARGCHK(in    != NULL);
    LTC_ARGCHK(in    != NULL);
@@ -63,40 +63,76 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
 
 
    /* scan the input and and get lengths and what not */
    /* scan the input and and get lengths and what not */
    while (*inlen) {
    while (*inlen) {
-      /* read the type byte */
-      type = *in;
-
-      /* fetch length */
-      data_offset = *inlen;
-      if ((err = der_decode_asn1_length(in, &data_offset, &len)) != CRYPT_OK) {
-         goto error;
-      } else if (len > *inlen) {
-         err = CRYPT_INVALID_PACKET;
-         goto error;
-      }
-
       /* alloc new link */
       /* alloc new link */
       if ((err = _new_element(&l)) != CRYPT_OK) {
       if ((err = _new_element(&l)) != CRYPT_OK) {
          goto error;
          goto error;
       }
       }
 
 
-      if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
-         /* constructed, use the 'used' field to store the original identifier */
-         l->used = type;
-         /* treat constructed elements like SETs */
-         type = 0x20;
+      id_len = *inlen;
+      if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
+         goto error;
       }
       }
-      else if ((type & 0xC0) == 0x80) {
-         /* context-specific, use the 'used' field to store the original identifier */
-         l->used = type;
-         /* context-specific elements are treated as opaque data */
-         type = 0x80;
+      /* read the type byte */
+      identifier = *in;
+
+      if (l->type != LTC_ASN1_EOL) {
+         /* fetch length */
+         len_len = *inlen - id_len;
+#if defined(LTC_TEST_DBG)
+         data_offset = 666;
+         len = 0;
+#endif
+         if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
+#if defined(LTC_TEST_DBG)
+            fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+            goto error;
+         } else if ((len + id_len + len_len) > *inlen) {
+            err = CRYPT_INVALID_PACKET;
+#if defined(LTC_TEST_DBG)
+            fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
+#endif
+            goto error;
+         }
+         data_offset = id_len + len_len;
+#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
+         if (l->type == LTC_ASN1_CUSTOM_TYPE && l->class == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
+            fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
+         } else {
+            fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
+         }
+#endif
+         len += data_offset;
+
+         if (l->type == LTC_ASN1_CUSTOM_TYPE) {
+            /* Custom type, use the 'used' field to store the original identifier */
+            l->used = identifier;
+            if (l->pc == LTC_ASN1_PC_CONSTRUCTED) {
+               /* treat constructed elements like SEQUENCEs */
+               identifier = 0x20;
+            } else {
+               /* primitive elements are treated as opaque data */
+               identifier = 0x80;
+            }
+         }
+      } else {
+         /* Init this so gcc won't complain,
+          * as this case will only be hit when we
+          * can't decode the identifier so the
+          * switch-case should go to default anyway...
+          */
+         data_offset = 0;
       }
       }
 
 
      /* now switch on type */
      /* now switch on type */
-      switch (type) {
+      switch (identifier) {
          case 0x01: /* BOOLEAN */
          case 0x01: /* BOOLEAN */
-            l->type = LTC_ASN1_BOOLEAN;
+            if (l->type != LTC_ASN1_BOOLEAN) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
+
+            /* init field */
             l->size = 1;
             l->size = 1;
             l->data = XCALLOC(1, sizeof(int));
             l->data = XCALLOC(1, sizeof(int));
 
 
@@ -110,8 +146,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x02: /* INTEGER */
          case 0x02: /* INTEGER */
+             if (l->type != LTC_ASN1_INTEGER) {
+                err = CRYPT_PK_ASN1_ERROR;
+                goto error;
+             }
+
              /* init field */
              /* init field */
-             l->type = LTC_ASN1_INTEGER;
              l->size = 1;
              l->size = 1;
              if ((err = mp_init(&l->data)) != CRYPT_OK) {
              if ((err = mp_init(&l->data)) != CRYPT_OK) {
                  goto error;
                  goto error;
@@ -129,8 +169,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
              break;
              break;
 
 
          case 0x03: /* BIT */
          case 0x03: /* BIT */
+            if (l->type != LTC_ASN1_BIT_STRING) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
+
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_BIT_STRING;
             l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char.  */
             l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char.  */
 
 
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -148,9 +192,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x04: /* OCTET */
          case 0x04: /* OCTET */
+            if (l->type != LTC_ASN1_OCTET_STRING) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_OCTET_STRING;
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -168,6 +215,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x05: /* NULL */
          case 0x05: /* NULL */
+            if (l->type != LTC_ASN1_NULL) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* valid NULL is 0x05 0x00 */
             /* valid NULL is 0x05 0x00 */
             if (in[0] != 0x05 || in[1] != 0x00) {
             if (in[0] != 0x05 || in[1] != 0x00) {
@@ -176,7 +227,6 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             }
             }
 
 
             /* simple to store ;-) */
             /* simple to store ;-) */
-            l->type = LTC_ASN1_NULL;
             l->data = NULL;
             l->data = NULL;
             l->size = 0;
             l->size = 0;
             len     = 2;
             len     = 2;
@@ -184,9 +234,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x06: /* OID */
          case 0x06: /* OID */
+            if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_OBJECT_IDENTIFIER;
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
             if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
@@ -213,7 +266,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
          case 0x0C: /* UTF8 */
          case 0x0C: /* UTF8 */
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_UTF8_STRING;
+            if (l->type != LTC_ASN1_UTF8_STRING) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
             if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
@@ -231,9 +287,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x13: /* PRINTABLE */
          case 0x13: /* PRINTABLE */
+            if (l->type != LTC_ASN1_PRINTABLE_STRING) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_PRINTABLE_STRING;
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -251,9 +310,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x14: /* TELETEXT */
          case 0x14: /* TELETEXT */
+            if (l->type != LTC_ASN1_TELETEX_STRING) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_TELETEX_STRING;
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -271,9 +333,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x16: /* IA5 */
          case 0x16: /* IA5 */
+            if (l->type != LTC_ASN1_IA5_STRING) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_IA5_STRING;
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
             if ((l->data = XCALLOC(1, l->size)) == NULL) {
@@ -291,9 +356,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x17: /* UTC TIME */
          case 0x17: /* UTC TIME */
+            if (l->type != LTC_ASN1_UTCTIME) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
 
 
             /* init field */
             /* init field */
-            l->type = LTC_ASN1_UTCTIME;
             l->size = 1;
             l->size = 1;
 
 
             if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
             if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
@@ -312,7 +380,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
             break;
             break;
 
 
          case 0x18:
          case 0x18:
-            l->type = LTC_ASN1_GENERALIZEDTIME;
+            if (l->type != LTC_ASN1_GENERALIZEDTIME) {
+               err = CRYPT_PK_ASN1_ERROR;
+               goto error;
+            }
+
+            /* init field */
             l->size = len;
             l->size = len;
 
 
             if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
             if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
@@ -335,14 +408,23 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
          case 0x31: /* SET */
          case 0x31: /* SET */
 
 
              /* init field */
              /* init field */
-             if (type == 0x20) {
-                l->type = LTC_ASN1_CONSTRUCTED;
+             if (identifier == 0x20) {
+               if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+                  err = CRYPT_PK_ASN1_ERROR;
+                  goto error;
+               }
              }
              }
-             else if (type == 0x30) {
-                l->type = LTC_ASN1_SEQUENCE;
+             else if (identifier == 0x30) {
+               if (l->type != LTC_ASN1_SEQUENCE) {
+                  err = CRYPT_PK_ASN1_ERROR;
+                  goto error;
+               }
              }
              }
              else {
              else {
-                l->type = LTC_ASN1_SET;
+               if (l->type != LTC_ASN1_SET) {
+                  err = CRYPT_PK_ASN1_ERROR;
+                  goto error;
+               }
              }
              }
 
 
              if ((l->data = XMALLOC(len)) == NULL) {
              if ((l->data = XMALLOC(len)) == NULL) {
@@ -357,12 +439,19 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
              /* jump to the start of the data */
              /* jump to the start of the data */
              in     += data_offset;
              in     += data_offset;
              *inlen -= data_offset;
              *inlen -= data_offset;
-             len = len - data_offset;
+             len    -= data_offset;
+
+             /* save the decoded ASN.1 len */
+             len_len = len;
 
 
              /* Sequence elements go as child */
              /* Sequence elements go as child */
              if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
              if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
                 goto error;
                 goto error;
              }
              }
+             if (len_len != len) {
+                err = CRYPT_PK_ASN1_ERROR;
+                goto error;
+             }
 
 
              /* len update */
              /* len update */
              totlen += data_offset;
              totlen += data_offset;
@@ -376,7 +465,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
              break;
              break;
 
 
          case 0x80: /* Context-specific */
          case 0x80: /* Context-specific */
-             l->type = LTC_ASN1_CONTEXT_SPECIFIC;
+             if (l->type != LTC_ASN1_CUSTOM_TYPE) {
+                err = CRYPT_PK_ASN1_ERROR;
+                goto error;
+             }
 
 
              if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
              if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
                 err = CRYPT_MEM;
                 err = CRYPT_MEM;

+ 2 - 0
src/pk/asn1/der/sequence/der_decode_sequence_multi.c

@@ -72,6 +72,7 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
                 break;
                 break;
 
 
            case LTC_ASN1_EOL:
            case LTC_ASN1_EOL:
+           case LTC_ASN1_CUSTOM_TYPE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:
                va_end(args);
                va_end(args);
@@ -125,6 +126,7 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
                 break;
                 break;
            /* coverity[dead_error_line] */
            /* coverity[dead_error_line] */
            case LTC_ASN1_EOL:
            case LTC_ASN1_EOL:
+           case LTC_ASN1_CUSTOM_TYPE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:
                 break;
                 break;

+ 11 - 43
src/pk/asn1/der/sequence/der_encode_sequence_ex.c

@@ -31,7 +31,6 @@ 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);
@@ -53,21 +52,11 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
    x = 0;
    x = 0;
    out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
    out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
 
 
-   if (z < 128) {
-      out[x++] = (unsigned char)z;
-   } else if (z < 256) {
-      out[x++] = 0x81;
-      out[x++] = (unsigned char)z;
-   } else if (z < 65536UL) {
-      out[x++] = 0x82;
-      out[x++] = (unsigned char)((z>>8UL)&255);
-      out[x++] = (unsigned char)(z&255);
-   } else if (z < 16777216UL) {
-      out[x++] = 0x83;
-      out[x++] = (unsigned char)((z>>16UL)&255);
-      out[x++] = (unsigned char)((z>>8UL)&255);
-      out[x++] = (unsigned char)(z&255);
+   y = *outlen - x;
+   if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
+      goto LBL_ERR;
    }
    }
+   x += y;
 
 
    /* store data */
    /* store data */
    *outlen -= x;
    *outlen -= x;
@@ -192,6 +181,13 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                }
                }
                break;
                break;
 
 
+           case LTC_ASN1_CUSTOM_TYPE:
+               z = *outlen;
+               if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               break;
+
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:
@@ -201,34 +197,6 @@ 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;
    }
    }

+ 2 - 0
src/pk/asn1/der/sequence/der_encode_sequence_multi.c

@@ -73,6 +73,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:
+           case LTC_ASN1_CUSTOM_TYPE:
            case LTC_ASN1_EOL:
            case LTC_ASN1_EOL:
            case LTC_ASN1_TELETEX_STRING:
            case LTC_ASN1_TELETEX_STRING:
                va_end(args);
                va_end(args);
@@ -126,6 +127,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:
+           case LTC_ASN1_CUSTOM_TYPE:
            case LTC_ASN1_EOL:
            case LTC_ASN1_EOL:
            case LTC_ASN1_TELETEX_STRING:
            case LTC_ASN1_TELETEX_STRING:
                va_end(args);
                va_end(args);

+ 7 - 17
src/pk/asn1/der/sequence/der_length_sequence.c

@@ -143,6 +143,13 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                y += x;
                y += x;
                break;
                break;
 
 
+           case LTC_ASN1_CUSTOM_TYPE:
+               if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
+                  goto LBL_ERR;
+               }
+               y += x;
+               break;
+
            case LTC_ASN1_SET:
            case LTC_ASN1_SET:
            case LTC_ASN1_SETOF:
            case LTC_ASN1_SETOF:
            case LTC_ASN1_SEQUENCE:
            case LTC_ASN1_SEQUENCE:
@@ -152,7 +159,6 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
                y += x;
                y += x;
                break;
                break;
 
 
-
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CHOICE:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONSTRUCTED:
            case LTC_ASN1_CONTEXT_SPECIFIC:
            case LTC_ASN1_CONTEXT_SPECIFIC:
@@ -160,22 +166,6 @@ 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;
-         }
-       }
    }
    }
 
 
    if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
    if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {

+ 1 - 0
src/pk/asn1/der/set/der_encode_set.c

@@ -39,6 +39,7 @@ static int _ltc_to_asn1(ltc_asn1_type v)
       case LTC_ASN1_CHOICE:
       case LTC_ASN1_CHOICE:
       case LTC_ASN1_CONSTRUCTED:
       case LTC_ASN1_CONSTRUCTED:
       case LTC_ASN1_CONTEXT_SPECIFIC:
       case LTC_ASN1_CONTEXT_SPECIFIC:
+      case LTC_ASN1_CUSTOM_TYPE:
       case LTC_ASN1_EOL:                     return -1;
       case LTC_ASN1_EOL:                     return -1;
    }
    }
    return -1;
    return -1;