Skip to content

Commit 218ddb4

Browse files
authored
Merge pull request #10394 from dgarske/sp_nonblock_rsa_dh
Add RSA/DH SP non-blocking support for C/Small 2048/3072/4096
2 parents 3afa901 + d465d8b commit 218ddb4

14 files changed

Lines changed: 4426 additions & 35 deletions

File tree

.github/workflows/os-check.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,14 @@ jobs:
107107
'CPPFLAGS=-DNO_WOLFSSL_SERVER',
108108
'--enable-lms=small,verify-only --enable-xmss=small,verify-only',
109109
'--enable-opensslall --enable-ecc CPPFLAGS="-DWC_ALLOW_ECC_ZERO_HASH"',
110-
'--enable-curve25519=nonblock --enable-ecc=nonblock --enable-sp=yes,nonblock CPPFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK"',
110+
# Non-blocking ECC + Curve25519 + RSA + DH on the default SP word
111+
# size for the host (sp_c64.c on x86_64). RSA/DH non-block require
112+
# RSA_LOW_MEM (CRT path is not supported in non-block mode).
113+
'--enable-curve25519=nonblock --enable-ecc=nonblock --enable-rsa=nonblock --enable-dh=nonblock --enable-sp=yes,nonblock CPPFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK -DRSA_LOW_MEM"',
114+
# Same configuration but force SP_WORD_SIZE=32 to exercise sp_c32.c
115+
# on a 64-bit host. The two builds together cover both generated
116+
# variants of mod_exp_<words>_nb / RSA / DH wrappers.
117+
'--enable-curve25519=nonblock --enable-ecc=nonblock --enable-rsa=nonblock --enable-dh=nonblock --enable-sp=yes,nonblock CPPFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK -DRSA_LOW_MEM -DSP_WORD_SIZE=32"',
111118
'--enable-certreq --enable-certext --enable-certgen --disable-secure-renegotiation-info CPPFLAGS="-DNO_TLS"',
112119
# Minimal DTLS 1.3 client-only build. The SHA-224/384/512/3
113120
# disables are deliberately omitted: --disable-sha384 alone

.wolfssl_known_macro_extras

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,6 @@ WC_PROTECT_ENCRYPTED_MEM
673673
WC_PUF_SHA3
674674
WC_RNG_BANK_NO_DEFAULT_SUPPORT
675675
WC_RNG_BLOCKING
676-
WC_RSA_NONBLOCK
677676
WC_RSA_NONBLOCK_TIME
678677
WC_RSA_NO_FERMAT_CHECK
679678
WC_RWLOCK_OPS_INLINE

configure.ac

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5009,6 +5009,15 @@ then
50095009
test -z "$enable_asynccrypt_sw" && enable_asynccrypt_sw=yes
50105010
fi
50115011

5012+
# Handle RSA/DH nonblock - the SP non-blocking dispatch wants the same
5013+
# WOLFSSL_ASYNC_CRYPT_SW shim that ECC/Curve25519 nonblock use so the
5014+
# TLS layer can manage per-SSL nb contexts and yield MP_WOULDBLOCK.
5015+
if test "$enable_rsa" = "nonblock" || test "$enable_dh" = "nonblock"
5016+
then
5017+
test -z "$enable_asynccrypt" && enable_asynccrypt=yes
5018+
test -z "$enable_asynccrypt_sw" && enable_asynccrypt_sw=yes
5019+
fi
5020+
50125021
if test "$ENABLED_CURVE25519" = "no" && test "$ENABLED_QUIC" = "yes" && test "$ENABLED_FIPS" = "no"
50135022
then
50145023
ENABLED_CURVE25519=yes
@@ -5525,14 +5534,25 @@ fi
55255534

55265535
# RSA
55275536
AC_ARG_ENABLE([rsa],
5528-
[AS_HELP_STRING([--enable-rsa],[Enable RSA (default: enabled)])],
5537+
[AS_HELP_STRING([--enable-rsa],[Enable RSA (default: enabled). Set to "nonblock" to enable non-blocking RSA via TFM fp_exptmod_nb or SP small mod_exp_nb])],
55295538
[ ENABLED_RSA=$enableval ],
55305539
[ ENABLED_RSA=yes ]
55315540
)
55325541

55335542
if test "$ENABLED_RSA" = "no"
55345543
then
55355544
AM_CFLAGS="$AM_CFLAGS -DNO_RSA"
5545+
elif test "$ENABLED_RSA" = "nonblock"
5546+
then
5547+
AM_CFLAGS="$AM_CFLAGS -DWC_RSA_NONBLOCK"
5548+
ENABLED_RSA=yes
5549+
ENABLED_CERTS=yes
5550+
# asynccrypt + asynccrypt-sw are auto-enabled earlier in this file when
5551+
# --enable-rsa=nonblock is detected, so the TLS layer can pick up the
5552+
# per-SSL nb context and yield MP_WOULDBLOCK. RSA_LOW_MEM is left as a
5553+
# user choice - the SP non-block backend's compile-time check in
5554+
# wolfssl/wolfcrypt/rsa.h enforces it for SP, while the TFM (fastmath)
5555+
# backend supports the CRT path without it.
55365556
else
55375557
# turn off RSA if leanpsk or leantls on
55385558
if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes"
@@ -5612,7 +5632,7 @@ fi
56125632

56135633
# DH
56145634
AC_ARG_ENABLE([dh],
5615-
[AS_HELP_STRING([--enable-dh],[Enable DH (default: enabled)])],
5635+
[AS_HELP_STRING([--enable-dh],[Enable DH (default: enabled). Set to "nonblock" to enable non-blocking DH key agreement via SP small mod_exp_nb])],
56165636
[ ENABLED_DH=$enableval ],
56175637
[ ENABLED_DH=yes ]
56185638
)
@@ -5625,6 +5645,11 @@ fi
56255645
if test "$ENABLED_DH" = "no"
56265646
then
56275647
AM_CFLAGS="$AM_CFLAGS -DNO_DH"
5648+
elif test "$ENABLED_DH" = "nonblock"
5649+
then
5650+
AM_CFLAGS="$AM_CFLAGS -DWC_DH_NONBLOCK"
5651+
ENABLED_DH=yes
5652+
# asynccrypt + asynccrypt-sw are auto-enabled earlier in this file.
56285653
else
56295654
# turn off DH if leanpsk or leantls on
56305655
if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes"

src/internal.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8305,6 +8305,15 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
83058305
switch (type) {
83068306
#ifndef NO_RSA
83078307
case DYNAMIC_TYPE_RSA:
8308+
#if defined(WC_RSA_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8309+
defined(WC_ASYNC_ENABLE_RSA)
8310+
if (((RsaKey*)*pKey)->nb != NULL) {
8311+
XFREE(((RsaKey*)*pKey)->nb, ssl->heap,
8312+
DYNAMIC_TYPE_TMP_BUFFER);
8313+
((RsaKey*)*pKey)->nb = NULL;
8314+
}
8315+
#endif /* WC_RSA_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8316+
WC_ASYNC_ENABLE_RSA */
83088317
wc_FreeRsaKey((RsaKey*)*pKey);
83098318
break;
83108319
#endif /* ! NO_RSA */
@@ -8360,6 +8369,15 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
83608369
#endif /* HAVE_DILITHIUM */
83618370
#ifndef NO_DH
83628371
case DYNAMIC_TYPE_DH:
8372+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8373+
defined(WC_ASYNC_ENABLE_DH)
8374+
if (((DhKey*)*pKey)->nb != NULL) {
8375+
XFREE(((DhKey*)*pKey)->nb, ssl->heap,
8376+
DYNAMIC_TYPE_TMP_BUFFER);
8377+
((DhKey*)*pKey)->nb = NULL;
8378+
}
8379+
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8380+
WC_ASYNC_ENABLE_DH */
83638381
wc_FreeDhKey((DhKey*)*pKey);
83648382
break;
83658383
#endif /* !NO_DH */
@@ -8390,6 +8408,14 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
83908408
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
83918409
x25519_nb_ctx_t* x25519NbCtx;
83928410
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW */
8411+
#if !defined(NO_RSA) && defined(WC_RSA_NONBLOCK) && \
8412+
defined(WOLFSSL_ASYNC_CRYPT_SW) && defined(WC_ASYNC_ENABLE_RSA)
8413+
RsaNb* rsaNb;
8414+
#endif
8415+
#if !defined(NO_DH) && defined(WC_DH_NONBLOCK) && \
8416+
defined(WOLFSSL_ASYNC_CRYPT_SW) && defined(WC_ASYNC_ENABLE_DH)
8417+
DhNb* dhNb;
8418+
#endif
83938419

83948420
if (ssl == NULL || pKey == NULL) {
83958421
return BAD_FUNC_ARG;
@@ -8469,6 +8495,26 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
84698495
#ifndef NO_RSA
84708496
case DYNAMIC_TYPE_RSA:
84718497
ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId);
8498+
#if defined(WC_RSA_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8499+
defined(WC_ASYNC_ENABLE_RSA)
8500+
/* Only set non-blocking context when async device is active. With
8501+
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
8502+
* skip non-blocking setup and use blocking mode instead. */
8503+
if (ret == 0 && ssl->devId != INVALID_DEVID) {
8504+
rsaNb = (RsaNb*)XMALLOC(sizeof(RsaNb), ssl->heap,
8505+
DYNAMIC_TYPE_TMP_BUFFER);
8506+
if (rsaNb == NULL) {
8507+
ret = MEMORY_E;
8508+
}
8509+
else {
8510+
ret = wc_RsaSetNonBlock((RsaKey*)*pKey, rsaNb);
8511+
if (ret != 0) {
8512+
XFREE(rsaNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
8513+
}
8514+
}
8515+
}
8516+
#endif /* WC_RSA_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8517+
WC_ASYNC_ENABLE_RSA */
84728518
break;
84738519
#endif /* ! NO_RSA */
84748520
#ifdef HAVE_ECC
@@ -8556,6 +8602,26 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
85568602
#ifndef NO_DH
85578603
case DYNAMIC_TYPE_DH:
85588604
ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId);
8605+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8606+
defined(WC_ASYNC_ENABLE_DH)
8607+
/* Only set non-blocking context when async device is active. With
8608+
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
8609+
* skip non-blocking setup and use blocking mode instead. */
8610+
if (ret == 0 && ssl->devId != INVALID_DEVID) {
8611+
dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
8612+
DYNAMIC_TYPE_TMP_BUFFER);
8613+
if (dhNb == NULL) {
8614+
ret = MEMORY_E;
8615+
}
8616+
else {
8617+
ret = wc_DhSetNonBlock((DhKey*)*pKey, dhNb);
8618+
if (ret != 0) {
8619+
XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
8620+
}
8621+
}
8622+
}
8623+
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8624+
WC_ASYNC_ENABLE_DH */
85598625
break;
85608626
#endif /* !NO_DH */
85618627
default:

src/tls.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8021,6 +8021,26 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
80218021
ret = wc_DhSetNamedKey(dhKey, kse->group);
80228022
#endif
80238023
}
8024+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8025+
defined(WC_ASYNC_ENABLE_DH)
8026+
/* Only set non-blocking context when async device is active. With
8027+
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
8028+
* skip non-blocking setup and use blocking mode instead. */
8029+
if (ret == 0 && ssl->devId != INVALID_DEVID) {
8030+
DhNb* dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
8031+
DYNAMIC_TYPE_TMP_BUFFER);
8032+
if (dhNb == NULL) {
8033+
ret = MEMORY_E;
8034+
}
8035+
else {
8036+
ret = wc_DhSetNonBlock((DhKey*)kse->key, dhNb);
8037+
if (ret != 0) {
8038+
XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
8039+
}
8040+
}
8041+
}
8042+
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
8043+
WC_ASYNC_ENABLE_DH */
80248044
}
80258045

80268046
/* Allocate space for the private and public key */
@@ -8096,8 +8116,16 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
80968116

80978117
/* Always release the DH key to free up memory.
80988118
* The DhKey will be setup again in TLSX_KeyShare_ProcessDh */
8099-
if (dhKey != NULL)
8119+
if (dhKey != NULL) {
8120+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
8121+
defined(WC_ASYNC_ENABLE_DH)
8122+
if (dhKey->nb != NULL) {
8123+
XFREE(dhKey->nb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
8124+
dhKey->nb = NULL;
8125+
}
8126+
#endif
81008127
wc_FreeDhKey(dhKey);
8128+
}
81018129
XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_DH);
81028130
kse->key = NULL;
81038131

@@ -9062,6 +9090,15 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
90629090
list = current->next;
90639091
if (WOLFSSL_NAMED_GROUP_IS_FFDHE(current->group)) {
90649092
#ifndef NO_DH
9093+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
9094+
defined(WC_ASYNC_ENABLE_DH)
9095+
if (current->key != NULL &&
9096+
((DhKey*)current->key)->nb != NULL) {
9097+
XFREE(((DhKey*)current->key)->nb, heap,
9098+
DYNAMIC_TYPE_TMP_BUFFER);
9099+
((DhKey*)current->key)->nb = NULL;
9100+
}
9101+
#endif
90659102
wc_FreeDhKey((DhKey*)current->key);
90669103
if (current->privKey != NULL && current->privKeyLen > 0) {
90679104
ForceZero(current->privKey, current->privKeyLen);
@@ -9321,6 +9358,26 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
93219358
ret = wc_DhSetNamedKey(dhKey, keyShareEntry->group);
93229359
#endif
93239360
}
9361+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
9362+
defined(WC_ASYNC_ENABLE_DH)
9363+
/* Only set non-blocking context when async device is active. With
9364+
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
9365+
* skip non-blocking setup and use blocking mode instead. */
9366+
if (ret == 0 && ssl->devId != INVALID_DEVID) {
9367+
DhNb* dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
9368+
DYNAMIC_TYPE_TMP_BUFFER);
9369+
if (dhNb == NULL) {
9370+
ret = MEMORY_E;
9371+
}
9372+
else {
9373+
ret = wc_DhSetNonBlock((DhKey*)keyShareEntry->key, dhNb);
9374+
if (ret != 0) {
9375+
XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
9376+
}
9377+
}
9378+
}
9379+
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
9380+
WC_ASYNC_ENABLE_DH */
93249381
}
93259382

93269383
if (ret == 0
@@ -9361,8 +9418,16 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
93619418
}
93629419

93639420
/* done with key share, release resources */
9364-
if (dhKey)
9421+
if (dhKey) {
9422+
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
9423+
defined(WC_ASYNC_ENABLE_DH)
9424+
if (dhKey->nb != NULL) {
9425+
XFREE(dhKey->nb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
9426+
dhKey->nb = NULL;
9427+
}
9428+
#endif
93659429
wc_FreeDhKey(dhKey);
9430+
}
93669431
XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_DH);
93679432
keyShareEntry->key = NULL;
93689433
if (keyShareEntry->privKey) {

0 commit comments

Comments
 (0)