TLS ECH keylogging

This commit is contained in:
sebastian-carpenter
2026-04-17 15:04:13 -06:00
parent 2dd7947d27
commit 406365ec1c
8 changed files with 372 additions and 54 deletions
+18
View File
@@ -535,6 +535,12 @@ void wolfssl_priv_der_unblind_free(DerBuffer* key)
#define SSC_TLS13_EES "EARLY_EXPORTER_SECRET"
/* Label string for exporter secret. */
#define SSC_TLS13_ES "EXPORTER_SECRET"
#ifdef HAVE_ECH
/* Label string for ECH KEM shared secret. */
#define SSC_TLS13_ECH_S "ECH_SECRET"
/* Label string for ECHConfig used to construct ECH. */
#define SSC_TLS13_ECH_C "ECH_CONFIG"
#endif
/*
* This function builds up string for key-logging then call user's
@@ -594,6 +600,18 @@ void wolfssl_priv_der_unblind_free(DerBuffer* key)
label = SSC_TLS13_ES;
break;
#ifdef HAVE_ECH
case ECH_SECRET:
labelSz = sizeof(SSC_TLS13_ECH_S);
label = SSC_TLS13_ECH_S;
break;
case ECH_CONFIG:
labelSz = sizeof(SSC_TLS13_ECH_C);
label = SSC_TLS13_ECH_C;
break;
#endif
default:
return BAD_FUNC_ARG;
}
+133 -43
View File
@@ -13952,6 +13952,42 @@ static int TLSX_ECH_GetSize(WOLFSSL_ECH* ech, byte msgType)
return (int)size;
}
#ifdef HAVE_SECRET_CALLBACK
/* log ECH_SECRET and ECH_CONFIG
* returns 0 on success, TLS13_SECRET_CB_E otherwise */
static int EchWriteKeyLog(WOLFSSL* ssl, const byte* secret, word32 secretSz,
const byte* config, word32 configSz)
{
int ret = 0;
if (ssl->tls13SecretCb != NULL) {
ret = ssl->tls13SecretCb(ssl, ECH_SECRET, secret, (int)secretSz,
ssl->tls13SecretCtx);
if (ret == 0) {
ret = ssl->tls13SecretCb(ssl, ECH_CONFIG, config, (int)configSz,
ssl->tls13SecretCtx);
}
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(TLS13_SECRET_CB_E);
ret = TLS13_SECRET_CB_E;
}
}
#ifdef OPENSSL_EXTRA
if (ret == 0 && ssl->tls13KeyLogCb != NULL) {
ret = ssl->tls13KeyLogCb(ssl, ECH_SECRET, secret, (int)secretSz, NULL);
if (ret == 0) {
ret = ssl->tls13KeyLogCb(ssl, ECH_CONFIG, config, (int)configSz,
NULL);
}
if (ret != 0) {
WOLFSSL_ERROR_VERBOSE(TLS13_SECRET_CB_E);
ret = TLS13_SECRET_CB_E;
}
}
#endif /* OPENSSL_EXTRA */
return ret;
}
#endif /* HAVE_SECRET_CALLBACK */
/* rough check that inner hello fields do not exceed length of decrypted
* information. Additionally, this function will check that all padding bytes
* are zero and decrease the innerHelloLen accordingly if so.
@@ -14361,8 +14397,8 @@ static int TLSX_ECH_ExpandOuterExtensions(WOLFSSL* ssl, WOLFSSL_ECH* ech,
/* return status after attempting to open the hpke encrypted ech extension, if
* successful the inner client hello will be stored in
* ech->innerClientHelloLen */
static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
byte* aad, word32 aadLen, void* heap)
static int TLSX_ExtractEch(WOLFSSL* ssl, WOLFSSL_ECH* ech,
WOLFSSL_EchConfig* echConfig, byte* aad, word32 aadLen)
{
int ret = 0;
int i;
@@ -14370,7 +14406,7 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
word32 rawConfigLen = 0;
byte* info = NULL;
word32 infoLen = 0;
if (ech == NULL || echConfig == NULL || aad == NULL)
if (ssl == NULL || ech == NULL || echConfig == NULL || aad == NULL)
return BAD_FUNC_ARG;
/* verify the kem and key len */
if (wc_HpkeKemGetEncLen(echConfig->kemId) != ech->encLen)
@@ -14388,13 +14424,14 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
/* check if hpke already exists, may if HelloRetryRequest */
if (ech->hpke == NULL) {
allocatedHpke = 1;
ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER);
ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
if (ech->hpke == NULL)
ret = MEMORY_E;
/* init the hpke struct */
if (ret == 0) {
ret = wc_HpkeInit(ech->hpke, echConfig->kemId,
ech->cipherSuite.kdfId, ech->cipherSuite.aeadId, heap);
ech->cipherSuite.kdfId, ech->cipherSuite.aeadId, ssl->heap);
}
if (ret == 0) {
/* allocate hpkeContext */
@@ -14412,7 +14449,7 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
/* create info */
if (ret == 0) {
infoLen = TLS_INFO_CONST_STRING_SZ + 1 + rawConfigLen;
info = (byte*)XMALLOC(infoLen, heap, DYNAMIC_TYPE_TMP_BUFFER);
info = (byte*)XMALLOC(infoLen, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (info == NULL)
ret = MEMORY_E;
@@ -14423,6 +14460,16 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
TLS_INFO_CONST_STRING_SZ + 1, &rawConfigLen);
}
}
#ifdef HAVE_SECRET_CALLBACK
/* allocate secret buffer for wc_HpkeInitOpenContext to copy into */
if (ret == 0 && (ssl->tls13SecretCb != NULL
#ifdef OPENSSL_EXTRA
|| ssl->tls13KeyLogCb != NULL
#endif
)) {
ret = wc_HpkeInitEchSecret(ech->hpke);
}
#endif /* HAVE_SECRET_CALLBACK */
/* init the context for opening */
if (ret == 0) {
ret = wc_HpkeInitOpenContext(ech->hpke, ech->hpkeContext,
@@ -14436,17 +14483,29 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig,
ech->outerClientPayload, ech->innerClientHelloLen,
ech->innerClientHello + HANDSHAKE_HEADER_SZ);
}
#ifdef HAVE_SECRET_CALLBACK
if (ret == 0 && ech->hpke->echSecret != NULL) {
ret = EchWriteKeyLog(ssl, ech->hpke->echSecret, ech->hpke->Nsecret,
info + TLS_INFO_CONST_STRING_SZ + 1, rawConfigLen);
}
wc_HpkeFreeEchSecret(ech->hpke);
#endif /* HAVE_SECRET_CALLBACK */
/* only free hpke/hpkeContext if allocated in this call; otherwise preserve
* them for clientHello2 */
if (ret != 0 && allocatedHpke) {
XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(ech->hpke, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
ech->hpke = NULL;
XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
ech->hpkeContext = NULL;
if (ech->hpkeContext != NULL) {
ForceZero(ech->hpkeContext, sizeof(HpkeBaseContext));
XFREE(ech->hpkeContext, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
ech->hpkeContext = NULL;
}
}
if (info != NULL)
XFREE(info, heap, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(info, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
@@ -14650,9 +14709,9 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
echConfig = ssl->ctx->echConfigs;
while (echConfig != NULL) {
if (echConfig->configId == ech->configId) {
ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
ssl->heap);
if (ret == 0)
ret = TLSX_ExtractEch(ssl, ech, echConfig, aadCopy,
ech->aadLen);
if (ret == 0 || ret == WC_NO_ERR_TRACE(TLS13_SECRET_CB_E))
break;
}
echConfig = echConfig->next;
@@ -14662,42 +14721,46 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
echConfig = ssl->ctx->echConfigs;
while (echConfig != NULL) {
if (echConfig->configId != ech->configId) {
ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
ssl->heap);
if (ret == 0)
ret = TLSX_ExtractEch(ssl, ech, echConfig, aadCopy,
ech->aadLen);
if (ret == 0 || ret == WC_NO_ERR_TRACE(TLS13_SECRET_CB_E))
break;
}
echConfig = echConfig->next;
}
}
/* if we failed to extract/expand */
if (ret != 0 || echConfig == NULL) {
WOLFSSL_MSG("ECH rejected");
/* TLS13_SECRET_CB_E isn't correlated with ECH acceptance so skip both
* paths */
if (ret != WC_NO_ERR_TRACE(TLS13_SECRET_CB_E)) {
/* if we failed to extract/expand */
if (ret != 0 || echConfig == NULL) {
WOLFSSL_MSG("ECH rejected");
if (ssl->options.echAccepted == 1) {
/* on SH2 this is fatal */
SendAlert(ssl, alert_fatal, decrypt_error);
WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR);
ret = DECRYPT_ERROR;
if (ssl->options.echAccepted == 0) {
/* on SH1 prepare to write retry configs */
XFREE(ech->innerClientHello, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
ech->innerClientHello = NULL;
ech->state = ECH_WRITE_RETRY_CONFIGS;
ret = 0;
}
else {
/* on SH2 failure to decrypt is fatal */
SendAlert(ssl, alert_fatal, decrypt_error);
WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR);
ret = DECRYPT_ERROR;
}
}
else {
/* on SH1 prepare to write retry configs */
XFREE(ech->innerClientHello, ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
ech->innerClientHello = NULL;
ech->state = ECH_WRITE_RETRY_CONFIGS;
ret = 0;
}
}
else {
WOLFSSL_MSG("ECH accepted");
ssl->options.echAccepted = 1;
WOLFSSL_MSG("ECH accepted");
ssl->options.echAccepted = 1;
ret = TLSX_ECH_CheckInnerPadding(ssl, ech);
if (ret == 0) {
/* expand EchOuterExtensions if present.
* Also, if it exists, copy sessionID from outer hello */
ret = TLSX_ECH_ExpandOuterExtensions(ssl, ech, ssl->heap);
ret = TLSX_ECH_CheckInnerPadding(ssl, ech);
if (ret == 0) {
/* expand EchOuterExtensions if present.
* Also, if it exists, copy sessionID from outer hello */
ret = TLSX_ECH_ExpandOuterExtensions(ssl, ech, ssl->heap);
}
}
}
if (ret != 0) {
@@ -14719,10 +14782,14 @@ static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
if (ech->ephemeralKey != NULL)
wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
ech->hpke->heap);
/* wc_HpkeFreeEchSecret is intentionally not here, free it in
* TLSX_ExtractEch / TLSX_FinalizeEch */
XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
}
if (ech->hpkeContext != NULL)
if (ech->hpkeContext != NULL) {
ForceZero(ech->hpkeContext, sizeof(HpkeBaseContext));
XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
}
if (ech->privateName != NULL)
XFREE((char*)ech->privateName, heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -14732,13 +14799,15 @@ static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
/* encrypt the client hello and store it in ech->outerClientPayload, return
* status */
int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
int TLSX_FinalizeEch(WOLFSSL* ssl, WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
{
int ret = 0;
void* receiverPubkey = NULL;
byte* info = NULL;
int infoLen = 0;
byte* aadCopy = NULL;
if (ssl == NULL || ech == NULL || aad == NULL)
return BAD_FUNC_ARG;
/* setup hpke context to seal, should be done at most once per connection */
if (ech->hpkeContext == NULL) {
/* import the server public key */
@@ -14766,6 +14835,18 @@ int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
TLS_INFO_CONST_STRING_SZ + 1);
XMEMCPY(info + TLS_INFO_CONST_STRING_SZ + 1,
ech->echConfig->raw, ech->echConfig->rawLen);
}
#ifdef HAVE_SECRET_CALLBACK
/* allocate secret buffer for wc_HpkeInitSealContext to copy into */
if (ret == 0 && (ssl->tls13SecretCb != NULL
#ifdef OPENSSL_EXTRA
|| ssl->tls13KeyLogCb != NULL
#endif
)) {
ret = wc_HpkeInitEchSecret(ech->hpke);
}
#endif /* HAVE_SECRET_CALLBACK */
if (ret == 0) {
/* init the context for seal with info and keys */
ret = wc_HpkeInitSealContext(ech->hpke, ech->hpkeContext,
ech->ephemeralKey, receiverPubkey, info, infoLen);
@@ -14786,6 +14867,15 @@ int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
aadLen, ech->innerClientHello,
ech->innerClientHelloLen - ech->hpke->Nt, ech->outerClientPayload);
}
#ifdef HAVE_SECRET_CALLBACK
if (ret == 0 && ech->hpke->echSecret != NULL) {
ret = EchWriteKeyLog(ssl, ech->hpke->echSecret, ech->hpke->Nsecret,
ech->echConfig->raw, ech->echConfig->rawLen);
}
wc_HpkeFreeEchSecret(ech->hpke);
#endif /* HAVE_SECRET_CALLBACK */
if (info != NULL)
XFREE(info, ech->hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (aadCopy != NULL)
@@ -14804,7 +14894,7 @@ int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
#define ECH_PARSE TLSX_ECH_Parse
#define ECH_FREE TLSX_ECH_Free
#endif
#endif /* WOLFSSL_TLS13 && HAVE_ECH */
/** Releases all extensions in the provided list. */
void TLSX_FreeAll(TLSX* list, void* heap)
+7 -1
View File
@@ -5097,7 +5097,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
return ret;
}
#endif
ret = TLSX_FinalizeEch(args->ech,
ret = TLSX_FinalizeEch(ssl, args->ech,
args->output + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ,
(word32)(args->sendSz - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ)));
@@ -16099,6 +16099,12 @@ int tls13ShowSecrets(WOLFSSL* ssl, int id, const unsigned char* secret,
str = "SERVER_TRAFFIC_SECRET_0"; break;
case EXPORTER_SECRET:
str = "EXPORTER_SECRET"; break;
#ifdef HAVE_ECH
case ECH_SECRET:
str = "ECH_SECRET"; break;
case ECH_CONFIG:
str = "ECH_CONFIG"; break;
#endif
default:
#ifdef WOLFSSL_SSLKEYLOGFILE_OUTPUT
XFCLOSE(fp);
+167 -8
View File
@@ -14552,12 +14552,57 @@ static int test_wolfSSL_Tls12_Key_Logging_test(void)
#if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \
defined(HAVE_SECRET_CALLBACK)
#ifdef HAVE_ECH
static int test_ech_server_ctx_ready(WOLFSSL_CTX* ctx);
static int test_ech_server_ssl_ready(WOLFSSL* ssl);
static int test_ech_client_ssl_ready(WOLFSSL* ssl);
#endif
static int test_wolfSSL_Tls13_Key_Logging_client_ctx_ready(WOLFSSL_CTX* ctx)
{
/* set keylog callback */
wolfSSL_CTX_set_keylog_callback(ctx, keyLog_callback);
return TEST_SUCCESS;
}
static int test_wolfSSL_Tls13_Key_Logging_server_ctx_ready(WOLFSSL_CTX* ctx)
{
#ifdef HAVE_ECH
if (test_ech_server_ctx_ready(ctx) != TEST_SUCCESS)
return TEST_FAIL;
#endif
/* set keylog callback */
wolfSSL_CTX_set_keylog_callback(ctx, keyLog_callback);
return TEST_SUCCESS;
}
static int test_wolfSSL_Tls13_Key_Logging_client_ssl_ready(WOLFSSL* ssl)
{
#ifdef HAVE_KEYING_MATERIAL
/* retain arrays so EXPORTER_SECRET is logged */
wolfSSL_KeepArrays(ssl);
#endif
#ifdef HAVE_ECH
return test_ech_client_ssl_ready(ssl);
#else
(void)ssl;
return TEST_SUCCESS;
#endif
}
static int test_wolfSSL_Tls13_Key_Logging_server_ssl_ready(WOLFSSL* ssl)
{
#ifdef HAVE_KEYING_MATERIAL
/* retain arrays so EXPORTER_SECRET is logged */
wolfSSL_KeepArrays(ssl);
#endif
#ifdef HAVE_ECH
return test_ech_server_ssl_ready(ssl);
#else
(void)ssl;
return TEST_SUCCESS;
#endif
}
#endif
static int test_wolfSSL_Tls13_Key_Logging_test(void)
@@ -14566,16 +14611,26 @@ static int test_wolfSSL_Tls13_Key_Logging_test(void)
#if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \
defined(HAVE_SECRET_CALLBACK)
/* This test is intended for checking whether keylog callback is called
* in client during TLS handshake between the client and a server.
* in the client/server during a TLS handshake.
*/
test_ssl_cbf server_cbf;
test_ssl_cbf client_cbf;
XFILE fp = XBADFILE;
int label_count = 4;
#ifdef HAVE_KEYING_MATERIAL
label_count += 1;
#endif
#ifdef HAVE_ECH
label_count += 2;
#endif
XMEMSET(&server_cbf, 0, sizeof(test_ssl_cbf));
XMEMSET(&client_cbf, 0, sizeof(test_ssl_cbf));
server_cbf.method = wolfTLSv1_3_server_method; /* TLS1.3 */
client_cbf.ctx_ready = &test_wolfSSL_Tls13_Key_Logging_client_ctx_ready;
client_cbf.ssl_ready = &test_wolfSSL_Tls13_Key_Logging_client_ssl_ready;
server_cbf.ctx_ready = &test_wolfSSL_Tls13_Key_Logging_server_ctx_ready;
server_cbf.ssl_ready = &test_wolfSSL_Tls13_Key_Logging_server_ssl_ready;
/* clean up keylog file */
ExpectTrue((fp = XFOPEN("./MyKeyLog.txt", "w")) != XBADFILE);
@@ -14590,7 +14645,7 @@ static int test_wolfSSL_Tls13_Key_Logging_test(void)
/* check if the keylog file exists */
{
char buff[300] = {0};
int found[4] = {0};
int found[7] = {0};
int numfnd = 0;
int i;
@@ -14600,37 +14655,140 @@ static int test_wolfSSL_Tls13_Key_Logging_test(void)
XFGETS(buff, (int)sizeof(buff), fp) != NULL) {
if (0 == strncmp(buff, "CLIENT_HANDSHAKE_TRAFFIC_SECRET ",
sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET ")-1)) {
found[0] = 1;
found[0]++;
continue;
}
else if (0 == strncmp(buff, "SERVER_HANDSHAKE_TRAFFIC_SECRET ",
sizeof("SERVER_HANDSHAKE_TRAFFIC_SECRET ")-1)) {
found[1] = 1;
found[1]++;
continue;
}
else if (0 == strncmp(buff, "CLIENT_TRAFFIC_SECRET_0 ",
sizeof("CLIENT_TRAFFIC_SECRET_0 ")-1)) {
found[2] = 1;
found[2]++;
continue;
}
else if (0 == strncmp(buff, "SERVER_TRAFFIC_SECRET_0 ",
sizeof("SERVER_TRAFFIC_SECRET_0 ")-1)) {
found[3] = 1;
found[3]++;
continue;
}
#ifdef HAVE_KEYING_MATERIAL
else if (0 == strncmp(buff, "EXPORTER_SECRET ",
sizeof("EXPORTER_SECRET ")-1)) {
found[4]++;
continue;
}
#endif
#ifdef HAVE_ECH
else if (0 == strncmp(buff, "ECH_SECRET ",
sizeof("ECH_SECRET ")-1)) {
found[5]++;
continue;
}
else if (0 == strncmp(buff, "ECH_CONFIG ",
sizeof("ECH_CONFIG ")-1)) {
found[6]++;
continue;
}
#endif
}
if (fp != XBADFILE)
XFCLOSE(fp);
for (i = 0; i < 4; i++) {
for (i = 0; i < (int)(sizeof(found) / sizeof(found[0])); i++) {
if (found[i] != 0)
numfnd++;
}
ExpectIntEQ(numfnd, 4);
ExpectIntEQ(numfnd, label_count);
/* the four traffic secrets are derived by both client and server, so
* each label should appear twice with the callback set on both sides */
ExpectIntEQ(found[0], 2);
ExpectIntEQ(found[1], 2);
ExpectIntEQ(found[2], 2);
ExpectIntEQ(found[3], 2);
#ifdef HAVE_KEYING_MATERIAL
/* both sides retain arrays via KeepArrays, so EXPORTER_SECRET fires
* on each */
ExpectIntEQ(found[4], 2);
#endif
#ifdef HAVE_ECH
/* both sides also log ECH_SECRET and ECH_CONFIG (seal on client,
* open on server) */
ExpectIntEQ(found[5], 2);
ExpectIntEQ(found[6], 2);
#endif
}
#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK && WOLFSSL_TLS13 */
return EXPECT_RESULT();
}
#if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \
defined(HAVE_SECRET_CALLBACK) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES)
/* Fails only when the derive site fires with an id matching *ctx, so the
* caller can drive each Derive*Secret call site's failure path in isolation. */
static int keylog_fail_cb(WOLFSSL* ssl, int id, const unsigned char* secret,
int secretSz, void* ctx)
{
(void)ssl;
(void)secret;
(void)secretSz;
return (ctx != NULL && id == *(const int*)ctx) ? -1 : 0;
}
#endif
static int test_wolfSSL_Tls13_Key_Logging_callback_fail(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_TLS13) && defined(OPENSSL_EXTRA) && \
defined(HAVE_SECRET_CALLBACK) && defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES)
/* A non-zero return from Tls13SecretCb at any derive site must surface as
* TLS13_SECRET_CB_E and fail the handshake. */
const int labels[] = {
CLIENT_HANDSHAKE_TRAFFIC_SECRET,
SERVER_HANDSHAKE_TRAFFIC_SECRET,
CLIENT_TRAFFIC_SECRET,
SERVER_TRAFFIC_SECRET,
#ifdef HAVE_KEYING_MATERIAL
EXPORTER_SECRET,
#endif
#ifdef HAVE_ECH
ECH_SECRET,
ECH_CONFIG,
#endif
};
struct test_ssl_memio_ctx test_ctx;
int fail_id;
int i;
for (i = 0; i < (int)(sizeof(labels) / sizeof(labels[0])); i++) {
fail_id = labels[i];
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
test_ctx.s_cb.method = wolfTLSv1_3_server_method;
test_ctx.c_cb.method = wolfTLSv1_3_client_method;
test_ctx.c_cb.ctx_ready = &test_wolfSSL_Tls13_Key_Logging_client_ctx_ready;
test_ctx.c_cb.ssl_ready = &test_wolfSSL_Tls13_Key_Logging_client_ssl_ready;
test_ctx.s_cb.ctx_ready = &test_wolfSSL_Tls13_Key_Logging_server_ctx_ready;
test_ctx.s_cb.ssl_ready = &test_wolfSSL_Tls13_Key_Logging_server_ssl_ready;
ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS);
ExpectIntEQ(wolfSSL_set_tls13_secret_cb(test_ctx.c_ssl,
keylog_fail_cb, &fail_id), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_set_tls13_secret_cb(test_ctx.s_ssl,
keylog_fail_cb, &fail_id), WOLFSSL_SUCCESS);
ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
TEST_SUCCESS);
/* either peer may surface the error first depending on derive order */
ExpectTrue(wolfSSL_get_error(test_ctx.c_ssl, 0)
== WC_NO_ERR_TRACE(TLS13_SECRET_CB_E) ||
wolfSSL_get_error(test_ctx.s_ssl, 0)
== WC_NO_ERR_TRACE(TLS13_SECRET_CB_E));
test_ssl_memio_cleanup(&test_ctx);
}
#endif
return EXPECT_RESULT();
}
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
#if defined(HAVE_IO_TESTS_DEPENDENCIES)
static int test_wolfSSL_Tls13_ECH_params(void)
@@ -40709,6 +40867,7 @@ TEST_CASE testCases[] = {
TEST_DECL(test_wolfSSL_Tls12_Key_Logging_test),
/* Can't memory test as server hangs. */
TEST_DECL(test_wolfSSL_Tls13_Key_Logging_test),
TEST_DECL(test_wolfSSL_Tls13_Key_Logging_callback_fail),
TEST_DECL(test_wolfSSL_Tls13_postauth),
TEST_DECL(test_wolfSSL_set_ecdh_auto),
TEST_DECL(test_wolfSSL_CTX_set_ecdh_auto),
+32
View File
@@ -906,6 +906,11 @@ static int wc_HpkeSetupBaseSender(Hpke* hpke, HpkeBaseContext* context,
infoSz);
}
#if defined(HAVE_SECRET_CALLBACK) && defined(HAVE_ECH)
if (ret == 0 && hpke->echSecret != NULL) {
XMEMCPY(hpke->echSecret, sharedSecret, hpke->Nsecret);
}
#endif
ForceZero(sharedSecret, hpke->Nsecret);
WC_FREE_VAR_EX(sharedSecret, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1148,6 +1153,11 @@ static int wc_HpkeSetupBaseReceiver(Hpke* hpke, HpkeBaseContext* context,
infoSz);
}
#if defined(HAVE_SECRET_CALLBACK) && defined(HAVE_ECH)
if (ret == 0 && hpke->echSecret != NULL) {
XMEMCPY(hpke->echSecret, sharedSecret, hpke->Nsecret);
}
#endif
ForceZero(sharedSecret, hpke->Nsecret);
WC_FREE_VAR_EX(sharedSecret, hpke->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1345,4 +1355,26 @@ WOLFSSL_LOCAL int wc_HpkeAeadIsSupported(word16 aeadId)
}
}
#if defined(HAVE_SECRET_CALLBACK) && defined(HAVE_ECH)
WOLFSSL_LOCAL int wc_HpkeInitEchSecret(Hpke* hpke)
{
if (hpke == NULL)
return BAD_FUNC_ARG;
hpke->echSecret = (byte*)XMALLOC(hpke->Nsecret, hpke->heap,
DYNAMIC_TYPE_SECRET);
if (hpke->echSecret == NULL)
return MEMORY_E;
return 0;
}
WOLFSSL_LOCAL void wc_HpkeFreeEchSecret(Hpke* hpke)
{
if (hpke == NULL || hpke->echSecret == NULL)
return;
ForceZero(hpke->echSecret, hpke->Nsecret);
XFREE(hpke->echSecret, hpke->heap, DYNAMIC_TYPE_SECRET);
hpke->echSecret = NULL;
}
#endif /* HAVE_SECRET_CALLBACK && HAVE_ECH */
#endif /* HAVE_HPKE && (HAVE_ECC || HAVE_CURVE25519) && HAVE_AESGCM */
+2 -1
View File
@@ -3178,7 +3178,8 @@ typedef struct WOLFSSL_ECH {
WOLFSSL_LOCAL int EchConfigGetSupportedCipherSuite(WOLFSSL_EchConfig* config);
WOLFSSL_LOCAL int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen);
WOLFSSL_LOCAL int TLSX_FinalizeEch(WOLFSSL* ssl, WOLFSSL_ECH* ech, byte* aad,
word32 aadLen);
WOLFSSL_LOCAL int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
+5 -1
View File
@@ -1064,7 +1064,11 @@ enum Tls13Secret {
CLIENT_TRAFFIC_SECRET,
SERVER_TRAFFIC_SECRET,
EARLY_EXPORTER_SECRET,
EXPORTER_SECRET
EXPORTER_SECRET,
#if defined(HAVE_ECH)
ECH_SECRET,
ECH_CONFIG,
#endif
};
#endif
+8
View File
@@ -96,6 +96,9 @@ typedef struct {
word16 aead;
byte kem_suite_id[KEM_SUITE_ID_LEN];
byte hpke_suite_id[HPKE_SUITE_ID_LEN];
#if defined(HAVE_SECRET_CALLBACK) && defined(HAVE_ECH)
byte* echSecret;
#endif
} Hpke;
typedef struct {
@@ -135,6 +138,11 @@ WOLFSSL_LOCAL int wc_HpkeKemIsSupported(word16 kemId);
WOLFSSL_LOCAL int wc_HpkeKdfIsSupported(word16 kdfId);
WOLFSSL_LOCAL int wc_HpkeAeadIsSupported(word16 aeadId);
#if defined(HAVE_SECRET_CALLBACK) && defined(HAVE_ECH)
WOLFSSL_LOCAL int wc_HpkeInitEchSecret(Hpke* hpke);
WOLFSSL_LOCAL void wc_HpkeFreeEchSecret(Hpke* hpke);
#endif
#endif
#endif /* HAVE_HPKE && (HAVE_ECC || HAVE_CURVE25519) && HAVE_AESGCM */