From ad9779cdc141a89e0ea47444319d54d161f332d7 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Wed, 13 Sep 2023 15:27:47 -0400 Subject: [PATCH 1/4] Explicitly define code with WOLFCRYPT_ASYNC_CRYPT_SW --- configure.ac | 63 +++++++++++++++++++----------------- wolfcrypt/src/aes.c | 8 ++--- wolfcrypt/src/des3.c | 4 +-- wolfcrypt/src/dh.c | 4 +-- wolfcrypt/src/ecc.c | 2 +- wolfcrypt/src/rsa.c | 8 ++--- wolfssl/wolfcrypt/settings.h | 1 + 7 files changed, 47 insertions(+), 43 deletions(-) diff --git a/configure.ac b/configure.ac index 4aba828b3..1958e62ca 100644 --- a/configure.ac +++ b/configure.ac @@ -7004,7 +7004,7 @@ AC_ARG_WITH([cavium-v], ENABLED_CAVIUM_V=yes ], [ - ENABLED_CAVIUM_=no + ENABLED_CAVIUM=no ENABLED_CAVIUM_V=no ] ) @@ -7804,6 +7804,30 @@ then AC_MSG_ERROR([please use --with-libz if enabling mcapi.]) fi + +# cryptodev is old name, replaced with cryptocb +AC_ARG_ENABLE([cryptodev], + [AS_HELP_STRING([--enable-cryptodev],[DEPRECATED, use cryptocb instead])], + [ ENABLED_CRYPTOCB=$enableval ],[ ENABLED_CRYPTOCB=no ]) + +# Support for crypto callbacks +AC_ARG_ENABLE([cryptocb], + [AS_HELP_STRING([--enable-cryptocb],[Enable crypto callbacks (default: disabled)])], + [ ENABLED_CRYPTOCB=$enableval ], + [ ENABLED_CRYPTOCB=no ] + ) + +if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" || test "$ENABLED_CAAM" != "no" +then + ENABLED_CRYPTOCB=yes +fi +if test "$ENABLED_CRYPTOCB" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB" +fi + + + # Asynchronous Crypto AC_ARG_ENABLE([asynccrypt], [AS_HELP_STRING([--enable-asynccrypt],[Enable Asynchronous Crypto (default: disabled)])], @@ -7826,6 +7850,7 @@ fi if test "$ENABLED_ASYNCCRYPT" = "yes" then + AC_MSG_NOTICE([Enabling asynchronous support]) if ! test -f ${srcdir}/wolfcrypt/src/async.c || ! test -f ${srcdir}/wolfssl/wolfcrypt/async.h then AC_MSG_ERROR([--enable-asynccrypt requested, but WOLFSSL_ASYNC_CRYPT source files are missing.]) @@ -7835,15 +7860,14 @@ then # If no async backend (hardware or software) has been explicitly enabled, # use the software backend for testing. - if test "x$ENABLED_CAVIUM" = "xno" && test "x$ENABLED_INTEL_QA" = "xno" && - test "x$ENABLED_ASYNCCRYPT_SW" = "xno" + if test "x$ENABLED_CAVIUM" != "xyes" && test "x$ENABLED_INTEL_QA" != "xyes" && test "x$ENABLED_CRYPTOCB" != "xyes" && test "x$ENABLED_PKCALLBACKS" != "xyes" && test "x$ENABLED_ASYNCCRYPT_SW" != "xyes" then - # Async threading is Linux specific + AC_MSG_NOTICE([Enabling asynchronous software simulator]) AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT_SW" + ENABLED_ASYNCCRYPT_SW=yes fi fi - # check for async if using Intel QuckAssist or Cavium if test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_CAVIUM" = "xyes" ; then if test "x$ENABLED_ASYNCCRYPT" = "xno" ; then @@ -7851,8 +7875,7 @@ if test "x$ENABLED_INTEL_QA" = "xyes" || test "x$ENABLED_CAVIUM" = "xyes" ; then fi fi - -# Asynchronous threading +# Asynchronous threading (Linux specific) AC_ARG_ENABLE([asyncthreads], [AS_HELP_STRING([--enable-asyncthreads],[Enable Asynchronous Threading (default: enabled)])], [ ENABLED_ASYNCTHREADS=$enableval ], @@ -7875,28 +7898,6 @@ else fi -# cryptodev is old name, replaced with cryptocb -AC_ARG_ENABLE([cryptodev], - [AS_HELP_STRING([--enable-cryptodev],[DEPRECATED, use cryptocb instead])], - [ ENABLED_CRYPTOCB=$enableval ],[ ENABLED_CRYPTOCB=no ]) - -# Support for crypto callbacks -AC_ARG_ENABLE([cryptocb], - [AS_HELP_STRING([--enable-cryptocb],[Enable crypto callbacks (default: disabled)])], - [ ENABLED_CRYPTOCB=$enableval ], - [ ENABLED_CRYPTOCB=no ] - ) - -if test "x$ENABLED_PKCS11" = "xyes" || test "x$ENABLED_WOLFTPM" = "xyes" || test "$ENABLED_CAAM" != "no" -then - ENABLED_CRYPTOCB=yes -fi -if test "$ENABLED_CRYPTOCB" = "yes" -then - AM_CFLAGS="$AM_CFLAGS -DWOLF_CRYPTO_CB" -fi - - # Session Export AC_ARG_ENABLE([sessionexport], [AS_HELP_STRING([--enable-sessionexport],[Enable export and import of sessions (default: disabled)])], @@ -9515,7 +9516,8 @@ echo " * Stack sizes in tests: $ENABLED_STACKSIZE" echo " * Heap stats in tests: $ENABLED_TRACKMEMORY" echo " * User Crypto: $ENABLED_USER_CRYPTO" echo " * Fast RSA: $ENABLED_FAST_RSA" -echo " * Async Crypto: $ENABLED_ASYNCCRYPT" +echo " * Asynchronous Crypto: $ENABLED_ASYNCCRYPT" +echo " * Asynchronous Crypto (sim): $ENABLED_ASYNCCRYPT_SW" echo " * PKCS#8: $ENABLED_PKCS8" echo " * PKCS#11: $ENABLED_PKCS11" echo " * PKCS#12: $ENABLED_PKCS12" @@ -9536,6 +9538,7 @@ echo " * Inline Code: $ENABLED_INLINE" echo " * Linux AF_ALG: $ENABLED_AFALG" echo " * Linux KCAPI: $ENABLED_KCAPI" echo " * Linux devcrypto: $ENABLED_DEVCRYPTO" +echo " * PK callbacks: $ENABLED_PKCALLBACKS" echo " * Crypto callbacks: $ENABLED_CRYPTOCB" echo " * i.MX CAAM: $ENABLED_CAAM" echo " * IoT-Safe: $ENABLED_IOTSAFE" diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index fd2f9e0e5..d57c124cd 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4152,7 +4152,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz, (const byte*)aes->devKey, aes->keylen, (byte*)aes->reg, AES_BLOCK_SIZE); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&aes->asyncDev, ASYNC_SW_AES_CBC_ENCRYPT)) { WC_ASYNC_SW* sw = &aes->asyncDev.sw; sw->aes.aes = aes; @@ -4317,7 +4317,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz, (const byte*)aes->devKey, aes->keylen, (byte*)aes->reg, AES_BLOCK_SIZE); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&aes->asyncDev, ASYNC_SW_AES_CBC_DECRYPT)) { WC_ASYNC_SW* sw = &aes->asyncDev.sw; sw->aes.aes = aes; @@ -6887,7 +6887,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz, (const byte*)aes->devKey, aes->keylen, iv, ivSz, authTag, authTagSz, authIn, authInSz); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&aes->asyncDev, ASYNC_SW_AES_GCM_ENCRYPT)) { WC_ASYNC_SW* sw = &aes->asyncDev.sw; sw->aes.aes = aes; @@ -7447,7 +7447,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz, (const byte*)aes->devKey, aes->keylen, iv, ivSz, authTag, authTagSz, authIn, authInSz); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&aes->asyncDev, ASYNC_SW_AES_GCM_DECRYPT)) { WC_ASYNC_SW* sw = &aes->asyncDev.sw; sw->aes.aes = aes; diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index 741cfce65..650c33a36 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -1616,7 +1616,7 @@ #elif defined(HAVE_INTEL_QA) return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz, (const byte*)des->devKey, DES3_KEYLEN, (byte*)des->reg, DES3_IVLEN); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&des->asyncDev, ASYNC_SW_DES3_CBC_ENCRYPT)) { WC_ASYNC_SW* sw = &des->asyncDev.sw; sw->des.des = des; @@ -1667,7 +1667,7 @@ #elif defined(HAVE_INTEL_QA) return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz, (const byte*)des->devKey, DES3_KEYLEN, (byte*)des->reg, DES3_IVLEN); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&des->asyncDev, ASYNC_SW_DES3_CBC_DECRYPT)) { WC_ASYNC_SW* sw = &des->asyncDev.sw; sw->des.des = des; diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 086fc048d..e638a51ce 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1433,7 +1433,7 @@ static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng, #elif defined(HAVE_CAVIUM) /* TODO: Not implemented - use software for now */ -#else /* WOLFSSL_ASYNC_CRYPT_SW */ +#elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_DH_GEN)) { WC_ASYNC_SW* sw = &key->asyncDev.sw; sw->dhGen.key = key; @@ -2207,7 +2207,7 @@ static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz, #elif defined(HAVE_CAVIUM) /* TODO: Not implemented - use software for now */ -#else /* WOLFSSL_ASYNC_CRYPT_SW */ +#elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_DH_AGREE)) { WC_ASYNC_SW* sw = &key->asyncDev.sw; sw->dhAgree.key = key; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index eaff8ae8c..59ff57aa6 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -5495,7 +5495,7 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, /* TODO: Not implemented */ #elif defined(HAVE_INTEL_QA) /* Implemented in ecc_make_pub_ex for the pub calc */ - #else + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_ECC_MAKE)) { WC_ASYNC_SW* sw = &key->asyncDev.sw; sw->eccMake.rng = rng; diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index a1446c863..bc2ff370a 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -2767,7 +2767,7 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, } #endif /* WOLFSSL_ASYNC_CRYPT_SW */ - switch(type) { + switch (type) { #ifndef WOLFSSL_RSA_PUBLIC_ONLY case RSA_PRIVATE_DECRYPT: case RSA_PRIVATE_ENCRYPT: @@ -2789,7 +2789,7 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, &key->u.raw, out, outLen); #endif - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #else ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif break; @@ -2807,7 +2807,7 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, ret = IntelQaRsaPublic(&key->asyncDev, in, inLen, &key->e.raw, &key->n.raw, out, outLen); - #else /* WOLFSSL_ASYNC_CRYPT_SW */ + #else ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif break; @@ -4734,7 +4734,7 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) #elif defined(HAVE_INTEL_QA) err = IntelQaRsaKeyGen(&key->asyncDev, key, size, e, rng); goto out; - #else + #elif defined(WOLFSSL_ASYNC_CRYPT_SW) if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_RSA_MAKE)) { WC_ASYNC_SW* sw = &key->asyncDev.sw; sw->rsaMake.rng = rng; diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 7e44d312c..0f9bb0104 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2473,6 +2473,7 @@ extern void uITRON4_free(void *p) ; /* Asynchronous Crypto */ #ifdef WOLFSSL_ASYNC_CRYPT #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \ + !defined(WOLF_CRYPTO_CB) && !defined(HAVE_PK_CALLBACKS) && \ !defined(WOLFSSL_ASYNC_CRYPT_SW) #error No async backend defined with WOLFSSL_ASYNC_CRYPT! #endif From 186d3c2eb494e7799cc3b410adfb34ce094e9a3d Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 18 Sep 2023 13:12:00 -0400 Subject: [PATCH 2/4] Fixes to various Async issues --- src/internal.c | 19 +++++++++++++------ src/tls.c | 31 +++++++++++++++++++++---------- wolfcrypt/src/ecc.c | 5 ----- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/internal.c b/src/internal.c index fadb60e54..382830b6f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5349,7 +5349,7 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ - ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); if (ret != 0) return ret; #endif @@ -38733,18 +38733,25 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL); if (ret != WC_NO_PENDING_E && ret != WC_PENDING_E) { - /* advance key share state if doesn't need called again */ if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) { (*state)++; } - - /* clear event */ + /* clear event and async device */ XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT)); - - /* clear async dev */ ssl->asyncDev = NULL; } + #if !defined(WOLFSSL_ASYNC_CRYPT_SW) && \ + (defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)) + else if (ret == WC_PENDING_E) { + /* Allow the underlying crypto API to be called again to trigger the + * crypto or PK callback. The actual callback must be called, since + * the completion is not detected in the poll like Intel QAT or + * Nitrox */ + ret = wolfEventQueue_Remove(&ssl->ctx->event_queue, event); + printf("Queue_Remove: %d",ret); + } + #endif } else { ret = WC_NO_PENDING_E; diff --git a/src/tls.c b/src/tls.c index 92bac11b5..f719e186f 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7392,7 +7392,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) word16 curveId = (word16) ECC_CURVE_INVALID; ecc_key* eccKey = (ecc_key*)kse->key; - /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ + /* TODO: [TLS13] Get key sizes using wc_ecc_get_curve_size_from_id. */ /* Translate named group to a curve id. */ switch (kse->group) { #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 @@ -7431,9 +7431,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) } if (kse->key == NULL) { - kse->keyLen = keySize; - kse->pubKeyLen = keySize * 2 + 1; - #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13GenEccKeyPair(ssl, kse); if (ret != CRYPTOCB_UNAVAILABLE) { @@ -7447,9 +7444,13 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) return MEMORY_E; } - /* Make an ECC key */ + /* 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) { + kse->keyLen = keySize; + kse->pubKeyLen = keySize * 2 + 1; + /* setting eccKey means okay to call wc_ecc_free */ eccKey = (ecc_key*)kse->key; @@ -7461,11 +7462,21 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) /* set curve info for EccMakeKey "peer" info */ ret = wc_ecc_set_curve(eccKey, kse->keyLen, curveId); if (ret == 0) { - /* 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 + /* Detect when private key generation is done */ + if (ssl->error == 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_PENDING_E) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 59ff57aa6..b3d883bc2 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -5006,11 +5006,6 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { err = wc_ecc_shared_secret_gen_async(private_key, point, out, outlen); - if (err == 0) { - /* exit early */ - RESTORE_VECTOR_REGISTERS(); - return err; - } } else #endif From da39f66ff0d5d942083fd89c7288c741ade1c57c Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Mon, 18 Sep 2023 13:40:01 -0400 Subject: [PATCH 3/4] Remove accidental comment left in. --- src/internal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index 382830b6f..c6ca8442f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -38749,7 +38749,6 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) * the completion is not detected in the poll like Intel QAT or * Nitrox */ ret = wolfEventQueue_Remove(&ssl->ctx->event_queue, event); - printf("Queue_Remove: %d",ret); } #endif } From 9ed19cddfad128b9b0b97da4704e2f6aebbba9a7 Mon Sep 17 00:00:00 2001 From: Andras Fekete Date: Wed, 20 Sep 2023 12:23:14 -0400 Subject: [PATCH 4/4] Need to increment state after the async task completes --- src/internal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal.c b/src/internal.c index c6ca8442f..7566fe93e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5349,7 +5349,7 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ - ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); if (ret != 0) return ret; #endif