From b1f25ab306745917985f80217b3e4b411fae31be Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Tue, 11 Jun 2024 23:18:55 +0800 Subject: [PATCH] Fix DER length decoding bug `asn1_length_from_der` incorrectly accept the BER long length. --- src/asn1.c | 9 +++++++++ tests/asn1test.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/asn1.c b/src/asn1.c index 4059bb97..dd010ce5 100644 --- a/src/asn1.c +++ b/src/asn1.c @@ -202,6 +202,15 @@ int asn1_length_from_der(size_t *len, const uint8_t **in, size_t *inlen) error_print(); return -1; } + // make sure length is not in BER long presentation + if (nbytes == 1 && **in < 0x80) { + error_print(); + return -1; + } + if (nbytes > 1 && **in == 0) { + error_print(); + return -1; + } memcpy(buf + 4 - nbytes, *in, nbytes); *len = (size_t)GETU32(buf); diff --git a/tests/asn1test.c b/tests/asn1test.c index 211b457e..8bd69705 100644 --- a/tests/asn1test.c +++ b/tests/asn1test.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,37 @@ static int test_asn1_length(void) return 1; } +static int test_asn1_length_from_ber(void) +{ + char *tests[] = { + "80", + "8100", + "8101", + "820000", + "820001", + "8200ff", + "83001122", + "8400ffffff", + "850100000000", + }; + uint8_t buf[16]; + const uint8_t *p; + size_t a, len, i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[i]); i++) { + hex_to_bytes(tests[i], strlen(tests[i]), buf, &len); + p = buf; + len = (size_t)((uint64_t)1 << 33); + if (asn1_length_from_der(&a, &p, &len) != -1) { + error_print(); + return -1; + } + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + static int test_asn1_boolean(void) { int tests[] = {0, 1}; @@ -807,6 +839,7 @@ int main(void) { if (test_asn1_tag() != 1) goto err; if (test_asn1_length() != 1) goto err; + if (test_asn1_length_from_ber() != 1) goto err; if (test_asn1_boolean() != 1) goto err; if (test_asn1_int() != 1) goto err; if (test_asn1_bits() != 1) goto err;