diff options
Diffstat (limited to 'lib/asn1_decoder.c')
-rw-r--r-- | lib/asn1_decoder.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 2e4196ddf06f..de2c8b5a715b 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] = { | |||
46 | 46 | ||
47 | /* | 47 | /* |
48 | * Find the length of an indefinite length object | 48 | * Find the length of an indefinite length object |
49 | * @data: The data buffer | ||
50 | * @datalen: The end of the innermost containing element in the buffer | ||
51 | * @_dp: The data parse cursor (updated before returning) | ||
52 | * @_len: Where to return the size of the element. | ||
53 | * @_errmsg: Where to return a pointer to an error message on error | ||
49 | */ | 54 | */ |
50 | static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, | 55 | static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen, |
51 | const char **_errmsg, size_t *_err_dp) | 56 | size_t *_dp, size_t *_len, |
57 | const char **_errmsg) | ||
52 | { | 58 | { |
53 | unsigned char tag, tmp; | 59 | unsigned char tag, tmp; |
54 | size_t dp = 0, len, n; | 60 | size_t dp = *_dp, len, n; |
55 | int indef_level = 1; | 61 | int indef_level = 1; |
56 | 62 | ||
57 | next_tag: | 63 | next_tag: |
@@ -67,8 +73,11 @@ next_tag: | |||
67 | /* It appears to be an EOC. */ | 73 | /* It appears to be an EOC. */ |
68 | if (data[dp++] != 0) | 74 | if (data[dp++] != 0) |
69 | goto invalid_eoc; | 75 | goto invalid_eoc; |
70 | if (--indef_level <= 0) | 76 | if (--indef_level <= 0) { |
71 | return dp; | 77 | *_len = dp - *_dp; |
78 | *_dp = dp; | ||
79 | return 0; | ||
80 | } | ||
72 | goto next_tag; | 81 | goto next_tag; |
73 | } | 82 | } |
74 | 83 | ||
@@ -122,7 +131,7 @@ data_overrun_error: | |||
122 | missing_eoc: | 131 | missing_eoc: |
123 | *_errmsg = "Missing EOC in indefinite len cons"; | 132 | *_errmsg = "Missing EOC in indefinite len cons"; |
124 | error: | 133 | error: |
125 | *_err_dp = dp; | 134 | *_dp = dp; |
126 | return -1; | 135 | return -1; |
127 | } | 136 | } |
128 | 137 | ||
@@ -315,13 +324,14 @@ next_op: | |||
315 | skip_data: | 324 | skip_data: |
316 | if (!(flags & FLAG_CONS)) { | 325 | if (!(flags & FLAG_CONS)) { |
317 | if (flags & FLAG_INDEFINITE_LENGTH) { | 326 | if (flags & FLAG_INDEFINITE_LENGTH) { |
318 | len = asn1_find_indefinite_length( | 327 | ret = asn1_find_indefinite_length( |
319 | data + dp, datalen - dp, &errmsg, &dp); | 328 | data, datalen, &dp, &len, &errmsg); |
320 | if (len < 0) | 329 | if (ret < 0) |
321 | goto error; | 330 | goto error; |
331 | } else { | ||
332 | dp += len; | ||
322 | } | 333 | } |
323 | pr_debug("- LEAF: %zu\n", len); | 334 | pr_debug("- LEAF: %zu\n", len); |
324 | dp += len; | ||
325 | } | 335 | } |
326 | pc += asn1_op_lengths[op]; | 336 | pc += asn1_op_lengths[op]; |
327 | goto next_op; | 337 | goto next_op; |