summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2015-09-14 15:30:53 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2015-09-14 15:31:00 +0200
commita6a05643f0a1a9a5ea431bab65998a7c68b25c03 (patch)
tree786121b9e2b450b73027b2f2aa9df59a1f38edce
parent4e7a89e701d43f73b2b1398ad1eda470f7ddb9ee (diff)
downloadlibtasn1-a6a05643f0a1a9a5ea431bab65998a7c68b25c03.tar.gz
corrected regression in multi-byte tag handling
That is don't treat the explicit tag as part of the inner tag.
-rw-r--r--lib/decoding.c33
1 files 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)
{