diff options
Diffstat (limited to 'lib')
| -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; |
