From a6a05643f0a1a9a5ea431bab65998a7c68b25c03 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 14 Sep 2015 15:30:53 +0200 Subject: corrected regression in multi-byte tag handling That is don't treat the explicit tag as part of the inner tag. --- lib/decoding.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/decoding.c b/lib/decoding.c index 4d2302f..caf1eb4 100644 --- a/lib/decoding.c +++ b/lib/decoding.c @@ -480,10 +480,12 @@ asn1_get_bit_der (const unsigned char *der, int der_len, return ASN1_SUCCESS; } - +/* tag_len: the total tag length (explicit+inner) + * inner_tag_len: the inner_tag length + */ static int _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, - int *ret_len, unsigned flags) + int *tag_len, int *inner_tag_len, unsigned flags) { asn1_node p; int counter, len2, len3, is_tag_implicit; @@ -594,7 +596,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, unsigned type = type_field (node->type); if (type == ASN1_ETYPE_TAG) { - *ret_len = 0; + *tag_len = 0; + if (inner_tag_len) + *inner_tag_len = 0; return ASN1_SUCCESS; } @@ -654,7 +658,9 @@ _asn1_extract_tag_der (asn1_node node, const unsigned char *der, int der_len, } counter += len2; - *ret_len = counter; + *tag_len = counter; + if (inner_tag_len) + *inner_tag_len = len2; return ASN1_SUCCESS; cleanup: @@ -663,7 +669,7 @@ cleanup: static int extract_tag_der_recursive(asn1_node node, const unsigned char *der, int der_len, - int *ret_len, unsigned flags) + int *ret_len, int *inner_len, unsigned flags) { asn1_node p; int ris = ASN1_DER_ERROR; @@ -673,7 +679,7 @@ int ris = ASN1_DER_ERROR; p = node->down; while (p) { - ris = _asn1_extract_tag_der (p, der, der_len, ret_len, flags); + ris = _asn1_extract_tag_der (p, der, der_len, ret_len, inner_len, flags); if (ris == ASN1_SUCCESS) break; p = p->right; @@ -683,7 +689,7 @@ int ris = ASN1_DER_ERROR; return ris; } else - return _asn1_extract_tag_der (node, der, der_len, ret_len, flags); + return _asn1_extract_tag_der (node, der, der_len, ret_len, inner_len, flags); } static int @@ -1014,6 +1020,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, unsigned long tag; int tag_len; int indefinite, result, total_len = *max_ider_len, ider_len = *max_ider_len; + int inner_tag_len; const unsigned char *der = ider; node = *element; @@ -1037,6 +1044,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, while (1) { tag_len = 0; + inner_tag_len = 0; ris = ASN1_SUCCESS; if (move != UP) { @@ -1074,7 +1082,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, { ris = extract_tag_der_recursive (p2, der + counter, - ider_len, &len2, flags); + ider_len, &len2, NULL, flags); if (ris == ASN1_SUCCESS) { p2->type &= ~CONST_NOT_USED; @@ -1124,7 +1132,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, { ris = extract_tag_der_recursive (p->down, der + counter, - ider_len, &len2, flags); + ider_len, &len2, NULL, flags); if (ris == ASN1_SUCCESS) { @@ -1171,7 +1179,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, if (ris == ASN1_SUCCESS) ris = extract_tag_der_recursive (p, der + counter, ider_len, - &tag_len, flags); + &tag_len, &inner_tag_len, flags); if (ris != ASN1_SUCCESS) { @@ -1289,14 +1297,15 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len, move = RIGHT; break; case ASN1_ETYPE_OCTET_STRING: - if (counter < tag_len) + if (counter < inner_tag_len) { result = ASN1_DER_ERROR; warn(); goto cleanup; } + result = get_octet_string (p, der + counter, ider_len, - der + counter - tag_len, tag_len, + der + counter - inner_tag_len, inner_tag_len, &len3, flags); if (result != ASN1_SUCCESS) { -- cgit v1.2.1