1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Add TLS 1.3 handshake support for crypto callbacks returning WC_PENDING_E

This commit is contained in:
David Garske
2026-09-02 14:33:12 -07:00
parent 6314a051e9
commit 1ed9f2c02c
8 changed files with 1121 additions and 313 deletions

View File

@@ -11900,8 +11900,9 @@ then
fi
fi
# Crypto callbacks with async crypt may not work for TLS unless
# WOLF_CRYPTO_CB_ASYNC_POLL is defined. Report it once here and silence the
# Crypto callbacks with async crypt cannot complete TLS 1.2 record ciphers
# unless WOLF_CRYPTO_CB_ASYNC_POLL is defined (TLS 1.3 resumes them by
# re-invoking the callback). Report it once here and silence the
# source-level #warning. AC_MSG_NOTICE, not AC_MSG_WARN: the multi-test
# harness fails any scenario whose configure emits "configure: WARNING:".
if test "$ENABLED_ASYNCCRYPT" = "yes" && test "x$ENABLED_CRYPTOCB" != "xno" &&
@@ -11912,7 +11913,7 @@ then
*WOLF_CRYPTO_CB_ASYNC_POLL*)
;;
*)
AC_MSG_NOTICE([crypto callbacks with async crypt may not work for TLS. Define WOLF_CRYPTO_CB_ASYNC_POLL to enable it.])
AC_MSG_NOTICE([crypto callbacks with async crypt cannot complete TLS 1.2 record ciphers. Define WOLF_CRYPTO_CB_ASYNC_POLL to enable them.])
AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB_ASYNC_NO_WARN"
;;
esac

View File

@@ -9520,6 +9520,11 @@ void FreeAsyncCtx(WOLFSSL* ssl, byte freeAsync)
}
#endif
if (freeAsync) {
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_TLS13)
/* Teardown only: a suspended record build must keep its
* resume marker across handler-tail cleanups. */
ssl->options.buildArgs13Set = 0;
#endif
XFREE(ssl->async, ssl->heap, DYNAMIC_TYPE_ASYNC);
ssl->async = NULL;
}
@@ -9824,6 +9829,10 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
#ifdef WOLFSSL_ASYNC_IO
/* Cleanup async */
FreeAsyncCtx(ssl, 1);
#endif
#if defined(WOLFSSL_ASYNC_REINVOKE) && defined(WOLFSSL_TLS13) && \
!defined(NO_HMAC)
Tls13FreeHsHmac(ssl);
#endif
if (ssl->options.weOwnRng) {
wc_FreeRng(ssl->rng);
@@ -19294,6 +19303,12 @@ exit_ppc:
return ret;
}
/* TLS 1.3 replays skip the sanity check that re-sets got_certificate;
* restore on completion or Finished reports out-of-order. */
if (ret == 0 && IsAtLeastTLSv1_3(ssl->version) &&
ssl->msgsReceived.got_certificate == 0) {
ssl->msgsReceived.got_certificate = 1;
}
#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */
#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)
@@ -25250,6 +25265,26 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
return ssl->error;
}
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_ASYNC_CRYPT)
/* Finish a TLS 1.3 key schedule the last handshake message left pending
* before any further record is read or decrypted: the derives install
* the very keys that record needs. See DoTls13MsgDerives(). */
if (ssl->options.tls1_3 && ssl->kdfMsgStep > 0) {
ret = DoTls13MsgDerives(ssl, ssl->kdfMsgType);
if (ret != 0) {
if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) {
WOLFSSL_ERROR(ret);
}
return ret;
}
/* The pend is resolved; leaving ssl->error set would make the
* next message skip its sanity check and got_* marking. */
if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) {
ssl->error = 0;
}
}
#endif
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_ASYNC_CRYPT)
/* process any pending DTLS messages - this flow can happen with async */
if (ssl->dtls_rx_msg_list != NULL) {
@@ -25942,6 +25977,24 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
ssl->buffers.inputBuffer.buffer,
&ssl->buffers.inputBuffer.idx,
ssl->curStartIdx + ssl->curSize);
#if defined(WOLFSSL_ASYNC_CRYPT)
/* A post-handler key-schedule pend consumed the
* message but not the record; finish it here so
* the retry reads the next record. */
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) &&
ssl->kdfMsgStep > 0) {
ssl->options.processReply = doProcessInit;
if ((ssl->buffers.inputBuffer.idx -
ssl->curStartIdx) < ssl->curSize) {
ssl->options.processReply =
runProcessingOneMessage;
}
else if (IsEncryptionOn(ssl, 0)) {
ssl->buffers.inputBuffer.idx +=
ssl->keys.padSz;
}
}
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
/* Post-handshake auth resumes through
* wolfSSL_negotiate() instead of reprocessing this
@@ -25951,8 +26004,12 @@ static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
* the trailing MAC is read as the next record header
* and fails with VERSION_ERROR. Mirrors the end of
* record block below: resume inside the record when
* content is left, else skip the padding. */
* content is left, else skip the padding. Skipped for
* a key-schedule pend (kdfMsgStep != 0): the block
* above already finished the record, and running this
* one too would skip the padding twice. */
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) &&
ssl->kdfMsgStep == TLS13_MSG_KDF_NONE &&
ssl->options.processReply == doProcessInit) {
if ((ssl->buffers.inputBuffer.idx -
ssl->curStartIdx) < ssl->curSize) {

View File

@@ -5712,6 +5712,31 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out,
ssl->options.onlyPskDheKe = ssl->ctx->onlyPskDheKe;
#endif
#endif
/* An abandoned handshake can leave a key-schedule or record-build
* resume marker set; a reused object must not resume into the new
* handshake. */
ssl->kdfDeriveStep = TLS13_SEND_KDF_NONE;
ssl->kdfMsgStep = TLS13_MSG_KDF_NONE;
ssl->kdfMsgType = 0;
#if defined(WOLFSSL_ASYNC_REINVOKE) && !defined(NO_HMAC)
Tls13FreeHsHmac(ssl);
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
ssl->options.buildArgs13Set = 0;
/* An abandoned handshake can leave a mid-flight handler resume
* state and a queued key-schedule event behind; a reused object
* must start fresh. */
ssl->options.asyncState = TLS_ASYNC_BEGIN;
if (ssl->asyncDev == &ssl->kdfAsyncDev) {
if (ssl->kdfAsyncDev.event.state == WOLF_EVENT_STATE_PENDING &&
ssl->ctx != NULL) {
(void)wolfEventQueue_Remove(&ssl->ctx->event_queue,
&ssl->kdfAsyncDev.event);
}
XMEMSET(&ssl->kdfAsyncDev.event, 0, sizeof(WOLF_EVENT));
ssl->asyncDev = NULL;
}
#endif
#endif
#ifdef HAVE_SESSION_TICKET
#ifdef WOLFSSL_TLS13

155
src/tls.c
View File

@@ -8479,7 +8479,7 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
return MEMORY_E;
}
/* Make an Curve25519 key. */
/* Initialize the Curve25519 key. */
ret = wc_curve25519_init_ex((curve25519_key*)kse->key, ssl->heap,
ssl->devId);
if (ret == 0) {
@@ -8508,28 +8508,32 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
}
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
WC_ASYNC_ENABLE_X25519 */
if (ret == 0) {
#ifdef WOLFSSL_STATIC_EPHEMERAL
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE25519, kse->key);
if (ret != 0) /* on failure, fallback to local key generation */
#endif
{
#ifdef WOLFSSL_ASYNC_CRYPT
/* initialize event */
ret = wolfSSL_AsyncInit(ssl, &key->asyncDev,
WC_ASYNC_FLAG_NONE);
if (ret != 0)
return ret;
#endif
ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
}
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
/* Outside the allocation guard: a WC_PENDING_E retry must regenerate,
* not export an ungenerated key. pubKeyLen marks a completed export on
* every backend; pubSet stops the SW-async retry re-arming forever. */
if (ret == 0 && key != NULL && kse->pubKeyLen == 0 && !key->pubSet) {
#ifdef WOLFSSL_STATIC_EPHEMERAL
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE25519,
kse->key);
if (ret != 0) /* on failure, fallback to local key generation */
#endif
{
#ifdef WOLFSSL_ASYNC_CRYPT
/* initialize event */
ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE);
if (ret != 0)
return ret;
#endif
ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
/* Handle async pending response */
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
return wolfSSL_AsyncPush(ssl, &key->asyncDev);
}
#endif /* WOLFSSL_ASYNC_CRYPT */
}
}
@@ -8759,6 +8763,10 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
/* Initialize an ECC key struct for the ephemeral key */
ret = wc_ecc_init_ex((ecc_key*)kse->key, ssl->heap, ssl->devId);
if (ret == 0) {
/* setting eccKey means okay to call wc_ecc_free */
eccKey = (ecc_key*)kse->key;
}
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
defined(WC_ASYNC_ENABLE_ECC)
@@ -8781,49 +8789,44 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
}
#endif /* WC_ECC_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
WC_ASYNC_ENABLE_ECC */
}
if (ret == 0) {
kse->keyLen = keySize;
kse->pubKeyLen = keySize * 2 + 1;
/* Outside the allocation guard: a WC_PENDING_E retry must regenerate,
* not export an ungenerated key. The key type marks completion;
* kse->pubKey covers backends that never touch the ecc_key (TSIP). */
if (ret == 0 && eccKey != NULL) {
/* Outside the generation guard below: the export alloc reads
* pubKeyLen even when generation is skipped. */
kse->keyLen = keySize;
kse->pubKeyLen = keySize * 2 + 1;
}
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
ret = tsip_Tls13GenEccKeyPair(ssl, kse);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
if (ret == 0 && eccKey != NULL && kse->pubKey == NULL &&
eccKey->type != ECC_PRIVATEKEY &&
eccKey->type != ECC_PRIVATEKEY_ONLY) {
#if defined(WOLFSSL_RENESAS_TSIP_TLS)
ret = tsip_Tls13GenEccKeyPair(ssl, kse);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
return ret;
}
#endif
#ifdef WOLFSSL_STATIC_EPHEMERAL
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_ECDH, kse->key);
if (ret != 0 || eccKey->dp->id != curveId)
#endif
{
/* set curve info for EccMakeKey "peer" info */
ret = wc_ecc_set_curve(eccKey, (int)kse->keyLen, curveId);
if (ret == 0) {
/* Generate ephemeral ECC key; a crypto callback retry
* re-enters here, x963 export follows below. */
ret = EccMakeKey(ssl, eccKey, eccKey);
}
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
}
#endif
/* setting eccKey means okay to call wc_ecc_free */
eccKey = (ecc_key*)kse->key;
#ifdef WOLFSSL_STATIC_EPHEMERAL
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_ECDH, kse->key);
if (ret != 0 || eccKey->dp->id != curveId)
#endif
{
/* set curve info for EccMakeKey "peer" info */
ret = wc_ecc_set_curve(eccKey, (int)kse->keyLen, curveId);
if (ret == 0) {
#ifdef WOLFSSL_ASYNC_CRYPT
/* Detect when private key generation is done */
if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) &&
eccKey->type == ECC_PRIVATEKEY) {
ret = 0; /* ECC Key Generation is done */
}
else
#endif
{
/* Generate ephemeral ECC key */
/* For async this is called once and when event is done, the
* provided buffers in key be populated.
* Final processing is x963 key export below. */
ret = EccMakeKey(ssl, eccKey, eccKey);
}
}
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_NO_ERR_TRACE(WC_PENDING_E))
return ret;
#endif
}
}
}
@@ -10661,7 +10664,8 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
}
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) || \
defined(WOLFSSL_ASYNC_CRYPT)
keyShareEntry->derived = (ret == 0);
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
@@ -12278,6 +12282,27 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl)
TLSX* extension;
KeyShareEntry* list = NULL;
/* Find the KeyShare extension if it exists. */
extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
if (extension != NULL)
list = (KeyShareEntry*)extension->data;
if (list == NULL) {
/* Unreachable once the handshake reached this accept state
* (TLSX_KeyShare_Setup installed the extension), so no async event
* can be stranded by returning before the pop below. */
return KEY_SHARE_ERROR;
}
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) || \
defined(WOLFSSL_ASYNC_CRYPT)
/* Already derived: a later pend's retry re-enters here with the peer
* key freed. Checked before the pop so the later operation's queued
* event is not stolen. */
if (list->derived)
return 0;
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wolfSSL_AsyncPop(ssl, NULL);
/* Check for error */
@@ -12286,14 +12311,6 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl)
}
#endif
/* Find the KeyShare extension if it exists. */
extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
if (extension != NULL)
list = (KeyShareEntry*)extension->data;
if (list == NULL)
return KEY_SHARE_ERROR;
/* Calculate secret. */
ret = TLSX_KeyShare_Process(ssl, list);

File diff suppressed because it is too large Load Diff

View File

@@ -77,8 +77,9 @@ Crypto Callback Build Options:
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
!defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \
!defined(HAVE_CAVIUM) && !defined(WOLF_CRYPTO_CB_ASYNC_NO_WARN)
#warning "crypto callbacks with async crypt may not work for TLS. Define \
WOLF_CRYPTO_CB_ASYNC_POLL to enable it, or WOLF_CRYPTO_CB_ASYNC_NO_WARN to \
#warning "crypto callbacks with async crypt cannot complete TLS 1.2 \
record ciphers (TLS 1.3 resumes them by re-invoking the callback). Define \
WOLF_CRYPTO_CB_ASYNC_POLL to enable them, or WOLF_CRYPTO_CB_ASYNC_NO_WARN to \
silence."
#endif

View File

@@ -2373,6 +2373,19 @@ WOLFSSL_LOCAL int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input
#ifdef WOLFSSL_TLS13
WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
word16 sz, const byte* aad, word16 aadSz);
WOLFSSL_LOCAL int DoTls13MsgDerives(WOLFSSL* ssl, byte type);
/* A crypto/PK callback pending is finished by re-invoking the provider:
* wolfSSL_AsyncPoll() never runs a callback. Exported so tests compile in
* only where a callback pend is resumable. */
#if defined(WOLFSSL_ASYNC_CRYPT) && \
(defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)) && \
!defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \
!defined(HAVE_CAVIUM)
#define WOLFSSL_ASYNC_REINVOKE
#endif
#if defined(WOLFSSL_ASYNC_REINVOKE) && !defined(NO_HMAC)
WOLFSSL_LOCAL void Tls13FreeHsHmac(WOLFSSL* ssl);
#endif
WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input,
word32* inOutIdx, byte type,
word32 size, word32 totalSz);
@@ -3959,6 +3972,12 @@ typedef struct KeyShareEntry {
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
word16 session; /* NamedGroup that was in session */
#endif
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) || \
defined(WOLFSSL_ASYNC_CRYPT)
/* Also under WOLFSSL_ASYNC_CRYPT: a pending operation retried on the
* same accept state re-enters the derive with the peer key freed, and
* this is the marker that stops the re-derive. */
word16 derived; /* preMaster has been derived */
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
@@ -3978,7 +3997,7 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions,
byte* searched);
WOLFSSL_LOCAL int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE);
WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl, int* doHelloRetry);
WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* sclientKSEclientKSEsl);
WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl);
WOLFSSL_LOCAL int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input,
word16 length, byte msgType);
WOLFSSL_LOCAL int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl,
@@ -5577,6 +5596,19 @@ struct Options {
#ifdef WOLFSSL_ASYNC_CRYPT
word16 buildArgsSet:1; /* buildArgs are set and need to
* be free'd */
#ifdef WOLFSSL_TLS13
word16 buildArgs13Set:1; /* a TLS 1.3 record build is in
* progress and must resume,
* not restart */
word16 chHashInput:1; /* current ClientHello already
* hashed into the transcript;
* a PSK-binder pend must not
* re-hash it on resume */
word16 asyncReplayMsg:1; /* the next TLS 1.3 handshake
* message is a replay of one
* whose handler pended; skip
* its sanity check once */
#endif
#endif
#ifdef WOLFSSL_DTLS13
word16 dtls13SendMoreAcks:1; /* Send more acks during the
@@ -6176,8 +6208,8 @@ typedef struct HS_Hashes {
} HS_Hashes;
#ifndef WOLFSSL_NO_TLS12
/* Persistable BuildMessage arguments */
#if !defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)
/* Persistable BuildMessage/BuildTls13Message arguments */
typedef struct BuildMsgArgs {
word32 digestSz;
word32 sz;
@@ -6197,8 +6229,11 @@ typedef struct BuildMsgArgs {
typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs);
struct WOLFSSL_ASYNC {
#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WOLFSSL_NO_TLS12)
BuildMsgArgs buildArgs; /* holder for current BuildMessage args */
#if defined(WOLFSSL_ASYNC_CRYPT) && \
(!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13))
/* Record builder resume args, shared by BuildMessage() and
* BuildTls13Message(): a connection runs only one of them. */
BuildMsgArgs buildArgs;
#endif
FreeArgsCb freeArgs; /* function pointer to cleanup args */
#ifdef WC_NO_PTR_INT_CAST
@@ -6447,6 +6482,56 @@ enum ConnectionIdUsage {
(ssl)->ctx->suites))
/* wolfSSL ssl type */
/* TLS 1.3 key-schedule resume steps (kdfMsgStep/kdfDeriveStep). A value is
* recorded after its named operation completes ("step <= X" = X not done);
* 0 = sequence not entered or finished. Values repeat across sequences. */
/* Receive side (kdfMsgStep), driven by DoTls13MsgDerives(). */
enum Tls13KdfMsgStep {
TLS13_MSG_KDF_NONE = 0,
/* client processing server_hello */
TLS13_MSG_KDF_SH_ENTERED = 1,
TLS13_MSG_KDF_SH_EARLY_SECRET = 2,
TLS13_MSG_KDF_SH_HS_SECRET = 3,
TLS13_MSG_KDF_SH_HS_KEYS = 4,
TLS13_MSG_KDF_SH_KEYS_SET = 5,
TLS13_MSG_KDF_SH_DTLS_EPOCH = 6,
/* client processing finished */
TLS13_MSG_KDF_FIN_ENTERED = 1,
TLS13_MSG_KDF_FIN_MASTER_SECRET = 2,
TLS13_MSG_KDF_FIN_QUIC_EARLY_KEYS = 3,
TLS13_MSG_KDF_FIN_TRAFFIC_KEYS = 4,
TLS13_MSG_KDF_FIN_TRAFFIC_DONE = 5,
TLS13_MSG_KDF_FIN_KEYS_SET = 6,
/* server processing finished (resumption secret for tickets) */
TLS13_MSG_KDF_SFIN_ENTERED = 1,
TLS13_MSG_KDF_SFIN_RESUMPTION_SECRET = 2
};
/* Send side (kdfDeriveStep), inside the senders themselves. */
enum Tls13KdfSendStep {
TLS13_SEND_KDF_NONE = 0,
/* SendTls13EncryptedExtensions() */
TLS13_SEND_KDF_EE_HS_SECRET = 1,
TLS13_SEND_KDF_EE_HS_KEYS = 2,
TLS13_SEND_KDF_EE_ENC_KEYS_SET = 3,
TLS13_SEND_KDF_EE_KEYS_SET = 4,
TLS13_SEND_KDF_EE_DTLS_EPOCH = 5,
/* SendTls13Finished() */
TLS13_SEND_KDF_FIN_ENTERED = 1,
TLS13_SEND_KDF_FIN_MASTER_SECRET = 2,
TLS13_SEND_KDF_FIN_ENC_TRAFFIC_KEYS = 3,
TLS13_SEND_KDF_FIN_TRAFFIC_KEYS = 4,
TLS13_SEND_KDF_FIN_ENC_KEYS_SET = 5,
TLS13_SEND_KDF_FIN_DTLS_TRAFFIC_EPOCH = 6,
TLS13_SEND_KDF_FIN_EARLY_ENC_KEYS = 7,
TLS13_SEND_KDF_FIN_EARLY_KEYS_SET = 8,
TLS13_SEND_KDF_FIN_RESUMPTION_SECRET = 9,
TLS13_SEND_KDF_FIN_DTLS_EPOCH_SET = 10
};
struct WOLFSSL {
WOLFSSL_CTX* ctx;
#if defined(WOLFSSL_HAPROXY)
@@ -7028,6 +7113,27 @@ struct WOLFSSL {
* ciphers; 0 means uncached and is never a valid AEAD overhead. EtM does
* not apply to AEAD. */
word32 recordSzOverhead;
#ifdef WOLFSSL_ASYNC_CRYPT
/* Async device for the TLS 1.3 key schedule: HKDF has no key object
* to carry one. Event bookkeeping only, for the callback re-invoke
* path (never wolfAsync_DevCtxInit'd, no hardware context). */
WC_ASYNC_DEV kdfAsyncDev;
#endif
/* Key-schedule resume steps: completed derives must not re-run (e.g.
* the extract is in place over preMasterSecret). Unconditional so the
* schedule needs no ifdefs; without async they stay 0. */
byte kdfDeriveStep; /* enum Tls13KdfSendStep (send side) */
byte kdfMsgStep; /* enum Tls13KdfMsgStep (receive side) */
byte kdfMsgType; /* handshake type kdfMsgStep belongs to */
#if defined(WOLFSSL_ASYNC_REINVOKE) && defined(WOLFSSL_TLS13) && \
!defined(NO_HMAC)
/* Transcript HMAC (Finished verify_data, PSK binders) held across a
* WC_PENDING_E so the retry re-invokes the same object and arguments,
* bound to its output buffer. */
Hmac* hsHmac;
byte* hsHmacOut;
byte hsHmacStep;
#endif
};
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)

View File

@@ -4056,9 +4056,8 @@
#error WOLF_CRYPTO_CB_ASYNC_POLL requires bulk cipher async support
#endif
/* Crypto callbacks are the only async backend and cannot finish a pending
* bulk cipher op: the record layer has already advanced past the crypto
* call, and without poll routing nothing refills the output buffer. */
/* Callback-only async cannot finish a pending TLS 1.2 bulk cipher op
* (TLS 1.3 resumes them by re-invoking the callback). */
#if defined(WOLF_CRYPTO_CB) && !defined(WOLF_CRYPTO_CB_ASYNC_POLL) && \
!defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \
!defined(HAVE_CAVIUM)