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
13 changes: 10 additions & 3 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,14 @@ int DeriveHandshakeSecret(WOLFSSL* ssl)
mac2hash(ssl->specs.mac_algorithm));
PRIVATE_KEY_LOCK();
}
if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) {
/* Last use of the early secret and of the PSK it was extracted from -
* zeroize both. */
ForceZero(ssl->arrays->secret, SECRET_LEN);
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
ForceZero(ssl->arrays->psk_key, MAX_PSK_KEY_LEN);
#endif
}

#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("DeriveHandshakeSecret key", key, WC_MAX_DIGEST_SIZE);
Expand Down Expand Up @@ -13758,7 +13766,7 @@ static int SendTls13Finished(WOLFSSL* ssl)
ssl->kdfDeriveStep = TLS13_SEND_KDF_FIN_MASTER_SECRET;
}
/* Last use of preMasterSecret - zeroize as soon as possible. */
ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN);
#ifdef WOLFSSL_EARLY_DATA

#ifdef WOLFSSL_DTLS13
Expand Down Expand Up @@ -15546,8 +15554,7 @@ int DoTls13MsgDerives(WOLFSSL* ssl, byte type)
}
/* Zeroized only after the derive completed: a pend retry
* still reads preMasterSecret. */
ForceZero(ssl->arrays->preMasterSecret,
ssl->arrays->preMasterSz);
ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN);
ssl->kdfMsgStep = TLS13_MSG_KDF_FIN_MASTER_SECRET;
}
#ifdef WOLFSSL_EARLY_DATA
Expand Down
185 changes: 185 additions & 0 deletions tests/api/test_tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -11612,3 +11612,188 @@ int test_tls13_cryptocb_async(void)
#endif
return EXPECT_RESULT();
}

/* A psk_ke handshake, where preMasterSz is 0, must leave no handshake secret
* behind in preMasterSecret. */
int test_tls13_hs_secret_zeroized_psk_ke(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_CTX* ctx_c = NULL;
WOLFSSL_CTX* ctx_s = NULL;
WOLFSSL* ssl_c = NULL;
WOLFSSL* ssl_s = NULL;
struct test_memio_ctx test_ctx;

byte zeros[ENCRYPT_LEN];

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
XMEMSET(zeros, 0, sizeof(zeros));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);

wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_fnp_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_fnp_server_cb);

/* No key_share, so preMasterSz is zero when DeriveHandshakeSecret runs. */
ExpectIntEQ(wolfSSL_no_dhe_psk(ssl_c), 0);
ExpectIntEQ(wolfSSL_no_dhe_psk(ssl_s), 0);

wolfSSL_KeepArrays(ssl_c);
wolfSSL_KeepArrays(ssl_s);
XMEMSET(ssl_c->arrays->preMasterSecret, 0xAA, ENCRYPT_LEN);
XMEMSET(ssl_s->arrays->preMasterSecret, 0xAA, ENCRYPT_LEN);

ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectIntEQ(ssl_c->options.noPskDheKe, 1);
ExpectIntEQ(ssl_c->arrays->preMasterSz, 0);

ExpectIntEQ(XMEMCMP(ssl_c->arrays->preMasterSecret, zeros, ENCRYPT_LEN), 0);
ExpectIntEQ(XMEMCMP(ssl_s->arrays->preMasterSecret, zeros, ENCRYPT_LEN), 0);

wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}

/* An X25519 handshake under TLS_AES_256_GCM_SHA384, where preMasterSz is 32
* and the handshake secret 48 bytes, must leave none of it in preMasterSecret.
*/
int test_tls13_hs_secret_zeroized_sha384(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && defined(HAVE_CURVE25519) && \
defined(BUILD_TLS_AES_256_GCM_SHA384) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_CTX* ctx_c = NULL;
WOLFSSL_CTX* ctx_s = NULL;
WOLFSSL* ssl_c = NULL;
WOLFSSL* ssl_s = NULL;
struct test_memio_ctx test_ctx;
byte zeros[ENCRYPT_LEN];

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
XMEMSET(zeros, 0, sizeof(zeros));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);

wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);

ExpectIntEQ(wolfSSL_set_cipher_list(ssl_c, "TLS13-AES256-GCM-SHA384"),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_cipher_list(ssl_s, "TLS13-AES256-GCM-SHA384"),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, WOLFSSL_ECC_X25519),
WOLFSSL_SUCCESS);

wolfSSL_KeepArrays(ssl_c);
wolfSSL_KeepArrays(ssl_s);
XMEMSET(ssl_c->arrays->preMasterSecret, 0xAA, ENCRYPT_LEN);
XMEMSET(ssl_s->arrays->preMasterSecret, 0xAA, ENCRYPT_LEN);

ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectIntEQ(ssl_c->specs.hash_size, WC_SHA384_DIGEST_SIZE);

ExpectIntEQ(XMEMCMP(ssl_c->arrays->preMasterSecret, zeros, ENCRYPT_LEN), 0);
ExpectIntEQ(XMEMCMP(ssl_s->arrays->preMasterSecret, zeros, ENCRYPT_LEN), 0);

wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}

/* A TLS 1.3 handshake must leave no early secret behind in arrays->secret. */
int test_tls13_early_secret_zeroized(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_CTX* ctx_c = NULL;
WOLFSSL_CTX* ctx_s = NULL;
WOLFSSL* ssl_c = NULL;
WOLFSSL* ssl_s = NULL;
struct test_memio_ctx test_ctx;
byte zeros[SECRET_LEN];

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
XMEMSET(zeros, 0, sizeof(zeros));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);

wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);

wolfSSL_KeepArrays(ssl_c);
wolfSSL_KeepArrays(ssl_s);

ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);

ExpectIntEQ(XMEMCMP(ssl_c->arrays->secret, zeros, SECRET_LEN), 0);
Comment thread
gasbytes marked this conversation as resolved.
ExpectIntEQ(XMEMCMP(ssl_s->arrays->secret, zeros, SECRET_LEN), 0);

wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}

/* An external PSK handshake must leave no PSK behind in arrays->psk_key. */
int test_tls13_psk_key_zeroized(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) && \
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
defined(HAVE_SUPPORTED_CURVES) && \
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_CTX* ctx_c = NULL;
WOLFSSL_CTX* ctx_s = NULL;
WOLFSSL* ssl_c = NULL;
WOLFSSL* ssl_s = NULL;
struct test_memio_ctx test_ctx;
byte zeros[MAX_PSK_KEY_LEN];

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
XMEMSET(zeros, 0, sizeof(zeros));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0);

wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_verify(ssl_s, WOLFSSL_VERIFY_NONE, NULL);
wolfSSL_set_psk_client_callback(ssl_c, test_tls13_fnp_client_cb);
wolfSSL_set_psk_server_callback(ssl_s, test_tls13_fnp_server_cb);

wolfSSL_KeepArrays(ssl_c);
wolfSSL_KeepArrays(ssl_s);

ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectIntEQ(ssl_s->options.isPSK, 1);

ExpectIntEQ(XMEMCMP(ssl_c->arrays->psk_key, zeros, MAX_PSK_KEY_LEN), 0);
ExpectIntEQ(XMEMCMP(ssl_s->arrays->psk_key, zeros, MAX_PSK_KEY_LEN), 0);
ExpectIntEQ(XMEMCMP(ssl_c->arrays->secret, zeros, SECRET_LEN), 0);
ExpectIntEQ(XMEMCMP(ssl_s->arrays->secret, zeros, SECRET_LEN), 0);

wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}
10 changes: 9 additions & 1 deletion tests/api/test_tls13.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ int test_tls13_pha_status_request(void);
int test_tls13_x25519_keyshare_masks_reserved_bit(void);
int test_tls13_is_init_finished_want_write(void);
int test_tls13_cryptocb_async(void);
int test_tls13_hs_secret_zeroized_psk_ke(void);
int test_tls13_hs_secret_zeroized_sha384(void);
int test_tls13_early_secret_zeroized(void);
int test_tls13_psk_key_zeroized(void);

#define TEST_TLS13_DECLS \
TEST_DECL_GROUP("tls13", test_tls13_apis), \
Expand Down Expand Up @@ -243,6 +247,10 @@ int test_tls13_cryptocb_async(void);
TEST_DECL_GROUP("tls13", test_tls13_pha_status_request), \
TEST_DECL_GROUP("tls13", test_tls13_x25519_keyshare_masks_reserved_bit), \
TEST_DECL_GROUP("tls13", test_tls13_is_init_finished_want_write), \
TEST_DECL_GROUP("tls13", test_tls13_cryptocb_async)
TEST_DECL_GROUP("tls13", test_tls13_cryptocb_async), \
TEST_DECL_GROUP("tls13", test_tls13_hs_secret_zeroized_psk_ke), \
TEST_DECL_GROUP("tls13", test_tls13_hs_secret_zeroized_sha384), \
TEST_DECL_GROUP("tls13", test_tls13_early_secret_zeroized), \
TEST_DECL_GROUP("tls13", test_tls13_psk_key_zeroized)

#endif /* WOLFCRYPT_TEST_TLS13_H */
Loading