Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion linuxkm/linuxkm_wc_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -1920,7 +1920,7 @@
#define WC_LINUXKM_ROUND_UP_P_OF_2(x) ( \
{ \
size_t _alloc_sz = (x); \
if ((_alloc_sz < 8192) && (_alloc_sz != 0)) \
if ((_alloc_sz < 8192) && (_alloc_sz > 1)) \
_alloc_sz = 1UL << \
((sizeof(_alloc_sz) * 8UL) - __builtin_clzl(_alloc_sz - 1)); \
_alloc_sz; \
Expand Down
12 changes: 12 additions & 0 deletions linuxkm/lkcapi_rsa_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,12 @@ static int km_pkcs1pad_verify(struct akcipher_request *req)
goto pkcs1pad_verify_out;
}

/* bail if the padded ASN.1-prefixed digest won't fit in the given RSA key. */
if ((word64)ctx->digest_len + (word64)hash_enc_len + RSA_MIN_PAD_SZ > ctx->key_len) {
err = -EOVERFLOW;
goto pkcs1pad_verify_out;
}

work_buffer = malloc(2 * ctx->key_len);
if (unlikely(work_buffer == NULL)) {
err = -ENOMEM;
Expand Down Expand Up @@ -1513,6 +1519,12 @@ static int km_pkcs1_verify(struct crypto_sig *tfm,
goto pkcs1_verify_out;
}

/* bail if the padded ASN.1-prefixed digest won't fit in the given RSA key. */
if ((word64)ctx->digest_len + (word64)hash_enc_len + RSA_MIN_PAD_SZ > ctx->key_len) {
err = -EOVERFLOW;
goto pkcs1_verify_out;
}

work_buffer = malloc(2 * ctx->key_len);
if (unlikely(work_buffer == NULL)) {
err = -ENOMEM;
Expand Down
62 changes: 52 additions & 10 deletions wolfcrypt/src/coding.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen)
}
e1 = in[j++];
if (e1 == '\0') {
inLen = 0;
break;
}
inLen--;
Expand Down Expand Up @@ -230,11 +231,6 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen)
return ASN_INPUT_E;
}

if (i + 1 + !pad3 + !pad4 > *outLen) {
WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
return BUFFER_E;
}

e1 = Base64_Char2Val_by_table(e1);
e2 = Base64_Char2Val_by_table(e2);
e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_by_table(e3));
Expand All @@ -245,6 +241,11 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen)
return ASN_INPUT_E;
}

if (i + 1 + !pad3 + !pad4 > *outLen) {
WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
return BUFFER_E;
}

b1 = (byte)((e1 << 2) | (e2 >> 4));
b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
b3 = (byte)(((e3 & 0x3) << 6) | e4);
Expand All @@ -258,6 +259,24 @@ int Base64_Decode_nonCT(const byte* in, word32 inLen, byte* out, word32* outLen)
break;
}

/* If there is still input available, and it's not whitespace or nulls, then
* the input is invalid.
*/
while (inLen > 0) {
word32 cur_j = j;
if (in[j] == 0)
break;
if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
/* Running out of buffer here is not an error */
break;
}
return ret;
}
if (j == cur_j)
return ASN_INPUT_E;
}

/* If the output buffer has a room for an extra byte, add a null terminator */
if (out && *outLen > i)
out[i]= '\0';
Expand Down Expand Up @@ -294,6 +313,7 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
}
e1 = in[j++];
if (e1 == '\0') {
inLen = 0;
break;
}
inLen--;
Expand Down Expand Up @@ -321,11 +341,6 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
if (pad3 && !pad4)
return ASN_INPUT_E;

if (i + 1 + !pad3 + !pad4 > *outLen) {
WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
return BUFFER_E;
}

e1 = Base64_Char2Val_CT(e1);
e2 = Base64_Char2Val_CT(e2);
e3 = (byte)((e3 == PAD) ? 0 : Base64_Char2Val_CT(e3));
Expand All @@ -336,6 +351,15 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
return ASN_INPUT_E;
}

/* Output space check needs to follow input character validation to
* assure ASN_INPUT_E is returned on truncated input with the
* terminating null included in the input buffer.
*/
if (i + 1 + !pad3 + !pad4 > *outLen) {
WOLFSSL_MSG("Bad Base64 Decode out buffer, too small");
return BUFFER_E;
}

b1 = (byte)((e1 << 2) | (e2 >> 4));
b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2));
b3 = (byte)(((e3 & 0x3) << 6) | e4);
Expand All @@ -349,6 +373,24 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen)
break;
}

/* If there is still input available, and it's not whitespace or nulls, then
* the input is invalid.
*/
while (inLen > 0) {
word32 cur_j = j;
if (in[j] == 0)
break;
if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) {
if (ret == WC_NO_ERR_TRACE(BUFFER_E)) {
/* Running out of buffer here is not an error */
break;
}
return ret;
}
if (j == cur_j)
return ASN_INPUT_E;
}

/* If the output buffer has a room for an extra byte, add a null terminator */
if (out && *outLen > i)
out[i]= '\0';
Expand Down
35 changes: 34 additions & 1 deletion wolfcrypt/test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -4130,12 +4130,18 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void)
static const byte goodChar[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/;";
"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 trailingLFTest[] = "YWFhYQ==\n\n";
static const byte trailingSpaceTest[] = "YWFhYQ== ";
static const byte trailingCodesTest1[] = "YWFhY";
static const byte trailingCodesTest2[] = "YWFhYW";
static const byte trailingCodesTest3[] = "YWFhYWF";
static const byte trailingJunkTest[] = "YWFhYQ==X";
static const byte byteTestOutput[] = "aaaa";
int i;
WOLFSSL_ENTER("base64_test");
Expand Down Expand Up @@ -4255,6 +4261,26 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void)
N_BYTE_TEST(Base64_Decode, 3, threeByteTest);
N_BYTE_TEST(Base64_Decode, 4, fourByteTest);

#define N_BYTE_TRAILING_TEST(f, n, t, e) do { \
outLen = (n); \
ret = (f)(t, sizeof(t), out, &outLen); \
if (ret != (e)) \
return WC_TEST_RET_ENC_EC(ret); \
else if (ret == 0) { \
if (outLen != (n)) \
return WC_TEST_RET_ENC_I(outLen); \
if (XMEMCMP(out, byteTestOutput, n) != 0) \
return WC_TEST_RET_ENC_NC; \
} \
} while (0)

N_BYTE_TRAILING_TEST(Base64_Decode, 4, trailingLFTest, 0);
N_BYTE_TRAILING_TEST(Base64_Decode, 4, trailingSpaceTest, 0);
N_BYTE_TRAILING_TEST(Base64_Decode, 4, trailingCodesTest1, WC_NO_ERR_TRACE(ASN_INPUT_E));
N_BYTE_TRAILING_TEST(Base64_Decode, 4, trailingCodesTest2, WC_NO_ERR_TRACE(ASN_INPUT_E));
N_BYTE_TRAILING_TEST(Base64_Decode, 4, trailingCodesTest3, WC_NO_ERR_TRACE(ASN_INPUT_E));
N_BYTE_TRAILING_TEST(Base64_Decode, 4, trailingJunkTest, WC_NO_ERR_TRACE(ASN_INPUT_E));

/* Same tests again, using Base64_Decode_nonCT() */

/* Good Base64 encodings. */
Expand Down Expand Up @@ -4335,6 +4361,13 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void)
N_BYTE_TEST(Base64_Decode_nonCT, 3, threeByteTest);
N_BYTE_TEST(Base64_Decode_nonCT, 4, fourByteTest);

N_BYTE_TRAILING_TEST(Base64_Decode_nonCT, 4, trailingLFTest, 0);
N_BYTE_TRAILING_TEST(Base64_Decode_nonCT, 4, trailingSpaceTest, 0);
N_BYTE_TRAILING_TEST(Base64_Decode_nonCT, 4, trailingCodesTest1, WC_NO_ERR_TRACE(ASN_INPUT_E));
N_BYTE_TRAILING_TEST(Base64_Decode_nonCT, 4, trailingCodesTest2, WC_NO_ERR_TRACE(ASN_INPUT_E));
N_BYTE_TRAILING_TEST(Base64_Decode_nonCT, 4, trailingCodesTest3, WC_NO_ERR_TRACE(ASN_INPUT_E));
N_BYTE_TRAILING_TEST(Base64_Decode_nonCT, 4, trailingJunkTest, WC_NO_ERR_TRACE(ASN_INPUT_E));

#ifdef WOLFSSL_BASE64_ENCODE
/* Decode and encode all symbols - non-alphanumeric. */
dataLen = sizeof(data);
Expand Down
Loading