Skip to content
Merged
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
42 changes: 42 additions & 0 deletions src/ssl_sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,38 @@ int wolfSSL_memsave_session_cache(void* mem, int sz)
}


#if !defined(SESSION_CACHE_DYNAMIC_MEM) && \
(defined(HAVE_SESSION_TICKET) || \
(defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)))
static void SessionSanityPointerSet(SessionRow* row)
{
int j;

/* Reset pointers to safe values after raw copy */
for (j = 0; j < SESSIONS_PER_ROW; j++) {
WOLFSSL_SESSION* s = &row->Sessions[j];
#ifdef HAVE_SESSION_TICKET
s->ticket = s->staticTicket;
s->ticketLenAlloc = 0;
if (s->ticketLen > SESSION_TICKET_LEN) {
s->ticketLen = SESSION_TICKET_LEN;
}
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \
defined(WOLFSSL_TICKET_NONCE_MALLOC) && \
(!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)))
s->ticketNonce.data = s->ticketNonce.dataStatic;
if (s->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ) {
s->ticketNonce.len = MAX_TICKET_NONCE_STATIC_SZ;
}
#endif
#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)
s->peer = NULL;
#endif
}
}
#endif

/* Restore the persistent session cache from memory */
int wolfSSL_memrestore_session_cache(const void* mem, int sz)
{
Expand Down Expand Up @@ -522,6 +554,11 @@ int wolfSSL_memrestore_session_cache(const void* mem, int sz)
#endif

XMEMCPY(&SessionCache[i], row++, SIZEOF_SESSION_ROW);
#if !defined(SESSION_CACHE_DYNAMIC_MEM) && \
(defined(HAVE_SESSION_TICKET) || \
(defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)))
SessionSanityPointerSet(&SessionCache[i]);
#endif
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
SESSION_ROW_UNLOCK(&SessionCache[i]);
#endif
Expand Down Expand Up @@ -681,6 +718,11 @@ int wolfSSL_restore_session_cache(const char *fname)
#endif

ret = (int)XFREAD(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file);
#if !defined(SESSION_CACHE_DYNAMIC_MEM) && \
(defined(HAVE_SESSION_TICKET) || \
(defined(SESSION_CERTS) && defined(OPENSSL_EXTRA)))
SessionSanityPointerSet(&SessionCache[i]);
#endif
#ifdef ENABLE_SESSION_CACHE_ROW_LOCK
SESSION_ROW_UNLOCK(&SessionCache[i]);
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -9950,6 +9950,10 @@ static int TLSX_KeyShare_ProcessPqcClient_ex(WOLFSSL* ssl,
}
#endif

if (ret == 0 && keyShareEntry->keLen < ctSz) {
WOLFSSL_MSG("PQC key share data too short for ciphertext.");
ret = BUFFER_E;
}
if (ret == 0) {
ret = wc_KyberKey_Decapsulate(kem, ssOutput,
keyShareEntry->ke, ctSz);
Expand Down
184 changes: 184 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,19 @@
#include <sys/uio.h>
#endif

#ifdef HAVE_DILITHIUM
#include <wolfssl/wolfcrypt/dilithium.h>
#endif
#if defined(WOLFSSL_HAVE_MLKEM)
#include <wolfssl/wolfcrypt/mlkem.h>
#endif
#if defined(HAVE_PKCS7)
#include <wolfssl/wolfcrypt/pkcs7.h>
#endif
#if !defined(NO_BIG_INT)
#include <wolfssl/wolfcrypt/sp_int.h>
#endif

/* include misc.c here regardless of NO_INLINE, because misc.c implementations
* have default (hidden) visibility, and in the absence of visibility, it's
* benign to mask out the library implementation.
Expand Down Expand Up @@ -34758,6 +34771,47 @@ static int test_DhAgree_rejects_p_minus_1(void)
return EXPECT_RESULT();
}


/* ML-DSA HashML-DSA verify must reject hashLen > WC_MAX_DIGEST_SIZE */
static int test_mldsa_verify_hash(void)
{
EXPECT_DECLS;
#if defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \
!defined(WOLFSSL_DILITHIUM_NO_VERIFY)
dilithium_key key;
WC_RNG rng;
int res = 0;
byte sig[4000];
byte hash[4096]; /* larger than WC_MAX_DIGEST_SIZE */

XMEMSET(&key, 0, sizeof(key));
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(sig, 0x41, sizeof(sig));
XMEMSET(hash, 'A', sizeof(hash));

ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_dilithium_init(&key), 0);
#ifndef WOLFSSL_NO_ML_DSA_65
ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_65), 0);
#elif !defined(WOLFSSL_NO_ML_DSA_44)
ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_44), 0);
#else
ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_87), 0);
#endif
ExpectIntEQ(wc_dilithium_make_key(&key, &rng), 0);

/* hashLen=4096 must be rejected, not overflow the stack */
ExpectIntEQ(wc_dilithium_verify_ctx_hash(sig, sizeof(sig), NULL, 0,
WC_HASH_TYPE_SHA256, hash, sizeof(hash), &res, &key),
WC_NO_ERR_TRACE(BAD_LENGTH_E));

wc_dilithium_free(&key);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
#endif
return EXPECT_RESULT();
}

/* Test: Ed448 must reject identity public key (0,1) */
static int test_ed448_rejects_identity_key(void)
{
Expand Down Expand Up @@ -34936,6 +34990,133 @@ static int test_pkcs7_ori_oversized_oid(void)
return EXPECT_RESULT();
}

/* Dilithium verify_ctx_msg must reject absurdly large msgLen */
static int test_dilithium_hash(void)
{
EXPECT_DECLS;
#if defined(HAVE_DILITHIUM) && defined(WOLFSSL_WC_DILITHIUM) && \
!defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \
!defined(WOLFSSL_DILITHIUM_NO_VERIFY)
dilithium_key key;
WC_RNG rng;
int res = 0;
byte sig[4000];
byte msg[64];

XMEMSET(&key, 0, sizeof(key));
XMEMSET(&rng, 0, sizeof(rng));
XMEMSET(sig, 0, sizeof(sig));
XMEMSET(msg, 'A', sizeof(msg));

ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_dilithium_init(&key), 0);
#ifndef WOLFSSL_NO_ML_DSA_65
ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_65), 0);
#elif !defined(WOLFSSL_NO_ML_DSA_44)
ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_44), 0);
#else
ExpectIntEQ(wc_dilithium_set_level(&key, WC_ML_DSA_87), 0);
#endif
ExpectIntEQ(wc_dilithium_make_key(&key, &rng), 0);

ExpectIntEQ(wc_dilithium_verify_ctx_msg(sig, sizeof(sig), NULL, 0,
msg, 0xFFFFFFC0, &res, &key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));

wc_dilithium_free(&key);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
#endif
return EXPECT_RESULT();
}

/* PKCS7 CBC must validate all padding bytes */
static int test_pkcs7_padding(void)
{
EXPECT_DECLS;
#if defined(HAVE_PKCS7) && !defined(NO_AES) && defined(HAVE_AES_CBC) && \
defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA)
PKCS7 pkcs7;
byte key[32];
byte plaintext[27]; /* 27 bytes -> padded to 32 -> padding = 05 05 05 05 05 */
byte encoded[4096];
byte output[256];
byte modified[4096];
int encodedSz = 0;
int outSz;
int ctOff = -1;
int ctLen = 0;
int i;

XMEMSET(key, 0xAA, sizeof(key));
XMEMSET(plaintext, 'X', sizeof(plaintext));

/* Encode EncryptedData */
XMEMSET(&pkcs7, 0, sizeof(pkcs7));
ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, 0), 0);
pkcs7.content = plaintext;
pkcs7.contentSz = sizeof(plaintext);
pkcs7.contentOID = DATA;
pkcs7.encryptOID = AES256CBCb;
pkcs7.encryptionKey = key;
pkcs7.encryptionKeySz = sizeof(key);

ExpectIntGT(encodedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encoded,
sizeof(encoded)), 0);

/* Verify normal decrypt works */
ExpectIntEQ(outSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, encoded,
(word32)encodedSz, output, sizeof(output)), (int)sizeof(plaintext));
wc_PKCS7_Free(&pkcs7);

/* Find ciphertext block in encoded DER */
if (EXPECT_SUCCESS()) {
for (i = encodedSz - 10; i > 10; i--) {
if (encoded[i] == 0x04 || encoded[i] == 0x80) {
int len, lbytes;

if (encoded[i+1] < 0x80) {
len = encoded[i+1]; lbytes = 1;
}
else if (encoded[i+1] == 0x81) {
len = encoded[i+2]; lbytes = 2;
}
else {
continue;
}
if (len > 0 && len % 16 == 0 &&
i + 1 + lbytes + len <= encodedSz) {
ctOff = i + 1 + lbytes;
ctLen = len;
break;
}
}
}
}
ExpectIntGT(ctOff, 0);
ExpectIntGE(ctLen, 32);

/* Corrupt an interior padding byte via CBC bit-flip */
if (EXPECT_SUCCESS()) {
XMEMCPY(modified, encoded, (size_t)encodedSz);
/* Flip byte in penultimate block to corrupt interior padding */
modified[ctOff + ctLen - 32 + 11] ^= 0x42;

/* Decrypt modified ciphertext - must fail, not succeed */
XMEMSET(&pkcs7, 0, sizeof(pkcs7));
ExpectIntEQ(wc_PKCS7_Init(&pkcs7, NULL, 0), 0);
pkcs7.encryptionKey = key;
pkcs7.encryptionKeySz = sizeof(key);

outSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, modified,
(word32)encodedSz, output, sizeof(output));
/* Must return an error - if it returns plaintext size, padding
* oracle vulnerability exists */
ExpectIntLT(outSz, 0);
wc_PKCS7_Free(&pkcs7);
}
#endif
return EXPECT_RESULT();
}

TEST_CASE testCases[] = {
TEST_DECL(test_fileAccess),

Expand Down Expand Up @@ -35754,11 +35935,14 @@ TEST_CASE testCases[] = {
TEST_DECL(test_ed448_rejects_identity_key),
TEST_DECL(test_pkcs7_decode_encrypted_outputsz),
TEST_DECL(test_pkcs7_ori_oversized_oid),
TEST_DECL(test_pkcs7_padding),

#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_CHAIN_INPUT)
TEST_DECL(test_sniffer_chain_input_overflow),
#endif

TEST_DECL(test_mldsa_verify_hash),
TEST_DECL(test_dilithium_hash),
/* This test needs to stay at the end to clean up any caches allocated. */
TEST_DECL(test_wolfSSL_Cleanup)
};
Expand Down
4 changes: 3 additions & 1 deletion wolfcrypt/src/curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -1113,10 +1113,12 @@ curve25519_key* wc_curve25519_new(void* heap, int devId, int *result_code)
}

int wc_curve25519_delete(curve25519_key* key, curve25519_key** key_p) {
void* heap;
if (key == NULL)
return BAD_FUNC_ARG;
heap = key->heap;
wc_curve25519_free(key);
XFREE(key, key->heap, DYNAMIC_TYPE_CURVE25519);
XFREE(key, heap, DYNAMIC_TYPE_CURVE25519);
if (key_p != NULL)
*key_p = NULL;
return 0;
Expand Down
11 changes: 10 additions & 1 deletion wolfcrypt/src/dilithium.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ static int dilithium_hash256(wc_Shake* shake256, const byte* data1,
word64* state = shake256->s;
word8 *state8 = (word8*)state;

if (data2Len > (UINT32_MAX - data1Len)) {
return BAD_FUNC_ARG;
}
if (data1Len + data2Len >= WC_SHA3_256_COUNT * 8) {
XMEMCPY(state8, data1, data1Len);
XMEMCPY(state8 + data1Len, data2, WC_SHA3_256_COUNT * 8 - data1Len);
Expand Down Expand Up @@ -10554,6 +10557,10 @@ int wc_dilithium_verify_ctx_msg(const byte* sig, word32 sigLen, const byte* ctx,
if ((ret == 0) && (ctx == NULL) && (ctxLen > 0)) {
ret = BAD_FUNC_ARG;
}
/* Reject msgLen that would cause integer overflow in hash computations */
if ((ret == 0) && (msgLen > UINT32_MAX / 2)) {
ret = BAD_FUNC_ARG;
}

#ifdef WOLF_CRYPTO_CB
if (ret == 0) {
Expand Down Expand Up @@ -10737,10 +10744,12 @@ dilithium_key* wc_dilithium_new(void* heap, int devId)

int wc_dilithium_delete(dilithium_key* key, dilithium_key** key_p)
{
void* heap;
if (key == NULL)
return BAD_FUNC_ARG;
heap = key->heap;
wc_dilithium_free(key);
XFREE(key, key->heap, DYNAMIC_TYPE_DILITHIUM);
XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM);
if (key_p != NULL)
*key_p = NULL;

Expand Down
4 changes: 3 additions & 1 deletion wolfcrypt/src/ed25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -1047,10 +1047,12 @@ ed25519_key* wc_ed25519_new(void* heap, int devId, int *result_code)
}

int wc_ed25519_delete(ed25519_key* key, ed25519_key** key_p) {
void* heap;
if (key == NULL)
return BAD_FUNC_ARG;
heap = key->heap;
wc_ed25519_free(key);
XFREE(key, key->heap, DYNAMIC_TYPE_ED25519);
XFREE(key, heap, DYNAMIC_TYPE_ED25519);
if (key_p != NULL)
*key_p = NULL;
return 0;
Expand Down
9 changes: 5 additions & 4 deletions wolfcrypt/src/evp.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ int wolfSSL_EVP_PKEY_is_a(const WOLFSSL_EVP_PKEY *pkey, const char *name) {

#define WOLFSSL_EVP_PKEY_PRINT_LINE_WIDTH_MAX 80
#define WOLFSSL_EVP_PKEY_PRINT_DIGITS_PER_LINE 15
#define WOLFSSL_EVP_EXPONENT_PRINT_MAX 24

static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher);

Expand Down Expand Up @@ -11877,7 +11878,7 @@ static int PrintHexWithColon(WOLFSSL_BIO* out, const byte* input,
static int PrintPubKeyRSA(WOLFSSL_BIO* out, const byte* pkey, int pkeySz,
int indent, int bitlen, WOLFSSL_ASN1_PCTX* pctx)
{
byte buff[8] = { 0 };
byte buff[WOLFSSL_EVP_EXPONENT_PRINT_MAX] = { 0 };
int res = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
word32 inOutIdx = 0;
word32 nSz; /* size of modulus */
Expand Down Expand Up @@ -12021,7 +12022,7 @@ static int PrintPubKeyEC(WOLFSSL_BIO* out, const byte* pkey, int pkeySz,
{
byte* pub = NULL;
word32 pubSz = 0;
byte buff[8] = { 0 };
byte buff[WOLFSSL_EVP_EXPONENT_PRINT_MAX] = { 0 };
int res = WOLFSSL_SUCCESS;
word32 inOutIdx = 0;
int curveId = 0;
Expand Down Expand Up @@ -12210,7 +12211,7 @@ static int PrintPubKeyDSA(WOLFSSL_BIO* out, const byte* pkey, int pkeySz,
int indent, int bitlen, WOLFSSL_ASN1_PCTX* pctx)
{

byte buff[8] = { 0 };
byte buff[WOLFSSL_EVP_EXPONENT_PRINT_MAX] = { 0 };
int length;
int res = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
word32 inOutIdx = 0;
Expand Down Expand Up @@ -12417,7 +12418,7 @@ static int PrintPubKeyDH(WOLFSSL_BIO* out, const byte* pkey, int pkeySz,
int indent, int bitlen, WOLFSSL_ASN1_PCTX* pctx)
{

byte buff[8] = { 0 };
byte buff[WOLFSSL_EVP_EXPONENT_PRINT_MAX] = { 0 };
int res = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
word32 length;
word32 inOutIdx;
Expand Down
Loading
Loading