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_ */