mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 13:00:52 +02:00
Merge pull request #10394 from dgarske/sp_nonblock_rsa_dh
Add RSA/DH SP non-blocking support for C/Small 2048/3072/4096
This commit is contained in:
@@ -107,7 +107,14 @@ jobs:
|
||||
'CPPFLAGS=-DNO_WOLFSSL_SERVER',
|
||||
'--enable-lms=small,verify-only --enable-xmss=small,verify-only',
|
||||
'--enable-opensslall --enable-ecc CPPFLAGS="-DWC_ALLOW_ECC_ZERO_HASH"',
|
||||
'--enable-curve25519=nonblock --enable-ecc=nonblock --enable-sp=yes,nonblock CPPFLAGS="-DWOLFSSL_PUBLIC_MP -DWOLFSSL_DEBUG_NONBLOCK"',
|
||||
# Non-blocking ECC + Curve25519 + RSA + DH on the default SP word
|
||||
# size for the host (sp_c64.c on x86_64). RSA/DH non-block require
|
||||
# RSA_LOW_MEM (CRT path is not supported in non-block mode).
|
||||
'--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"',
|
||||
# Same configuration but force SP_WORD_SIZE=32 to exercise sp_c32.c
|
||||
# on a 64-bit host. The two builds together cover both generated
|
||||
# variants of mod_exp_<words>_nb / RSA / DH wrappers.
|
||||
'--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"',
|
||||
'--enable-certreq --enable-certext --enable-certgen --disable-secure-renegotiation-info CPPFLAGS="-DNO_TLS"',
|
||||
# Minimal DTLS 1.3 client-only build. The SHA-224/384/512/3
|
||||
# disables are deliberately omitted: --disable-sha384 alone
|
||||
|
||||
@@ -673,7 +673,6 @@ WC_PROTECT_ENCRYPTED_MEM
|
||||
WC_PUF_SHA3
|
||||
WC_RNG_BANK_NO_DEFAULT_SUPPORT
|
||||
WC_RNG_BLOCKING
|
||||
WC_RSA_NONBLOCK
|
||||
WC_RSA_NONBLOCK_TIME
|
||||
WC_RSA_NO_FERMAT_CHECK
|
||||
WC_RWLOCK_OPS_INLINE
|
||||
|
||||
+27
-2
@@ -5009,6 +5009,15 @@ then
|
||||
test -z "$enable_asynccrypt_sw" && enable_asynccrypt_sw=yes
|
||||
fi
|
||||
|
||||
# Handle RSA/DH nonblock - the SP non-blocking dispatch wants the same
|
||||
# WOLFSSL_ASYNC_CRYPT_SW shim that ECC/Curve25519 nonblock use so the
|
||||
# TLS layer can manage per-SSL nb contexts and yield MP_WOULDBLOCK.
|
||||
if test "$enable_rsa" = "nonblock" || test "$enable_dh" = "nonblock"
|
||||
then
|
||||
test -z "$enable_asynccrypt" && enable_asynccrypt=yes
|
||||
test -z "$enable_asynccrypt_sw" && enable_asynccrypt_sw=yes
|
||||
fi
|
||||
|
||||
if test "$ENABLED_CURVE25519" = "no" && test "$ENABLED_QUIC" = "yes" && test "$ENABLED_FIPS" = "no"
|
||||
then
|
||||
ENABLED_CURVE25519=yes
|
||||
@@ -5525,7 +5534,7 @@ fi
|
||||
|
||||
# RSA
|
||||
AC_ARG_ENABLE([rsa],
|
||||
[AS_HELP_STRING([--enable-rsa],[Enable RSA (default: enabled)])],
|
||||
[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])],
|
||||
[ ENABLED_RSA=$enableval ],
|
||||
[ ENABLED_RSA=yes ]
|
||||
)
|
||||
@@ -5533,6 +5542,17 @@ AC_ARG_ENABLE([rsa],
|
||||
if test "$ENABLED_RSA" = "no"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DNO_RSA"
|
||||
elif test "$ENABLED_RSA" = "nonblock"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWC_RSA_NONBLOCK"
|
||||
ENABLED_RSA=yes
|
||||
ENABLED_CERTS=yes
|
||||
# asynccrypt + asynccrypt-sw are auto-enabled earlier in this file when
|
||||
# --enable-rsa=nonblock is detected, so the TLS layer can pick up the
|
||||
# per-SSL nb context and yield MP_WOULDBLOCK. RSA_LOW_MEM is left as a
|
||||
# user choice - the SP non-block backend's compile-time check in
|
||||
# wolfssl/wolfcrypt/rsa.h enforces it for SP, while the TFM (fastmath)
|
||||
# backend supports the CRT path without it.
|
||||
else
|
||||
# turn off RSA if leanpsk or leantls on
|
||||
if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes"
|
||||
@@ -5612,7 +5632,7 @@ fi
|
||||
|
||||
# DH
|
||||
AC_ARG_ENABLE([dh],
|
||||
[AS_HELP_STRING([--enable-dh],[Enable DH (default: enabled)])],
|
||||
[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])],
|
||||
[ ENABLED_DH=$enableval ],
|
||||
[ ENABLED_DH=yes ]
|
||||
)
|
||||
@@ -5625,6 +5645,11 @@ fi
|
||||
if test "$ENABLED_DH" = "no"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DNO_DH"
|
||||
elif test "$ENABLED_DH" = "nonblock"
|
||||
then
|
||||
AM_CFLAGS="$AM_CFLAGS -DWC_DH_NONBLOCK"
|
||||
ENABLED_DH=yes
|
||||
# asynccrypt + asynccrypt-sw are auto-enabled earlier in this file.
|
||||
else
|
||||
# turn off DH if leanpsk or leantls on
|
||||
if test "$ENABLED_LEANPSK" = "yes" || test "$ENABLED_LEANTLS" = "yes"
|
||||
|
||||
@@ -8305,6 +8305,15 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
|
||||
switch (type) {
|
||||
#ifndef NO_RSA
|
||||
case DYNAMIC_TYPE_RSA:
|
||||
#if defined(WC_RSA_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_RSA)
|
||||
if (((RsaKey*)*pKey)->nb != NULL) {
|
||||
XFREE(((RsaKey*)*pKey)->nb, ssl->heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
((RsaKey*)*pKey)->nb = NULL;
|
||||
}
|
||||
#endif /* WC_RSA_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
|
||||
WC_ASYNC_ENABLE_RSA */
|
||||
wc_FreeRsaKey((RsaKey*)*pKey);
|
||||
break;
|
||||
#endif /* ! NO_RSA */
|
||||
@@ -8360,6 +8369,15 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey)
|
||||
#endif /* HAVE_DILITHIUM */
|
||||
#ifndef NO_DH
|
||||
case DYNAMIC_TYPE_DH:
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
if (((DhKey*)*pKey)->nb != NULL) {
|
||||
XFREE(((DhKey*)*pKey)->nb, ssl->heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
((DhKey*)*pKey)->nb = NULL;
|
||||
}
|
||||
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
|
||||
WC_ASYNC_ENABLE_DH */
|
||||
wc_FreeDhKey((DhKey*)*pKey);
|
||||
break;
|
||||
#endif /* !NO_DH */
|
||||
@@ -8390,6 +8408,14 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
|
||||
#if defined(WC_X25519_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW)
|
||||
x25519_nb_ctx_t* x25519NbCtx;
|
||||
#endif /* WC_X25519_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW */
|
||||
#if !defined(NO_RSA) && defined(WC_RSA_NONBLOCK) && \
|
||||
defined(WOLFSSL_ASYNC_CRYPT_SW) && defined(WC_ASYNC_ENABLE_RSA)
|
||||
RsaNb* rsaNb;
|
||||
#endif
|
||||
#if !defined(NO_DH) && defined(WC_DH_NONBLOCK) && \
|
||||
defined(WOLFSSL_ASYNC_CRYPT_SW) && defined(WC_ASYNC_ENABLE_DH)
|
||||
DhNb* dhNb;
|
||||
#endif
|
||||
|
||||
if (ssl == NULL || pKey == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
@@ -8469,6 +8495,26 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
|
||||
#ifndef NO_RSA
|
||||
case DYNAMIC_TYPE_RSA:
|
||||
ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId);
|
||||
#if defined(WC_RSA_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_RSA)
|
||||
/* Only set non-blocking context when async device is active. With
|
||||
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
|
||||
* skip non-blocking setup and use blocking mode instead. */
|
||||
if (ret == 0 && ssl->devId != INVALID_DEVID) {
|
||||
rsaNb = (RsaNb*)XMALLOC(sizeof(RsaNb), ssl->heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (rsaNb == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
else {
|
||||
ret = wc_RsaSetNonBlock((RsaKey*)*pKey, rsaNb);
|
||||
if (ret != 0) {
|
||||
XFREE(rsaNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WC_RSA_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
|
||||
WC_ASYNC_ENABLE_RSA */
|
||||
break;
|
||||
#endif /* ! NO_RSA */
|
||||
#ifdef HAVE_ECC
|
||||
@@ -8556,6 +8602,26 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey)
|
||||
#ifndef NO_DH
|
||||
case DYNAMIC_TYPE_DH:
|
||||
ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId);
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
/* Only set non-blocking context when async device is active. With
|
||||
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
|
||||
* skip non-blocking setup and use blocking mode instead. */
|
||||
if (ret == 0 && ssl->devId != INVALID_DEVID) {
|
||||
dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (dhNb == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
else {
|
||||
ret = wc_DhSetNonBlock((DhKey*)*pKey, dhNb);
|
||||
if (ret != 0) {
|
||||
XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
|
||||
WC_ASYNC_ENABLE_DH */
|
||||
break;
|
||||
#endif /* !NO_DH */
|
||||
default:
|
||||
|
||||
@@ -8021,6 +8021,26 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
|
||||
ret = wc_DhSetNamedKey(dhKey, kse->group);
|
||||
#endif
|
||||
}
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
/* Only set non-blocking context when async device is active. With
|
||||
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
|
||||
* skip non-blocking setup and use blocking mode instead. */
|
||||
if (ret == 0 && ssl->devId != INVALID_DEVID) {
|
||||
DhNb* dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (dhNb == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
else {
|
||||
ret = wc_DhSetNonBlock((DhKey*)kse->key, dhNb);
|
||||
if (ret != 0) {
|
||||
XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
|
||||
WC_ASYNC_ENABLE_DH */
|
||||
}
|
||||
|
||||
/* Allocate space for the private and public key */
|
||||
@@ -8096,8 +8116,16 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
|
||||
|
||||
/* Always release the DH key to free up memory.
|
||||
* The DhKey will be setup again in TLSX_KeyShare_ProcessDh */
|
||||
if (dhKey != NULL)
|
||||
if (dhKey != NULL) {
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
if (dhKey->nb != NULL) {
|
||||
XFREE(dhKey->nb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
dhKey->nb = NULL;
|
||||
}
|
||||
#endif
|
||||
wc_FreeDhKey(dhKey);
|
||||
}
|
||||
XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_DH);
|
||||
kse->key = NULL;
|
||||
|
||||
@@ -9062,6 +9090,15 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
|
||||
list = current->next;
|
||||
if (WOLFSSL_NAMED_GROUP_IS_FFDHE(current->group)) {
|
||||
#ifndef NO_DH
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
if (current->key != NULL &&
|
||||
((DhKey*)current->key)->nb != NULL) {
|
||||
XFREE(((DhKey*)current->key)->nb, heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
((DhKey*)current->key)->nb = NULL;
|
||||
}
|
||||
#endif
|
||||
wc_FreeDhKey((DhKey*)current->key);
|
||||
if (current->privKey != NULL && current->privKeyLen > 0) {
|
||||
ForceZero(current->privKey, current->privKeyLen);
|
||||
@@ -9321,6 +9358,26 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
|
||||
ret = wc_DhSetNamedKey(dhKey, keyShareEntry->group);
|
||||
#endif
|
||||
}
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
/* Only set non-blocking context when async device is active. With
|
||||
* INVALID_DEVID there is no async loop to retry on MP_WOULDBLOCK, so
|
||||
* skip non-blocking setup and use blocking mode instead. */
|
||||
if (ret == 0 && ssl->devId != INVALID_DEVID) {
|
||||
DhNb* dhNb = (DhNb*)XMALLOC(sizeof(DhNb), ssl->heap,
|
||||
DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (dhNb == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
else {
|
||||
ret = wc_DhSetNonBlock((DhKey*)keyShareEntry->key, dhNb);
|
||||
if (ret != 0) {
|
||||
XFREE(dhNb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WC_DH_NONBLOCK && WOLFSSL_ASYNC_CRYPT_SW &&
|
||||
WC_ASYNC_ENABLE_DH */
|
||||
}
|
||||
|
||||
if (ret == 0
|
||||
@@ -9361,8 +9418,16 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
|
||||
}
|
||||
|
||||
/* done with key share, release resources */
|
||||
if (dhKey)
|
||||
if (dhKey) {
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_ASYNC_CRYPT_SW) && \
|
||||
defined(WC_ASYNC_ENABLE_DH)
|
||||
if (dhKey->nb != NULL) {
|
||||
XFREE(dhKey->nb, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
dhKey->nb = NULL;
|
||||
}
|
||||
#endif
|
||||
wc_FreeDhKey(dhKey);
|
||||
}
|
||||
XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_DH);
|
||||
keyShareEntry->key = NULL;
|
||||
if (keyShareEntry->privKey) {
|
||||
|
||||
+100
-9
@@ -972,6 +972,10 @@ int wc_InitDhKey_ex(DhKey* key, void* heap, int devId)
|
||||
key->handle = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
key->nb = NULL;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -980,6 +984,23 @@ int wc_InitDhKey(DhKey* key)
|
||||
return wc_InitDhKey_ex(key, NULL, INVALID_DEVID);
|
||||
}
|
||||
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
int wc_DhSetNonBlock(DhKey* key, DhNb* nb)
|
||||
{
|
||||
if (key == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
if (nb != NULL) {
|
||||
XMEMSET(nb, 0, sizeof(DhNb));
|
||||
}
|
||||
|
||||
/* Pass NULL to disable non-blocking mode. */
|
||||
key->nb = nb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int wc_FreeDhKey(DhKey* key)
|
||||
{
|
||||
@@ -2030,19 +2051,81 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
|
||||
if (mp_iseven(&key->p) == MP_YES) {
|
||||
return MP_VAL;
|
||||
}
|
||||
|
||||
/* Non-blocking re-entry: the same wc_DhAgree call repeats until the
|
||||
* SP state machine completes, so cache the per-op key validation
|
||||
* results instead of re-running them each yield. The cache is
|
||||
* scoped to non-blocking, non-const-time callers only. */
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
if (key->nb == NULL || ct || !key->nb->pubKeyValidated)
|
||||
#endif
|
||||
{
|
||||
#ifdef WOLFSSL_VALIDATE_FFC_IMPORT
|
||||
if (wc_DhCheckPrivKey(key, priv, privSz) != 0) {
|
||||
WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed");
|
||||
return DH_CHECK_PRIV_E;
|
||||
if (wc_DhCheckPrivKey(key, priv, privSz) != 0) {
|
||||
WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed");
|
||||
return DH_CHECK_PRIV_E;
|
||||
}
|
||||
#endif
|
||||
/* Always validate peer public key (2 <= y <= p-2) per SP 800-56A */
|
||||
if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) {
|
||||
WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed");
|
||||
return DH_CHECK_PUB_E;
|
||||
}
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
if (key->nb != NULL && !ct) {
|
||||
key->nb->pubKeyValidated = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_HAVE_SP_DH) && \
|
||||
defined(WOLFSSL_SP_NONBLOCK) && defined(WOLFSSL_SP_SMALL) && \
|
||||
!defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
/* Non-blocking dispatch bypasses the mp_int dance entirely - the SP
|
||||
* wrapper takes byte buffers and persists across yields. The constant-
|
||||
* time fold-back (ct branch) is intentionally not applied here; nb
|
||||
* callers should use the standard wc_DhAgree(). */
|
||||
if (key->nb != NULL && !ct) {
|
||||
int nb_ret = MP_OKAY;
|
||||
int dispatched = 0;
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
if (mp_count_bits(&key->p) == 2048) {
|
||||
nb_ret = sp_DhExp_2048_nb(&key->nb->sp_ctx, otherPub, pubSz,
|
||||
priv, privSz, &key->p, agree, agreeSz);
|
||||
dispatched = 1;
|
||||
}
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
if (!dispatched && mp_count_bits(&key->p) == 3072) {
|
||||
nb_ret = sp_DhExp_3072_nb(&key->nb->sp_ctx, otherPub, pubSz,
|
||||
priv, privSz, &key->p, agree, agreeSz);
|
||||
dispatched = 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
if (!dispatched && mp_count_bits(&key->p) == 4096) {
|
||||
nb_ret = sp_DhExp_4096_nb(&key->nb->sp_ctx, otherPub, pubSz,
|
||||
priv, privSz, &key->p, agree, agreeSz);
|
||||
dispatched = 1;
|
||||
}
|
||||
#endif
|
||||
if (dispatched) {
|
||||
/* Op finished (or hit a hard error) - clear the cached
|
||||
* validation so the next op on this DhNb re-runs the
|
||||
* SP 800-56A peer-key check. MP_WOULDBLOCK keeps it. */
|
||||
if (nb_ret != WC_NO_ERR_TRACE(MP_WOULDBLOCK)) {
|
||||
key->nb->pubKeyValidated = 0;
|
||||
}
|
||||
return nb_ret;
|
||||
}
|
||||
/* size not nb-supported - the blocking path below completes in
|
||||
* one call, so the cached validation is single-use. Clear it
|
||||
* here so the next agree on this DhNb re-validates. */
|
||||
key->nb->pubKeyValidated = 0;
|
||||
/* fall through to blocking path */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Always validate peer public key (2 <= y <= p-2) per SP 800-56A */
|
||||
if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) {
|
||||
WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed");
|
||||
return DH_CHECK_PUB_E;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH);
|
||||
if (y == NULL)
|
||||
@@ -2304,6 +2387,11 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
|
||||
ret = KcapiDh_SharedSecret(key, otherPub, pubSz, agree, agreeSz);
|
||||
#else
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
|
||||
/* Async marker takes precedence: when wolfAsync_DoSw (wolfcrypt/src/
|
||||
* async.c) re-enters the compute path, wc_DhAgree_Async dispatches
|
||||
* to the SP nonblock wrapper if key->nb is attached, and per-yield
|
||||
* FP_WOULDBLOCK (alias of MP_WOULDBLOCK) is translated to
|
||||
* WC_PENDING_E by wolfAsync_DoSw so the TLS event loop drives it. */
|
||||
if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) {
|
||||
ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub,
|
||||
pubSz);
|
||||
@@ -2311,6 +2399,9 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* wc_DhAgree_Sync handles key->nb internally; no separate dispatch
|
||||
* needed here. wc_DhAgree_ct (constant-time fold-back) bypasses
|
||||
* this function entirely so passing ct=0 is correct. */
|
||||
ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub,
|
||||
pubSz, 0);
|
||||
}
|
||||
|
||||
+91
-2
@@ -2289,12 +2289,69 @@ static int wc_RsaFunctionNonBlock(const byte* in, word32 inLen, byte* out,
|
||||
word32* outLen, int type, RsaKey* key)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef USE_FAST_MATH
|
||||
word32 keyLen, len;
|
||||
#endif
|
||||
/* SP non-blocking RSA wrappers depend on sp_<N>_mod_exp_<W>_nb,
|
||||
* which the SP generator only emits when (!RSA_PUBLIC_ONLY ||
|
||||
* HAVE_SP_DH). Match that gate here so the dispatch is omitted when
|
||||
* those symbols are not available. */
|
||||
#if defined(WOLFSSL_HAVE_SP_RSA) && defined(WOLFSSL_SP_NONBLOCK) && \
|
||||
defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) && \
|
||||
(!defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_HAVE_SP_DH))
|
||||
int bits;
|
||||
#endif
|
||||
|
||||
if (key == NULL || key->nb == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#if defined(WOLFSSL_HAVE_SP_RSA) && defined(WOLFSSL_SP_NONBLOCK) && \
|
||||
defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP) && \
|
||||
(!defined(WOLFSSL_RSA_PUBLIC_ONLY) || defined(WOLFSSL_HAVE_SP_DH))
|
||||
bits = mp_count_bits(&key->n);
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
if (bits == 2048) {
|
||||
if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
|
||||
return sp_RsaPublic_2048_nb(&key->nb->sp_ctx, in, inLen,
|
||||
&key->e, &key->n, out, outLen);
|
||||
}
|
||||
#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
|
||||
(defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM))
|
||||
return sp_RsaPrivate_2048_nb(&key->nb->sp_ctx, in, inLen,
|
||||
&key->d, &key->n, out, outLen);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
if (bits == 3072) {
|
||||
if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
|
||||
return sp_RsaPublic_3072_nb(&key->nb->sp_ctx, in, inLen,
|
||||
&key->e, &key->n, out, outLen);
|
||||
}
|
||||
#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
|
||||
(defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM))
|
||||
return sp_RsaPrivate_3072_nb(&key->nb->sp_ctx, in, inLen,
|
||||
&key->d, &key->n, out, outLen);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
if (bits == 4096) {
|
||||
if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
|
||||
return sp_RsaPublic_4096_nb(&key->nb->sp_ctx, in, inLen,
|
||||
&key->e, &key->n, out, outLen);
|
||||
}
|
||||
#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
|
||||
(defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM))
|
||||
return sp_RsaPrivate_4096_nb(&key->nb->sp_ctx, in, inLen,
|
||||
&key->d, &key->n, out, outLen);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif /* SP nonblock RSA */
|
||||
|
||||
#ifdef USE_FAST_MATH
|
||||
if (key->nb->exptmod.state == TFM_EXPTMOD_NB_INIT) {
|
||||
if (mp_init(&key->nb->tmp) != MP_OKAY) {
|
||||
ret = MP_INIT_E;
|
||||
@@ -2358,6 +2415,18 @@ static int wc_RsaFunctionNonBlock(const byte* in, word32 inLen, byte* out,
|
||||
}
|
||||
|
||||
mp_clear(&key->nb->tmp);
|
||||
#else
|
||||
/* No non-blocking backend available for this build. The SP non-block
|
||||
* dispatch above only matches enabled key sizes; if we reach this
|
||||
* point the key is not 2048/3072/4096 (or SP RSA itself isn't built)
|
||||
* and TFM fastmath isn't compiled in either. */
|
||||
(void)in;
|
||||
(void)inLen;
|
||||
(void)out;
|
||||
(void)outLen;
|
||||
(void)type;
|
||||
ret = NOT_COMPILED_IN;
|
||||
#endif /* USE_FAST_MATH */
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -3153,6 +3222,18 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out,
|
||||
}
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT_SW */
|
||||
|
||||
#ifdef WC_RSA_NONBLOCK
|
||||
/* When a non-blocking context is attached and the SP nonblock backend
|
||||
* is available, drive the chunked state machine here. wolfAsync_DoSw
|
||||
* (line "if (ret == FP_WOULDBLOCK) ret = WC_PENDING_E;" at the bottom
|
||||
* of the SW switch in wolfcrypt/src/async.c, FP_WOULDBLOCK aliases
|
||||
* MP_WOULDBLOCK) translates per-yield MP_WOULDBLOCK into WC_PENDING_E
|
||||
* so the TLS / async event loop can drive the operation to completion. */
|
||||
if (key->nb != NULL) {
|
||||
return wc_RsaFunctionNonBlock(in, inLen, out, outLen, type, key);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
||||
case RSA_PRIVATE_DECRYPT:
|
||||
@@ -3518,12 +3599,20 @@ static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out,
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA)
|
||||
if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA &&
|
||||
key->n.raw.len > 0) {
|
||||
/* wc_RsaFunctionAsync dispatches to the SP nonblock state machine
|
||||
* in its compute path when key->nb is attached - wolfAsync_DoSw
|
||||
* (in wolfcrypt/src/async.c) translates per-yield FP_WOULDBLOCK
|
||||
* (alias of MP_WOULDBLOCK) into WC_PENDING_E so the TLS / async
|
||||
* event loop can drive completion. */
|
||||
ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef WC_RSA_NONBLOCK
|
||||
if (key->nb) {
|
||||
/* Direct (non-async) nonblock dispatch - the caller (e.g. wolfcrypt
|
||||
* test) drives the loop on MP_WOULDBLOCK directly. Reached when no
|
||||
* async marker is set on the key. */
|
||||
ret = wc_RsaFunctionNonBlock(in, inLen, out, outLen, type, key);
|
||||
}
|
||||
else
|
||||
@@ -5766,7 +5855,7 @@ int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef WC_RSA_NONBLOCK_TIME
|
||||
#if defined(WC_RSA_NONBLOCK_TIME) && defined(USE_FAST_MATH)
|
||||
int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz)
|
||||
{
|
||||
if (key == NULL || key->nb == NULL) {
|
||||
@@ -5778,7 +5867,7 @@ int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* WC_RSA_NONBLOCK_TIME */
|
||||
#endif /* WC_RSA_NONBLOCK_TIME && USE_FAST_MATH */
|
||||
#endif /* WC_RSA_NONBLOCK */
|
||||
|
||||
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+56
-2
@@ -24363,8 +24363,10 @@ static wc_test_ret_t rsa_nb_test(RsaKey* key, const byte* in, word32 inLen, byte
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
#ifdef WC_RSA_NONBLOCK_TIME
|
||||
/* Enable time based RSA blocking. 8 microseconds max (3.1GHz) */
|
||||
#if defined(WC_RSA_NONBLOCK_TIME) && defined(USE_FAST_MATH)
|
||||
/* Enable time based RSA blocking. 8 microseconds max (3.1GHz).
|
||||
* Only available with USE_FAST_MATH; SP-only WC_RSA_NONBLOCK
|
||||
* builds do not expose this entry point. */
|
||||
ret = wc_RsaSetNonBlockTime(key, 8, 3100);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@@ -27806,6 +27808,14 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name)
|
||||
#endif
|
||||
word32 agreeSz = MAX_DH_KEY_SZ;
|
||||
word32 agreeSz2 = MAX_DH_KEY_SZ;
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_HAVE_SP_DH) && \
|
||||
defined(WOLFSSL_SP_NONBLOCK) && defined(WOLFSSL_SP_SMALL) && \
|
||||
!defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
DhNb dhNb;
|
||||
word32 nbAgreeSz;
|
||||
int nbCount;
|
||||
wc_test_ret_t nb_ret;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
|
||||
if ((priv == NULL) ||
|
||||
@@ -27892,6 +27902,50 @@ static wc_test_ret_t dh_ffdhe_test(WC_RNG *rng, int name)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, done);
|
||||
}
|
||||
|
||||
#if defined(WC_DH_NONBLOCK) && defined(WOLFSSL_HAVE_SP_DH) && \
|
||||
defined(WOLFSSL_SP_NONBLOCK) && defined(WOLFSSL_SP_SMALL) && \
|
||||
!defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
nbAgreeSz = MAX_DH_KEY_SZ;
|
||||
nbCount = 0;
|
||||
XMEMSET(agree2, 0, MAX_DH_KEY_SZ);
|
||||
|
||||
nb_ret = wc_DhSetNonBlock(key, &dhNb);
|
||||
if (nb_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(nb_ret), done);
|
||||
|
||||
do {
|
||||
nb_ret = wc_DhAgree(key, agree2, &nbAgreeSz, priv, privSz,
|
||||
pub2, pubSz2);
|
||||
nbCount++;
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT)
|
||||
/* When async crypt is enabled, the SW shim returns WC_PENDING_E
|
||||
* on the first call (init phase) and wc_AsyncWait drives the SP
|
||||
* non-block state machine to completion. wc_AsyncSimulate
|
||||
* translates each per-yield MP_WOULDBLOCK from sp_DhExp_<size>_nb
|
||||
* into WC_PENDING_E internally so the wait loop polls until the
|
||||
* operation finishes. */
|
||||
if (nb_ret == WC_NO_ERR_TRACE(WC_PENDING_E)) {
|
||||
nb_ret = wc_AsyncWait(nb_ret, &key->asyncDev,
|
||||
WC_ASYNC_FLAG_NONE);
|
||||
}
|
||||
#endif
|
||||
} while (nb_ret == WC_NO_ERR_TRACE(MP_WOULDBLOCK) ||
|
||||
nb_ret == WC_NO_ERR_TRACE(WC_PENDING_E));
|
||||
if (nb_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(nb_ret), done);
|
||||
|
||||
#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG_NONBLOCK)
|
||||
printf("DH non-block agree: %d times\n", nbCount);
|
||||
#endif
|
||||
|
||||
if (nbAgreeSz != agreeSz || XMEMCMP(agree, agree2, agreeSz))
|
||||
ERROR_OUT(WC_TEST_RET_ENC_NC, done);
|
||||
|
||||
nb_ret = wc_DhSetNonBlock(key, NULL);
|
||||
if (nb_ret != 0)
|
||||
ERROR_OUT(WC_TEST_RET_ENC_EC(nb_ret), done);
|
||||
#endif /* WC_DH_NONBLOCK + SP nonblock */
|
||||
|
||||
/* wc_DhGeneratePublic_fips() was added in 5.2.3, but some customers are
|
||||
* building with configure scripts that set version to 5.2.1, but with 5.2.3
|
||||
* wolfCrypt sources. 5.3.0 is used for both fips-v5-ready and v5-kcapi,
|
||||
|
||||
@@ -49,6 +49,23 @@
|
||||
#include <wolfssl/wolfcrypt/async.h>
|
||||
#endif
|
||||
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
/* Non-blocking DH currently requires the SP small backend with the
|
||||
* non-blocking + no-malloc + non-fast-modexp trio. */
|
||||
#if !defined(WOLFSSL_HAVE_SP_DH) || !defined(WOLFSSL_SP_NONBLOCK)
|
||||
#error WC_DH_NONBLOCK requires WOLFSSL_HAVE_SP_DH + WOLFSSL_SP_NONBLOCK
|
||||
#endif
|
||||
#if !defined(WOLFSSL_SP_SMALL)
|
||||
#error WC_DH_NONBLOCK requires WOLFSSL_SP_SMALL
|
||||
#endif
|
||||
#if !defined(WOLFSSL_SP_NO_MALLOC)
|
||||
#error WC_DH_NONBLOCK requires WOLFSSL_SP_NO_MALLOC
|
||||
#endif
|
||||
#if defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
#error WC_DH_NONBLOCK is incompatible with WOLFSSL_SP_FAST_MODEXP
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct DhParams {
|
||||
#ifdef HAVE_FFDHE_Q
|
||||
const byte* q;
|
||||
@@ -60,6 +77,23 @@ typedef struct DhParams {
|
||||
word32 g_len;
|
||||
} DhParams;
|
||||
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
/* Non-blocking DH context. Holds the SP wrapper state across yields.
|
||||
* Caller allocates one DhNb per active operation and binds it to a key
|
||||
* via wc_DhSetNonBlock(). Lifetime must outlast the operation. */
|
||||
typedef struct DhNb {
|
||||
#if defined(WOLFSSL_HAVE_SP_DH) && defined(WOLFSSL_SP_NONBLOCK) && \
|
||||
defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
sp_dh_ctx_t sp_ctx;
|
||||
#else
|
||||
int unused;
|
||||
#endif
|
||||
/* Set once wc_DhCheckPubKey has succeeded for this op so subsequent
|
||||
* MP_WOULDBLOCK retries skip re-validating the peer public key. */
|
||||
byte pubKeyValidated;
|
||||
} DhNb;
|
||||
#endif
|
||||
|
||||
/* Diffie-Hellman Key */
|
||||
struct DhKey {
|
||||
mp_int p, g, q; /* group parameters */
|
||||
@@ -75,6 +109,9 @@ struct DhKey {
|
||||
#ifdef WOLFSSL_KCAPI_DH
|
||||
struct kcapi_handle* handle;
|
||||
#endif
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
DhNb* nb; /* non-blocking context, NULL when not in non-block mode */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef WC_DH_TYPE_DEFINED
|
||||
@@ -162,6 +199,10 @@ WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g
|
||||
WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz,
|
||||
const byte* g, word32 gSz, const byte* q, word32 qSz);
|
||||
WOLFSSL_API int wc_DhSetNamedKey(DhKey* key, int name);
|
||||
|
||||
#ifdef WC_DH_NONBLOCK
|
||||
WOLFSSL_API int wc_DhSetNonBlock(DhKey* key, DhNb* nb);
|
||||
#endif
|
||||
WOLFSSL_API int wc_DhGetNamedKeyParamSize(int name,
|
||||
word32* p, word32* g, word32* q);
|
||||
WOLFSSL_API word32 wc_DhGetNamedKeyMinSize(int name);
|
||||
|
||||
+38
-7
@@ -44,14 +44,36 @@ RSA keys can be used to encrypt, decrypt, sign and verify data.
|
||||
#endif
|
||||
|
||||
#if defined(WC_RSA_NONBLOCK)
|
||||
/* enable support for fast math based non-blocking exptmod */
|
||||
/* this splits the RSA function into many smaller operations */
|
||||
#ifndef USE_FAST_MATH
|
||||
#error RSA non-blocking mode only supported using fast math
|
||||
/* Non-blocking RSA splits the operation into many smaller chunks so a
|
||||
* bare-metal system loop stays responsive. Two backends are supported:
|
||||
* - TFM fastmath (fp_exptmod_nb), the original implementation.
|
||||
* - SP small (sp_RsaPublic_<n>_nb / sp_RsaPrivate_<n>_nb) when SP
|
||||
* non-blocking is enabled. SP requires RSA_LOW_MEM (CRT not
|
||||
* supported in non-block mode) and the small / no-malloc /
|
||||
* non-blocking trio that drives the chunked state machine. */
|
||||
#if !defined(USE_FAST_MATH) && \
|
||||
!(defined(WOLFSSL_HAVE_SP_RSA) && defined(WOLFSSL_SP_NONBLOCK) && \
|
||||
defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP))
|
||||
#error RSA non-blocking mode requires fast math or SP non-blocking
|
||||
#endif
|
||||
#ifndef TFM_TIMING_RESISTANT
|
||||
#if defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)
|
||||
#error RSA non-blocking mode only supported with timing resistance enabled
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_SP_RSA) && defined(WOLFSSL_SP_NONBLOCK)
|
||||
#if !defined(WOLFSSL_SP_SMALL)
|
||||
#error SP non-blocking RSA requires WOLFSSL_SP_SMALL
|
||||
#endif
|
||||
#if !defined(WOLFSSL_SP_NO_MALLOC)
|
||||
#error SP non-blocking RSA requires WOLFSSL_SP_NO_MALLOC
|
||||
#endif
|
||||
#if defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
#error SP non-blocking RSA is incompatible with WOLFSSL_SP_FAST_MODEXP
|
||||
#endif
|
||||
#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \
|
||||
!defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
|
||||
#error SP non-blocking RSA requires RSA_LOW_MEM (CRT path is unsupported)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* RSA bounds check is not supported with RSA non-blocking mode */
|
||||
#undef NO_RSA_BOUNDS_CHECK
|
||||
@@ -195,8 +217,14 @@ enum {
|
||||
|
||||
#ifdef WC_RSA_NONBLOCK
|
||||
typedef struct RsaNb {
|
||||
exptModNb_t exptmod; /* non-block expt_mod */
|
||||
#ifdef USE_FAST_MATH
|
||||
exptModNb_t exptmod; /* TFM non-block expt_mod state */
|
||||
mp_int tmp;
|
||||
#endif
|
||||
#if defined(WOLFSSL_HAVE_SP_RSA) && defined(WOLFSSL_SP_NONBLOCK) && \
|
||||
defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
sp_rsa_ctx_t sp_ctx; /* SP non-block wrapper state */
|
||||
#endif
|
||||
} RsaNb;
|
||||
#endif
|
||||
|
||||
@@ -422,7 +450,10 @@ WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz,
|
||||
#endif
|
||||
#ifdef WC_RSA_NONBLOCK
|
||||
WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb);
|
||||
#ifdef WC_RSA_NONBLOCK_TIME
|
||||
/* maxBlockInst budget lives on the TFM exptModNb_t; only available
|
||||
* with USE_FAST_MATH. SP-only WC_RSA_NONBLOCK builds do not expose
|
||||
* this entry point. */
|
||||
#if defined(WC_RSA_NONBLOCK_TIME) && defined(USE_FAST_MATH)
|
||||
WOLFSSL_API int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs,
|
||||
word32 cpuMHz);
|
||||
#endif
|
||||
|
||||
@@ -107,6 +107,40 @@ WOLFSSL_LOCAL int sp_RsaPrivate_4096(const byte* in, word32 inLen,
|
||||
|
||||
#endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */
|
||||
|
||||
#if defined(WOLFSSL_SP_NONBLOCK) && defined(WOLFSSL_SP_SMALL) && \
|
||||
!defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
WOLFSSL_LOCAL int sp_RsaPublic_2048_nb(sp_rsa_ctx_t* sp_ctx, const byte* in,
|
||||
word32 inLen, const mp_int* em, const mp_int* mm, byte* out,
|
||||
word32* outLen);
|
||||
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
||||
WOLFSSL_LOCAL int sp_RsaPrivate_2048_nb(sp_rsa_ctx_t* sp_ctx, const byte* in,
|
||||
word32 inLen, const mp_int* dm, const mp_int* mm, byte* out,
|
||||
word32* outLen);
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
WOLFSSL_LOCAL int sp_RsaPublic_3072_nb(sp_rsa_ctx_t* sp_ctx, const byte* in,
|
||||
word32 inLen, const mp_int* em, const mp_int* mm, byte* out,
|
||||
word32* outLen);
|
||||
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
||||
WOLFSSL_LOCAL int sp_RsaPrivate_3072_nb(sp_rsa_ctx_t* sp_ctx, const byte* in,
|
||||
word32 inLen, const mp_int* dm, const mp_int* mm, byte* out,
|
||||
word32* outLen);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
WOLFSSL_LOCAL int sp_RsaPublic_4096_nb(sp_rsa_ctx_t* sp_ctx, const byte* in,
|
||||
word32 inLen, const mp_int* em, const mp_int* mm, byte* out,
|
||||
word32* outLen);
|
||||
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
||||
WOLFSSL_LOCAL int sp_RsaPrivate_4096_nb(sp_rsa_ctx_t* sp_ctx, const byte* in,
|
||||
word32 inLen, const mp_int* dm, const mp_int* mm, byte* out,
|
||||
word32* outLen);
|
||||
#endif
|
||||
#endif
|
||||
#endif /* WOLFSSL_SP_NONBLOCK && WOLFSSL_SP_SMALL && !WOLFSSL_SP_FAST_MODEXP */
|
||||
|
||||
#endif /* WOLFSSL_HAVE_SP_RSA */
|
||||
|
||||
#if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA)
|
||||
@@ -167,6 +201,31 @@ WOLFSSL_LOCAL int sp_DhExp_4096(const mp_int* base, const byte* exp,
|
||||
|
||||
#endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */
|
||||
|
||||
#if defined(WOLFSSL_SP_NONBLOCK) && defined(WOLFSSL_SP_SMALL) && \
|
||||
!defined(WOLFSSL_SP_FAST_MODEXP)
|
||||
#ifndef WOLFSSL_SP_NO_2048
|
||||
WOLFSSL_LOCAL int sp_DhExp_2048_nb(sp_dh_ctx_t* sp_ctx, const byte* base,
|
||||
word32 baseSz, const byte* exp, word32 expLen, const mp_int* mod,
|
||||
byte* out, word32* outLen);
|
||||
WOLFSSL_LOCAL int sp_ModExp_2048_nb(sp_dh_ctx_t* sp_ctx, const mp_int* base,
|
||||
const mp_int* exp, const mp_int* mod, mp_int* res);
|
||||
#endif
|
||||
#ifndef WOLFSSL_SP_NO_3072
|
||||
WOLFSSL_LOCAL int sp_DhExp_3072_nb(sp_dh_ctx_t* sp_ctx, const byte* base,
|
||||
word32 baseSz, const byte* exp, word32 expLen, const mp_int* mod,
|
||||
byte* out, word32* outLen);
|
||||
WOLFSSL_LOCAL int sp_ModExp_3072_nb(sp_dh_ctx_t* sp_ctx, const mp_int* base,
|
||||
const mp_int* exp, const mp_int* mod, mp_int* res);
|
||||
#endif
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
WOLFSSL_LOCAL int sp_DhExp_4096_nb(sp_dh_ctx_t* sp_ctx, const byte* base,
|
||||
word32 baseSz, const byte* exp, word32 expLen, const mp_int* mod,
|
||||
byte* out, word32* outLen);
|
||||
WOLFSSL_LOCAL int sp_ModExp_4096_nb(sp_dh_ctx_t* sp_ctx, const mp_int* base,
|
||||
const mp_int* exp, const mp_int* mod, mp_int* res);
|
||||
#endif
|
||||
#endif /* WOLFSSL_SP_NONBLOCK && WOLFSSL_SP_SMALL && !WOLFSSL_SP_FAST_MODEXP */
|
||||
|
||||
#endif /* WOLFSSL_HAVE_SP_DH */
|
||||
|
||||
#ifdef WOLFSSL_HAVE_SP_ECC
|
||||
|
||||
@@ -401,6 +401,45 @@ typedef struct sp_ecc_ctx {
|
||||
} sp_ecc_ctx_t;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SP_NONBLOCK) && \
|
||||
(defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH))
|
||||
/* Non-blocking RSA / DH operation contexts. The wrapper state struct
|
||||
* embeds the inner modexp ctx (which dominates the size) plus per-op
|
||||
* buffers for the modulus, base/result, and exponent. Sized for the
|
||||
* worst-case wrapper across C32/C64 word layouts at the largest
|
||||
* enabled key size:
|
||||
* 2048-bit: mod_exp td[3*144]*4 = 1728B + wrapper ~= 2960B
|
||||
* 3072-bit: mod_exp td[3*216]*4 = 2592B + wrapper ~= 4400B
|
||||
* 4096-bit: mod_exp td[3*284]*4 = 3408B + wrapper ~= 5760B
|
||||
* Each tier carries a small safety margin for alignment / future
|
||||
* generator changes. The compile-time ctx_size_test inside each
|
||||
* sp_<size>_<op>_<words>_nb function asserts the buffer fits the
|
||||
* generated wrapper. */
|
||||
#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(NO_RSA)
|
||||
typedef struct sp_rsa_ctx {
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
XALIGNED(8) byte data[6144];
|
||||
#elif !defined(WOLFSSL_SP_NO_3072)
|
||||
XALIGNED(8) byte data[4608];
|
||||
#else
|
||||
XALIGNED(8) byte data[3072];
|
||||
#endif
|
||||
} sp_rsa_ctx_t;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_HAVE_SP_DH) && !defined(NO_DH)
|
||||
typedef struct sp_dh_ctx {
|
||||
#ifdef WOLFSSL_SP_4096
|
||||
XALIGNED(8) byte data[6144];
|
||||
#elif !defined(WOLFSSL_SP_NO_3072)
|
||||
XALIGNED(8) byte data[4608];
|
||||
#else
|
||||
XALIGNED(8) byte data[3072];
|
||||
#endif
|
||||
} sp_dh_ctx_t;
|
||||
#endif
|
||||
#endif /* WOLFSSL_SP_NONBLOCK && (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) */
|
||||
|
||||
#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user