From 17a34c58997465849c3adb9f170d9cc64acd6f58 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 15 Aug 2016 13:59:41 -0600 Subject: [PATCH 1/3] Added asynchronous wolfCrypt RSA, TLS client and Cavium Nitrox V support. Asynchronous wolfSSL client support for "DoServerKeyExchange", "SendClientKeyExchange", "SendCertificateVerify" and "DoCertificateVerify". Fixes for async DTLS. Refactor of the wolf event and async handling for use in wolfCrypt. Refactor of the async device support so its hardware agnostic. Added Cavium Nitrox V support (Nitrox tested using SDK v0.2 CNN55XX-SDK with new configure "--with-cavium-v=/dir" option). Moved Nitrox specific functions to new port file "port/cavium/cavium_nitrox.c". RSA refactor to handle async with states. RSA optimization for using dpraw for private key decode. Use double linked list in wolf event for faster/cleaner code. Use typedef for wolf event flag. Cleanup of the async error codes. wolfCrypt test and benchmark support for async RSA. Asynchronous mode enabled using "./configure --enable-asynccrypt". If no async hardware is defined then the internal async simulator (WOLFSSL_ASYNC_CRYPT_TEST) is used. Note: Using async mode requires async.c/h files from wolfSSL. If interested in using asynchronous mode please send email to info@wolfssl.com. --- .gitignore | 2 + IDE/WIN/wolfssl-fips.vcxproj | 1 + autogen.sh | 4 +- configure.ac | 79 +- cyassl/ctaocrypt/aes.h | 5 - cyassl/ctaocrypt/arc4.h | 5 +- cyassl/ctaocrypt/des3.h | 6 +- cyassl/ctaocrypt/hmac.h | 6 +- cyassl/ctaocrypt/rsa.h | 6 +- examples/client/client.c | 43 +- examples/echoclient/echoclient.c | 33 +- examples/echoserver/echoserver.c | 28 +- examples/server/server.c | 27 +- mcapi/crypto.c | 1 + mcapi/crypto.h | 2 +- src/include.am | 12 +- src/internal.c | 5403 +++++++++-------- src/keys.c | 52 +- src/ssl.c | 135 +- tests/api.c | 93 +- tests/unit.c | 9 - testsuite/testsuite.c | 10 - wolfcrypt/benchmark/benchmark.c | 364 +- wolfcrypt/src/aes.c | 168 +- wolfcrypt/src/arc4.c | 86 +- wolfcrypt/src/asn.c | 168 +- wolfcrypt/src/des3.c | 161 +- wolfcrypt/src/ecc.c | 201 +- wolfcrypt/src/error.c | 20 +- wolfcrypt/src/hash.c | 38 +- wolfcrypt/src/hmac.c | 242 +- wolfcrypt/src/include.am | 4 + wolfcrypt/src/port/cavium/README.md | 32 + wolfcrypt/src/port/cavium/cavium_nitrox.c | 778 +++ wolfcrypt/src/random.c | 78 +- wolfcrypt/src/rsa.c | 1439 ++--- wolfcrypt/src/wolfevent.c | 274 + wolfcrypt/test/test.c | 413 +- wolfcrypt/user-crypto/include/user_rsa.h | 1 + wolfcrypt/user-crypto/src/rsa.c | 8 +- wolfssl-ntru.vcproj | 4 + wolfssl.vcproj | 4 + wolfssl.vcxproj | 1 + wolfssl/error-ssl.h | 1 - wolfssl/internal.h | 42 +- wolfssl/ssl.h | 48 +- wolfssl/test.h | 48 +- wolfssl/wolfcrypt/aes.h | 27 +- wolfssl/wolfcrypt/arc4.h | 16 +- wolfssl/wolfcrypt/des3.h | 17 +- wolfssl/wolfcrypt/ecc.h | 16 +- wolfssl/wolfcrypt/error-crypt.h | 9 +- wolfssl/wolfcrypt/hash.h | 2 +- wolfssl/wolfcrypt/hmac.h | 44 +- wolfssl/wolfcrypt/include.am | 7 +- wolfssl/wolfcrypt/integer.h | 3 + wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h | 165 + wolfssl/wolfcrypt/random.h | 16 +- wolfssl/wolfcrypt/rsa.h | 55 +- wolfssl/wolfcrypt/settings.h | 7 +- wolfssl/wolfcrypt/tfm.h | 3 + wolfssl/wolfcrypt/types.h | 7 +- wolfssl/wolfcrypt/wolfevent.h | 103 + 63 files changed, 6611 insertions(+), 4471 deletions(-) create mode 100644 wolfcrypt/src/port/cavium/README.md create mode 100644 wolfcrypt/src/port/cavium/cavium_nitrox.c create mode 100644 wolfcrypt/src/wolfevent.c create mode 100644 wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h create mode 100644 wolfssl/wolfcrypt/wolfevent.h diff --git a/.gitignore b/.gitignore index 47c38e3f1..ab22d786e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,8 @@ fips_test.c fips src/async.c wolfssl/async.h +wolfcrypt/src/async.c +wolfssl/wolfcrypt/async.h ctaocrypt/benchmark/benchmark ctaocrypt/test/testctaocrypt wolfcrypt/benchmark/benchmark diff --git a/IDE/WIN/wolfssl-fips.vcxproj b/IDE/WIN/wolfssl-fips.vcxproj index 74c1041ab..8575aeb9a 100644 --- a/IDE/WIN/wolfssl-fips.vcxproj +++ b/IDE/WIN/wolfssl-fips.vcxproj @@ -300,6 +300,7 @@ + diff --git a/autogen.sh b/autogen.sh index 971878e33..7d5ffd856 100755 --- a/autogen.sh +++ b/autogen.sh @@ -20,8 +20,8 @@ if test -d .git; then touch ./ctaocrypt/src/fips_test.c # touch async crypt files - touch ./src/async.c - touch ./wolfssl/async.h + touch ./wolfcrypt/src/async.c + touch ./wolfssl/wolfcrypt/async.h else WARNINGS="all" fi diff --git a/configure.ac b/configure.ac index ed283b5ef..79d44702e 100644 --- a/configure.ac +++ b/configure.ac @@ -2439,28 +2439,69 @@ AC_ARG_WITH([cavium], AC_MSG_CHECKING([for cavium]) CPPFLAGS="$CPPFLAGS -DHAVE_CAVIUM" - if test "x$withval" == "xyes" ; then - AC_MSG_ERROR([need a PATH for --with-cavium]) - fi - if test "x$withval" != "xno" ; then - trycaviumdir=$withval - fi + if test "x$withval" == "xyes" ; then + AC_MSG_ERROR([need a PATH for --with-cavium]) + fi + if test "x$withval" != "xno" ; then + trycaviumdir=$withval + fi - LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/cavium_common.o" - CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" + LDFLAGS="$AM_LDFLAGS $trycaviumdir/api/cavium_common.o" + CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cavium_common.h"]], [[ CspShutdown(CAVIUM_DEV_ID); ]])],[ cavium_linked=yes ],[ cavium_linked=no ]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cavium_common.h"]], [[ CspShutdown(CAVIUM_DEV_ID); ]])],[ cavium_linked=yes ],[ cavium_linked=no ]) - if test "x$cavium_linked" == "xno" ; then - AC_MSG_ERROR([cavium isn't found. - If it's already installed, specify its path using --with-cavium=/dir/]) - fi - AC_MSG_RESULT([yes]) - enable_shared=no - enable_static=yes + if test "x$cavium_linked" == "xno" ; then + AC_MSG_ERROR([cavium isn't found. + If it's already installed, specify its path using --with-cavium=/dir/]) + fi + AC_MSG_RESULT([yes]) + enable_shared=no + enable_static=yes + ENABLED_CAVIUM=yes + ], + [ ENABLED_CAVIUM=no ] +) + +# cavium V +trycaviumdir="" +AC_ARG_WITH([cavium-v], + [ --with-cavium-v=PATH PATH to Cavium V/software dir ], + [ + AC_MSG_CHECKING([for cavium]) + CPPFLAGS="$CPPFLAGS -DHAVE_CAVIUM -DHAVE_CAVIUM_V" + + if test "x$withval" == "xyes" ; then + AC_MSG_ERROR([need a PATH for --with-cavium]) + fi + if test "x$withval" != "xno" ; then + trycaviumdir=$withval + fi + + LDFLAGS="$AM_LDFLAGS $trycaviumdir/utils/sample_tests/cavium_common.o $trycaviumdir/utils/sample_tests/cavium_sym_crypto.o $trycaviumdir/utils/sample_tests/cavium_asym_crypto.o" + CPPFLAGS="$CPPFLAGS -I$trycaviumdir/include" + + #AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "cavium_common.h"]], [[ CspShutdown(0); ]])],[ cavium_linked=yes ],[ cavium_linked=no ]) + + if test "x$cavium_linked" == "xno" ; then + AC_MSG_ERROR([cavium isn't found. + If it's already installed, specify its path using --with-cavium-v=/dir/]) + fi + AC_MSG_RESULT([yes]) + + enable_shared=no + enable_static=yes + ENABLED_CAVIUM=yes + ENABLED_CAVIUM_V=yes + ], + [ + ENABLED_CAVIUM_=no + ENABLED_CAVIUM_V=no ] ) +AM_CONDITIONAL([BUILD_CAVIUM], [test "x$ENABLED_CAVIUM" = "xyes"]) + # Fast RSA using Intel IPP ippdir="${srcdir}/IPP" @@ -2668,7 +2709,7 @@ AC_ARG_ENABLE([asynccrypt], if test "$ENABLED_ASYNCCRYPT" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT -DHAVE_WOLF_EVENT" # if Cavium not enabled the use async simulator for testing if test "x$ENABLED_CAVIUM" = "xno" @@ -2679,6 +2720,9 @@ fi AM_CONDITIONAL([BUILD_ASYNCCRYPT], [test "x$ENABLED_ASYNCCRYPT" = "xyes"]) +AM_CONDITIONAL([BUILD_WOLFEVENT], [test "x$ENABLED_ASYNCCRYPT" = "xyes"]) + + # Session Export AC_ARG_ENABLE([sessionexport], @@ -3069,6 +3113,7 @@ echo " * Examples: $ENABLED_EXAMPLES" echo " * User Crypto: $ENABLED_USER_CRYPTO" echo " * Fast RSA: $ENABLED_FAST_RSA" echo " * Async Crypto: $ENABLED_ASYNCCRYPT" +echo " * Cavium: $ENABLED_CAVIUM" echo "" echo "---" diff --git a/cyassl/ctaocrypt/aes.h b/cyassl/ctaocrypt/aes.h index 8ad064f06..78ab33dcb 100644 --- a/cyassl/ctaocrypt/aes.h +++ b/cyassl/ctaocrypt/aes.h @@ -56,11 +56,6 @@ #define AesCcmDecrypt wc_AesCcmDecrypt #endif /* HAVE_AESCCM */ -#ifdef HAVE_CAVIUM - #define AesInitCavium wc_AesInitCavium - #define AesFreeCavium wc_AesFreeCavium -#endif - #endif /* CTAO_CRYPT_AES_H */ #endif /* NO_AES */ diff --git a/cyassl/ctaocrypt/arc4.h b/cyassl/ctaocrypt/arc4.h index 093d8465b..c99eb3cbd 100644 --- a/cyassl/ctaocrypt/arc4.h +++ b/cyassl/ctaocrypt/arc4.h @@ -26,11 +26,10 @@ /* for arc4 reverse compatibility */ #ifndef NO_RC4 #include - #define CYASSL_ARC4_CAVIUM_MAGIC WOLFSSL_ARC4_CAVIUM_MAGIC #define Arc4Process wc_Arc4Process #define Arc4SetKey wc_Arc4SetKey - #define Arc4InitCavium wc_Arc4InitCavium - #define Arc4FreeCavium wc_Arc4FreeCavium + #define Arc4AsyncInit wc_Arc4AsyncInit + #define Arc4AsyncFree wc_Arc4AsyncFree #endif #endif /* CTAO_CRYPT_ARC4_H */ diff --git a/cyassl/ctaocrypt/des3.h b/cyassl/ctaocrypt/des3.h index 674d96840..40719554e 100644 --- a/cyassl/ctaocrypt/des3.h +++ b/cyassl/ctaocrypt/des3.h @@ -39,9 +39,9 @@ #define Des3_CbcEncrypt wc_Des3_CbcEncrypt #define Des3_CbcDecrypt wc_Des3_CbcDecrypt #define Des3_CbcDecryptWithKey wc_Des3_CbcDecryptWithKey -#ifdef HAVE_CAVIUM - #define Des3_InitCavium wc_Des3_InitCavium - #define Des3_FreeCavium wc_Des3_FreeCavium +#ifdef WOLFSSL_ASYNC_CRYPT + #define Des3AsyncInit wc_Des3AsyncInit + #define Des3AsyncFree wc_Des3AsyncFree #endif #endif /* NO_DES3 */ diff --git a/cyassl/ctaocrypt/hmac.h b/cyassl/ctaocrypt/hmac.h index b582395e3..505e44a7c 100644 --- a/cyassl/ctaocrypt/hmac.h +++ b/cyassl/ctaocrypt/hmac.h @@ -30,9 +30,9 @@ #define HmacSetKey wc_HmacSetKey #define HmacUpdate wc_HmacUpdate #define HmacFinal wc_HmacFinal -#ifdef HAVE_CAVIUM - #define HmacInitCavium wc_HmacInitCavium - #define HmacFreeCavium wc_HmacFreeCavium +#ifdef WOLFSSL_ASYNC_CRYPT + #define HmacAsyncInit wc_HmacAsyncInit + #define HmacAsyncFree wc_HmacAsyncFree #endif #define CyaSSL_GetHmacMaxSize wolfSSL_GetHmacMaxSize #ifdef HAVE_HKDF diff --git a/cyassl/ctaocrypt/rsa.h b/cyassl/ctaocrypt/rsa.h index 3c8a9f23b..ecb7de485 100644 --- a/cyassl/ctaocrypt/rsa.h +++ b/cyassl/ctaocrypt/rsa.h @@ -47,9 +47,9 @@ #define RsaKeyToDer wc_RsaKeyToDer #endif -#ifdef HAVE_CAVIUM - #define RsaInitCavium wc_RsaInitCavium - #define RsaFreeCavium wc_RsaFreeCavium +#ifdef WOLFSSL_ASYNC_CRYPT + #define RsaAsyncInit wc_RsaAsyncInit + #define RsaAsyncFree wc_RsaAsyncFree #endif #endif /* CTAO_CRYPT_RSA_H */ diff --git a/examples/client/client.c b/examples/client/client.c index 0469be812..f814c0d4e 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -53,6 +53,10 @@ #include "examples/client/client.h" +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + /* Note on using port 0: the client standalone example doesn't utilize the * port 0 port sharing; that is used by (1) the server in external control * test mode and (2) the testsuite which uses this code and sets up the correct @@ -78,7 +82,7 @@ static void NonBlockingSSL_Connect(WOLFSSL* ssl) #endif int error = wolfSSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)wolfSSL_get_fd(ssl); - int select_ret; + int select_ret = 0; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE || @@ -91,15 +95,17 @@ static void NonBlockingSSL_Connect(WOLFSSL* ssl) printf("... client would write block\n"); #ifdef WOLFSSL_ASYNC_CRYPT else if (error == WC_PENDING_E) { - ret = AsyncCryptPoll(ssl); + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); if (ret < 0) { break; } else if (ret == 0) { continue; } } #endif -#ifdef WOLFSSL_DTLS - currTimeout = wolfSSL_dtls_get_current_timeout(ssl); -#endif - select_ret = tcp_select(sockfd, currTimeout); + if (error != WC_PENDING_E) { + #ifdef WOLFSSL_DTLS + currTimeout = wolfSSL_dtls_get_current_timeout(ssl); + #endif + select_ret = tcp_select(sockfd, currTimeout); + } if ((select_ret == TEST_RECV_READY) || (select_ret == TEST_ERROR_READY)) { @@ -1175,9 +1181,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb); #endif -#ifdef HAVE_CAVIUM - wolfSSL_CTX_UseCavium(ctx, CAVIUM_DEV_ID); -#endif +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + if (ret != 0) { + err_sys("Async device open failed"); + } + wolfSSL_CTX_UseAsync(ctx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_SNI if (sniHostName) @@ -1343,7 +1353,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) do { #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_PENDING_E) { - ret = AsyncCryptPoll(ssl); + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); if (ret < 0) { break; } else if (ret == 0) { continue; } } #endif @@ -1622,6 +1632,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ((func_args*)args)->return_code = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + #if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) if (trackMemory) ShowMemoryTracker(); @@ -1650,11 +1664,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { func_args args; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ StartTCP(); @@ -1674,10 +1683,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif wolfSSL_Cleanup(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 2c5f10b2b..6cb836e6a 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -52,6 +52,11 @@ #include "examples/echoclient/echoclient.h" +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + + void echoclient_test(void* args) { SOCKET_T sockfd = 0; @@ -162,9 +167,17 @@ void echoclient_test(void* args) SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - #if defined(WOLFSSL_MDK_ARM) +#if defined(WOLFSSL_MDK_ARM) CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - #endif +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + if (ret != 0) { + err_sys("Async device open failed"); + } + wolfSSL_CTX_UseAsync(ctx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); tcp_connect(&sockfd, yasslIP, port, doDTLS, ssl); @@ -178,7 +191,7 @@ void echoclient_test(void* args) do { #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_PENDING_E) { - ret = AsyncCryptPoll(ssl); + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); if (ret < 0) { break; } else if (ret == 0) { continue; } } #endif @@ -250,6 +263,10 @@ void echoclient_test(void* args) SSL_free(ssl); SSL_CTX_free(ctx); +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + fflush(fout); if (inCreated) fclose(fin); if (outCreated) fclose(fout); @@ -266,12 +283,6 @@ void echoclient_test(void* args) { func_args args; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) err_sys("Whitewood netRandom global config failed"); @@ -293,10 +304,6 @@ void echoclient_test(void* args) CyaSSL_Cleanup(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 65ca4c46c..d917c946b 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -53,6 +53,10 @@ #include "examples/echoserver/echoserver.h" +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + #define SVR_COMMAND_SIZE 256 static void SignalReady(void* args, word16 port) @@ -226,6 +230,14 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #endif } +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + if (ret != 0) { + err_sys("Async device open failed"); + } + wolfSSL_CTX_UseAsync(ctx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + SignalReady(args, port); while (!shutDown) { @@ -272,7 +284,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) do { #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_PENDING_E) { - ret = AsyncCryptPoll(ssl); + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); if (ret < 0) { break; } else if (ret == 0) { continue; } } #endif @@ -390,6 +402,10 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) TicketCleanup(); #endif +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + #ifndef CYASSL_TIRTOS return 0; #endif @@ -403,12 +419,6 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) { func_args args; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) err_sys("Whitewood netRandom global config failed"); @@ -427,10 +437,6 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) echoserver_test(&args); CyaSSL_Cleanup(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); diff --git a/examples/server/server.c b/examples/server/server.c index b5dc3de2d..74feccc0b 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -55,6 +55,10 @@ #include "examples/server/server.h" +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif + /* Note on using port 0: if the server uses port 0 to bind an ephemeral port * number and is using the ready file for scripted testing, the code in * test.h will write the actual port number into the ready file for use @@ -806,6 +810,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #endif /* USE_WINDOWS_API */ +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + if (ret != 0) { + err_sys("Async device open failed"); + } + wolfSSL_CTX_UseAsync(ctx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + while (1) { /* allow resume option */ if(resumeCount > 1) { @@ -947,7 +959,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) do { #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_PENDING_E) { - ret = AsyncCryptPoll(ssl); + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); if (ret < 0) { break; } else if (ret == 0) { continue; } } #endif @@ -1088,6 +1100,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) TicketCleanup(); #endif +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + /* There are use cases when these assignments are not read. To avoid * potential confusion those warnings have been handled here. */ @@ -1112,11 +1128,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) func_args args; tcp_ready ready; -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ StartTCP(); @@ -1139,10 +1150,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) CyaSSL_Cleanup(); FreeTcpReady(&ready); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); diff --git a/mcapi/crypto.c b/mcapi/crypto.c index c8a99f579..d0216035d 100644 --- a/mcapi/crypto.c +++ b/mcapi/crypto.c @@ -223,6 +223,7 @@ int CRYPT_SHA512_Finalize(CRYPT_SHA512_CTX* sha512, unsigned char* digest) int CRYPT_HMAC_SetKey(CRYPT_HMAC_CTX* hmac, int type, const unsigned char* key, unsigned int sz) { + /* compile-time check to verify CRYPT_HMAC_CTX is large enough to hold Hmac */ typedef char hmac_test[sizeof(CRYPT_HMAC_CTX) >= sizeof(Hmac) ? 1 : -1]; (void)sizeof(hmac_test); diff --git a/mcapi/crypto.h b/mcapi/crypto.h index 8fe323631..3a6a87a6f 100644 --- a/mcapi/crypto.h +++ b/mcapi/crypto.h @@ -104,7 +104,7 @@ enum { /* HMAC */ typedef struct CRYPT_HMAC_CTX { - long long holder[67]; /* big enough to hold internal, but check on init */ + long long holder[68]; /* big enough to hold internal, but check on init */ } CRYPT_HMAC_CTX; int CRYPT_HMAC_SetKey(CRYPT_HMAC_CTX*, int, const unsigned char*, unsigned int); diff --git a/src/include.am b/src/include.am index 5044bd9a4..8dc391ce8 100644 --- a/src/include.am +++ b/src/include.am @@ -65,6 +65,14 @@ src_libwolfssl_la_SOURCES += \ wolfcrypt/src/sha256.c \ wolfcrypt/src/hash.c +if BUILD_WOLFEVENT +src_libwolfssl_la_SOURCES += wolfcrypt/src/wolfevent.c +endif + +if BUILD_ASYNCCRYPT +src_libwolfssl_la_SOURCES += wolfcrypt/src/async.c +endif + if !BUILD_USER_RSA if BUILD_RSA if BUILD_FAST_RSA @@ -254,8 +262,4 @@ if BUILD_SNIFFER src_libwolfssl_la_SOURCES += src/sniffer.c endif -if BUILD_ASYNCCRYPT -src_libwolfssl_la_SOURCES += src/async.c -endif - endif # !BUILD_CRYPTONLY diff --git a/src/internal.c b/src/internal.c index 0fba76ab6..6f11389e3 100755 --- a/src/internal.c +++ b/src/internal.c @@ -588,15 +588,15 @@ static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = keys->encryptionOn; exp[idx++] = keys->decryptedCur; - #ifdef WORD64_AVAILABLE +#ifdef WORD64_AVAILABLE c64toa(keys->dtls_state.window, exp + idx); idx += OPAQUE64_LEN; c64toa(keys->dtls_state.prevWindow, exp + idx); idx += OPAQUE64_LEN; - #else +#else c32toa(keys->dtls_state.window, exp + idx); idx += OPAQUE32_LEN; c32toa(0, exp + idx); idx += OPAQUE32_LEN; c32toa(keys->dtls_state.prevWindow, exp + idx); idx += OPAQUE32_LEN; c32toa(0, exp + idx); idx += OPAQUE32_LEN; - #endif +#endif #ifdef HAVE_TRUNCATED_HMAC sz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size; @@ -713,15 +713,15 @@ static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) keys->encryptionOn = exp[idx++]; keys->decryptedCur = exp[idx++]; - #ifdef WORD64_AVAILABLE +#ifdef WORD64_AVAILABLE ato64(exp + idx, &keys->dtls_state.window); idx += OPAQUE64_LEN; ato64(exp + idx, &keys->dtls_state.prevWindow); idx += OPAQUE64_LEN; - #else +#else ato32(exp + idx, &keys->dtls_state.window); idx += OPAQUE32_LEN; ato32(exp + idx, 0); idx += OPAQUE32_LEN; ato32(exp + idx, &keys->dtls_state.prevWindow); idx += OPAQUE32_LEN; ato32(exp + idx, 0); idx += OPAQUE32_LEN; - #endif +#endif #ifdef HAVE_TRUNCATED_HMAC ssl->truncated_hmac = exp[idx++]; @@ -1300,61 +1300,6 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz) #endif /* WOLFSSL_SESSION_EXPORT */ -#ifdef HAVE_WOLF_EVENT -int wolfSSL_EventInit(WOLFSSL* ssl, WOLF_EVENT_TYPE type) -{ - if (!ssl) { - return BAD_FUNC_ARG; - } - - if (ssl->event.pending) { - WOLFSSL_MSG("ssl.event already pending!"); - return BAD_COND_E; - } - - XMEMSET(&ssl->event, 0, sizeof(WOLF_EVENT)); - ssl->event.ssl = ssl; - ssl->event.type = type; - - return 0; -} - -int wolfSSL_CTX_EventPush(WOLFSSL_CTX* ctx, WOLF_EVENT* event) -{ - int ret; - - if (ctx == NULL || event == NULL) { - return BAD_FUNC_ARG; - } - -#ifndef SINGLE_THREADED - if (LockMutex(&ctx->event_queue.lock) != 0) { - return BAD_MUTEX_E; - } -#endif - - /* Setup event */ - event->next = NULL; - event->pending = 1; - - if (ctx->event_queue.tail == NULL) { - ctx->event_queue.head = event; - } - else { - ctx->event_queue.tail->next = event; - } - ctx->event_queue.tail = event; /* add to the end either way */ - ret = 0; - -#ifndef SINGLE_THREADED - UnLockMutex(&ctx->event_queue.lock); -#endif - - return ret; -} -#endif /* HAVE_WOLF_EVENT */ - - void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) { method->version = pv; @@ -1366,6 +1311,8 @@ void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) /* Initialize SSL context, return 0 on success */ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) { + int ret = 0; + XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX)); ctx->method = method; @@ -1424,9 +1371,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) } #endif -#ifdef HAVE_CAVIUM - ctx->devId = NO_CAVIUM_DEVICE; -#endif + ctx->devId = INVALID_DEVID; #ifndef NO_CERTS ctx->cm = wolfSSL_CertManagerNew_ex(heap); @@ -1441,18 +1386,12 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #endif #ifdef HAVE_WOLF_EVENT - XMEMSET(&ctx->event_queue, 0, sizeof(WOLF_EVENT_QUEUE)); - #ifndef SINGLE_THREADED - if (InitMutex(&ctx->event_queue.lock) < 0) { - WOLFSSL_MSG("Mutex error on CTX event queue init"); - return BAD_MUTEX_E; - } - #endif + ret = wolfEventQueue_Init(&ctx->event_queue); #endif /* HAVE_WOLF_EVENT */ ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */ - return 0; + return ret; } @@ -1464,9 +1403,7 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) (void)i; #ifdef HAVE_WOLF_EVENT - #ifndef SINGLE_THREADED - FreeMutex(&ctx->event_queue.lock); - #endif + wolfEventQueue_Free(&ctx->event_queue); #endif /* HAVE_WOLF_EVENT */ XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD); @@ -1528,7 +1465,7 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) } #endif } -#endif +#endif /* WOLFSSL_STATIC_MEMORY */ } @@ -1616,30 +1553,30 @@ void FreeCiphers(WOLFSSL* ssl) { (void)ssl; #ifdef BUILD_ARC4 - #ifdef HAVE_CAVIUM - if (ssl->devId != NO_CAVIUM_DEVICE) { - wc_Arc4FreeCavium(ssl->encrypt.arc4); - wc_Arc4FreeCavium(ssl->decrypt.arc4); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->devId != INVALID_DEVID) { + wc_Arc4AsyncFree(ssl->encrypt.arc4); + wc_Arc4AsyncFree(ssl->decrypt.arc4); } #endif XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_DES3 - #ifdef HAVE_CAVIUM - if (ssl->devId != NO_CAVIUM_DEVICE) { - wc_Des3_FreeCavium(ssl->encrypt.des3); - wc_Des3_FreeCavium(ssl->decrypt.des3); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->devId != INVALID_DEVID) { + wc_Des3AsyncFree(ssl->encrypt.des3); + wc_Des3AsyncFree(ssl->decrypt.des3); } #endif XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_AES - #ifdef HAVE_CAVIUM - if (ssl->devId != NO_CAVIUM_DEVICE) { - wc_AesFreeCavium(ssl->encrypt.aes); - wc_AesFreeCavium(ssl->decrypt.aes); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->devId != INVALID_DEVID) { + wc_AesAsyncFree(ssl->encrypt.aes); + wc_AesAsyncFree(ssl->decrypt.aes); } #endif XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); @@ -2681,24 +2618,7 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, (void)keySz; (void)ctx; -#if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_RSA_SIGN; - ssl->asyncCryptTest.rsaSign.in = in; - ssl->asyncCryptTest.rsaSign.inSz = inSz; - ssl->asyncCryptTest.rsaSign.out = out; - ssl->asyncCryptTest.rsaSign.outSz = outSz; - ssl->asyncCryptTest.rsaSign.keyBuf = keyBuf; - ssl->asyncCryptTest.rsaSign.keySz = keySz; - ssl->asyncCryptTest.rsaSign.key = key; - #if defined(HAVE_PK_CALLBACKS) - ssl->asyncCryptTest.ctx = ctx; - #endif - return WC_PENDING_E; - } -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + WOLFSSL_ENTER("RsaSign"); #if defined(HAVE_PK_CALLBACKS) if (ssl->ctx->RsaSignCb) { @@ -2710,11 +2630,26 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, { ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng); } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ if (ret > 0) { *outSz = ret; ret = 0; } + WOLFSSL_LEAVE("RsaSign", ret); + return ret; } @@ -2728,6 +2663,8 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, (void)keySz; (void)ctx; + WOLFSSL_ENTER("RsaVerify"); + #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->RsaVerifyCb) { ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx); @@ -2737,18 +2674,27 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, { ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("RsaVerify", ret); + return ret; } /* Verify RSA signature, 0 on success */ -int VerifyRsaSign(WOLFSSL* ssl, const byte* sig, word32 sigSz, +int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, const byte* plain, word32 plainSz, RsaKey* key) { - #ifdef WOLFSSL_SMALL_STACK - byte* verifySig = NULL; - #else - byte verifySig[ENCRYPT_LEN]; - #endif byte* out = NULL; /* inline result */ int ret; @@ -2756,8 +2702,7 @@ int VerifyRsaSign(WOLFSSL* ssl, const byte* sig, word32 sigSz, WOLFSSL_ENTER("VerifyRsaSign"); - if (sig == NULL || plain == NULL || key == NULL) { - WOLFSSL_MSG("Null pointer input"); + if (verifySig == NULL || plain == NULL || key == NULL) { return BAD_FUNC_ARG; } @@ -2766,26 +2711,30 @@ int VerifyRsaSign(WOLFSSL* ssl, const byte* sig, word32 sigSz, return BUFFER_E; } - #ifdef WOLFSSL_SMALL_STACK - verifySig = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_SIGNATURE); - if (verifySig == NULL) - return MEMORY_ERROR; - #endif - - XMEMCPY(verifySig, sig, sigSz); ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); - if (ret != (int)plainSz || !out || XMEMCMP(plain, out, plainSz) != 0) { - WOLFSSL_MSG("RSA Signature verification failed"); - ret = RSA_SIGN_FAULT; - } else { - ret = 0; /* RSA reset */ + if (ret > 0) { + if (ret != (int)plainSz || !out || + XMEMCMP(plain, out, plainSz) != 0) { + WOLFSSL_MSG("RSA Signature verification failed"); + ret = RSA_SIGN_FAULT; + } else { + ret = 0; /* RSA reset */ + } } - #ifdef WOLFSSL_SMALL_STACK - XFREE(verifySig, NULL, DYNAMIC_TYPE_SIGNATURE); - #endif + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("VerifyRsaSign", ret); return ret; } @@ -2800,24 +2749,7 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, (void)keySz; (void)ctx; -#if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_RSA_DEC; - ssl->asyncCryptTest.rsaDec.in = in; - ssl->asyncCryptTest.rsaDec.inSz = inSz; - ssl->asyncCryptTest.rsaDec.out = out; - ssl->asyncCryptTest.rsaDec.outSz = outSz; - ssl->asyncCryptTest.rsaDec.keyBuf = keyBuf; - ssl->asyncCryptTest.rsaDec.keySz = keySz; - ssl->asyncCryptTest.rsaDec.key = key; - #if defined(HAVE_PK_CALLBACKS) - ssl->asyncCryptTest.ctx = ctx; - #endif - return WC_PENDING_E; - } -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + WOLFSSL_ENTER("RsaDec"); #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->RsaDecCb) { @@ -2835,10 +2767,70 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, ret = wc_RsaPrivateDecryptInline(in, inSz, out, key); } + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ if (ret > 0) { *outSz = ret; ret = 0; } + + WOLFSSL_LEAVE("RsaDec", ret); + + return ret; +} + +int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, + RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx) +{ + int ret; + + (void)ssl; + (void)keyBuf; + (void)keySz; + (void)ctx; + + WOLFSSL_ENTER("RsaEnc"); + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaEncCb) { + ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, + ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng); + } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaEnc", ret); + return ret; } @@ -2856,24 +2848,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, (void)keySz; (void)ctx; -#if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_ECC_SIGN; - ssl->asyncCryptTest.eccSign.in = in; - ssl->asyncCryptTest.eccSign.inSz = inSz; - ssl->asyncCryptTest.eccSign.out = out; - ssl->asyncCryptTest.eccSign.outSz = outSz; - ssl->asyncCryptTest.eccSign.keyBuf = keyBuf; - ssl->asyncCryptTest.eccSign.keySz = keySz; - ssl->asyncCryptTest.eccSign.key = key; - #if defined(HAVE_PK_CALLBACKS) - ssl->asyncCryptTest.ctx = ctx; - #endif - return WC_PENDING_E; - } -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + WOLFSSL_ENTER("EccSign"); #if defined(HAVE_PK_CALLBACKS) if (ssl->ctx->EccSignCb) { @@ -2885,10 +2860,24 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, { ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key); } + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccSign", ret); + return ret; } -int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, +int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx) { @@ -2899,18 +2888,35 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, (void)keySz; (void)ctx; + WOLFSSL_ENTER("EccVerify"); + #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccVerifyCb) { ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz, &verify, ctx); } else -#endif +#endif /* HAVE_PK_CALLBACKS */ { ret = wc_ecc_verify_hash(in, inSz, out, outSz, &verify, key); } - ret = (ret != 0 || verify == 0) ? VERIFY_SIGN_ERROR : 0; + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + { + ret = (ret != 0 || verify == 0) ? VERIFY_SIGN_ERROR : 0; + } + + WOLFSSL_LEAVE("EccVerify", ret); return ret; } @@ -2922,44 +2928,56 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, (void)ssl; -#if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_ECC_SHARED_SEC; - ssl->asyncCryptTest.eccSharedSec.private_key = priv_key; - ssl->asyncCryptTest.eccSharedSec.public_key = pub_key; - ssl->asyncCryptTest.eccSharedSec.out = out; - ssl->asyncCryptTest.eccSharedSec.outLen = outSz; - return WC_PENDING_E; - } -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + WOLFSSL_ENTER("EccSharedSecret"); ret = wc_ecc_shared_secret(priv_key, pub_key, out, outSz); + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &priv_key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; + } + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccSharedSecret", ret); + return ret; } -int EccMakeTempKey(WOLFSSL* ssl) +int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) { int ret = 0; - if (ssl->eccTempKeyPresent == 0) { - #if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_ECC_TMPKEY_GEN; - return WC_PENDING_E; - } - #endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + int keySz = 0; - ret = wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz, - ssl->eccTempKey); - if (ret == MP_OKAY) { - ssl->eccTempKeyPresent = 1; - ret = 0; + WOLFSSL_ENTER("EccMakeKey"); + + if (peer == NULL) { + keySz = ssl->eccTempKeySz; + } + else { + keySz = peer->dp->size; + } + + /* TODO: Implement _ex version here */ + ret = wc_ecc_make_key(ssl->rng, keySz, key); + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfAsync_EventInit(&ssl->event, + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); + if (ret == 0) { + ret = WC_PENDING_E; } } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccMakeKey", ret); + return ret; } @@ -2979,29 +2997,13 @@ int DhGenKeyPair(WOLFSSL* ssl, int ret; DhKey dhKey; -#if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_DH_GEN; - ssl->asyncCryptTest.dhGen.p = p; - ssl->asyncCryptTest.dhGen.pSz = pSz; - ssl->asyncCryptTest.dhGen.g = g; - ssl->asyncCryptTest.dhGen.gSz = gSz; - ssl->asyncCryptTest.dhGen.priv = priv; - ssl->asyncCryptTest.dhGen.privSz = privSz; - ssl->asyncCryptTest.dhGen.pub = pub; - ssl->asyncCryptTest.dhGen.pubSz = pubSz; - return WC_PENDING_E; - } -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ - wc_InitDhKey(&dhKey); ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); if (ret == 0) { ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); } wc_FreeDhKey(&dhKey); + return ret; } @@ -3016,27 +3018,6 @@ int DhAgree(WOLFSSL* ssl, int ret; DhKey dhKey; -#if defined(WOLFSSL_ASYNC_CRYPT_TEST) - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->asyncCryptTest.type == ASYNC_TEST_NONE) - { - ssl->asyncCryptTest.type = ASYNC_TEST_DH_AGREE; - ssl->asyncCryptTest.dhAgree.p = p; - ssl->asyncCryptTest.dhAgree.pSz = pSz; - ssl->asyncCryptTest.dhAgree.g = g; - ssl->asyncCryptTest.dhAgree.gSz = gSz; - ssl->asyncCryptTest.dhAgree.priv = priv; - ssl->asyncCryptTest.dhAgree.privSz = privSz; - ssl->asyncCryptTest.dhAgree.pub = pub; - ssl->asyncCryptTest.dhAgree.pubSz = pubSz; - ssl->asyncCryptTest.dhAgree.otherPub = otherPub; - ssl->asyncCryptTest.dhAgree.otherPubSz = otherPubSz; - ssl->asyncCryptTest.dhAgree.agree = agree; - ssl->asyncCryptTest.dhAgree.agreeSz = agreeSz; - return WC_PENDING_E; - } -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ - wc_InitDhKey(&dhKey); ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); if (ret == 0 && pub) { @@ -3172,7 +3153,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->buffers.key = ctx->privateKey; #endif -#ifdef HAVE_CAVIUM +#ifdef WOLFSSL_ASYNC_CRYPT ssl->devId = ctx->devId; #endif @@ -3321,7 +3302,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) } #else ssl->heap = ctx->heap; /* carry over user heap without static memory */ -#endif +#endif /* WOLFSSL_STATIC_MEMORY */ ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; @@ -3380,7 +3361,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ALPN ssl->alpn_client_list = NULL; #endif -#endif +#endif /* HAVE_TLS_EXTENSIONS */ /* default alert state (none) */ ssl->alert_history.last_rx.code = -1; @@ -3523,6 +3504,13 @@ static void FreeKeyExchange(WOLFSSL* ssl) ssl->buffers.sig.length = 0; } + /* Cleanup digest buffer */ + if (ssl->buffers.digest.buffer) { + XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + } + /* Free sigKey */ if (ssl->sigKey) { switch (ssl->sigType) @@ -3585,7 +3573,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); } -#endif +#endif /* !NO_DH */ #ifndef NO_CERTS ssl->keepCert = 0; /* make sure certificate is free'd */ wolfSSL_UnloadCertsKeys(ssl); @@ -3637,7 +3625,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) wc_ecc_free(ssl->eccTempKey); XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); } -#endif +#endif /* HAVE_ECC */ #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); @@ -3728,7 +3716,7 @@ static void HashFinal(WOLFSSL * ssl) { #define HashFinal(ssl) -#endif +#endif /* WOLFSSL_TI_HASH */ /* Free any handshake resources no longer needed */ void FreeHandshakeResources(WOLFSSL* ssl) @@ -3811,7 +3799,7 @@ void FreeHandshakeResources(WOLFSSL* ssl) XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); ssl->eccTempKey = NULL; } -#endif +#endif /* HAVE_ECC */ #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, @@ -3828,7 +3816,7 @@ void FreeHandshakeResources(WOLFSSL* ssl) XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); ssl->buffers.serverDH_P.buffer = NULL; } -#endif +#endif /* !NO_DH */ #ifndef NO_CERTS wolfSSL_UnloadCertsKeys(ssl); #endif @@ -6573,14 +6561,14 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("PeerRsaKey Memory error"); keyRet = MEMORY_E; } else { - keyRet = wc_InitRsaKey(ssl->peerRsaKey, - ssl->heap); + keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, + ssl->heap, ssl->devId); } } else if (ssl->peerRsaKeyPresent) { /* don't leak on reuse */ wc_FreeRsaKey(ssl->peerRsaKey); ssl->peerRsaKeyPresent = 0; - keyRet = wc_InitRsaKey(ssl->peerRsaKey, ssl->heap); + keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, ssl->heap, ssl->devId); } if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey, @@ -6645,12 +6633,14 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("PeerEccDsaKey Memory error"); return MEMORY_E; } - wc_ecc_init_h(ssl->peerEccDsaKey, ssl->heap); + wc_ecc_init_ex(ssl->peerEccDsaKey, ssl->heap, + ssl->devId); } else if (ssl->peerEccDsaKeyPresent) { /* don't leak on reuse */ wc_ecc_free(ssl->peerEccDsaKey); ssl->peerEccDsaKeyPresent = 0; - wc_ecc_init_h(ssl->peerEccDsaKey, ssl->heap); + wc_ecc_init_ex(ssl->peerEccDsaKey, ssl->heap, + ssl->devId); } curveId = wc_ecc_get_oid(dCert->keyOID, NULL, NULL); @@ -7542,6 +7532,16 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } + /* if async, offset index so this msg will be processed again */ + if (ret == WC_PENDING_E) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + *inOutIdx -= DTLS_HANDSHAKE_EXTRA; + } + #endif + } + WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); return ret; } @@ -7807,10 +7807,13 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } else { /* This branch is in order next, and a complete message. */ - ssl->keys.dtls_expected_peer_handshake_number++; ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); - if (ret == 0 && ssl->dtls_msg_list != NULL) - ret = DtlsMsgDrain(ssl); + if (ret == 0) { + ssl->keys.dtls_expected_peer_handshake_number++; + if (ssl->dtls_msg_list != NULL) { + ret = DtlsMsgDrain(ssl); + } + } } WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret); @@ -10770,8 +10773,13 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (ssl->options.handShakeState != HANDSHAKE_DONE) { int err; WOLFSSL_MSG("handshake not complete, trying to finish"); - if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) + if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) { + /* if async would block return WANT_WRITE */ + if (ssl->error == WC_PENDING_E) { + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } return err; + } } /* last time system socket output buffer was full, try again to send */ @@ -10899,8 +10907,13 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) if (ssl->options.handShakeState != HANDSHAKE_DONE) { int err; WOLFSSL_MSG("Handshake not complete, trying to finish"); - if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) + if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) { + /* if async would block return WANT_WRITE */ + if (ssl->error == WC_PENDING_E) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } return err; + } } #ifdef HAVE_SECURE_RENEGOTIATION @@ -11379,9 +11392,6 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case OCSP_INVALID_STATUS: return "Invalid OCSP Status Error"; - case ASYNC_NOT_PENDING: - return "Async operation not pending"; - case RSA_KEY_SIZE_E: return "RSA key too small"; @@ -13283,926 +13293,894 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #endif /* HAVE_ECC */ - static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, - word32* inOutIdx, word32 size) + +static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + int ret = 0; + word16 length = 0; + word32 idx = *inOutIdx, begin = *inOutIdx; + int typeH = 0; + byte* output = NULL; + byte sigAlgo = ssl->specs.sig_algo; + word16 sigSz = 0; +#if !defined(NO_DH) || defined(HAVE_ECC) + byte* verifySig = NULL; +#endif + + (void)output; + (void)sigSz; + (void)typeH; + + WOLFSSL_ENTER("DoServerKeyExchange"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + if (ret != WC_NOT_PENDING_E) { + WOLF_EVENT_TYPE eType = ssl->event.type; + + /* Clear event */ + XMEMSET(&ssl->event, 0, sizeof(ssl->event)); + + /* Check for error */ + if (ret < 0) { + goto exit_dske; + } + else { + /* Restore variables needed for async */ + idx = ssl->async.idx; + length = ssl->async.length; + output = ssl->async.output; + sigSz = ssl->async.sigSz; + typeH = ssl->async.hashAlgo; + sigAlgo = ssl->async.sigAlgo; + #if !defined(NO_DH) || defined(HAVE_ECC) + verifySig = ssl->async.data; + #endif + + /* Advance key share state if not wolfCrypt */ + if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { + ssl->options.keyShareState++; + } + } + } + else +#endif { - #ifdef HAVE_QSH - word16 name; - int qshSz; - #endif - word16 length = 0; - word32 begin = *inOutIdx; - int ret = 0; + /* Reset state */ + ret = 0; + ssl->options.keyShareState = KEYSHARE_BEGIN; + } - (void)length; /* shut up compiler warnings */ - (void)begin; - (void)ssl; - (void)input; - (void)size; - (void)ret; - - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("ServerKeyExchange", &ssl->timeoutInfo); - #endif - - switch (ssl->specs.kea) + switch(ssl->options.keyShareState) + { + case KEYSHARE_BEGIN: { - #ifndef NO_PSK - case psk_kea: - { - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("ServerKeyExchange", &ssl->timeoutInfo); + #endif + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + int srvHintLen; + + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = min(length, MAX_PSK_ID_LEN - 1); + XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); + ssl->arrays->server_hint[srvHintLen] = 0; + idx += length; + break; + } + #endif /* !NO_PSK */ + #ifndef NO_DH + case diffie_hellman_kea: + { + /* p */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + if (length < ssl->options.minDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too small"); + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_KEY_SIZE_E, exit_dske); + } + + ssl->buffers.serverDH_P.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_P.buffer) { + ssl->buffers.serverDH_P.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_dske); + } + + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); + idx += length; + + ssl->options.dhKeySz = length; + + /* g */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ssl->buffers.serverDH_G.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_G.buffer) { + ssl->buffers.serverDH_G.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_dske); + } + + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); + idx += length; + + /* pub */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ssl->buffers.serverDH_Pub.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_Pub.buffer) { + ssl->buffers.serverDH_Pub.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_dske); + } + + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); + idx += length; + break; + } + #endif /* !NO_DH */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + byte b; + int curveId, curveOid; + + if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + b = input[idx++]; + if (b != named_curve) { + ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); + } + + idx += 1; /* curve type, eat leading 0 */ + b = input[idx++]; + if ((curveOid = CheckCurveId(b)) < 0) { + ERROR_OUT(ECC_CURVE_ERROR, exit_dske); + } + + length = input[idx++]; + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + ERROR_OUT(MEMORY_E, exit_dske); + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) { + goto exit_dske; + } + } + + curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + if (wc_ecc_import_x963_ex(input + idx, length, + ssl->peerEccKey, curveId) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + idx += length; + ssl->peerEccKeyPresent = 1; + break; + } + #endif /* HAVE_ECC */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + int srvHintLen; + + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = min(length, MAX_PSK_ID_LEN - 1); + XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); + ssl->arrays->server_hint[srvHintLen] = 0; + idx += length; + + /* p */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + if (length < ssl->options.minDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too small"); + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_KEY_SIZE_E, exit_dske); + } + + ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(length, + ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_P.buffer) { + ssl->buffers.serverDH_P.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_dske); + } + + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); + idx += length; + + ssl->options.dhKeySz = length; + + /* g */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(length, + ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_G.buffer) { + ssl->buffers.serverDH_G.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_dske); + } + + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); + idx += length; + + /* pub */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(length, + ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_Pub.buffer) { + ssl->buffers.serverDH_Pub.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_dske); + } + + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); + idx += length; + break; + } + #endif /* !NO_DH || !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte b; + int curveOid, curveId; + int srvHintLen; + + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = min(length, MAX_PSK_ID_LEN - 1); + XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); + ssl->arrays->server_hint[srvHintLen] = 0; + + idx += length; + + if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* Check curve name and ID */ + b = input[idx++]; + if (b != named_curve) { + ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); + } + + idx += 1; /* curve type, eat leading 0 */ + b = input[idx++]; + if ((curveOid = CheckCurveId(b)) < 0) { + ERROR_OUT(ECC_CURVE_ERROR, exit_dske); + } + + length = input[idx++]; + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + ERROR_OUT(MEMORY_E, exit_dske); + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) { + goto exit_dske; + } + } + + curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + if (wc_ecc_import_x963_ex(input + idx, length, + ssl->peerEccKey, curveId) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + idx += length; + ssl->peerEccKeyPresent = 1; + break; + } + #endif /* HAVE_ECC || !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; } - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_BUILD; + } /* case KEYSHARE_BEGIN */ - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; + case KEYSHARE_BUILD: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + byte hashAlgo = sha_mac; + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + word16 verifySz; + + if (ssl->options.usingAnon_cipher) { + break; + } + + verifySz = (word16)(idx - begin); + if (verifySz > MAX_DH_SZ) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + if (IsAtLeastTLSv1_2(ssl)) { + if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + hashAlgo = input[idx++]; + sigAlgo = input[idx++]; + + switch (hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif + break; + case sha384_mac: + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif + break; + case sha256_mac: + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif + break; + case sha_mac: + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + #endif + break; + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + if (hashType == WC_HASH_TYPE_NONE) { + ERROR_OUT(ALGO_ID_E, exit_dske); + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_dske); + #endif + } + typeH = wc_HashGetOID(hashType); + + /* signature */ + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + idx, &length); + idx += OPAQUE16_LEN; + + if ((idx - begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* buffer for signature */ + ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + ssl->buffers.sig.length = SEED_LEN + verifySz; + + /* buffer for hash */ + ssl->buffers.digest.length = wc_HashGetDigestSize(hashType); + ssl->buffers.digest.buffer = (byte*)XMALLOC( + ssl->buffers.digest.length, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.digest.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + + /* build message to hash */ + XMEMCPY(ssl->buffers.sig.buffer, + ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN], + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], + input + begin, verifySz); /* message */ + + /* Perform hash */ + ret = wc_Hash(hashType, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + ssl->buffers.digest.buffer, ssl->buffers.digest.length); + if (ret != 0) { + goto exit_dske; + } + + switch (sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + if (ssl->peerRsaKey == NULL || + !ssl->peerRsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + if (!ssl->peerEccDsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ECC */ + + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + + #endif /* NO_DH && !HAVE_ECC */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; } - XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, - min(length, MAX_PSK_ID_LEN)); + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_DO; + } /* case KEYSHARE_BUILD */ - ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; - *inOutIdx += length; + case KEYSHARE_DO: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + if (ssl->options.usingAnon_cipher) { + break; + } + + if (verifySig == NULL) { + verifySig = (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (!verifySig) { + ERROR_OUT(MEMORY_E, exit_dske); + } + XMEMCPY(verifySig, input + idx, length); + } + + switch (sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + ret = RsaVerify(ssl, + verifySig, length, + &output, + ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx + #else + NULL, 0, NULL + #endif + ); + + if (ret >= 0) { + sigSz = (word16)ret; + ret = 0; + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + ret = EccVerify(ssl, + verifySig, length, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->EccVerifyCtx + #else + NULL, 0, NULL + #endif + ); + break; + } + #endif /* HAVE_ECC */ + + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + #endif /* NO_DH && !HAVE_ECC */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_VERIFY; + } /* case KEYSHARE_DO */ + + case KEYSHARE_VERIFY: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + if (ssl->options.usingAnon_cipher) { + break; + } + + /* increment index after verify is done */ + idx += length; + + switch(sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + word32 encSigSz; + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + #endif + + encSigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, typeH); + if (encSigSz != sigSz || !output || + XMEMCMP(output, encodedSig, + min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_SIGN_ERROR; + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + if (ret != 0) { + goto exit_dske; + } + } + else if (sigSz != FINISHED_SZ || !output || + XMEMCMP(output, ssl->buffers.digest.buffer, + FINISHED_SZ) != 0) { + ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske); + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + /* Nothing to do in this algo */ + break; + #endif /* HAVE_ECC */ + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + #endif /* NO_DH && !HAVE_ECC */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_FINALIZE; + } /* case KEYSHARE_VERIFY */ + + case KEYSHARE_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + idx += ssl->keys.padSz; + } /* QSH extensions */ #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { + word16 name; + int qshSz; + /* extension name */ - ato16(input + *inOutIdx, &name); - *inOutIdx += OPAQUE16_LEN; + ato16(input + idx, &name); + idx += OPAQUE16_LEN; if (name == TLSX_QUANTUM_SAFE_HYBRID) { - /* if qshSz is larger than 0 it is the length of buffer - used */ - if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, - size, 0)) < 0) { - return qshSz; + /* if qshSz is larger than 0 it is the length of + buffer used */ + if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + idx, + size, 0)) < 0) { + ERROR_OUT(qshSz, exit_dske); } - *inOutIdx += qshSz; + idx += qshSz; } else { - /* unknown extension sent server ignored - handshake */ - return BUFFER_ERROR; + /* unknown extension sent server ignored handshake */ + ERROR_OUT(BUFFER_ERROR, exit_dske); } } #endif - return 0; - } - #endif - #ifndef NO_DH - case diffie_hellman_kea: + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_END; + } /* case KEYSHARE_FINALIZE */ + + case KEYSHARE_END: { - /* p */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - if (length < ssl->options.minDhKeySz) { - WOLFSSL_MSG("Server using a DH key that is too small"); - SendAlert(ssl, alert_fatal, handshake_failure); - return DH_KEY_SIZE_E; - } - - ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_P.buffer) { - ssl->buffers.serverDH_P.length = length; - } - else { - return MEMORY_ERROR; - } - - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - ssl->options.dhKeySz = length; - - /* g */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_G.buffer) { - ssl->buffers.serverDH_G.length = length; - } - else { - return MEMORY_ERROR; - } - - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - /* pub */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - ssl->buffers.serverDH_Pub.buffer = - (byte*) XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_Pub.buffer) { - ssl->buffers.serverDH_Pub.length = length; - } - else { - return MEMORY_ERROR; - } - - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, - length); - *inOutIdx += length; - break; - } /* dh_kea */ - #endif /* NO_DH */ - - #ifdef HAVE_ECC - case ecc_diffie_hellman_kea: - { - byte b; - int curveId, curveOid; - - if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN + - OPAQUE8_LEN > size) { - return BUFFER_ERROR; - } - - b = input[(*inOutIdx)++]; - - if (b != named_curve) { - return ECC_CURVETYPE_ERROR; - } - - *inOutIdx += 1; /* curve type, eat leading 0 */ - b = input[(*inOutIdx)++]; - - if ((curveOid = CheckCurveId(b)) < 0) { - return curveOid; - } - - length = input[(*inOutIdx)++]; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - return MEMORY_E; - } - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); - } - - curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + *inOutIdx, length, - ssl->peerEccKey, curveId) != 0) { - return ECC_PEERKEY_ERROR; - } - - *inOutIdx += length; - ssl->peerEccKeyPresent = 1; + /* return index */ + *inOutIdx = idx; + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; break; } - #endif /* HAVE_ECC */ - - #if !defined(NO_DH) && !defined(NO_PSK) - case dhe_psk_kea: - { - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, - min(length, MAX_PSK_ID_LEN)); - - ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; - *inOutIdx += length; - - /* p */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - if (length < ssl->options.minDhKeySz) { - WOLFSSL_MSG("Server using a DH key that is too small"); - SendAlert(ssl, alert_fatal, handshake_failure); - return DH_KEY_SIZE_E; - } - - ssl->buffers.serverDH_P.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_P.buffer) { - ssl->buffers.serverDH_P.length = length; - } - else { - return MEMORY_ERROR; - } - - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - ssl->options.dhKeySz = length; - - /* g */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - ssl->buffers.serverDH_G.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_G.buffer) { - ssl->buffers.serverDH_G.length = length; - } - else { - return MEMORY_ERROR; - } - - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - /* pub */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - ssl->buffers.serverDH_Pub.buffer = (byte*) XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_DH); - - if (ssl->buffers.serverDH_Pub.buffer) { - ssl->buffers.serverDH_Pub.length = length; - } - else { - return MEMORY_ERROR; - } - - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + *inOutIdx, length); - *inOutIdx += length; - - break; - } - #endif /* !NO_DH || !NO_PSK */ - - #if defined(HAVE_ECC) && !defined(NO_PSK) - case ecdhe_psk_kea: - { - byte b; - int curveOid, curveId; - - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - return BUFFER_ERROR; - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - /* get PSK server hint from the wire */ - XMEMCPY(ssl->arrays->server_hint, input + *inOutIdx, - min(length, MAX_PSK_ID_LEN)); - - ssl->arrays->server_hint[min(length, MAX_PSK_ID_LEN - 1)] = 0; - *inOutIdx += length; - - - if ((*inOutIdx - begin) + ENUM_LEN + OPAQUE16_LEN + - OPAQUE8_LEN > size) { - return BUFFER_ERROR; - } - - /* Check curve name and ID */ - b = input[(*inOutIdx)++]; - if (b != named_curve) { - return ECC_CURVETYPE_ERROR; - } - - *inOutIdx += 1; /* curve type, eat leading 0 */ - b = input[(*inOutIdx)++]; - if ((curveOid = CheckCurveId(b)) < 0) { - return curveOid; - } - - length = input[(*inOutIdx)++]; - - if ((*inOutIdx - begin) + length > size) { - return BUFFER_ERROR; - } - - if (ssl->peerEccKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - return MEMORY_E; - } - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); - } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); - } - - curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + *inOutIdx, length, - ssl->peerEccKey, curveId) != 0) { - return ECC_PEERKEY_ERROR; - } - - *inOutIdx += length; - ssl->peerEccKeyPresent = 1; - - break; - } - #endif /* HAVE_ECC || !NO_PSK */ - } /* switch() */ - - #if !defined(NO_DH) || defined(HAVE_ECC) - if (!ssl->options.usingAnon_cipher && - (ssl->specs.kea == ecc_diffie_hellman_kea || - ssl->specs.kea == diffie_hellman_kea)) - { -#ifndef NO_OLD_TLS -#ifdef WOLFSSL_SMALL_STACK - Md5* md5 = NULL; - Sha* sha = NULL; -#else - Md5 md5[1]; - Sha sha[1]; -#endif -#endif -#ifndef NO_SHA256 -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256 = NULL; - byte* hash256 = NULL; -#else - Sha256 sha256[1]; - byte hash256[SHA256_DIGEST_SIZE]; -#endif -#endif -#ifdef WOLFSSL_SHA384 -#ifdef WOLFSSL_SMALL_STACK - Sha384* sha384 = NULL; - byte* hash384 = NULL; -#else - Sha384 sha384[1]; - byte hash384[SHA384_DIGEST_SIZE]; -#endif -#endif -#ifdef WOLFSSL_SHA512 -#ifdef WOLFSSL_SMALL_STACK - Sha512* sha512 = NULL; - byte* hash512 = NULL; -#else - Sha512 sha512[1]; - byte hash512[SHA512_DIGEST_SIZE]; -#endif -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* hash = NULL; - byte* messageVerify = NULL; -#else - byte hash[FINISHED_SZ]; - byte messageVerify[MAX_DH_SZ]; -#endif - byte hashAlgo = sha_mac; - byte sigAlgo = ssl->specs.sig_algo; - word16 verifySz = (word16) (*inOutIdx - begin); - -#ifndef NO_OLD_TLS - byte doMd5 = 0; - byte doSha = 0; -#endif -#ifndef NO_SHA256 - byte doSha256 = 0; -#endif -#ifdef WOLFSSL_SHA384 - byte doSha384 = 0; -#endif -#ifdef WOLFSSL_SHA512 - byte doSha512 = 0; -#endif - - (void)hash; - (void)sigAlgo; - (void)hashAlgo; - - /* save message for hash verify */ - if (verifySz > MAX_DH_SZ) { - ERROR_OUT(BUFFER_ERROR, done); - } - - #ifdef WOLFSSL_SMALL_STACK - messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (messageVerify == NULL) { - ERROR_OUT(MEMORY_E, done); - } - #endif - - XMEMCPY(messageVerify, input + begin, verifySz); - - if (IsAtLeastTLSv1_2(ssl)) { - byte setHash = 0; - if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) { - ERROR_OUT(BUFFER_ERROR, done); - } - - hashAlgo = input[(*inOutIdx)++]; - sigAlgo = input[(*inOutIdx)++]; - - switch (hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - doSha512 = 1; - setHash = 1; - #endif - break; - - case sha384_mac: - #ifdef WOLFSSL_SHA384 - doSha384 = 1; - setHash = 1; - #endif - break; - - case sha256_mac: - #ifndef NO_SHA256 - doSha256 = 1; - setHash = 1; - #endif - break; - - case sha_mac: - #ifndef NO_OLD_TLS - doSha = 1; - setHash = 1; - #endif - break; - - default: - ERROR_OUT(ALGO_ID_E, done); - } - - if (setHash == 0) { - ERROR_OUT(ALGO_ID_E, done); - } - - } else { - /* only using sha and md5 for rsa */ - #ifndef NO_OLD_TLS - doSha = 1; - if (sigAlgo == rsa_sa_algo) { - doMd5 = 1; - } - #else - ERROR_OUT(ALGO_ID_E, done); - #endif - } - - /* signature */ - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { - ERROR_OUT(BUFFER_ERROR, done); - } - - ato16(input + *inOutIdx, &length); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + length > size) { - ERROR_OUT(BUFFER_ERROR, done); - } - - /* inOutIdx updated at the end of the function */ - - /* verify signature */ - #ifdef WOLFSSL_SMALL_STACK - hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (hash == NULL) { - ERROR_OUT(MEMORY_E, done); - } - #endif - -#ifndef NO_OLD_TLS - /* md5 */ - #ifdef WOLFSSL_SMALL_STACK - if (doMd5) { - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (md5 == NULL) { - ERROR_OUT(MEMORY_E, done); - } - } - #endif - if (doMd5) { - wc_InitMd5(md5); - wc_Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); - wc_Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); - wc_Md5Update(md5, messageVerify, verifySz); - wc_Md5Final(md5, hash); - } - /* sha */ - #ifdef WOLFSSL_SMALL_STACK - if (doSha) { - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) { - ERROR_OUT(MEMORY_E, done); - } - } - #endif - if (doSha) { - ret = wc_InitSha(sha); - if (ret != 0) { - goto done; - } - wc_ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); - wc_ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); - wc_ShaUpdate(sha, messageVerify, verifySz); - wc_ShaFinal(sha, hash + MD5_DIGEST_SIZE); - } -#endif - -#ifndef NO_SHA256 - #ifdef WOLFSSL_SMALL_STACK - if (doSha256) { - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL || hash256 == NULL) { - ERROR_OUT(MEMORY_E, done); - } - } - #endif - if (doSha256) { - if (!(ret = wc_InitSha256(sha256)) - && !(ret = wc_Sha256Update(sha256, ssl->arrays->clientRandom, - RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, ssl->arrays->serverRandom, - RAN_LEN)) - && !(ret = wc_Sha256Update(sha256, messageVerify, verifySz))) { - ret = wc_Sha256Final(sha256, hash256); - } - if (ret != 0) { - goto done; - } - } -#endif - -#ifdef WOLFSSL_SHA384 - #ifdef WOLFSSL_SMALL_STACK - if (doSha384) { - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL || hash384 == NULL) { - ERROR_OUT(MEMORY_E, done); - } - } - #endif - if (doSha384) { - if (!(ret = wc_InitSha384(sha384)) - && !(ret = wc_Sha384Update(sha384, ssl->arrays->clientRandom, - RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, ssl->arrays->serverRandom, - RAN_LEN)) - && !(ret = wc_Sha384Update(sha384, messageVerify, verifySz))) { - ret = wc_Sha384Final(sha384, hash384); - } - if (ret != 0) { - goto done; - } - } -#endif - -#ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SMALL_STACK - if (doSha512) { - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - hash512 = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL || hash512 == NULL) { - ERROR_OUT(MEMORY_E, done); - } - } - #endif - if (doSha512) { - if (!(ret = wc_InitSha512(sha512)) - && !(ret = wc_Sha512Update(sha512, ssl->arrays->clientRandom, - RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, ssl->arrays->serverRandom, - RAN_LEN)) - && !(ret = wc_Sha512Update(sha512, messageVerify, verifySz))) { - ret = wc_Sha512Final(sha512, hash512); - } - if (ret != 0) { - goto done; - } - } -#endif - - switch (sigAlgo) - { -#ifndef NO_RSA - /* rsa */ - case rsa_sa_algo: - { - byte* out = NULL; - word32 verifiedSz = 0; - - if (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent) { - ERROR_OUT(NO_PEER_KEY, done); - } - - verifiedSz = RsaVerify(ssl, - (byte *)input + *inOutIdx, - length, - &out, - ssl->peerRsaKey, - #ifdef HAVE_PK_CALLBACKS - ssl->buffers.peerRsaKey.buffer, - ssl->buffers.peerRsaKey.length, - ssl->RsaVerifyCtx - #else - NULL, 0, NULL - #endif - ); - - if (IsAtLeastTLSv1_2(ssl)) { - word32 encSigSz; -#ifndef NO_OLD_TLS - byte* digest = &hash[MD5_DIGEST_SIZE]; - int typeH = SHAh; - int digestSz = SHA_DIGEST_SIZE; -#else - byte* digest = hash256; - int typeH = SHA256h; - int digestSz = SHA256_DIGEST_SIZE; -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; -#else - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - - if (hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = &hash[MD5_DIGEST_SIZE]; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - - #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - ERROR_OUT(MEMORY_E, done); - } - #endif - - if (digest == NULL) { - ERROR_OUT(ALGO_ID_E, done); - } - encSigSz = wc_EncodeSignature(encodedSig, digest, digestSz, - typeH); - if (encSigSz != verifiedSz || !out || XMEMCMP(out, encodedSig, - min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { - ret = VERIFY_SIGN_ERROR; - } - #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - if (ret != 0) { - goto done; - } - } - else if (verifiedSz != FINISHED_SZ || !out || XMEMCMP(out, - hash, FINISHED_SZ) != 0) { - ERROR_OUT(VERIFY_SIGN_ERROR, done); - } - break; - } -#endif -#ifdef HAVE_ECC - /* ecdsa */ - case ecc_dsa_sa_algo: - { -#ifndef NO_OLD_TLS - byte* digest = &hash[MD5_DIGEST_SIZE]; - word32 digestSz = SHA_DIGEST_SIZE; -#else - byte* digest = hash256; - word32 digestSz = SHA256_DIGEST_SIZE; -#endif - - if (!ssl->peerEccDsaKeyPresent) - ERROR_OUT(NO_PEER_KEY, done); - - if (IsAtLeastTLSv1_2(ssl)) { - if (hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = &hash[MD5_DIGEST_SIZE]; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = hash256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = hash384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = hash512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - } - - ret = EccVerify(ssl, - input + *inOutIdx, length, - digest, digestSz, - ssl->peerEccDsaKey, - #ifdef HAVE_PK_CALLBACKS - ssl->buffers.peerEccDsaKey.buffer, - ssl->buffers.peerEccDsaKey.length, - ssl->EccVerifyCtx - #else - NULL, 0, NULL - #endif - ); - break; - } -#endif /* HAVE_ECC */ default: - ERROR_OUT(ALGO_ID_E, done); - } /* switch (sigAlgo) */ + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.keyShareState) */ - /* signature length */ - *inOutIdx += length; +exit_dske: - ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + WOLFSSL_LEAVE("DoServerKeyExchange", ret); - done: -#ifdef WOLFSSL_SMALL_STACK - #ifndef NO_OLD_TLS - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + /* Handle cleanup for stack variables here */ + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + /* Store variables needed for async */ + XMEMSET(&ssl->async, 0, sizeof(ssl->async)); + ssl->async.idx = idx; + ssl->async.length = length; + ssl->async.output = output; + ssl->async.sigSz = sigSz; + ssl->async.hashAlgo = typeH; + ssl->async.sigAlgo = sigAlgo; + #if !defined(NO_DH) || defined(HAVE_ECC) + ssl->async.data = verifySig; #endif - #ifndef NO_SHA256 - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - #ifdef WOLFSSL_SHA512 - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(hash512, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - if (ret != 0) { - return ret; + + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_server_key_exchange = 0; + + /* Push event to queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); + if (ret == 0) { + return WC_PENDING_E; } } +#endif /* WOLFSSL_ASYNC_CRYPT */ - if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; - } - - - /* QSH extensions */ -#ifdef HAVE_QSH - if (ssl->peerQSHKeyPresent) { - /* extension name */ - ato16(input + *inOutIdx, &name); - *inOutIdx += OPAQUE16_LEN; - - if (name == TLSX_QUANTUM_SAFE_HYBRID) { - /* if qshSz is larger than 0 it is the length of buffer used */ - if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, - size, 0)) < 0) { - return qshSz; - } - *inOutIdx += qshSz; - } - else { - /* unknown extension sent server ignored - handshake */ - return BUFFER_ERROR; - } +#if !defined(NO_DH) || defined(HAVE_ECC) + if (verifySig) { + XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + verifySig = NULL; } #endif - return 0; -#else /* !NO_DH or HAVE_ECC */ - return NOT_COMPILED_IN; /* not supported by build */ -#endif /* !NO_DH or HAVE_ECC */ - } + /* Final cleanup */ + FreeKeyExchange(ssl); + + return ret; +} #ifdef HAVE_QSH @@ -14574,161 +14552,249 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) #endif /* HAVE_QSH */ - int SendClientKeyExchange(WOLFSSL* ssl) - { -#ifdef WOLFSSL_SMALL_STACK - byte* encSecret = NULL; -#else - byte encSecret[MAX_ENCRYPT_SZ]; -#endif - word32 encSz = 0; - word32 idx = 0; - int ret = 0; - byte doUserRsa = 0; +int SendClientKeyExchange(WOLFSSL* ssl) +{ + int ret = 0; + int sendSz = 0; + word32 length_lcl = 0; + word32* length = &length_lcl; + byte* output = NULL; + byte* encSecret = NULL; + word32 encSz = 0; - #ifdef HAVE_QSH - word32 qshSz = 0; - if (ssl->peerQSHKeyPresent) { - qshSz = QSH_KeyGetSize(ssl); + (void)length; + + WOLFSSL_ENTER("SendClientKeyExchange"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* use async pointer for length */ + length = &ssl->async.length; + + ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + if (ret != WC_NOT_PENDING_E) { + WOLF_EVENT_TYPE eType = ssl->event.type; + + /* Clear event */ + XMEMSET(&ssl->event, 0, sizeof(ssl->event)); + + /* Check for error */ + if (ret < 0) { + goto exit_scke; } - #endif + else { + /* Restore variables needed for async */ + output = ssl->async.output; + sendSz = ssl->async.sendSz; + encSecret = ssl->async.data; + encSz = ssl->async.sigSz; - (void)doUserRsa; + /* Advance key share state if not wolfCrypt */ + if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { + ssl->options.keyShareState++; + } + } + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.keyShareState = KEYSHARE_BEGIN; + } -#ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - if (ssl->ctx->RsaEncCb) - doUserRsa = 1; - #endif /* NO_RSA */ -#endif /*HAVE_PK_CALLBACKS */ - - #ifdef WOLFSSL_SMALL_STACK - encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encSecret == NULL) - return MEMORY_E; - #endif - - switch (ssl->specs.kea) { - #ifndef NO_RSA - case rsa_kea: - ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, - SECRET_LEN); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - - ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; - ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; - ssl->arrays->preMasterSz = SECRET_LEN; - - if (ssl->peerRsaKey == NULL || ssl->peerRsaKeyPresent == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - if (doUserRsa) { - #ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - encSz = MAX_ENCRYPT_SZ; - ret = ssl->ctx->RsaEncCb(ssl, - ssl->arrays->preMasterSecret, - SECRET_LEN, - encSecret, &encSz, - ssl->buffers.peerRsaKey.buffer, - ssl->buffers.peerRsaKey.length, - ssl->RsaEncCtx); - #endif /* NO_RSA */ - #endif /*HAVE_PK_CALLBACKS */ - } - else { - ret = wc_RsaPublicEncrypt(ssl->arrays->preMasterSecret, - SECRET_LEN, encSecret, MAX_ENCRYPT_SZ, - ssl->peerRsaKey, ssl->rng); - if (ret > 0) { - encSz = ret; - ret = 0; /* set success to 0 */ + switch(ssl->options.keyShareState) + { + case KEYSHARE_BEGIN: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + if (ssl->peerRsaKey == NULL || + ssl->peerRsaKeyPresent == 0) { + ERROR_OUT(NO_PEER_KEY, exit_scke); } - } - break; - #endif - #ifndef NO_DH - case diffie_hellman_kea: - { - buffer serverP = ssl->buffers.serverDH_P; - buffer serverG = ssl->buffers.serverDH_G; - buffer serverPub = ssl->buffers.serverDH_Pub; - #ifdef WOLFSSL_SMALL_STACK - byte* priv = NULL; - #else - byte priv[ENCRYPT_LEN]; - #endif - word32 privSz = 0; - - if (serverP.buffer == NULL || serverG.buffer == NULL || - serverPub.buffer == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; + break; + #endif + #ifndef NO_DH + case diffie_hellman_kea: + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL || + ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); } - - #ifdef WOLFSSL_SMALL_STACK - priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (priv == NULL) { - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + break; + #endif /* NO_DH */ + #ifndef NO_PSK + case psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + break; + #endif /* NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL || + ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); } - #endif - - ret = DhAgree(ssl, - serverP.buffer, serverP.length, - serverG.buffer, serverG.length, - priv, &privSz, - encSecret, &encSz, - serverPub.buffer, serverPub.length, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } - break; - #endif /* NO_DH */ - #ifndef NO_PSK - case psk_kea: - { - byte* pms = ssl->arrays->preMasterSecret; /* sanity check that PSK client callback has been set */ if (ssl->options.client_psk_cb == NULL) { WOLFSSL_MSG("No client PSK callback set"); - return PSK_KEY_ERROR; + ERROR_OUT(PSK_KEY_ERROR, exit_scke); } + break; + #endif /* !NO_DH && !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + + /* Check client ECC public key */ + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create private key */ + ssl->sigKey = XMALLOC(sizeof(ecc_key), + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->sigKey == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + ssl->sigType = DYNAMIC_TYPE_ECC; + + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_scke; + } + ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, ssl->peerEccKey); + break; + #endif /* HAVE_ECC && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + if (ssl->peerNtruKeyPresent == 0) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + ecc_key* peerKey; + + if (ssl->specs.static_ecdh) { + /* TODO: EccDsa is really fixed Ecc change naming */ + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccKey; + } + if (peerKey == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create private key */ + ssl->sigKey = XMALLOC(sizeof(ecc_key), + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->sigKey == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + ssl->sigType = DYNAMIC_TYPE_ECC; + + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_scke; + } + ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, peerKey); + break; + } + #endif /* HAVE_ECC */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_BUILD; + } /* case KEYSHARE_BEGIN */ + + case KEYSHARE_BUILD: + { + encSz = MAX_ENCRYPT_SZ; + encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encSecret == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->arrays->preMasterSecret, SECRET_LEN); + if (ret != 0) { + goto exit_scke; + } + + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + ssl->arrays->preMasterSz = SECRET_LEN; + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ssl->buffers.sig.length = ENCRYPT_LEN; + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, ssl->arrays->server_hint, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); if (ssl->arrays->psk_keySz == 0 || ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return PSK_KEY_ERROR; + ERROR_OUT(PSK_KEY_ERROR, exit_scke); } encSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (encSz > MAX_PSK_ID_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return CLIENT_ID_ERROR; + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } - XMEMCPY(encSecret, ssl->arrays->client_identity, encSz); + XMEMCPY(encSecret, + ssl->arrays->client_identity, encSz); /* make psk pre master secret */ /* length of key + length 0s + length of key + key */ @@ -14742,92 +14808,286 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ + break; } - break; - #endif /* NO_PSK */ - #if !defined(NO_DH) && !defined(NO_PSK) - case dhe_psk_kea: + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; - byte* es = encSecret; - buffer serverP = ssl->buffers.serverDH_P; - buffer serverG = ssl->buffers.serverDH_G; - buffer serverPub = ssl->buffers.serverDH_Pub; - #ifdef WOLFSSL_SMALL_STACK - byte* priv = NULL; - #else - byte priv[ENCRYPT_LEN]; - #endif - word32 privSz = 0; - word32 pubSz = 0; - word32 esSz = 0; + word32 esSz = 0; + output = encSecret; - if (serverP.buffer == 0 || serverG.buffer == 0 || - serverPub.buffer == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - /* sanity check that PSK client callback has been set */ - if (ssl->options.client_psk_cb == NULL) { - WOLFSSL_MSG("No client PSK callback set"); - return PSK_KEY_ERROR; - } ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, ssl->arrays->server_hint, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); if (ssl->arrays->psk_keySz == 0 || ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return PSK_KEY_ERROR; + ERROR_OUT(PSK_KEY_ERROR, exit_scke); } esSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (esSz > MAX_PSK_ID_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return CLIENT_ID_ERROR; + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } - #ifdef WOLFSSL_SMALL_STACK - priv = (byte*)XMALLOC(ENCRYPT_LEN, NULL, + ssl->buffers.sig.length = ENCRYPT_LEN; + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (priv == NULL) { - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); } - #endif - c16toa((word16)esSz, es); - es += OPAQUE16_LEN; - XMEMCPY(es, ssl->arrays->client_identity, esSz); - es += esSz; + + c16toa((word16)esSz, output); + output += OPAQUE16_LEN; + XMEMCPY(output, ssl->arrays->client_identity, esSz); + output += esSz; encSz = esSz + OPAQUE16_LEN; - ret = DhAgree(ssl, - serverP.buffer, serverP.length, - serverG.buffer, serverG.length, - priv, &privSz, - es + OPAQUE16_LEN, &pubSz, - serverPub.buffer, serverPub.length, - pms + OPAQUE16_LEN, &ssl->arrays->preMasterSz); + *length = 0; + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + word32 esSz = 0; + output = encSecret; - #ifdef WOLFSSL_SMALL_STACK - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + /* Send PSK client identity */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - c16toa((word16)pubSz, es); - encSz += pubSz + OPAQUE16_LEN; + esSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (esSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); + } + + /* place size and identity in output buffer sz:identity */ + c16toa((word16)esSz, output); + output += OPAQUE16_LEN; + XMEMCPY(output, ssl->arrays->client_identity, esSz); + output += esSz; + encSz = esSz + OPAQUE16_LEN; + + /* Place ECC key in output buffer, leaving room for size */ + *length = MAX_ENCRYPT_SZ; + ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, + output + 1, length); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + *output = (byte)*length; /* place size of key in output buffer */ + encSz += *length + 1; + + /* Create shared ECC key leaving room at the begining + of buffer for size of shared key. Note sizeof + preMasterSecret is ENCRYPT_LEN currently 512 */ + *length = sizeof(ssl->arrays->preMasterSecret) - OPAQUE16_LEN; + break; + } + #endif /* HAVE_ECC && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->arrays->preMasterSecret, SECRET_LEN); + if (ret != 0) { + goto exit_scke; + } + + ssl->arrays->preMasterSz = SECRET_LEN; + encSz = MAX_ENCRYPT_SZ; + break; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + /* precede export with 1 byte length */ + *length = MAX_ENCRYPT_SZ; + ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, + encSecret + 1, length); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + encSecret[0] = (byte)*length; + encSz = *length + 1; + + *length = sizeof(ssl->arrays->preMasterSecret); + break; + } + #endif /* HAVE_ECC */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_DO; + } /* case KEYSHARE_BUILD */ + + case KEYSHARE_DO: + { + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + ret = RsaEnc(ssl, + ssl->arrays->preMasterSecret, SECRET_LEN, + encSecret, &encSz, + ssl->peerRsaKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaEncCtx + #else + NULL, 0, NULL + #endif + ); + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ret = DhAgree(ssl, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + encSecret, &encSz, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + ret = DhAgree(ssl, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + output + OPAQUE16_LEN, length, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + ret = EccSharedSecret(ssl, (ecc_key*)ssl->sigKey, + ssl->peerEccKey, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + length); + break; + } + #endif /* HAVE_ECC && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word32 rc; + DRBG_HANDLE drbg; + + rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (rc != DRBG_OK) { + ERROR_OUT(NTRU_DRBG_ERROR, exit_scke); + } + rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, + ssl->peerNtruKey, + ssl->arrays->preMasterSz, + ssl->arrays->preMasterSecret, + &encSz, + encSecret); + ntru_crypto_drbg_uninstantiate(drbg); + if (rc != NTRU_OK) { + ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke); + } + ret = 0; + break; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + ecc_key* peerKey = (ssl->specs.static_ecdh) ? + ssl->peerEccDsaKey : ssl->peerEccKey; + + ret = EccSharedSecret(ssl, (ecc_key*)ssl->sigKey, peerKey, + ssl->arrays->preMasterSecret, length); + break; + } + #endif /* HAVE_ECC */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_VERIFY; + } /* case KEYSHARE_DO */ + + case KEYSHARE_VERIFY: + { + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + + c16toa((word16)*length, output); + encSz += *length + OPAQUE16_LEN; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -14838,121 +15098,21 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->preMasterSz += - ssl->arrays->psk_keySz + OPAQUE16_LEN; + ssl->arrays->psk_keySz + OPAQUE16_LEN; ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ + break; } - break; - #endif /* !NO_DH && !NO_PSK */ - #if defined(HAVE_ECC) && !defined(NO_PSK) - case ecdhe_psk_kea: + #endif /* !NO_DH && !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; - byte* es = encSecret; - ecc_key myKey; - ecc_key* peerKey = NULL; - word32 size = MAX_ENCRYPT_SZ; - word32 esSz = 0; - - /* sanity check that PSK client callback has been set */ - if (ssl->options.client_psk_cb == NULL) { - WOLFSSL_MSG("No client PSK callback set"); - return PSK_KEY_ERROR; - } - - /* Send PSK client identity */ - ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, - ssl->arrays->server_hint, ssl->arrays->client_identity, - MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); - if (ssl->arrays->psk_keySz == 0 || - ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return PSK_KEY_ERROR; - } - esSz = (word32)XSTRLEN(ssl->arrays->client_identity); - - if (esSz > MAX_PSK_ID_LEN) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return CLIENT_ID_ERROR; - } - - /* place size and identity in output buffer sz:identity */ - c16toa((word16)esSz, es); - es += OPAQUE16_LEN; - XMEMCPY(es, ssl->arrays->client_identity, esSz); - es += esSz; - encSz = esSz + OPAQUE16_LEN; - - /* Send Client ECC public key */ - if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || - !ssl->peerEccKey->dp) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - peerKey = ssl->peerEccKey; - - if (peerKey == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - wc_ecc_init_h(&myKey, ssl->heap); - ret = wc_ecc_make_key(ssl->rng, peerKey->dp->size, &myKey); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ECC_MAKEKEY_ERROR; - } - - /* Place ECC key in output buffer, leaving room for size */ - ret = wc_ecc_export_x963(&myKey, es + 1, &size); - *es = (byte)size; /* place size of key in output buffer */ - encSz += size + 1; - - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - ret = ECC_EXPORT_ERROR; - } - else { - /* Create shared ECC key leaving room at the begining - of buffer for size of shared key. Note sizeof - preMasterSecret is ENCRYPT_LEN currently 512 */ - size = sizeof(ssl->arrays->preMasterSecret) - - OPAQUE16_LEN; - - ret = EccSharedSecret(ssl, &myKey, peerKey, - ssl->arrays->preMasterSecret + OPAQUE16_LEN, &size); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - ret = ECC_SHARED_ERROR; - } - } - - wc_ecc_free(&myKey); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } /* Create pre master secret is the concatination of eccSize + eccSharedKey + pskSize + pskKey */ - c16toa((word16)size, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN + size; + c16toa((word16)*length, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN + *length; pms += ssl->arrays->preMasterSz; c16toa((word16)ssl->arrays->psk_keySz, pms); @@ -14963,157 +15123,71 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ + break; } - break; - #endif /* HAVE_ECC && !NO_PSK */ - #ifdef HAVE_NTRU - case ntru_kea: + #endif /* HAVE_ECC && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: { - word32 rc; - word16 cipherLen = MAX_ENCRYPT_SZ; - DRBG_HANDLE drbg; - - ret = wc_RNG_GenerateBlock(ssl->rng, - ssl->arrays->preMasterSecret, SECRET_LEN); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - - ssl->arrays->preMasterSz = SECRET_LEN; - - if (ssl->peerNtruKeyPresent == 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); - if (rc != DRBG_OK) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NTRU_DRBG_ERROR; - } - - rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, - ssl->peerNtruKey, - ssl->arrays->preMasterSz, - ssl->arrays->preMasterSecret, - &cipherLen, encSecret); - ntru_crypto_drbg_uninstantiate(drbg); - if (rc != NTRU_OK) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NTRU_ENCRYPT_ERROR; - } - - encSz = cipherLen; - ret = 0; + break; } - break; - #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC - case ecc_diffie_hellman_kea: + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: { - ecc_key myKey; - ecc_key* peerKey = NULL; - word32 size = MAX_ENCRYPT_SZ; - - if (ssl->specs.static_ecdh) { - /* TODO: EccDsa is really fixed Ecc change naming */ - if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || - !ssl->peerEccDsaKey->dp) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - peerKey = ssl->peerEccDsaKey; - } - else { - if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || - !ssl->peerEccKey->dp) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - peerKey = ssl->peerEccKey; - } - - if (peerKey == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return NO_PEER_KEY; - } - - wc_ecc_init_h(&myKey, ssl->heap); - ret = wc_ecc_make_key_ex(ssl->rng, 0, &myKey, peerKey->dp->id); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ECC_MAKEKEY_ERROR; - } - - /* precede export with 1 byte length */ - ret = wc_ecc_export_x963(&myKey, encSecret + 1, &size); - encSecret[0] = (byte)size; - encSz = size + 1; - - if (ret != 0) - ret = ECC_EXPORT_ERROR; - else { - size = sizeof(ssl->arrays->preMasterSecret); - ret = EccSharedSecret(ssl, &myKey, peerKey, - ssl->arrays->preMasterSecret, &size); - if (ret != 0) - ret = ECC_SHARED_ERROR; - } - - ssl->arrays->preMasterSz = size; - wc_ecc_free(&myKey); + ssl->arrays->preMasterSz = *length; + break; } - break; - #endif /* HAVE_ECC */ - default: - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ALGO_ID_E; /* unsupported kea */ - } + #endif /* HAVE_ECC */ - if (ret == 0) { - byte *output; - int sendSz; - word32 tlsSz = 0; + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ - if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_FINALIZE; + } /* case KEYSHARE_VERIFY */ + + case KEYSHARE_FINALIZE: + { + word32 tlsSz = 0; + word32 idx = 0; + + #ifdef HAVE_QSH + word32 qshSz = 0; + if (ssl->peerQSHKeyPresent) { + qshSz = QSH_KeyGetSize(ssl); + } + #endif + + if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) { tlsSz = 2; + } if (ssl->specs.kea == ecc_diffie_hellman_kea || ssl->specs.kea == dhe_psk_kea || - ssl->specs.kea == ecdhe_psk_kea) /* always off */ + ssl->specs.kea == ecdhe_psk_kea) { /* always off */ tlsSz = 0; + } - sendSz = encSz + tlsSz + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + sendSz = encSz + tlsSz + idx; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - } - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + } + #endif - if (IsEncryptionOn(ssl, 1)) + if (IsEncryptionOn(ssl, 1)) { sendSz += MAX_MSG_EXTRA; + } #ifdef HAVE_QSH encSz += qshSz; @@ -15122,24 +15196,21 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; + goto exit_scke; } /* get output buffer */ output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - -#ifdef HAVE_QSH + #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { byte idxSave = idx; idx = sendSz - qshSz; - if (QSH_KeyExchangeWrite(ssl, 0) != 0) - return MEMORY_E; + if (QSH_KeyExchangeWrite(ssl, 0) != 0) { + ERROR_OUT(MEMORY_E, exit_scke); + } /* extension type */ c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); @@ -15147,20 +15218,21 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) /* write to output and check amount written */ if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) - return MEMORY_E; + > qshSz - OPAQUE16_LEN) { + ERROR_OUT(MEMORY_E, exit_scke); + } idx = idxSave; } -#endif + #endif AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl); -#ifdef HAVE_QSH + #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { encSz -= qshSz; } -#endif + #endif if (tlsSz) { c16toa((word16)encSz, &output[idx]); idx += 2; @@ -15175,10 +15247,7 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (input == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_scke); } XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); @@ -15186,246 +15255,377 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) handshake, 1, 0); XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (sendSz < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return sendSz; - } - } else { - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - } - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - } - #endif - - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); - #endif - - ssl->buffers.outputBuffer.length += sendSz; - - if (ssl->options.groupMessages) - ret = 0; - else - ret = SendBuffered(ssl); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - if (ret == 0 || ret == WANT_WRITE) { - int tmpRet = MakeMasterSecret(ssl); - if (tmpRet != 0) - ret = tmpRet; /* save WANT_WRITE unless more serious */ - ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; - } - /* No further need for PMS */ - ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); - ssl->arrays->preMasterSz = 0; - - return ret; - } - -#ifndef NO_CERTS - - - int SendCertificateVerify(WOLFSSL* ssl) - { - byte *output; - int sendSz = MAX_CERT_VERIFY_SZ, length, ret; - word32 idx = 0; - word32 sigOutSz = 0; -#ifndef NO_RSA - RsaKey key; - int initRsaKey = 0; -#endif - int usingEcc = 0; -#ifdef HAVE_ECC - ecc_key eccKey; -#endif - - (void)idx; - - if (ssl->options.sendVerify == SEND_BLANK_CERT) - return 0; /* sent blank cert, can't verify */ - - if (IsEncryptionOn(ssl, 1)) - sendSz += MAX_MSG_EXTRA; - - /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - - ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); - if (ret != 0) - return ret; - -#ifdef HAVE_ECC - wc_ecc_init_h(&eccKey, ssl->heap); -#endif -#ifndef NO_RSA - ret = wc_InitRsaKey(&key, ssl->heap); - if (ret == 0) initRsaKey = 1; - if (ret == 0) - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key, - ssl->buffers.key->length); - if (ret == 0) { - int keySz = wc_RsaEncryptSize(&key); - if (keySz < 0) { /* check if keySz has error case */ - return keySz; - } - - sigOutSz = (word32)keySz; - if (keySz < ssl->options.minRsaKeySz) { - WOLFSSL_MSG("RSA key size too small"); - return RSA_KEY_SIZE_E; - } - } - else -#endif - { - #ifdef HAVE_ECC - WOLFSSL_MSG("Trying ECC client cert, RSA didn't work"); - - if (ssl->buffers.key == NULL) { - WOLFSSL_MSG("ECC Key missing"); - return NO_PRIVATE_KEY; - } - - idx = 0; - ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &eccKey, - ssl->buffers.key->length); - if (ret == 0) { - WOLFSSL_MSG("Using ECC client cert"); - usingEcc = 1; - sigOutSz = MAX_ENCODED_SIG_SZ; - - /* check minimum size of ECC key */ - if (wc_ecc_size(&eccKey) < ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size too small"); - return ECC_KEY_SIZE_E; + ERROR_OUT(sendSz, exit_scke); } } else { - WOLFSSL_MSG("Bad client cert type"); + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) { + goto exit_scke; + } } - #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + goto exit_scke; + } + } + #endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, + output, sendSz, ssl->heap); + #endif + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_END; + } /* case KEYSHARE_FINALIZE */ + + case KEYSHARE_END: + { + ssl->buffers.outputBuffer.length += sendSz; + + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); + } + if (ret == 0 || ret == WANT_WRITE) { + int tmpRet = MakeMasterSecret(ssl); + if (tmpRet != 0) { + ret = tmpRet; /* save WANT_WRITE unless more serious */ + } + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + break; } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.keyShareState) */ + +exit_scke: + + WOLFSSL_LEAVE("SendClientKeyExchange", ret); + + /* Handle cleanup for stack variables here */ + + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + /* Store variables needed for async */ + length_lcl = ssl->async.length; + XMEMSET(&ssl->async, 0, sizeof(ssl->async)); + ssl->async.output = output; + ssl->async.sendSz = sendSz; + ssl->async.data = encSecret; + ssl->async.sigSz = encSz; + ssl->async.length = length_lcl; + + /* Push event to queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); if (ret == 0) { - byte* verify = (byte*)&output[RECORD_HEADER_SZ + - HANDSHAKE_HEADER_SZ]; -#ifndef NO_OLD_TLS - byte* signBuffer = ssl->hsHashes->certHashes.md5; -#else - byte* signBuffer = NULL; -#endif - word32 signSz = FINISHED_SZ; - word32 extraSz = 0; /* tls 1.2 hash/sig */ -#ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; -#else - byte encodedSig[MAX_ENCODED_SIG_SZ]; + return WC_PENDING_E; + } + } #endif -#ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - #ifndef NO_RSA - if (initRsaKey) - wc_FreeRsaKey(&key); - #endif - #ifdef HAVE_ECC - wc_ecc_free(&eccKey); - #endif - return MEMORY_E; + /* No further need for PMS */ + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + ssl->arrays->preMasterSz = 0; + + if (encSecret) { + XFREE(encSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + encSecret = NULL; + } + + /* Final cleanup */ + FreeKeyExchange(ssl); + + return ret; +} + + +#ifndef NO_CERTS + +int SendCertificateVerify(WOLFSSL* ssl) +{ + byte* output = NULL; + int sendSz = 0, length = 0, ret; + byte* verify = NULL; + word32 idx = 0; + word32 extraSz = 0; +#ifndef NO_RSA + byte* verifySig = NULL; +#endif + + WOLFSSL_ENTER("SendCertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + if (ret != WC_NOT_PENDING_E) { + WOLF_EVENT_TYPE eType = ssl->event.type; + + /* Clear event */ + XMEMSET(&ssl->event, 0, sizeof(ssl->event)); + + /* Check for error */ + if (ret < 0) { + goto exit_scv; + } + else { + /* Restore variables needed for async */ + output = ssl->async.output; + sendSz = ssl->async.sendSz; + extraSz = ssl->async.sigSz; + length = ssl->async.length; + idx = ssl->async.idx; + #ifndef NO_RSA + verifySig = ssl->async.data; + #endif + + /* Advance key share state if not wolfCrypt */ + if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { + ssl->options.keyShareState++; } + } + } + else #endif + { + /* Reset state */ + ret = 0; + ssl->options.keyShareState = KEYSHARE_BEGIN; + } - (void)encodedSig; - (void)signSz; - (void)signBuffer; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - #endif - length = sigOutSz; - if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = ssl->suites->hashAlgo; - verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo; - extraSz = HASH_SIG_SIZE; + switch(ssl->options.keyShareState) + { + case KEYSHARE_BEGIN: + { + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + return 0; /* sent blank cert, can't verify */ } - if (usingEcc) { -#ifdef HAVE_ECC - word32 localSz = MAX_ENCODED_SIG_SZ; - word32 digestSz; - byte* digest; -#ifndef NO_OLD_TLS - /* old tls default */ - digestSz = SHA_DIGEST_SIZE; - digest = ssl->hsHashes->certHashes.sha; -#else - /* new tls default */ - digestSz = SHA256_DIGEST_SIZE; - digest = ssl->hsHashes->certHashes.sha256; -#endif + sendSz = MAX_CERT_VERIFY_SZ; + if (IsEncryptionOn(ssl, 1)) { + sendSz += MAX_MSG_EXTRA; + } - if (IsAtLeastTLSv1_2(ssl)) { - if (ssl->suites->hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = ssl->hsHashes->certHashes.sha; - digestSz = SHA_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + goto exit_scv; + } + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_BUILD; + } /* case KEYSHARE_BEGIN */ + + case KEYSHARE_BUILD: + { + int keySz; + int typeH; + + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + if (ret != 0) { + goto exit_scv; + } + + #ifndef NO_RSA + ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, + DYNAMIC_TYPE_RSA); + if (ssl->sigKey == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + ssl->sigType = DYNAMIC_TYPE_RSA; + + ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, ssl->devId); + if (ret != 0) { + goto exit_scv; + } + + WOLFSSL_MSG("Trying RSA client cert"); + + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + if (ret == 0) { + keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + if (keySz < 0) { /* check if keySz has error case */ + ERROR_OUT(keySz, exit_scv); } + length = (word32)keySz; + if (keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_scv); + } + } + else + #endif /* !NO_RSA */ + { + #ifdef HAVE_ECC + if (ssl->sigKey) { + XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_RSA); + } + ssl->sigKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_ECC); + if (ssl->sigKey == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + ssl->sigType = DYNAMIC_TYPE_ECC; + + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); + if (ret != 0) { + goto exit_scv; + } + + WOLFSSL_MSG("Trying ECC client cert, RSA didn't work"); + + if (ssl->buffers.key == NULL) { + WOLFSSL_MSG("ECC Key missing"); + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + + idx = 0; + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ecc_key*)ssl->sigKey, ssl->buffers.key->length); + if (ret != 0) { + WOLFSSL_MSG("Bad client cert type"); + goto exit_scv; + } + + WOLFSSL_MSG("Using ECC client cert"); + length = MAX_ENCODED_SIG_SZ; + + /* check minimum size of ECC key */ + keySz = wc_ecc_size((ecc_key*)ssl->sigKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_scv); + } + #endif + } + + + /* idx is used to track verify pointer offset to output */ + idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + verify = &output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + extraSz = 0; /* tls 1.2 hash/sig */ + + /* build encoded signature buffer */ + ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ; + ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + #ifndef NO_OLD_TLS + /* old tls default */ + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + typeH = SHAh; + #else + /* new tls default */ + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + typeH = SHA256h; + #endif + + if (IsAtLeastTLSv1_2(ssl)) { + verify[0] = ssl->suites->hashAlgo; + verify[1] = (ssl->sigType == DYNAMIC_TYPE_ECC) ? + ecc_dsa_sa_algo : rsa_sa_algo; + extraSz = HASH_SIG_SIZE; + + switch (ssl->suites->hashAlgo) { + #ifndef NO_SHA + case sha_mac: + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + typeH = SHAh; + break; + #endif /* NO_SHA */ + #ifndef NO_SHA256 + case sha256_mac: + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + typeH = SHA256h; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + typeH = SHA384h; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + typeH = SHA512h; + break; + #endif /* WOLFSSL_SHA512 */ + } /* switch */ + } + #ifndef NO_OLD_TLS + else { + /* if old TLS load MD5 hash as value to sign */ + XMEMCPY(ssl->buffers.sig.buffer, ssl->hsHashes->certHashes.md5, + FINISHED_SZ); + } + #endif + + (void)typeH; + + #ifndef NO_RSA + if (ssl->sigType == DYNAMIC_TYPE_RSA) { + ssl->buffers.sig.length = FINISHED_SZ; + ssl->sigLen = ENCRYPT_LEN; + + if (IsAtLeastTLSv1_2(ssl)) { + ssl->buffers.sig.length = wc_EncodeSignature( + ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, + ssl->buffers.digest.length, typeH); + } + + c16toa((word16)length, verify + extraSz); /* prepend hdr */ + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_DO; + } /* case KEYSHARE_BUILD */ + + case KEYSHARE_DO: + { + /* restore verify pointer */ + verify = &output[idx]; + + #ifdef HAVE_ECC + if (ssl->sigType == DYNAMIC_TYPE_ECC) { ret = EccSign(ssl, - digest, digestSz, - encodedSig, &localSz, - &eccKey, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + (ecc_key*)ssl->sigKey, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -15434,85 +15634,14 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) NULL, 0, NULL #endif ); - if (ret == 0) { - length = localSz; - c16toa((word16)length, verify + extraSz); /* prepend hdr */ - XMEMCPY(verify + extraSz + VERIFY_HEADER,encodedSig,length); - } -#endif /* HAVE_ECC */ } -#ifndef NO_RSA - else { - word32 ioLen = ENCRYPT_LEN; - - if (IsAtLeastTLSv1_2(ssl)) { - /* - * MSVC Compiler complains because it can not - * guarantee any of the conditionals will succeed in - * assigning a value before wc_EncodeSignature executes. - */ - byte* digest = NULL; - int digestSz = 0; - int typeH = 0; - int didSet = 0; - - if (ssl->suites->hashAlgo == sha_mac) { - #ifndef NO_SHA - digest = ssl->hsHashes->certHashes.sha; - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - didSet = 1; - #endif - } - else if (ssl->suites->hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - didSet = 1; - #endif - } - else if (ssl->suites->hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - didSet = 1; - #endif - } - else if (ssl->suites->hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - didSet = 1; - #endif - } - - if (didSet == 0) { - /* defaults */ - #ifndef NO_OLD_TLS - digest = ssl->hsHashes->certHashes.sha; - digestSz = SHA_DIGEST_SIZE; - typeH = SHAh; - #else - digest = ssl->hsHashes->certHashes.sha256; - digestSz = SHA256_DIGEST_SIZE; - typeH = SHA256h; - #endif - } - - signSz = wc_EncodeSignature(encodedSig, digest,digestSz,typeH); - signBuffer = encodedSig; - } - - c16toa((word16)length, verify + extraSz); /* prepend hdr */ - + #endif /* HAVE_ECC */ + #ifndef NO_RSA + if (ssl->sigType == DYNAMIC_TYPE_RSA) { ret = RsaSign(ssl, - signBuffer, signSz, - verify + extraSz + VERIFY_HEADER, - &ioLen, - &key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + verify + extraSz + VERIFY_HEADER, &ssl->sigLen, + (RsaKey*)ssl->sigKey, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -15521,27 +15650,66 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) NULL #endif ); - if (ret == 0) { - /* check for signature faults */ - ret = VerifyRsaSign(ssl, - verify + extraSz + VERIFY_HEADER, - ioLen, - signBuffer, - signSz, - &key); - } } -#endif -#ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + #endif /* !NO_RSA */ - if (ret == 0) { - AddHeaders(output, length + extraSz + VERIFY_HEADER, - certificate_verify, ssl); + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } - sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + - extraSz + VERIFY_HEADER; + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_VERIFY; + } /* case KEYSHARE_DO */ + + case KEYSHARE_VERIFY: + { + /* restore verify pointer */ + verify = &output[idx]; + + #ifdef HAVE_ECC + if (ssl->sigType == DYNAMIC_TYPE_ECC) { + length = ssl->buffers.sig.length; + c16toa((word16)ssl->buffers.sig.length, verify + extraSz); /* prepend hdr */ + XMEMCPY(verify + extraSz + VERIFY_HEADER, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + } + #endif /* HAVE_ECC */ + #ifndef NO_RSA + if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (verifySig == NULL) { + verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (verifySig == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + XMEMCPY(verifySig, verify + extraSz + VERIFY_HEADER, ssl->sigLen); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + verifySig, ssl->sigLen, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + (RsaKey*)ssl->sigKey); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_FINALIZE; + } /* case KEYSHARE_VERIFY */ + + case KEYSHARE_FINALIZE: + { + AddHeaders(output, length + extraSz + VERIFY_HEADER, + certificate_verify, ssl); + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + + extraSz + VERIFY_HEADER; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -15549,66 +15717,118 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) } #endif - if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = sendSz - RECORD_HEADER_SZ; - /* build msg adds rec hdr */ - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) - ret = MEMORY_E; - else { + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = sendSz - RECORD_HEADER_SZ; + /* build msg adds rec hdr */ + input = (byte*)XMALLOC(inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA, input, inputSz, handshake, 1, 0); XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (sendSz < 0) + if (sendSz < 0) { ret = sendSz; + } } - } else { - ret = HashOutput(ssl, output, sendSz, 0); - } - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif + else { + ret = HashOutput(ssl, output, sendSz, 0); } - } -#ifndef NO_RSA - if (initRsaKey) - wc_FreeRsaKey(&key); -#endif -#ifdef HAVE_ECC - wc_ecc_free(&eccKey); -#endif - if (ret == 0) { - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("CertificateVerify", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, - output, sendSz, ssl->heap); - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ret = DtlsPoolSave(ssl, output, sendSz); + } + #endif + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_END; + } /* case KEYSHARE_FINALIZE */ + + case KEYSHARE_END: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, + output, sendSz, ssl->heap); + #endif + ssl->buffers.outputBuffer.length += sendSz; - if (ssl->options.groupMessages) - return 0; - else - return SendBuffered(ssl); + + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); } - else - return ret; + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.keyShareState) */ + +exit_scv: + + WOLFSSL_LEAVE("SendCertificateVerify", ret); + + /* Handle cleanup for stack variables here */ + + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + /* Store variables needed for async */ + XMEMSET(&ssl->async, 0, sizeof(ssl->async)); + ssl->async.output = output; + ssl->async.sendSz = sendSz; + ssl->async.sigSz = extraSz; + ssl->async.length = length; + ssl->async.idx = idx; + #ifndef NO_RSA + ssl->async.data = verifySig; + #endif + + /* Push event to queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); + if (ret == 0) { + return WC_PENDING_E; + } } +#endif + +#ifndef NO_RSA + if (verifySig) { + XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + verifySig = NULL; + } +#endif + + /* Digest is not allocated, so do this to prevent free */ + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + + /* Final cleanup */ + FreeKeyExchange(ssl); + + return ret; +} + #endif /* NO_CERTS */ + #ifdef HAVE_SESSION_TICKET -int DoSessionTicket(WOLFSSL* ssl, - const byte* input, word32* inOutIdx, word32 size) +int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size) { word32 begin = *inOutIdx; word32 lifetime; @@ -15935,15 +16155,25 @@ int DoSessionTicket(WOLFSSL* ssl, qshSz = QSH_KeyGetSize(ssl); } #endif + #ifndef NO_RSA + byte* verifySig = NULL; + #endif (void)ssl; (void)sigSz; (void)length; (void)idx; + WOLFSSL_ENTER("SendServerKeyExchange"); + #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfSSL_async_pop(ssl, WOLF_EVENT_TYPE_ASYNC_ACCEPT); - if (ret != ASYNC_NOT_PENDING) { + ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + if (ret != WC_NOT_PENDING_E) { + WOLF_EVENT_TYPE eType = ssl->event.type; + + /* Clear event */ + XMEMSET(&ssl->event, 0, sizeof(ssl->event)); + /* Check for error */ if (ret < 0) { goto exit_sske; @@ -15955,9 +16185,14 @@ int DoSessionTicket(WOLFSSL* ssl, idx = ssl->async.idx; sigSz = ssl->async.sigSz; length = ssl->async.length; + #ifndef NO_RSA + verifySig = ssl->async.data; + #endif - /* Advance key share state */ - ssl->options.keyShareState++; + /* Advance key share state if not wolfCrypt */ + if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { + ssl->options.keyShareState++; + } } } else @@ -15978,8 +16213,7 @@ int DoSessionTicket(WOLFSSL* ssl, #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { - /* pub key size */ - WOLFSSL_MSG("Using ephemeral ECDH"); + WOLFSSL_MSG("Using ephemeral ECDH PSK"); break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -16073,9 +16307,18 @@ int DoSessionTicket(WOLFSSL* ssl, WOLFSSL_MSG("EccTempKey Memory error"); ERROR_OUT(MEMORY_E, exit_sske); } - wc_ecc_init_h(ssl->eccTempKey, ssl->heap); + ret = wc_ecc_init_ex(ssl->eccTempKey, ssl->heap, ssl->devId); + if (ret != 0) + goto exit_sske; + } + + if (ssl->eccTempKeyPresent == 0) { + /* TODO: Need to first do wc_EccPrivateKeyDecode, then we know curve dp */ + ret = EccMakeKey(ssl, ssl->eccTempKey, NULL); + if (ret == 0 || ret == WC_PENDING_E) { + ssl->eccTempKeyPresent = 1; + } } - ret = EccMakeTempKey(ssl); break; } #endif /* HAVE_ECC */ @@ -16325,8 +16568,8 @@ int DoSessionTicket(WOLFSSL* ssl, } ssl->sigType = DYNAMIC_TYPE_RSA; - ret = wc_InitRsaKey((RsaKey*)ssl->sigKey, - ssl->heap); + ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, + ssl->heap, ssl->devId); if (ret != 0) { goto exit_sske; } @@ -16360,7 +16603,9 @@ int DoSessionTicket(WOLFSSL* ssl, } ssl->sigType = DYNAMIC_TYPE_ECC; - wc_ecc_init_h((ecc_key*)ssl->sigKey, ssl->heap); + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); + if (ret != 0) + goto exit_sske; ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &i, (ecc_key*)ssl->sigKey, @@ -16560,40 +16805,11 @@ int DoSessionTicket(WOLFSSL* ssl, /* write sig size here */ c16toa((word16)ssl->sigLen, output + idx); idx += LENGTH_SZ; - - ret = RsaSign(ssl, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, - ssl->buffers.key->buffer, - ssl->buffers.key->length, - #ifdef HAVE_PK_CALLBACKS - ssl->RsaSignCtx - #else - NULL - #endif - ); break; } #endif /* !NO_RSA */ case ecc_dsa_sa_algo: { - ret = EccSign(ssl, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, - output + LENGTH_SZ + idx, - &ssl->sigLen, - (ecc_key*)ssl->sigKey, - #if defined(HAVE_PK_CALLBACKS) - ssl->buffers.key->buffer, - ssl->buffers.key->length, - ssl->EccSignCtx - #else - NULL, 0, NULL - #endif - ); break; } } /* switch(ssl->specs.sig_algo) */ @@ -16618,14 +16834,15 @@ int DoSessionTicket(WOLFSSL* ssl, word32 i = 0; int keySz; - ssl->sigKey = XMALLOC(sizeof(RsaKey), ssl->heap, + ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, DYNAMIC_TYPE_RSA); if (ssl->sigKey == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } ssl->sigType = DYNAMIC_TYPE_RSA; - ret = wc_InitRsaKey((RsaKey*)ssl->sigKey,ssl->heap); + ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, + ssl->heap, ssl->devId); if (ret != 0) { goto exit_sske; } @@ -16712,154 +16929,256 @@ int DoSessionTicket(WOLFSSL* ssl, } #endif - if (!ssl->options.usingAnon_cipher) { - /* Determine hash type */ - if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; + if (ssl->options.usingAnon_cipher) { + break; + } - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - hashType = WC_HASH_TYPE_SHA; - #endif - break; - default: - WOLFSSL_MSG("Bad hash sig algo"); - break; - } + /* Determine hash type */ + if (IsAtLeastTLSv1_2(ssl)) { + output[idx++] = ssl->suites->hashAlgo; + output[idx++] = ssl->suites->sigAlgo; - if (hashType == WC_HASH_TYPE_NONE) { - ERROR_OUT(ALGO_ID_E, exit_sske); - } - } else { - /* only using sha and md5 for rsa */ - #ifndef NO_OLD_TLS - hashType = WC_HASH_TYPE_SHA; - if (ssl->suites->sigAlgo == rsa_sa_algo) { - hashType = WC_HASH_TYPE_MD5_SHA; - } - #else + switch (ssl->suites->hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif + break; + case sha384_mac: + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif + break; + case sha256_mac: + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif + break; + case sha_mac: + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + #endif + break; + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + if (hashType == WC_HASH_TYPE_NONE) { ERROR_OUT(ALGO_ID_E, exit_sske); - #endif } - - /* signature size */ - c16toa((word16)sigSz, output + idx); - idx += LENGTH_SZ; - - /* Assemble buffer to hash for signature */ - sigDataSz = RAN_LEN + RAN_LEN + preSigSz; - sigDataBuf = (byte*)XMALLOC(sigDataSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (sigDataBuf == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; } - XMEMCPY(sigDataBuf, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN+RAN_LEN, output + preSigIdx, preSigSz); + #else + ERROR_OUT(ALGO_ID_E, exit_sske); + #endif + } - ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC( - ssl->buffers.sig.length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (ssl->buffers.sig.buffer == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } + /* signature size */ + c16toa((word16)sigSz, output + idx); + idx += LENGTH_SZ; - /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, - ssl->buffers.sig.buffer, ssl->buffers.sig.length); - if (ret != 0) { - goto exit_sske; - } + /* Assemble buffer to hash for signature */ + sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + sigDataBuf = (byte*)XMALLOC(sigDataSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sigDataBuf == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(sigDataBuf, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(sigDataBuf+RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(sigDataBuf+RAN_LEN+RAN_LEN, output + preSigIdx, preSigSz); - ssl->sigLen = sigSz; + ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( + ssl->buffers.sig.length, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } - /* Sign hash to create signature */ - switch (ssl->suites->sigAlgo) + /* Perform hash */ + ret = wc_Hash(hashType, sigDataBuf, sigDataSz, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } + + ssl->sigLen = sigSz; + + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: { - #ifndef NO_RSA - case rsa_sa_algo: - { - /* For TLS 1.2 re-encode signature */ - if (IsAtLeastTLSv1_2(ssl)) { - int typeH = 0; - byte* encodedSig = (byte*)XMALLOC( - MAX_ENCODED_SIG_SZ, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - - switch (ssl->suites->hashAlgo) { - case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif - break; - case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif - break; - case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif - break; - case sha_mac: - #ifndef NO_OLD_TLS - typeH = SHAh; - #endif - break; - default: - break; - } - - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); - - /* Replace sig buffer with new one */ - XFREE(ssl->buffers.sig.buffer, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - ssl->buffers.sig.buffer = encodedSig; + /* For TLS 1.2 re-encode signature */ + if (IsAtLeastTLSv1_2(ssl)) { + int typeH = 0; + byte* encodedSig = (byte*)XMALLOC( + MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); } - ret = RsaSign(ssl, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, - ssl->buffers.key->buffer, - ssl->buffers.key->length, - #ifdef HAVE_PK_CALLBACKS - ssl->RsaSignCtx - #else - NULL - #endif - ); + switch (ssl->suites->hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + typeH = SHA512h; + #endif + break; + case sha384_mac: + #ifdef WOLFSSL_SHA384 + typeH = SHA384h; + #endif + break; + case sha256_mac: + #ifndef NO_SHA256 + typeH = SHA256h; + #endif + break; + case sha_mac: + #ifndef NO_OLD_TLS + typeH = SHAh; + #endif + break; + default: + break; + } + + ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + + /* Replace sig buffer with new one */ + XFREE(ssl->buffers.sig.buffer, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = encodedSig; + } + break; + } + #endif /* NO_RSA */ + } /* switch (ssl->suites->sigAlgo) */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_DO; + } /* case KEYSHARE_BUILD */ + + case KEYSHARE_DO: + { + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { + break; + } + #endif /* HAVE_ECC && !NO_PSK */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + /* Sign hash to create signature */ + switch (ssl->specs.sig_algo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + output + idx, + &ssl->sigLen, + (RsaKey*)ssl->sigKey, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + #ifdef HAVE_PK_CALLBACKS + ssl->RsaSignCtx + #else + NULL + #endif + ); + break; + } + #endif /* !NO_RSA */ + case ecc_dsa_sa_algo: + { + ret = EccSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + output + LENGTH_SZ + idx, + &ssl->sigLen, + (ecc_key*)ssl->sigKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->EccSignCtx + #else + NULL, 0, NULL + #endif + ); + break; + } + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + if (ssl->options.usingAnon_cipher) { break; } - #endif /* NO_RSA */ - } /* switch (ssl->suites->sigAlgo) */ - } /* !ssl->options.usingAnon_cipher */ + + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + output + idx, + &ssl->sigLen, + (RsaKey*)ssl->sigKey, + ssl->buffers.key->buffer, + ssl->buffers.key->length, + #ifdef HAVE_PK_CALLBACKS + ssl->RsaSignCtx + #else + NULL + #endif + ); + break; + } + #endif /* NO_RSA */ + } /* switch (ssl->suites->sigAlgo) */ break; } @@ -16873,7 +17192,7 @@ int DoSessionTicket(WOLFSSL* ssl, /* Advance state and proceed */ ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_BUILD */ + } /* case KEYSHARE_DO */ case KEYSHARE_VERIFY: { @@ -16908,13 +17227,21 @@ int DoSessionTicket(WOLFSSL* ssl, #ifndef NO_RSA case rsa_sa_algo: { + if (verifySig == NULL) { + verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (!verifySig) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(verifySig, output + idx, ssl->sigLen); + } + /* check for signature faults */ ret = VerifyRsaSign(ssl, - output + idx, - ssl->sigLen, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + verifySig, ssl->sigLen, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + (RsaKey*)ssl->sigKey); break; } #endif @@ -16942,15 +17269,25 @@ int DoSessionTicket(WOLFSSL* ssl, #ifndef NO_RSA case rsa_sa_algo: { - if (!ssl->options.usingAnon_cipher) { - /* check for signature faults */ - ret = VerifyRsaSign(ssl, - output + idx, - ssl->sigLen, - ssl->buffers.sig.buffer, - ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + if (ssl->options.usingAnon_cipher) { + break; } + + if (verifySig == NULL) { + verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (!verifySig) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(verifySig, output + idx, ssl->sigLen); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + verifySig, ssl->sigLen, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + (RsaKey*)ssl->sigKey); break; } #endif @@ -17053,6 +17390,8 @@ int DoSessionTicket(WOLFSSL* ssl, exit_sske: + WOLFSSL_LEAVE("SendServerKeyExchange", ret); + /* Handle cleanup for stack variables here */ #if defined(HAVE_ECC) if (exportBuf) { @@ -17067,7 +17406,8 @@ int DoSessionTicket(WOLFSSL* ssl, } #endif -#ifdef WOLFSSL_ASYNC_CRYPT + + #ifdef WOLFSSL_ASYNC_CRYPT /* Handle WC_PENDING_E */ if (ret == WC_PENDING_E) { /* Store variables needed for async */ @@ -17077,14 +17417,24 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->async.idx = idx; ssl->async.length = length; ssl->async.sigSz = sigSz; + #ifndef NO_RSA + ssl->async.data = verifySig; + #endif /* Push event to queue */ - ret = wolfSSL_async_push(ssl, WOLF_EVENT_TYPE_ASYNC_ACCEPT); + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); if (ret == 0) { return WC_PENDING_E; } } -#endif + #endif + + #ifndef NO_RSA + if (verifySig) { + XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + verifySig = NULL; + } + #endif /* Final cleanup */ FreeKeyExchange(ssl); @@ -17830,179 +18180,329 @@ int DoSessionTicket(WOLFSSL* ssl, return MatchSuite(ssl, &clSuites); } + #if !defined(NO_RSA) || defined(HAVE_ECC) - static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, - word32 size) + + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 size) { + int ret = 0; + byte* output = NULL; + word32 sendSz = 0; word16 sz = 0; - int ret = VERIFY_CERT_ERROR; /* start in error state */ + word32 sigSz = 0; byte hashAlgo = sha_mac; byte sigAlgo = anonymous_sa_algo; - word32 begin = *inOutIdx; + word32 idx = *inOutIdx, begin = *inOutIdx; - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("CertificateVerify", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("CertificateVerify", &ssl->timeoutInfo); - #endif + WOLFSSL_ENTER("DoCertificateVerify"); + (void)sigSz; + (void)output; + (void)sendSz; - if (IsAtLeastTLSv1_2(ssl)) { - if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) - return BUFFER_ERROR; + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + if (ret != WC_NOT_PENDING_E) { + WOLF_EVENT_TYPE eType = ssl->event.type; - hashAlgo = input[(*inOutIdx)++]; - sigAlgo = input[(*inOutIdx)++]; - } + /* Clear event */ + XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - if ((*inOutIdx - begin) + OPAQUE16_LEN > size) - return BUFFER_ERROR; - - ato16(input + *inOutIdx, &sz); - *inOutIdx += OPAQUE16_LEN; - - if ((*inOutIdx - begin) + sz > size || sz > ENCRYPT_LEN) - return BUFFER_ERROR; - - /* RSA */ -#ifndef NO_RSA - if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { - byte* out = NULL; - int outLen = 0; - - WOLFSSL_MSG("Doing RSA peer cert verify"); - - outLen = RsaVerify(ssl, - input + *inOutIdx, - sz, - &out, - ssl->peerRsaKey, -#ifdef HAVE_PK_CALLBACKS - ssl->buffers.peerRsaKey.buffer, - ssl->buffers.peerRsaKey.length, - ssl->RsaVerifyCtx -#else - NULL, 0, NULL -#endif - ); - - if (IsAtLeastTLSv1_2(ssl)) { -#ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; -#else - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - word32 sigSz; - byte* digest = ssl->hsHashes->certHashes.sha; - int typeH = SHAh; - int digestSz = SHA_DIGEST_SIZE; - -#ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) - return MEMORY_E; -#endif - - if (sigAlgo != rsa_sa_algo) { - WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); - } - - if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - - sigSz = wc_EncodeSignature(encodedSig, digest, digestSz, typeH); - - if (outLen == (int)sigSz && out && XMEMCMP(out, encodedSig, - min(sigSz, MAX_ENCODED_SIG_SZ)) == 0) - ret = 0; /* verified */ - -#ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* Check for error */ + if (ret < 0) { + goto exit_dcv; } - else { - if (outLen == FINISHED_SZ && out && XMEMCMP(out, - &ssl->hsHashes->certHashes, - FINISHED_SZ) == 0) { - ret = 0; /* verified */ + else { + /* Restore variables needed for async */ + output = ssl->async.output; + sendSz = ssl->async.sendSz; + idx = ssl->async.idx; + sigSz = ssl->async.sigSz; + sz = ssl->async.length; + sigAlgo = ssl->async.sigAlgo; + hashAlgo = ssl->async.hashAlgo; + + /* Advance key share state if not wolfCrypt */ + if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { + ssl->options.keyShareState++; } } } -#endif -#ifdef HAVE_ECC - if (ssl->peerEccDsaKeyPresent) { - byte* digest = ssl->hsHashes->certHashes.sha; - word32 digestSz = SHA_DIGEST_SIZE; + else + #endif + { + /* Reset state */ + ret = 0; + ssl->options.keyShareState = KEYSHARE_BEGIN; + } - WOLFSSL_MSG("Doing ECC peer cert verify"); - - if (IsAtLeastTLSv1_2(ssl)) { - if (sigAlgo != ecc_dsa_sa_algo) { - WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); - } - - if (hashAlgo == sha256_mac) { - #ifndef NO_SHA256 - digest = ssl->hsHashes->certHashes.sha256; - digestSz = SHA256_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha384_mac) { - #ifdef WOLFSSL_SHA384 - digest = ssl->hsHashes->certHashes.sha384; - digestSz = SHA384_DIGEST_SIZE; - #endif - } - else if (hashAlgo == sha512_mac) { - #ifdef WOLFSSL_SHA512 - digest = ssl->hsHashes->certHashes.sha512; - digestSz = SHA512_DIGEST_SIZE; - #endif - } - } - - ret = EccVerify(ssl, - input + *inOutIdx, sz, - digest, digestSz, - ssl->peerEccDsaKey, - #ifdef HAVE_PK_CALLBACKS - ssl->buffers.peerEccDsaKey.buffer, - ssl->buffers.peerEccDsaKey.length, - ssl->EccVerifyCtx - #else - NULL, 0, NULL + switch(ssl->options.keyShareState) + { + case KEYSHARE_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("CertificateVerify", &ssl->timeoutInfo); #endif - ); - } -#endif - *inOutIdx += sz; - if (ret == 0) - ssl->options.havePeerVerify = 1; + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_BUILD; + } /* case KEYSHARE_BEGIN */ + + case KEYSHARE_BUILD: + { + if (IsAtLeastTLSv1_2(ssl)) { + if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + hashAlgo = input[idx++]; + sigAlgo = input[idx++]; + } + + if ((idx - begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + ato16(input + idx, &sz); + idx += OPAQUE16_LEN; + + if ((idx - begin) + sz > size || sz > ENCRYPT_LEN) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + + WOLFSSL_MSG("Doing ECC peer cert verify"); + + if (IsAtLeastTLSv1_2(ssl)) { + if (sigAlgo != ecc_dsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + + if (hashAlgo == sha256_mac) { + #ifndef NO_SHA256 + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha384_mac) { + #ifdef WOLFSSL_SHA384 + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #endif + } + else if (hashAlgo == sha512_mac) { + #ifdef WOLFSSL_SHA512 + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #endif + } + } + } + #endif /* HAVE_ECC */ + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_DO; + } /* case KEYSHARE_BUILD */ + + case KEYSHARE_DO: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, + input + idx, + sz, + &output, + ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx + #else + NULL, 0, NULL + #endif + ); + if (ret >= 0) { + sendSz = ret; + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + ret = EccVerify(ssl, + input + idx, sz, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->EccVerifyCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* HAVE_ECC */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcv; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_VERIFY; + } /* case KEYSHARE_DO */ + + case KEYSHARE_VERIFY: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + int typeH = SHAh; + + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + #endif + + if (sigAlgo != rsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + + switch (hashAlgo) { + #ifndef NO_SHA256 + case sha256_mac: + typeH = SHA256h; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + typeH = SHA384h; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + typeH = SHA512h; + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + } /* switch */ + + sigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + typeH); + + if (sendSz != sigSz || !output || XMEMCMP(output, + encodedSig, min(sigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_CERT_ERROR; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + else { + if (sendSz != FINISHED_SZ || !output || XMEMCMP(output, + &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) { + ret = VERIFY_CERT_ERROR; + } + } + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_FINALIZE; + } /* case KEYSHARE_VERIFY */ + + case KEYSHARE_FINALIZE: + { + ssl->options.havePeerVerify = 1; + + /* Set final index */ + idx += sz; + *inOutIdx = idx; + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_END; + } /* case KEYSHARE_FINALIZE */ + + case KEYSHARE_END: + { + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.keyShareState) */ + + exit_dcv: + + WOLFSSL_LEAVE("DoCertificateVerify", ret); + + /* Handle cleanup for stack variables here */ + + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + /* Store variables needed for async */ + XMEMSET(&ssl->async, 0, sizeof(ssl->async)); + ssl->async.output = output; + ssl->async.sendSz = sendSz; + ssl->async.idx = idx; + ssl->async.sigSz = sigSz; + ssl->async.length = sz; + ssl->async.sigAlgo = sigAlgo; + ssl->async.hashAlgo = hashAlgo; + + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + /* Push event to queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); + if (ret == 0) { + return WC_PENDING_E; + } + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Digest is not allocated, so do this to prevent free */ + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + + /* Final cleanup */ + FreeKeyExchange(ssl); return ret; } + #endif /* !NO_RSA || HAVE_ECC */ int SendServerHelloDone(WOLFSSL* ssl) @@ -18296,7 +18796,7 @@ int DoSessionTicket(WOLFSSL* ssl, return SendBuffered(ssl); } -#endif +#endif /* WOLFSSL_DTLS */ static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) @@ -18314,12 +18814,19 @@ int DoSessionTicket(WOLFSSL* ssl, (void)idx; (void)output; + WOLFSSL_ENTER("DoClientKeyExchange"); + #ifdef WOLFSSL_ASYNC_CRYPT - /* Use async output pointer */ + /* use async pointer for output */ output = &ssl->async.output; - ret = wolfSSL_async_pop(ssl, WOLF_EVENT_TYPE_ASYNC_ACCEPT); - if (ret != ASYNC_NOT_PENDING) { + ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + if (ret != WC_NOT_PENDING_E) { + WOLF_EVENT_TYPE eType = ssl->event.type; + + /* Clear event */ + XMEMSET(&ssl->event, 0, sizeof(ssl->event)); + /* Check for error */ if (ret < 0) { goto exit_dcke; @@ -18329,12 +18836,14 @@ int DoSessionTicket(WOLFSSL* ssl, idx = ssl->async.idx; length = ssl->async.length; - /* Advance state */ - ssl->options.keyShareState++; + /* Advance key share state if not wolfCrypt */ + if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { + ssl->options.keyShareState++; + } } } else - #endif + #endif /* WOLFSSL_ASYNC_CRYPT */ { /* Reset state */ ret = 0; @@ -18374,7 +18883,7 @@ int DoSessionTicket(WOLFSSL* ssl, return NO_PEER_CERT; } } - #endif + #endif /* !NO_CERTS */ #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) { @@ -18489,13 +18998,14 @@ int DoSessionTicket(WOLFSSL* ssl, } ssl->sigType = DYNAMIC_TYPE_RSA; - ret = wc_InitRsaKey((RsaKey*)ssl->sigKey, ssl->heap); + ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, + ssl->devId); if (ret != 0) { goto exit_dcke; } - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &i, - (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, + &i, (RsaKey*)ssl->sigKey, ssl->buffers.key->length); if (ret != 0) { goto exit_dcke; } @@ -18532,22 +19042,7 @@ int DoSessionTicket(WOLFSSL* ssl, ERROR_OUT(BUFFER_ERROR, exit_dcke); } - /* These RSA variables persist throughout DoClientKeyExchange */ *output = NULL; - ret = RsaDec(ssl, - input + idx, - length, - output, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, - #if defined(HAVE_PK_CALLBACKS) - ssl->buffers.key->buffer, - ssl->buffers.key->length, - ssl->RsaDecCtx - #else - NULL, 0, NULL - #endif - ); break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -18636,7 +19131,6 @@ int DoSessionTicket(WOLFSSL* ssl, idx += cipherLen; ssl->arrays->preMasterSz = plainLen; - break; } #endif /* HAVE_NTRU */ @@ -18656,7 +19150,10 @@ int DoSessionTicket(WOLFSSL* ssl, } ssl->sigType = DYNAMIC_TYPE_ECC; - wc_ecc_init_h((ecc_key*)ssl->sigKey, ssl->heap); + ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); + if (ret != 0) { + goto exit_dcke; + } ret = wc_EccPrivateKeyDecode( ssl->buffers.key->buffer, @@ -18666,7 +19163,7 @@ int DoSessionTicket(WOLFSSL* ssl, if (ret == 0) { private_key = (ecc_key*)ssl->sigKey; if (wc_ecc_size(private_key) < - ssl->options.minEccKeySz) { + ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key too small"); ERROR_OUT(ECC_KEY_SIZE_E, exit_dcke); } @@ -18692,11 +19189,19 @@ int DoSessionTicket(WOLFSSL* ssl, WOLFSSL_MSG("PeerEccKey Memory error"); ERROR_OUT(MEMORY_E, exit_dcke); } - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ wc_ecc_free(ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } } if (wc_ecc_import_x963_ex(input + idx, length, ssl->peerEccKey, @@ -18708,14 +19213,10 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->peerEccKeyPresent = 1; ssl->sigLen = sizeof(ssl->arrays->preMasterSecret); - + if (ret != 0) { - ERROR_OUT(ECC_SHARED_ERROR, exit_dcke); + goto exit_dcke; } - - /* Generate shared secret */ - ret = EccSharedSecret(ssl, private_key, ssl->peerEccKey, - ssl->arrays->preMasterSecret, &ssl->sigLen); break; } #endif /* HAVE_ECC */ @@ -18735,28 +19236,13 @@ int DoSessionTicket(WOLFSSL* ssl, ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, - ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientPubSz, - ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz); - - idx += clientPubSz; + ssl->sigLen = clientPubSz; break; } #endif /* !NO_DH */ #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; word16 clientSz; /* Read in the PSK hint */ @@ -18791,41 +19277,7 @@ int DoSessionTicket(WOLFSSL* ssl, ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, - ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientSz, - pms + OPAQUE16_LEN, - &ssl->arrays->preMasterSz); - - idx += clientSz; - c16toa((word16)ssl->arrays->preMasterSz, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN; - pms += ssl->arrays->preMasterSz; - - /* Use the PSK hint to look up the PSK and add it to the - * preMasterSecret here. */ - ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, - ssl->arrays->client_identity, ssl->arrays->psk_key, - MAX_PSK_KEY_LEN); - - if (ssl->arrays->psk_keySz == 0 || - ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { - ERROR_OUT(PSK_KEY_ERROR, exit_dcke); - } - - c16toa((word16) ssl->arrays->psk_keySz, pms); - pms += OPAQUE16_LEN; - - XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + OPAQUE16_LEN; + ssl->sigLen = clientSz; break; } #endif /* !NO_DH && !NO_PSK */ @@ -18873,11 +19325,19 @@ int DoSessionTicket(WOLFSSL* ssl, WOLFSSL_MSG("PeerEccKey Memory error"); ERROR_OUT(MEMORY_E, exit_dcke); } - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ wc_ecc_free(ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - wc_ecc_init_h(ssl->peerEccKey, ssl->heap); + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); + if (ret != 0) { + goto exit_dcke; + } } if (wc_ecc_import_x963_ex(input + idx, length, ssl->peerEccKey, ssl->eccTempKey->dp->id)) { @@ -18890,6 +19350,121 @@ int DoSessionTicket(WOLFSSL* ssl, /* Note sizeof preMasterSecret is ENCRYPT_LEN currently 512 */ ssl->sigLen = sizeof(ssl->arrays->preMasterSecret); + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + break; + } + #endif /* HAVE_ECC && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.keyShareState = KEYSHARE_DO; + } /* KEYSHARE_BUILD */ + + case KEYSHARE_DO: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + ret = RsaDec(ssl, + input + idx, + length, + output, + &ssl->sigLen, + (RsaKey*)ssl->sigKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, + ssl->buffers.key->length, + ssl->RsaDecCtx + #else + NULL, 0, NULL + #endif + ); + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + break; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + { + ecc_key* private_key = ssl->eccTempKey; + if (ssl->specs.static_ecdh) { + private_key = (ecc_key*)ssl->sigKey; + } + + /* Generate shared secret */ + ret = EccSharedSecret(ssl, private_key, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &ssl->sigLen); + break; + } + #endif /* HAVE_ECC */ + #ifndef NO_DH + case diffie_hellman_kea: + { + word16 clientPubSz = (word16)ssl->sigLen; + + ret = DhAgree(ssl, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + ssl->buffers.serverDH_Priv.buffer, + &ssl->buffers.serverDH_Priv.length, + NULL, + 0, + input + idx, + clientPubSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = ssl->sigLen; + + ret = DhAgree(ssl, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + ssl->buffers.serverDH_Priv.buffer, + &ssl->buffers.serverDH_Priv.length, + NULL, + 0, + input + idx, + clientSz, + pms + OPAQUE16_LEN, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if defined(HAVE_ECC) && !defined(NO_PSK) + case ecdhe_psk_kea: + { /* Generate shared secret */ ret = EccSharedSecret(ssl, ssl->eccTempKey, @@ -18910,7 +19485,7 @@ int DoSessionTicket(WOLFSSL* ssl, /* Advance state and proceed */ ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* KEYSHARE_BUILD */ + } /* KEYSHARE_DO */ case KEYSHARE_VERIFY: { @@ -18956,12 +19531,38 @@ int DoSessionTicket(WOLFSSL* ssl, #ifndef NO_DH case diffie_hellman_kea: { + word16 clientPubSz = (word16)ssl->sigLen; + idx += clientPubSz; break; } #endif /* !NO_DH */ #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = ssl->sigLen; + + idx += clientSz; + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; + pms += ssl->arrays->preMasterSz; + + /* Use the PSK hint to look up the PSK and add it to the + * preMasterSecret here. */ + ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + c16toa((word16) ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + OPAQUE16_LEN; break; } #endif /* !NO_DH && !NO_PSK */ @@ -19034,7 +19635,7 @@ int DoSessionTicket(WOLFSSL* ssl, ERROR_OUT(BUFFER_ERROR, exit_dcke); } } - #endif + #endif /* HAVE_QSH */ ret = MakeMasterSecret(ssl); /* Check for error */ @@ -19064,26 +19665,32 @@ int DoSessionTicket(WOLFSSL* ssl, } /* switch(ssl->options.keyShareState) */ exit_dcke: + + WOLFSSL_LEAVE("DoClientKeyExchange", ret); + + /* Handle cleanup for stack variables here */ + + #ifdef WOLFSSL_ASYNC_CRYPT /* Handle WC_PENDING_E */ if (ret == WC_PENDING_E) { /* Store variables needed for async */ + output_lcl = ssl->async.output; XMEMSET(&ssl->async, 0, sizeof(ssl->async)); ssl->async.idx = idx; ssl->async.length = length; + ssl->async.output = output_lcl; - /* Adjust the index so header will be re-evaluated */ - *inOutIdx -= HANDSHAKE_HEADER_SZ; /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_client_key_exchange = 0; /* Push event to queue */ - ret = wolfSSL_async_push(ssl, WOLF_EVENT_TYPE_ASYNC_ACCEPT); + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); if (ret == 0) { return WC_PENDING_E; } } - #endif + #endif /* WOLFSSL_ASYNC_CRYPT */ /* Cleanup PMS */ ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); diff --git a/src/keys.c b/src/keys.c index dd3207c88..50e888521 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2070,18 +2070,18 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); if (dec && dec->arc4 == NULL) return MEMORY_E; -#ifdef HAVE_CAVIUM - if (devId != NO_CAVIUM_DEVICE) { +#ifdef WOLFSSL_ASYNC_CRYPT + if (devId != INVALID_DEVID) { if (enc) { - if (wc_Arc4InitCavium(enc->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; + if (wc_Arc4AsyncInit(enc->arc4, devId) != 0) { + WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); + return ASYNC_INIT_E; } } if (dec) { - if (wc_Arc4InitCavium(dec->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; + if (wc_Arc4AsyncInit(dec->arc4, devId) != 0) { + WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); + return ASYNC_INIT_E; } } } @@ -2282,18 +2282,18 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); if (dec && dec->des3 == NULL) return MEMORY_E; -#ifdef HAVE_CAVIUM - if (devId != NO_CAVIUM_DEVICE) { +#ifdef WOLFSSL_ASYNC_CRYPT + if (devId != INVALID_DEVID) { if (enc) { - if (wc_Des3_InitCavium(enc->des3, devId) != 0) { - WOLFSSL_MSG("Des3_InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; + if (wc_Des3AsyncInit(enc->des3, devId) != 0) { + WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); + return ASYNC_INIT_E; } } if (dec) { - if (wc_Des3_InitCavium(dec->des3, devId) != 0) { - WOLFSSL_MSG("Des3_InitCavium failed in SetKeys"); - return CAVIUM_INIT_E; + if (wc_Des3AsyncInit(dec->des3, devId) != 0) { + WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); + return ASYNC_INIT_E; } } } @@ -2346,18 +2346,18 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); if (dec && dec->aes == NULL) return MEMORY_E; -#ifdef HAVE_CAVIUM - if (devId != NO_CAVIUM_DEVICE) { +#ifdef WOLFSSL_ASYNC_CRYPT + if (devId != INVALID_DEVID) { if (enc) { - if (wc_AesInitCavium(enc->aes, devId) != 0) { - WOLFSSL_MSG("AesInitCavium failed in SetKeys"); - return CAVIUM_INIT_E; + if (wc_AesAsyncInit(enc->aes, devId) != 0) { + WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); + return ASYNC_INIT_E; } } if (dec) { - if (wc_AesInitCavium(dec->aes, devId) != 0) { - WOLFSSL_MSG("AesInitCavium failed in SetKeys"); - return CAVIUM_INIT_E; + if (wc_AesAsyncInit(dec->aes, devId) != 0) { + WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); + return ASYNC_INIT_E; } } } @@ -2675,14 +2675,14 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, */ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) { - int devId = NO_CAVIUM_DEVICE, ret, copy = 0; + int devId = INVALID_DEVID, ret, copy = 0; Ciphers* wc_encrypt = NULL; Ciphers* wc_decrypt = NULL; Keys* keys = &ssl->keys; (void)copy; -#ifdef HAVE_CAVIUM +#ifdef WOLFSSL_ASYNC_CRYPT devId = ssl->devId; #endif diff --git a/src/ssl.c b/src/ssl.c index 11c313c45..2fb0d17ed 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1090,10 +1090,10 @@ int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) } -#ifdef HAVE_CAVIUM +#ifdef WOLFSSL_ASYNC_CRYPT -/* let's use cavium, SSL_SUCCESS on ok */ -int wolfSSL_UseCavium(WOLFSSL* ssl, int devId) +/* let's use async hardware, SSL_SUCCESS on ok */ +int wolfSSL_UseAsync(WOLFSSL* ssl, int devId) { if (ssl == NULL) return BAD_FUNC_ARG; @@ -1104,8 +1104,8 @@ int wolfSSL_UseCavium(WOLFSSL* ssl, int devId) } -/* let's use cavium, SSL_SUCCESS on ok */ -int wolfSSL_CTX_UseCavium(WOLFSSL_CTX* ctx, int devId) +/* let's use async hardware, SSL_SUCCESS on ok */ +int wolfSSL_CTX_UseAsync(WOLFSSL_CTX* ctx, int devId) { if (ctx == NULL) return BAD_FUNC_ARG; @@ -1115,8 +1115,7 @@ int wolfSSL_CTX_UseCavium(WOLFSSL_CTX* ctx, int devId) return SSL_SUCCESS; } - -#endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_SNI @@ -19016,118 +19015,38 @@ void* wolfSSL_get_jobject(WOLFSSL* ssl) #endif /* WOLFSSL_JNI */ -#ifdef HAVE_WOLF_EVENT -static int _wolfSSL_CTX_poll(WOLFSSL_CTX* ctx, WOLFSSL* ssl, WOLF_EVENT* events, - int maxEvents, unsigned char flags, int* eventCount) + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount) { - WOLF_EVENT* event, *event_prev = NULL; - int count = 0, ret = SSL_ERROR_NONE; - - if (ctx == NULL || maxEvents <= 0) { + if (ctx == NULL) { return BAD_FUNC_ARG; } - /* Events arg can be NULL only if peek */ - if (events == NULL && !(flags & WOLF_POLL_FLAG_PEEK)) { + return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, + events, maxEvents, flags, eventCount); +} + +int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) +{ + int ret, eventCount = 0; + WOLF_EVENT* events[1]; + + if (ssl == NULL) { return BAD_FUNC_ARG; } -#ifndef SINGLE_THREADED - /* In single threaded mode "event_queue.lock" doesn't exist */ - if (LockMutex(&ctx->event_queue.lock) != 0) { - return BAD_MUTEX_E; - } -#endif - - /* Itterate event queue */ - for (event = ctx->event_queue.head; event != NULL; event = event->next) - { - byte removeEvent = 0; - - /* Optionally filter by ssl object pointer */ - if (ssl == NULL || (ssl == event->ssl)) { - if (flags & WOLF_POLL_FLAG_PEEK) { - if (events) { - /* Copy event data to provided buffer */ - XMEMCPY(&events[count], event, sizeof(WOLF_EVENT)); - } - count++; - } - else { - /* Check hardware */ - if (flags & WOLF_POLL_FLAG_CHECK_HW) { - #ifdef WOLFSSL_ASYNC_CRYPT - if (event->type >= WOLF_EVENT_TYPE_ASYNC_FIRST && - event->type <= WOLF_EVENT_TYPE_ASYNC_LAST) - { - ret = wolfSSL_async_poll(event, flags); - } - #endif /* WOLFSSL_ASYNC_CRYPT */ - } - - /* If event is done then return in 'events' argument */ - if (event->done) { - /* Copy event data to provided buffer */ - XMEMCPY(&events[count], event, sizeof(WOLF_EVENT)); - count++; - removeEvent = 1; - } - } - } - - if (removeEvent) { - /* Remove from queue list */ - if (event_prev == NULL) { - ctx->event_queue.head = event->next; - if (ctx->event_queue.head == NULL) { - ctx->event_queue.tail = NULL; - } - } - else { - event_prev->next = event->next; - } - } - else { - /* Leave in queue, save prev pointer */ - event_prev = event; - } - - /* Check to make sure our event list isn't full */ - if (events && count >= maxEvents) { - break; /* Exit for */ - } - - /* Check for error */ - if (ret < 0) { - break; /* Exit for */ - } - } - -#ifndef SINGLE_THREADED - UnLockMutex(&ctx->event_queue.lock); -#endif - - /* Return number of properly populated events */ - if (eventCount) { - *eventCount = count; + /* not filtering on "ssl", since its the asyncDev */ + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, NULL, + events, sizeof(events)/sizeof(events), flags, &eventCount); + if (ret == 0 && eventCount > 0) { + ret = 1; /* Success */ } return ret; } +#endif /* WOLFSSL_ASYNC_CRYPT */ -int wolfSSL_CTX_poll(WOLFSSL_CTX* ctx, WOLF_EVENT* events, - int maxEvents, unsigned char flags, int* eventCount) -{ - return _wolfSSL_CTX_poll(ctx, NULL, events, maxEvents, flags, eventCount); -} - -int wolfSSL_poll(WOLFSSL* ssl, WOLF_EVENT* events, - int maxEvents, unsigned char flags, int* eventCount) -{ - return _wolfSSL_CTX_poll(ssl->ctx, ssl, events, maxEvents, flags, - eventCount); -} - -#endif /* HAVE_WOLF_EVENT */ #endif /* WOLFCRYPT_ONLY */ diff --git a/tests/api.c b/tests/api.c index 689100e68..a387a404d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -537,6 +537,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) char msg[] = "I hear you fa shizzle!"; char input[1024]; int idx; + int ret, err = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -602,9 +603,22 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #endif #endif - if (wolfSSL_accept(ssl) != SSL_SUCCESS) - { - int err = wolfSSL_get_error(ssl, 0); + do { +#ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) { break; } else if (ret == 0) { continue; } + } +#endif + + err = 0; /* Reset error */ + ret = wolfSSL_accept(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + + if (ret != SSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); /*err_sys("SSL_accept failed");*/ @@ -666,6 +680,7 @@ static void test_client_nofail(void* args) char reply[1024]; int input; int msgSz = (int)XSTRLEN(msg); + int ret, err = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -706,12 +721,25 @@ static void test_client_nofail(void* args) goto done2; } - if (wolfSSL_connect(ssl) != SSL_SUCCESS) - { - int err = wolfSSL_get_error(ssl, 0); + do { +#ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) { break; } else if (ret == 0) { continue; } + } +#endif + + err = 0; /* Reset error */ + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + + if (ret != SSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); - /*printf("SSL_connect failed");*/ + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); + /*err_sys("SSL_connect failed");*/ goto done2; } @@ -759,6 +787,7 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) int len = (int) XSTRLEN(msg); char input[1024]; int idx; + int ret, err = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -829,13 +858,27 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); - /* AssertIntEQ(SSL_SUCCESS, wolfSSL_accept(ssl)); */ - if (wolfSSL_accept(ssl) != SSL_SUCCESS) { - int err = wolfSSL_get_error(ssl, 0); + do { +#ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) { break; } else if (ret == 0) { continue; } + } +#endif + + err = 0; /* Reset error */ + ret = wolfSSL_accept(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + + if (ret != SSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); - - } else { + /*err_sys("SSL_accept failed");*/ + } + else { if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { input[idx] = 0; printf("Client message: %s\n", input); @@ -898,6 +941,7 @@ static void run_wolfssl_client(void* args) int len = (int) XSTRLEN(msg); char input[1024]; int idx; + int ret, err = 0; #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); @@ -932,12 +976,27 @@ static void run_wolfssl_client(void* args) if (callbacks->ssl_ready) callbacks->ssl_ready(ssl); - if (wolfSSL_connect(ssl) != SSL_SUCCESS) { - int err = wolfSSL_get_error(ssl, 0); + do { +#ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) { break; } else if (ret == 0) { continue; } + } +#endif + + err = 0; /* Reset error */ + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != SSL_SUCCESS && err == WC_PENDING_E); + + if (ret != SSL_SUCCESS) { char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); - - } else { + /*err_sys("SSL_connect failed");*/ + } + else { AssertIntEQ(len, wolfSSL_write(ssl, msg, len)); if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { diff --git a/tests/unit.c b/tests/unit.c index 4b64d1082..dd9846529 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -54,11 +54,6 @@ int unit_test(int argc, char** argv) #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) wolfSSL_Debugging_ON(); #endif -#ifdef HAVE_CAVIUM - ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) @@ -85,10 +80,6 @@ int unit_test(int argc, char** argv) SrpTest(); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 6d95d3199..f27e575a6 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -84,12 +84,6 @@ int testsuite_test(int argc, char** argv) int num = 6; #endif -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) - err_sys("Cavium OpenNitroxDevice failed"); -#endif /* HAVE_CAVIUM */ - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { err_sys("Whitewood netRandom global config failed"); @@ -204,10 +198,6 @@ int testsuite_test(int argc, char** argv) fdCloseSession(Task_self()); #endif -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index a510d61d7..e535d0b72 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -77,15 +77,16 @@ #endif #include -#ifdef HAVE_CAVIUM - #include "cavium_sysdep.h" - #include "cavium_common.h" - #include "cavium_ioctl.h" -#endif #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #endif #include +#include + +#ifdef WOLFSSL_ASYNC_CRYPT + #include + static int devId = INVALID_DEVID; +#endif #ifdef HAVE_WNR const char* wnrConfigFile = "wnr-example.conf"; @@ -161,6 +162,9 @@ void bench_ripemd(void); void bench_cmac(void); void bench_rsa(void); +#ifdef WOLFSSL_ASYNC_CRYPT + void bench_rsa_async(void); +#endif void bench_rsaKeyGen(void); void bench_dh(void); #ifdef HAVE_ECC @@ -189,29 +193,6 @@ void bench_rng(void); double current_time(int); -#ifdef HAVE_CAVIUM - -static int OpenNitroxDevice(int dma_mode,int dev_id) -{ - Csp1CoreAssignment core_assign; - Uint32 device; - - if (CspInitialize(CAVIUM_DIRECT,CAVIUM_DEV_ID)) - return -1; - if (Csp1GetDevType(&device)) - return -1; - if (device != NPX_DEVICE) { - if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, - (Uint32 *)&core_assign)!= 0) - return -1; - } - CspShutdown(CAVIUM_DEV_ID); - - return CspInitialize(dma_mode, dev_id); -} - -#endif - #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) WOLFSSL_API int wolfSSL_Debugging_ON(); #endif @@ -274,29 +255,28 @@ int benchmark_test(void *args) wolfCrypt_Init(); - #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) - wolfSSL_Debugging_ON(); - #endif +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); +#endif (void)plain; (void)cipher; (void)key; (void)iv; - #ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) { - printf("Cavium OpenNitroxDevice failed\n"); +#ifdef WOLFSSL_ASYNC_CRYPT + if (wolfAsync_DevOpen(&devId) != 0) { + printf("Async device open failed\n"); exit(-1); } - #endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ - #ifdef HAVE_WNR +#ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { printf("Whitewood netRandom config init failed\n"); exit(-1); } - #endif /* HAVE_WNR */ +#endif /* HAVE_WNR */ #if defined(HAVE_LOCAL_RNG) { @@ -384,16 +364,18 @@ int benchmark_test(void *args) #ifndef NO_RSA bench_rsa(); + #ifdef WOLFSSL_ASYNC_CRYPT + bench_rsa_async(); + #endif + #ifdef WOLFSSL_KEY_GEN + bench_rsaKeyGen(); + #endif #endif #ifndef NO_DH bench_dh(); #endif -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) - bench_rsaKeyGen(); -#endif - #ifdef HAVE_NTRU bench_ntru(); bench_ntruKeyGen(); @@ -426,6 +408,10 @@ int benchmark_test(void *args) wc_FreeRng(&rng); #endif +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) { printf("Failed to free netRandom context\n"); @@ -452,9 +438,15 @@ static const char blockType[] = "kB"; /* used in printf output */ #else enum BenchmarkBounds { numBlocks = 50, /* how many megs to test (en/de)cryption */ +#ifdef WOLFSSL_ASYNC_CRYPT + ntimes = 1000, + genTimes = 1000, + agreeTimes = 1000 +#else ntimes = 100, genTimes = 100, agreeTimes = 100 +#endif }; static const char blockType[] = "megs"; /* used in printf output */ #endif @@ -526,9 +518,9 @@ void bench_aes(int show) int i; int ret; -#ifdef HAVE_CAVIUM - if (wc_AesInitCavium(&enc, CAVIUM_DEV_ID) != 0) { - printf("aes init cavium failed\n"); +#ifdef WOLFSSL_ASYNC_CRYPT + if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { + printf("wc_AesAsyncInit failed, ret = %d\n", ret); return; } #endif @@ -559,10 +551,10 @@ void bench_aes(int show) SHOW_INTEL_CYCLES printf("\n"); } -#ifdef HAVE_CAVIUM - wc_AesFreeCavium(&enc); - if (wc_AesInitCavium(&enc, CAVIUM_DEV_ID) != 0) { - printf("aes init cavium failed\n"); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_AesAsyncFree(&enc); + if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { + printf("wc_AesAsyncInit failed, ret = %d\n", ret); return; } #endif @@ -593,8 +585,8 @@ void bench_aes(int show) SHOW_INTEL_CYCLES printf("\n"); } -#ifdef HAVE_CAVIUM - wc_AesFreeCavium(&enc); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_AesAsyncFree(&enc); #endif } #endif /* HAVE_AES_CBC */ @@ -805,9 +797,9 @@ void bench_des(void) double start, total, persec; int i, ret; -#ifdef HAVE_CAVIUM - if (wc_Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0) - printf("des3 init cavium failed\n"); +#ifdef WOLFSSL_ASYNC_CRYPT + if (wc_Des3AsyncInit(&enc, devId) != 0) + printf("des3 async init failed\n"); #endif ret = wc_Des3_SetKey(&enc, key, iv, DES_ENCRYPTION); if (ret != 0) { @@ -833,8 +825,8 @@ void bench_des(void) blockType, total, persec); SHOW_INTEL_CYCLES printf("\n"); -#ifdef HAVE_CAVIUM - wc_Des3_FreeCavium(&enc); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_Des3AsyncFree(&enc); #endif } #endif @@ -882,9 +874,9 @@ void bench_arc4(void) double start, total, persec; int i; -#ifdef HAVE_CAVIUM - if (wc_Arc4InitCavium(&enc, CAVIUM_DEV_ID) != 0) - printf("arc4 init cavium failed\n"); +#ifdef WOLFSSL_ASYNC_CRYPT + if (wc_Arc4AsyncInit(&enc, devId) != 0) + printf("arc4 async init failed\n"); #endif wc_Arc4SetKey(&enc, key, 16); @@ -906,8 +898,8 @@ void bench_arc4(void) blockType, total, persec); SHOW_INTEL_CYCLES printf("\n"); -#ifdef HAVE_CAVIUM - wc_Arc4FreeCavium(&enc); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_Arc4AsyncFree(&enc); #endif } #endif @@ -1395,7 +1387,7 @@ void bench_rsa(void) word32 idx = 0; const byte* tmp; - byte message[] = "Everyone gets Friday off."; + const byte message[] = "Everyone gets Friday off."; byte enc[256]; /* for up to 2048 bit */ const int len = (int)strlen((char*)message); double start, total, each, milliEach; @@ -1414,32 +1406,33 @@ void bench_rsa(void) #error "need a cert buffer size" #endif /* USE_CERT_BUFFERS */ - -#ifdef HAVE_CAVIUM - if (wc_RsaInitCavium(&rsaKey, CAVIUM_DEV_ID) != 0) - printf("RSA init cavium failed\n"); -#endif - ret = wc_InitRsaKey(&rsaKey, 0); - if (ret < 0) { - printf("InitRsaKey failed\n"); + if ((ret = wc_InitRsaKey(&rsaKey, 0)) < 0) { + printf("InitRsaKey failed! %d\n", ret); return; } + + /* decode the private key */ ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); start = current_time(1); - for (i = 0; i < ntimes; i++) - ret = wc_RsaPublicEncrypt(message,len,enc,sizeof(enc), &rsaKey, &rng); + for (i = 0; i < ntimes; i++) { + ret = wc_RsaPublicEncrypt(message, len, enc, sizeof(enc), + &rsaKey, &rng); + if (ret < 0) { + break; + } + } /* for ntimes */ total = current_time(0) - start; each = total / ntimes; /* per second */ milliEach = each * 1000; /* milliseconds */ - printf("RSA %d encryption took %6.3f milliseconds, avg over %d" + printf("RSA %d public %6.3f milliseconds, avg over %d" " iterations\n", rsaKeySz, milliEach, ntimes); if (ret < 0) { - printf("Rsa Public Encrypt failed\n"); + printf("Rsa Public Encrypt failed! %d\n", ret); return; } @@ -1447,25 +1440,232 @@ void bench_rsa(void) wc_RsaSetRNG(&rsaKey, &rng); #endif start = current_time(1); + + /* capture resulting encrypt length */ + idx = ret; for (i = 0; i < ntimes; i++) { - byte out[256]; /* for up to 2048 bit */ - wc_RsaPrivateDecrypt(enc, (word32)ret, out, sizeof(out), &rsaKey); - } + byte out[256]; /* for up to 2048 bit */ + + ret = wc_RsaPrivateDecrypt(enc, idx, out, sizeof(out), &rsaKey); + if (ret < 0 && ret != WC_PENDING_E) { + break; + } + } /* for ntimes */ total = current_time(0) - start; each = total / ntimes; /* per second */ milliEach = each * 1000; /* milliseconds */ - printf("RSA %d decryption took %6.3f milliseconds, avg over %d" + printf("RSA %d private %6.3f milliseconds, avg over %d" " iterations\n", rsaKeySz, milliEach, ntimes); wc_FreeRsaKey(&rsaKey); -#ifdef HAVE_CAVIUM - wc_RsaFreeCavium(&rsaKey); -#endif } -#endif + + +#ifdef WOLFSSL_ASYNC_CRYPT +void bench_rsa_async(void) +{ + int i; + int ret; + size_t bytes; + word32 idx = 0; + const byte* tmp; + + const byte message[] = "Everyone gets Friday off."; + byte enc[256]; /* for up to 2048 bit */ + const int len = (int)strlen((char*)message); + double start, total, each, milliEach; + + RsaKey rsaKey[WOLF_ASYNC_MAX_PENDING]; + int rsaKeySz = 2048; /* used in printf */ + + WOLF_EVENT events[WOLF_ASYNC_MAX_PENDING]; + WOLF_EVENT_QUEUE eventQueue; + int evtNum, asyncDone, asyncPend; + +#ifdef USE_CERT_BUFFERS_1024 + tmp = rsa_key_der_1024; + bytes = sizeof_rsa_key_der_1024; + rsaKeySz = 1024; +#elif defined(USE_CERT_BUFFERS_2048) + tmp = rsa_key_der_2048; + bytes = sizeof_rsa_key_der_2048; +#else + #error "need a cert buffer size" +#endif /* USE_CERT_BUFFERS */ + + /* init event queue */ + ret = wolfEventQueue_Init(&eventQueue); + if (ret != 0) { + return; + } + + /* clear for done cleanup */ + XMEMSET(&events, 0, sizeof(events)); + XMEMSET(&rsaKey, 0, sizeof(rsaKey)); + + /* init events and keys */ + for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + /* setup an async context for each key */ + if ((ret = wc_InitRsaKey_ex(&rsaKey[i], 0, devId)) < 0) { + goto done; + } + #ifdef WC_RSA_BLINDING + wc_RsaSetRNG(&rsaKey[i], &rng); + #endif + if ((ret = wolfAsync_EventInit(&events[i], + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &rsaKey[i].asyncDev)) != 0) { + goto done; + } + events[i].pending = 0; /* Reset pending flag */ + + /* decode the private key */ + idx = 0; + if ((ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey[i], + (word32)bytes)) != 0) { + printf("wc_RsaPrivateKeyDecode failed! %d\n", ret); + goto done; + } + } + + /* begin public async RSA */ + start = current_time(1); + + asyncPend = 0; + for (i = 0; i < ntimes; ) { + + /* while free pending slots in queue, submit RSA operations */ + for (evtNum = 0; evtNum < WOLF_ASYNC_MAX_PENDING; evtNum++) { + if (events[evtNum].done || (events[evtNum].pending == 0 && + (i + asyncPend) < ntimes)) + { + /* check for event error */ + if (events[evtNum].ret != WC_PENDING_E && events[evtNum].ret < 0) { + printf("wc_RsaPublicEncrypt: Async event error: %d\n", events[evtNum].ret); + goto done; + } + + ret = wc_RsaPublicEncrypt(message, len, enc, sizeof(enc), + &rsaKey[evtNum], &rng); + if (ret == WC_PENDING_E) { + ret = wc_RsaAsyncHandle(&rsaKey[evtNum], &eventQueue, + &events[evtNum]); + if (ret != 0) goto done; + asyncPend++; + } + else if (ret >= 0) { + /* operation completed */ + i++; + asyncPend--; + events[evtNum].done = 0; + } + else { + printf("wc_RsaPublicEncrypt failed: %d\n", ret); + goto done; + } + } + } /* for evtNum */ + + /* poll until there are events done */ + if (asyncPend > 0) { + do { + ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, + WOLF_POLL_FLAG_CHECK_HW, &asyncDone); + if (ret != 0) goto done; + } while (asyncDone == 0); + } + } /* for ntimes */ + + total = current_time(0) - start; + each = total / ntimes; /* per second */ + milliEach = each * 1000; /* milliseconds */ + + printf("RSA %d public async %6.3f milliseconds, avg over %d" + " iterations\n", rsaKeySz, milliEach, ntimes); + + if (ret < 0) { + goto done; + } + + + /* begin private async RSA */ + start = current_time(1); + + /* capture resulting encrypt length */ + idx = sizeof(enc); /* fixed at 2048 bit */ + + asyncPend = 0; + for (i = 0; i < ntimes; ) { + byte out[256]; /* for up to 2048 bit */ + + /* while free pending slots in queue, submit RSA operations */ + for (evtNum = 0; evtNum < WOLF_ASYNC_MAX_PENDING; evtNum++) { + if (events[evtNum].done || (events[evtNum].pending == 0 && + (i + asyncPend) < ntimes)) + { + /* check for event error */ + if (events[evtNum].ret != WC_PENDING_E && events[evtNum].ret < 0) { + printf("wc_RsaPrivateDecrypt: Async event error: %d\n", events[evtNum].ret); + goto done; + } + + ret = wc_RsaPrivateDecrypt(enc, idx, out, sizeof(out), + &rsaKey[evtNum]); + if (ret == WC_PENDING_E) { + ret = wc_RsaAsyncHandle(&rsaKey[evtNum], &eventQueue, + &events[evtNum]); + if (ret != 0) goto done; + asyncPend++; + } + else if (ret >= 0) { + /* operation completed */ + i++; + asyncPend--; + events[evtNum].done = 0; + } + else { + printf("wc_RsaPrivateDecrypt failed: %d\n", ret); + goto done; + } + } + } /* for evtNum */ + + /* poll until there are events done */ + if (asyncPend > 0) { + do { + ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, + WOLF_POLL_FLAG_CHECK_HW, &asyncDone); + if (ret != 0) goto done; + } while (asyncDone == 0); + } + } /* for ntimes */ + + total = current_time(0) - start; + each = total / ntimes; /* per second */ + milliEach = each * 1000; /* milliseconds */ + + printf("RSA %d private async %6.3f milliseconds, avg over %d" + " iterations\n", rsaKeySz, milliEach, ntimes); + +done: + + if (ret < 0) { + printf("bench_rsa_async failed: %d\n", ret); + } + + /* cleanup */ + for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + wc_FreeRsaKey(&rsaKey[i]); + } + + /* free event queue */ + wolfEventQueue_Free(&eventQueue); +} +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#endif /* !NO_RSA */ #ifndef NO_DH diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index c12cd328b..e13ae49a2 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -164,16 +164,15 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AESCCM */ -#ifdef HAVE_CAVIUM -int wc_AesInitCavium(Aes* aes, int i) +#ifdef WOLFSSL_ASYNC_CRYPT +int wc_AesAsyncInit(Aes* aes, int i) { - return AesInitCavium(aes, i); + return AesAsyncInit(aes, i); } - -void wc_AesFreeCavium(Aes* aes) +void wc_AesAsyncFree(Aes* aes) { - AesFreeCavium(aes); + AesAsyncFree(aes); } #endif #else /* HAVE_FIPS */ @@ -332,22 +331,8 @@ void wc_AesFreeCavium(Aes* aes) #define DEBUG_WOLFSSL #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" #elif defined(HAVE_CAVIUM) - #include - #include "cavium_common.h" - /* still leave SW crypto available */ #define NEED_AES_TABLES - - static int wc_AesCaviumSetKey(Aes* aes, const byte* key, word32 length, - const byte* iv); - #ifdef HAVE_AES_CBC - static int wc_AesCaviumCbcEncrypt(Aes* aes, byte* out, const byte* in, - word32 length); - #ifdef HAVE_AES_DECRYPT - static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, - word32 length); - #endif /* HAVE_AES_DECRYPT */ - #endif /* HAVE_AES_CBC */ #elif defined(WOLFSSL_NRF51_AES) /* Use built-in AES hardware - AES 128 ECB Encrypt Only */ #include "wolfssl/wolfcrypt/port/nrf51.h" @@ -1870,9 +1855,10 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) } #endif - #ifdef HAVE_CAVIUM - if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) - return wc_AesCaviumSetKey(aes, userKey, keylen, iv); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { + return NitroxAesSetKey(aes, userKey, keylen, iv); + } #endif #ifdef WOLFSSL_AESNI @@ -2490,9 +2476,9 @@ int wc_InitAes_h(Aes* aes, void* h) { word32 blocks = sz / AES_BLOCK_SIZE; - #ifdef HAVE_CAVIUM - if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) - return wc_AesCaviumCbcEncrypt(aes, out, in, sz); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) + return NitroxAesCbcEncrypt(aes, out, in, sz); #endif #ifdef WOLFSSL_AESNI @@ -2554,9 +2540,10 @@ int wc_InitAes_h(Aes* aes, void* h) { word32 blocks = sz / AES_BLOCK_SIZE; - #ifdef HAVE_CAVIUM - if (aes->magic == WOLFSSL_AES_CAVIUM_MAGIC) - return wc_AesCaviumCbcDecrypt(aes, out, in, sz); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { + return NitroxAesCbcDecrypt(aes, out, in, sz); + } #endif #ifdef WOLFSSL_AESNI @@ -3909,8 +3896,6 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte *ctr ; byte scratch[AES_BLOCK_SIZE]; - WOLFSSL_ENTER("AesGcmEncrypt"); - #ifdef WOLFSSL_AESNI if (haveAESNI) { AES_GCM_encrypt((void*)in, out, (void*)authIn, (void*)iv, authTag, @@ -3982,8 +3967,6 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte *ctr ; byte scratch[AES_BLOCK_SIZE]; - WOLFSSL_ENTER("AesGcmDecrypt"); - #ifdef WOLFSSL_AESNI if (haveAESNI) { if (AES_GCM_decrypt(in, out, authIn, iv, authTag, @@ -4323,131 +4306,28 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif /* HAVE_AESCCM */ -#ifdef HAVE_CAVIUM - -#include -#include "cavium_common.h" - +#ifdef WOLFSSL_ASYNC_CRYPT + /* Initialize Aes for use with Nitrox device */ -int wc_AesInitCavium(Aes* aes, int devId) +int wc_AesAsyncInit(Aes* aes, int devId) { if (aes == NULL) - return -1; + return BAD_FUNC_ARG; - if (CspAllocContext(CONTEXT_SSL, &aes->contextHandle, devId) != 0) - return -1; - - aes->devId = devId; - aes->magic = WOLFSSL_AES_CAVIUM_MAGIC; - - return 0; + return wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, devId); } /* Free Aes from use with Nitrox device */ -void wc_AesFreeCavium(Aes* aes) +void wc_AesAsyncFree(Aes* aes) { if (aes == NULL) return; - if (aes->magic != WOLFSSL_AES_CAVIUM_MAGIC) - return; - - CspFreeContext(CONTEXT_SSL, aes->contextHandle, aes->devId); - aes->magic = 0; + wolfAsync_DevCtxFree(&aes->asyncDev); } - -static int wc_AesCaviumSetKey(Aes* aes, const byte* key, word32 length, - const byte* iv) -{ - if (aes == NULL) - return -1; - - XMEMCPY(aes->key, key, length); /* key still holds key, iv still in reg */ - if (length == 16) - aes->type = AES_128; - else if (length == 24) - aes->type = AES_192; - else if (length == 32) - aes->type = AES_256; - - return wc_AesSetIV(aes, iv); -} - -#ifdef HAVE_AES_CBC -static int wc_AesCaviumCbcEncrypt(Aes* aes, byte* out, const byte* in, - word32 length) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspEncryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Encrypt"); - return -1; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - if (CspEncryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Encrypt"); - return -1; - } - XMEMCPY(aes->reg, out + offset+length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - } - return 0; -} - -#ifdef HAVE_AES_DECRYPT -static int wc_AesCaviumCbcDecrypt(Aes* aes, byte* out, const byte* in, - word32 length) -{ - word32 requestId; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - if (CspDecryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Decrypt"); - return -1; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - if (CspDecryptAes(CAVIUM_BLOCKING, aes->contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &requestId, - aes->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Aes Decrypt"); - return -1; - } - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - return 0; -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ - -#endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* WOLFSSL_TI_CRYPT */ diff --git a/wolfcrypt/src/arc4.c b/wolfcrypt/src/arc4.c index a30d11117..6922089de 100644 --- a/wolfcrypt/src/arc4.c +++ b/wolfcrypt/src/arc4.c @@ -28,23 +28,19 @@ #ifndef NO_RC4 +#include #include -#ifdef HAVE_CAVIUM - static void wc_Arc4CaviumSetKey(Arc4* arc4, const byte* key, word32 length); - static void wc_Arc4CaviumProcess(Arc4* arc4, byte* out, const byte* in, - word32 length); -#endif - void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) { word32 i; word32 keyIndex = 0, stateIndex = 0; -#ifdef HAVE_CAVIUM - if (arc4->magic == WOLFSSL_ARC4_CAVIUM_MAGIC) - return wc_Arc4CaviumSetKey(arc4, key, length); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { + return NitroxArc4SetKey(arc4, key, length); + } #endif arc4->x = 1; @@ -85,9 +81,10 @@ void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) word32 x; word32 y; -#ifdef HAVE_CAVIUM - if (arc4->magic == WOLFSSL_ARC4_CAVIUM_MAGIC) - return wc_Arc4CaviumProcess(arc4, out, in, length); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { + return NitroxArc4Process(arc4, out, in, length); + } #endif x = arc4->x; @@ -101,79 +98,28 @@ void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) } -#ifdef HAVE_CAVIUM - -#include -#include "cavium_common.h" +#ifdef WOLFSSL_ASYNC_CRYPT /* Initialize Arc4 for use with Nitrox device */ -int wc_Arc4InitCavium(Arc4* arc4, int devId) +int wc_Arc4AsyncInit(Arc4* arc4, int devId) { if (arc4 == NULL) - return -1; + return BAD_FUNC_ARG; - if (CspAllocContext(CONTEXT_SSL, &arc4->contextHandle, devId) != 0) - return -1; - - arc4->devId = devId; - arc4->magic = WOLFSSL_ARC4_CAVIUM_MAGIC; - - return 0; + return wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, devId); } /* Free Arc4 from use with Nitrox device */ -void wc_Arc4FreeCavium(Arc4* arc4) +void wc_Arc4AsyncFree(Arc4* arc4) { if (arc4 == NULL) return; - if (arc4->magic != WOLFSSL_ARC4_CAVIUM_MAGIC) - return; - - CspFreeContext(CONTEXT_SSL, arc4->contextHandle, arc4->devId); - arc4->magic = 0; + wolfAsync_DevCtxFree(&arc4->asyncDev); } - -static void wc_Arc4CaviumSetKey(Arc4* arc4, const byte* key, word32 length) -{ - word32 requestId; - - if (CspInitializeRc4(CAVIUM_BLOCKING, arc4->contextHandle, length, - (byte*)key, &requestId, arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Init"); - } -} - - -static void wc_Arc4CaviumProcess(Arc4* arc4, byte* out, const byte* in, - word32 length) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspEncryptRc4(CAVIUM_BLOCKING, arc4->contextHandle,CAVIUM_UPDATE, - slen, (byte*)in + offset, out + offset, &requestId, - arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Encrypt"); - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (length) { - word16 slen = (word16)length; - if (CspEncryptRc4(CAVIUM_BLOCKING, arc4->contextHandle,CAVIUM_UPDATE, - slen, (byte*)in + offset, out + offset, &requestId, - arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Encrypt"); - } - } -} - -#endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* NO_RC4 */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index cc2a856dc..59d89b882 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -646,7 +646,7 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version) } #endif /* !NO_ASN_TIME */ -WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, +int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) { word32 i = *inOutIdx; @@ -676,6 +676,62 @@ WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, return 0; } +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) +static int GetIntRsa(RsaKey* key, mp_int* mpi, const byte* input, + word32* inOutIdx, word32 maxIdx) +{ + word32 i = *inOutIdx; + byte b = input[i++]; + int length; + + (void)key; + + if (b != ASN_INTEGER) + return ASN_PARSE_E; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return ASN_PARSE_E; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + XMEMSET(mpi, 0, sizeof(mp_int)); + mpi->used = length; + #ifdef USE_FAST_MATH + if (length > (FP_SIZE * (int)sizeof(fp_digit))) { + return MEMORY_E; + } + mpi->dpraw = (byte*)mpi->dp; + #else + mpi->dpraw = (byte*)XMALLOC(length, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + if (mpi->dpraw == NULL) { + return MEMORY_E; + } + + XMEMCPY(mpi->dpraw, input + i, length); + } + else +#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM */ + { + if (mp_init(mpi) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } + } + + *inOutIdx = i + length; + return 0; +} +#endif /* !NO_RSA && !HAVE_USER_RSA */ + /* hashType */ static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2}; @@ -1297,78 +1353,11 @@ WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, #ifndef NO_RSA - -#ifdef HAVE_CAVIUM - -static int GetCaviumInt(byte** buff, word16* buffSz, const byte* input, - word32* inOutIdx, word32 maxIdx, void* heap) -{ - word32 i = *inOutIdx; - byte b = input[i++]; - int length; - - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, maxIdx) < 0) - return ASN_PARSE_E; - - if ( (b = input[i++]) == 0x00) - length--; - else - i--; - - *buffSz = (word16)length; - *buff = XMALLOC(*buffSz, heap, DYNAMIC_TYPE_CAVIUM_RSA); - if (*buff == NULL) - return MEMORY_E; - - XMEMCPY(*buff, input + i, *buffSz); - - *inOutIdx = i + length; - return 0; -} - -static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx, - RsaKey* key, word32 inSz) -{ - int version, length; - void* h = key->heap; - - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - if (GetMyVersion(input, inOutIdx, &version) < 0) - return ASN_PARSE_E; - - key->type = RSA_PRIVATE; - - if (GetCaviumInt(&key->c_n, &key->c_nSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_e, &key->c_eSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_d, &key->c_dSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_p, &key->c_pSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_q, &key->c_qSz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_dP, &key->c_dP_Sz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_dQ, &key->c_dQ_Sz, input, inOutIdx, inSz, h) < 0 || - GetCaviumInt(&key->c_u, &key->c_uSz, input, inOutIdx, inSz, h) < 0 ) - return ASN_RSA_KEY_E; - - return 0; -} - - -#endif /* HAVE_CAVIUM */ - #ifndef HAVE_USER_RSA int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { - int version, length; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPrivateKeyDecode(input, inOutIdx, key, inSz); -#endif + int version, length; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -1378,14 +1367,14 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, key->type = RSA_PRIVATE; - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0 || - GetInt(&key->d, input, inOutIdx, inSz) < 0 || - GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->q, input, inOutIdx, inSz) < 0 || - GetInt(&key->dP, input, inOutIdx, inSz) < 0 || - GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || - GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + if (GetIntRsa(key, &key->n, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->e, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->d, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->p, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->q, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->dP, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->dQ, input, inOutIdx, inSz) < 0 || + GetIntRsa(key, &key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; return 0; } @@ -3674,11 +3663,22 @@ static int ConfirmSignature(const byte* buf, word32 bufSz, else { XMEMCPY(plain, sig, sigSz); - if ((verifySz = wc_RsaSSL_VerifyInline(plain, sigSz, &out, - pubKey)) < 0) { + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, pubKey); + #endif + if (ret >= 0) { + ret = wc_RsaSSL_VerifyInline(plain, sigSz, &out, + pubKey); + } + } while (ret == WC_PENDING_E); + + if (ret < 0) { WOLFSSL_MSG("Rsa SSL verify error"); } else { + verifySz = ret; /* make sure we're right justified */ encodedSigSz = wc_EncodeSignature(encodedSig, digest, digestSz, typeH); @@ -7359,7 +7359,15 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, if (rsaKey) { /* signature */ encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH); - ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); + ret = 0; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, rsaKey); +#endif + if (ret >= 0) { + ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); + } + } while (ret == WC_PENDING_E); } #endif diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index bac3e90a7..2f9bd34d0 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -31,13 +31,6 @@ #include #ifdef HAVE_FIPS -#ifdef HAVE_CAVIUM - static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv); - static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, - word32 length); - static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, - word32 length); -#endif int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { @@ -98,23 +91,24 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) } -#ifdef HAVE_CAVIUM +#ifdef WOLFSSL_ASYNC_CRYPT /* Initialize Des3 for use with Nitrox device */ -int wc_Des3_InitCavium(Des3* des3, int devId) +int wc_Des3AsyncInit(Des3* des3, int devId) { - return Des3_InitCavium(des3, devId); + return Des3AsyncInit(des3, devId); } /* Free Des3 from use with Nitrox device */ -void wc_Des3_FreeCavium(Des3* des3) +void wc_Des3AsyncFree(Des3* des3) { - Des3_FreeCavium(des3); + Des3AsyncFree(des3); } -#endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ + #else /* build without fips */ #if defined(WOLFSSL_TI_CRYPT) @@ -132,17 +126,6 @@ void wc_Des3_FreeCavium(Des3* des3) #endif -#ifdef HAVE_CAVIUM - static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv); - static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, - word32 length); - static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, - word32 length); -#endif - - - - #ifdef STM32F2_CRYPTO /* * STM32F2 hardware DES/3DES support through the STM32F2 standard @@ -150,7 +133,7 @@ void wc_Des3_FreeCavium(Des3* des3) * Peripheral Library document (See note in README). */ #include "stm32f2xx.h" - #include "stm32f2xx_cryp.h" + #include "stm32f2xx_cryp.h" int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { @@ -1292,9 +1275,10 @@ int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { int ret; -#ifdef HAVE_CAVIUM - if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) - return wc_Des3_CaviumSetKey(des, key, iv); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + return NitroxDes3SetKey(des, key, iv); + } #endif ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); @@ -1433,9 +1417,10 @@ int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) { word32 blocks; -#ifdef HAVE_CAVIUM - if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) - return wc_Des3_CaviumCbcEncrypt(des, out, in, sz); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + return NitroxDes3CbcEncrypt(des, out, in, sz); + } #endif blocks = sz / DES_BLOCK_SIZE; @@ -1455,9 +1440,10 @@ int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) { word32 blocks; -#ifdef HAVE_CAVIUM - if (des->magic == WOLFSSL_3DES_CAVIUM_MAGIC) - return wc_Des3_CaviumCbcDecrypt(des, out, in, sz); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + return NitroxDes3CbcDecrypt(des, out, in, sz); + } #endif blocks = sz / DES_BLOCK_SIZE; @@ -1513,122 +1499,29 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) } -#ifdef HAVE_CAVIUM - -#include "cavium_common.h" +#ifdef WOLFSSL_ASYNC_CRYPT /* Initialize Des3 for use with Nitrox device */ -int wc_Des3_InitCavium(Des3* des3, int devId) +int wc_Des3AsyncInit(Des3* des3, int devId) { if (des3 == NULL) - return -1; + return BAD_FUNC_ARG; - if (CspAllocContext(CONTEXT_SSL, &des3->contextHandle, devId) != 0) - return -1; - - des3->devId = devId; - des3->magic = WOLFSSL_3DES_CAVIUM_MAGIC; - - return 0; + return wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, devId); } /* Free Des3 from use with Nitrox device */ -void wc_Des3_FreeCavium(Des3* des3) +void wc_Des3AsyncFree(Des3* des3) { if (des3 == NULL) return; - if (des3->magic != WOLFSSL_3DES_CAVIUM_MAGIC) - return; - - CspFreeContext(CONTEXT_SSL, des3->contextHandle, des3->devId); - des3->magic = 0; + wolfAsync_DevCtxFree(&des3->asyncDev); } +#endif /* WOLFSSL_ASYNC_CRYPT */ -static int wc_Des3_CaviumSetKey(Des3* des3, const byte* key, const byte* iv) -{ - if (des3 == NULL) - return -1; - - /* key[0] holds key, iv in reg */ - XMEMCPY(des3->key[0], key, DES_BLOCK_SIZE*3); - - return wc_Des3_SetIV(des3, iv); -} - - -static int wc_Des3_CaviumCbcEncrypt(Des3* des3, byte* out, const byte* in, - word32 length) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspEncrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &requestId, des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3DES Cbc Encrypt"); - return -1; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(des3->reg, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - - if (CspEncrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &requestId, des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3DES Cbc Encrypt"); - return -1; - } - XMEMCPY(des3->reg, out+offset+length - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - return 0; -} - -static int wc_Des3_CaviumCbcDecrypt(Des3* des3, byte* out, const byte* in, - word32 length) -{ - word32 requestId; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - if (CspDecrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in+offset, out+offset, - (byte*)des3->reg, (byte*)des3->key[0], &requestId, - des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3Des Decrypt"); - return -1; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE,DES_BLOCK_SIZE); - if (CspDecrypt3Des(CAVIUM_BLOCKING, des3->contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in+offset, out+offset, - (byte*)des3->reg, (byte*)des3->key[0], &requestId, - des3->devId) != 0) { - WOLFSSL_MSG("Bad Cavium 3Des Decrypt"); - return -1; - } - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - return 0; -} - -#endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_TI_CRYPT */ #endif /* HAVE_FIPS */ #endif /* NO_DES3 */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 3f7e88c2a..7fc45faa3 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2223,8 +2223,9 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, int err; if (private_key == NULL || public_key == NULL || out == NULL || - outlen == NULL) + outlen == NULL) { return BAD_FUNC_ARG; + } /* type valid? */ if (private_key->type != ECC_PRIVATEKEY) { @@ -2242,6 +2243,24 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return ECC_BAD_ARG_E; } +#ifdef WOLFSSL_ASYNC_CRYPT + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #else + AsyncCryptTestDev* testDev = &private_key->asyncDev.dev; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_SHARED_SEC; + testDev->eccSharedSec.private_key = private_key; + testDev->eccSharedSec.public_key = public_key; + testDev->eccSharedSec.out = out; + testDev->eccSharedSec.outLen = outlen; + return WC_PENDING_E; + } + #endif + } +#endif + /* make new point */ result = wc_ecc_new_point_h(private_key->heap); if (result == NULL) { @@ -2302,8 +2321,10 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, mp_int a; int err; - if (private_key == NULL || point == NULL || out == NULL || outlen == NULL) + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { return BAD_FUNC_ARG; + } /* type valid? */ if (private_key->type != ECC_PRIVATEKEY) { @@ -2391,6 +2412,24 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) return err; } +#ifdef WOLFSSL_ASYNC_CRYPT + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #else + AsyncCryptTestDev* testDev = &key->asyncDev.dev; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_MAKE; + testDev->eccMake.rng = rng; + testDev->eccMake.key = key; + testDev->eccMake.size = keysize; + testDev->eccMake.curve_id = curve_id; + return WC_PENDING_E; + } + #endif + } +#endif + #ifdef WOLFSSL_SMALL_STACK buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (buf == NULL) @@ -2567,13 +2606,18 @@ int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key) return wc_ecc_make_key_ex(rng, keysize, key, ECC_CURVE_DEF); } -/* Setup dynamic pointers is using normal math for proper freeing */ -int wc_ecc_init(ecc_key* key) + +/* Setup dynamic pointers if using normal math for proper freeing */ +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) { + int ret = 0; + if (key == NULL) { return BAD_FUNC_ARG; } + (void)devId; + #ifdef ECC_DUMP_OID wc_ecc_dump_oids(); #endif @@ -2590,8 +2634,9 @@ int wc_ecc_init(ecc_key* key) #endif #ifdef ALT_ECC_SIZE - if (mp_init(&key->k) != MP_OKAY) + if (mp_init(&key->k) != MP_OKAY) { return MEMORY_E; + } key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; @@ -2604,26 +2649,26 @@ int wc_ecc_init(ecc_key* key) #ifdef WOLFSSL_HEAP_TEST key->heap = (void*)WOLFSSL_HEAP_TEST; #else - key->heap = NULL; + key->heap = heap; #endif - return MP_OKAY; -} - - -int wc_ecc_init_h(ecc_key* key, void* heap) -{ - int ret; - - if ((ret = wc_ecc_init(key)) != MP_OKAY) { - return ret; +#ifdef WOLFSSL_ASYNC_CRYPT + if (devId != INVALID_DEVID) { + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, + devId); } +#endif - key->heap = heap; - - return MP_OKAY; + return ret; } +int wc_ecc_init(ecc_key* key) +{ + return wc_ecc_init_ex(key, NULL, INVALID_DEVID); +} + + #ifdef HAVE_ECC_SIGN #ifndef NO_ASN @@ -2644,16 +2689,40 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, int err; if (in == NULL || out == NULL || outlen == NULL || - key == NULL || rng == NULL) + key == NULL || rng == NULL) { return ECC_BAD_ARG_E; + } + + +#ifdef WOLFSSL_ASYNC_CRYPT + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #else + AsyncCryptTestDev* testDev = &key->asyncDev.dev; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_SIGN; + testDev->eccSign.in = in; + testDev->eccSign.inSz = inlen; + testDev->eccSign.out = out; + testDev->eccSign.outSz = outlen; + testDev->eccSign.rng = rng; + testDev->eccSign.key = key; + return WC_PENDING_E; + } + #endif + } +#endif if ((err = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL)) != MP_OKAY) { return err; } err = wc_ecc_sign_hash_ex(in, inlen, rng, key, &r, &s); - if (err == MP_OKAY) + if (err == MP_OKAY) { + /* encoded with DSA header */ err = StoreECC_DSA_Sig(out, outlen, &r, &s); + } #ifndef USE_FAST_MATH mp_clear(&r); @@ -2780,8 +2849,15 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, */ void wc_ecc_free(ecc_key* key) { - if (key == NULL) + if (key == NULL) { return; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + wolfAsync_DevCtxFree(&key->asyncDev); + } +#endif mp_clear(key->pubkey.x); mp_clear(key->pubkey.y); @@ -3048,12 +3124,33 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, mp_int s; int err; - if (sig == NULL || hash == NULL || stat == NULL || key == NULL) + if (sig == NULL || hash == NULL || stat == NULL || key == NULL) { return ECC_BAD_ARG_E; + } /* default to invalid signature */ *stat = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #else + AsyncCryptTestDev* testDev = &key->asyncDev.dev; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_VERIFY; + testDev->eccVerify.in = sig; + testDev->eccVerify.inSz = siglen; + testDev->eccVerify.out = hash; + testDev->eccVerify.outSz = hashlen; + testDev->eccVerify.stat = stat; + testDev->eccVerify.key = key; + return WC_PENDING_E; + } + #endif + } +#endif + /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. * If either of those don't allocate correctly, none of * the rest of this function will execute, and everything @@ -5680,7 +5777,7 @@ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) ctx->cliSt = ecCLI_SALT_SET; else { ctx->cliSt = ecCLI_BAD_STATE; - return BAD_ENC_STATE_E; + return BAD_STATE_E; } } else { @@ -5689,7 +5786,7 @@ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) ctx->srvSt = ecSRV_SALT_SET; else { ctx->srvSt = ecSRV_BAD_STATE; - return BAD_ENC_STATE_E; + return BAD_STATE_E; } } @@ -5871,13 +5968,13 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, keysLen *= 2; if (ctx->srvSt != ecSRV_RECV_REQ) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */ } else if (ctx->protocol == REQ_RESP_CLIENT) { if (ctx->cliSt != ecCLI_SALT_SET) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */ } @@ -6023,13 +6120,13 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, keysLen *= 2; if (ctx->cliSt != ecCLI_SENT_REQ) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */ } else if (ctx->protocol == REQ_RESP_SERVER) { if (ctx->srvSt != ecSRV_SALT_SET) - return BAD_ENC_STATE_E; + return BAD_STATE_E; ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */ } @@ -6526,4 +6623,50 @@ int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp) #endif /* WOLFSSL_CUSTOM_CURVES */ +#ifdef WOLFSSL_ASYNC_CRYPT + +int wc_ecc_async_handle(ecc_key* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret; + + if (key == NULL || queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + /* make sure this ECC context had "wc_EccAsyncInit" called on it */ + if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) { + return ASYNC_INIT_E; + } + + /* setup the event and push to queue */ + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); + if (ret == 0) { + ret = wolfEventQueue_Push(queue, event); + } + + /* check for error (helps with debugging) */ + if (ret != 0) { + WOLFSSL_MSG("wc_EccAsyncHandle failed"); + } + return ret; +} + +int wc_ecc_async_wait(int ret, ecc_key* key) +{ + if (ret == WC_PENDING_E) { + WOLF_EVENT event; + XMEMSET(&event, 0, sizeof(event)); + ret = wolfAsync_EventInit(&event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); + if (ret == 0) { + ret = wolfAsync_EventWait(&event); + if (ret == 0 && event.ret >= 0) { + ret = event.ret; + } + } + } + return ret; +} + +#endif /* WOLFSSL_ASYNC_CRYPT */ + #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index b4c617ce8..23a2afef6 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -62,6 +62,15 @@ const char* wc_GetErrorString(int error) case BAD_MUTEX_E : return "Bad mutex, operation failed"; + case WC_TIMEOUT_E: + return "Timeout error"; + + case WC_PENDING_E: + return "wolfCrypt Operation Pending (would block / eagain) error"; + + case WC_NOT_PENDING_E: + return "wolfCrypt operation not pending error"; + case MP_INIT_E : return "mp_init error state"; @@ -227,8 +236,8 @@ const char* wc_GetErrorString(int error) case AES_CCM_AUTH_E: return "AES-CCM Authentication check fail"; - case CAVIUM_INIT_E: - return "Cavium Init type error"; + case ASYNC_INIT_E: + return "Async Init error"; case COMPRESS_INIT_E: return "Compress Init error"; @@ -257,8 +266,8 @@ const char* wc_GetErrorString(int error) case ASN_OCSP_CONFIRM_E : return "ASN OCSP sig error, confirm failure"; - case BAD_ENC_STATE_E: - return "Bad ecc encrypt state operation"; + case BAD_STATE_E: + return "Bad state operation"; case BAD_PADDING_E: return "Bad padding, message wrong length"; @@ -377,9 +386,6 @@ const char* wc_GetErrorString(int error) case HASH_TYPE_E: return "Hash type not enabled/available"; - case WC_PENDING_E: - return "wolfCrypt Operation Pending (would block / eagain) error"; - case WC_KEY_SIZE_E: return "Key size error, either too small or large"; diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 7dd5fd507..28d04e76b 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -34,42 +34,54 @@ #include -#ifndef NO_ASN +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + +#ifdef NO_ASN +enum Hash_Sum { + MD2h = 646, + MD5h = 649, + SHAh = 88, + SHA256h = 414, + SHA384h = 415, + SHA512h = 416 +}; +#endif + int wc_HashGetOID(enum wc_HashType hash_type) { int oid = HASH_TYPE_E; /* Default to hash type error */ switch(hash_type) { case WC_HASH_TYPE_MD2: -#ifdef WOLFSSL_MD2 + #ifdef WOLFSSL_MD2 oid = MD2h; -#endif + #endif break; case WC_HASH_TYPE_MD5_SHA: case WC_HASH_TYPE_MD5: -#ifndef NO_MD5 + #ifndef NO_MD5 oid = MD5h; -#endif + #endif break; case WC_HASH_TYPE_SHA: -#ifndef NO_SHA + #ifndef NO_SHA oid = SHAh; -#endif + #endif break; case WC_HASH_TYPE_SHA256: -#ifndef NO_SHA256 + #ifndef NO_SHA256 oid = SHA256h; -#endif + #endif break; case WC_HASH_TYPE_SHA384: -#if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) + #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) oid = SHA384h; -#endif + #endif break; case WC_HASH_TYPE_SHA512: -#ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA512 oid = SHA512h; -#endif + #endif break; /* Not Supported */ diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 23b53b305..2a26d2663 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -50,16 +50,16 @@ int wc_HmacFinal(Hmac* hmac, byte* out) } -#ifdef HAVE_CAVIUM - int wc_HmacInitCavium(Hmac* hmac, int i) +#ifdef WOLFSSL_ASYNC_CRYPT + int wc_HmacAsyncInit(Hmac* hmac, int i) { - return HmacInitCavium(hmac, i); + return HmacAsyncInit(hmac, i); } - void wc_HmacFreeCavium(Hmac* hmac) + void wc_HmacAsyncFree(Hmac* hmac) { - HmacFreeCavium(hmac); + HmacAsyncFree(hmac); } #endif @@ -105,12 +105,48 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, #include -#ifdef HAVE_CAVIUM - static int HmacCaviumFinal(Hmac* hmac, byte* hash); - static int HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length); - static int HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, - word32 length); -#endif +int wc_HmacSizeByType(int type) +{ + if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 + || type == SHA512 || type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; + } + + switch (type) { + #ifndef NO_MD5 + case MD5: + return MD5_DIGEST_SIZE; + #endif + + #ifndef NO_SHA + case SHA: + return SHA_DIGEST_SIZE; + #endif + + #ifndef NO_SHA256 + case SHA256: + return SHA256_DIGEST_SIZE; + #endif + + #ifdef WOLFSSL_SHA384 + case SHA384: + return SHA384_DIGEST_SIZE; + #endif + + #ifdef WOLFSSL_SHA512 + case SHA512: + return SHA512_DIGEST_SIZE; + #endif + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + return BLAKE2B_OUTBYTES; + #endif + + default: + return BAD_FUNC_ARG; + } +} static int InitHmac(Hmac* hmac, int type) { @@ -175,9 +211,10 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) word32 i, hmac_block_size = 0; int ret; -#ifdef HAVE_CAVIUM - if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) - return HmacCaviumSetKey(hmac, type, key, length); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + return NitroxHmacSetKey(hmac, type, key, length); + } #endif ret = InitHmac(hmac, type); @@ -391,9 +428,10 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { int ret; -#ifdef HAVE_CAVIUM - if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) - return HmacCaviumUpdate(hmac, msg, length); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + return NitroxHmacUpdate(hmac, msg, length); + } #endif if (!hmac->innerHashKeyed) { @@ -459,9 +497,10 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) { int ret; -#ifdef HAVE_CAVIUM - if (hmac->magic == WOLFSSL_HMAC_CAVIUM_MAGIC) - return HmacCaviumFinal(hmac, hash); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + return NitroxHmacFinal(hmac, hash); + } #endif if (!hmac->innerHashKeyed) { @@ -606,129 +645,57 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) } -#ifdef HAVE_CAVIUM +#ifdef WOLFSSL_ASYNC_CRYPT /* Initialize Hmac for use with Nitrox device */ -int wc_HmacInitCavium(Hmac* hmac, int devId) +int wc_HmacAsyncInit(Hmac* hmac, int devId) { + int ret = 0; + if (hmac == NULL) return -1; - if (CspAllocContext(CONTEXT_SSL, &hmac->contextHandle, devId) != 0) - return -1; + ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, devId); + if (ret != 0) { + return ret; + } +#ifdef HAVE_CAVIUM hmac->keyLen = 0; hmac->dataLen = 0; hmac->type = 0; - hmac->devId = devId; - hmac->magic = WOLFSSL_HMAC_CAVIUM_MAGIC; hmac->data = NULL; /* buffered input data */ hmac->innerHashKeyed = 0; +#endif /* HAVE_CAVIUM */ /* default to NULL heap hint or test value */ #ifdef WOLFSSL_HEAP_TEST hmac->heap = (void)WOLFSSL_HEAP_TEST; #else hmac->heap = NULL; -#endif +#endif /* WOLFSSL_HEAP_TEST */ return 0; } /* Free Hmac from use with Nitrox device */ -void wc_HmacFreeCavium(Hmac* hmac) +void wc_HmacAsyncFree(Hmac* hmac) { if (hmac == NULL) return; - CspFreeContext(CONTEXT_SSL, hmac->contextHandle, hmac->devId); - hmac->magic = 0; - XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); + wolfAsync_DevCtxFree(&hmac->asyncDev); + +#ifdef HAVE_CAVIUM + XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_ASYNC_TMP); hmac->data = NULL; +#endif } +#endif /* WOLFSSL_ASYNC_CRYPT */ -static int HmacCaviumFinal(Hmac* hmac, byte* hash) -{ - word32 requestId; - - if (CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, - (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId, - hmac->devId) != 0) { - WOLFSSL_MSG("Cavium Hmac failed"); - return -1; - } - hmac->innerHashKeyed = 0; /* tell update to start over if used again */ - - return 0; -} - - -static int HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length) -{ - word16 add = (word16)length; - word32 total; - byte* tmp; - - if (length > WOLFSSL_MAX_16BIT) { - WOLFSSL_MSG("Too big msg for cavium hmac"); - return -1; - } - - if (hmac->innerHashKeyed == 0) { /* starting new */ - hmac->dataLen = 0; - hmac->innerHashKeyed = 1; - } - - total = add + hmac->dataLen; - if (total > WOLFSSL_MAX_16BIT) { - WOLFSSL_MSG("Too big msg for cavium hmac"); - return -1; - } - - tmp = XMALLOC(hmac->dataLen + add, hmac->heap ,DYNAMIC_TYPE_CAVIUM_TMP); - if (tmp == NULL) { - WOLFSSL_MSG("Out of memory for cavium update"); - return -1; - } - if (hmac->dataLen) - XMEMCPY(tmp, hmac->data, hmac->dataLen); - XMEMCPY(tmp + hmac->dataLen, msg, add); - - hmac->dataLen += add; - XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_CAVIUM_TMP); - hmac->data = tmp; - - return 0; -} - - -static int HmacCaviumSetKey(Hmac* hmac, int type, const byte* key, - word32 length) -{ - hmac->macType = (byte)type; - if (type == MD5) - hmac->type = MD5_TYPE; - else if (type == SHA) - hmac->type = SHA1_TYPE; - else if (type == SHA256) - hmac->type = SHA256_TYPE; - else { - WOLFSSL_MSG("unsupported cavium hmac type"); - } - - hmac->innerHashKeyed = 0; /* should we key Startup flag */ - - hmac->keyLen = (word16)length; - /* store key in ipad */ - XMEMCPY(hmac->ipad, key, length); - - return 0; -} - -#endif /* HAVE_CAVIUM */ int wolfSSL_GetHmacMaxSize(void) { @@ -748,49 +715,6 @@ int wolfSSL_GetHmacMaxSize(void) #endif /* WOLFSSL_HAVE_MIN */ -static INLINE int GetHashSizeByType(int type) -{ - if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 - || type == SHA512 || type == BLAKE2B_ID)) - return BAD_FUNC_ARG; - - switch (type) { - #ifndef NO_MD5 - case MD5: - return MD5_DIGEST_SIZE; - #endif - - #ifndef NO_SHA - case SHA: - return SHA_DIGEST_SIZE; - #endif - - #ifndef NO_SHA256 - case SHA256: - return SHA256_DIGEST_SIZE; - #endif - - #ifdef WOLFSSL_SHA384 - case SHA384: - return SHA384_DIGEST_SIZE; - #endif - - #ifdef WOLFSSL_SHA512 - case SHA512: - return SHA512_DIGEST_SIZE; - #endif - - #ifdef HAVE_BLAKE2 - case BLAKE2B_ID: - return BLAKE2B_OUTBYTES; - #endif - - default: - return BAD_FUNC_ARG; - } -} - - /* HMAC-KDF with hash type, optional salt and info, return 0 on success */ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, @@ -806,7 +730,7 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, byte prk[MAX_DIGEST_SIZE]; #endif const byte* localSalt; /* either points to user input or tmp */ - int hashSz = GetHashSizeByType(type); + int hashSz = wc_HmacSizeByType(type); word32 outIdx = 0; byte n = 0x1; int ret; @@ -815,13 +739,13 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, return BAD_FUNC_ARG; #ifdef WOLFSSL_SMALL_STACK - tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, hmac->heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) return MEMORY_E; - prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, hmac->heap, DYNAMIC_TYPE_TMP_BUFFER); if (prk == NULL) { - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, hmac->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } #endif @@ -873,8 +797,8 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, } #ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(prk, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, hmac->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(prk, hmac->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 28707ce21..983b63b4f 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -46,4 +46,8 @@ EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/pic32/pic32mz-hash.c \ wolfcrypt/src/port/nrf51.c +if BUILD_CAVIUM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c +EXTRA_DIST += wolfcrypt/src/port/cavium/README.md +endif diff --git a/wolfcrypt/src/port/cavium/README.md b/wolfcrypt/src/port/cavium/README.md new file mode 100644 index 000000000..982a938b9 --- /dev/null +++ b/wolfcrypt/src/port/cavium/README.md @@ -0,0 +1,32 @@ +# Cavium Nitrox V Support + +## Directory Structure: +`/` + `/CNN55XX-SDK` + `/wolfssl` + +## Cavium Driver + +Tested again `CNN55XX-Driver-Linux-KVM-XEN-PF-SDK-0.2-04.tar` +From inside `CNN55XX-SDK`: +1. `make` + Note: To resolve warnings in `CNN55XX-SDK/include/vf_defs.h`: + a. Changed `vf_config_mode_str` to return `const char*` and modify `vf_mode_str` to be `const char*`. + b. In `vf_config_mode_to_num_vfs` above `default:` add `case PF:`. + +2. `sudo make load` + +## wolfSSL + +Currently the AES and DES3 benchmark tests causes the kernel to crash, so they are disabled for now, even though the wolfCrypt tests pass for those. + +From inside `wolfssl`: +1. `./configure --with-cavium-v=../CNN55XX-SDK --enable-asynccrypt --enable-aesni --enable-intelasm --disable-aes --disable-aesgcm --disable-des3` +2. `make` + +## Usage + +Note: Must run applications with sudo to access device. + +`sudo ./wolfcrypt/benchmark/benchmark` +`sudo ./wolfcrypt/test/testwolfcrypt` diff --git a/wolfcrypt/src/port/cavium/cavium_nitrox.c b/wolfcrypt/src/port/cavium/cavium_nitrox.c new file mode 100644 index 000000000..1acc49644 --- /dev/null +++ b/wolfcrypt/src/port/cavium/cavium_nitrox.c @@ -0,0 +1,778 @@ +/* cavium-nitrox.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_CAVIUM + +#include +#include +#include +#include +#ifndef NO_RSA + #include +#endif +#ifndef NO_AES + #include +#endif + +#include +#include /* For ntohs */ + +static CspHandle mLastDevHandle = INVALID_DEVID; + +int NitroxTranslateResponseCode(int ret) +{ + switch (ret) { + case EAGAIN: + case ERR_REQ_PENDING: + ret = WC_PENDING_E; + break; + case ERR_REQ_TIMEOUT: + ret = WC_TIMEOUT_E; + break; + case 0: + /* leave as-is */ + break; + default: + printf("NitroxTranslateResponseCode Unknown ret=%x\n", ret); + ret = ASYNC_INIT_E; + } + return ret; +} + + +CspHandle NitroxGetDeviceHandle(void) +{ + return mLastDevHandle; +} + +CspHandle NitroxOpenDevice(int dma_mode, int dev_id) +{ + mLastDevHandle = INVALID_DEVID; + +#ifdef HAVE_CAVIUM_V + (void)dma_mode; + + if (CspInitialize(dev_id, &mLastDevHandle)) { + return -1; + } + +#else + Csp1CoreAssignment core_assign; + Uint32 device; + + if (CspInitialize(CAVIUM_DIRECT, CAVIUM_DEV_ID)) { + return -1; + } + if (Csp1GetDevType(&device)) { + return -1; + } + if (device != NPX_DEVICE) { + if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, + (Uint32 *)&core_assign)!= 0) { + return -1; + } + } + CspShutdown(CAVIUM_DEV_ID); + + mLastDevHandle = CspInitialize(dma_mode, dev_id); + if (mLastDevHandle == 0) { + mLastDevHandle = dev_id; + } + +#endif /* HAVE_CAVIUM_V */ + + return mLastDevHandle; +} + + +int NitroxAllocContext(CaviumNitroxDev* nitrox, CspHandle devId, + ContextType type) +{ + int ret; + + if (nitrox == NULL) { + return -1; + } + + /* If invalid handle provided, use last open one */ + if (devId == INVALID_DEVID) { + devId = NitroxGetDeviceHandle(); + } + +#ifdef HAVE_CAVIUM_V + ret = CspAllocContext(devId, type, &nitrox->contextHandle); +#else + ret = CspAllocContext(type, &nitrox->contextHandle, devId); +#endif + if (ret != 0) { + return -1; + } + + nitrox->type = type; + nitrox->devId = devId; + + return 0; +} + +void NitroxFreeContext(CaviumNitroxDev* nitrox) +{ + if (nitrox == NULL) { + return; + } + +#ifdef HAVE_CAVIUM_V + CspFreeContext(nitrox->devId, nitrox->type, nitrox->contextHandle); +#else + CspFreeContext(nitrox->type, nitrox->contextHandle, nitrox->devId); +#endif +} + +void NitroxCloseDevice(CspHandle devId) +{ + if (devId >= 0) { + CspShutdown(devId); + } +} + +#if defined(WOLFSSL_ASYNC_CRYPT) + +int NitroxCheckRequest(CspHandle devId, CavReqId reqId) +{ + int ret = CspCheckForCompletion(devId, reqId); + return NitroxTranslateResponseCode(ret); +} + +int NitroxCheckRequests(CspHandle devId, CspMultiRequestStatusBuffer* req_stat_buf) +{ + int ret = CspGetAllResults(req_stat_buf, devId); + return NitroxTranslateResponseCode(ret); +} + + +#ifndef NO_RSA + +int NitroxRsaExptMod(const byte* in, word32 inLen, + byte* exponent, word32 expLen, + byte* modulus, word32 modLen, + byte* out, word32* outLen, RsaKey* key) +{ + int ret; + + if (key == NULL || in == NULL || inLen == 0 || exponent == NULL || + modulus == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + (void)outLen; + +#ifdef HAVE_CAVIUM_V + ret = CspMe(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, + CAVIUM_DPORT, modLen, expLen, inLen, + modulus, exponent, (Uint8*)in, out, + &key->asyncDev.dev.reqId); + #if 0 + /* TODO: Try MeCRT */ + ret = CspMeCRT(); + #endif +#else + /* Not implemented/supported */ + ret = NOT_COMPILED_IN; +#endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + + return ret; +} + +int NitroxRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 ret; + + if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->n.used) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_CAVIUM_V + ret = CspPkcs1v15Enc(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, + BT2, key->n.used, key->e.used, + (word16)inLen, key->n.dpraw, key->e.dpraw, (byte*)in, out, + &key->asyncDev.dev.reqId); +#else + ret = CspPkcs1v15Enc(CAVIUM_REQ_MODE, BT2, key->n.used, key->e.used, + (word16)inLen, key->n.dpraw, key->e.dpraw, (byte*)in, out, + &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); +#endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + + return key->n.used; +} + + +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (c[0] << 8) | (c[1]); +} + +int NitroxRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 ret; + word16 outSz = (word16)outLen; + + if (key == NULL || in == NULL || out == NULL || + inLen != (word32)key->n.used) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_CAVIUM_V + ret = CspPkcs1v15CrtDec(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, + BT2, key->n.used, key->q.dpraw, + key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, + (byte*)in, &outSz, out, &key->asyncDev.dev.reqId); +#else + ret = CspPkcs1v15CrtDec(CAVIUM_REQ_MODE, BT2, key->n.used, key->q.dpraw, + key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, + (byte*)in, &outSz, out, &key->asyncDev.dev.reqId, + key->asyncDev.dev.devId); +#endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + + ato16((const byte*)&outSz, &outSz); + + return outSz; +} + + +int NitroxRsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 ret; + + if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < + (word32)key->n.used) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_CAVIUM_V + ret = CspPkcs1v15CrtEnc(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, + BT1, key->n.used, (word16)inLen, + key->q.dpraw, key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, + (byte*)in, out, &key->asyncDev.dev.reqId); +#else + ret = CspPkcs1v15CrtEnc(CAVIUM_REQ_MODE, BT1, key->n.used, (word16)inLen, + key->q.dpraw, key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, + (byte*)in, out, &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); +#endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + + return key->n.used; +} + + +int NitroxRsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + word32 ret; + word16 outSz = (word16)outLen; + + if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->n.used) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_CAVIUM_V + ret = CspPkcs1v15Dec(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, + BT1, key->n.used, key->e.used, + key->n.dpraw, key->e.dpraw, (byte*)in, &outSz, out, + &key->asyncDev.dev.reqId); +#else + ret = CspPkcs1v15Dec(CAVIUM_REQ_MODE, BT1, key->n.used, key->e.used, + key->n.dpraw, key->e.dpraw, (byte*)in, &outSz, out, + &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); +#endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + + outSz = ntohs(outSz); + + return outSz; +} +#endif /* !NO_RSA */ + + +#ifndef NO_AES +int NitroxAesSetKey(Aes* aes, const byte* key, word32 length, const byte* iv) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(aes->key, key, length); /* key still holds key, iv still in reg */ + if (length == 16) + aes->type = AES_128_BIT; + else if (length == 24) + aes->type = AES_192_BIT; + else if (length == 32) + aes->type = AES_256_BIT; + + return wc_AesSetIV(aes, iv); +} + +#ifdef HAVE_AES_CBC +int NitroxAesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 length) +{ + int ret; + wolfssl_word offset = 0; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + #ifdef HAVE_CAVIUM_V + ret = CspEncryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, + (byte*)aes->reg, 0, NULL, slen, (byte*)in + offset, + out + offset, &aes->asyncDev.dev.reqId); + #else + ret = CspEncryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, + aes->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(aes->reg, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + #ifdef HAVE_CAVIUM_V + ret = CspEncryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, + (byte*)aes->reg, 0, NULL, slen, (byte*)in + offset, + out + offset, &aes->asyncDev.dev.reqId); + #else + ret = CspEncryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, + aes->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + XMEMCPY(aes->reg, out + offset+length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + return 0; +} + +#ifdef HAVE_AES_DECRYPT +int NitroxAesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 length) +{ + wolfssl_word offset = 0; + int ret; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + #ifdef HAVE_CAVIUM_V + ret = CspDecryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, (byte*)aes->reg, + 0, NULL, slen, (byte*)in + offset, out + offset, &aes->asyncDev.dev.reqId); + #else + ret = CspDecryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, + aes->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + #ifdef HAVE_CAVIUM_V + ret = CspDecryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, (byte*)aes->reg, + 0, NULL, slen, (byte*)in + offset, out + offset, &aes->asyncDev.dev.reqId); + #else + ret = CspDecryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, + aes->type, slen, (byte*)in + offset, out + offset, + (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, + aes->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + } + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + + +#if !defined(NO_ARC4) && !defined(HAVE_CAVIUM_V) +void NitroxArc4SetKey(Arc4* arc4, const byte* key, word32 length) +{ + if (CspInitializeRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, length, + (byte*)key, &arc4->asyncDev.dev.reqId, arc4->devId) != 0) { + WOLFSSL_MSG("Bad Cavium Arc4 Init"); + } +} + +void NitroxArc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) +{ + int ret; + wolfssl_word offset = 0; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + ret = CspEncryptRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, + CAVIUM_UPDATE, slen, (byte*)in + offset, out + offset, + &arc4->asyncDev.dev.reqId, arc4->devId); + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + } + if (length) { + word16 slen = (word16)length; + ret = CspEncryptRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, + CAVIUM_UPDATE, slen, (byte*)in + offset, out + offset, + &arc4->asyncDev.dev.reqId, arc4->devId); + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + } +} +#endif /* !NO_ARC4 && !HAVE_CAVIUM_V */ + + +#ifndef NO_DES3 +int NitroxDes3SetKey(Des3* des3, const byte* key, const byte* iv) +{ + if (des3 == NULL) + return BAD_FUNC_ARG; + + /* key[0] holds key, iv in reg */ + XMEMCPY(des3->key[0], key, DES_BLOCK_SIZE*3); + + return wc_Des3_SetIV(des3, iv); +} + +int NitroxDes3CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 length) +{ + wolfssl_word offset = 0; + int ret; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + #ifdef HAVE_CAVIUM_V + ret = CspEncrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], + (byte*)des3->reg, slen, (byte*)in + offset, + out + offset, &des3->asyncDev.dev.reqId); + #else + ret = CspEncrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in + offset, + out + offset, (byte*)des3->reg, (byte*)des3->key[0], + &des3->asyncDev.dev.reqId, des3->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(des3->reg, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + #ifdef HAVE_CAVIUM_V + ret = CspEncrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, + slen, (byte*)in + offset, out + offset, + &des3->asyncDev.dev.reqId); + #else + ret = CspEncrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in + offset, + out + offset, (byte*)des3->reg, (byte*)des3->key[0], + &des3->asyncDev.dev.reqId, des3->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + XMEMCPY(des3->reg, out+offset+length - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + } + return 0; +} + +int NitroxDes3CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 length) +{ + wolfssl_word offset = 0; + int ret; + + while (length > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + #ifdef HAVE_CAVIUM_V + ret = CspDecrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, + slen, (byte*)in + offset, out + offset, + &des3->asyncDev.dev.reqId); + #else + ret = CspDecrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in + offset, out + offset, + (byte*)des3->reg, (byte*)des3->key[0], &des3->asyncDev.dev.reqId, + des3->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + length -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); + } + if (length) { + word16 slen = (word16)length; + XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE,DES_BLOCK_SIZE); + #ifdef HAVE_CAVIUM_V + ret = CspDecrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, + FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, + slen, (byte*)in + offset, out + offset, + &des3->asyncDev.dev.reqId); + #else + ret = CspDecrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, + CAVIUM_NO_UPDATE, slen, (byte*)in + offset, out + offset, + (byte*)des3->reg, (byte*)des3->key[0], &des3->asyncDev.dev.reqId, + des3->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); + } + return 0; +} +#endif /* !NO_DES3 */ + + +#ifndef NO_HMAC +int NitroxHmacFinal(Hmac* hmac, byte* hash) +{ + int ret = -1; + +#ifdef HAVE_CAVIUM_V + word16 hashLen = wc_HmacSizeByType(hmac->macType); + ret = CspHmac(hmac->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, hmac->type, hmac->keyLen, + (byte*)hmac->ipad, hmac->dataLen, hmac->data, hashLen, + hash, &hmac->asyncDev.dev.reqId); +#else + ret = CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, + (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, + &hmac->asyncDev.dev.reqId, hmac->asyncDev.dev.devId); +#endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + + hmac->innerHashKeyed = 0; /* tell update to start over if used again */ + + return 0; +} + +int NitroxHmacUpdate(Hmac* hmac, const byte* msg, word32 length) +{ + word16 add = (word16)length; + word32 total; + byte* tmp; + + if (length > WOLFSSL_MAX_16BIT) { + WOLFSSL_MSG("Too big msg for cavium hmac"); + return -1; + } + + if (hmac->innerHashKeyed == 0) { /* starting new */ + hmac->dataLen = 0; + hmac->innerHashKeyed = 1; + } + + total = add + hmac->dataLen; + if (total > WOLFSSL_MAX_16BIT) { + WOLFSSL_MSG("Too big msg for cavium hmac"); + return -1; + } + + tmp = XMALLOC(hmac->dataLen + add, NULL, DYNAMIC_TYPE_ASYNC_TMP); + if (tmp == NULL) { + WOLFSSL_MSG("Out of memory for cavium update"); + return -1; + } + if (hmac->dataLen) + XMEMCPY(tmp, hmac->data, hmac->dataLen); + XMEMCPY(tmp + hmac->dataLen, msg, add); + + hmac->dataLen += add; + XFREE(hmac->data, NULL, DYNAMIC_TYPE_ASYNC_TMP); + hmac->data = tmp; + + return 0; +} + +int NitroxHmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) +{ + hmac->macType = (byte)type; + + /* Determine Cavium HashType */ + switch(type) { + #ifndef NO_MD5 + case MD5: + hmac->type = MD5_TYPE; + break; + #endif + #ifndef NO_SHA + case SHA: + hmac->type = SHA1_TYPE; + break; + #endif + #ifndef NO_SHA256 + case SHA256: + #ifdef HAVE_CAVIUM_V + hmac->type = SHA2_SHA256; + #else + hmac->type = SHA256_TYPE; + #endif + break; + #endif + #ifdef HAVE_CAVIUM_V + #ifndef WOLFSSL_SHA512 + case SHA512: + hmac->type = SHA2_SHA512; + break; + #endif + #ifndef WOLFSSL_SHA384 + case SHA384: + hmac->type = SHA2_SHA384; + break; + #endif + #endif /* HAVE_CAVIUM_V */ + default: + WOLFSSL_MSG("unsupported cavium hmac type"); + break; + } + + hmac->innerHashKeyed = 0; /* should we key Startup flag */ + + hmac->keyLen = (word16)length; + /* store key in ipad */ + XMEMCPY(hmac->ipad, key, length); + + return 0; +} +#endif /* !NO_HMAC */ + + +#if !defined(HAVE_HASHDRBG) && !defined(NO_RC4) +void NitroxRngGenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ + wolfssl_word offset = 0; + word32 requestId; + + while (sz > WOLFSSL_MAX_16BIT) { + word16 slen = (word16)WOLFSSL_MAX_16BIT; + #ifdef HAVE_CAVIUM_V + ret = CspTrueRandom(rng->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, slen, output + offset, &requestId); + #else + ret = CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, + rng->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + sz -= WOLFSSL_MAX_16BIT; + offset += WOLFSSL_MAX_16BIT; + } + if (sz) { + word16 slen = (word16)sz; + #ifdef HAVE_CAVIUM_V + ret = CspTrueRandom(rng->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, + CAVIUM_SSL_GRP, CAVIUM_DPORT, slen, output + offset, &requestId); + #else + ret = CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, + rng->asyncDev.dev.devId); + #endif + ret = NitroxTranslateResponseCode(ret); + if (ret != 0) { + return ret; + } + } +} +#endif /* !defined(HAVE_HASHDRBG) && !defined(NO_RC4) */ + + +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#endif /* HAVE_CAVIUM */ diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 4e533cf93..efcd3a570 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -47,14 +47,6 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) return GenerateSeed(os, seed, sz); } -#ifdef HAVE_CAVIUM - int wc_InitRngCavium(WC_RNG* rng, int i) - { - return InitRngCavium(rng, i); - } -#endif - - int wc_InitRng(WC_RNG* rng) { return InitRng_fips(rng); @@ -178,6 +170,7 @@ int wc_FreeRng(WC_RNG* rng) #define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) #endif + #if defined(HAVE_HASHDRBG) || defined(NO_RC4) /* Start NIST DRBG code */ @@ -811,12 +804,13 @@ int wc_InitRng(WC_RNG* rng) #endif #ifdef HAVE_INTEL_RDGEN - wc_InitRng_IntelRD() ; - if(IS_INTEL_RDRAND)return 0 ; + wc_InitRng_IntelRD(); + if(IS_INTEL_RDRAND) return 0; #endif -#ifdef HAVE_CAVIUM - if (rng->magic == WOLFSSL_RNG_CAVIUM_MAGIC) - return 0; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, INVALID_DEVID); + if (ret != 0) return -2007; #endif #ifdef WOLFSSL_SMALL_STACK @@ -847,10 +841,6 @@ int wc_InitRng(WC_RNG* rng) return ret; } -#ifdef HAVE_CAVIUM - static void CaviumRNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz); -#endif - /* place a generated block in output */ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) { @@ -858,9 +848,10 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) if(IS_INTEL_RDRAND) return wc_GenerateRand_IntelRD(NULL, output, sz) ; #endif -#ifdef HAVE_CAVIUM - if (rng->magic == WOLFSSL_RNG_CAVIUM_MAGIC) - return CaviumRNG_GenerateBlock(rng, output, sz); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { + return NitroxRngGenerateBlock(rng, output, sz); + } #endif XMEMSET(output, 0, sz); wc_Arc4Process(&rng->cipher, output, output, sz); @@ -878,53 +869,14 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) int wc_FreeRng(WC_RNG* rng) { (void)rng; - return 0; -} - -#ifdef HAVE_CAVIUM - -#include -#include "cavium_common.h" - -/* Initialize RNG for use with Nitrox device */ -int wc_InitRngCavium(WC_RNG* rng, int devId) -{ - if (rng == NULL) - return -1; - - rng->devId = devId; - rng->magic = WOLFSSL_RNG_CAVIUM_MAGIC; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + wolfAsync_DevCtxFree(&rng->asyncDev); +#endif return 0; } - -static void CaviumRNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (sz > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->devId) != 0) { - WOLFSSL_MSG("Cavium RNG failed"); - } - sz -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (sz) { - word16 slen = (word16)sz; - if (CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->devId) != 0) { - WOLFSSL_MSG("Cavium RNG failed"); - } - } -} - -#endif /* HAVE_CAVIUM */ - #endif /* HAVE_HASHDRBG || NO_RC4 */ @@ -1127,7 +1079,7 @@ static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) return 0; } -#else +#else /* HAVE_HASHDRBG || NO_RC4 */ /* return 0 on success */ static INLINE int IntelRDrand32(unsigned int *rnd) diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index e34e17c85..cff7477a4 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -32,18 +32,34 @@ /* Possible RSA enable options: - * NO_RSA: Overall control of RSA default: off - * WC_RSA_BLINDING: Uses Blinding w/ Private Ops slower by ~20% default: off + * NO_RSA: Overall control of RSA default: on (not defined) + * WC_RSA_BLINDING: Uses Blinding w/ Private Ops default: off + Note: slower by ~20% * WOLFSSL_KEY_GEN: Allows Private Key Generation default: off * RSA_LOW_MEM: NON CRT Private Operations, less memory default: off + * WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined) + * RSA_CHECK_KEYTYPE: RSA check key type default: off */ +/* +RSA Key Size Configuration: + * FP_MAX_BITS: With USE_FAST_MATH only default: 4096 + If USE_FAST_MATH then use this to override default. + Value is key size * 2. Example: RSA 3072 = 6144 +*/ + + #ifdef HAVE_FIPS int wc_InitRsaKey(RsaKey* key, void* ptr) { return InitRsaKey_fips(key, ptr); } +int wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId) +{ + (void)devId; + return InitRsaKey_fips(key, ptr); +} int wc_FreeRsaKey(RsaKey* key) { @@ -112,25 +128,13 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, #endif -#ifdef HAVE_CAVIUM - int wc_RsaInitCavium(RsaKey* key, int i) - { - return RsaInitCavium(key, i); - } - - - void wc_RsaFreeCavium(RsaKey* key) - { - RsaFreeCavium(key); - } -#endif - /* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c * wc_RsaPrivateKeyDecode * wc_RsaPublicKeyDecode */ #else /* else build without fips */ + #include #include #include @@ -141,91 +145,101 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, #include #endif -#ifdef HAVE_CAVIUM - static int InitCaviumRsaKey(RsaKey* key, void* heap); - static int FreeCaviumRsaKey(RsaKey* key); - static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); - static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); - static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); - static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key); -#endif +#define ERROR_OUT(x) { ret = (x); goto done;} + + +#ifdef WOLFSSL_ASYNC_CRYPT + static int InitAsyncRsaKey(RsaKey* key); + static int FreeAsyncRsaKey(RsaKey* key); +#endif /* WOLFSSL_ASYNC_CRYPT */ enum { - RSA_PUBLIC_ENCRYPT = 0, - RSA_PUBLIC_DECRYPT = 1, - RSA_PRIVATE_ENCRYPT = 2, - RSA_PRIVATE_DECRYPT = 3, + RSA_STATE_NONE = 0, - RSA_BLOCK_TYPE_1 = 1, - RSA_BLOCK_TYPE_2 = 2, + RSA_STATE_ENCRYPT_PAD, + RSA_STATE_ENCRYPT_EXPTMOD, + RSA_STATE_ENCRYPT_RES, - RSA_MIN_SIZE = 512, - RSA_MAX_SIZE = 4096, - - RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */ + RSA_STATE_DECRYPT_EXPTMOD, + RSA_STATE_DECRYPT_UNPAD, + RSA_STATE_DECRYPT_RES, }; +int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + + key->type = RSA_TYPE_UNKNOWN; + key->state = RSA_STATE_NONE; + key->heap = heap; + key->tmp = NULL; + key->tmpLen = 0; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (devId != INVALID_DEVID) { + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA, + devId); + if (ret == 0) { + ret = InitAsyncRsaKey(key); + } + } + else +#endif + { + mp_init(&key->n); + mp_init(&key->e); + mp_init(&key->d); + mp_init(&key->p); + mp_init(&key->q); + mp_init(&key->dP); + mp_init(&key->dQ); + mp_init(&key->u); + } + + return ret; +} int wc_InitRsaKey(RsaKey* key, void* heap) { -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return InitCaviumRsaKey(key, heap); -#endif - - key->type = -1; /* haven't decided yet */ - key->heap = heap; - -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->n.dp = key->e.dp = 0; /* public alloc parts */ - - key->d.dp = key->p.dp = 0; /* private alloc parts */ - key->q.dp = key->dP.dp = 0; - key->u.dp = key->dQ.dp = 0; -#else - mp_init(&key->n); - mp_init(&key->e); - mp_init(&key->d); - mp_init(&key->p); - mp_init(&key->q); - mp_init(&key->dP); - mp_init(&key->dQ); - mp_init(&key->u); -#endif - - return 0; + return wc_InitRsaKey_ex(key, heap, INVALID_DEVID); } - int wc_FreeRsaKey(RsaKey* key) { - (void)key; + int ret = 0; - if (key == NULL) - return 0; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return FreeCaviumRsaKey(key); -#endif - - if (key->type == RSA_PRIVATE) { - mp_forcezero(&key->u); - mp_forcezero(&key->dQ); - mp_forcezero(&key->dP); - mp_forcezero(&key->q); - mp_forcezero(&key->p); - mp_forcezero(&key->d); + if (key == NULL) { + return BAD_FUNC_ARG; } - mp_clear(&key->e); - mp_clear(&key->n); - return 0; +#ifdef WOLFSSL_ASYNC_CRYPT + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + ret = FreeAsyncRsaKey(key); + wolfAsync_DevCtxFree(&key->asyncDev); + } + else +#endif + { + if (key->type == RSA_PRIVATE) { + mp_forcezero(&key->u); + mp_forcezero(&key->dQ); + mp_forcezero(&key->dP); + mp_forcezero(&key->q); + mp_forcezero(&key->p); + mp_forcezero(&key->d); + } + mp_clear(&key->e); + mp_clear(&key->n); + } + + return ret; } @@ -237,8 +251,8 @@ int wc_FreeRsaKey(RsaKey* key) out: mask output after generation outSz: size of output buffer */ -static int wc_MGF1(enum wc_HashType hType, byte* seed, word32 seedSz, - byte* out, word32 outSz, void* heap) +static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz, + byte* out, word32 outSz, void* heap) { byte* tmp; /* needs to be large enough for seed size plus counter(4) */ @@ -301,8 +315,7 @@ static int wc_MGF1(enum wc_HashType hType, byte* seed, word32 seedSz, out[idx++] = tmp[i]; } counter++; - } - while (idx < outSz); + } while (idx < outSz); /* check for if dynamic memory was needed, then free */ if (tmpF) { @@ -312,41 +325,37 @@ static int wc_MGF1(enum wc_HashType hType, byte* seed, word32 seedSz, return 0; } - /* helper function to direct which mask generation function is used switeched on type input */ -static int wc_MGF(int type, byte* seed, word32 seedSz, - byte* out, word32 outSz, void* heap) +static int RsaMGF(int type, byte* seed, word32 seedSz, byte* out, + word32 outSz, void* heap) { int ret; switch(type) { - #ifndef NO_SHA + #ifndef NO_SHA case WC_MGF1SHA1: - ret = wc_MGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz, heap); - break; - #endif - #ifndef NO_SHA256 + ret = RsaMGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz, heap); + break; + #endif + #ifndef NO_SHA256 case WC_MGF1SHA256: - ret = wc_MGF1(WC_HASH_TYPE_SHA256, seed, seedSz, - out, outSz, heap); - break; - #endif - #ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SHA384 + ret = RsaMGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz, heap); + break; + #endif + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case WC_MGF1SHA384: - ret = wc_MGF1(WC_HASH_TYPE_SHA384, seed, seedSz, - out, outSz, heap); - break; - #endif + ret = RsaMGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz, heap); + break; + #endif case WC_MGF1SHA512: - ret = wc_MGF1(WC_HASH_TYPE_SHA512, seed, seedSz, - out, outSz, heap); - break; - #endif + ret = RsaMGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz, heap); + break; + #endif default: - WOLFSSL_MSG("Unknown MGF function: check build options"); + WOLFSSL_MSG("Unknown MGF type: check build options"); ret = BAD_FUNC_ARG; } @@ -359,12 +368,15 @@ static int wc_MGF(int type, byte* seed, word32 seedSz, return ret; } +#endif /* !WC_NO_RSA_OAEP */ -static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, - word32 pkcsBlockLen, byte padValue, WC_RNG* rng, - enum wc_HashType hType, int mgf, byte* optLabel, - word32 labelLen, void* heap) +/* Padding */ +#ifndef WC_NO_RSA_OAEP +static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + void* heap) { int ret; int hLen; @@ -383,8 +395,7 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, byte seed[ WC_MAX_DIGEST_SIZE]; #endif - /* can use with no lable but catch if no lable provided while having - length > 0 */ + /* no label is allowed, but catch if no label provided and length > 0 */ if (optLabel == NULL && labelLen > 0) { return BUFFER_E; } @@ -396,13 +407,13 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, } #ifdef WOLFSSL_SMALL_STACK - lHash = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_TMP_BUFFER); if (lHash == NULL) { return MEMORY_E; } - seed = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_TMP_BUFFER); if (seed == NULL) { - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } #else @@ -417,8 +428,8 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if ((ret = wc_Hash(hType, optLabel, labelLen, lHash, hLen)) != 0) { WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small"); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -434,8 +445,8 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if ((word32)(2 * hLen + 2) > pkcsBlockLen) { WOLFSSL_MSG("OAEP pad error hash to big for RSA key size"); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return BAD_FUNC_ARG; } @@ -443,8 +454,8 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) { WOLFSSL_MSG("OAEP pad error message too long"); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return BAD_FUNC_ARG; } @@ -454,8 +465,8 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, psLen = pkcsBlockLen - inputLen - 2 * hLen - 2; if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */ #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return BUFFER_E; } @@ -472,8 +483,8 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, /* generate random seed */ if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -482,19 +493,19 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, heap, DYNAMIC_TYPE_RSA); if (dbMask == NULL) { #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return MEMORY_E; } XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */ - ret = wc_MGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1, heap); + ret = RsaMGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1, heap); if (ret != 0) { XFREE(dbMask, heap, DYNAMIC_TYPE_RSA); #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -512,11 +523,11 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, idx = 0; pkcsBlock[idx++] = 0x00; /* create seedMask inline */ - if ((ret = wc_MGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, - pkcsBlock + 1, hLen, heap)) != 0) { + if ((ret = RsaMGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, + pkcsBlock + 1, hLen, heap)) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -529,20 +540,21 @@ static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, } #ifdef WOLFSSL_SMALL_STACK - XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(lHash, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif (void)padValue; return 0; } -#endif /* WC_NO_RSA_OAEP */ +#endif /* !WC_NO_RSA_OAEP */ -static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, - word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) { - if (inputLen == 0 || pkcsBlockLen == 0) { + if (input == NULL || inputLen == 0 || pkcsBlock == NULL || + pkcsBlockLen == 0) { return BAD_FUNC_ARG; } @@ -552,6 +564,7 @@ static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, if (padValue == RSA_BLOCK_TYPE_1) { if (pkcsBlockLen < inputLen + 2) { + WOLFSSL_MSG("RsaPad error, invalid length"); return RSA_PAD_E; } @@ -564,17 +577,20 @@ static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, int ret; if (pkcsBlockLen < inputLen + 1) { + WOLFSSL_MSG("RsaPad error, invalid length"); return RSA_PAD_E; } padLen = pkcsBlockLen - inputLen - 1; ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); - if (ret != 0) + if (ret != 0) { return ret; + } /* remove zeros */ - for (i = 1; i < padLen; i++) + for (i = 1; i < padLen; i++) { if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + } } pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ @@ -583,37 +599,35 @@ static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, return 0; } - -#ifndef WC_NO_RSA_OAEP /* helper function to direct which padding is used */ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, - word32 pkcsBlockLen, byte padValue, WC_RNG* rng, - int padType, enum wc_HashType hType, int mgf, - byte* optLabel, word32 labelLen, void* heap) + word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + void* heap) { int ret; switch (padType) { case WC_RSA_PKCSV15_PAD: - WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); - ret = wc_RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, - padValue, rng); + //WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng); break; + #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); - ret = wc_RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, - padValue, rng, hType, mgf, optLabel, labelLen, heap); + //WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng, hType, mgf, optLabel, labelLen, heap); break; - + #endif default: WOLFSSL_MSG("Unknown RSA Pad Type"); ret = RSA_PAD_E; } /* silence warning if not used with padding scheme */ - (void)padType; (void)hType; (void)mgf; (void)optLabel; @@ -624,9 +638,11 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, } +/* UnPadding */ +#ifndef WC_NO_RSA_OAEP /* UnPad plaintext, set start to *output, return length of plaintext, * < 0 on error */ -static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, +static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, byte **output, enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, void* heap) { @@ -636,6 +652,11 @@ static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, byte* tmp; word32 idx; + /* no label is allowed, but catch if no label provided and length > 0 */ + if (optLabel == NULL && labelLen > 0) { + return BUFFER_E; + } + hLen = wc_HashGetDigestSize(hType); if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) { return BAD_FUNC_ARG; @@ -648,9 +669,9 @@ static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, XMEMSET(tmp, 0, pkcsBlockLen); /* find seedMask value */ - if ((ret = wc_MGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), - pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) { - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), + pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -660,9 +681,9 @@ static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, } /* get dbMask value */ - if ((ret = wc_MGF(mgf, tmp, hLen, tmp + hLen, - pkcsBlockLen - hLen - 1, heap)) != 0) { - XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen, + pkcsBlockLen - hLen - 1, heap)) != 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -708,19 +729,20 @@ static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, /* UnPad plaintext, set start to *output, return length of plaintext, * < 0 on error */ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, - byte **output, byte padValue) + byte **output, byte padValue) { - word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0, - invalid = 0, - i = 1, - outputLen; + word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0; + word32 invalid = 0; + word32 i = 1; + word32 outputLen; - if (pkcsBlockLen == 0) { + if (output == NULL || pkcsBlockLen == 0) { return BAD_FUNC_ARG; } - if (pkcsBlock[0] != 0x0) /* skip past zero */ + if (pkcsBlock[0] != 0x0) { /* skip past zero */ invalid = 1; + } pkcsBlock++; pkcsBlockLen--; /* Require block type padValue */ @@ -751,8 +773,6 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, return outputLen; } - -#ifndef WC_NO_RSA_OAEP /* helper function to direct unpadding */ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, byte padValue, int padType, enum wc_HashType hType, @@ -763,23 +783,24 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, switch (padType) { case WC_RSA_PKCSV15_PAD: - WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + //WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); break; + #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); - ret = wc_RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, - hType, mgf, optLabel, labelLen, heap); + //WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, + hType, mgf, optLabel, labelLen, heap); break; + #endif default: - WOLFSSL_MSG("Unknown RSA Pad Type"); + WOLFSSL_MSG("Unknown RSA UnPad Type"); ret = RSA_PAD_E; } /* silence warning if not used with padding scheme */ - (void)padType; (void)hType; (void)mgf; (void)optLabel; @@ -788,7 +809,6 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, return ret; } -#endif /* WC_NO_RSA_OAEP */ #ifdef WC_RSA_BLINDING @@ -856,11 +876,9 @@ static int mp_rand(mp_int* a, int digits, WC_RNG* rng) #endif /* WC_RSA_BLINGING */ -static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, +static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { - #define ERROR_OUT(x) { ret = (x); goto done;} - mp_int tmp; #ifdef WC_RSA_BLINDING mp_int rnd, rndi; @@ -885,92 +903,100 @@ static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY) ERROR_OUT(MP_READ_E); - if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - #ifdef WC_RSA_BLINDING - /* blind */ - ret = mp_rand(&rnd, get_digit_count(&key->n), rng); - if (ret != MP_OKAY) - ERROR_OUT(ret); + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + { + #ifdef WC_RSA_BLINDING + /* blind */ + ret = mp_rand(&rnd, get_digit_count(&key->n), rng); + if (ret != MP_OKAY) + ERROR_OUT(ret); - /* rndi = 1/rnd mod n */ - if (mp_invmod(&rnd, &key->n, &rndi) != MP_OKAY) - ERROR_OUT(MP_INVMOD_E); + /* rndi = 1/rnd mod n */ + if (mp_invmod(&rnd, &key->n, &rndi) != MP_OKAY) + ERROR_OUT(MP_INVMOD_E); - /* rnd = rnd^e */ - if (mp_exptmod(&rnd, &key->e, &key->n, &rnd) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); + /* rnd = rnd^e */ + if (mp_exptmod(&rnd, &key->e, &key->n, &rnd) != MP_OKAY) + ERROR_OUT(MP_EXPTMOD_E); - /* tmp = tmp*rnd mod n */ - if (mp_mulmod(&tmp, &rnd, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_MULMOD_E); - #endif /* WC_RSA_BLINGING */ + /* tmp = tmp*rnd mod n */ + if (mp_mulmod(&tmp, &rnd, &key->n, &tmp) != MP_OKAY) + ERROR_OUT(MP_MULMOD_E); + #endif /* WC_RSA_BLINGING */ - #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ - if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); - #else - #define INNER_ERROR_OUT(x) { ret = (x); goto inner_done; } + #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ + if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) + ERROR_OUT(MP_EXPTMOD_E); + #else + #define INNER_ERROR_OUT(x) { ret = (x); goto inner_done; } + + { /* tmpa/b scope */ + mp_int tmpa, tmpb; - { /* tmpa/b scope */ - mp_int tmpa, tmpb; + if (mp_init(&tmpa) != MP_OKAY) + ERROR_OUT(MP_INIT_E); - if (mp_init(&tmpa) != MP_OKAY) - ERROR_OUT(MP_INIT_E); - - if (mp_init(&tmpb) != MP_OKAY) { - mp_clear(&tmpa); - ERROR_OUT(MP_INIT_E); - } - - /* tmpa = tmp^dP mod p */ - if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY) - INNER_ERROR_OUT(MP_EXPTMOD_E); - - /* tmpb = tmp^dQ mod q */ - if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY) - INNER_ERROR_OUT(MP_EXPTMOD_E); - - /* tmp = (tmpa - tmpb) * qInv (mod p) */ - if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_SUB_E); - - if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_MULMOD_E); - - /* tmp = tmpb + q * tmp */ - if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_MUL_E); - - if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY) - INNER_ERROR_OUT(MP_ADD_E); - - inner_done: + if (mp_init(&tmpb) != MP_OKAY) { mp_clear(&tmpa); - mp_clear(&tmpb); + ERROR_OUT(MP_INIT_E); + } - if (ret != 0) { - goto done; - } - } /* tmpa/b scope */ + /* tmpa = tmp^dP mod p */ + if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY) + INNER_ERROR_OUT(MP_EXPTMOD_E); - #endif /* RSA_LOW_MEM */ + /* tmpb = tmp^dQ mod q */ + if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY) + INNER_ERROR_OUT(MP_EXPTMOD_E); - #ifdef WC_RSA_BLINDING - /* unblind */ - if (mp_mulmod(&tmp, &rndi, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_MULMOD_E); - #endif /* WC_RSA_BLINDING */ + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_SUB_E); + + if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_MULMOD_E); + + /* tmp = tmpb + q * tmp */ + if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_MUL_E); + + if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY) + INNER_ERROR_OUT(MP_ADD_E); + + inner_done: + mp_clear(&tmpa); + mp_clear(&tmpb); + + if (ret != 0) { + goto done; + } + #undef INNER_ERROR_OUT + } /* tmpa/b scope */ + #endif /* RSA_LOW_MEM */ + + #ifdef WC_RSA_BLINDING + /* unblind */ + if (mp_mulmod(&tmp, &rndi, &key->n, &tmp) != MP_OKAY) + ERROR_OUT(MP_MULMOD_E); + #endif /* WC_RSA_BLINDING */ + + break; } - else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) ERROR_OUT(MP_EXPTMOD_E); - } - else + break; + default: ERROR_OUT(RSA_WRONG_TYPE_E); + } - keyLen = mp_unsigned_bin_size(&key->n); - if (keyLen > *outLen) + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) { ERROR_OUT(RSA_BUFFER_E); + } len = mp_unsigned_bin_size(&tmp); @@ -1000,41 +1026,91 @@ done: return ret; } - -int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key, WC_RNG* rng) +#ifdef WOLFSSL_ASYNC_CRYPT +static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) { - int sz, ret; + int ret = 0; -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); -#endif +#ifdef WOLFSSL_ASYNC_CRYPT_TEST + AsyncCryptTestDev* testDev = &key->asyncDev.dev; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_RSA_FUNC; + testDev->rsaFunc.in = in; + testDev->rsaFunc.inSz = inLen; + testDev->rsaFunc.out = out; + testDev->rsaFunc.outSz = outLen; + testDev->rsaFunc.type = type; + testDev->rsaFunc.key = key; + testDev->rsaFunc.rng = rng; + return WC_PENDING_E; + } +#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ - sz = mp_unsigned_bin_size(&key->n); - if (sz > (int)outLen) - return RSA_BUFFER_E; + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef HAVE_CAVIUM + ret = NitroxRsaExptMod(in, inLen, key->d.dpraw, key->d.used, + key->n.dpraw, key->n.used, out, outLen, key); + #elif defined(HAVE_INTEL_QA) + /* TODO: Add support for Intel Quick Assist */ + ret = -1; + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + #endif + break; - if (sz < RSA_MIN_PAD_SZ) { - return WC_KEY_SIZE_E; + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + #ifdef HAVE_CAVIUM + ret = NitroxRsaExptMod(in, inLen, key->e.dpraw, key->e.used, + key->n.dpraw, key->n.used, out, outLen, key); + #elif defined(HAVE_INTEL_QA) + /* TODO: Add support for Intel Quick Assist */ + ret = -1; + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + #endif + break; + + default: + ret = RSA_WRONG_TYPE_E; } - if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) - return RSA_BUFFER_E; + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ - ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng); - if (ret != 0) - return ret; +int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret; - if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PUBLIC_ENCRYPT, key, NULL)) < 0) - sz = ret; + if (key == NULL || in == NULL || inLen == 0 || out == NULL || + outLen == NULL || *outLen == 0 || type == RSA_TYPE_UNKNOWN) { + return BAD_FUNC_ARG; + } - return sz; +#ifdef WOLFSSL_ASYNC_CRYPT + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng); + } + else +#endif + { + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + } + + if (ret == MP_EXPTMOD_E) { + /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */ + WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); + } + return ret; } -#ifndef WC_NO_RSA_OAEP +/* Internal Wrappers */ /* Gives the option of choosing padding type in : input to be encrypted inLen: length of input buffer @@ -1042,332 +1118,380 @@ int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, outLen: length of encrypted output buffer key : wolfSSL initialized RSA key struct rng : wolfSSL initialized random number struct - type : type of padding to use ie WC_RSA_OAEP_PAD + rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT, + RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT + pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2 + pad_type : type of padding: WC_RSA_PKCSV15_PAD or WC_RSA_OAEP_PAD hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h mgf : type of mask generation function to use label : optional label labelSz : size of optional label buffer */ -int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key, WC_RNG* rng, int type, - enum wc_HashType hash, int mgf, byte* label, word32 labelSz) +static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int rsa_type, + byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, + byte* label, word32 labelSz, WC_RNG* rng) { - int sz, ret; + int ret = BAD_FUNC_ARG, sz; -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); -#endif + if (in == NULL || inLen == 0 || out == NULL || key == NULL) { + return ret; + } - sz = mp_unsigned_bin_size(&key->n); - if (sz > (int)outLen) + sz = wc_RsaEncryptSize(key); + if (sz > (int)outLen) { return RSA_BUFFER_E; + } if (sz < RSA_MIN_PAD_SZ) { return WC_KEY_SIZE_E; } - if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) { return RSA_BUFFER_E; + } - ret = wc_RsaPad_ex(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng, - type, hash, mgf, label, labelSz, key->heap); - if (ret != 0) + /* Optional key type check (disabled by default) */ + /* Note: internal tests allow private to be used as public */ +#ifdef RSA_CHECK_KEYTYPE + if ((rsa_type == RSA_PUBLIC_ENCRYPT && key->type != RSA_PUBLIC) || + (rsa_type == RSA_PRIVATE_ENCRYPT && key->type != RSA_PRIVATE)) { + WOLFSSL_MSG("Wrong RSA Encrypt key type"); + return RSA_WRONG_TYPE_E; + } +#endif + + switch (key->state) { + case RSA_STATE_NONE: + case RSA_STATE_ENCRYPT_PAD: + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + if (rsa_type == RSA_PUBLIC_ENCRYPT && pad_value == RSA_BLOCK_TYPE_2) { + key->state = RSA_STATE_ENCRYPT_RES; + key->tmpLen = key->n.used; + return NitroxRsaPublicEncrypt(in, inLen, out, outLen, key); + } + else if (rsa_type == RSA_PRIVATE_ENCRYPT && pad_value == RSA_BLOCK_TYPE_1) { + key->state = RSA_STATE_ENCRYPT_RES; + key->tmpLen = key->n.used; + return NitroxRsaSSL_Sign(in, inLen, out, outLen, key); + } + } + #endif + + key->state = RSA_STATE_ENCRYPT_EXPTMOD; + + ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, + pad_type, hash, mgf, label, labelSz, key->heap); + if (ret < 0) { + break; + } + /* fall through */ + case RSA_STATE_ENCRYPT_EXPTMOD: + key->state = RSA_STATE_ENCRYPT_RES; + + key->tmpLen = outLen; + ret = wc_RsaFunction(out, sz, out, &key->tmpLen, rsa_type, key, rng); + if (ret < 0) { + break; + } + /* fall through */ + case RSA_STATE_ENCRYPT_RES: + key->state = RSA_STATE_NONE; + ret = key->tmpLen; + break; + + default: + ret = BAD_STATE_E; + } + + /* if async pending then return and skip done cleanup below */ + if (ret == WC_PENDING_E) { return ret; + } - if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PUBLIC_ENCRYPT, key, NULL)) < 0) - sz = ret; + key->state = RSA_STATE_NONE; - return sz; + return ret; +} + +/* Gives the option of choosing padding type + in : input to be decrypted + inLen: length of input buffer + out: decrypted message + outLen: length of decrypted message in bytes + outPtr: optional inline output pointer (if provided doing inline) + key : wolfSSL initialized RSA key struct + rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT, + RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT + pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2 + pad_type : type of padding: WC_RSA_PKCSV15_PAD or WC_RSA_OAEP_PAD + hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h + mgf : type of mask generation function to use + label : optional label + labelSz : size of optional label buffer */ +static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, + word32 outLen, byte** outPtr, RsaKey* key, + int rsa_type, byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, + byte* label, word32 labelSz, WC_RNG* rng) +{ + int ret = BAD_FUNC_ARG; + + if (in == NULL || inLen == 0 || out == NULL || key == NULL) { + return ret; + } + + /* Optional key type check (disabled by default) */ + /* Note: internal tests allow private to be used as public */ +#ifdef RSA_CHECK_KEYTYPE + if ((rsa_type == RSA_PUBLIC_DECRYPT && key->type != RSA_PUBLIC) || + (rsa_type == RSA_PRIVATE_DECRYPT && key->type != RSA_PRIVATE)) { + WOLFSSL_MSG("Wrong RSA Decrypt key type"); + return RSA_WRONG_TYPE_E; + } +#endif + + switch (key->state) { + case RSA_STATE_NONE: + case RSA_STATE_DECRYPT_EXPTMOD: + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + key->tmpLen = 0; + if (rsa_type == RSA_PRIVATE_DECRYPT && pad_value == RSA_BLOCK_TYPE_2) { + key->state = RSA_STATE_DECRYPT_RES; + key->tmp = NULL; + ret = NitroxRsaPrivateDecrypt(in, inLen, out, outLen, key); + if (ret > 0) { + if (outPtr) + *outPtr = in; + } + return ret; + } + else if (rsa_type == RSA_PUBLIC_DECRYPT && pad_value == RSA_BLOCK_TYPE_1) { + key->state = RSA_STATE_DECRYPT_RES; + key->tmp = NULL; + return NitroxRsaSSL_Verify(in, inLen, out, outLen, key); + } + } + #endif + + key->state = RSA_STATE_DECRYPT_UNPAD; + + /* verify the tmp ptr is NULL, otherwise indicates bad state */ + if (key->tmp != NULL) { + ERROR_OUT(BAD_STATE_E); + } + + /* if not doing this inline then allocate a buffer for it */ + key->tmpLen = inLen; + if (outPtr == NULL) { + key->tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); + if (key->tmp == NULL) { + ERROR_OUT(MEMORY_E); + } + XMEMCPY(key->tmp, in, inLen); + } + else { + key->tmp = out; + } + ret = wc_RsaFunction(key->tmp, inLen, key->tmp, &key->tmpLen, + rsa_type, key, rng); + if (ret < 0) { + break; + } + /* fall through */ + case RSA_STATE_DECRYPT_UNPAD: + { + byte* pad = NULL; + key->state = RSA_STATE_DECRYPT_RES; + ret = wc_RsaUnPad_ex(key->tmp, key->tmpLen, &pad, pad_value, pad_type, + hash, mgf, label, labelSz, key->heap); + if (ret > 0 && ret <= (int)outLen && pad != NULL) { + /* only copy output if not inline */ + if (outPtr == NULL) { + XMEMCPY(out, pad, ret); + } + else { + *outPtr = pad; + } + } + else if (ret >= 0) { + ret = RSA_BUFFER_E; + } + if (ret < 0) { + break; + } + /* fall through */ + } + case RSA_STATE_DECRYPT_RES: + key->state = RSA_STATE_NONE; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + ret = key->tmpLen; + } + #endif + break; + default: + ret = BAD_STATE_E; + } + + /* if async pending then return and skip done cleanup below */ + if (ret == WC_PENDING_E) { + return ret; + } + +done: + + key->state = RSA_STATE_NONE; + if (key->tmp) { + /* if not inline */ + if (outPtr == NULL) { + ForceZero(key->tmp, key->tmpLen); + XFREE(key->tmp, key->heap, DYNAMIC_TYPE_RSA); + } + key->tmp = NULL; + key->tmpLen = 0; + } + + return ret; +} + + +/* Public RSA Functions */ +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PUBLIC_ENCRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); +} + + +#ifndef WC_NO_RSA_OAEP +int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng, int type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, RSA_PUBLIC_ENCRYPT, + RSA_BLOCK_TYPE_2, type, hash, mgf, label, labelSz, rng); } #endif /* WC_NO_RSA_OAEP */ int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) { - int ret; WC_RNG* rng = NULL; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { - ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); - if (ret > 0) - *out = in; - return ret; - } -#endif - #ifdef WC_RSA_BLINDING rng = key->rng; #endif - - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key, - rng)) < 0) { - return ret; - } - - return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2); + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } #ifndef WC_NO_RSA_OAEP -/* Gives the option of choosing padding type - in : input to be decrypted - inLen: length of input buffer - out: pointer to place of decrypted message - key : wolfSSL initialized RSA key struct - type : type of padding to use ie WC_RSA_OAEP_PAD - hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h - mgf : type of mask generation function to use - label : optional label - labelSz : size of optional label buffer */ int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, - RsaKey* key, int type, enum wc_HashType hash, int mgf, - byte* label, word32 labelSz) + RsaKey* key, int type, enum wc_HashType hash, + int mgf, byte* label, word32 labelSz) { - int ret; WC_RNG* rng = NULL; - - /* sanity check on arguments */ - if (in == NULL || key == NULL) { - return BAD_FUNC_ARG; - } - - /* check if given a label size but not given a label buffer */ - if (label == NULL && labelSz > 0) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { - ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); - if (ret > 0) - *out = in; - return ret; - } -#endif - #ifdef WC_RSA_BLINDING rng = key->rng; #endif - - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key, - rng)) - < 0) { - return ret; - } - - return wc_RsaUnPad_ex(in, inLen, out, RSA_BLOCK_TYPE_2, type, hash, mgf, - label, labelSz, key->heap); + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, + mgf, label, labelSz, rng); } #endif /* WC_NO_RSA_OAEP */ -int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key) +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) { - int plainLen; - byte* tmp; - byte* pad = 0; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; #endif - - tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); - if (tmp == NULL) { - return MEMORY_E; - } - - XMEMCPY(tmp, in, inLen); - - if ( (plainLen = wc_RsaPrivateDecryptInline(tmp, inLen, &pad, key) ) < 0) { - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - return plainLen; - } - if (plainLen > (int)outLen || pad == NULL) - plainLen = BAD_FUNC_ARG; - else - XMEMCPY(out, pad, plainLen); - - ForceZero(tmp, inLen); - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - - return plainLen; + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } #ifndef WC_NO_RSA_OAEP -/* Gives the option of choosing padding type - in : input to be decrypted - inLen: length of input buffer - out: decrypted message - outLen: length of decrypted message in bytes - key : wolfSSL initialized RSA key struct - type : type of padding to use ie WC_RSA_OAEP_PAD - hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h - mgf : type of mask generation function to use - label : optional label - labelSz : size of optional label buffer */ -int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key, int type, enum wc_HashType hash, int mgf, - byte* label, word32 labelSz) +int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) { - int plainLen; - byte* tmp; - byte* pad = 0; - - /* sanity check on arguments */ - if (out == NULL || in == NULL || key == NULL) { - return BAD_FUNC_ARG; - } - - /* check if given a label size but not given a label buffer */ - if (label == NULL && labelSz > 0) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; #endif - - tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); - if (tmp == NULL) { - return MEMORY_E; - } - - XMEMCPY(tmp, in, inLen); - - if ( (plainLen = wc_RsaPrivateDecryptInline_ex(tmp, inLen, &pad, key, - type, hash, mgf, label, labelSz) ) < 0) { - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - return plainLen; - } - if (plainLen > (int)outLen || pad == NULL) - plainLen = BAD_FUNC_ARG; - else - XMEMCPY(out, pad, plainLen); - - ForceZero(tmp, inLen); - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - - return plainLen; + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label, + labelSz, rng); } #endif /* WC_NO_RSA_OAEP */ -/* for Rsa Verify */ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) { - int ret; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { - ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key); - if (ret > 0) - *out = in; - return ret; - } + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; #endif - - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key, - NULL)) < 0) { - return ret; - } - - return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } - int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key) + RsaKey* key) { - int plainLen; - byte* tmp; - byte* pad = 0; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaSSL_Verify(in, inLen, out, outLen, key); + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; #endif - - tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); - if (tmp == NULL) { - return MEMORY_E; - } - - XMEMCPY(tmp, in, inLen); - - if ( (plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key) ) < 0) { - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - return plainLen; - } - - if (plainLen > (int)outLen || pad == NULL) - plainLen = BAD_FUNC_ARG; - else - XMEMCPY(out, pad, plainLen); - - ForceZero(tmp, inLen); - XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); - - return plainLen; + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } -/* for Rsa Sign */ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, - RsaKey* key, WC_RNG* rng) + RsaKey* key, WC_RNG* rng) { - int sz, ret; - -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return CaviumRsaSSL_Sign(in, inLen, out, outLen, key); -#endif - - sz = mp_unsigned_bin_size(&key->n); - if (sz > (int)outLen) - return RSA_BUFFER_E; - - if (sz < RSA_MIN_PAD_SZ) { - return WC_KEY_SIZE_E; - } - - if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) - return RSA_BUFFER_E; - - ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng); - if (ret != 0) - return ret; - - if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PRIVATE_ENCRYPT, key, rng)) < 0) - sz = ret; - - return sz; + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } int wc_RsaEncryptSize(RsaKey* key) { -#ifdef HAVE_CAVIUM - if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) - return key->c_nSz; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + return key->n.used; + } #endif return mp_unsigned_bin_size(&key->n); } + /* flatten RsaKey structure into individual elements (e, n) */ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, - word32* nSz) + word32* nSz) { int sz, ret; - if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) - return BAD_FUNC_ARG; + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) { + return BAD_FUNC_ARG; + } sz = mp_unsigned_bin_size(&key->e); if ((word32)sz > *eSz) @@ -1377,7 +1501,7 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, return ret; *eSz = (word32)sz; - sz = mp_unsigned_bin_size(&key->n); + sz = wc_RsaEncryptSize(key); if ((word32)sz > *nSz) return RSA_BUFFER_E; ret = mp_to_unsigned_bin(&key->n, n); @@ -1494,8 +1618,6 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) return 0; } - - #endif /* WOLFSSL_KEY_GEN */ @@ -1513,183 +1635,118 @@ int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) #endif /* WC_RSA_BLINDING */ -#ifdef HAVE_CAVIUM -#include -#include "cavium_common.h" - -/* Initialize RSA for use with Nitrox device */ -int wc_RsaInitCavium(RsaKey* rsa, int devId) +#ifdef WOLFSSL_ASYNC_CRYPT +int wc_RsaAsyncHandle(RsaKey* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) { - if (rsa == NULL) - return -1; + int ret; - if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0) - return -1; + if (key == NULL || queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } - rsa->devId = devId; - rsa->magic = WOLFSSL_RSA_CAVIUM_MAGIC; + /* make sure this rsa context had "wc_RsaAsyncInit" called on it */ + if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_RSA) { + return ASYNC_INIT_E; + } + + /* setup the event and push to queue */ + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = wolfEventQueue_Push(queue, event); + } + + /* check for error (helps with debugging) */ + if (ret != 0) { + WOLFSSL_MSG("wc_RsaAsyncHandle failed"); + } + return ret; +} + +int wc_RsaAsyncWait(int ret, RsaKey* key) +{ + if (ret == WC_PENDING_E) { + WOLF_EVENT event; + XMEMSET(&event, 0, sizeof(event)); + ret = wolfAsync_EventInit(&event, WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); + if (ret == 0) { + ret = wolfAsync_EventWait(&event); + if (ret == 0 && event.ret >= 0) { + ret = event.ret; + } + } + } + return ret; +} + +/* Initialize async RSA key */ +static int InitAsyncRsaKey(RsaKey* key) +{ + XMEMSET(&key->n, 0, sizeof(key->n)); + XMEMSET(&key->e, 0, sizeof(key->e)); + XMEMSET(&key->d, 0, sizeof(key->d)); + XMEMSET(&key->p, 0, sizeof(key->p)); + XMEMSET(&key->q, 0, sizeof(key->q)); + XMEMSET(&key->dP, 0, sizeof(key->dP)); + XMEMSET(&key->dQ, 0, sizeof(key->dQ)); + XMEMSET(&key->u, 0, sizeof(key->u)); return 0; } - -/* Free RSA from use with Nitrox device */ -void wc_RsaFreeCavium(RsaKey* rsa) +/* Free async RSA key */ +static int FreeAsyncRsaKey(RsaKey* key) { - if (rsa == NULL) - return; - - CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId); - rsa->magic = 0; -} - - -/* Initialize cavium RSA key */ -static int InitCaviumRsaKey(RsaKey* key, void* heap) -{ - if (key == NULL) - return BAD_FUNC_ARG; - - key->heap = heap; - key->type = -1; /* don't know yet */ - - key->c_n = NULL; - key->c_e = NULL; - key->c_d = NULL; - key->c_p = NULL; - key->c_q = NULL; - key->c_dP = NULL; - key->c_dQ = NULL; - key->c_u = NULL; - - key->c_nSz = 0; - key->c_eSz = 0; - key->c_dSz = 0; - key->c_pSz = 0; - key->c_qSz = 0; - key->c_dP_Sz = 0; - key->c_dQ_Sz = 0; - key->c_uSz = 0; - - return 0; -} - - -/* Free cavium RSA key */ -static int FreeCaviumRsaKey(RsaKey* key) -{ - if (key == NULL) - return BAD_FUNC_ARG; - - XFREE(key->c_n, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_e, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_d, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_p, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_q, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - XFREE(key->c_u, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); - - return InitCaviumRsaKey(key, key->heap); /* reset pointers */ -} - - -static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - - if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz, - (word16)inLen, key->c_n, key->c_e, (byte*)in, out, - &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium Enc BT2 failed"); - return -1; + if (key->type == RSA_PRIVATE) { + if (key->d.dpraw) { + ForceZero(key->d.dpraw, key->d.used); + #ifndef USE_FAST_MATH + XFREE(key->d.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + } + if (key->p.dpraw) { + ForceZero(key->p.dpraw, key->p.used); + #ifndef USE_FAST_MATH + XFREE(key->p.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + } + if (key->q.dpraw) { + ForceZero(key->q.dpraw, key->q.used); + #ifndef USE_FAST_MATH + XFREE(key->q.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + } + if (key->dP.dpraw) { + ForceZero(key->dP.dpraw, key->dP.used); + #ifndef USE_FAST_MATH + XFREE(key->dP.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + } + if (key->dQ.dpraw) { + ForceZero(key->dQ.dpraw, key->dQ.used); + #ifndef USE_FAST_MATH + XFREE(key->dQ.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + } + if (key->u.dpraw) { + ForceZero(key->u.dpraw, key->u.used); + #ifndef USE_FAST_MATH + XFREE(key->u.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + #endif + } } - return key->c_nSz; + +#ifndef USE_FAST_MATH + XFREE(key->n.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); + XFREE(key->e.dpraw, key->heap, DYNAMIC_TYPE_ASYNC_RSA); +#endif + + return InitAsyncRsaKey(key); /* reset pointers */ } +#endif /* WOLFSSL_ASYNC_CRYPT */ -static INLINE void ato16(const byte* c, word16* u16) -{ - *u16 = (c[0] << 8) | (c[1]); -} - - -static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q, - key->c_dQ, key->c_p, key->c_dP, key->c_u, - (byte*)in, &outSz, out, &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium CRT Dec BT2 failed"); - return -1; - } - ato16((const byte*)&outSz, &outSz); - - return outSz; -} - - -static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - - if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < - (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen, - key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u, - (byte*)in, out, &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium CRT Enc BT1 failed"); - return -1; - } - return key->c_nSz; -} - - -static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 requestId; - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) - return -1; - - ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz, - key->c_n, key->c_e, (byte*)in, &outSz, out, - &requestId, key->devId); - if (ret != 0) { - WOLFSSL_MSG("Cavium Dec BT1 failed"); - return -1; - } - outSz = ntohs(outSz); - - return outSz; -} - - -#endif /* HAVE_CAVIUM */ +#undef ERROR_OUT #endif /* HAVE_FIPS */ #endif /* NO_RSA */ - diff --git a/wolfcrypt/src/wolfevent.c b/wolfcrypt/src/wolfevent.c new file mode 100644 index 000000000..4da1b2b33 --- /dev/null +++ b/wolfcrypt/src/wolfevent.c @@ -0,0 +1,274 @@ +/* wolfevent.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + + +#ifdef HAVE_WOLF_EVENT + +#include +#include +#include + +#include + + +int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context) +{ + if (event == NULL) { + return BAD_FUNC_ARG; + } + + if (event->pending) { + WOLFSSL_MSG("event already pending!"); + return BAD_COND_E; + } + + XMEMSET(event, 0, sizeof(WOLF_EVENT)); + event->type = type; + event->context = context; + + return 0; +} + +int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags) +{ + int ret = BAD_COND_E; + + /* Check hardware */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (event->type >= WOLF_EVENT_TYPE_ASYNC_FIRST && + event->type <= WOLF_EVENT_TYPE_ASYNC_LAST) + { + ret = wolfAsync_EventPoll(event, flags); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue) +{ + int ret = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(queue, 0, sizeof(WOLF_EVENT_QUEUE)); +#ifndef SINGLE_THREADED + ret = InitMutex(&queue->lock); +#endif + return ret; +} + + +int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + if ((ret = LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* Setup event */ + event->next = NULL; + event->pending = 1; + + if (queue->tail == NULL) { + queue->head = event; + } + else { + queue->tail->next = event; + event->prev = queue->tail; + } + queue->tail = event; /* add to the end either way */ + queue->count++; + ret = 0; + +#ifndef SINGLE_THREADED + UnLockMutex(&queue->lock); +#endif + + return ret; +} + +int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* Pop first item off queue */ + *event = queue->head; + ret = wolfEventQueue_Remove(queue, *event); + +#ifndef SINGLE_THREADED + UnLockMutex(&queue->lock); +#endif + + return ret; +} + +/* assumes queue is locked by caller */ +int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + if (event == queue->head && event == queue->tail) { + queue->head = NULL; + queue->tail = NULL; + } + else if (event == queue->head) { + queue->head = event->next; + queue->head->prev = NULL; + } + else if (event == queue->tail) { + queue->tail = event->prev; + queue->tail->next = NULL; + } + else { + WOLF_EVENT* next = event->next; + WOLF_EVENT* prev = event->prev; + next->prev = prev; + prev->next = next; + } + queue->count--; + + return ret; +} + +int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, + WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount) +{ + WOLF_EVENT* event; + int ret = 0, count = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* itterate event queue */ + for (event = queue->head; event != NULL; event = event->next) + { + /* optional filter based on context */ + if (context_filter == NULL || event->context == context_filter) { + + /* poll event */ + ret = wolfEvent_Poll(event, flags); + if (ret < 0) break; /* exit for */ + + /* If event is done then process */ + if (event->done) { + /* remove from queue */ + ret = wolfEventQueue_Remove(queue, event); + if (ret < 0) break; /* exit for */ + + /* return pointer in 'events' arg */ + if (events) { + events[count] = event; /* return pointer */ + } + count++; + + /* check to make sure our event list isn't full */ + if (events && count >= maxEvents) { + break; /* exit for */ + } + } + } + } + +#ifndef SINGLE_THREADED + UnLockMutex(&queue->lock); +#endif + + /* return number of properly populated events */ + if (eventCount) { + *eventCount = count; + } + + return ret; +} + +int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue) +{ + int ret; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + ret = queue->count; + +#ifndef SINGLE_THREADED + UnLockMutex(&queue->lock); +#endif + + return ret; +} + +void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue) +{ + if (queue) { + #ifndef SINGLE_THREADED + FreeMutex(&queue->lock); + #endif + } +} + +#endif /* HAVE_WOLF_EVENT */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9feda3ad6..a9c2088ff 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -107,6 +107,9 @@ #ifdef HAVE_FIPS #include #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ @@ -133,11 +136,6 @@ #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #endif -#ifdef HAVE_CAVIUM - #include "cavium_sysdep.h" - #include "cavium_common.h" - #include "cavium_ioctl.h" -#endif #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #include @@ -165,6 +163,9 @@ #include "wolfssl/wolfcrypt/mem_track.h" #endif +/* for async devices */ +static int devId = INVALID_DEVID; + #ifdef HAVE_WNR const char* wnrConfigFile = "wnr-example.conf"; #endif @@ -251,6 +252,10 @@ int idea_test(void); int memory_test(void); #endif +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && !defined(OPENSSL_EXTRA) + int wolfSSL_Debugging_ON(void); +#endif + /* General big buffer size for many tests. */ #define FOURK_BUF 4096 @@ -295,10 +300,18 @@ int wolfcrypt_test(void* args) ((func_args*)args)->return_code = -1; /* error state */ +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); +#endif + #if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) InitMemoryTracker(); #endif +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); +#endif + wolfCrypt_Init(); #ifdef HAVE_FIPS @@ -316,6 +329,16 @@ int wolfcrypt_test(void* args) #endif /* USE_FAST_MATH */ #endif /* !NO_BIG_INT */ +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevOpen(&devId); + if (ret != 0) { + err_sys("Async device open failed", -1236); + return -1236; + } +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + #ifndef NO_MD5 if ( (ret = md5_test()) != 0) return err_sys("MD5 test failed!\n", ret); @@ -661,45 +684,12 @@ int wolfcrypt_test(void* args) #ifndef NO_MAIN_DRIVER -#ifdef HAVE_CAVIUM - -static int OpenNitroxDevice(int dma_mode,int dev_id) -{ - Csp1CoreAssignment core_assign; - Uint32 device; - - if (CspInitialize(CAVIUM_DIRECT,CAVIUM_DEV_ID)) - return -1; - if (Csp1GetDevType(&device)) - return -1; - if (device != NPX_DEVICE) { - if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, - (Uint32 *)&core_assign)!= 0) - return -1; - } - CspShutdown(CAVIUM_DEV_ID); - - return CspInitialize(dma_mode, dev_id); -} - -#endif /* HAVE_CAVIUM */ - /* so overall tests can pull in test function */ int main(int argc, char** argv) { - func_args args; - -#ifdef HAVE_CAVIUM - int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID); - if (ret != 0) { - err_sys("Cavium OpenNitroxDevice failed", -1236); - return -1236; - } -#endif /* HAVE_CAVIUM */ - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { err_sys("Whitewood netRandom global config failed", -1237); @@ -712,10 +702,6 @@ static int OpenNitroxDevice(int dma_mode,int dev_id) wolfcrypt_test(&args); -#ifdef HAVE_CAVIUM - CspShutdown(CAVIUM_DEV_ID); -#endif - #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context", -1238); @@ -1337,14 +1323,18 @@ int hmac_md5_test(void) test_hmac[2] = c; for (i = 0; i < times; ++i) { -#if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) - if (i == 1) + #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) + if (i == 1) { continue; /* cavium can't handle short keys, fips not allowed */ -#endif -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) + } + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + if (wc_HmacAsyncInit(&hmac, devId) != 0) { return -20009; -#endif + } + #endif + ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) return -4015; @@ -1358,9 +1348,10 @@ int hmac_md5_test(void) if (XMEMCMP(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0) return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); -#endif + + #ifdef WOLFSSL_ASYNC_CRYPT + wc_HmacAsyncFree(&hmac); + #endif } return 0; @@ -1418,8 +1409,8 @@ int hmac_sha_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) +#ifdef WOLFSSL_ASYNC_CRYPT + if (wc_HmacAsyncInit(&hmac, devId) != 0) return -20010; #endif ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)XSTRLEN(keys[i])); @@ -1435,8 +1426,8 @@ int hmac_sha_test(void) if (XMEMCMP(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0) return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_HmacAsyncFree(&hmac); #endif } @@ -1499,8 +1490,8 @@ int hmac_sha256_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) +#ifdef WOLFSSL_ASYNC_CRYPT + if (wc_HmacAsyncInit(&hmac, devId) != 0) return -20011; #endif ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys[i],(word32)XSTRLEN(keys[i])); @@ -1516,8 +1507,8 @@ int hmac_sha256_test(void) if (XMEMCMP(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0) return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_HmacAsyncFree(&hmac); #endif } @@ -1580,8 +1571,12 @@ int hmac_blake2b_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef HAVE_CAVIUM - if (wc_HmacInitCavium(&hmac, CAVIUM_DEV_ID) != 0) +#ifdef WOLFSSL_ASYNC_CRYPT + #ifdef HAVE_CAVIUM_V + /* Blake2 not supported on Cavium V, but SHA3 is */ + return 0; + #endif + if (wc_HmacAsyncInit(&hmac, devId) != 0) return -20011; #endif ret = wc_HmacSetKey(&hmac, BLAKE2B_ID, (byte*)keys[i], @@ -1598,8 +1593,8 @@ int hmac_blake2b_test(void) if (XMEMCMP(hash, test_hmac[i].output, BLAKE2B_256) != 0) return -20 - i; -#ifdef HAVE_CAVIUM - wc_HmacFreeCavium(&hmac); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_HmacAsyncFree(&hmac); #endif } @@ -1816,12 +1811,12 @@ int arc4_test(void) if (i == 3) keylen = 4; -#ifdef HAVE_CAVIUM - if (wc_Arc4InitCavium(&enc, CAVIUM_DEV_ID) != 0) + #ifdef WOLFSSL_ASYNC_CRYPT + if (wc_Arc4AsyncInit(&enc, devId) != 0) return -20001; - if (wc_Arc4InitCavium(&dec, CAVIUM_DEV_ID) != 0) + if (wc_Arc4AsyncInit(&dec, devId) != 0) return -20002; -#endif + #endif wc_Arc4SetKey(&enc, (byte*)keys[i], keylen); wc_Arc4SetKey(&dec, (byte*)keys[i], keylen); @@ -1836,10 +1831,10 @@ int arc4_test(void) if (XMEMCMP(cipher, test_arc4[i].output, test_arc4[i].outLen)) return -20 - 5 - i; -#ifdef HAVE_CAVIUM - wc_Arc4FreeCavium(&enc); - wc_Arc4FreeCavium(&dec); -#endif + #ifdef WOLFSSL_ASYNC_CRYPT + wc_Arc4AsyncFree(&enc); + wc_Arc4AsyncFree(&dec); + #endif } return 0; @@ -2596,18 +2591,24 @@ int des_test(void) if (ret != 0) return -31; - wc_Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); - ret = wc_Des_SetKey(&dec, key, iv, DES_DECRYPTION); + ret = wc_Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); if (ret != 0) return -32; - wc_Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); - if (XMEMCMP(plain, vector, sizeof(plain))) + ret = wc_Des_SetKey(&dec, key, iv, DES_DECRYPTION); + if (ret != 0) return -33; - if (XMEMCMP(cipher, verify, sizeof(cipher))) + ret = wc_Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); + if (ret != 0) return -34; + if (XMEMCMP(plain, vector, sizeof(plain))) + return -35; + + if (XMEMCMP(cipher, verify, sizeof(cipher))) + return -36; + return 0; } #endif /* NO_DES3 */ @@ -2652,10 +2653,10 @@ int des3_test(void) int ret; -#ifdef HAVE_CAVIUM - if (wc_Des3_InitCavium(&enc, CAVIUM_DEV_ID) != 0) +#ifdef WOLFSSL_ASYNC_CRYPT + if (wc_Des3AsyncInit(&enc, devId) != 0) return -20005; - if (wc_Des3_InitCavium(&dec, CAVIUM_DEV_ID) != 0) + if (wc_Des3AsyncInit(&dec, devId) != 0) return -20006; #endif ret = wc_Des3_SetKey(&enc, key3, iv3, DES_ENCRYPTION); @@ -2677,9 +2678,9 @@ int des3_test(void) if (XMEMCMP(cipher, verify3, sizeof(cipher))) return -36; -#ifdef HAVE_CAVIUM - wc_Des3_FreeCavium(&enc); - wc_Des3_FreeCavium(&dec); +#ifdef WOLFSSL_ASYNC_CRYPT + wc_Des3AsyncFree(&enc); + wc_Des3AsyncFree(&dec); #endif return 0; } @@ -2714,11 +2715,11 @@ int aes_test(void) byte key[] = "0123456789abcdef "; /* align */ byte iv[] = "1234567890abcdef "; /* align */ -#ifdef HAVE_CAVIUM - if (wc_AesInitCavium(&enc, CAVIUM_DEV_ID) != 0) - return -20003; - if (wc_AesInitCavium(&dec, CAVIUM_DEV_ID) != 0) - return -20004; +#ifdef WOLFSSL_ASYNC_CRYPT + if (wc_AesAsyncInit(&enc, devId) != 0) + return -20003; + if (wc_AesAsyncInit(&dec, devId) != 0) + return -20004; #endif ret = wc_AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); if (ret != 0) @@ -2829,10 +2830,11 @@ int aes_test(void) } #endif /* WOLFSSL_AESNI HAVE_AES_DECRYPT */ -#ifdef HAVE_CAVIUM - wc_AesFreeCavium(&enc); - wc_AesFreeCavium(&dec); -#endif +#ifdef WOLFSSL_ASYNC_CRYPT + wc_AesAsyncFree(&enc); + wc_AesAsyncFree(&dec); +#endif /* WOLFSSL_ASYNC_CRYPT */ + #endif /* HAVE_AES_CBC */ #ifdef WOLFSSL_AES_COUNTER @@ -3745,10 +3747,6 @@ static int random_rng_test(void) byte block[32]; int ret, i; -#ifdef HAVE_CAVIUM - ret = wc_InitRngCavium(&rng, CAVIUM_DEV_ID); - if (ret != 0) return -2007; -#endif ret = wc_InitRng(&rng); if (ret != 0) return -39; @@ -4263,6 +4261,7 @@ int certext_test(void) } #endif /* WOLFSSL_CERT_EXT && WOLFSSL_TEST_CERT */ + int rsa_test(void) { byte* tmp; @@ -4309,11 +4308,7 @@ int rsa_test(void) fclose(file); #endif /* USE_CERT_BUFFERS */ -#ifdef HAVE_CAVIUM - wc_RsaInitCavium(&key, CAVIUM_DEV_ID); -#endif - - ret = wc_InitRsaKey(&key, HEAP_HINT); + ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId); if (ret != 0) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -39; @@ -4328,11 +4323,20 @@ int rsa_test(void) TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -42; } - ret = wc_RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -43; } + #ifdef WC_RSA_BLINDING { int tmpret = ret; @@ -4344,26 +4348,54 @@ int rsa_test(void) ret = tmpret; } #endif - ret = wc_RsaPrivateDecrypt(out, ret, plain, sizeof(plain), &key); + + idx = ret; /* save off encrypted length */ + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt(out, idx, plain, sizeof(plain), &key); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -44; } + if (XMEMCMP(plain, in, inLen)) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -45; } - ret = wc_RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -46; } + + idx = ret; XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaSSL_Verify(out, ret, plain, sizeof(plain), &key); + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaSSL_Verify(out, idx, plain, sizeof(plain), &key); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -47; } + if (XMEMCMP(plain, in, ret)) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -48; @@ -4375,18 +4407,36 @@ int rsa_test(void) !defined(HAVE_FIPS) #ifndef NO_SHA XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -143; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, + + idx = ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -144; } + if (XMEMCMP(plain, in, inLen)) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -145; @@ -4395,18 +4445,35 @@ int rsa_test(void) #ifndef NO_SHA256 XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -243; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, + + idx = ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -244; } + if (XMEMCMP(plain, in, inLen)) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -245; @@ -4414,53 +4481,104 @@ int rsa_test(void) /* check fails if not using the same optional label */ XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -246; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + + idx = ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + } + } while (ret == WC_PENDING_E); if (ret > 0) { /* in this case decrypt should fail */ TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -247; } + ret = 0; /* check using optional label with encrypt/decrypt */ XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -248; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + + idx = ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -249; } + if (XMEMCMP(plain, in, inLen)) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -250; } - #ifndef NO_SHA + #ifndef NO_SHA /* check fail using mismatch hash algorithms */ XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, in, sizeof(in)); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); + #endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, in, sizeof(in)); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -251; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, - WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + + idx = ret; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); + #endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, sizeof(in)); + } + } while (ret == WC_PENDING_E); if (ret > 0) { /* should fail */ TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -252; } + ret = 0; #endif /* NO_SHA*/ #endif /* NO_SHA256 */ @@ -4471,18 +4589,35 @@ int rsa_test(void) BAD_FUNC_ARG is returned when this case is not met */ if (wc_RsaEncryptSize(&key) > ((int)SHA512_DIGEST_SIZE * 2) + 2) { XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); + #endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -343; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, + + idx = ret; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); + #endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -344; } + if (XMEMCMP(plain, in, inLen)) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -345; @@ -4492,18 +4627,35 @@ int rsa_test(void) /* check using pkcsv15 padding with _ex API */ XMEMSET(plain, 0, sizeof(plain)); - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -443; } - ret = wc_RsaPrivateDecrypt_ex(out, ret, plain, sizeof(plain), &key, + + idx = ret; + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_RsaAsyncWait(ret, &key); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0); + } + } while (ret == WC_PENDING_E); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -444; } + if (XMEMCMP(plain, in, inLen)) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -445; @@ -4540,7 +4692,10 @@ int rsa_test(void) InitDecodedCert(&cert, tmp, (word32)bytes, 0); ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); - if (ret != 0) return -491; + if (ret != 0) { + free(tmp); + return -491; + } FreeDecodedCert(&cert); #else @@ -4568,7 +4723,7 @@ int rsa_test(void) fclose(file); #endif /* USE_CERT_BUFFERS */ - ret = wc_InitRsaKey(&keypub, 0); + ret = wc_InitRsaKey(&keypub, HEAP_HINT); if (ret != 0) { TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -51; @@ -5367,7 +5522,7 @@ int rsa_test(void) bytes = fread(tmp, 1, FOURK_BUF, caFile); fclose(caFile); - ret = wc_InitRsaKey(&caKey, 0); + ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { TEST_XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); TEST_XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -5652,9 +5807,7 @@ int rsa_test(void) #ifdef WOLFSSL_CERT_EXT wc_FreeRsaKey(&keypub); #endif -#ifdef HAVE_CAVIUM - wc_RsaFreeCavium(&key); -#endif + TEST_XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRng(&rng); diff --git a/wolfcrypt/user-crypto/include/user_rsa.h b/wolfcrypt/user-crypto/include/user_rsa.h index 72d2c610e..771982fa8 100644 --- a/wolfcrypt/user-crypto/include/user_rsa.h +++ b/wolfcrypt/user-crypto/include/user_rsa.h @@ -76,6 +76,7 @@ typedef struct RsaKey { } RsaKey; WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); +WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, diff --git a/wolfcrypt/user-crypto/src/rsa.c b/wolfcrypt/user-crypto/src/rsa.c index 974789ce7..8beb6bf8c 100644 --- a/wolfcrypt/user-crypto/src/rsa.c +++ b/wolfcrypt/user-crypto/src/rsa.c @@ -74,7 +74,7 @@ enum { }; -int wc_InitRsaKey(RsaKey* key, void* heap) +int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) { USER_DEBUG(("Entering wc_InitRsaKey\n")); @@ -87,10 +87,16 @@ int wc_InitRsaKey(RsaKey* key, void* heap) USER_DEBUG(("\tExit wc_InitRsaKey\n")); + (void)devId; (void)heap; return 0; } +int wc_InitRsaKey(RsaKey* key, void* heap) +{ + return wc_InitRsaKey_ex(key, heap, INVALID_DEVID); +} + /* three functions needed for cert and key gen */ #if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) diff --git a/wolfssl-ntru.vcproj b/wolfssl-ntru.vcproj index b427e9c0a..a9f5c4577 100755 --- a/wolfssl-ntru.vcproj +++ b/wolfssl-ntru.vcproj @@ -322,6 +322,10 @@ RelativePath=".\wolfcrypt\src\wc_encrypt.c" > + + + + + diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 4f484aa6b..bdf8f5bab 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -142,7 +142,6 @@ enum wolfSSL_ErrorCodes { UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */ - ASYNC_NOT_PENDING = -408, /* Async operation not pending */ RSA_KEY_SIZE_E = -409, /* RSA key too small */ ECC_KEY_SIZE_E = -410, /* ECC key too small */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ac6f062f8..3a3e00635 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -155,7 +155,7 @@ #endif #ifdef WOLFSSL_ASYNC_CRYPT - #include + #include #endif #ifdef _MSC_VER @@ -1059,8 +1059,6 @@ enum Misc { HASH_SIG_SIZE = 2, /* default SHA1 RSA */ - NO_CAVIUM_DEVICE = -2, /* invalid cavium device id */ - NO_COPY = 0, /* should we copy static buffer for write */ COPY = 1 /* should we copy static buffer for write */ }; @@ -1899,20 +1897,6 @@ WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name); #endif /* HAVE_QSH */ -#ifdef HAVE_WOLF_EVENT -typedef struct { - WOLF_EVENT* head; /* head of queue */ - WOLF_EVENT* tail; /* tail of queue */ -#ifndef SINGLE_THREADED - wolfSSL_Mutex lock; /* queue lock */ -#endif -} WOLF_EVENT_QUEUE; - -WOLFSSL_LOCAL int wolfSSL_EventInit(WOLFSSL* ssl, WOLF_EVENT_TYPE type); - -WOLFSSL_LOCAL int wolfSSL_CTX_EventPush(WOLFSSL_CTX* ctx, WOLF_EVENT* event); -#endif /* HAVE_WOLF_EVENT */ - #ifdef WOLFSSL_STATIC_MEMORY WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap); #endif @@ -2002,9 +1986,7 @@ struct WOLFSSL_CTX { #ifdef HAVE_OCSP WOLFSSL_OCSP ocsp; #endif -#ifdef HAVE_CAVIUM - int devId; /* cavium device id to use */ -#endif + int devId; /* async device id to use */ #ifdef HAVE_TLS_EXTENSIONS TLSX* extensions; /* RFC 6066 TLS Extensions data */ #ifndef NO_WOLFSSL_SERVER @@ -2314,6 +2296,7 @@ enum AcceptState { enum KeyShareState { KEYSHARE_BEGIN = 0, KEYSHARE_BUILD, + KEYSHARE_DO, KEYSHARE_VERIFY, KEYSHARE_FINALIZE, KEYSHARE_END @@ -2326,6 +2309,7 @@ typedef struct Buffers { buffer domainName; /* for client check */ buffer clearOutputBuffer; buffer sig; /* signature data */ + buffer digest; /* digest data */ int prevSent; /* previous plain text bytes sent when got WANT_WRITE */ int plainSz; /* plain text bytes in buffer to send @@ -2683,7 +2667,8 @@ struct WOLFSSL { void* hsDoneCtx; /* user handshake cb context */ #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCrypt async; + AsyncCryptSSLState async; + AsyncCryptDev asyncDev; #endif void* sigKey; /* RsaKey or ecc_key allocated from heap */ word32 sigType; /* Type of sigKey */ @@ -2782,9 +2767,7 @@ struct WOLFSSL { #if defined(FORTRESS) || defined(HAVE_STUNNEL) void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ #endif -#ifdef HAVE_CAVIUM - int devId; /* cavium device id to use */ -#endif + int devId; /* async device id to use */ #ifdef HAVE_ONE_TIME_AUTH OneTimeAuth auth; #endif @@ -2846,9 +2829,6 @@ struct WOLFSSL { #ifdef HAVE_WOLF_EVENT WOLF_EVENT event; #endif /* HAVE_WOLF_EVENT */ -#ifdef WOLFSSL_ASYNC_CRYPT_TEST - AsyncCryptTests asyncCryptTest; -#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ }; @@ -3001,7 +2981,7 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); #ifndef NO_CERTS #ifndef NO_RSA WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, - const byte* sig, word32 sigSz, + byte* verifySig, word32 sigSz, const byte* plain, word32 plainSz, RsaKey* key); WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, @@ -3010,6 +2990,8 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); + WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); #endif /* !NO_RSA */ #ifdef HAVE_ECC @@ -3017,7 +2999,7 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); byte* out, word32* outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, - byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, + const byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, byte* out, word32* outSz); @@ -3132,7 +3114,7 @@ WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); #endif #ifdef HAVE_ECC - WOLFSSL_LOCAL int EccMakeTempKey(WOLFSSL* ssl); + WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer); #endif WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 1b84c4c80..2af2dfffa 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -31,6 +31,10 @@ #include #include +#ifdef HAVE_WOLF_EVENT + #include +#endif + #ifndef NO_FILESYSTEM #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #if MQX_USE_IO_OLD @@ -1416,9 +1420,9 @@ WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*); WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*); -/* cavium additions */ -WOLFSSL_API int wolfSSL_UseCavium(WOLFSSL*, int devId); -WOLFSSL_API int wolfSSL_CTX_UseCavium(WOLFSSL_CTX*, int devId); +/* async additions */ +WOLFSSL_API int wolfSSL_UseAsync(WOLFSSL*, int devId); +WOLFSSL_API int wolfSSL_CTX_UseAsync(WOLFSSL_CTX*, int devId); /* TLS Extensions */ @@ -1909,41 +1913,13 @@ WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr); WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl); #endif /* WOLFSSL_JNI */ -#ifdef HAVE_WOLF_EVENT -typedef enum WOLF_EVENT_TYPE { - WOLF_EVENT_TYPE_NONE, - #ifdef WOLFSSL_ASYNC_CRYPT - WOLF_EVENT_TYPE_ASYNC_ACCEPT, - WOLF_EVENT_TYPE_ASYNC_CONNECT, - WOLF_EVENT_TYPE_ASYNC_READ, - WOLF_EVENT_TYPE_ASYNC_WRITE, - WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_ACCEPT, - WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WRITE, - #endif -} WOLF_EVENT_TYPE; -typedef struct WOLF_EVENT WOLF_EVENT; -struct WOLF_EVENT { - WOLF_EVENT* next; /* To support event linked list */ - WOLFSSL* ssl; /* Reference back to SSL object */ - int ret; /* Async return code */ - WOLF_EVENT_TYPE type; - unsigned short pending:1; - unsigned short done:1; - /* Future event flags can go here */ -}; +#ifdef WOLFSSL_ASYNC_CRYPT +WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags); +WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount); +#endif /* WOLFSSL_ASYNC_CRYPT */ -enum WOLF_POLL_FLAGS { - WOLF_POLL_FLAG_CHECK_HW = 0x01, - WOLF_POLL_FLAG_PEEK = 0x02, -}; - -WOLFSSL_API int wolfSSL_CTX_poll(WOLFSSL_CTX* ctx, WOLF_EVENT* events, - int maxEvents, unsigned char flags, int* eventCount); -WOLFSSL_API int wolfSSL_poll(WOLFSSL* ssl, WOLF_EVENT* events, - int maxEvents, unsigned char flags, int* eventCount); - -#endif /* HAVE_WOLF_EVENT */ #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/test.h b/wolfssl/test.h index d8922b223..360d3e908 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -107,10 +107,11 @@ #define SNPRINTF snprintf #endif /* USE_WINDOWS_API */ +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif #ifdef HAVE_CAVIUM - #include "cavium_sysdep.h" - #include "cavium_common.h" - #include "cavium_ioctl.h" + #include #endif #ifdef _MSC_VER @@ -1218,29 +1219,6 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) #endif /* !NO_CERTS */ -#ifdef HAVE_CAVIUM - -static INLINE int OpenNitroxDevice(int dma_mode,int dev_id) -{ - Csp1CoreAssignment core_assign; - Uint32 device; - - if (CspInitialize(CAVIUM_DIRECT,CAVIUM_DEV_ID)) - return -1; - if (Csp1GetDevType(&device)) - return -1; - if (device != NPX_DEVICE) { - if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, - (Uint32 *)&core_assign)!= 0) - return -1; - } - CspShutdown(CAVIUM_DEV_ID); - - return CspInitialize(dma_mode, dev_id); -} - -#endif /* HAVE_CAVIUM */ - /* Wolf Root Directory Helper */ /* KEIL-RL File System does not support relative directory */ @@ -1974,24 +1952,6 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) #endif /* HAVE_SESSION_TICKET && CHACHA20 && POLY1305 */ -#ifdef WOLFSSL_ASYNC_CRYPT - static INLINE int AsyncCryptPoll(WOLFSSL* ssl) - { - int ret, eventCount = 0; - WOLF_EVENT events[1]; - - printf("Connect/Accept got WC_PENDING_E\n"); - - ret = wolfSSL_poll(ssl, events, sizeof(events)/sizeof(WOLF_EVENT), - WOLF_POLL_FLAG_CHECK_HW, &eventCount); - if (ret == 0 && eventCount > 0) { - ret = 1; /* Success */ - } - - return ret; - } -#endif - static INLINE word16 GetRandomPort(void) { word16 port = 0; diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 125d63b94..8d91f4367 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -39,10 +39,6 @@ #endif #ifndef HAVE_FIPS /* to avoid redefinition of macros */ -#ifdef HAVE_CAVIUM - #include - #include "cavium_common.h" -#endif #ifdef WOLFSSL_AESNI @@ -74,7 +70,10 @@ #endif #ifndef HAVE_FIPS /* to avoid redefinition of structures */ -#define WOLFSSL_AES_CAVIUM_MAGIC 0xBEEF0002 + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { AES_ENC_TYPE = 1, /* cipher unique type */ @@ -102,12 +101,12 @@ typedef struct Aes { #ifdef WOLFSSL_AESNI byte use_aesni; #endif /* WOLFSSL_AESNI */ -#ifdef HAVE_CAVIUM - AesType type; /* aes key type */ - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ -#endif +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; + #ifdef HAVE_CAVIUM + AesType type; /* aes key type */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AES_COUNTER word32 left; /* unused bytes left from last call */ #endif @@ -183,9 +182,9 @@ WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* authIn, word32 authInSz); #endif /* HAVE_AESCCM */ -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_AesInitCavium(Aes*, int); - WOLFSSL_API void wc_AesFreeCavium(Aes*); +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_API int wc_AesAsyncInit(Aes*, int); + WOLFSSL_API void wc_AesAsyncFree(Aes*); #endif #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/arc4.h b/wolfssl/wolfcrypt/arc4.h index a97430632..752f1d062 100644 --- a/wolfssl/wolfcrypt/arc4.h +++ b/wolfssl/wolfcrypt/arc4.h @@ -30,7 +30,9 @@ extern "C" { #endif -#define WOLFSSL_ARC4_CAVIUM_MAGIC 0xBEEF0001 +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { ARC4_ENC_TYPE = 4, /* cipher unique type */ @@ -42,19 +44,17 @@ typedef struct Arc4 { byte x; byte y; byte state[ARC4_STATE_SIZE]; -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; #endif } Arc4; WOLFSSL_API void wc_Arc4Process(Arc4*, byte*, const byte*, word32); WOLFSSL_API void wc_Arc4SetKey(Arc4*, const byte*, word32); -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_Arc4InitCavium(Arc4*, int); - WOLFSSL_API void wc_Arc4FreeCavium(Arc4*); +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_API int wc_Arc4AsyncInit(Arc4*, int); + WOLFSSL_API void wc_Arc4AsyncFree(Arc4*); #endif #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/des3.h b/wolfssl/wolfcrypt/des3.h index 370b52d44..07ddb1aaa 100644 --- a/wolfssl/wolfcrypt/des3.h +++ b/wolfssl/wolfcrypt/des3.h @@ -37,7 +37,10 @@ #endif #ifndef HAVE_FIPS /* to avoid redefinition of macros */ -#define WOLFSSL_3DES_CAVIUM_MAGIC 0xBEEF0003 + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { DES_ENC_TYPE = 2, /* cipher unique type */ @@ -76,10 +79,8 @@ typedef struct Des3 { word32 key[3][DES_KS_SIZE]; word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; #endif } Des3; #endif /* HAVE_FIPS */ @@ -102,9 +103,9 @@ WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in,word32 sz); -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_Des3_InitCavium(Des3*, int); - WOLFSSL_API void wc_Des3_FreeCavium(Des3*); +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_API int wc_Des3AsyncInit(Des3*, int); + WOLFSSL_API void wc_Des3AsyncFree(Des3*); #endif #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 9e82cb111..70d67e481 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -30,6 +30,10 @@ #include #include +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -230,6 +234,10 @@ typedef struct { ecc_point pubkey; /* public key */ mp_int k; /* private key */ void* heap; /* heap hint */ + +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; +#endif } ecc_key; @@ -275,7 +283,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, WOLFSSL_API int wc_ecc_init(ecc_key* key); WOLFSSL_API -int wc_ecc_init_h(ecc_key* key, void* heap); +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); WOLFSSL_API void wc_ecc_free(ecc_key* key); WOLFSSL_API @@ -421,6 +429,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #endif /* HAVE_ECC_ENCRYPT */ +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_API int wc_ecc_async_handle(ecc_key* key, + WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); + WOLFSSL_API int wc_ecc_async_wait(int ret, ecc_key* key); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index f165f27f5..d52c55acf 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -44,6 +44,9 @@ enum { CRYPTGEN_E = -104, /* windows crypt generation error */ RAN_BLOCK_E = -105, /* reading random device would block */ BAD_MUTEX_E = -106, /* Bad mutex operation */ + WC_TIMEOUT_E = -107, /* timeout error */ + WC_PENDING_E = -108, /* wolfCrypt operation pending (would block) */ + WC_NOT_PENDING_E = -109, /* wolfCrypt operation not pending */ MP_INIT_E = -110, /* mp_init error state */ MP_READ_E = -111, /* mp_read error state */ @@ -61,7 +64,6 @@ enum { MEMORY_E = -125, /* out of memory error */ VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */ - RSA_WRONG_TYPE_E = -130, /* RSA wrong block type for RSA function */ RSA_BUFFER_E = -131, /* RSA buffer error, output too small or input too large */ @@ -108,7 +110,7 @@ enum { AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */ AES_CCM_AUTH_E = -181, /* AES-CCM Authentication check failure */ - CAVIUM_INIT_E = -182, /* Cavium Init type error */ + ASYNC_INIT_E = -182, /* Async Init type error */ COMPRESS_INIT_E = -183, /* Compress init error */ COMPRESS_E = -184, /* Compress error */ @@ -121,7 +123,7 @@ enum { ASN_CRL_NO_SIGNER_E = -190, /* ASN CRL no signer to confirm failure */ ASN_OCSP_CONFIRM_E = -191, /* ASN OCSP signature confirm failure */ - BAD_ENC_STATE_E = -192, /* Bad ecc enc state operation */ + BAD_STATE_E = -192, /* Bad state operation */ BAD_PADDING_E = -193, /* Bad padding, msg not correct length */ REQ_ATTRIBUTE_E = -194, /* setting cert request attributes error */ @@ -169,7 +171,6 @@ enum { BAD_COND_E = -230, /* Bad condition variable operation */ SIG_TYPE_E = -231, /* Signature Type not enabled/available */ HASH_TYPE_E = -232, /* Hash Type not enabled/available */ - WC_PENDING_E = -233, /* wolfCrypt operation pending (would block) */ WC_KEY_SIZE_E = -234, /* Key size error, either too small or large */ ASN_COUNTRY_SIZE_E = -235, /* ASN Cert Gen, invalid country code size */ diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 37125cdcc..a2d2eca92 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -58,7 +58,7 @@ enum wc_HashType { #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ #endif -#ifndef NO_ASN +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); #endif diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 5311c92e0..46f0b6079 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -53,17 +53,15 @@ #include #endif -#ifdef HAVE_CAVIUM - #include - #include "cavium_common.h" -#endif - #ifdef __cplusplus extern "C" { #endif #ifndef HAVE_FIPS -#define WOLFSSL_HMAC_CAVIUM_MAGIC 0xBEEF0005 + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { HMAC_FIPS_MIN_KEY = 14, /* 112 bit key length minimum */ @@ -144,18 +142,18 @@ typedef struct Hmac { word32 ipad[HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ word32 opad[HMAC_BLOCK_SIZE / sizeof(word32)]; word32 innerHash[MAX_DIGEST_SIZE / sizeof(word32)]; -#ifdef HAVE_CAVIUM - word64 contextHandle; /* nitrox context memory handle */ - HashType type; /* hmac key type */ - word32 magic; /* using cavium magic */ - int devId; /* nitrox device id */ - void* heap /* heap hint , currently only used with cavium */ - byte* data; /* buffered input data for one call */ - word16 keyLen; /* hmac key length */ - word16 dataLen; -#endif - byte macType; /* md5 sha or sha256 */ - byte innerHashKeyed; /* keyed flag */ + void* heap; /* heap hint */ + byte macType; /* md5 sha or sha256 */ + byte innerHashKeyed; /* keyed flag */ +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; + #ifdef HAVE_CAVIUM + word16 keyLen; /* hmac key length */ + word16 dataLen; + HashType type; /* hmac key type */ + byte* data; /* buffered input data for one call */ + #endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ } Hmac; #endif /* HAVE_FIPS */ @@ -164,12 +162,14 @@ typedef struct Hmac { WOLFSSL_API int wc_HmacSetKey(Hmac*, int type, const byte* key, word32 keySz); WOLFSSL_API int wc_HmacUpdate(Hmac*, const byte*, word32); WOLFSSL_API int wc_HmacFinal(Hmac*, byte*); - -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_HmacInitCavium(Hmac*, int); - WOLFSSL_API void wc_HmacFreeCavium(Hmac*); +WOLFSSL_API int wc_HmacSizeByType(int type); +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_API int wc_HmacAsyncInit(Hmac*, int); + WOLFSSL_API void wc_HmacAsyncFree(Hmac*); #endif + + WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index cdce81c61..43d9c227b 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -56,10 +56,15 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/memory.h \ wolfssl/wolfcrypt/mpi_class.h \ wolfssl/wolfcrypt/mpi_superclass.h \ - wolfssl/wolfcrypt/mem_track.h + wolfssl/wolfcrypt/mem_track.h \ + wolfssl/wolfcrypt/wolfevent.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ wolfssl/wolfcrypt/port/ti/ti-hash.h \ wolfssl/wolfcrypt/port/ti/ti-ccm.h \ wolfssl/wolfcrypt/port/nrf51.h + +if BUILD_CAVIUM +noinst_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +endif diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 938fb2527..3c8a0020a 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -181,6 +181,9 @@ typedef int mp_err; typedef struct { int used, alloc, sign; mp_digit *dp; +#ifdef WOLFSSL_ASYNC_CRYPT + byte* dpraw; /* Used for hardware crypto */ +#endif } mp_int; /* callback for mp_prime_random, should fill dst with random bytes and return diff --git a/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h b/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h new file mode 100644 index 000000000..aed338f40 --- /dev/null +++ b/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h @@ -0,0 +1,165 @@ +/* cavium-nitrox.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _CAVIUM_NITROX_H_ +#define _CAVIUM_NITROX_H_ + +#ifdef HAVE_CAVIUM + +#include + +#ifndef HAVE_CAVIUM_V + #include "cavium_sysdep.h" +#endif +#include "cavium_common.h" +#ifndef HAVE_CAVIUM_V + #include "cavium_ioctl.h" +#else + #include "cavium_sym_crypto.h" + #include "cavium_asym_crypto.h" +#endif +#include + +#define CAVIUM_SSL_GRP 0 +#define CAVIUM_DPORT 256 + +/* Compatibility with older Cavium SDK's */ +#ifndef HAVE_CAVIUM_V + typedef int CspHandle; + typedef word32 CavReqId; + + #define AES_128 AES_128_BIT + #define AES_192 AES_192_BIT + #define AES_256 AES_256_BIT +#else + #define CAVIUM_DEV_ID 0 + #define CAVIUM_BLOCKING BLOCKING + #define CAVIUM_NON_BLOCKING NON_BLOCKING + #define CAVIUM_DIRECT DMA_DIRECT_DIRECT + typedef Uint64 CavReqId; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #define CAVIUM_REQ_MODE CAVIUM_NON_BLOCKING +#else + #define CAVIUM_REQ_MODE CAVIUM_BLOCKING +#endif + + +#ifdef WOLFSSL_ASYNC_CRYPT + #define CAVIUM_MAX_PENDING 90 + #define CAVIUM_MAX_POLL MAX_TO_POLL +#endif + + +typedef struct CaviumNitroxDev { + CspHandle devId; /* nitrox device id */ + ContextType type; /* Typically CONTEXT_SSL, but also ECC types */ + Uint64 contextHandle; /* nitrox context memory handle */ + CavReqId reqId; /* Current requestId */ +} CaviumNitroxDev; + +struct WOLF_EVENT; + + +/* Wrapper API's */ +WOLFSSL_LOCAL int NitroxTranslateResponseCode(int ret); +WOLFSSL_LOCAL CspHandle NitroxGetDeviceHandle(void); +WOLFSSL_LOCAL CspHandle NitroxOpenDevice(int dma_mode, int dev_id); +WOLFSSL_LOCAL int NitroxAllocContext(CaviumNitroxDev* nitrox, CspHandle devId, + ContextType type); +WOLFSSL_LOCAL void NitroxFreeContext(CaviumNitroxDev* nitrox); +WOLFSSL_LOCAL void NitroxCloseDevice(CspHandle devId); + +#if defined(WOLFSSL_ASYNC_CRYPT) +WOLFSSL_LOCAL int NitroxCheckRequest(CspHandle devId, CavReqId reqId); +WOLFSSL_LOCAL int NitroxCheckRequests(CspHandle devId, + CspMultiRequestStatusBuffer* req_stat_buf); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + +/* Crypto wrappers */ +#ifndef NO_RSA + struct RsaKey; + WOLFSSL_LOCAL int NitroxRsaExptMod( + const byte* in, word32 inLen, + byte* exponent, word32 expLen, + byte* modulus, word32 modLen, + byte* out, word32* outLen, struct RsaKey* key); + WOLFSSL_LOCAL int NitroxRsaPublicEncrypt(const byte* in, word32 inLen, + byte* out, word32 outLen, struct RsaKey* key); + WOLFSSL_LOCAL int NitroxRsaPrivateDecrypt(const byte* in, word32 inLen, + byte* out, word32 outLen, struct RsaKey* key); + WOLFSSL_LOCAL int NitroxRsaSSL_Sign(const byte* in, word32 inLen, + byte* out, word32 outLen, struct RsaKey* key); + WOLFSSL_LOCAL int NitroxRsaSSL_Verify(const byte* in, word32 inLen, + byte* out, word32 outLen, struct RsaKey* key); +#endif /* !NO_RSA */ + +#ifndef NO_AES + struct Aes; + WOLFSSL_LOCAL int NitroxAesSetKey(struct Aes* aes, const byte* key, + word32 length, const byte* iv); + #ifdef HAVE_AES_CBC + WOLFSSL_LOCAL int NitroxAesCbcEncrypt(struct Aes* aes, byte* out, + const byte* in, word32 length); + #ifdef HAVE_AES_DECRYPT + WOLFSSL_LOCAL int NitroxAesCbcDecrypt(struct Aes* aes, byte* out, + const byte* in, word32 length); + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + +#ifndef NO_RC4 + struct Arc4; + WOLFSSL_LOCAL void NitroxArc4SetKey(struct Arc4* arc4, const byte* key, + word32 length); + WOLFSSL_LOCAL void NitroxArc4Process(struct Arc4* arc4, byte* out, + const byte* in, word32 length); +#endif /* !NO_RC4 */ + +#ifndef NO_DES3 + struct Des3; + WOLFSSL_LOCAL int NitroxDes3SetKey(struct Des3* des3, const byte* key, + const byte* iv); + WOLFSSL_LOCAL int NitroxDes3CbcEncrypt(struct Des3* des3, byte* out, + const byte* in, word32 length); + WOLFSSL_LOCAL int NitroxDes3CbcDecrypt(struct Des3* des3, byte* out, + const byte* in, word32 length); +#endif /* !NO_DES3 */ + +#ifndef NO_HMAC + struct Hmac; + WOLFSSL_LOCAL int NitroxHmacFinal(struct Hmac* hmac, byte* hash); + WOLFSSL_LOCAL int NitroxHmacUpdate(struct Hmac* hmac, const byte* msg, + word32 length); + WOLFSSL_LOCAL int NitroxHmacSetKey(struct Hmac* hmac, int type, + const byte* key, word32 length); +#endif /* NO_HMAC */ + +#if !defined(HAVE_HASHDRBG) && !defined(NO_RC4) + WOLFSSL_API void NitroxRngGenerateBlock(WC_RNG* rng, byte* output, word32 sz); +#endif + + +#endif /* HAVE_CAVIUM */ + +#endif /* _CAVIUM_NITROX_H_ */ diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index e8d63257a..64889f15e 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -101,7 +101,9 @@ struct WC_RNG { #else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ -#define WOLFSSL_RNG_CAVIUM_MAGIC 0xBEEF0004 +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif /* secure Random Number Generator */ @@ -111,9 +113,8 @@ struct WC_RNG { #ifndef NO_RC4 Arc4 cipher; #endif -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; #endif }; @@ -131,13 +132,6 @@ struct WC_RNG { WOLFSSL_LOCAL int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_InitRngCavium(WC_RNG*, int); -#endif - -#endif /* HAVE_HASH_DRBG || NO_RC4 */ #ifdef HAVE_WNR /* Whitewood netRandom client library */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 6e51e9fbe..491692057 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -52,42 +52,54 @@ /* avoid redefinition of structs */ #if !defined(HAVE_FIPS) -#define WOLFSSL_RSA_CAVIUM_MAGIC 0xBEEF0006 + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif enum { RSA_PUBLIC = 0, RSA_PRIVATE = 1, -}; + RSA_TYPE_UNKNOWN = -1, + RSA_PUBLIC_ENCRYPT = 0, + RSA_PUBLIC_DECRYPT = 1, + RSA_PRIVATE_ENCRYPT = 2, + RSA_PRIVATE_DECRYPT = 3, + + RSA_BLOCK_TYPE_1 = 1, + RSA_BLOCK_TYPE_2 = 2, + + RSA_MIN_SIZE = 512, + RSA_MAX_SIZE = 4096, + + RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */ +}; /* RSA */ typedef struct RsaKey { mp_int n, e, d, p, q, dP, dQ, u; int type; /* public or private */ void* heap; /* for user memory overrides */ + int state; + byte* tmp; + word32 tmpLen; #ifdef WC_RSA_BLINDING WC_RNG* rng; /* for PrivateDecrypt blinding */ #endif -#ifdef HAVE_CAVIUM - int devId; /* nitrox device id */ - word32 magic; /* using cavium magic */ - word64 contextHandle; /* nitrox context memory handle */ - byte* c_n; /* cavium byte buffers for key parts */ - byte* c_e; - byte* c_d; - byte* c_p; - byte* c_q; - byte* c_dP; - byte* c_dQ; - byte* c_u; /* sizes in bytes */ - word16 c_nSz, c_eSz, c_dSz, c_pSz, c_qSz, c_dP_Sz, c_dQ_Sz, c_uSz; -#endif +#ifdef WOLFSSL_ASYNC_CRYPT + AsyncCryptDev asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ } RsaKey; #endif /*HAVE_FIPS */ -WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); +WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); +WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); +WOLFSSL_LOCAL int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng); + WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng); WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, @@ -120,6 +132,7 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); */ /* Mask Generation Function Identifiers */ +#define WC_MGF1NONE 0 #define WC_MGF1SHA1 26 #define WC_MGF1SHA256 1 #define WC_MGF1SHA384 2 @@ -147,11 +160,13 @@ WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); #endif -#ifdef HAVE_CAVIUM - WOLFSSL_API int wc_RsaInitCavium(RsaKey*, int); - WOLFSSL_API void wc_RsaFreeCavium(RsaKey*); +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_API int wc_RsaAsyncHandle(RsaKey* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); + WOLFSSL_API int wc_RsaAsyncWait(int ret, RsaKey* key); #endif + #endif /* HAVE_USER_RSA */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index ad95b6137..55de9030f 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1235,9 +1235,10 @@ static char *fgets(char *buff, int sz, FILE *fp) /* Make sure wolf events are enabled */ #undef HAVE_WOLF_EVENT #define HAVE_WOLF_EVENT -#else - #ifdef WOLFSSL_ASYNC_CRYPT_TEST - #error Must have WOLFSSL_ASYNC_CRYPT enabled with WOLFSSL_ASYNC_CRYPT_TEST + + #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \ + !defined(WOLFSSL_ASYNC_CRYPT_TEST) + #error No async hardware defined with WOLFSSL_ASYNC_CRYPT! #endif #endif /* WOLFSSL_ASYNC_CRYPT */ diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index e44e7dbf3..4d1661f99 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -289,6 +289,9 @@ typedef struct { int size; #endif fp_digit dp[FP_SIZE]; +#ifdef WOLFSSL_ASYNC_CRYPT + byte *dpraw; /* Used for hardware crypto */ +#endif } fp_int; /* externally define this symbol to ignore the default settings, useful for changing the build from the make process */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index ff5d41e95..b6e91b8aa 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -312,8 +312,8 @@ DYNAMIC_TYPE_ECC = 37, DYNAMIC_TYPE_TMP_BUFFER = 38, DYNAMIC_TYPE_DTLS_MSG = 39, - DYNAMIC_TYPE_CAVIUM_TMP = 40, - DYNAMIC_TYPE_CAVIUM_RSA = 41, + DYNAMIC_TYPE_ASYNC_TMP = 40, + DYNAMIC_TYPE_ASYNC_RSA = 41, DYNAMIC_TYPE_X509 = 42, DYNAMIC_TYPE_TLSX = 43, DYNAMIC_TYPE_OCSP = 44, @@ -376,6 +376,9 @@ return 1 if a match otherwise 0 */ #define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings()) + /* invalid device id */ + #define INVALID_DEVID -2 + #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/wolfevent.h b/wolfssl/wolfcrypt/wolfevent.h new file mode 100644 index 000000000..5dbf16450 --- /dev/null +++ b/wolfssl/wolfcrypt/wolfevent.h @@ -0,0 +1,103 @@ +/* wolfevent.h + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _WOLF_EVENT_H_ +#define _WOLF_EVENT_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef SINGLE_THREADED + #include +#endif + +typedef struct WOLFSSL WOLFSSL; +typedef struct WOLF_EVENT WOLF_EVENT; +typedef struct WOLFSSL_CTX WOLFSSL_CTX; + +typedef unsigned short WOLF_EVENT_FLAG; + +typedef enum WOLF_EVENT_TYPE { + WOLF_EVENT_TYPE_NONE, + #ifdef WOLFSSL_ASYNC_CRYPT + WOLF_EVENT_TYPE_ASYNC_ANY, + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, + WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, + #endif +} WOLF_EVENT_TYPE; + +struct WOLF_EVENT { + /* double linked list */ + WOLF_EVENT* next; + WOLF_EVENT* prev; + + void* context; +#ifdef HAVE_CAVIUM + word64 reqId; +#endif + int ret; /* Async return code */ + WOLF_EVENT_TYPE type; + WOLF_EVENT_FLAG pending:1; + WOLF_EVENT_FLAG done:1; + /* Future event flags can go here */ +}; + +enum WOLF_POLL_FLAGS { + WOLF_POLL_FLAG_CHECK_HW = 0x01, +}; + +typedef struct { + WOLF_EVENT* head; /* head of queue */ + WOLF_EVENT* tail; /* tail of queue */ +#ifndef SINGLE_THREADED + wolfSSL_Mutex lock; /* queue lock */ +#endif + int count; +} WOLF_EVENT_QUEUE; + + +#ifdef HAVE_WOLF_EVENT + +/* Event */ +WOLFSSL_API int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context); +WOLFSSL_API int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags); + +/* Event Queue */ +WOLFSSL_API int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue); +WOLFSSL_API int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); +WOLFSSL_API int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event); +WOLFSSL_API int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); +WOLFSSL_API int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, + WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount); +WOLFSSL_API int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue); +WOLFSSL_API void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue); + +#endif /* HAVE_WOLF_EVENT */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLF_EVENT_H_ */ From 3e6be9bf2c1b9984be8c67a23ecc9a092f050aab Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 15 Aug 2016 14:07:16 -0600 Subject: [PATCH 2/3] Fix in "wc_InitRsaKey_ex" for normal math so mp_init isn't called to defer allocation. --- wolfcrypt/src/rsa.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index cff7477a4..f5f65541f 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -193,6 +193,13 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) else #endif { + /* For normal math defer the memory allocations */ + #ifndef USE_FAST_MATH + key->n.dp = key->e.dp = 0; /* public alloc parts */ + key->d.dp = key->p.dp = 0; /* private alloc parts */ + key->q.dp = key->dP.dp = 0; + key->u.dp = key->dQ.dp = 0; + #else mp_init(&key->n); mp_init(&key->e); mp_init(&key->d); @@ -201,6 +208,7 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) mp_init(&key->dP); mp_init(&key->dQ); mp_init(&key->u); + #endif /* USE_FAST_MATH */ } return ret; From a9278fe492547bb553f36a5cf86dd40e1059ce4b Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 23 Aug 2016 11:31:15 -0700 Subject: [PATCH 3/3] Added check for GetLength result in asn GetIntRsa function. Fixed return code in random.c for "wolfAsync_DevCtxInit" due to copy/paste error. Added RSA wc_RsaCleanup to make sure allocated tmp buffer is always free'd. Eliminated invalid RSA key type checks and "RSA_CHECK_KEYTYPE". --- wolfcrypt/src/asn.c | 11 +++++--- wolfcrypt/src/random.c | 2 +- wolfcrypt/src/rsa.c | 57 ++++++++++++++++++----------------------- wolfssl/wolfcrypt/rsa.h | 3 ++- 4 files changed, 35 insertions(+), 38 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 59d89b882..884e66ae5 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -692,10 +692,13 @@ static int GetIntRsa(RsaKey* key, mp_int* mpi, const byte* input, if (GetLength(input, &i, &length, maxIdx) < 0) return ASN_PARSE_E; - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + if (length > 0) { + /* remove leading zero */ + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index efcd3a570..75ba61a8f 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -810,7 +810,7 @@ int wc_InitRng(WC_RNG* rng) #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, INVALID_DEVID); - if (ret != 0) return -2007; + if (ret != 0) return ret; #endif #ifdef WOLFSSL_SMALL_STACK diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index f5f65541f..e7fa4b9f4 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -38,7 +38,7 @@ Possible RSA enable options: * WOLFSSL_KEY_GEN: Allows Private Key Generation default: off * RSA_LOW_MEM: NON CRT Private Operations, less memory default: off * WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined) - * RSA_CHECK_KEYTYPE: RSA check key type default: off + */ /* @@ -165,6 +165,23 @@ enum { RSA_STATE_DECRYPT_RES, }; +static void wc_RsaCleanup(RsaKey* key) +{ + if (key && key->tmp) { + /* make sure any allocated memory is free'd */ + if (key->tmpIsAlloc) { + if (key->type == RSA_PRIVATE_DECRYPT || + key->type == RSA_PRIVATE_ENCRYPT) { + ForceZero(key->tmp, key->tmpLen); + } + XFREE(key->tmp, key->heap, DYNAMIC_TYPE_RSA); + key->tmpIsAlloc = 0; + } + key->tmp = NULL; + key->tmpLen = 0; + } +} + int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) { int ret = 0; @@ -180,6 +197,7 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) key->heap = heap; key->tmp = NULL; key->tmpLen = 0; + key->tmpIsAlloc = 0; #ifdef WOLFSSL_ASYNC_CRYPT if (devId != INVALID_DEVID) { @@ -227,6 +245,8 @@ int wc_FreeRsaKey(RsaKey* key) return BAD_FUNC_ARG; } + wc_RsaCleanup(key); + #ifdef WOLFSSL_ASYNC_CRYPT if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { ret = FreeAsyncRsaKey(key); @@ -791,13 +811,13 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, switch (padType) { case WC_RSA_PKCSV15_PAD: - //WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); break; #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - //WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, optLabel, labelLen, heap); break; @@ -1159,16 +1179,6 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, return RSA_BUFFER_E; } - /* Optional key type check (disabled by default) */ - /* Note: internal tests allow private to be used as public */ -#ifdef RSA_CHECK_KEYTYPE - if ((rsa_type == RSA_PUBLIC_ENCRYPT && key->type != RSA_PUBLIC) || - (rsa_type == RSA_PRIVATE_ENCRYPT && key->type != RSA_PRIVATE)) { - WOLFSSL_MSG("Wrong RSA Encrypt key type"); - return RSA_WRONG_TYPE_E; - } -#endif - switch (key->state) { case RSA_STATE_NONE: case RSA_STATE_ENCRYPT_PAD: @@ -1251,16 +1261,6 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, return ret; } - /* Optional key type check (disabled by default) */ - /* Note: internal tests allow private to be used as public */ -#ifdef RSA_CHECK_KEYTYPE - if ((rsa_type == RSA_PUBLIC_DECRYPT && key->type != RSA_PUBLIC) || - (rsa_type == RSA_PRIVATE_DECRYPT && key->type != RSA_PRIVATE)) { - WOLFSSL_MSG("Wrong RSA Decrypt key type"); - return RSA_WRONG_TYPE_E; - } -#endif - switch (key->state) { case RSA_STATE_NONE: case RSA_STATE_DECRYPT_EXPTMOD: @@ -1296,6 +1296,7 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, key->tmpLen = inLen; if (outPtr == NULL) { key->tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); + key->tmpIsAlloc = 1; if (key->tmp == NULL) { ERROR_OUT(MEMORY_E); } @@ -1353,15 +1354,7 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, done: key->state = RSA_STATE_NONE; - if (key->tmp) { - /* if not inline */ - if (outPtr == NULL) { - ForceZero(key->tmp, key->tmpLen); - XFREE(key->tmp, key->heap, DYNAMIC_TYPE_RSA); - } - key->tmp = NULL; - key->tmpLen = 0; - } + wc_RsaCleanup(key); return ret; } diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 491692057..79b787014 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -82,8 +82,9 @@ typedef struct RsaKey { int type; /* public or private */ void* heap; /* for user memory overrides */ int state; - byte* tmp; + byte* tmp; /* temp buffer for async RSA */ word32 tmpLen; + byte tmpIsAlloc; #ifdef WC_RSA_BLINDING WC_RNG* rng; /* for PrivateDecrypt blinding */ #endif