From 98b6b92a7637b74b09df4c111ee2f7cde37534af Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Fri, 8 Aug 2025 13:15:37 -0400 Subject: [PATCH] Error from GetShortInt with negative INTEGER values --- tests/api/test_asn.c | 68 +++++++++++++++++++++++++++++------------ tests/api/test_asn.h | 4 +-- wolfcrypt/src/asn.c | 19 +++++++++++- wolfssl/wolfcrypt/asn.h | 4 +-- 4 files changed, 71 insertions(+), 24 deletions(-) diff --git a/tests/api/test_asn.c b/tests/api/test_asn.c index d9fd7d692..794029da1 100644 --- a/tests/api/test_asn.c +++ b/tests/api/test_asn.c @@ -411,7 +411,7 @@ int test_SetAsymKeyDer(void) } #ifndef NO_ASN -static int test_SetShortInt_once(word32 val, byte* valDer, word32 valDerSz) +static int test_GetSetShortInt_once(word32 val, byte* valDer, word32 valDerSz) { EXPECT_DECLS; @@ -423,6 +423,7 @@ static int test_SetShortInt_once(word32 val, byte* valDer, word32 valDerSz) word32 outDerSz = 0; word32 inOutIdx = 0; word32 maxIdx = MAX_SHORT_SZ; + int value; ExpectIntLE(2 + valDerSz, MAX_SHORT_SZ); ExpectIntEQ(outDerSz = SetShortInt(outDer, &inOutIdx, val, maxIdx), @@ -430,6 +431,11 @@ static int test_SetShortInt_once(word32 val, byte* valDer, word32 valDerSz) ExpectIntEQ(outDer[0], ASN_INTEGER); ExpectIntEQ(outDer[1], valDerSz); ExpectIntEQ(XMEMCMP(outDer + 2, valDer, valDerSz), 0); + if (val < 0x80000000) { + /* GetShortInt only supports positive values. */ + inOutIdx = 0; + ExpectIntEQ(val, GetShortInt(outDer, &inOutIdx, &value, maxIdx)); + } #endif /* !WOLFSSL_ASN_TEMPLATE || HAVE_PKCS8 || HAVE_PKCS12 */ #endif /* !NO_PWDBASED */ @@ -442,7 +448,7 @@ static int test_SetShortInt_once(word32 val, byte* valDer, word32 valDerSz) } #endif -int test_SetShortInt(void) +int test_GetSetShortInt(void) { EXPECT_DECLS; @@ -453,43 +459,43 @@ int test_SetShortInt(void) { /* Input 1 byte min */ valDer[0] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x00, valDer, 1)); + EXPECT_TEST(test_GetSetShortInt_once(0x00, valDer, 1)); /* Input 1 byte max */ valDer[0] = 0x00; valDer[1] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0xff, valDer, 2)); + EXPECT_TEST(test_GetSetShortInt_once(0xff, valDer, 2)); /* Input 2 bytes min */ valDer[0] = 0x01; valDer[1] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x0100, valDer, 2)); + EXPECT_TEST(test_GetSetShortInt_once(0x0100, valDer, 2)); /* Input 2 bytes max */ valDer[0] = 0x00; valDer[1] = 0xff; valDer[2] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0xffff, valDer, 3)); + EXPECT_TEST(test_GetSetShortInt_once(0xffff, valDer, 3)); /* Input 3 bytes min */ valDer[0] = 0x01; valDer[1] = 0x00; valDer[2] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x010000, valDer, 3)); + EXPECT_TEST(test_GetSetShortInt_once(0x010000, valDer, 3)); /* Input 3 bytes max */ valDer[0] = 0x00; valDer[1] = 0xff; valDer[2] = 0xff; valDer[3] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0xffffff, valDer, 4)); + EXPECT_TEST(test_GetSetShortInt_once(0xffffff, valDer, 4)); /* Input 4 bytes min */ valDer[0] = 0x01; valDer[1] = 0x00; valDer[2] = 0x00; valDer[3] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x01000000, valDer, 4)); + EXPECT_TEST(test_GetSetShortInt_once(0x01000000, valDer, 4)); /* Input 4 bytes max */ valDer[0] = 0x00; @@ -497,7 +503,7 @@ int test_SetShortInt(void) valDer[2] = 0xff; valDer[3] = 0xff; valDer[4] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0xffffffff, valDer, 5)); + EXPECT_TEST(test_GetSetShortInt_once(0xffffffff, valDer, 5)); } /* Corner tests for output size */ @@ -506,43 +512,43 @@ int test_SetShortInt(void) /* Output 1 byte max */ valDer[0] = 0x7f; - EXPECT_TEST(test_SetShortInt_once(0x7f, valDer, 1)); + EXPECT_TEST(test_GetSetShortInt_once(0x7f, valDer, 1)); /* Output 2 bytes min */ valDer[0] = 0x00; valDer[1] = 0x80; - EXPECT_TEST(test_SetShortInt_once(0x80, valDer, 2)); + EXPECT_TEST(test_GetSetShortInt_once(0x80, valDer, 2)); /* Output 2 bytes max */ valDer[0] = 0x7f; valDer[1] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0x7fff, valDer, 2)); + EXPECT_TEST(test_GetSetShortInt_once(0x7fff, valDer, 2)); /* Output 3 bytes min */ valDer[0] = 0x00; valDer[1] = 0x80; valDer[2] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x8000, valDer, 3)); + EXPECT_TEST(test_GetSetShortInt_once(0x8000, valDer, 3)); /* Output 3 bytes max */ valDer[0] = 0x7f; valDer[1] = 0xff; valDer[2] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0x7fffff, valDer, 3)); + EXPECT_TEST(test_GetSetShortInt_once(0x7fffff, valDer, 3)); /* Output 4 bytes min */ valDer[0] = 0x00; valDer[1] = 0x80; valDer[2] = 0x00; valDer[3] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x800000, valDer, 4)); + EXPECT_TEST(test_GetSetShortInt_once(0x800000, valDer, 4)); /* Output 4 bytes max */ valDer[0] = 0x7f; valDer[1] = 0xff; valDer[2] = 0xff; valDer[3] = 0xff; - EXPECT_TEST(test_SetShortInt_once(0x7fffffff, valDer, 4)); + EXPECT_TEST(test_GetSetShortInt_once(0x7fffffff, valDer, 4)); /* Output 5 bytes min */ valDer[0] = 0x00; @@ -550,7 +556,7 @@ int test_SetShortInt(void) valDer[2] = 0x00; valDer[3] = 0x00; valDer[4] = 0x00; - EXPECT_TEST(test_SetShortInt_once(0x80000000, valDer, 5)); + EXPECT_TEST(test_GetSetShortInt_once(0x80000000, valDer, 5)); /* Skip "Output 5 bytes max" because of same as "Input 4 bytes max" */ } @@ -558,8 +564,32 @@ int test_SetShortInt(void) /* Extra tests */ { valDer[0] = 0x01; - EXPECT_TEST(test_SetShortInt_once(0x01, valDer, 1)); + EXPECT_TEST(test_GetSetShortInt_once(0x01, valDer, 1)); } + +#if !defined(NO_PWDBASED) || defined(WOLFSSL_ASN_EXTRA) + /* Negative INTEGER values. */ + { + word32 idx = 0; + int value; + + valDer[0] = ASN_INTEGER; + valDer[1] = 1; + valDer[2] = 0x80; + ExpectIntEQ(GetShortInt(valDer, &idx, &value, 3), + WC_NO_ERR_TRACE(ASN_EXPECT_0_E)); + + idx = 0; + valDer[0] = ASN_INTEGER; + valDer[1] = 4; + valDer[2] = 0xFF; + valDer[3] = 0xFF; + valDer[4] = 0xFF; + valDer[5] = 0xFF; + ExpectIntEQ(GetShortInt(valDer, &idx, &value, 6), + WC_NO_ERR_TRACE(ASN_EXPECT_0_E)); + } +#endif #endif return EXPECT_RESULT(); diff --git a/tests/api/test_asn.h b/tests/api/test_asn.h index b8bb688bd..1d2e20b2f 100644 --- a/tests/api/test_asn.h +++ b/tests/api/test_asn.h @@ -25,12 +25,12 @@ #include int test_SetAsymKeyDer(void); -int test_SetShortInt(void); +int test_GetSetShortInt(void); int test_wc_IndexSequenceOf(void); #define TEST_ASN_DECLS \ TEST_DECL_GROUP("asn", test_SetAsymKeyDer), \ - TEST_DECL_GROUP("asn", test_SetShortInt), \ + TEST_DECL_GROUP("asn", test_GetSetShortInt), \ TEST_DECL_GROUP("asn", test_wc_IndexSequenceOf) #endif /* WOLFCRYPT_TEST_ASN_H */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index a68e4bf85..c67fd92c5 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1294,6 +1294,12 @@ static int GetASN_StoreData(const ASNItem* asn, ASNGetData* data, #endif return ASN_PARSE_E; } + if (!zeroPadded && (input[idx] >= 0x80U)) { + #ifdef WOLFSSL_DEBUG_ASN_TEMPLATE + WOLFSSL_MSG_VSNPRINTF("Unexpected negative INTEGER value"); + #endif + return ASN_EXPECT_0_E; + } /* Fill number with all of data. */ *data->data.u16 = 0; for (i = 0; i < len; i++) { @@ -1309,6 +1315,12 @@ static int GetASN_StoreData(const ASNItem* asn, ASNGetData* data, #endif return ASN_PARSE_E; } + if (!zeroPadded && (input[idx] >= 0x80U)) { + #ifdef WOLFSSL_DEBUG_ASN_TEMPLATE + WOLFSSL_MSG_VSNPRINTF("Unexpected negative INTEGER value"); + #endif + return ASN_EXPECT_0_E; + } /* Fill number with all of data. */ *data->data.u32 = 0; for (i = 0; i < len; i++) { @@ -3271,7 +3283,7 @@ int GetMyVersion(const byte* input, word32* inOutIdx, #if !defined(NO_PWDBASED) || defined(WOLFSSL_ASN_EXTRA) -/* Decode small integer, 32 bits or less. +/* Decode small positive integer, 32 bits or less. * * @param [in] input Buffer of BER data. * @param [in, out] inOutIdx On in, start of encoded INTEGER. @@ -3309,6 +3321,11 @@ int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) if (len + idx > maxIdx) return ASN_PARSE_E; + if (input[idx] >= 0x80U) { + /* This function only expects positive INTEGER values. */ + return ASN_EXPECT_0_E; + } + while (len--) { *number = *number << 8 | input[idx++]; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 58f40b9dd..80811316e 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2229,8 +2229,8 @@ WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name); WOLFSSL_LOCAL const char* GetOneCertName(CertName* name, int idx); WOLFSSL_LOCAL byte GetCertNameId(int idx); #endif -WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number, - word32 maxIdx); +WOLFSSL_TEST_VIS int GetShortInt(const byte* input, word32* inOutIdx, + int* number, word32 maxIdx); WOLFSSL_TEST_VIS int SetShortInt(byte* output, word32* inOutIdx, word32 number, word32 maxIdx);