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
3 changes: 3 additions & 0 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -8669,6 +8669,9 @@ void FreeKeyExchange(WOLFSSL* ssl)
{
/* Cleanup signature buffer */
if (ssl->buffers.sig.buffer) {
/* May transiently hold the client's DH private exponent in the
* TLS 1.2 diffie_hellman_kea / dhe_psk_kea paths. */
ForceZero(ssl->buffers.sig.buffer, ssl->buffers.sig.length);
XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE);
ssl->buffers.sig.buffer = NULL;
ssl->buffers.sig.length = 0;
Expand Down
13 changes: 10 additions & 3 deletions src/pk.c
Original file line number Diff line number Diff line change
Expand Up @@ -4743,6 +4743,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
int ret = 1;
word32 pubSz = 0;
word32 privSz = 0;
word32 privAllocSz = 0;
int localRng = 0;
WC_RNG* rng = NULL;
WC_DECLARE_VAR(tmpRng, WC_RNG, 1, 0);
Expand Down Expand Up @@ -4792,9 +4793,12 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
else {
privSz = pubSz;
}
/* Allocate public and private key arrays. */
/* Allocate public and private key arrays. Preserve the allocation
* size because wc_DhGenerateKeyPair updates privSz in-place. */
privAllocSz = privSz;
pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
priv = (unsigned char*)XMALLOC(privAllocSz, NULL,
DYNAMIC_TYPE_PRIVATE_KEY);
if (pub == NULL || priv == NULL) {
WOLFSSL_ERROR_MSG("Unable to malloc memory");
ret = 0;
Expand Down Expand Up @@ -4846,7 +4850,10 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh)
}
/* Dispose of allocated data. */
XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
if (priv != NULL) {
ForceZero(priv, privAllocSz);
XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY);
}

return ret;
}
Expand Down
8 changes: 6 additions & 2 deletions src/sniffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2459,11 +2459,15 @@ static void FreeSetupKeysArgs(WOLFSSL* ssl, void* pArgs)
args->key->type = WC_PK_TYPE_NONE;
args->key->initPriv = 0; args->key->initPub = 0;

/* Scrub the raw DH private exponent (and any other key material
* embedded in the union) before release. wc_FreeDhKey above only
* clears the mp_int DhKey, not the separate privKey byte array.
* Use ForceZero (rather than XMEMSET) so the wipe cannot be
* elided by the optimizer. */
ForceZero(args->key, sizeof(*args->key));
#ifdef WOLFSSL_ASYNC_CRYPT
XFREE(args->key, NULL, DYNAMIC_TYPE_SNIFFER_KEY);
args->key = NULL;
#else
XMEMSET(args->key, 0, sizeof(args->key));
#endif
}

Expand Down
18 changes: 14 additions & 4 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -10069,11 +10069,21 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
#ifdef WOLFSSL_DTLS
ssl->options.dtlsStateful = 0;
#endif
#ifdef WOLFSSL_TLS13
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
ssl->options.noPskDheKe = 0;
#ifdef HAVE_SUPPORTED_CURVES
ssl->options.onlyPskDheKe = 0;
#endif
if (ssl->ctx != NULL) {
ssl->options.noPskDheKe = ssl->ctx->noPskDheKe;
#ifdef HAVE_SUPPORTED_CURVES
ssl->options.onlyPskDheKe = ssl->ctx->onlyPskDheKe;
#endif
}
else {
ssl->options.noPskDheKe = 0;
#ifdef HAVE_SUPPORTED_CURVES
ssl->options.onlyPskDheKe = 0;
#endif
}
#endif
#endif
#ifdef HAVE_SESSION_TICKET
#ifdef WOLFSSL_TLS13
Expand Down
12 changes: 10 additions & 2 deletions src/ssl_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2722,11 +2722,19 @@ void wolfSSL_DES_ncbc_encrypt(const unsigned char* input, unsigned char* output,
int enc)
{
unsigned char tmp[DES_IV_SIZE];
/* Calculate length to a multiple of block size. */
size_t offset = (size_t)length;
size_t offset;

WOLFSSL_ENTER("wolfSSL_DES_ncbc_encrypt");

/* Zero/negative length: no block to derive an IV from. The offset math
* below would underflow for length == 0, yielding a wild-pointer read. */
if (length <= 0) {
WOLFSSL_LEAVE("wolfSSL_DES_ncbc_encrypt", 0);
return;
}

/* Calculate length to a multiple of block size. */
offset = (size_t)length;
offset = (offset + DES_BLOCK_SIZE - 1) / DES_BLOCK_SIZE;
offset *= DES_BLOCK_SIZE;
offset -= DES_BLOCK_SIZE;
Expand Down
11 changes: 7 additions & 4 deletions src/ssl_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -5513,10 +5513,13 @@ int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
ret = 1;
}
#else
/* OpenSSL's implementation of this API does not require loading the
* system CA cert directory. Allow skipping this without erroring out.
*/
ret = 1;
/* No source available: SSL_CERT_DIR/SSL_CERT_FILE not set and
* WOLFSSL_SYS_CA_CERTS not compiled in. Returning success would be
* fail-open since no trust anchors were loaded. */
WOLFSSL_MSG("wolfSSL_CTX_set_default_verify_paths: no CA source "
"available (build without WOLFSSL_SYS_CA_CERTS and no "
"SSL_CERT_DIR/SSL_CERT_FILE env)");
ret = WOLFSSL_FAILURE;
#endif
}

Expand Down
4 changes: 4 additions & 0 deletions src/ssl_sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -1598,8 +1598,12 @@ int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session)
#if !defined(OPENSSL_EXTRA) || !defined(WOLFSSL_ERROR_CODE_OPENSSL)
return WOLFSSL_FAILURE; /* session timed out */
#else /* defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) */
/* Return success for OpenSSL compatibility but do not carry the
* expired session's version/cipher into ssl state, which would
* otherwise pin the ClientHello to stale values. */
WOLFSSL_MSG("Session is expired but return success for "
"OpenSSL compatibility");
return WOLFSSL_SUCCESS;
#endif
}
ssl->options.resuming = 1;
Expand Down
30 changes: 28 additions & 2 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -9063,6 +9063,9 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
if (WOLFSSL_NAMED_GROUP_IS_FFDHE(current->group)) {
#ifndef NO_DH
wc_FreeDhKey((DhKey*)current->key);
if (current->privKey != NULL && current->privKeyLen > 0) {
ForceZero(current->privKey, current->privKeyLen);
}
#endif
}
else if (current->group == WOLFSSL_ECC_X25519) {
Expand Down Expand Up @@ -17208,8 +17211,8 @@ static word16 TLSX_GetMinSize_Server(const word16 *type)


/** Parses a buffer of TLS extensions. */
int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
Suites *suites)
WOLFSSL_TEST_VIS int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length,
byte msgType, Suites *suites)
{
int ret = 0;
word16 offset = 0;
Expand Down Expand Up @@ -17831,6 +17834,20 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
#ifdef WOLFSSL_SRTP
case TLSX_USE_SRTP:
WOLFSSL_MSG("Use SRTP extension received");

#if defined(WOLFSSL_TLS13)
if (IsAtLeastTLSv1_3(ssl->version)) {
if (msgType != client_hello &&
msgType != encrypted_extensions)
return EXT_NOT_ALLOWED;
}
else
#endif
{
if (msgType != client_hello &&
msgType != server_hello)
return EXT_NOT_ALLOWED;
}
ret = SRTP_PARSE(ssl, input + offset, size, isRequest);
break;
#endif
Expand Down Expand Up @@ -17925,6 +17942,15 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
case TLSX_ECH:
WOLFSSL_MSG("ECH extension received");
if (!IsAtLeastTLSv1_3(ssl->version))
break;

if (msgType != client_hello &&
msgType != encrypted_extensions &&
msgType != hello_retry_request) {
return EXT_NOT_ALLOWED;
}

ret = ECH_PARSE(ssl, input + offset, size, msgType);
break;
case TLSXT_ECH_OUTER_EXTENSIONS:
Expand Down
2 changes: 2 additions & 0 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -39694,6 +39694,8 @@ TEST_CASE testCases[] = {
TEST_DECL(test_certificate_authorities_client_hello),
TEST_DECL(test_TLSX_TCA_Find),
TEST_DECL(test_TLSX_SNI_GetSize_overflow),
TEST_DECL(test_TLSX_ECH_msg_type_validation),
TEST_DECL(test_TLSX_SRTP_msg_type_validation),
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
TEST_DECL(test_wolfSSL_clear_secure_renegotiation),
TEST_DECL(test_wolfSSL_SCR_Reconnect),
Expand Down
28 changes: 28 additions & 0 deletions tests/api/test_ossl_cipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,34 @@ int test_wolfSSL_DES_ncbc(void)
return EXPECT_RESULT();
}

int test_wolfSSL_DES_ncbc_zero_length(void)
{
EXPECT_DECLS;
#if defined(OPENSSL_EXTRA) && !defined(NO_DES3)
const_DES_cblock myDes;
DES_cblock iv;
DES_cblock ivSaved;
DES_key_schedule key = {0};
unsigned char msg[DES_BLOCK_SIZE] = {0};
unsigned char out[DES_BLOCK_SIZE] = {0};

DES_set_key(&key, &myDes);

/* length == 0 must no-op: the offset math would otherwise underflow
* size_t and read from a wild pointer. */
XMEMSET((byte*)&iv, 0xAB, DES_BLOCK_SIZE);
XMEMCPY(&ivSaved, &iv, DES_BLOCK_SIZE);
DES_ncbc_encrypt(msg, out, 0, &myDes, &iv, DES_ENCRYPT);
ExpectIntEQ(XMEMCMP(&iv, &ivSaved, DES_BLOCK_SIZE), 0);

XMEMSET((byte*)&iv, 0xAB, DES_BLOCK_SIZE);
XMEMCPY(&ivSaved, &iv, DES_BLOCK_SIZE);
DES_ncbc_encrypt(msg, out, 0, &myDes, &iv, DES_DECRYPT);
ExpectIntEQ(XMEMCMP(&iv, &ivSaved, DES_BLOCK_SIZE), 0);
#endif
return EXPECT_RESULT();
}

int test_wolfSSL_DES_ecb_encrypt(void)
{
EXPECT_DECLS;
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_ossl_cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

int test_wolfSSL_DES(void);
int test_wolfSSL_DES_ncbc(void);
int test_wolfSSL_DES_ncbc_zero_length(void);
int test_wolfSSL_DES_ecb_encrypt(void);
int test_wolfSSL_DES_ede3_cbc_encrypt(void);
int test_wolfSSL_AES_encrypt(void);
Expand All @@ -38,6 +39,7 @@ int test_wolfSSL_RC4(void);
#define TEST_OSSL_CIPHER_DECLS \
TEST_DECL_GROUP("ossl_cipher", test_wolfSSL_DES), \
TEST_DECL_GROUP("ossl_cipher", test_wolfSSL_DES_ncbc), \
TEST_DECL_GROUP("ossl_cipher", test_wolfSSL_DES_ncbc_zero_length), \
TEST_DECL_GROUP("ossl_cipher", test_wolfSSL_DES_ecb_encrypt), \
TEST_DECL_GROUP("ossl_cipher", test_wolfSSL_DES_ede3_cbc_encrypt), \
TEST_DECL_GROUP("ossl_cipher", test_wolfSSL_AES_encrypt), \
Expand Down
26 changes: 26 additions & 0 deletions tests/api/test_tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -5847,3 +5847,29 @@ int test_tls13_ticket_peer_cert_reverify(void)
#endif
return EXPECT_RESULT();
}

int test_tls13_clear_preserves_psk_dhe(void)
{
EXPECT_DECLS;
#if (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) && \
defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) && \
(defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \
!defined(NO_WOLFSSL_CLIENT)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;

ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
ExpectIntEQ(wolfSSL_CTX_no_dhe_psk(ctx), 0);
ExpectNotNull(ssl = wolfSSL_new(ctx));
ExpectIntEQ(ssl->options.noPskDheKe, 1);

/* SSL reuse must preserve the CTX-level noPskDheKe; resetting to 0
* would silently re-enable psk_dhe_ke for the next handshake. */
ExpectIntEQ(wolfSSL_clear(ssl), WOLFSSL_SUCCESS);
ExpectIntEQ(ssl->options.noPskDheKe, 1);

wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
4 changes: 3 additions & 1 deletion tests/api/test_tls13.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ int test_tls13_cert_with_extern_psk_rejects_resumption(void);
int test_tls13_cert_with_extern_psk_sh_missing_key_share(void);
int test_tls13_cert_with_extern_psk_sh_confirms_resumption(void);
int test_tls13_ticket_peer_cert_reverify(void);
int test_tls13_clear_preserves_psk_dhe(void);

#define TEST_TLS13_DECLS \
TEST_DECL_GROUP("tls13", test_tls13_apis), \
Expand Down Expand Up @@ -111,6 +112,7 @@ int test_tls13_ticket_peer_cert_reverify(void);
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_rejects_resumption), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_sh_missing_key_share), \
TEST_DECL_GROUP("tls13", test_tls13_cert_with_extern_psk_sh_confirms_resumption), \
TEST_DECL_GROUP("tls13", test_tls13_ticket_peer_cert_reverify)
TEST_DECL_GROUP("tls13", test_tls13_ticket_peer_cert_reverify), \
TEST_DECL_GROUP("tls13", test_tls13_clear_preserves_psk_dhe)

#endif /* WOLFCRYPT_TEST_TLS13_H */
51 changes: 51 additions & 0 deletions tests/api/test_tls_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,3 +982,54 @@ int test_TLSX_SNI_GetSize_overflow(void)
#endif
return EXPECT_RESULT();
}

/* ECH is only valid in ClientHello, EncryptedExtensions, or
* HelloRetryRequest per RFC 9460. Feeding it in a Finished message must
* be rejected with EXT_NOT_ALLOWED rather than being silently accepted. */
int test_TLSX_ECH_msg_type_validation(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
/* type = TLSX_ECH (0xfe0d), size = 0x0000 */
const byte extBytes[] = { 0xfe, 0x0d, 0x00, 0x00 };

ExpectNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
ExpectNotNull(ssl = wolfSSL_new(ctx));

ExpectIntEQ(TLSX_Parse(ssl, extBytes, (word16)sizeof(extBytes),
finished, NULL),
WC_NO_ERR_TRACE(EXT_NOT_ALLOWED));

wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}

/* use_srtp is only valid in ClientHello/ServerHello (pre-TLS 1.3) or
* ClientHello/EncryptedExtensions (TLS 1.3) per RFC 5764. Feeding it in a
* Finished message must be rejected with EXT_NOT_ALLOWED. */
int test_TLSX_SRTP_msg_type_validation(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_SRTP) && !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS)
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
/* type = TLSX_USE_SRTP (0x000e), size = 0x0000 */
const byte extBytes[] = { 0x00, 0x0e, 0x00, 0x00 };

ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()));
ExpectNotNull(ssl = wolfSSL_new(ctx));

ExpectIntEQ(TLSX_Parse(ssl, extBytes, (word16)sizeof(extBytes),
finished, NULL),
WC_NO_ERR_TRACE(EXT_NOT_ALLOWED));

wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
#endif
return EXPECT_RESULT();
}
2 changes: 2 additions & 0 deletions tests/api/test_tls_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,7 @@ int test_certificate_authorities_certificate_request(void);
int test_certificate_authorities_client_hello(void);
int test_TLSX_TCA_Find(void);
int test_TLSX_SNI_GetSize_overflow(void);
int test_TLSX_ECH_msg_type_validation(void);
int test_TLSX_SRTP_msg_type_validation(void);

#endif /* TESTS_API_TEST_TLS_EMS_H */
5 changes: 4 additions & 1 deletion wolfssl/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3231,7 +3231,10 @@ WOLFSSL_LOCAL int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input,
WOLFSSL_LOCAL int TLSX_SupportedVersions_Parse(const WOLFSSL* ssl,
const byte* input, word16 length, byte msgType, ProtocolVersion* pv,
Options* opts, TLSX** exts);
WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length,
#ifdef WOLFSSL_API_PREFIX_MAP
#define TLSX_Parse wolfSSL_TLSX_Parse
#endif
WOLFSSL_TEST_VIS int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length,
byte msgType, Suites *suites);
WOLFSSL_LOCAL int TLSX_Push(TLSX** list, TLSX_Type type,
const void* data, void* heap);
Expand Down
Loading