mirror of https://github.com/wolfSSL/wolfssl.git
Merge pull request #11231 from dgarske/cryptocb_async_tls13
Extend TLS 1.3 async support to HKDF, HMAC, AES-GCM, RNG and X25519/Ed25519pull/11427/head
commit
252c3b1aa3
|
|
@ -71,7 +71,7 @@ jobs:
|
|||
run: |
|
||||
cat > "$RUNNER_TEMP/async-configs.json" <<'EOF'
|
||||
[
|
||||
{"comment": "The only entry that pairs the software async simulator with --enable-all. --enable-all turns on cryptocb, which stops configure.ac from auto-enabling the simulator, so the asynccrypt-all entries below define WOLFSSL_ASYNC_CRYPT but never actually return WC_PENDING_E. Without this one nothing exercises TLS 1.3 post-handshake auth or DTLS writes against a pending crypto op. The minutes value is a projection, not a CI measurement: this config takes 1.6 min locally where the asynccrypt-all entries below take 1.4 against their declared 3. Refresh it from the first real run.",
|
||||
{"comment": "The only entry that pairs the software async simulator with --enable-all. --enable-all turns on cryptocb, which stops configure.ac from auto-enabling the simulator, so the asynccrypt-all entries below define WOLFSSL_ASYNC_CRYPT but their built-in devices never return WC_PENDING_E; pending is exercised there by the tests that register their own pending callback (hkdf_cryptocb_async_test() in wolfCrypt, test_tls13_cryptocb_async in the api suite). Without this one nothing exercises TLS 1.3 post-handshake auth or DTLS writes against a pending crypto op. The minutes value is a projection, not a CI measurement: this config takes 1.6 min locally where the asynccrypt-all entries below take 1.4 against their declared 3. Refresh it from the first real run.",
|
||||
"name": "asynccrypt-sw-all-dtls13", "minutes": 3,
|
||||
"configure": ["--enable-asynccrypt-sw", "--enable-all",
|
||||
"--enable-dtls13",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -245,6 +245,19 @@ int wc_HKDF_Extract(
|
|||
\return HMAC_MIN_KEYLEN_E May be returned when using a FIPS implementation
|
||||
and the key length specified is shorter than the minimum acceptable FIPS
|
||||
standard
|
||||
\return WC_PENDING_E May be returned in a WOLF_CRYPTO_CB build when the
|
||||
registered crypto callback device has taken the request but not yet
|
||||
finished it. The caller must re-invoke with identical arguments until the
|
||||
result is no longer WC_PENDING_E; HKDF has no WC_ASYNC_DEV, so this is a
|
||||
poll and not a wc_AsyncWait(). In a WOLFSSL_ASYNC_CRYPT build the TLS 1.3
|
||||
key schedule resumes a pending HKDF request by re-invoking the callback
|
||||
with identical arguments; without WOLFSSL_ASYNC_CRYPT a device also used
|
||||
for TLS 1.3 must complete HKDF requests synchronously. wc_HKDF_ex()
|
||||
follows the same contract and re-issues its extract step on every retry,
|
||||
so a device that pends must serve a repeated identical request from its
|
||||
completed result. There is no request handle: a device should key its
|
||||
completion tracking on the output pointer plus the argument tuple, and
|
||||
one that cannot correlate a retry that way must not pend.
|
||||
|
||||
\param type hash type to use for the HKDF. Valid types are: WC_MD5, WC_SHA,
|
||||
WC_SHA256, WC_SHA384, WC_SHA512, WC_SHA3_224, WC_SHA3_256, WC_SHA3_384 or
|
||||
|
|
@ -357,6 +370,19 @@ int wc_HKDF_Expand(
|
|||
\return HMAC_MIN_KEYLEN_E May be returned when using a FIPS implementation
|
||||
and the key length specified is shorter than the minimum acceptable FIPS
|
||||
standard
|
||||
\return WC_PENDING_E May be returned in a WOLF_CRYPTO_CB build when the
|
||||
registered crypto callback device has taken the request but not yet
|
||||
finished it. The caller must re-invoke with identical arguments until the
|
||||
result is no longer WC_PENDING_E; HKDF has no WC_ASYNC_DEV, so this is a
|
||||
poll and not a wc_AsyncWait(). In a WOLFSSL_ASYNC_CRYPT build the TLS 1.3
|
||||
key schedule resumes a pending HKDF request by re-invoking the callback
|
||||
with identical arguments; without WOLFSSL_ASYNC_CRYPT a device also used
|
||||
for TLS 1.3 must complete HKDF requests synchronously. wc_HKDF_ex()
|
||||
follows the same contract and re-issues its extract step on every retry,
|
||||
so a device that pends must serve a repeated identical request from its
|
||||
completed result. There is no request handle: a device should key its
|
||||
completion tracking on the output pointer plus the argument tuple, and
|
||||
one that cannot correlate a retry that way must not pend.
|
||||
|
||||
\param type hash type to use for the HKDF. Valid types are: WC_MD5, WC_SHA,
|
||||
WC_SHA256, WC_SHA384, WC_SHA512, WC_SHA3_224, WC_SHA3_256, WC_SHA3_384 or
|
||||
|
|
@ -459,6 +485,11 @@ int wc_Tls13_HKDF_Extract(
|
|||
\return HMAC_MIN_KEYLEN_E May be returned when using a FIPS implementation
|
||||
and the key length specified is shorter than the minimum acceptable FIPS
|
||||
standard
|
||||
\return WC_PENDING_E May be returned in a WOLF_CRYPTO_CB build when the
|
||||
registered crypto callback device has taken the request but not yet
|
||||
finished it; the caller re-invokes with identical arguments until the
|
||||
result is no longer WC_PENDING_E. The TLS 1.3 key schedule does this in
|
||||
WOLFSSL_ASYNC_CRYPT builds.
|
||||
|
||||
\param prk Generated pseudorandom key
|
||||
\param salt Salt. May be NULL; saltLen is then ignored unless a crypto
|
||||
|
|
@ -510,6 +541,11 @@ int wc_Tls13_HKDF_Extract_ex(
|
|||
\return HMAC_MIN_KEYLEN_E May be returned when using a FIPS implementation
|
||||
and the key length specified is shorter than the minimum acceptable FIPS
|
||||
standard
|
||||
\return WC_PENDING_E May be returned in a WOLF_CRYPTO_CB build when the
|
||||
registered crypto callback device has taken the request but not yet
|
||||
finished it; the caller re-invokes with identical arguments until the
|
||||
result is no longer WC_PENDING_E. The TLS 1.3 key schedule does this in
|
||||
WOLFSSL_ASYNC_CRYPT builds.
|
||||
|
||||
\param okm Generated pseudorandom key - output key material.
|
||||
\param okmLen Length of generated pseudorandom key - output key material.
|
||||
|
|
@ -591,6 +627,11 @@ int wc_Tls13_HKDF_Expand_Label(
|
|||
\return HMAC_MIN_KEYLEN_E May be returned when using a FIPS implementation
|
||||
and the key length specified is shorter than the minimum acceptable FIPS
|
||||
standard
|
||||
\return WC_PENDING_E May be returned in a WOLF_CRYPTO_CB build when the
|
||||
registered crypto callback device has taken the request but not yet
|
||||
finished it; the caller re-invokes with identical arguments until the
|
||||
result is no longer WC_PENDING_E. The TLS 1.3 key schedule does this in
|
||||
WOLFSSL_ASYNC_CRYPT builds.
|
||||
|
||||
\param okm Generated pseudorandom key - output key material.
|
||||
\param okmLen Length of generated pseudorandom key - output key material.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,14 @@ make -C examples/async ASYNC_MODE=sw
|
|||
|
||||
### Crypto Callback Mode
|
||||
Uses `WOLF_CRYPTO_CB` with the `AsyncTlsCryptoCb` callback that simulates hardware
|
||||
crypto delays by returning `WC_PENDING_E` for a configurable number of iterations:
|
||||
crypto delays by returning `WC_PENDING_E` for a configurable number of iterations.
|
||||
The simulated device keeps a job table keyed by the request, like a hardware
|
||||
crypto manager: a request pends `TEST_PEND_COUNT` times (default 2) and the
|
||||
next re-invocation with identical arguments completes it. On TLS 1.3 every supported
|
||||
operation class pends (HKDF, AES-GCM, ECC/X25519 key generation and shared
|
||||
secret, ECDSA/Ed25519 sign and verify), including mutual authentication. On
|
||||
TLS 1.2 (`--tls12`) only the RSA and ECDSA signing set pends; the TLS 1.2 state
|
||||
machines do not resume the other classes.
|
||||
```
|
||||
make -C examples/async ASYNC_MODE=cryptocb
|
||||
```
|
||||
|
|
@ -68,7 +75,7 @@ Define `NET_USER_HEADER` to include your network shim and provide the
|
|||
|
||||
## Asynchronous Cryptography Design
|
||||
|
||||
When a cryptographic call is handed off to hardware it return `WC_PENDING_E` up to caller. Then it can keep calling until the operation completes. For some platforms it is required to call `wolfSSL_AsyncPoll`. At the TLS layer a "devId" (Device ID) must be set using `wolfSSL_CTX_SetDevId` to indicate desire to offload cryptography.
|
||||
When a cryptographic call is handed off to hardware, `WC_PENDING_E` is returned up to the caller, which keeps calling until the operation completes. For some platforms it is required to call `wolfSSL_AsyncPoll`. At the TLS layer a "devId" (Device ID) must be set using `wolfSSL_CTX_SetDevId` to indicate the desire to offload cryptography.
|
||||
|
||||
For further design details please see: https://github.com/wolfSSL/wolfAsyncCrypt#design
|
||||
|
||||
|
|
|
|||
|
|
@ -252,8 +252,11 @@ int client_async_test(int argc, char** argv)
|
|||
AsyncTlsCryptoCbCtx cryptoCbCtx;
|
||||
#endif
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
static byte memory[300000];
|
||||
static byte memoryIO[34500];
|
||||
/* Sized for a TLS 1.3 mutual-auth handshake with every supported
|
||||
* operation class pending: suspended verifies during mutual auth raise
|
||||
* the bucket high-water mark well above the synchronous footprint. */
|
||||
static byte memory[800000];
|
||||
static byte memoryIO[64000];
|
||||
#if !defined(WOLFSSL_STATIC_MEMORY_LEAN)
|
||||
WOLFSSL_MEM_CONN_STATS ssl_stats;
|
||||
#endif
|
||||
|
|
@ -304,6 +307,7 @@ int client_async_test(int argc, char** argv)
|
|||
if (devId == INVALID_DEVID)
|
||||
devId = 1;
|
||||
XMEMSET(&cryptoCbCtx, 0, sizeof(cryptoCbCtx));
|
||||
cryptoCbCtx.tls12 = tls12;
|
||||
if (wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &cryptoCbCtx) != 0) {
|
||||
fprintf(stderr, "ERROR: wc_CryptoCb_RegisterDevice failed\n");
|
||||
goto out;
|
||||
|
|
@ -567,6 +571,10 @@ int client_async_test(int argc, char** argv)
|
|||
#ifdef WOLFSSL_DEBUG_NONBLOCK
|
||||
printf("WANT_READ/WRITE count: %d\n", wouldblock_count);
|
||||
printf("WC_PENDING_E count: %d\n", pending_count);
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
printf("Device WC_PENDING_E returns: %d (table-full completions: %d)\n",
|
||||
cryptoCbCtx.pendingCount, cryptoCbCtx.jobFullCount);
|
||||
#endif
|
||||
#endif
|
||||
ret = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -212,8 +212,11 @@ int server_async_test(int argc, char** argv)
|
|||
AsyncTlsCryptoCbCtx cryptoCbCtx;
|
||||
#endif
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
static byte memory[300000];
|
||||
static byte memoryIO[34500];
|
||||
/* Sized for a TLS 1.3 mutual-auth handshake with every supported
|
||||
* operation class pending: suspended verifies during mutual auth raise
|
||||
* the bucket high-water mark well above the synchronous footprint. */
|
||||
static byte memory[800000];
|
||||
static byte memoryIO[64000];
|
||||
#if !defined(WOLFSSL_STATIC_MEMORY_LEAN)
|
||||
WOLFSSL_MEM_CONN_STATS ssl_stats;
|
||||
#endif
|
||||
|
|
@ -311,6 +314,7 @@ int server_async_test(int argc, char** argv)
|
|||
if (devId == INVALID_DEVID)
|
||||
devId = 1;
|
||||
XMEMSET(&cryptoCbCtx, 0, sizeof(cryptoCbCtx));
|
||||
cryptoCbCtx.tls12 = tls12;
|
||||
if (wc_CryptoCb_RegisterDevice(devId, AsyncTlsCryptoCb, &cryptoCbCtx) != 0) {
|
||||
fprintf(stderr, "ERROR: wc_CryptoCb_RegisterDevice failed\n");
|
||||
goto exit;
|
||||
|
|
@ -666,6 +670,10 @@ int server_async_test(int argc, char** argv)
|
|||
#ifdef WOLFSSL_DEBUG_NONBLOCK
|
||||
printf("WANT_READ/WRITE count: %d\n", wouldblock_count);
|
||||
printf("WC_PENDING_E count: %d\n", pending_count);
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
printf("Device WC_PENDING_E returns: %d (table-full completions: %d)\n",
|
||||
cryptoCbCtx.pendingCount, cryptoCbCtx.jobFullCount);
|
||||
#endif
|
||||
#endif
|
||||
ret = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,78 @@ int posix_getdevrandom(unsigned char *out, unsigned int sz)
|
|||
#define TEST_PEND_COUNT 2
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* Return 1 to simulate WC_PENDING_E. A request (hash of wc_CryptoInfo)
|
||||
* pends TEST_PEND_COUNT times and completes on re-invocation, like a
|
||||
* hardware crypto manager job table. A full table completes requests
|
||||
* synchronously (jobFullCount records the degradation). */
|
||||
static int AsyncTlsCryptoCbPend(AsyncTlsCryptoCbCtx* myCtx,
|
||||
wc_CryptoInfo* info)
|
||||
{
|
||||
unsigned long h = 5381;
|
||||
const unsigned char* b = (const unsigned char*)info;
|
||||
size_t i;
|
||||
int simulate = 0;
|
||||
|
||||
/* TLS 1.3 resumes every class below; TLS 1.2 only retries the
|
||||
* signing set, so restrict when the app selected TLS 1.2. */
|
||||
if (myCtx->tls12) {
|
||||
if (info->algo_type == WC_ALGO_TYPE_PK) {
|
||||
simulate = (info->pk.type == WC_PK_TYPE_RSA ||
|
||||
info->pk.type == WC_PK_TYPE_ECDSA_SIGN);
|
||||
}
|
||||
}
|
||||
else if (info->algo_type == WC_ALGO_TYPE_PK) {
|
||||
simulate = (info->pk.type == WC_PK_TYPE_RSA ||
|
||||
info->pk.type == WC_PK_TYPE_EC_KEYGEN ||
|
||||
info->pk.type == WC_PK_TYPE_ECDSA_SIGN ||
|
||||
info->pk.type == WC_PK_TYPE_ECDSA_VERIFY ||
|
||||
info->pk.type == WC_PK_TYPE_ECDH ||
|
||||
info->pk.type == WC_PK_TYPE_CURVE25519_KEYGEN ||
|
||||
info->pk.type == WC_PK_TYPE_CURVE25519 ||
|
||||
info->pk.type == WC_PK_TYPE_ED25519_SIGN ||
|
||||
info->pk.type == WC_PK_TYPE_ED25519_VERIFY);
|
||||
}
|
||||
else if (info->algo_type == WC_ALGO_TYPE_KDF) {
|
||||
simulate = 1; /* TLS 1.3 HKDF key schedule */
|
||||
}
|
||||
else if (info->algo_type == WC_ALGO_TYPE_CIPHER) {
|
||||
simulate = (info->cipher.type == WC_CIPHER_AES_GCM);
|
||||
}
|
||||
if (!simulate)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < sizeof(*info); i++)
|
||||
h = (h * 33) + b[i];
|
||||
|
||||
for (i = 0; i < (size_t)myCtx->jobCount; i++) {
|
||||
if (myCtx->jobHash[i] == h) {
|
||||
myCtx->jobTries[i]++;
|
||||
if (myCtx->jobTries[i] <= TEST_PEND_COUNT) {
|
||||
myCtx->pendingCount++;
|
||||
return 1; /* still pending */
|
||||
}
|
||||
/* complete: remove job and run the operation below */
|
||||
myCtx->jobCount--;
|
||||
myCtx->jobHash[i] = myCtx->jobHash[myCtx->jobCount];
|
||||
myCtx->jobTries[i] = myCtx->jobTries[myCtx->jobCount];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (myCtx->jobCount >= ASYNC_TLS_PEND_JOBS) {
|
||||
/* Full (non-identical retries strand entries): complete
|
||||
* synchronously and count the degradation. */
|
||||
myCtx->jobFullCount++;
|
||||
return 0;
|
||||
}
|
||||
myCtx->jobHash[myCtx->jobCount] = h;
|
||||
myCtx->jobTries[myCtx->jobCount] = 1;
|
||||
myCtx->jobCount++;
|
||||
myCtx->pendingCount++;
|
||||
return 1;
|
||||
}
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT */
|
||||
|
||||
/* Example crypto dev callback function that calls software version */
|
||||
/* This is where you would plug-in calls to your own hardware crypto */
|
||||
int AsyncTlsCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
|
|
@ -169,32 +241,20 @@ int AsyncTlsCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
|||
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); /* bypass HW by default */
|
||||
AsyncTlsCryptoCbCtx* myCtx = (AsyncTlsCryptoCbCtx*)ctx;
|
||||
|
||||
if (info == NULL)
|
||||
if (info == NULL || myCtx == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef DEBUG_CRYPTOCB
|
||||
wc_CryptoCb_InfoString(info);
|
||||
#endif
|
||||
|
||||
if (info->algo_type == WC_ALGO_TYPE_PK) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* Simulate async pending for RSA and ECC signing operations.
|
||||
* This matches a typical hardware crypto scenario (e.g., TPM) where
|
||||
* only signing is offloaded to hardware. Keygen, verify, and ECDH
|
||||
* are performed synchronously in software.
|
||||
* Note: WOLFSSL_ASYNC_CRYPT + WOLF_CRYPTO_CB pending simulation
|
||||
* requires operations whose TLS state machines properly handle retry
|
||||
* via wolfSSL_AsyncPop. ECC keygen in TLSX_KeyShare_GenEccKey does
|
||||
* not support this because the keygen call is inside the key
|
||||
* allocation guard (kse->key == NULL) which is skipped on retry. */
|
||||
if (info->pk.type == WC_PK_TYPE_RSA ||
|
||||
info->pk.type == WC_PK_TYPE_ECDSA_SIGN)
|
||||
{
|
||||
if (myCtx->pendingCount++ < TEST_PEND_COUNT) return WC_PENDING_E;
|
||||
myCtx->pendingCount = 0;
|
||||
}
|
||||
if (AsyncTlsCryptoCbPend(myCtx, info)) {
|
||||
return WC_PENDING_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (info->algo_type == WC_ALGO_TYPE_PK) {
|
||||
#ifndef NO_RSA
|
||||
if (info->pk.type == WC_PK_TYPE_RSA) {
|
||||
/* set devId to invalid, so software is used */
|
||||
|
|
|
|||
|
|
@ -46,8 +46,23 @@ typedef struct wc_CryptoInfo wc_CryptoInfo;
|
|||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Example custom context for crypto callback */
|
||||
/* Max simultaneous simulated pending requests (device job table) */
|
||||
#ifndef ASYNC_TLS_PEND_JOBS
|
||||
#define ASYNC_TLS_PEND_JOBS 64
|
||||
#endif
|
||||
typedef struct {
|
||||
int pendingCount; /* track pending tries test count */
|
||||
int pendingCount; /* total WC_PENDING_E returns (statistic) */
|
||||
/* Simulated device job table. A pended request is identified by a
|
||||
* hash of its wc_CryptoInfo so the re-invocation with identical
|
||||
* arguments can be matched and completed. */
|
||||
unsigned long jobHash[ASYNC_TLS_PEND_JOBS];
|
||||
int jobTries[ASYNC_TLS_PEND_JOBS];
|
||||
int jobCount;
|
||||
int jobFullCount; /* requests completed synchronously: table full */
|
||||
/* Set by the application when TLS 1.2 was selected: restricts the
|
||||
* simulated pending to the operations the TLS 1.2 state machines can
|
||||
* retry. TLS 1.3 (0, the default) pends every supported class. */
|
||||
int tls12;
|
||||
} AsyncTlsCryptoCbCtx;
|
||||
int AsyncTlsCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx);
|
||||
#endif /* WOLF_CRYPTO_CB */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
25
src/ssl.c
25
src/ssl.c
|
|
@ -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
155
src/tls.c
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
1062
src/tls13.c
1062
src/tls13.c
File diff suppressed because it is too large
Load Diff
|
|
@ -11241,3 +11241,374 @@ int test_tls13_is_init_finished_want_write(void)
|
|||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_TLS13) && defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_ASYNC_REINVOKE) && \
|
||||
defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
|
||||
#define TEST_TLS13_CB_PEND_DEVID_C 1
|
||||
#define TEST_TLS13_CB_PEND_DEVID_S 2
|
||||
#define TEST_TLS13_CB_PEND_JOBS 64
|
||||
|
||||
/* Which class of operation the callback pends. */
|
||||
enum TestTls13PendTarget {
|
||||
TEST_TLS13_PEND_AESGCM,
|
||||
TEST_TLS13_PEND_ECC_KEYGEN,
|
||||
TEST_TLS13_PEND_ECDSA_SIGN,
|
||||
TEST_TLS13_PEND_ECDSA_VERIFY,
|
||||
TEST_TLS13_PEND_KDF,
|
||||
TEST_TLS13_PEND_HMAC
|
||||
};
|
||||
|
||||
typedef struct TestTls13PendCtx {
|
||||
/* Job table keyed by request: first sight queues and pends, the
|
||||
* identical re-invocation completes (falls through to software). */
|
||||
unsigned long jobs[TEST_TLS13_CB_PEND_JOBS];
|
||||
int jobCount;
|
||||
int target; /* enum TestTls13PendTarget */
|
||||
int pended; /* WC_PENDING_E results issued; asserted non-zero */
|
||||
int seen; /* matching requests observed; asserted non-zero */
|
||||
} TestTls13PendCtx;
|
||||
|
||||
static int TestTls13PendMatches(int target, wc_CryptoInfo* info)
|
||||
{
|
||||
int match = 0;
|
||||
|
||||
switch (target) {
|
||||
#ifndef WOLF_CRYPTO_CB_ASYNC_POLL
|
||||
/* With WOLF_CRYPTO_CB_ASYNC_POLL the record ciphers follow the
|
||||
* poll-completion contract instead of re-invocation; that model is
|
||||
* covered by tests/api/test_async.c. */
|
||||
case TEST_TLS13_PEND_AESGCM:
|
||||
match = (info->algo_type == WC_ALGO_TYPE_CIPHER) &&
|
||||
(info->cipher.type == WC_CIPHER_AES_GCM);
|
||||
break;
|
||||
#endif
|
||||
case TEST_TLS13_PEND_ECC_KEYGEN:
|
||||
match = (info->algo_type == WC_ALGO_TYPE_PK) &&
|
||||
(info->pk.type == WC_PK_TYPE_EC_KEYGEN);
|
||||
break;
|
||||
case TEST_TLS13_PEND_ECDSA_SIGN:
|
||||
match = (info->algo_type == WC_ALGO_TYPE_PK) &&
|
||||
(info->pk.type == WC_PK_TYPE_ECDSA_SIGN);
|
||||
break;
|
||||
case TEST_TLS13_PEND_ECDSA_VERIFY:
|
||||
match = (info->algo_type == WC_ALGO_TYPE_PK) &&
|
||||
(info->pk.type == WC_PK_TYPE_ECDSA_VERIFY);
|
||||
break;
|
||||
case TEST_TLS13_PEND_KDF:
|
||||
match = (info->algo_type == WC_ALGO_TYPE_KDF);
|
||||
break;
|
||||
case TEST_TLS13_PEND_HMAC:
|
||||
match = (info->algo_type == WC_ALGO_TYPE_HMAC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/* Request fingerprint over the whole info struct: op class, sizes, pointers
|
||||
* and inline content distinguish interleaved requests. */
|
||||
static unsigned long TestTls13PendHash(wc_CryptoInfo* info)
|
||||
{
|
||||
unsigned long h = 5381;
|
||||
const unsigned char* b = (const unsigned char*)info;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(*info); i++)
|
||||
h = h * 33 + b[i];
|
||||
return h;
|
||||
}
|
||||
|
||||
static int TestTls13PendCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
||||
{
|
||||
TestTls13PendCtx* c = (TestTls13PendCtx*)ctx;
|
||||
unsigned long h;
|
||||
int i;
|
||||
|
||||
(void)devIdArg;
|
||||
|
||||
if (info == NULL || c == NULL)
|
||||
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
#if defined(HAVE_HKDF) && !defined(NO_HMAC) && !defined(HAVE_SELFTEST) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
|
||||
if (c->target == TEST_TLS13_PEND_HMAC &&
|
||||
info->algo_type == WC_ALGO_TYPE_KDF) {
|
||||
/* Serve the key schedule synchronously in software; falling back
|
||||
* with the devId set would route its internal HMACs back here and
|
||||
* those cannot resume (see wolfcrypt/src/hmac.c). Only the
|
||||
* TLS-layer transcript HMACs are left to pend. */
|
||||
if (info->kdf.type == WC_KDF_TYPE_HKDF_EXTRACT) {
|
||||
return wc_HKDF_Extract_ex(info->kdf.hkdf_extract.hashType,
|
||||
info->kdf.hkdf_extract.salt, info->kdf.hkdf_extract.saltSz,
|
||||
info->kdf.hkdf_extract.inKey, info->kdf.hkdf_extract.inKeySz,
|
||||
info->kdf.hkdf_extract.out, NULL, INVALID_DEVID);
|
||||
}
|
||||
if (info->kdf.type == WC_KDF_TYPE_HKDF_EXPAND) {
|
||||
return wc_HKDF_Expand_ex(info->kdf.hkdf_expand.hashType,
|
||||
info->kdf.hkdf_expand.inKey, info->kdf.hkdf_expand.inKeySz,
|
||||
info->kdf.hkdf_expand.info, info->kdf.hkdf_expand.infoSz,
|
||||
info->kdf.hkdf_expand.out, info->kdf.hkdf_expand.outSz,
|
||||
NULL, INVALID_DEVID);
|
||||
}
|
||||
if (info->kdf.type == WC_KDF_TYPE_HKDF) {
|
||||
return wc_HKDF_ex(info->kdf.hkdf.hashType,
|
||||
info->kdf.hkdf.inKey, info->kdf.hkdf.inKeySz,
|
||||
info->kdf.hkdf.salt, info->kdf.hkdf.saltSz,
|
||||
info->kdf.hkdf.info, info->kdf.hkdf.infoSz,
|
||||
info->kdf.hkdf.out, info->kdf.hkdf.outSz,
|
||||
NULL, INVALID_DEVID);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!TestTls13PendMatches(c->target, info))
|
||||
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
|
||||
c->seen++;
|
||||
h = TestTls13PendHash(info);
|
||||
for (i = 0; i < c->jobCount; i++) {
|
||||
if (c->jobs[i] == h) {
|
||||
/* Re-invocation of a pended request: complete it. */
|
||||
c->jobs[i] = c->jobs[--c->jobCount];
|
||||
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
if (c->jobCount < TEST_TLS13_CB_PEND_JOBS) {
|
||||
c->jobs[c->jobCount++] = h;
|
||||
c->pended++;
|
||||
return WC_PENDING_E;
|
||||
}
|
||||
|
||||
return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
|
||||
}
|
||||
|
||||
/* wolfSSL_write()/wolfSSL_read() can return WC_PENDING_E just as the
|
||||
* handshake does; drive them with the poll-and-retry loop the application is
|
||||
* expected to use. Returns the byte count, or the error. */
|
||||
static int TestTls13PendWrite(WOLFSSL* ssl, const char* buf, int sz)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
int rounds = 0;
|
||||
|
||||
do {
|
||||
ret = wolfSSL_write(ssl, buf, sz);
|
||||
if (ret > 0)
|
||||
break;
|
||||
err = wolfSSL_get_error(ssl, ret);
|
||||
if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
if (wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW) < 0)
|
||||
return -1;
|
||||
}
|
||||
else if (err != WOLFSSL_ERROR_WANT_READ &&
|
||||
err != WOLFSSL_ERROR_WANT_WRITE) {
|
||||
return ret;
|
||||
}
|
||||
} while (++rounds < 100);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int TestTls13PendRead(WOLFSSL* ssl, char* buf, int sz)
|
||||
{
|
||||
int ret;
|
||||
int err;
|
||||
int rounds = 0;
|
||||
|
||||
do {
|
||||
ret = wolfSSL_read(ssl, buf, sz);
|
||||
if (ret > 0)
|
||||
break;
|
||||
err = wolfSSL_get_error(ssl, ret);
|
||||
if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
if (wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW) < 0)
|
||||
return -1;
|
||||
}
|
||||
else if (err != WOLFSSL_ERROR_WANT_READ &&
|
||||
err != WOLFSSL_ERROR_WANT_WRITE) {
|
||||
return ret;
|
||||
}
|
||||
} while (++rounds < 100);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* One TLS 1.3 handshake with the given operation class pending on both sides,
|
||||
* then application data both ways so records queued after the handshake are
|
||||
* parsed by the peer as well. */
|
||||
static int test_tls13_cryptocb_pend_one(int target, int mutual)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
WOLFSSL_CTX* ctx_c = NULL;
|
||||
WOLFSSL_CTX* ctx_s = NULL;
|
||||
WOLFSSL* ssl_c = NULL;
|
||||
WOLFSSL* ssl_s = NULL;
|
||||
TestTls13PendCtx cliCtx;
|
||||
TestTls13PendCtx srvCtx;
|
||||
struct test_memio_ctx memio;
|
||||
const char msg[] = "hello over TLS 1.3";
|
||||
char buf[64];
|
||||
|
||||
XMEMSET(&cliCtx, 0, sizeof(cliCtx));
|
||||
XMEMSET(&srvCtx, 0, sizeof(srvCtx));
|
||||
XMEMSET(&memio, 0, sizeof(memio));
|
||||
cliCtx.target = target;
|
||||
srvCtx.target = target;
|
||||
|
||||
ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_TLS13_CB_PEND_DEVID_C,
|
||||
TestTls13PendCb, &cliCtx), 0);
|
||||
ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_TLS13_CB_PEND_DEVID_S,
|
||||
TestTls13PendCb, &srvCtx), 0);
|
||||
|
||||
/* devId set on the CTX before credentials and SSL objects so all of
|
||||
* it inherits the devId. ECC credentials: an RSA key under a devId
|
||||
* would be treated as device-held. */
|
||||
ExpectNotNull(ctx_c = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
||||
ExpectNotNull(ctx_s = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
||||
ExpectIntEQ(wolfSSL_CTX_SetDevId(ctx_c, TEST_TLS13_CB_PEND_DEVID_C),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_CTX_SetDevId(ctx_s, TEST_TLS13_CB_PEND_DEVID_S),
|
||||
WOLFSSL_SUCCESS);
|
||||
#ifdef HAVE_AESGCM
|
||||
if (target == TEST_TLS13_PEND_AESGCM) {
|
||||
/* Pin the AEAD so the pend assertion cannot depend on suite
|
||||
* preference ordering. */
|
||||
ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx_c,
|
||||
"TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_CTX_set_cipher_list(ctx_s,
|
||||
"TLS13-AES128-GCM-SHA256"), WOLFSSL_SUCCESS);
|
||||
}
|
||||
#endif
|
||||
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_c,
|
||||
"./certs/ca-ecc-cert.pem", 0), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx_s,
|
||||
"./certs/server-ecc.pem"), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_s, "./certs/ecc-key.pem",
|
||||
WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS);
|
||||
if (mutual) {
|
||||
/* Mutual auth: pending verifies of the client's chain and CV
|
||||
* cover the received-marker restores. */
|
||||
ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx_c,
|
||||
"./certs/client-ecc-cert.pem"), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_c,
|
||||
"./certs/ecc-client-key.pem", WOLFSSL_FILETYPE_PEM),
|
||||
WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_s,
|
||||
"./certs/client-ecc-cert.pem", 0), WOLFSSL_SUCCESS);
|
||||
wolfSSL_CTX_set_verify(ctx_s, WOLFSSL_VERIFY_PEER |
|
||||
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
||||
}
|
||||
|
||||
ExpectNotNull(ssl_c = wolfSSL_new(ctx_c));
|
||||
ExpectNotNull(ssl_s = wolfSSL_new(ctx_s));
|
||||
|
||||
/* Pin the group so every run negotiates the same way; the default offer
|
||||
* can trigger HelloRetryRequest or a PQC key share, which are separate
|
||||
* scenarios from the pend-resume paths this test covers. */
|
||||
if (EXPECT_SUCCESS()) {
|
||||
int groups[1];
|
||||
groups[0] = WOLFSSL_ECC_SECP256R1;
|
||||
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 1), WOLFSSL_SUCCESS);
|
||||
ExpectIntEQ(wolfSSL_set_groups(ssl_s, groups, 1), WOLFSSL_SUCCESS);
|
||||
}
|
||||
|
||||
/* The shared memio transport; its TLS path serves a byte stream, so
|
||||
* the re-read patterns of pending crypto operations cannot desync it. */
|
||||
if (EXPECT_SUCCESS()) {
|
||||
wolfSSL_SSLSetIORecv(ssl_c, test_memio_read_cb);
|
||||
wolfSSL_SSLSetIOSend(ssl_c, test_memio_write_cb);
|
||||
wolfSSL_SSLSetIORecv(ssl_s, test_memio_read_cb);
|
||||
wolfSSL_SSLSetIOSend(ssl_s, test_memio_write_cb);
|
||||
wolfSSL_SetIOReadCtx(ssl_c, &memio);
|
||||
wolfSSL_SetIOWriteCtx(ssl_c, &memio);
|
||||
wolfSSL_SetIOReadCtx(ssl_s, &memio);
|
||||
wolfSSL_SetIOWriteCtx(ssl_s, &memio);
|
||||
}
|
||||
|
||||
/* Generous rounds: pending every KDF request costs one poll-and-retry
|
||||
* round trip per operation, and a TLS 1.3 handshake with session tickets
|
||||
* runs a couple of hundred of them. */
|
||||
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 600, NULL), 0);
|
||||
|
||||
/* Assert per-side pends so the test cannot pass without exercising a
|
||||
* resume path; the client signs nothing unless mutual. */
|
||||
ExpectIntGT(srvCtx.seen, 0);
|
||||
ExpectIntGT(srvCtx.pended, 0);
|
||||
if (mutual || target != TEST_TLS13_PEND_ECDSA_SIGN) {
|
||||
ExpectIntGT(cliCtx.seen, 0);
|
||||
ExpectIntGT(cliCtx.pended, 0);
|
||||
}
|
||||
|
||||
ExpectIntEQ(TestTls13PendWrite(ssl_c, msg, (int)sizeof(msg)),
|
||||
(int)sizeof(msg));
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
ExpectIntEQ(TestTls13PendRead(ssl_s, buf, (int)sizeof(buf)),
|
||||
(int)sizeof(msg));
|
||||
ExpectIntEQ(XMEMCMP(buf, msg, sizeof(msg)), 0);
|
||||
|
||||
ExpectIntEQ(TestTls13PendWrite(ssl_s, msg, (int)sizeof(msg)),
|
||||
(int)sizeof(msg));
|
||||
XMEMSET(buf, 0, sizeof(buf));
|
||||
ExpectIntEQ(TestTls13PendRead(ssl_c, buf, (int)sizeof(buf)),
|
||||
(int)sizeof(msg));
|
||||
ExpectIntEQ(XMEMCMP(buf, msg, sizeof(msg)), 0);
|
||||
|
||||
wolfSSL_free(ssl_c);
|
||||
wolfSSL_free(ssl_s);
|
||||
wolfSSL_CTX_free(ctx_c);
|
||||
wolfSSL_CTX_free(ctx_s);
|
||||
wc_CryptoCb_UnRegisterDevice(TEST_TLS13_CB_PEND_DEVID_C);
|
||||
wc_CryptoCb_UnRegisterDevice(TEST_TLS13_CB_PEND_DEVID_S);
|
||||
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
#endif /* guards */
|
||||
|
||||
/* Drive TLS 1.3 handshakes and application data with the poll-and-retry
|
||||
* loop while a crypto callback pends each matching request. */
|
||||
int test_tls13_cryptocb_async(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_TLS13) && defined(WOLF_CRYPTO_CB) && \
|
||||
defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_ASYNC_REINVOKE) && \
|
||||
defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) && \
|
||||
defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
#if defined(HAVE_AESGCM) && !defined(WOLF_CRYPTO_CB_ASYNC_POLL)
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_AESGCM, 0),
|
||||
TEST_SUCCESS);
|
||||
#endif
|
||||
#ifdef HAVE_ECC
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_ECC_KEYGEN, 0),
|
||||
TEST_SUCCESS);
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_ECDSA_SIGN, 0),
|
||||
TEST_SUCCESS);
|
||||
/* Mutual auth with pending verifies: regression for the msgsReceived
|
||||
* marker restores (a pended Certificate/CertificateVerify replay used
|
||||
* to leave its marker clear and fail Finished with OUT_OF_ORDER_E). */
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_ECDSA_VERIFY, 1),
|
||||
TEST_SUCCESS);
|
||||
#endif
|
||||
#if defined(HAVE_HKDF) && !defined(NO_HMAC)
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_KDF, 0),
|
||||
TEST_SUCCESS);
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_KDF, 1),
|
||||
TEST_SUCCESS);
|
||||
#if !defined(HAVE_SELFTEST) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
|
||||
/* Transcript HMACs (Finished verify_data) pending on both sides. */
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_HMAC, 0),
|
||||
TEST_SUCCESS);
|
||||
ExpectIntEQ(test_tls13_cryptocb_pend_one(TEST_TLS13_PEND_HMAC, 1),
|
||||
TEST_SUCCESS);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ int test_tls13_pqc_hybrid_async_server(void);
|
|||
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);
|
||||
|
||||
#define TEST_TLS13_DECLS \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_apis), \
|
||||
|
|
@ -241,6 +242,7 @@ int test_tls13_is_init_finished_want_write(void);
|
|||
TEST_DECL_GROUP("tls13", test_tls13_pqc_hybrid_async_server), \
|
||||
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_is_init_finished_want_write), \
|
||||
TEST_DECL_GROUP("tls13", test_tls13_cryptocb_async)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_TLS13_H */
|
||||
|
|
|
|||
|
|
@ -129,7 +129,44 @@ int test_memio_read_cb(WOLFSSL *ssl, char *data, int sz, void *ctx)
|
|||
if (*len == 0 || *msg_pos >= *msg_count)
|
||||
return WOLFSSL_CBIO_ERR_WANT_READ;
|
||||
|
||||
/* Calculate how much we can read from current message */
|
||||
if (!is_dtls) {
|
||||
/* TLS is a byte stream: serve across message boundaries so
|
||||
* pending-crypto re-read patterns cannot desync the slots. */
|
||||
int rem;
|
||||
|
||||
read_sz = *len;
|
||||
if (read_sz > sz)
|
||||
read_sz = sz;
|
||||
|
||||
XMEMCPY(data, buf, (size_t)read_sz);
|
||||
XMEMMOVE(buf, buf + read_sz, (size_t)(*len - read_sz));
|
||||
*len -= read_sz;
|
||||
|
||||
rem = read_sz;
|
||||
while (rem > 0 && *msg_pos < *msg_count) {
|
||||
if (msg_sizes[*msg_pos] > rem) {
|
||||
msg_sizes[*msg_pos] -= rem;
|
||||
rem = 0;
|
||||
}
|
||||
else {
|
||||
rem -= msg_sizes[*msg_pos];
|
||||
msg_sizes[*msg_pos] = 0;
|
||||
(*msg_pos)++;
|
||||
}
|
||||
}
|
||||
if (rem != 0) {
|
||||
/* Slot accounting desynced from the byte count; fail loudly. */
|
||||
return WOLFSSL_CBIO_ERR_GENERAL;
|
||||
}
|
||||
if (*msg_pos >= *msg_count && *len == 0) {
|
||||
*msg_pos = 0;
|
||||
*msg_count = 0;
|
||||
}
|
||||
|
||||
return read_sz;
|
||||
}
|
||||
|
||||
/* DTLS: datagram boundaries matter, serve one message at a time. */
|
||||
read_sz = msg_sizes[*msg_pos];
|
||||
if (read_sz > sz)
|
||||
read_sz = sz;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1774,6 +1774,26 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
}
|
||||
|
||||
#ifdef HAVE_HKDF
|
||||
/* Wait out an async HMAC sub-op: the HKDF loops cannot resume
|
||||
* mid-chain. QAT/Cavium only (not covered by CI); a crypto callback
|
||||
* pending must instead propagate so the caller can re-invoke. */
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) && \
|
||||
(defined(HAVE_INTEL_QA) || defined(HAVE_CAVIUM))
|
||||
/* QAT/Cavium only: WOLFSSL_ASYNC_REINVOKE is never defined for these
|
||||
* backends (see internal.h), so an HKDF sub-op can only pend on the
|
||||
* hardware device, never on a re-invokable crypto callback. Wait
|
||||
* unconditionally: the HKDF loops cannot resume mid-chain. */
|
||||
#define HKDF_HMAC_WAIT(ret, hmac) \
|
||||
do { \
|
||||
(ret) = wc_AsyncWait((ret), &(hmac)->asyncDev, \
|
||||
WC_ASYNC_FLAG_NONE); \
|
||||
} while (0)
|
||||
#else
|
||||
/* No HMAC device to wait on, or the pending must reach the caller
|
||||
* (crypto callback re-invocation); hmac is unevaluated. */
|
||||
#define HKDF_HMAC_WAIT(ret, hmac) WC_DO_NOTHING
|
||||
#endif
|
||||
|
||||
/* HMAC-KDF-Extract.
|
||||
* RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF).
|
||||
*
|
||||
|
|
@ -1799,7 +1819,9 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
}
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Try crypto callback first */
|
||||
/* Try crypto callback first. Only CRYPTOCB_UNAVAILABLE falls back
|
||||
* to software. WC_PENDING_E is returned as-is: the caller polls,
|
||||
* re-invoking with identical arguments until it clears. */
|
||||
if (devId != INVALID_DEVID) {
|
||||
ret = wc_CryptoCb_Hkdf_Extract(type, salt, saltSz, inKey, inKeySz,
|
||||
out, devId);
|
||||
|
|
@ -1832,10 +1854,14 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
#else
|
||||
ret = wc_HmacSetKey(myHmac, type, localSalt, saltSz);
|
||||
#endif
|
||||
if (ret == 0)
|
||||
if (ret == 0) {
|
||||
ret = wc_HmacUpdate(myHmac, inKey, inKeySz);
|
||||
if (ret == 0)
|
||||
HKDF_HMAC_WAIT(ret, myHmac);
|
||||
}
|
||||
if (ret == 0) {
|
||||
ret = wc_HmacFinal(myHmac, out);
|
||||
HKDF_HMAC_WAIT(ret, myHmac);
|
||||
}
|
||||
wc_HmacFree(myHmac);
|
||||
}
|
||||
WC_FREE_VAR_EX(myHmac, NULL, DYNAMIC_TYPE_HMAC);
|
||||
|
|
@ -1891,7 +1917,8 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
return BAD_FUNC_ARG;
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Try crypto callback first for complete operation */
|
||||
/* Try crypto callback first. WC_PENDING_E is returned to the
|
||||
* caller to poll, as in wc_HKDF_Extract_ex(). */
|
||||
if (devId != INVALID_DEVID) {
|
||||
ret = wc_CryptoCb_Hkdf_Expand(type, inKey, inKeySz, info, infoSz,
|
||||
out, outSz, devId);
|
||||
|
|
@ -1927,15 +1954,19 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
if (ret != 0)
|
||||
break;
|
||||
ret = wc_HmacUpdate(myHmac, tmp, tmpSz);
|
||||
HKDF_HMAC_WAIT(ret, myHmac);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = wc_HmacUpdate(myHmac, info, infoSz);
|
||||
HKDF_HMAC_WAIT(ret, myHmac);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = wc_HmacUpdate(myHmac, &n, 1);
|
||||
HKDF_HMAC_WAIT(ret, myHmac);
|
||||
if (ret != 0)
|
||||
break;
|
||||
ret = wc_HmacFinal(myHmac, tmp);
|
||||
HKDF_HMAC_WAIT(ret, myHmac);
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
|
|
@ -1988,7 +2019,8 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
(void)devId; /* suppress unused parameter warning */
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB
|
||||
/* Try crypto callback first for complete operation */
|
||||
/* Try crypto callback first. WC_PENDING_E is returned to the
|
||||
* caller to poll, as in wc_HKDF_Extract_ex(). */
|
||||
if (devId != INVALID_DEVID) {
|
||||
ret = wc_CryptoCb_Hkdf(type, inKey, inKeySz, salt, saltSz, info,
|
||||
infoSz, out, outSz, devId);
|
||||
|
|
@ -2006,6 +2038,8 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
XMEMSET(prk, 0, WC_MAX_DIGEST_SIZE);
|
||||
wc_MemZero_Add("wc_HKDF_ex prk", prk, WC_MAX_DIGEST_SIZE);
|
||||
#endif
|
||||
/* Restartable, not resumable: the retry redoes extract, so a
|
||||
* device that pends must serve the repeat from its result. */
|
||||
ret = wc_HKDF_Extract_ex(type, salt, saltSz, inKey, inKeySz, prk, heap,
|
||||
devId);
|
||||
if (ret == 0) {
|
||||
|
|
@ -2027,6 +2061,8 @@ int wolfSSL_GetHmacMaxSize(void)
|
|||
outSz, NULL, INVALID_DEVID);
|
||||
}
|
||||
|
||||
#undef HKDF_HMAC_WAIT
|
||||
|
||||
#endif /* HAVE_HKDF */
|
||||
|
||||
#endif /* NO_HMAC */
|
||||
|
|
|
|||
|
|
@ -81415,6 +81415,10 @@ typedef struct {
|
|||
#if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD)
|
||||
int rsaPssVerifyCount; /* RSA-PSS verify callback invocations */
|
||||
#endif
|
||||
#if defined(HAVE_HKDF) && !defined(NO_HMAC)
|
||||
int hkdfPendArm; /* pend the next this-many HKDF callback calls */
|
||||
int hkdfPendCount; /* pends issued; test asserts non-zero */
|
||||
#endif
|
||||
} myCryptoDevCtx;
|
||||
|
||||
#ifdef WOLF_CRYPTO_CB_ONLY_RSA
|
||||
|
|
@ -85119,6 +85123,17 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
|
|||
#endif /* WOLFSSL_CMAC && !(NO_AES) && WOLFSSL_AES_DIRECT */
|
||||
else if (info->algo_type == WC_ALGO_TYPE_KDF) {
|
||||
#if defined(HAVE_HKDF) && !defined(NO_HMAC)
|
||||
/* Simulate a device that queues the request and completes it on a
|
||||
* later call, so the caller has to poll. */
|
||||
if (myCtx->hkdfPendArm > 0 &&
|
||||
(info->kdf.type == WC_KDF_TYPE_HKDF ||
|
||||
info->kdf.type == WC_KDF_TYPE_HKDF_EXTRACT ||
|
||||
info->kdf.type == WC_KDF_TYPE_HKDF_EXPAND)) {
|
||||
myCtx->hkdfPendArm--;
|
||||
myCtx->hkdfPendCount++;
|
||||
return WC_PENDING_E;
|
||||
}
|
||||
|
||||
if (info->kdf.type == WC_KDF_TYPE_HKDF) {
|
||||
/* Redirect to software implementation for testing */
|
||||
#if !defined(HAVE_SELFTEST) && \
|
||||
|
|
@ -85432,6 +85447,122 @@ static wc_test_ret_t shake_cb_copy_free_test(myCryptoDevCtx* myCtx,
|
|||
}
|
||||
#endif /* WOLFSSL_SHA3 && SHAKE && (CB_COPY || CB_FREE) */
|
||||
|
||||
#if defined(HAVE_HKDF) && !defined(NO_HMAC) && \
|
||||
!defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0)) && \
|
||||
!defined(WC_TEST_NO_CRYPTOCB_SW_TEST)
|
||||
|
||||
/* Bound retries so a broken contract fails instead of spinning. */
|
||||
#define HKDF_CB_MAX_POLL 16
|
||||
|
||||
/* Drive the HKDF crypto callbacks against a device that pends first: the
|
||||
* caller re-invokes with identical arguments until WC_PENDING_E clears.
|
||||
* Vectors are RFC 5869 appendix A.1 (test case 1, SHA-256). */
|
||||
static wc_test_ret_t hkdf_cryptocb_async_test(myCryptoDevCtx* ctx)
|
||||
{
|
||||
wc_test_ret_t ret = 0;
|
||||
int rc;
|
||||
int polls;
|
||||
byte prk[WC_SHA256_DIGEST_SIZE];
|
||||
byte okm[42];
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte ikm[22] = {
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte salt[13] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c };
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte info[10] = {
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9 };
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expectedPrk[WC_SHA256_DIGEST_SIZE]
|
||||
= {
|
||||
0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf,
|
||||
0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63,
|
||||
0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,
|
||||
0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5 };
|
||||
WOLFSSL_SMALL_STACK_STATIC const byte expected[42] = {
|
||||
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a,
|
||||
0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a,
|
||||
0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
|
||||
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf,
|
||||
0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18,
|
||||
0x58, 0x65 };
|
||||
|
||||
/* Three pends, so four passes: proves the caller loops, not retries
|
||||
* exactly once. */
|
||||
ctx->hkdfPendArm = 3;
|
||||
ctx->hkdfPendCount = 0;
|
||||
polls = 0;
|
||||
do {
|
||||
rc = wc_HKDF_Extract_ex(WC_SHA256, salt, (word32)sizeof(salt),
|
||||
ikm, (word32)sizeof(ikm), prk,
|
||||
HEAP_HINT, devId);
|
||||
polls++;
|
||||
} while (rc == WC_NO_ERR_TRACE(WC_PENDING_E) && polls < HKDF_CB_MAX_POLL);
|
||||
if (rc != 0)
|
||||
ret = WC_TEST_RET_ENC_EC(rc);
|
||||
else if (polls != 4)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
else if (XMEMCMP(prk, expectedPrk, sizeof(prk)) != 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
if (ret != 0)
|
||||
goto exit_hkdf_async;
|
||||
|
||||
/* Expand the PRK, pending three times as well. */
|
||||
ctx->hkdfPendArm = 3;
|
||||
ctx->hkdfPendCount = 0;
|
||||
polls = 0;
|
||||
do {
|
||||
rc = wc_HKDF_Expand_ex(WC_SHA256, prk, (word32)sizeof(prk),
|
||||
info, (word32)sizeof(info), okm,
|
||||
(word32)sizeof(okm), HEAP_HINT, devId);
|
||||
polls++;
|
||||
} while (rc == WC_NO_ERR_TRACE(WC_PENDING_E) && polls < HKDF_CB_MAX_POLL);
|
||||
if (rc != 0)
|
||||
ret = WC_TEST_RET_ENC_EC(rc);
|
||||
else if (polls != 4)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
else if (XMEMCMP(okm, expected, sizeof(okm)) != 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
if (ret != 0)
|
||||
goto exit_hkdf_async;
|
||||
|
||||
/* Same vector through the one-shot wc_HKDF_ex(). */
|
||||
XMEMSET(okm, 0, sizeof(okm));
|
||||
ctx->hkdfPendArm = 1;
|
||||
ctx->hkdfPendCount = 0;
|
||||
polls = 0;
|
||||
do {
|
||||
rc = wc_HKDF_ex(WC_SHA256, ikm, (word32)sizeof(ikm),
|
||||
salt, (word32)sizeof(salt),
|
||||
info, (word32)sizeof(info),
|
||||
okm, (word32)sizeof(okm), HEAP_HINT, devId);
|
||||
polls++;
|
||||
} while (rc == WC_NO_ERR_TRACE(WC_PENDING_E) && polls < HKDF_CB_MAX_POLL);
|
||||
if (rc != 0)
|
||||
ret = WC_TEST_RET_ENC_EC(rc);
|
||||
else if (polls != 2)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
else if (XMEMCMP(okm, expected, sizeof(okm)) != 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
/* Counter is reset per leg, so an earlier leg cannot satisfy this. */
|
||||
else if (ctx->hkdfPendCount == 0)
|
||||
ret = WC_TEST_RET_ENC_NC;
|
||||
|
||||
exit_hkdf_async:
|
||||
/* Disarm on every path, or a failing leg would leave the simulated
|
||||
* device injecting WC_PENDING_E into later HKDF requests. */
|
||||
ctx->hkdfPendArm = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef HKDF_CB_MAX_POLL
|
||||
|
||||
#endif /* HAVE_HKDF && !NO_HMAC && !NO_SHA256 && !HAVE_SELFTEST && ... */
|
||||
|
||||
|
||||
#if !defined(WC_TEST_NO_CRYPTOCB_SW_TEST)
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
||||
{
|
||||
|
|
@ -85465,6 +85596,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
|||
#if defined(WC_RSA_PSS) && defined(WOLF_CRYPTO_CB_RSA_PAD)
|
||||
myCtx.rsaPssVerifyCount = 0;
|
||||
#endif
|
||||
#if defined(HAVE_HKDF) && !defined(NO_HMAC)
|
||||
/* myCtx is uninitialized stack: a garbage arm would inject
|
||||
* WC_PENDING_E into callers that are not polling. */
|
||||
myCtx.hkdfPendArm = 0;
|
||||
myCtx.hkdfPendCount = 0;
|
||||
#endif
|
||||
|
||||
/* set devId to something other than INVALID_DEVID */
|
||||
devId = 1;
|
||||
|
|
@ -85945,6 +86082,11 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
|
|||
#if defined(HAVE_HKDF) && !defined(NO_HMAC)
|
||||
if (ret == 0)
|
||||
ret = hkdf_test();
|
||||
#if !defined(NO_SHA256) && !defined(HAVE_SELFTEST) && \
|
||||
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(7,0))
|
||||
if (ret == 0)
|
||||
ret = hkdf_cryptocb_async_test(&myCtx);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(HAVE_CMAC_KDF)
|
||||
if (ret == 0)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue