From 344db9d7f7362670b3552c99739c08b246c3906f Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Tue, 12 Aug 2025 18:10:14 -0500 Subject: [PATCH] wolfcrypt/src/coding.c: in Base64_Decode_nonCT() and Base64_Decode(), remove overly restrictive preamble check on outLen; return BUFFER_E, not BAD_FUNC_ARG, when output buffer is too short (similarly fixed in Base16_Decode()); wolfcrypt/test/test.c: add N_BYTE_TEST() and test vectors to test all input and output length scenarios. --- wolfcrypt/src/coding.c | 18 ++++---------- wolfcrypt/test/test.c | 55 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index 2b0a4b212..c9153da58 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -171,13 +171,9 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen) { word32 i = 0; word32 j = 0; - word32 plainSz = inLen - ((inLen + (BASE64_LINE_SZ - 1)) / BASE64_LINE_SZ ); int ret; const byte maxIdx = BASE64DECODE_TABLE_SZ + BASE64_MIN - 1; - plainSz = (plainSz * 3 + 3) / 4; - if (plainSz > *outLen) return BAD_FUNC_ARG; - while (inLen > 3) { int pad3 = 0; int pad4 = 0; @@ -233,7 +229,7 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen) if (i + 1 + !pad3 + !pad4 > *outLen) { WOLFSSL_MSG("Bad Base64 Decode out buffer, too small"); - return BAD_FUNC_ARG; + return BUFFER_E; } e1 = Base64_Char2Val_by_table(e1); @@ -263,7 +259,7 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen) if (out && *outLen > i) out[i]= '\0'; - *outLen = i; + *outLen = i; /* Note, does not reflect terminating null, if any. */ return 0; } @@ -274,12 +270,8 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) { word32 i = 0; word32 j = 0; - word32 plainSz = inLen - ((inLen + (BASE64_LINE_SZ - 1)) / BASE64_LINE_SZ ); int ret; - plainSz = (plainSz * 3 + 3) / 4; - if (plainSz > *outLen) return BAD_FUNC_ARG; - while (inLen > 3) { int pad3 = 0; int pad4 = 0; @@ -324,7 +316,7 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) if (i + 1 + !pad3 + !pad4 > *outLen) { WOLFSSL_MSG("Bad Base64 Decode out buffer, too small"); - return BAD_FUNC_ARG; + return BUFFER_E; } e1 = Base64_Char2Val_CT(e1); @@ -354,7 +346,7 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) if (out && *outLen > i) out[i]= '\0'; - *outLen = i; + *outLen = i; /* Note, does not reflect terminating null, if any. */ return 0; } @@ -630,7 +622,7 @@ int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) return BAD_FUNC_ARG; if (*outLen < (inLen / 2)) - return BAD_FUNC_ARG; + return BUFFER_E; while (inLen) { byte b = (byte)(in[inIdx++] - BASE16_MIN); /* 0 starts at 0x30 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4ea30d48f..113e50af4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -2970,6 +2970,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void) "abcdefghijklmnopqrstuvwxyz" "0123456789+/;"; static const byte charTest[] = "A+Gd\0\0\0"; + static const byte oneByteTest[] = "YQ=="; + static const byte twoByteTest[] = "YWE="; + static const byte threeByteTest[] = "YWFh"; + static const byte fourByteTest[] = "YWFhYQ=="; + static const byte byteTestOutput[] = "aaaa"; int i; WOLFSSL_ENTER("base64_test"); @@ -2997,7 +3002,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void) /* Bad parameters. */ outLen = 1; ret = Base64_Decode(good, sizeof(good), out, &outLen); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + if (ret != WC_NO_ERR_TRACE(BUFFER_E)) return WC_TEST_RET_ENC_EC(ret); outLen = sizeof(out); @@ -3046,6 +3051,48 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void) return WC_TEST_RET_ENC_I(i); } + /* overrun/right-sized tests */ +#define N_BYTE_TEST(f, n, t) do { \ + outLen = (n) - 1; \ + ret = (f)(t, sizeof(t), out, &outLen); \ + if (ret != WC_NO_ERR_TRACE(BUFFER_E)) \ + return WC_TEST_RET_ENC_EC(ret); \ + outLen = (n); \ + ret = (f)(t, sizeof(t), out, &outLen); \ + if (ret != 0) \ + return WC_TEST_RET_ENC_EC(ret); \ + if (outLen != (n)) \ + return WC_TEST_RET_ENC_I(outLen); \ + ret = XMEMCMP(out, byteTestOutput, (n)); \ + if (ret != 0) \ + return WC_TEST_RET_ENC_I(ret); \ + ret = (f)(t, sizeof(t) - 1, out, &outLen); \ + if (ret != 0) \ + return WC_TEST_RET_ENC_EC(ret); \ + if (outLen != (n)) \ + return WC_TEST_RET_ENC_I(outLen); \ + ret = XMEMCMP(out, byteTestOutput, (n)); \ + if (ret != 0) \ + return WC_TEST_RET_ENC_I(ret); \ + outLen = (n) + 1; \ + out[n] = 1; \ + ret = (f)(t, sizeof(t), out, &outLen); \ + if (ret != 0) \ + return WC_TEST_RET_ENC_EC(ret); \ + if (outLen != (n)) \ + return WC_TEST_RET_ENC_I(outLen); \ + ret = XMEMCMP(out, byteTestOutput, (n)); \ + if (ret != 0) \ + return WC_TEST_RET_ENC_I(ret); \ + if (out[n] != 0) \ + return WC_TEST_RET_ENC_NC; \ + } while (0) + + N_BYTE_TEST(Base64_Decode, 1, oneByteTest); + N_BYTE_TEST(Base64_Decode, 2, twoByteTest); + N_BYTE_TEST(Base64_Decode, 3, threeByteTest); + N_BYTE_TEST(Base64_Decode, 4, fourByteTest); + /* Same tests again, using Base64_Decode_nonCT() */ /* Good Base64 encodings. */ @@ -3072,7 +3119,7 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void) /* Bad parameters. */ outLen = 1; ret = Base64_Decode_nonCT(good, sizeof(good), out, &outLen); - if (ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) + if (ret != WC_NO_ERR_TRACE(BUFFER_E)) return WC_TEST_RET_ENC_EC(ret); outLen = sizeof(out); @@ -3121,6 +3168,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void) return WC_TEST_RET_ENC_I(i); } + N_BYTE_TEST(Base64_Decode_nonCT, 1, oneByteTest); + N_BYTE_TEST(Base64_Decode_nonCT, 2, twoByteTest); + N_BYTE_TEST(Base64_Decode_nonCT, 3, threeByteTest); + N_BYTE_TEST(Base64_Decode_nonCT, 4, fourByteTest); #ifdef WOLFSSL_BASE64_ENCODE /* Decode and encode all symbols - non-alphanumeric. */