Fix non-blocking X25519/ECC with WOLFSSL_ASYNC_CRYPT_SW

The non-blocking setup for X25519 and ECC in TLS was unconditionally
setting up nbCtx, which caused functions to return FP_WOULDBLOCK. However,
with INVALID_DEVID (the default), TLS has no async loop to handle
FP_WOULDBLOCK, only WC_PENDING_E via the async framework.

The fix follows the pattern used in asn.c: only set up nbCtx when the async
device is active (devId != INVALID_DEVID). With INVALID_DEVID, the code now
uses the blocking fallback (WC_ECC_NONBLOCK_ONLY) instead.

This prevents unit test timeouts when built with --enable-curve25519=nonblock
or --enable-ecc=nonblock.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
David Garske
2026-02-09 09:22:36 -08:00
parent 19bb7198a2
commit 2a18b7ee44
2 changed files with 23 additions and 7 deletions
+12 -4
View File
@@ -8338,7 +8338,10 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId);
#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
defined(WC_ASYNC_ENABLE_ECC)
if (ret == 0) {
/* Only set non-blocking context when async device is active. With
* INVALID_DEVID there is no async loop to retry on FP_WOULDBLOCK, so
* let the WC_ECC_NONBLOCK_ONLY blocking fallback handle it instead. */
if (ret == 0 && ssl->devId != INVALID_DEVID) {
eccNbCtx = (ecc_nb_ctx_t*)XMALLOC(sizeof(ecc_nb_ctx_t),
eccKey->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (eccNbCtx == NULL) {
@@ -8365,8 +8368,12 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
case DYNAMIC_TYPE_CURVE25519:
x25519Key = (curve25519_key*)*pKey;
ret = wc_curve25519_init_ex(x25519Key, ssl->heap, ssl->devId);
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
if (ret == 0) {
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
defined(WC_ASYNC_ENABLE_X25519)
/* Only set non-blocking context when async device is active. With
* INVALID_DEVID there is no async loop to retry on FP_WOULDBLOCK, so
* skip non-blocking setup and use blocking mode instead. */
if (ret == 0 && ssl->devId != INVALID_DEVID) {
x25519NbCtx = (x25519_nb_ctx_t*)XMALLOC(sizeof(x25519_nb_ctx_t),
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (x25519NbCtx == NULL) {
@@ -8379,7 +8386,8 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
}
}
}
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW */
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
WC_ASYNC_ENABLE_X25519 */
break;
#endif /* HAVE_CURVE25519 */
#ifdef HAVE_ED448
+11 -3
View File
@@ -8008,8 +8008,12 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
key = (curve25519_key*)kse->key;
kse->keyLen = CURVE25519_KEYSIZE;
}
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
if (ret == 0) {
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
defined(WC_ASYNC_ENABLE_X25519)
/* Only set non-blocking context when async device is active. With
* INVALID_DEVID there is no async loop to retry on FP_WOULDBLOCK, so
* skip non-blocking setup and use blocking mode instead. */
if (ret == 0 && ssl->devId != INVALID_DEVID) {
x25519_nb_ctx_t* nbCtx = (x25519_nb_ctx_t*)XMALLOC(
sizeof(x25519_nb_ctx_t), ssl->heap,
DYNAMIC_TYPE_TMP_BUFFER);
@@ -8018,9 +8022,13 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
}
else {
ret = wc_curve25519_set_nonblock(key, nbCtx);
if (ret != 0) {
XFREE(nbCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
}
}
}
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW */
#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);