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.
This commit is contained in:
Daniel Pouzzner
2025-08-12 18:10:14 -05:00
parent 22b221a8be
commit 344db9d7f7
2 changed files with 58 additions and 15 deletions

View File

@@ -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 */

View File

@@ -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. */