summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-04-07 17:38:37 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-04-08 12:20:39 +0200
commitc89e27ee98c5567453c68e035a74d0ed9e1b7d54 (patch)
treecff215ca703bfa879472fc8fdc4e064579dfde3c
parentc8d8c06676976df78defba22ab3d1db2425c442a (diff)
downloadlibtasn1-c89e27ee98c5567453c68e035a74d0ed9e1b7d54.tar.gz
asn1_decode_simple_ber: simplified and cleaned up
-rw-r--r--lib/decoding.c112
-rw-r--r--lib/int.h6
2 files changed, 73 insertions, 45 deletions
diff --git a/lib/decoding.c b/lib/decoding.c
index 2b2faf6..95d3b60 100644
--- a/lib/decoding.c
+++ b/lib/decoding.c
@@ -2182,7 +2182,10 @@ asn1_decode_simple_der (unsigned int etype, const unsigned char *der,
return ret;
if (class != ETYPE_CLASS (etype) || tag != ETYPE_TAG (etype))
- return ASN1_DER_ERROR;
+ {
+ warn();
+ return ASN1_DER_ERROR;
+ }
p += tag_len;
der_len -= tag_len;
@@ -2242,8 +2245,9 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
unsigned char class;
unsigned long tag;
unsigned char *out = NULL;
+ const unsigned char *cout = NULL;
unsigned out_len;
- long ret;
+ long result;
if (ber_len) *ber_len = 0;
@@ -2259,7 +2263,7 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
return ASN1_VALUE_NOT_VALID;
}
- /* doesn't handle constructed classes */
+ /* doesn't handle constructed + definite classes */
if (ETYPE_CLASS (etype) != ASN1_CLASS_UNIVERSAL)
{
warn();
@@ -2267,15 +2271,13 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
}
p = der;
- ret = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
- if (ret != ASN1_SUCCESS)
+ result = asn1_get_tag_der (p, der_len, &class, &tag_len, &tag);
+ if (result != ASN1_SUCCESS)
{
warn();
- return ret;
+ return result;
}
- if (ber_len) *ber_len += tag_len;
-
if (tag != ETYPE_TAG (etype))
{
warn();
@@ -2283,24 +2285,25 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
}
p += tag_len;
- der_len -= tag_len;
- if (der_len <= 0)
- return ASN1_DER_ERROR;
+ DECR_LEN(der_len, tag_len);
+
+ if (ber_len) *ber_len += tag_len;
+
+ /* indefinite constructed */
if (class == ASN1_CLASS_STRUCTURED && ETYPE_IS_STRING(etype))
{
-
len_len = 1;
+
+ DECR_LEN(der_len, len_len);
if (p[0] != 0x80)
{
warn();
- return ASN1_DER_ERROR;
+ result = ASN1_DER_ERROR;
+ goto cleanup;
}
p += len_len;
- der_len -= len_len;
- if (der_len <= 0)
- return ASN1_DER_ERROR;
if (ber_len) *ber_len += len_len;
@@ -2309,38 +2312,48 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
{
unsigned tmp_len;
- ret = asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len);
- if (ret != ASN1_SUCCESS)
+ result = asn1_decode_simple_ber(etype, p, der_len, &out, &out_len, &tmp_len);
+ if (result != ASN1_SUCCESS)
{
- free(total);
- return ret;
+ warn();
+ goto cleanup;
}
+
p += tmp_len;
- der_len -= tmp_len;
+ DECR_LEN(der_len, tmp_len);
+
if (ber_len) *ber_len += tmp_len;
- if (der_len < 2) /* we need the EOC */
- {
- free(total);
- return ASN1_DER_ERROR;
- }
+ DECR_LEN(der_len, 2); /* we need the EOC */
if (out_len > 0)
{
- ret = append(&total, &total_size, out, out_len);
- free(out);
- if (ret != ASN1_SUCCESS)
+ result = append(&total, &total_size, out, out_len);
+ if (result != ASN1_SUCCESS)
{
- free(total);
- return ret;
+ warn();
+ goto cleanup;
}
}
+ free(out);
+ out = NULL;
+
if (p[0] == 0 && p[1] == 0) /* EOC */
{
if (ber_len) *ber_len += 2;
break;
}
+
+ /* no EOC */
+ der_len += 2;
+
+ if (der_len == 2)
+ {
+ warn();
+ result = ASN1_DER_ERROR;
+ goto cleanup;
+ }
}
while(1);
}
@@ -2348,29 +2361,44 @@ asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
{
if (ber_len)
{
- ret = asn1_get_length_der (p, der_len, &len_len);
- if (ret < 0)
+ result = asn1_get_length_der (p, der_len, &len_len);
+ if (result < 0)
{
warn();
- return ASN1_DER_ERROR;
+ result = ASN1_DER_ERROR;
+ goto cleanup;
}
- *ber_len += ret + len_len;
+ *ber_len += result + len_len;
}
/* non-string values are decoded as DER */
- ret = asn1_decode_simple_der(etype, der, _der_len, (const unsigned char**)&out, &out_len);
- if (ret != ASN1_SUCCESS)
- return ret;
+ result = asn1_decode_simple_der(etype, der, _der_len, &cout, &out_len);
+ if (result != ASN1_SUCCESS)
+ {
+ warn();
+ goto cleanup;
+ }
- ret = append(&total, &total_size, out, out_len);
- if (ret != ASN1_SUCCESS)
- return ret;
+ result = append(&total, &total_size, cout, out_len);
+ if (result != ASN1_SUCCESS)
+ {
+ warn();
+ goto cleanup;
+ }
}
else
- return ASN1_DER_ERROR;
+ {
+ warn();
+ result = ASN1_DER_ERROR;
+ goto cleanup;
+ }
*str = total;
*str_len = total_size;
return ASN1_SUCCESS;
+cleanup:
+ free(out);
+ free(total);
+ return result;
}
diff --git a/lib/int.h b/lib/int.h
index a3e890d..f1f1302 100644
--- a/lib/int.h
+++ b/lib/int.h
@@ -97,9 +97,9 @@ typedef struct tag_and_class_st
#define ETYPE_TAG(etype) (_asn1_tags[etype].tag)
#define ETYPE_CLASS(etype) (_asn1_tags[etype].class)
-#define ETYPE_OK(etype) ((etype != ASN1_ETYPE_INVALID && \
- etype <= _asn1_tags_size && \
- _asn1_tags[etype].desc != NULL)?1:0)
+#define ETYPE_OK(etype) (((etype) != ASN1_ETYPE_INVALID && \
+ (etype) <= _asn1_tags_size && \
+ _asn1_tags[(etype)].desc != NULL)?1:0)
#define ETYPE_IS_STRING(etype) ((etype == ASN1_ETYPE_GENERALSTRING || \
etype == ASN1_ETYPE_NUMERIC_STRING || etype == ASN1_ETYPE_IA5_STRING || \