diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 2e4196ddf06..de2c8b5a715 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -46,12 +46,18 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = { /* * Find the length of an indefinite length object + * @data: The data buffer + * @datalen: The end of the innermost containing element in the buffer + * @_dp: The data parse cursor (updated before returning) + * @_len: Where to return the size of the element. + * @_errmsg: Where to return a pointer to an error message on error */ static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, - const char **_errmsg, size_t *_err_dp) + size_t *_dp, size_t *_len, + const char **_errmsg) { unsigned char tag, tmp; - size_t dp = 0, len, n; + size_t dp = *_dp, len, n; int indef_level = 1; next_tag: @@ -67,8 +73,11 @@ next_tag: /* It appears to be an EOC. */ if (data[dp++] != 0) goto invalid_eoc; - if (--indef_level <= 0) - return dp; + if (--indef_level <= 0) { + *_len = dp - *_dp; + *_dp = dp; + return 0; + } goto next_tag; } @@ -122,7 +131,7 @@ data_overrun_error: missing_eoc: *_errmsg = "Missing EOC in indefinite len cons"; error: - *_err_dp = dp; + *_dp = dp; return -1; } @@ -315,13 +324,14 @@ next_op: skip_data: if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) { - len = asn1_find_indefinite_length( - data + dp, datalen - dp, &errmsg, &dp); - if (len < 0) + ret = asn1_find_indefinite_length( + data, datalen, &dp, &len, &errmsg); + if (ret < 0) goto error; + } else { + dp += len; } pr_debug("- LEAF: %zu\n", len); - dp += len; } pc += asn1_op_lengths[op]; goto next_op;