summaryrefslogtreecommitdiff
path: root/lib/decoding.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/decoding.c')
-rw-r--r--lib/decoding.c92
1 files changed, 60 insertions, 32 deletions
diff --git a/lib/decoding.c b/lib/decoding.c
index 1069e44..05dc236 100644
--- a/lib/decoding.c
+++ b/lib/decoding.c
@@ -43,12 +43,19 @@
#define HAVE_TWO(x) (x>=2?1:0)
+/* Decoding flags (dflags) used in several decoding functions.
+ * DECODE_FLAG_HAVE_TAG: The provided buffer includes a tag
+ * DECODE_FLAG_INDEFINITE: The provided buffer is of indefinite encoding (useful
+ * when no tags are present).
+ * DECODE_FLAG_LEVEL1: Internal flag to indicate a level of recursion for BER strings.
+ * DECODE_FLAG_LEVEL2: Internal flag to indicate two levels of recursion for BER strings.
+ * DECODE_FLAG_LEVEL3: Internal flag to indicate three levels of recursion for BER strings.
+ * This is the maximum levels of recursion possible to prevent stack
+ * exhaustion.
+ */
+
#define DECODE_FLAG_HAVE_TAG 1
#define DECODE_FLAG_INDEFINITE (1<<1)
-/* On indefinite string decoding, allow this maximum levels
- * of recursion. Allowing infinite recursion, makes the BER
- * decoder susceptible to stack exhaustion due to that recursion.
- */
#define DECODE_FLAG_LEVEL1 (1<<2)
#define DECODE_FLAG_LEVEL2 (1<<3)
#define DECODE_FLAG_LEVEL3 (1<<4)
@@ -121,7 +128,7 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
k = der[0] & 0x7F;
punt = 1;
if (k)
- { /* definite length method */
+ { /* definite length method */
ans = 0;
while (punt <= k && punt < der_len)
{
@@ -161,7 +168,7 @@ asn1_get_length_der (const unsigned char *der, int der_len, int *len)
* @der_len: Length of DER data to decode.
* @cls: Output variable containing decoded class.
* @len: Output variable containing the length of the DER TAG data.
- * @tag: Output variable containing the decoded tag.
+ * @tag: Output variable containing the decoded tag (may be %NULL).
*
* Decode the class and TAG from DER code.
*
@@ -244,9 +251,9 @@ asn1_get_length_ber (const unsigned char *ber, int ber_len, int *len)
long err;
ret = asn1_get_length_der (ber, ber_len, len);
- if (ret == -1)
+ if (ret == -1 && ber_len > 1)
{ /* indefinite length method */
- err = _asn1_get_indefinite_length_string (ber + 1, ber_len, &ret);
+ err = _asn1_get_indefinite_length_string (ber + 1, ber_len-1, &ret);
if (err != ASN1_SUCCESS)
return -3;
}
@@ -336,10 +343,10 @@ _asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *r
if (str_len < 8)
{
warn();
- return ASN1_DER_ERROR;
+ return ASN1_TIME_ENCODING_ERROR;
}
- if (flags & ASN1_DECODE_FLAG_STRICT_DER)
+ if ((flags & ASN1_DECODE_FLAG_STRICT_DER) && !(flags & ASN1_DECODE_FLAG_ALLOW_INCORRECT_TIME))
{
p = &der[len_len];
for (i=0;i<(unsigned)(str_len-1);i++)
@@ -366,14 +373,14 @@ _asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *r
}
warn();
- return ASN1_DER_ERROR;
+ return ASN1_TIME_ENCODING_ERROR;
}
}
if (sign_count == 0 && p[str_len-1] != 'Z')
{
warn();
- return ASN1_DER_ERROR;
+ return ASN1_TIME_ENCODING_ERROR;
}
}
memcpy (str, der + len_len, str_len);
@@ -391,7 +398,8 @@ _asn1_get_time_der (unsigned type, const unsigned char *der, int der_len, int *r
* @str: Pre-allocated output buffer to put the textual object id in.
* @str_size: Length of pre-allocated output buffer.
*
- * Converts a DER encoded object identifier to its textual form.
+ * Converts a DER encoded object identifier to its textual form. This
+ * function expects the DER object identifier without the tag.
*
* Returns: %ASN1_SUCCESS on success, or an error.
**/
@@ -402,7 +410,7 @@ asn1_get_object_id_der (const unsigned char *der, int der_len, int *ret_len,
int len_len, len, k;
int leading;
char temp[LTOSTR_MAX_SIZE];
- unsigned long val, val1;
+ uint64_t val, val1;
*ret_len = 0;
if (str && str_size > 0)
@@ -1147,8 +1155,8 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
if (result != ASN1_SUCCESS)
{
warn();
- goto cleanup;
- }
+ goto cleanup;
+ }
DECR_LEN(ider_len, len2);
@@ -1192,15 +1200,15 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
dflags |= DECODE_FLAG_INDEFINITE;
result = _asn1_decode_simple_ber(type_field (p->type), der+counter, ider_len, &ptmp, &vlen, &ber_len, dflags);
- if (result != ASN1_SUCCESS)
+ if (result != ASN1_SUCCESS)
{
warn();
goto cleanup;
}
- DECR_LEN(ider_len, ber_len);
+ DECR_LEN(ider_len, ber_len);
- _asn1_set_value_lv (p, ptmp, vlen);
+ _asn1_set_value_lv (p, ptmp, vlen);
counter += ber_len;
free(ptmp);
@@ -1311,7 +1319,12 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
{ /* indefinite length method */
if (!HAVE_TWO(ider_len) || ((der[counter]) || der[counter + 1]))
{
- _asn1_append_sequence_set (p, &tcache);
+ result = _asn1_append_sequence_set (p, &tcache);
+ if (result != 0)
+ {
+ warn();
+ goto cleanup;
+ }
p = tcache.tail;
move = RIGHT;
continue;
@@ -1327,7 +1340,12 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
{ /* definite length method */
if (len2 > counter)
{
- _asn1_append_sequence_set (p, &tcache);
+ result = _asn1_append_sequence_set (p, &tcache);
+ if (result != 0)
+ {
+ warn();
+ goto cleanup;
+ }
p = tcache.tail;
move = RIGHT;
continue;
@@ -1368,12 +1386,27 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
{ /* indefinite length method */
p->tmp_ival = -1;
}
+
p2 = p->down;
+ if (p2 == NULL)
+ {
+ result = ASN1_DER_ERROR;
+ warn();
+ goto cleanup;
+ }
+
while ((type_field (p2->type) == ASN1_ETYPE_TAG)
|| (type_field (p2->type) == ASN1_ETYPE_SIZE))
p2 = p2->right;
if (p2->right == NULL)
- _asn1_append_sequence_set (p, &tcache);
+ {
+ result = _asn1_append_sequence_set (p, &tcache);
+ if (result != 0)
+ {
+ warn();
+ goto cleanup;
+ }
+ }
p = p2;
}
}
@@ -1432,8 +1465,8 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
if (result != ASN1_SUCCESS)
{
warn();
- goto cleanup;
- }
+ goto cleanup;
+ }
DECR_LEN(ider_len, len2);
_asn1_set_value_lv (p, der + counter, len2);
@@ -1468,7 +1501,7 @@ asn1_der_decoding2 (asn1_node *element, const void *ider, int *max_ider_len,
if (p)
{
- p->end = counter - 1;
+ p->end = counter - 1;
}
if (p == node && move != DOWN)
@@ -1539,11 +1572,6 @@ asn1_der_decoding (asn1_node * element, const void *ider, int ider_len,
return asn1_der_decoding2 (element, ider, &ider_len, 0, errorDescription);
}
-#define FOUND 1
-#define SAME_BRANCH 2
-#define OTHER_BRANCH 3
-#define EXIT 4
-
/**
* asn1_der_decoding_element:
* @structure: pointer to an ASN1 structure
@@ -2263,8 +2291,8 @@ _asn1_decode_simple_ber (unsigned int etype, const unsigned char *der,
if (p[0] == 0 && p[1] == 0) /* EOC */
{
if (ber_len) *ber_len += 2;
- break;
- }
+ break;
+ }
/* no EOC */
der_len += 2;