From 4edcbc79c19a32cd8e9c25ce7e76e905b20232e3 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 19 Dec 2016 12:15:10 -0800 Subject: [PATCH] RipeMd and Sha224 added to unit test. --- .cproject | 2 +- .gitignore | 30 +- IDE/ARDUINO/wolfssl-arduino.sh | 11 + IDE/HEXIWEAR/wolfSSL_HW/.cproject | 143 + .../wolfSSL_HW/.cwGeneratedFileSetLog | 19 + IDE/HEXIWEAR/wolfSSL_HW/.project | 50 + ...freescale.processorexpert.derivative.prefs | 2 + IDE/HEXIWEAR/wolfSSL_HW/user_settings.h | 6 + IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp | 6 + IDE/IAR-EWARM/Projects/user_settings.h | 1 + IDE/INTIME-RTOS/README.md | 158 + IDE/INTIME-RTOS/include.am | 13 + IDE/INTIME-RTOS/libwolfssl.c | 20 + IDE/INTIME-RTOS/libwolfssl.vcxproj | 225 + IDE/INTIME-RTOS/user_settings.h | 511 + IDE/INTIME-RTOS/wolfExamples.c | 619 + IDE/INTIME-RTOS/wolfExamples.h | 47 + IDE/INTIME-RTOS/wolfExamples.sln | 31 + IDE/INTIME-RTOS/wolfExamples.vcxproj | 100 + IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h | 25 +- IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp | 28 +- IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp | 28 +- IDE/WIN/wolfssl-fips.vcxproj | 4 +- IDE/WORKBENCH/README.md | 12 +- IDE/include.am | 3 +- Makefile.am | 13 +- README | 118 +- README.md | 120 +- autogen.sh | 14 + certs/crl/crl2.pem | 80 + certs/crl/include.am | 3 +- certs/dsaparams.pem | 9 + certs/ecc-privkey.pem | 4 + certs/external/ca-verisign-g5.pem | 14 + certs/include.am | 9 +- certs/renewcerts.sh | 34 + certs/renewcerts/wolfssl.cnf | 22 + certs/server-keyPkcs8.der | Bin 0 -> 1219 bytes certs/test/cert-ext-ia.cfg | 18 + certs/test/cert-ext-ia.der | Bin 0 -> 1030 bytes certs/test/cert-ext-nc.cfg | 18 + certs/test/cert-ext-nc.der | Bin 0 -> 1052 bytes certs/test/cert-ext-ns.der | Bin 0 -> 4677 bytes certs/test/digsigku.pem | 41 +- certs/test/gen-ext-certs.sh | 69 + certs/test/include.am | 13 + certs/test/server-duplicate-policy.pem | 182 + configure.ac | 344 +- cyassl/ctaocrypt/settings.h | 2 +- cyassl/openssl/include.am | 1 + cyassl/openssl/ssl23.h | 3 + examples/client/client.c | 830 +- examples/echoclient/echoclient.c | 124 +- examples/echoserver/echoserver.c | 142 +- examples/server/server.c | 439 +- fips-check.sh | 55 +- gencertbuf.pl | 1 + mcapi/crypto.c | 12 +- mcapi/crypto.h | 34 +- mcapi/mcapi_test.c | 45 +- mplabx/benchmark_main.c | 2 +- rpm/spec.in | 15 +- scripts/include.am | 4 + scripts/openssl.test | 13 +- scripts/tls13.test | 312 + src/bio.c | 446 + src/crl.c | 294 +- src/include.am | 6 +- src/internal.c | 8526 ++++---- src/io.c | 1166 +- src/keys.c | 454 +- src/ocsp.c | 609 +- src/sniffer.c | 332 +- src/ssl.c | 16031 ++++++++++------ src/tls.c | 3675 +++- src/tls13.c | 5557 ++++++ support/wolfssl.pc | 2 +- tests/api.c | 2959 ++- tests/hash.c | 70 +- tests/include.am | 1 + tests/srp.c | 34 +- tests/suites.c | 243 +- tests/test-dtls.conf | 215 +- tests/test-sig.conf | 11 + tests/test-tls13.conf | 95 + tests/test.conf | 124 +- tests/unit.c | 9 +- testsuite/testsuite.c | 4 +- tirtos/README | 3 + tirtos/packages/ti/net/wolfssl/package.bld | 1 + wolfcrypt/benchmark/benchmark.c | 3564 ++-- wolfcrypt/benchmark/benchmark.h | 6 +- wolfcrypt/src/aes.c | 1198 +- wolfcrypt/src/arc4.c | 46 +- wolfcrypt/src/asn.c | 3689 ++-- wolfcrypt/src/blake2b.c | 15 + wolfcrypt/src/cmac.c | 11 - wolfcrypt/src/coding.c | 3 +- wolfcrypt/src/des3.c | 1522 +- wolfcrypt/src/dh.c | 767 +- wolfcrypt/src/dsa.c | 76 +- wolfcrypt/src/ecc.c | 2686 ++- wolfcrypt/src/ed25519.c | 12 +- wolfcrypt/src/error.c | 20 +- wolfcrypt/src/evp.c | 539 + wolfcrypt/src/fe_low_mem.c | 18 +- wolfcrypt/src/fe_operations.c | 8 +- wolfcrypt/src/fe_x25519_128.i | 612 + wolfcrypt/src/ge_operations.c | 1550 +- wolfcrypt/src/hash.c | 404 +- wolfcrypt/src/hmac.c | 988 +- wolfcrypt/src/include.am | 12 +- wolfcrypt/src/integer.c | 275 +- wolfcrypt/src/logging.c | 341 +- wolfcrypt/src/md4.c | 11 - wolfcrypt/src/md5.c | 429 +- wolfcrypt/src/memory.c | 58 +- wolfcrypt/src/misc.c | 41 +- wolfcrypt/src/pkcs12.c | 34 +- wolfcrypt/src/pkcs7.c | 1406 +- wolfcrypt/src/poly1305.c | 24 +- wolfcrypt/src/port/arm/armv8-aes.c | 60 +- wolfcrypt/src/port/arm/armv8-sha256.c | 66 +- wolfcrypt/src/port/cavium/README.md | 33 +- wolfcrypt/src/port/cavium/cavium_nitrox.c | 778 - wolfcrypt/src/port/intel/README.md | 3 + wolfcrypt/src/port/nxp/ksdk_port.c | 374 +- wolfcrypt/src/port/ti/ti-aes.c | 3 + wolfcrypt/src/port/ti/ti-ccm.c | 51 +- wolfcrypt/src/port/ti/ti-hash.c | 204 +- wolfcrypt/src/pwdbased.c | 101 +- wolfcrypt/src/random.c | 1161 +- wolfcrypt/src/ripemd.c | 40 +- wolfcrypt/src/rsa.c | 675 +- wolfcrypt/src/sha.c | 206 +- wolfcrypt/src/sha256.c | 2574 +-- wolfcrypt/src/sha512.c | 1639 +- wolfcrypt/src/signature.c | 44 +- wolfcrypt/src/srp.c | 18 +- wolfcrypt/src/tfm.c | 343 +- wolfcrypt/src/wc_encrypt.c | 2 + wolfcrypt/src/wc_port.c | 1364 +- wolfcrypt/src/wolfevent.c | 31 +- wolfcrypt/src/wolfmath.c | 272 + wolfcrypt/test/test.c | 8029 +++++--- wolfcrypt/test/test.h | 4 + wolfcrypt/user-crypto/src/rsa.c | 82 +- wolfssl-ntru.vcproj | 4 + wolfssl.vcproj | 4 + wolfssl.vcxproj | 1 + wolfssl/certs_test.h | 126 + wolfssl/crl.h | 4 +- wolfssl/error-ssl.h | 14 +- wolfssl/include.am | 3 +- wolfssl/internal.h | 671 +- wolfssl/io.h | 413 + wolfssl/ocsp.h | 50 + wolfssl/openssl/aes.h | 73 + wolfssl/openssl/bn.h | 5 +- wolfssl/openssl/crypto.h | 7 +- wolfssl/openssl/des.h | 4 +- wolfssl/openssl/dsa.h | 8 +- wolfssl/openssl/ec.h | 13 +- wolfssl/openssl/ecdsa.h | 8 +- wolfssl/openssl/evp.h | 196 +- wolfssl/openssl/hmac.h | 3 + wolfssl/openssl/include.am | 2 + wolfssl/openssl/md5.h | 11 +- wolfssl/openssl/ocsp.h | 43 + wolfssl/openssl/opensslv.h | 2 +- wolfssl/openssl/pem.h | 27 +- wolfssl/openssl/rsa.h | 8 +- wolfssl/openssl/sha.h | 22 +- wolfssl/openssl/ssl.h | 378 +- wolfssl/openssl/ssl23.h | 1 + wolfssl/ssl.h | 717 +- wolfssl/test.h | 316 +- wolfssl/version.h | 4 +- wolfssl/wolfcrypt/aes.h | 41 +- wolfssl/wolfcrypt/arc4.h | 13 +- wolfssl/wolfcrypt/asn.h | 129 +- wolfssl/wolfcrypt/asn_public.h | 44 +- wolfssl/wolfcrypt/coding.h | 3 +- wolfssl/wolfcrypt/des3.h | 20 +- wolfssl/wolfcrypt/dh.h | 34 +- wolfssl/wolfcrypt/dsa.h | 4 +- wolfssl/wolfcrypt/ecc.h | 191 +- wolfssl/wolfcrypt/error-crypt.h | 18 +- wolfssl/wolfcrypt/fe_operations.h | 6 +- wolfssl/wolfcrypt/hash.h | 29 +- wolfssl/wolfcrypt/hmac.h | 73 +- wolfssl/wolfcrypt/include.am | 15 +- wolfssl/wolfcrypt/integer.h | 190 +- wolfssl/wolfcrypt/logging.h | 39 +- wolfssl/wolfcrypt/md5.h | 38 +- wolfssl/wolfcrypt/mem_track.h | 9 +- wolfssl/wolfcrypt/memory.h | 14 +- wolfssl/wolfcrypt/misc.h | 15 + wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h | 165 - wolfssl/wolfcrypt/port/nxp/ksdk_port.h | 19 +- wolfssl/wolfcrypt/port/ti/ti-hash.h | 40 +- wolfssl/wolfcrypt/random.h | 100 +- wolfssl/wolfcrypt/ripemd.h | 6 +- wolfssl/wolfcrypt/rsa.h | 35 +- wolfssl/wolfcrypt/settings.h | 205 +- wolfssl/wolfcrypt/sha.h | 44 +- wolfssl/wolfcrypt/sha256.h | 29 +- wolfssl/wolfcrypt/sha512.h | 18 + wolfssl/wolfcrypt/tfm.h | 186 +- wolfssl/wolfcrypt/types.h | 264 +- wolfssl/wolfcrypt/wc_port.h | 64 +- wolfssl/wolfcrypt/wolfevent.h | 39 +- wolfssl/wolfcrypt/wolfmath.h | 69 + wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs | 29 + wrapper/python/wolfcrypt/wolfcrypt/random.py | 8 +- 215 files changed, 63617 insertions(+), 26408 deletions(-) create mode 100644 IDE/HEXIWEAR/wolfSSL_HW/.cproject create mode 100644 IDE/HEXIWEAR/wolfSSL_HW/.cwGeneratedFileSetLog create mode 100644 IDE/HEXIWEAR/wolfSSL_HW/.project create mode 100644 IDE/HEXIWEAR/wolfSSL_HW/.settings/com.freescale.processorexpert.derivative.prefs create mode 100644 IDE/HEXIWEAR/wolfSSL_HW/user_settings.h create mode 100755 IDE/INTIME-RTOS/README.md create mode 100644 IDE/INTIME-RTOS/include.am create mode 100755 IDE/INTIME-RTOS/libwolfssl.c create mode 100755 IDE/INTIME-RTOS/libwolfssl.vcxproj create mode 100755 IDE/INTIME-RTOS/user_settings.h create mode 100755 IDE/INTIME-RTOS/wolfExamples.c create mode 100755 IDE/INTIME-RTOS/wolfExamples.h create mode 100755 IDE/INTIME-RTOS/wolfExamples.sln create mode 100755 IDE/INTIME-RTOS/wolfExamples.vcxproj create mode 100644 certs/crl/crl2.pem create mode 100644 certs/dsaparams.pem create mode 100644 certs/ecc-privkey.pem create mode 100644 certs/server-keyPkcs8.der create mode 100644 certs/test/cert-ext-ia.cfg create mode 100644 certs/test/cert-ext-ia.der create mode 100644 certs/test/cert-ext-nc.cfg create mode 100644 certs/test/cert-ext-nc.der create mode 100644 certs/test/cert-ext-ns.der create mode 100644 certs/test/gen-ext-certs.sh create mode 100644 certs/test/include.am create mode 100644 certs/test/server-duplicate-policy.pem create mode 100644 cyassl/openssl/ssl23.h create mode 100755 scripts/tls13.test create mode 100644 src/bio.c mode change 100644 => 100755 src/crl.c mode change 100644 => 100755 src/internal.c mode change 100644 => 100755 src/ssl.c mode change 100644 => 100755 src/tls.c create mode 100644 src/tls13.c create mode 100644 tests/test-tls13.conf mode change 100644 => 100755 wolfcrypt/src/aes.c mode change 100755 => 100644 wolfcrypt/src/asn.c mode change 100644 => 100755 wolfcrypt/src/des3.c mode change 100644 => 100755 wolfcrypt/src/dh.c mode change 100644 => 100755 wolfcrypt/src/ecc.c create mode 100644 wolfcrypt/src/evp.c mode change 100644 => 100755 wolfcrypt/src/fe_operations.c create mode 100644 wolfcrypt/src/fe_x25519_128.i mode change 100644 => 100755 wolfcrypt/src/hmac.c mode change 100644 => 100755 wolfcrypt/src/md5.c delete mode 100644 wolfcrypt/src/port/cavium/cavium_nitrox.c create mode 100644 wolfcrypt/src/port/intel/README.md mode change 100755 => 100644 wolfcrypt/src/random.c mode change 100644 => 100755 wolfcrypt/src/rsa.c mode change 100644 => 100755 wolfcrypt/src/sha.c mode change 100644 => 100755 wolfcrypt/src/sha256.c mode change 100644 => 100755 wolfcrypt/src/sha512.c mode change 100644 => 100755 wolfcrypt/src/wc_port.c create mode 100644 wolfcrypt/src/wolfmath.c mode change 100644 => 100755 wolfssl/internal.h create mode 100644 wolfssl/io.h create mode 100644 wolfssl/openssl/aes.h create mode 100644 wolfssl/openssl/ssl23.h mode change 100644 => 100755 wolfssl/wolfcrypt/aes.h mode change 100644 => 100755 wolfssl/wolfcrypt/logging.h delete mode 100644 wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h mode change 100644 => 100755 wolfssl/wolfcrypt/types.h create mode 100644 wolfssl/wolfcrypt/wolfmath.h diff --git a/.cproject b/.cproject index b93835e250..1db9a198ef 100644 --- a/.cproject +++ b/.cproject @@ -66,7 +66,7 @@ - + diff --git a/.gitignore b/.gitignore index b22328702c..551cad8f95 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,12 @@ src/async.c wolfssl/async.h wolfcrypt/src/async.c wolfssl/wolfcrypt/async.h +wolfcrypt/src/port/intel/quickassist.c +wolfcrypt/src/port/intel/quickassist_mem.c +wolfcrypt/src/port/cavium/cavium_nitrox.c +wolfssl/wolfcrypt/port/intel/quickassist.h +wolfssl/wolfcrypt/port/intel/quickassist_mem.h +wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h ctaocrypt/benchmark/benchmark ctaocrypt/test/testctaocrypt wolfcrypt/benchmark/benchmark @@ -64,6 +70,7 @@ testsuite/testsuite tests/unit testsuite/testsuite.test tests/unit.test +tests/bio_write_test.txt testsuite/*.der testsuite/*.pem testsuite/*.raw @@ -84,7 +91,18 @@ ecc-key.pem certreq.der certreq.pem pkcs7cert.der -pkcs7signedData.der +pkcs7signedData_RSA_SHA.der +pkcs7signedData_RSA_SHA_noattr.der +pkcs7signedData_RSA_SHA224.der +pkcs7signedData_RSA_SHA256.der +pkcs7signedData_RSA_SHA384.der +pkcs7signedData_RSA_SHA512.der +pkcs7signedData_ECDSA_SHA.der +pkcs7signedData_ECDSA_SHA_noattr.der +pkcs7signedData_ECDSA_SHA224.der +pkcs7signedData_ECDSA_SHA256.der +pkcs7signedData_ECDSA_SHA384.der +pkcs7signedData_ECDSA_SHA512.der pkcs7envelopedDataDES3.der pkcs7envelopedDataAES128CBC.der pkcs7envelopedDataAES192CBC.der @@ -188,4 +206,12 @@ wolfcrypt/user-crypto/lib/libusercrypto.* wrapper/CSharp/x64/ # Visual Studio Code Workspace Files -*.vscode \ No newline at end of file +*.vscode + +IDE/INTIME-RTOS/Debug_* + +# Hexiwear +IDE/HEXIWEAR/wolfSSL_HW/Debug + +# Binaries +wolfcrypt/src/port/intel/qat_test diff --git a/IDE/ARDUINO/wolfssl-arduino.sh b/IDE/ARDUINO/wolfssl-arduino.sh index d076ea7a12..4da3ff4b6d 100755 --- a/IDE/ARDUINO/wolfssl-arduino.sh +++ b/IDE/ARDUINO/wolfssl-arduino.sh @@ -13,3 +13,14 @@ if [ "$DIR" = "ARDUINO" ]; then else echo "ERROR: You must be in the IDE/ARDUINO directory to run this script" fi + +#UPDATED: 19 Apr 2017 to remove bio.c and evp.c from the root directory since +# they are included inline and should not be compiled directly + +ARDUINO_DIR=${PWD} +cd ../../ +rm bio.c +rm evp.c +cd $ARDUINO_DIR +# end script in the origin directory for any future functionality that may be added. +#End UPDATE: 19 Apr 2017 diff --git a/IDE/HEXIWEAR/wolfSSL_HW/.cproject b/IDE/HEXIWEAR/wolfSSL_HW/.cproject new file mode 100644 index 0000000000..72574db960 --- /dev/null +++ b/IDE/HEXIWEAR/wolfSSL_HW/.cproject @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/HEXIWEAR/wolfSSL_HW/.cwGeneratedFileSetLog b/IDE/HEXIWEAR/wolfSSL_HW/.cwGeneratedFileSetLog new file mode 100644 index 0000000000..8d1a66f61e --- /dev/null +++ b/IDE/HEXIWEAR/wolfSSL_HW/.cwGeneratedFileSetLog @@ -0,0 +1,19 @@ +Sources/main.c +Project_Settings/Linker_Files/MK64FN1M0xxx12_flash.ld +SDK/platform/CMSIS/Include/core_cmSimd.h +SDK/platform/devices/MK64F12/include/MK64F12.h +SDK/platform/CMSIS/Include/arm_common_tables.h +SDK/platform/CMSIS/Include/arm_const_structs.h +SDK/platform/devices/MK64F12/include/MK64F12_features.h +SDK/platform/CMSIS/Include/core_cm4.h +SDK/platform/CMSIS/Include/core_cmFunc.h +SDK/platform/CMSIS/Include/core_cmInstr.h +SDK/platform/devices/fsl_device_registers.h +SDK/platform/devices/MK64F12/include/fsl_bitaccess.h +SDK/platform/CMSIS/Include/arm_math.h +SDK/platform/devices/MK64F12/include/MK64F12_extension.h +Project_Settings/Startup_Code/startup.c +Project_Settings/Startup_Code/system_MK64F12.c +Project_Settings/Startup_Code/startup.h +Project_Settings/Startup_Code/startup_MK64F12.S +Project_Settings/Startup_Code/system_MK64F12.h \ No newline at end of file diff --git a/IDE/HEXIWEAR/wolfSSL_HW/.project b/IDE/HEXIWEAR/wolfSSL_HW/.project new file mode 100644 index 0000000000..44527e1af3 --- /dev/null +++ b/IDE/HEXIWEAR/wolfSSL_HW/.project @@ -0,0 +1,50 @@ + + + wolfSSL_HW + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + src + 2 + $%7BPARENT-3-PROJECT_LOC%7D/src + + + wolfcrypt + 2 + $%7BPARENT-3-PROJECT_LOC%7D/wolfcrypt + + + wolfssl + 2 + $%7BPARENT-3-PROJECT_LOC%7D/wolfssl + + + + + PROJECT_KSDK_PATH + file:/.KSDK_1.3.0 + + + diff --git a/IDE/HEXIWEAR/wolfSSL_HW/.settings/com.freescale.processorexpert.derivative.prefs b/IDE/HEXIWEAR/wolfSSL_HW/.settings/com.freescale.processorexpert.derivative.prefs new file mode 100644 index 0000000000..60d5016ea5 --- /dev/null +++ b/IDE/HEXIWEAR/wolfSSL_HW/.settings/com.freescale.processorexpert.derivative.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +versionGenerated/versionGenerated=1.0.0.RT7_b1550-0615 diff --git a/IDE/HEXIWEAR/wolfSSL_HW/user_settings.h b/IDE/HEXIWEAR/wolfSSL_HW/user_settings.h new file mode 100644 index 0000000000..6649009577 --- /dev/null +++ b/IDE/HEXIWEAR/wolfSSL_HW/user_settings.h @@ -0,0 +1,6 @@ +#define FREESCALE_KSDK_BM +#define FREESCALE_KSDK_1_3 +#define FSL_HW_CRYPTO_MANUAL_SELECTION +#define NO_MAIN_DRIVER +#define USE_CERT_BUFFERS_1024 +#define ECC_USER_CURVES diff --git a/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp b/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp index 61982d7047..219a61c9aa 100644 --- a/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp +++ b/IDE/IAR-EWARM/Projects/lib/wolfSSL-Lib.ewp @@ -2040,6 +2040,12 @@ $PROJ_DIR$\..\..\..\..\wolfcrypt\src\wc_port.c + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\wolfmath.c + + + $PROJ_DIR$\..\..\..\..\wolfcrypt\src\wolfevent.c + wolfSSL diff --git a/IDE/IAR-EWARM/Projects/user_settings.h b/IDE/IAR-EWARM/Projects/user_settings.h index 5e4f36e9a1..2652f6df17 100644 --- a/IDE/IAR-EWARM/Projects/user_settings.h +++ b/IDE/IAR-EWARM/Projects/user_settings.h @@ -8,6 +8,7 @@ #define NO_DEV_RANDOM #define USE_CERT_BUFFERS_2048 #define WOLFSSL_USER_CURRTIME +#define SIZEOF_LONG_LONG 8 #define CUSTOM_RAND_GENERATE custom_rand_generate /* warning "write a real random seed!!!!, just for testing now" */ diff --git a/IDE/INTIME-RTOS/README.md b/IDE/INTIME-RTOS/README.md new file mode 100755 index 0000000000..9d5d7bdfc4 --- /dev/null +++ b/IDE/INTIME-RTOS/README.md @@ -0,0 +1,158 @@ +# tenAsys INtime RTOS Port + +## Overview + +This port is for the tenAsys INtime RTOS available [here](http://www.tenasys.com/intime). + +To enable use the define `INTIME_RTOS`. + +## Usage + +The wolfExamples.sln is a Visual Studio 2015 project. You must have the INtime SDK installed and an INtime RTOS agent running. + +The default configuration is set inside the `IDE/INTIME-RTOS/user_settings.h` file. + +The example application provides a simple menu interface to select difference application functions to test. + +``` +wolfExamples started +wolfExamples finished initialization + + MENU + + t. WolfCrypt Test + b. WolfCrypt Benchmark + c. WolfSSL Client Example + s. WolfSSL Server Example + l. WolfSSL Localhost Client/Server Example +Please select one of the above options: +``` + +### `t`wolfCrypt Test + +Performs testing of all crypto algorithms. + +``` +Crypt Test +error test passed! +base64 test passed! +base64 test passed! +MD5 test passed! +SHA test passed! +SHA-256 test passed! +SHA-384 test passed! +SHA-512 test passed! +Hash test passed! +HMAC-MD5 test passed! +HMAC-SHA test passed! +HMAC-SHA256 test passed! +HMAC-SHA384 test passed! +HMAC-SHA512 test passed! +HMAC-KDF test passed! +X963-KDF test passed! +GMAC test passed! +Chacha test passed! +POLY1305 test passed! +ChaCha20-Poly1305 AEAD test passed! +DES test passed! +DES3 test passed! +AES test passed! +AES-GCM test passed! +AES-CCM test passed! +AES Key Wrap test passed! +RANDOM test passed! +RSA test passed! +DH test passed! +DSA test passed! +SRP test passed! +PWDBASED test passed! +openSSL extra test +OPENSSL test passed! +ECC test passed! +ECC Enc test passed! +ECC buffer test passed! +CURVE25519 test passed! +ED25519 test passed! +CMAC test passed! +PKCS7enveloped test passed! +PKCS7signed test passed! +PKCS7encrypted test passed! +mutex test passed! +memcb test passed! +Crypt Test: Return code 0 +``` + +### `b` wolfCrypt Benchmark + +Performs benchmark of crypto algorithms. + +``` +Benchmark Test +RNG 25 kB took 0.002 seconds, 11.017 MB/s +AES enc 25 kB took 0.002 seconds, 15.090 MB/s +AES dec 25 kB took 0.002 seconds, 15.119 MB/s +AES-GCM 25 kB took 0.003 seconds, 9.433 MB/s +AES-CTR 25 kB took 0.001 seconds, 22.378 MB/s +AES-CCM 25 kB took 0.002 seconds, 15.306 MB/s +CHACHA 25 kB took 0.002 seconds, 16.063 MB/s +CHA-POLY 25 kB took 0.001 seconds, 20.447 MB/s +3DES 25 kB took 0.002 seconds, 10.717 MB/s + +MD5 25 kB took 0.00 seconds, 31.576 MB/s +POLY1305 25 kB took 0.000 seconds, 201.575 MB/s +SHA 25 kB took 0.00 seconds, 43.761 MB/s +SHA-256 25 kB took 0.001 seconds, 19.299 MB/s +SHA-384 25 kB took 0.002 seconds, 14.577 MB/s +SHA-512 25 kB took 0.001 seconds, 21.718 MB/s +AES-CMAC 25 kB took 0.00 seconds, 34.925 MB/s + +RSA 2048 public 2.445 milliseconds, avg over 1 iterations +RSA 2048 private 64.711 milliseconds, avg over 1 iterations + +RSA 1024 key generation 318.755 milliseconds, avg over 5 iterations +RSA 2048 key generation 22648.396 milliseconds, avg over 5 iterations +DH 2048 key generation 23.119 milliseconds, avg over 1 iterations +DH 2048 key agreement 26.756 milliseconds, avg over 1 iterations + +ECC 256 key generation 2.984 milliseconds, avg over 5 iterations +EC-DHE key agreement 2.967 milliseconds, avg over 5 iterations +EC-DSA sign time 1.448 milliseconds, avg over 5 iterations +EC-DSA verify time 3.304 milliseconds, avg over 5 iterations +ECC encrypt 5.860 milliseconds, avg over 1 iterations +ECC decrypt 6.360 milliseconds, avg over 1 iterations + +CURVE25519 256 key generation 1.416 milliseconds, avg over 5 iterations +CURVE25519 key agreement 1.332 milliseconds, avg over 5 iterations + +ED25519 key generation 0.320 milliseconds, avg over 5 iterations +ED25519 sign time 0.595 milliseconds, avg over 5 iterations +ED25519 verify time 1.310 milliseconds, avg over 5 iterations +Benchmark Test: Return code 0 +``` + +### `c` wolfSSL Client + +To configure the host address and port modify the `TLS_HOST_REMOTE` and `TLS_PORT` macros at top of `wolfExamples.c`. This example uses TLS 1.2 to connect to a remote host. + +### `s` wolfSSL Server + +To configure the port to listen on modify `TLS_PORT` at top of `wolfExamples.c`. + +### `l` wolfSSL Localhost Server/Client + +Starts a TLS server thread listening on localhost. Starts the TLS client and performs connect, exchanges some data and disconnects. + +``` +Waiting for a connection... +Client connected successfully +Using Non-Blocking I/O: 0 +Message for server: Client: + +Received: I hear ya fa shizzle! + +The client has closed the connection. +``` + +## References + +For more information please contact info@wolfssl.com. diff --git a/IDE/INTIME-RTOS/include.am b/IDE/INTIME-RTOS/include.am new file mode 100644 index 0000000000..5828c76ec1 --- /dev/null +++ b/IDE/INTIME-RTOS/include.am @@ -0,0 +1,13 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +EXTRA_DIST += \ + IDE/INTIME-RTOS/README.md \ + IDE/INTIME-RTOS/user_settings.h \ + IDE/INTIME-RTOS/libwolfssl.c \ + IDE/INTIME-RTOS/libwolfssl.vcxproj \ + IDE/INTIME-RTOS/wolfExamples.c \ + IDE/INTIME-RTOS/wolfExamples.h \ + IDE/INTIME-RTOS/wolfExamples.vcxproj \ + IDE/INTIME-RTOS/wolfExamples.sln diff --git a/IDE/INTIME-RTOS/libwolfssl.c b/IDE/INTIME-RTOS/libwolfssl.c new file mode 100755 index 0000000000..94d39bb24b --- /dev/null +++ b/IDE/INTIME-RTOS/libwolfssl.c @@ -0,0 +1,20 @@ +// libwolfssl.c +// Defines the entry point for the DLL application + +#include + +BOOLEAN __stdcall RslMain( RTHANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) { + case RSL_PROCESS_ATTACH: + case RSL_THREAD_ATTACH: + case RSL_THREAD_DETACH: + case RSL_PROCESS_DETACH: + break; + } + + return TRUE; +} diff --git a/IDE/INTIME-RTOS/libwolfssl.vcxproj b/IDE/INTIME-RTOS/libwolfssl.vcxproj new file mode 100755 index 0000000000..155da63aa5 --- /dev/null +++ b/IDE/INTIME-RTOS/libwolfssl.vcxproj @@ -0,0 +1,225 @@ + + + + + Debug + INtime + + + Release + INtime + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {1731767D-573F-45C9-A466-191DA0D180CF} + 8.1 + + + + StaticLibrary + NotSet + v140 + + + StaticLibrary + false + NotSet + v140 + + + + + + + + + + + + $(Configuration)_$(ProjectName)\ + + + $(Configuration)_$(ProjectName)\ + + + + + + 21076.20052 + /SAFESEH:NO %(AdditionalOptions) + rt.lib;pcibus.lib;netlib.lib;clib.lib;vshelper.lib + $(SolutionDir)$(Configuration)\\libwolfssl.rsl + + + Async + _USRDLL;WOLFSSL_DLL;BUILDING_WOLFSSL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + $(ProjectDir);$(ProjectDir)..\..\;%(AdditionalIncludeDirectories) + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir)vc$(PlatformToolsetVersion).pdb + + + + + + + 21076.20052 + /SAFESEH:NO %(AdditionalOptions) + rt.lib;pcibus.lib;netlib.lib;clib.lib;vshelper.lib + $(SolutionDir)$(Configuration)\\libwolfssl.rsl + + + Async + _USRDLL;WOLFSSL_DLL;BUILDING_WOLFSSL;WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + $(ProjectDir);$(ProjectDir)..\..\;%(AdditionalIncludeDirectories) + $(IntDir) + $(IntDir) + $(IntDir) + $(IntDir)vc$(PlatformToolsetVersion).pdb + + + + + + diff --git a/IDE/INTIME-RTOS/user_settings.h b/IDE/INTIME-RTOS/user_settings.h new file mode 100755 index 0000000000..8458f38141 --- /dev/null +++ b/IDE/INTIME-RTOS/user_settings.h @@ -0,0 +1,511 @@ +/* Example custom user settings for wolfSSL and INtime RTOS port */ + +#ifndef WOLFSSL_USER_SETTINGS_H +#define WOLFSSL_USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------------- */ +/* Port - Platform */ +/* ------------------------------------------------------------------------- */ +#undef INTIME_RTOS +#define INTIME_RTOS + +#undef WOLF_EXAMPLES_STACK +#define WOLF_EXAMPLES_STACK 65536 + +#undef WOLFSSL_GENERAL_ALIGNMENT +#define WOLFSSL_GENERAL_ALIGNMENT 4 + +/* platform already has min()/max() */ +#undef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN +#undef WOLFSSL_HAVE_MAX +#define WOLFSSL_HAVE_MAX + +/* disable directory support */ +#undef NO_WOLFSSL_DIR +#define NO_WOLFSSL_DIR + +/* disable writev */ +#undef NO_WRITEV +#define NO_WRITEV + +/* we provide main entry point */ +#undef NO_MAIN_DRIVER +#define NO_MAIN_DRIVER + +/* if using in single threaded mode */ +#undef SINGLE_THREADED +//#define SINGLE_THREADED +/* Note: HAVE_THREAD_LS is not support for INtime RTOS */ + +/* reduces stack usage, by using malloc/free for stack variables over 100 bytes */ +#undef WOLFSSL_SMALL_STACK +//#define WOLFSSL_SMALL_STACK + + +/* ------------------------------------------------------------------------- */ +/* Math Configuration */ +/* ------------------------------------------------------------------------- */ +/* fast math uses stack and inline assembly to speed up math */ +#undef USE_FAST_MATH +#define USE_FAST_MATH + +#ifdef USE_FAST_MATH + /* timing resistance for side-channel attack protection */ + #undef TFM_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT +#endif + + +/* ------------------------------------------------------------------------- */ +/* Crypto */ +/* ------------------------------------------------------------------------- */ +/* ECC */ +#if 1 + #undef HAVE_ECC + #define HAVE_ECC + + /* Support for custom curves */ + #define WOLFSSL_CUSTOM_CURVES + + /* Curve types */ + //#define NO_ECC_SECP + #define HAVE_ECC_SECPR2 + #define HAVE_ECC_SECPR3 + #define HAVE_ECC_BRAINPOOL + #define HAVE_ECC_KOBLITZ + + /* Curve sizes */ + #undef HAVE_ALL_CURVES + //#define HAVE_ALL_CURVES + #ifndef HAVE_ALL_CURVES + /* allows enabling custom curve sizes */ + #undef ECC_USER_CURVES + #define ECC_USER_CURVES + + //#define HAVE_ECC112 + //#define HAVE_ECC128 + //#define HAVE_ECC160 + #define HAVE_ECC192 + #define HAVE_ECC224 + //#define NO_ECC256 + #define HAVE_ECC384 + #define HAVE_ECC521 + #endif + + /* Fixed point cache (speeds repeated operations against same private key) */ + #undef FP_ECC + #define FP_ECC + #ifdef FP_ECC + /* Bits / Entries */ + #undef FP_ENTRIES + #define FP_ENTRIES 2 + #undef FP_LUT + #define FP_LUT 4 + #endif + + /* Optional ECC calculation method */ + /* Note: doubles heap usage, but slightly faster */ + #undef ECC_SHAMIR + #define ECC_SHAMIR + + /* Reduces heap usage, but slower */ + /* timing resistance for side-channel attack protection */ + #undef ECC_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + + #ifdef USE_FAST_MATH + /* use reduced size math buffers for ecc points */ + #undef ALT_ECC_SIZE + #define ALT_ECC_SIZE + + /* Enable TFM optimizations for ECC */ + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #define TFM_ECC192 + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #define TFM_ECC224 + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #define TFM_ECC256 + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #define TFM_ECC384 + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define TFM_ECC521 + #endif + #endif +#endif + +/* RSA */ +#undef NO_RSA +#if 1 + #ifdef USE_FAST_MATH + /* Maximum math bits (Max RSA key bits * 2) */ + #undef FP_MAX_BITS + #define FP_MAX_BITS 4096 + #endif + + /* half as much memory but twice as slow */ + #undef RSA_LOW_MEM + //#define RSA_LOW_MEM + + /* RSA blinding countermeasures */ + #undef WC_RSA_BLINDING + #define WC_RSA_BLINDING +#else + #define NO_RSA +#endif + +/* AES */ +#undef NO_AES +#if 1 + #undef HAVE_AESGCM + #define HAVE_AESGCM + + #ifdef HAVE_AESGCM + /* GCM Method: GCM_SMALL, GCM_WORD32 or GCM_TABLE */ + //#define GCM_SMALL + #define GCM_TABLE + #endif + + #undef WOLFSSL_AES_COUNTER + #define WOLFSSL_AES_COUNTER + + #undef HAVE_AESCCM + #define HAVE_AESCCM + + #undef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + + #undef HAVE_AES_KEYWRAP + #define HAVE_AES_KEYWRAP +#else + #define NO_AES +#endif + +/* ChaCha20 / Poly1305 */ +#undef HAVE_CHACHA +#undef HAVE_POLY1305 +#if 1 + #define HAVE_CHACHA + #define HAVE_POLY1305 + + /* Needed for Poly1305 */ + #undef HAVE_ONE_TIME_AUTH + #define HAVE_ONE_TIME_AUTH +#endif + +/* Ed25519 / Curve25519 */ +#undef HAVE_CURVE25519 +#undef HAVE_ED25519 +#if 1 + #define HAVE_CURVE25519 + #define HAVE_ED25519 + + /* Optionally use small math (less flash usage, but much slower) */ + #if 0 + #define CURVED25519_SMALL + #endif +#endif + + +/* ------------------------------------------------------------------------- */ +/* Hashing */ +/* ------------------------------------------------------------------------- */ +/* Sha */ +#undef NO_SHA +#if 1 + /* 1k smaller, but 25% slower */ + //#define USE_SLOW_SHA +#else + #define NO_SHA +#endif + +/* Sha256 */ +#undef NO_SHA256 +#if 1 +#else + #define NO_SHA256 +#endif + +/* Sha512 */ +#undef WOLFSSL_SHA512 +#if 1 + #define WOLFSSL_SHA512 + + /* Sha384 */ + #undef WOLFSSL_SHA384 + #if 1 + #define WOLFSSL_SHA384 + #endif + + /* over twice as small, but 50% slower */ + //#define USE_SLOW_SHA2 +#endif + +/* MD5 */ +#undef NO_MD5 +#if 1 +#else + #define NO_MD5 +#endif + + +/* ------------------------------------------------------------------------- */ +/* Enable Features */ +/* ------------------------------------------------------------------------- */ +#undef KEEP_PEER_CERT +#define KEEP_PEER_CERT + +#undef HAVE_COMP_KEY +#define HAVE_COMP_KEY + +#undef HAVE_ECC_ENCRYPT +#define HAVE_ECC_ENCRYPT + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SUPPORTED_CURVES +#define HAVE_SUPPORTED_CURVES + +#undef HAVE_EXTENDED_MASTER +#define HAVE_EXTENDED_MASTER + +#undef WOLFSSL_DTLS +#define WOLFSSL_DTLS + +#undef OPENSSL_EXTRA +#define OPENSSL_EXTRA + +#undef WOLFSSL_BASE64_ENCODE +#define WOLFSSL_BASE64_ENCODE + +#undef HAVE_HKDF +#define HAVE_HKDF + +#undef WOLFSSL_CMAC +#define WOLFSSL_CMAC + +#undef WOLFSSL_KEY_GEN +#define WOLFSSL_KEY_GEN + +#undef WOLFSSL_CERT_GEN +#define WOLFSSL_CERT_GEN + +#undef WOLFSSL_CERT_REQ +#define WOLFSSL_CERT_REQ + +#undef WOLFSSL_CERT_EXT +#define WOLFSSL_CERT_EXT + +#undef HAVE_PK_CALLBACKS +#define HAVE_PK_CALLBACKS + +#undef HAVE_ALPN +#define HAVE_ALPN + +#undef HAVE_SNI +#define HAVE_SNI + +#undef HAVE_MAX_FRAGMENT +#define HAVE_MAX_FRAGMENT + +#undef HAVE_TRUNCATED_HMAC +#define HAVE_TRUNCATED_HMAC + +#undef SESSION_CERTS +#define SESSION_CERTS + +#undef HAVE_SESSION_TICKET +#define HAVE_SESSION_TICKET + +#undef WOLFCRYPT_HAVE_SRP +#define WOLFCRYPT_HAVE_SRP + +#undef WOLFSSL_HAVE_CERT_SERVICE +#define WOLFSSL_HAVE_CERT_SERVICE + +#undef HAVE_PKCS7 +#define HAVE_PKCS7 + +#undef HAVE_X963_KDF +#define HAVE_X963_KDF + +#undef WOLFSSL_HAVE_WOLFSCEP +#define WOLFSSL_HAVE_WOLFSCEP + +#undef WOLFSSL_ALWAYS_KEEP_SNI +#define WOLFSSL_ALWAYS_KEEP_SNI + +#undef WOLFSSL_ALWAYS_VERIFY_CB +#define WOLFSSL_ALWAYS_VERIFY_CB + +#undef WOLFSSL_SEP +#define WOLFSSL_SEP + +#undef ATOMIC_USER +#define ATOMIC_USER + +#undef HAVE_OCSP +#define HAVE_OCSP + +#undef HAVE_CERTIFICATE_STATUS_REQUEST +#define HAVE_CERTIFICATE_STATUS_REQUEST + +#undef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +#define HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +#undef HAVE_CRL +#define HAVE_CRL + +#undef PERSIST_CERT_CACHE +//#define PERSIST_CERT_CACHE + +#undef PERSIST_SESSION_CACHE +//#define PERSIST_SESSION_CACHE + +#undef WOLFSSL_DER_LOAD +//#define WOLFSSL_DER_LOAD + +#undef WOLFSSL_DES_ECB +//#define WOLFSSL_DES_ECB + +#undef HAVE_CAMELLIA +//#define HAVE_CAMELLIA + +#undef HAVE_NULL_CIPHER +//#define HAVE_NULL_CIPHER + +#undef WOLFSSL_RIPEMD +//#define WOLFSSL_RIPEMD + + +/* TLS Session Cache */ +#if 1 + #define SMALL_SESSION_CACHE + //#define MEDIUM_SESSION_CACHE + //#define BIG_SESSION_CACHE + //#define HUGE_SESSION_CACHE +#else + #define NO_SESSION_CACHE +#endif + + +/* ------------------------------------------------------------------------- */ +/* Disable Features */ +/* ------------------------------------------------------------------------- */ +#undef NO_WOLFSSL_SERVER +//#define NO_WOLFSSL_SERVER + +#undef NO_WOLFSSL_CLIENT +//#define NO_WOLFSSL_CLIENT + +/* disables TLS 1.0/1.1 support */ +#undef NO_OLD_TLS +//#define NO_OLD_TLS + +/* disable access to filesystem */ +#undef NO_FILESYSTEM +//#define NO_FILESYSTEM + +#undef NO_RC4 +#define NO_RC4 + +#undef NO_HC128 +#define NO_HC128 + +#undef NO_RABBIT +#define NO_RABBIT + +#undef NO_MD4 +#define NO_MD4 + +/* Pre-shared keys */ +#undef NO_PSK +//#define NO_PSK + +#undef NO_DSA +//#define NO_DSA + +#undef NO_DH +//#define NO_DH + +#undef NO_DES3 +//#define NO_DES3 + +#undef NO_PWDBASED +//#define NO_PWDBASED + +/* encoding/decoding support */ +#undef NO_CODING +//#define NO_CODING + +/* memory wrappers and memory callbacks */ +#undef NO_WOLFSSL_MEMORY +//#define NO_WOLFSSL_MEMORY + +/* In-lining of misc.c functions */ +/* If defined, must include wolfcrypt/src/misc.c in build */ +/* Slower, but about 1k smaller */ +#undef NO_INLINE +//#define NO_INLINE + + + +/* ------------------------------------------------------------------------- */ +/* Benchmark / Test */ +/* ------------------------------------------------------------------------- */ +#undef NO_CRYPT_TEST +//#define NO_CRYPT_TEST + +#undef NO_CRYPT_BENCHMARK +//#define NO_CRYPT_BENCHMARK + +/* Use reduced benchmark / test sizes */ +#undef BENCH_EMBEDDED +#define BENCH_EMBEDDED + +#undef USE_CERT_BUFFERS_2048 +#define USE_CERT_BUFFERS_2048 + +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 + + + +/* ------------------------------------------------------------------------- */ +/* Debugging */ +/* ------------------------------------------------------------------------- */ +#undef DEBUG_WOLFSSL +//#define DEBUG_WOLFSSL +#ifdef DEBUG_WOLFSSL + /* Use this to measure / print heap usage */ + #if 0 + #undef USE_WOLFSSL_MEMORY + #define USE_WOLFSSL_MEMORY + + #undef WOLFSSL_TRACK_MEMORY + #define WOLFSSL_TRACK_MEMORY + #endif + + /* Math debugging (adds support for mp_dump) */ + #undef WOLFSSL_DEBUG_MATH + //#define WOLFSSL_DEBUG_MATH +#else + #undef NO_ERROR_STRINGS + //#define NO_ERROR_STRINGS +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* WOLFSSL_USER_SETTINGS_H */ diff --git a/IDE/INTIME-RTOS/wolfExamples.c b/IDE/INTIME-RTOS/wolfExamples.c new file mode 100755 index 0000000000..72520eedca --- /dev/null +++ b/IDE/INTIME-RTOS/wolfExamples.c @@ -0,0 +1,619 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wolfExamples.h" +#include +#include +#include +#include +#include + + +/***************************************************************************** + * Globals + ****************************************************************************/ +RTHANDLE hRootProcess; +DWORD dwKtickInUsecs; +INIT_STRUCT gInit; +static int gServerExit = 0; +static int gServerReady = 0; + +static const char menu1[] = "\r\n" + "\tt. WolfCrypt Test\r\n" + "\tb. WolfCrypt Benchmark\r\n" + "\tc. WolfSSL Client Example\r\n" + "\ts. WolfSSL Server Example\r\n" + "\tl. WolfSSL Localhost Client/Server Example\r\n"; + + +/***************************************************************************** + * Configuration + ****************************************************************************/ + +#define TLS_MAXDATASIZE 4096 /* maximum acceptable amount of data */ +#define TLS_PORT 11111 /* define default port number */ +#define TLS_HOST_LOCAL "127.0.0.1" +#define TLS_HOST_REMOTE "192.168.0.112" +#define SOCK_MAX_PENDING 5 +#define THREAD_BASE_PRIO 150 + + +/***************************************************************************** + * TLS Client + ****************************************************************************/ +int wolfExample_TLSClient(const char* ip, int port) +{ + int ret = 0; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; /* create WOLFSSL object */ + int sockFd = -1; /* socket file descriptor */ + struct sockaddr_in servAddr; /* struct for server address */ + char sendBuff[TLS_MAXDATASIZE], rcvBuff[TLS_MAXDATASIZE]; + + sockFd = socket(AF_INET, SOCK_STREAM, 0); + if (sockFd < 0) { + printf("Failed to create socket. Error: %d\n", errno); + return errno; + } + + memset(&servAddr, 0, sizeof(servAddr)); /* clears memory block for use */ + servAddr.sin_family = AF_INET; /* sets addressfamily to internet*/ + servAddr.sin_port = htons(port); /* sets port to defined port */ + + /* looks for the server at the entered address (ip in the command line) */ + if (inet_pton(AF_INET, ip, &servAddr.sin_addr) < 1) { + /* checks validity of address */ + ret = errno; + printf("Invalid Address. Error: %d\n", ret); + goto exit; + } + + if (connect(sockFd, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) { + /* if socket fails to connect to the server*/ + ret = errno; + printf("Connect error. Error: %d\n", ret); + goto exit; + } + + /* create and initialize WOLFSSL_CTX structure */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())) == NULL) { + printf("SSL_CTX_new error.\n"); + goto exit; + } + + /* load CA certificates into wolfSSL_CTX. which will verify the server */ + ret = wolfSSL_CTX_load_verify_buffer(ctx, ca_cert_der_2048, + sizeof_ca_cert_der_2048, SSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) { + printf("Error %d loading CA cert\n", ret); + goto exit; + } + if ((ssl = wolfSSL_new(ctx)) == NULL) { + printf("wolfSSL_new error.\n"); + goto exit; + } + wolfSSL_set_fd(ssl, sockFd); + + ret = wolfSSL_connect(ssl); + if (ret == SSL_SUCCESS) { + printf("Message for server:\t"); + fgets(sendBuff, TLS_MAXDATASIZE, stdin); + + if (wolfSSL_write(ssl, sendBuff, strlen(sendBuff)) != strlen(sendBuff)) { + /* the message is not able to send, or error trying */ + ret = wolfSSL_get_error(ssl, 0); + printf("Write error: Error: %d\n", ret); + goto exit; + } + + memset(rcvBuff, 0, TLS_MAXDATASIZE); + if (wolfSSL_read(ssl, rcvBuff, TLS_MAXDATASIZE) < 0) { + /* the server failed to send data, or error trying */ + ret = wolfSSL_get_error(ssl, 0); + printf("Read error. Error: %d\n", ret); + goto exit; + } + printf("Received: \t%s\n", rcvBuff); + } + +exit: + /* frees all data before client termination */ + if (sockFd != -1) + close(sockFd); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + gServerExit = 1; + + return ret; +} + +/***************************************************************************** + * TLS Server + ****************************************************************************/ +int wolfExample_TLSServer(int port) +{ + int ret = 0; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + int sockFd = -1, clientFd = -1; + struct sockaddr_in serverAddr = {0}, clientAddr = {0}; + const char reply[] = "I hear ya fa shizzle!\n"; + int addrSize = sizeof(clientAddr); + char buff[256]; + + sockFd = socket(AF_INET, SOCK_STREAM, 0); + if (sockFd < 0) { + printf("Failed to create socket. Error: %d\n", errno); + return errno; + } + + /* create and initialize WOLFSSL_CTX structure */ + if ((ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method())) == NULL) { + fprintf(stderr, "wolfSSL_CTX_new error.\n"); + goto exit; + } + + /* Load server certificate into WOLFSSL_CTX */ + ret = wolfSSL_CTX_use_certificate_buffer(ctx, server_cert_der_2048, + sizeof_server_cert_der_2048, SSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) { + fprintf(stderr, "Error %d loading server-cert!\n", ret); + goto exit; + } + + /* Load server key into WOLFSSL_CTX */ + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, server_key_der_2048, + sizeof_server_key_der_2048, SSL_FILETYPE_ASN1); + if (ret != SSL_SUCCESS) { + fprintf(stderr, "Error %d loading server-key!\n", ret); + goto exit; + } + + /* Initialize the server address struct to zero */ + memset((char *)&serverAddr, 0, sizeof(serverAddr)); + + /* Fill the server's address family */ + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = INADDR_ANY; + serverAddr.sin_port = htons(port); + + /* Attach the server socket to our port */ + if (bind(sockFd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { + printf("ERROR: failed to bind\n"); + goto exit; + } + + printf("Waiting for a connection...\n"); + gServerReady = 1; + + /* Continuously accept connects while not in an active connection */ + while (gServerExit == 0) { + /* listen for a new connection */ + ret = listen(sockFd, SOCK_MAX_PENDING); + if (ret == 0) { + /* Wait until a client connects */ + clientFd = accept(sockFd, (struct sockaddr*)&clientAddr, &addrSize); + + /* If fails to connect, loop back up and wait for a new connection */ + if (clientFd == -1) { + printf("failed to accept the connection..\n"); + } + /* If it connects, read in and reply to the client */ + else { + printf("Client connected successfully\n"); + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + fprintf(stderr, "wolfSSL_new error.\n"); + break; + } + + /* direct our ssl to our clients connection */ + wolfSSL_set_fd(ssl, clientFd); + + printf("Using Non-Blocking I/O: %d\n", + wolfSSL_get_using_nonblock(ssl)); + + for ( ; ; ) { + /* Clear the buffer memory for anything possibly left over */ + memset(&buff, 0, sizeof(buff)); + + /* Read the client data into our buff array */ + ret = wolfSSL_read(ssl, buff, sizeof(buff) - 1); + if (ret > 0) { + /* Print any data the client sends to the console */ + printf("Client: %s\n", buff); + + /* Reply back to the client */ + ret = wolfSSL_write(ssl, reply, sizeof(reply) - 1); + if (ret < 0) { + printf("wolfSSL_write error = %d\n", + wolfSSL_get_error(ssl, ret)); + gServerExit = 1; + break; + } + } + /* if the client disconnects break the loop */ + else { + if (ret < 0) + printf("wolfSSL_read error = %d\n", + wolfSSL_get_error(ssl, ret)); + else if (ret == 0) + printf("The client has closed the connection.\n"); + gServerExit = 1; + break; + } + } + wolfSSL_free(ssl); /* Free the WOLFSSL object */ + ssl = NULL; + } + close(clientFd); /* close the connected socket */ + clientFd = -1; + } + } /* while */ + +exit: + if (clientFd != -1) + close(clientFd); + if (sockFd != -1) + close(sockFd); + wolfSSL_free(ssl); /* Free the WOLFSSL object */ + wolfSSL_CTX_free(ctx); /* Free WOLFSSL_CTX */ + + return ret; +} + +/***************************************************************************** + * TLS Local Test + ****************************************************************************/ +static void wolfSSLLocalServerThread(void* param) +{ + int port = (int)((int*)param); + wolfExample_TLSServer(port); +} + +int wolfExample_TLSLocal(int port) +{ + int ret; + RTHANDLE srvHandle; + + /* start server thread */ + srvHandle = CreateRtThread(THREAD_BASE_PRIO + 10, + (LPPROC)wolfSSLLocalServerThread, WOLF_EXAMPLES_STACK, (void*)port); + if (srvHandle == BAD_RTHANDLE) { + Fail("Cannot create server thread"); + return -1; + } + + /* wait for server to be ready */ + while (gServerReady != 1) { + RtSleep(0); + } + + /* run client */ + ret = wolfExample_TLSClient(TLS_HOST_LOCAL, port); + + return ret; +} + + +/***************************************************************************** + * Thread + memset(&args, 0, sizeof(args)); + ****************************************************************************/ +typedef struct func_args { + int argc; + char** argv; + int return_code; +} func_args; + +static void wolfExampleThread(void* param) +{ + func_args args; + +#ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); +#endif + + /* initialize wolfSSL */ + wolfSSL_Init(); + + while (1) { + char rc; + + gServerExit = 0; + gServerReady = 0; + + printf("\r\n\t\t\t\tMENU\r\n"); + printf(menu1); + printf("Please select one of the above options: "); + + rc = getchar(); + switch (rc) { + case 't': + printf("\nCrypt Test\n"); + wolfcrypt_test(&args); + printf("Crypt Test: Return code %d\n", args.return_code); + break; + + case 'b': + printf("\nBenchmark Test\n"); + benchmark_test(&args); + printf("Benchmark Test: Return code %d\n", args.return_code); + break; + + case 'c': + wolfExample_TLSClient(TLS_HOST_REMOTE, TLS_PORT); + break; + + case 's': + wolfExample_TLSServer(TLS_PORT); + break; + + case 'l': + wolfExample_TLSLocal(TLS_PORT); + break; + + // All other cases go here + default: + if (rc != '\r' && rc != '\n') + printf("\r\nSelection %c out of range\r\n", rc); + break; + } + } + + wolfSSL_Cleanup(); +} + + +/***************************************************************************** +* FUNCTION: Catalog +* +* PARAMETERS: 1. handle of the process whose object directory must be used +* 2. the object whose handle must be cataloged +* 3. the name to be used (upto 14 characters) +* +* RETURNS: TRUE on success +* +* DESCRIPTION: If the given name already exists, +* and the existing name refers to a non-existing object, +* then the existing name is removed before cataloging. +\*****************************************************************************/ +BOOLEAN Catalog( + RTHANDLE hProcess, + RTHANDLE hObject, + LPSTR lpszName) +{ + RTHANDLE hOld; + + if (CatalogRtHandle(hProcess, hObject, lpszName)) + return TRUE; + + // something wrong: check for the case mentioned above + if (((hOld = LookupRtHandle(hProcess, lpszName, NO_WAIT)) != BAD_RTHANDLE) && + (GetRtHandleType(hOld) == INVALID_TYPE)) + { + // this is the case mentioned above: remove the old entry and try again + if (UncatalogRtHandle(hProcess, lpszName)) + return (CatalogRtHandle(hProcess, hObject, lpszName)); + } + return FALSE; +} + +/***************************************************************************** +* FUNCTION: Cleanup (local function) +* +* DESCRIPTION: +* Tell threads to delete themselves and wait a while; +* if any thread still exists, kill it. +* Remove all other objects as far as they have been created. +\*****************************************************************************/ +void Cleanup(void) +{ + // indicate that we are cleaning up + gInit.state = CLEANUP_BUSY; + gInit.bShutdown = TRUE; + +#ifdef _DEBUG + fprintf(stderr, "wolfExamples started cleaning up\n"); +#endif + + // remove our name from the root process + if (gInit.bCataloged) { + if (!UncatalogRtHandle(hRootProcess, "wolfExample")) + Fail("Cannot remove my own name"); + } + +#ifdef _DEBUG + fprintf(stderr, "wolfExamples finished cleaning up\n"); +#endif + + // lie down + exit(0); +} + +/***************************************************************************** +* FUNCTION: Fail +* +* PARAMETERS: same parameters as expected by printf +* +* DESCRIPTION: +* If in debug mode, prints the message, appending a new line and the error number. +* Then the current process is killed graciously: +* If the current thread is the main thread, this is done directly. +* if the current thread is another one, a terminate request is sent and +* the function returns to the calling thread. +\*****************************************************************************/ +void Fail(LPSTR lpszMessage, ...) +{ + EXCEPTION eh; + RTHANDLE hDelMbx; + DWORD dwTerminate; + +#ifdef _DEBUG + va_list ap; + + va_start(ap, lpszMessage); + vfprintf(stderr, lpszMessage, ap); + va_end(ap); + fprintf(stderr, "\nError nr=%x %s\n", GetLastRtError(), GetRtErrorText(GetLastRtError())); +#endif + + // make sure that exceptions are returned for inline handling + GetRtExceptionHandlerInfo(THREAD_HANDLER, &eh); + eh.ExceptionMode = 0; + SetRtExceptionHandler(&eh); + + // if we had not started initializing yet, just get out + if (BEFORE_INIT == gInit.state) + exit(0); + + if (gInit.hMain == GetRtThreadHandles(THIS_THREAD)) + { + // this is the main thread: + // if we are busy initializing, then do Cleanup + if (INIT_BUSY == gInit.state) + Cleanup(); // does not return + + // this is the main thread, but we are not initializing: just return + return; + } + + // this is not the main thread: + // ask main thread to do cleanup + // (allow some time to setup the deletion mailbox, ignore errors) + hDelMbx = LookupRtHandle(NULL_RTHANDLE, "R?EXIT_MBOX", 5000); + dwTerminate = TERMINATE; + SendRtData(hDelMbx, &dwTerminate, 4); +} + +/***************************************************************************** +* +* FUNCTION: UsecsToKticks +* +* PARAMETERS: 1. number of usecs +* +* RETURNS: number of low level ticks +* +* DESCRIPTION: returns the parameter if it is WAIT_FOREVER +* otherwise rounds up to number of low level ticks +\*****************************************************************************/ +DWORD UsecsToKticks(DWORD dwUsecs) +{ + if (dwUsecs == WAIT_FOREVER) + return WAIT_FOREVER; + + return (dwUsecs + dwKtickInUsecs - 1) / dwKtickInUsecs; +} + + +/***************************************************************************** +* FUNCTION: main +* +* DESCRIPTION: +* This is the main program module. +* It creates global objects and all threads. +* The main thread then waits for notifications and acts accordingly +\*****************************************************************************/ +int main(int argc, char* argv[]) +{ + SYSINFO sysinfo; + EVENTINFO eiEventInfo; + RTHANDLE taskHandle; + +#ifdef _DEBUG + fprintf(stderr, "wolfExamples started\n"); +#endif + + // obtain handle of root process (cannot fail) + hRootProcess = GetRtThreadHandles(ROOT_PROCESS); + + // initialize the structure for cleaning up + memset(&gInit, 0, sizeof(gInit)); + gInit.state = BEFORE_INIT; + + // get low level tick length in usecs + if (!CopyRtSystemInfo(&sysinfo)) + Fail("Cannot copy system info"); + dwKtickInUsecs = 10000 / sysinfo.KernelTickRatio; + if (dwKtickInUsecs == 0) + Fail("Invalid low level tick length"); + + // adjust process max priority (ignore error) + // TODO adjust the 2nd parameter to a value closer to zero if you want to allow more priorities + SetRtProcessMaxPriority(NULL_RTHANDLE, THREAD_BASE_PRIO); + + // obtain main thread's handle + gInit.hMain = GetRtThreadHandles(THIS_THREAD); + gInit.state = INIT_BUSY; + + // attempt to catalog the thread but ignore error + Catalog(NULL_RTHANDLE, gInit.hMain, "TMain"); + + // catalog the handle of this process in the root process + if (!Catalog(hRootProcess, GetRtThreadHandles(THIS_PROCESS), "wolfExample")) { + Fail("Cannot catalog process name"); + } + gInit.bCataloged = TRUE; + + // create thread + taskHandle = CreateRtThread(THREAD_BASE_PRIO + 20, + (LPPROC)wolfExampleThread, WOLF_EXAMPLES_STACK, 0); + if (taskHandle == BAD_RTHANDLE) { + Fail("Cannot create thread"); + } + + // indicate that initialization has finished + gInit.state = INIT_DONE; +#ifdef _DEBUG + fprintf(stderr, "wolfExamples finished initialization\n"); +#endif + + // wait for notifications + while (RtNotifyEvent(RT_SYSTEM_NOTIFICATIONS | RT_EXIT_NOTIFICATIONS, + WAIT_FOREVER, &eiEventInfo)) + { + switch(eiEventInfo.dwNotifyType) + { + case TERMINATE: + // TODO: this process should terminate + // cleanup the environment + Cleanup(); // does not return + + case NT_HOST_UP: + // TODO: react to a Windows host that has come back + break; + + case NT_BLUESCREEN: + // TODO: react to a Windows blue screen + break; + + case KERNEL_STOPPING: + // TODO: react to the INtime kernel stopping + break; + + case NT_HOST_HIBERNATE: + // TODO: react to the Windows host going in hibernation + break; + + case NT_HOST_STANDBY: + // TODO: react to the Windows host going in standby mode + break; + + case NT_HOST_SHUTDOWN_PENDING: + // TODO: react to a Windows host that is about to shutdown + break; + } + } + Fail("Notify failed"); + return 0; +} diff --git a/IDE/INTIME-RTOS/wolfExamples.h b/IDE/INTIME-RTOS/wolfExamples.h new file mode 100755 index 0000000000..89ce77cda1 --- /dev/null +++ b/IDE/INTIME-RTOS/wolfExamples.h @@ -0,0 +1,47 @@ +#ifndef _WOLFEXAMPLES_H_ +#define _WOLFEXAMPLES_H_ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +// support functions for all threads +BOOLEAN Catalog(RTHANDLE hProcess, RTHANDLE hObject, LPSTR lpszName); +void Cleanup(void); +void Fail(LPSTR lpszMessage, ...); +DWORD UsecsToKticks(DWORD dwUsecs); + + +/* Example API's */ +int wolfExample_TLSServer(int port); +int wolfExample_TLSClient(const char* ip, int port); +int wolfExample_TLSLocal(int port); + + +// global type definitions +typedef enum { + BEFORE_INIT, + INIT_BUSY, + INIT_DONE, + CLEANUP_BUSY +} INIT_STATE; + +typedef struct { + RTHANDLE hMain; // RTHANDLE of main thread + INIT_STATE state; // main thread state + BOOLEAN bCataloged; // TRUE if we cataloged process name in root + BOOLEAN bShutdown; // TRUE if all threads have to terminate +} INIT_STRUCT; + +// global variables +extern RTHANDLE hRootProcess; // RTHANDLE of root process +extern DWORD dwKtickInUsecs; // length of one low level tick in usecs +extern INIT_STRUCT gInit; // structure describing all global objects + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLFEXAMPLES_H_ */ diff --git a/IDE/INTIME-RTOS/wolfExamples.sln b/IDE/INTIME-RTOS/wolfExamples.sln new file mode 100755 index 0000000000..ab478bf6d4 --- /dev/null +++ b/IDE/INTIME-RTOS/wolfExamples.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wolfExamples", "wolfExamples.vcxproj", "{557A7EFD-2627-478A-A855-50F518DD13EE}" + ProjectSection(ProjectDependencies) = postProject + {1731767D-573F-45C9-A466-191DA0D180CF} = {1731767D-573F-45C9-A466-191DA0D180CF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwolfssl", "libwolfssl.vcxproj", "{1731767D-573F-45C9-A466-191DA0D180CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|INtime = Debug|INtime + Release|INtime = Release|INtime + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {557A7EFD-2627-478A-A855-50F518DD13EE}.Debug|INtime.ActiveCfg = Debug|INtime + {557A7EFD-2627-478A-A855-50F518DD13EE}.Debug|INtime.Build.0 = Debug|INtime + {557A7EFD-2627-478A-A855-50F518DD13EE}.Release|INtime.ActiveCfg = Release|INtime + {557A7EFD-2627-478A-A855-50F518DD13EE}.Release|INtime.Build.0 = Release|INtime + {1731767D-573F-45C9-A466-191DA0D180CF}.Debug|INtime.ActiveCfg = Debug|INtime + {1731767D-573F-45C9-A466-191DA0D180CF}.Debug|INtime.Build.0 = Debug|INtime + {1731767D-573F-45C9-A466-191DA0D180CF}.Release|INtime.ActiveCfg = Release|INtime + {1731767D-573F-45C9-A466-191DA0D180CF}.Release|INtime.Build.0 = Release|INtime + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/IDE/INTIME-RTOS/wolfExamples.vcxproj b/IDE/INTIME-RTOS/wolfExamples.vcxproj new file mode 100755 index 0000000000..81f82318ee --- /dev/null +++ b/IDE/INTIME-RTOS/wolfExamples.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + INtime + + + Release + INtime + + + + + + + + + + + + + + + + {557A7EFD-2627-478A-A855-50F518DD13EE} + wolfExamples + 8.1 + + + + Application + NotSet + v140 + + + Application + false + NotSet + v140 + + + + + + + + + + + + $(Configuration)_$(ProjectName)\ + + + $(Configuration)_$(ProjectName)\ + + + + + + 21076.20053 + /SAFESEH:NO %(AdditionalOptions) + rt.lib;pcibus.lib;netlib.lib;clib.lib;vshelper.lib;libwolfssl.lib + $(SolutionDir)$(Configuration)\\wolfExamples.rta + $(ProjectDir)$(Configuration);%(AdditionalLibraryDirectories) + + + Async + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + $(ProjectDir);$(ProjectDir)..\..\;%(AdditionalIncludeDirectories) + $(IntDir) + $(IntDir) + $(IntDir)vc$(PlatformToolsetVersion).pdb + $(IntDir) + + + + + + + 21076.20053 + /SAFESEH:NO %(AdditionalOptions) + rt.lib;pcibus.lib;netlib.lib;clib.lib;vshelper.lib;libwolfssl.lib + $(SolutionDir)$(Configuration)\\wolfExamples.rta + $(ProjectDir)$(Configuration);%(AdditionalLibraryDirectories) + + + Async + WOLFSSL_USER_SETTINGS;%(PreprocessorDefinitions) + $(ProjectDir);$(ProjectDir)..\..\;%(AdditionalIncludeDirectories) + $(IntDir) + $(IntDir) + $(IntDir)vc$(PlatformToolsetVersion).pdb + $(IntDir) + + + + + + diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h b/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h index afa6be7936..95a795e024 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h +++ b/IDE/ROWLEY-CROSSWORKS-ARM/user_settings.h @@ -216,6 +216,8 @@ extern "C" { #define FREESCALE_USE_LTC #define LTC_MAX_ECC_BITS (512) #define LTC_MAX_INT_BYTES (256) + + //#define FREESCALE_LTC_TFM_RSA_4096_ENABLE #endif #endif #endif @@ -230,14 +232,17 @@ extern "C" { #undef USE_CERT_BUFFERS_2048 #define USE_CERT_BUFFERS_2048 +#undef USE_CERT_BUFFERS_256 +#define USE_CERT_BUFFERS_256 + /* ------------------------------------------------------------------------- */ /* Debugging */ /* ------------------------------------------------------------------------- */ -#undef WOLFSSL_DEBUG -//#define WOLFSSL_DEBUG +#undef DEBUG_WOLFSSL +//#define DEBUG_WOLFSSL -#ifdef WOLFSSL_DEBUG +#ifdef DEBUG_WOLFSSL #define fprintf(file, format, ...) printf(format, ##__VA_ARGS__) /* Use this to measure / print heap usage */ @@ -253,7 +258,7 @@ extern "C" { #define NO_WOLFSSL_MEMORY #undef NO_ERROR_STRINGS - #define NO_ERROR_STRINGS + //#define NO_ERROR_STRINGS #endif @@ -273,17 +278,21 @@ extern "C" { /* Size of returned HW RNG value */ #define CUSTOM_RAND_TYPE unsigned int +/* Seed source */ +extern unsigned int custom_rand_generate(void); +#undef CUSTOM_RAND_GENERATE +#define CUSTOM_RAND_GENERATE custom_rand_generate + /* Choose RNG method */ #if 1 /* Use built-in P-RNG (SHA256 based) with HW RNG */ /* P-RNG + HW RNG (P-RNG is ~8K) */ #undef HAVE_HASHDRBG #define HAVE_HASHDRBG - - extern unsigned int custom_rand_generate(void); - #undef CUSTOM_RAND_GENERATE - #define CUSTOM_RAND_GENERATE custom_rand_generate #else + #undef WC_NO_HASHDRBG + #define WC_NO_HASHDRBG + /* Bypass P-RNG and use only HW RNG */ extern int custom_rand_generate_block(unsigned char* output, unsigned int sz); #undef CUSTOM_RAND_GENERATE_BLOCK diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp index ad5c68af83..8b228c4c44 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp +++ b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl.hzp @@ -102,6 +102,8 @@ + + @@ -120,12 +122,26 @@ recurse="Yes" /> - + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp index ca6a3a5c54..30156bf33b 100644 --- a/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp +++ b/IDE/ROWLEY-CROSSWORKS-ARM/wolfssl_ltc.hzp @@ -104,6 +104,8 @@ + + @@ -298,12 +300,26 @@ recurse="Yes" /> - + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/WIN/wolfssl-fips.vcxproj b/IDE/WIN/wolfssl-fips.vcxproj index 8575aeb9ac..d6dc75b6f1 100644 --- a/IDE/WIN/wolfssl-fips.vcxproj +++ b/IDE/WIN/wolfssl-fips.vcxproj @@ -300,7 +300,9 @@ + + @@ -324,4 +326,4 @@ - \ No newline at end of file + diff --git a/IDE/WORKBENCH/README.md b/IDE/WORKBENCH/README.md index 576e3b6af7..1a3fc6cef5 100644 --- a/IDE/WORKBENCH/README.md +++ b/IDE/WORKBENCH/README.md @@ -1,5 +1,5 @@ ## Wind River Workbench using VxWorks with wolfSSL -####1 Steps to Add wolfSSL to Workbench Project +#### 1 Steps to Add wolfSSL to Workbench Project 1. Start by creating a new VxWorks image in Workbench by going to File > New > Project and then selecting VxWorks Image Project. @@ -52,8 +52,8 @@ workspace folder. This is where the simulator looks for the filesystem. new project you created. Click "Ok". - Rebuild the project. -####2 Testing wolfSSL with VxWorks: -#####2.1 wolfCrypt Test and Benchmark Applications +#### 2 Testing wolfSSL with VxWorks: +##### 2.1 wolfCrypt Test and Benchmark Applications The wolfCrypt test application will test each of the cryptographic algorithms and output the status for each as a success or failure. The benchmark application will output the runtime of the cryptographic algorithms in milliseconds. @@ -85,7 +85,7 @@ by adding the following to the usrAppInit() function: 4. To run the VxWorks simulator, click the dropdown list next to "VxWorks Simulator" at the top of Workbench and go to "Open Connection Details". Add the correct Kernel Image file. This will be located in ```workspace//default/vxWorks```. Click Apply. Start the simulator by clicking the green, "Connect 'VxWorks Simulator'" button to the right of the "VxWorks Simulator" dropdown list. Verify in the simulator terminal that all wolfCrypt tests pass. -#####2.2 Example Client +##### 2.2 Example Client The wolfSSL example client.c file can be found in ```/wolfssl/examples/client```. 1. Add the following include to usrAppInit.c: @@ -117,7 +117,7 @@ section, and add a call to the client function: SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Server response: I hear you fa shizzle! -#####2.3 Example Server +##### 2.3 Example Server The example server requires more configuration than the client if using the VxWorks simulator. @@ -164,7 +164,7 @@ Note: The wolfSSL example server and client cannot run at the same time on the V SSL cipher suite is TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 Client message: hello wolfssl! -####3 Necessary Files if Using VxWorks Simulator +#### 3 Necessary Files if Using VxWorks Simulator The following files are required to replicate this build: * vxsim\_linux\_1\_0\_2\_2 (directory) * compilers/gnu-4.8.1.5/include/c++/4.8 diff --git a/IDE/include.am b/IDE/include.am index 96fa894d78..e94d1f1b5e 100644 --- a/IDE/include.am +++ b/IDE/include.am @@ -8,5 +8,6 @@ include IDE/WIN-SGX/include.am include IDE/WORKBENCH/include.am include IDE/ROWLEY-CROSSWORKS-ARM/include.am include IDE/ARDUINO/include.am +include IDE/INTIME-RTOS/include.am -EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL IDE/LPCXPRESSO +EXTRA_DIST+= IDE/IAR-EWARM IDE/MDK-ARM IDE/MDK5-ARM IDE/MYSQL IDE/LPCXPRESSO IDE/HEXIWEAR diff --git a/Makefile.am b/Makefile.am index 1f042dc3d5..c81d7eca07 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,7 +54,18 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataAES128CBC.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ - pkcs7signedData.der + pkcs7signedData_RSA_SHA.der \ + pkcs7signedData_RSA_SHA_noattr.der \ + pkcs7signedData_RSA_SHA224.der \ + pkcs7signedData_RSA_SHA256.der \ + pkcs7signedData_RSA_SHA384.der \ + pkcs7signedData_RSA_SHA512.der \ + pkcs7signedData_ECDSA_SHA.der \ + pkcs7signedData_ECDSA_SHA_noattr.der \ + pkcs7signedData_ECDSA_SHA224.der \ + pkcs7signedData_ECDSA_SHA256.der \ + pkcs7signedData_ECDSA_SHA384.der \ + pkcs7signedData_ECDSA_SHA512.der exampledir = $(docdir)/example dist_example_DATA= diff --git a/README b/README index 63f245259f..f1923432e2 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ Note 1) wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer supports static key cipher suites with PSK, RSA, or ECDH. This means -if you plan to use TLS cipher suites you must enable DH (DH is on by default), +if you plan to use TLS cipher suites you must enable DH (DH is on by default), or enable ECC (ECC is on by default on 64bit systems), or you must enable static key cipher suites with WOLFSSL_STATIC_DH @@ -12,11 +12,11 @@ key cipher suites with WOLFSSL_STATIC_PSK though static key cipher suites are deprecated and will be removed from future -versions of TLS. They also lower your security by removing PFS. Since current +versions of TLS. They also lower your security by removing PFS. Since current NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be used in order to build with NTRU suites. -When compiling ssl.c wolfSSL will now issue a compiler error if no cipher suites +When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher suites are available. You can remove this error by defining WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not using TLS cipher suites. @@ -34,6 +34,118 @@ before calling wolfSSL_new(); Though it's not recommended. *** end Notes *** +********* wolfSSL (Formerly CyaSSL) Release 3.11.1 (5/11/2017) + +Release 3.11.1 of wolfSSL is a TLS 1.3 BETA release, which includes: + +- TLS 1.3 client and server support for TLS 1.3 with Draft 18 support + +This is strictly a BETA release, and designed for testing and user feedback. +Please send any comments, testing results, or feedback to wolfSSL at +support@wolfssl.com. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +********* wolfSSL (Formerly CyaSSL) Release 3.11.0 (5/04/2017) + +Release 3.11.0 of wolfSSL has bug fixes and new features including: + +- Code updates for warnings reported by Coverity scans +- Testing and warning fixes for FreeBSD on PowerPC +- Updates and refactoring done to ASN1 parsing functions +- Change max PSK identity buffer to account for an identity length of 128 characters +- Update Arduino script to handle recent files and additions +- Added support for PKCS#7 Signed Data with ECDSA +- Fix for interoperability with ChaCha20-Poly1305 suites using older draft versions +- DTLS update to allow multiple handshake messages in one DTLS record. Thanks to Eric Samsel over at Welch Allyn for reporting this bug. +- Intel QuickAssist asynchronous support (PR #715 - https://www.wolfssl.com/wolfSSL/Blog/Entries/2017/1/18_wolfSSL_Asynchronous_Intel_QuickAssist_Support.html) +- Added support for HAproxy load balancer +- Added option to allow SHA1 with TLS 1.2 for IIS compatibility (WOLFSSL_ALLOW_TLS_SHA1) +- Added Curve25519 51-bit Implementation, increasing performance on systems that have 128 bit types +- Fix to not send session ID on server side if session cache is off unless we're echoing +session ID as part of session tickets +- Fixes for ensuring all default ciphers are setup correctly (see PR #830) +- Added NXP Hexiwear example in `IDE/HEXIWEAR`. +- Added wolfSSL_write_dup() to create write only WOLFSSL object for concurrent access +- Fixes for TLS elliptic curve selection on private key import. +- Fixes for RNG with Intel rdrand and rdseed speedups. +- Improved performance with Intel rdrand to use full 64-bit output +- Added new --enable-intelrand option to indicate use of RDRAND preference for RNG source +- Removed RNG ARC4 support +- Added ECC helpers to get size and id from curve name. +- Added ECC Cofactor DH (ECC-CDH) support +- Added ECC private key only import / export functions. +- Added PKCS8 create function +- Improvements to TLS layer CTX handling for switching keys / certs. +- Added check for duplicate certificate policy OID in certificates. +- Normal math speed-up to not allocate on mp_int and defer until mp_grow +- Reduce heap usage with fast math when not using ALT_ECC_SIZE +- Fixes for building CRL with Windows +- Added support for inline CRL lookup when HAVE_CRL_IO is defined +- Added port for tenAsys INtime RTOS +- Improvements to uTKernel port (WOLFSSL_uTKERNEL2) +- Updated WPA Supplicant support +- Added support for Nginx +- Update stunnel port for version 5.40 +- Fixes for STM32 hardware crypto acceleration +- Extended test code coverage in bundled test.c +- Added a sanity check for minimum authentication tag size with AES-GCM. Thanks to Yueh-Hsun Lin and Peng Li at KNOX Security at Samsung Research America for suggesting this. +- Added a sanity check that subject key identifier is marked as non-critical and a check that no policy OIDS appear more than once in the cert policies extension. Thanks to the report from Professor Zhenhua Duan, Professor Cong Tian, and Ph.D candidate Chu Chen from Institute of Computing Theory and Technology (ICTT) of Xidian University, China. Profs. Zhenhua Duan and Cong Tian are supervisors of Ph.D candidate Chu Chen. + + +This release of wolfSSL fixes 5 low and 1 medium level security vulnerability. + +3 Low level fixes reported by Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America. +- Fix for out of bounds memory access in wc_DhParamsLoad() when GetLength() returns a zero. Before this fix there is a case where wolfSSL would read out of bounds memory in the function wc_DhParamsLoad. +- Fix for DH key accepted by wc_DhAgree when the key was malformed. +- Fix for a double free case when adding CA cert into X509_store. + +Low level fix for memory management with static memory feature enabled. By default static memory is disabled. Thanks to GitHub user hajjihraf for reporting this. + +Low level fix for out of bounds write in the function wolfSSL_X509_NAME_get_text_by_NID. This function is not used by TLS or crypto operations but could result in a buffer out of bounds write by one if called explicitly in an application. Discovered by Aleksandar Nikolic of Cisco Talos. http://talosintelligence.com/vulnerability-reports/ + +Medium level fix for check on certificate signature. There is a case in release versions 3.9.10, 3.10.0 and 3.10.2 where a corrupted signature on a peer certificate would not be properly flagged. Thanks to Wens Lo, James Tsai, Kenny Chang, and Oscar Yang at Castles Technology. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +********* wolfSSL (Formerly CyaSSL) Release 3.10.2 (2/10/2017) + +Release 3.10.2 of wolfSSL has bug fixes and new features including: + +- Poly1305 Windows macros fix. Thanks to GitHub user Jay Satiro +- Compatibility layer expanded with multiple functions added +- Improve fp_copy performance with ALT_ECC_SIZE +- OCSP updates and improvements +- Fixes for IAR EWARM 8 compiler warnings +- Reduce stack usage with ECC_CACHE_CURVE disabled +- Added ECC export raw for public and private key +- Fix for NO_ASN_TIME build +- Supported curves extensions now populated by default +- Add DTLS build without big integer math +- Fix for static memory feature with wc_ecc_verify_hash_ex and not SHAMIR +- Added PSK interoperability testing to script bundled with wolfSSL +- Fix for Python wrapper random number generation. Compiler optimizations with Python could place the random number in same buffer location each time. Thanks to GitHub user Erik Bray (embray) +- Fix for tests on unaligned memory with static memory feature +- Add macro WOLFSSL_NO_OCSP_OPTIONAL_CERTS to skip optional OCSP certificates +- Sanity checks on NULL arguments added to wolfSSL_set_fd and wolfSSL_DTLS_SetCookieSecret +- mp_jacobi stack use reduced, thanks to Szabi Tolnai for providing a solution to reduce stack usage + + +This release of wolfSSL fixes 2 low and 1 medium level security vulnerability. + +Low level fix of buffer overflow for when loading in a malformed temporary DH file. Thanks to Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America for the report. + +Medium level fix for processing of OCSP response. If using OCSP without hard faults enforced and no alternate revocation checks like OCSP stapling then it is recommended to update. + +Low level fix for potential cache attack on RSA operations. If using wolfSSL RSA on a server that other users can have access to monitor the cache, then it is recommended to update wolfSSL. Thanks to Andreas Zankl, Johann Heyszl and Georg Sigl at Fraunhofer AISEC for the initial report. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html ********* wolfSSL (Formerly CyaSSL) Release 3.10.0 (12/21/2016) diff --git a/README.md b/README.md index ae166c18ea..4c0c07e9b9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ``` wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer supports static key cipher suites with PSK, RSA, or ECDH. This means -if you plan to use TLS cipher suites you must enable DH (DH is on by default), +if you plan to use TLS cipher suites you must enable DH (DH is on by default), or enable ECC (ECC is on by default on 64bit systems), or you must enable static key cipher suites with WOLFSSL_STATIC_DH @@ -13,12 +13,12 @@ key cipher suites with WOLFSSL_STATIC_PSK though static key cipher suites are deprecated and will be removed from future -versions of TLS. They also lower your security by removing PFS. Since current +versions of TLS. They also lower your security by removing PFS. Since current NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be used in order to build with NTRU suites. -When compiling ssl.c wolfSSL will now issue a compiler error if no cipher suites +When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher suites are available. You can remove this error by defining WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not using TLS cipher suites. ``` @@ -38,6 +38,120 @@ wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); before calling wolfSSL_new(); Though it's not recommended. ``` +# wolfSSL (Formerly CyaSSL) Release 3.11.1 (5/11/2017) + +## Release 3.11.1 of wolfSSL is a TLS 1.3 BETA release, which includes: + +- TLS 1.3 client and server support for TLS 1.3 with Draft 18 support + +This is strictly a BETA release, and designed for testing and user feedback. +Please send any comments, testing results, or feedback to wolfSSL at +support@wolfssl.com. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.11.0 (5/04/2017) + +## Release 3.11.0 of wolfSSL has bug fixes and new features including: + +- Code updates for warnings reported by Coverity scans +- Testing and warning fixes for FreeBSD on PowerPC +- Updates and refactoring done to ASN1 parsing functions +- Change max PSK identity buffer to account for an identity length of 128 characters +- Update Arduino script to handle recent files and additions +- Added support for PKCS#7 Signed Data with ECDSA +- Fix for interoperability with ChaCha20-Poly1305 suites using older draft versions +- DTLS update to allow multiple handshake messages in one DTLS record. Thanks to Eric Samsel over at Welch Allyn for reporting this bug. +- Intel QuickAssist asynchronous support (PR #715 - https://www.wolfssl.com/wolfSSL/Blog/Entries/2017/1/18_wolfSSL_Asynchronous_Intel_QuickAssist_Support.html) +- Added support for HAproxy load balancer +- Added option to allow SHA1 with TLS 1.2 for IIS compatibility (WOLFSSL_ALLOW_TLS_SHA1) +- Added Curve25519 51-bit Implementation, increasing performance on systems that have 128 bit types +- Fix to not send session ID on server side if session cache is off unless we're echoing +session ID as part of session tickets +- Fixes for ensuring all default ciphers are setup correctly (see PR #830) +- Added NXP Hexiwear example in `IDE/HEXIWEAR`. +- Added wolfSSL_write_dup() to create write only WOLFSSL object for concurrent access +- Fixes for TLS elliptic curve selection on private key import. +- Fixes for RNG with Intel rdrand and rdseed speedups. +- Improved performance with Intel rdrand to use full 64-bit output +- Added new --enable-intelrand option to indicate use of RDRAND preference for RNG source +- Removed RNG ARC4 support +- Added ECC helpers to get size and id from curve name. +- Added ECC Cofactor DH (ECC-CDH) support +- Added ECC private key only import / export functions. +- Added PKCS8 create function +- Improvements to TLS layer CTX handling for switching keys / certs. +- Added check for duplicate certificate policy OID in certificates. +- Normal math speed-up to not allocate on mp_int and defer until mp_grow +- Reduce heap usage with fast math when not using ALT_ECC_SIZE +- Fixes for building CRL with Windows +- Added support for inline CRL lookup when HAVE_CRL_IO is defined +- Added port for tenAsys INtime RTOS +- Improvements to uTKernel port (WOLFSSL_uTKERNEL2) +- Updated WPA Supplicant support +- Added support for Nginx +- Update stunnel port for version 5.40 +- Fixes for STM32 hardware crypto acceleration +- Extended test code coverage in bundled test.c +- Added a sanity check for minimum authentication tag size with AES-GCM. Thanks to Yueh-Hsun Lin and Peng Li at KNOX Security at Samsung Research America for suggesting this. +- Added a sanity check that subject key identifier is marked as non-critical and a check that no policy OIDS appear more than once in the cert policies extension. Thanks to the report from Professor Zhenhua Duan, Professor Cong Tian, and Ph.D candidate Chu Chen from Institute of Computing Theory and Technology (ICTT) of Xidian University, China. Profs. Zhenhua Duan and Cong Tian are supervisors of Ph.D candidate Chu Chen. + +This release of wolfSSL fixes 5 low and 1 medium level security vulnerability. + +3 Low level fixes reported by Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America. +- Fix for out of bounds memory access in wc_DhParamsLoad() when GetLength() returns a zero. Before this fix there is a case where wolfSSL would read out of bounds memory in the function wc_DhParamsLoad. +- Fix for DH key accepted by wc_DhAgree when the key was malformed. +- Fix for a double free case when adding CA cert into X509_store. + +Low level fix for memory management with static memory feature enabled. By default static memory is disabled. Thanks to GitHub user hajjihraf for reporting this. + + +Low level fix for out of bounds write in the function wolfSSL_X509_NAME_get_text_by_NID. This function is not used by TLS or crypto operations but could result in a buffer out of bounds write by one if called explicitly in an application. Discovered by Aleksandar Nikolic of Cisco Talos. http://talosintelligence.com/vulnerability-reports/ + +Medium level fix for check on certificate signature. There is a case in release versions 3.9.10, 3.10.0 and 3.10.2 where a corrupted signature on a peer certificate would not be properly flagged. Thanks to Wens Lo, James Tsai, Kenny Chang, and Oscar Yang at Castles Technology. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.10.2 (2/10/2017) + +## Release 3.10.2 of wolfSSL has bug fixes and new features including: + +- Poly1305 Windows macros fix. Thanks to GitHub user Jay Satiro +- Compatibility layer expanded with multiple functions added +- Improve fp_copy performance with ALT_ECC_SIZE +- OCSP updates and improvements +- Fixes for IAR EWARM 8 compiler warnings +- Reduce stack usage with ECC_CACHE_CURVE disabled +- Added ECC export raw for public and private key +- Fix for NO_ASN_TIME build +- Supported curves extensions now populated by default +- Add DTLS build without big integer math +- Fix for static memory feature with wc_ecc_verify_hash_ex and not SHAMIR +- Added PSK interoperability testing to script bundled with wolfSSL +- Fix for Python wrapper random number generation. Compiler optimizations with Python could place the random number in same buffer location each time. Thanks to GitHub user Erik Bray (embray) +- Fix for tests on unaligned memory with static memory feature +- Add macro WOLFSSL_NO_OCSP_OPTIONAL_CERTS to skip optional OCSP certificates +- Sanity checks on NULL arguments added to wolfSSL_set_fd and wolfSSL_DTLS_SetCookieSecret +- mp_jacobi stack use reduced, thanks to Szabi Tolnai for providing a solution to reduce stack usage + + +This release of wolfSSL fixes 2 low and 1 medium level security vulnerability. + +Low level fix of buffer overflow for when loading in a malformed temporary DH file. Thanks to Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America for the report. + +Medium level fix for processing of OCSP response. If using OCSP without hard faults enforced and no alternate revocation checks like OCSP stapling then it is recommended to update. + +Low level fix for potential cache attack on RSA operations. If using wolfSSL RSA on a server that other users can have access to monitor the cache, then it is recommended to update wolfSSL. Thanks to Andreas Zankl, Johann Heyszl and Georg Sigl at Fraunhofer AISEC for the initial report. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + # wolfSSL (Formerly CyaSSL) Release 3.10.0 (12/21/2016) ## Release 3.10.0 of wolfSSL has bug fixes and new features including: diff --git a/autogen.sh b/autogen.sh index 6b08f3cd56..e5ea530fa1 100755 --- a/autogen.sh +++ b/autogen.sh @@ -22,6 +22,20 @@ if test -e .git; then # touch async crypt files touch ./wolfcrypt/src/async.c touch ./wolfssl/wolfcrypt/async.h + + # touch async port files + touch ./wolfcrypt/src/port/intel/quickassist.c + touch ./wolfcrypt/src/port/intel/quickassist_mem.c + touch ./wolfcrypt/src/port/cavium/cavium_nitrox.c + if [ ! -d ./wolfssl/wolfcrypt/port/intel ]; then + mkdir ./wolfssl/wolfcrypt/port/intel + fi + touch ./wolfssl/wolfcrypt/port/intel/quickassist.h + touch ./wolfssl/wolfcrypt/port/intel/quickassist_mem.h + if [ ! -d ./wolfssl/wolfcrypt/port/cavium ]; then + mkdir ./wolfssl/wolfcrypt/port/cavium + fi + touch ./wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h else WARNINGS="all" fi diff --git a/certs/crl/crl2.pem b/certs/crl/crl2.pem new file mode 100644 index 0000000000..e357de0685 --- /dev/null +++ b/certs/crl/crl2.pem @@ -0,0 +1,80 @@ +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: /C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Last Update: Aug 11 20:07:38 2016 GMT + Next Update: May 8 20:07:38 2019 GMT + CRL extensions: + X509v3 CRL Number: + 1 +Revoked Certificates: + Serial Number: 02 + Revocation Date: Aug 11 20:07:38 2016 GMT + Signature Algorithm: sha256WithRSAEncryption + 35:c6:7f:57:9a:e5:86:5a:15:1a:e2:e5:2b:9f:54:79:2a:58: + 51:a2:12:0c:4e:53:58:eb:99:e3:c2:ee:2b:d7:23:e4:3c:4d: + 0a:ab:ae:71:9b:ce:b1:c1:75:a1:b6:e5:32:5f:10:b0:72:28: + 2e:74:b1:99:dd:47:53:20:f6:9a:83:5c:bd:20:b0:aa:df:32: + f6:95:54:98:9e:59:96:55:7b:0a:74:be:94:66:44:b7:32:82: + f0:eb:16:f8:30:86:16:9f:73:43:98:82:b5:5e:ad:58:c0:c8: + 79:da:ad:b1:b4:d7:fb:34:c1:cc:3a:67:af:a4:56:5a:70:5c: + 2d:1f:73:16:78:92:01:06:e3:2c:fb:f1:ba:d5:8f:f9:be:dd: + e1:4a:ce:de:ca:e6:2d:96:09:24:06:40:9e:10:15:2e:f2:cd: + 85:d6:84:88:db:9c:4a:7b:75:7a:06:0e:40:02:20:60:7e:91: + f7:92:53:1e:34:7a:ea:ee:df:e7:cd:a8:9e:a6:61:b4:56:50: + 4d:dc:b1:78:0d:86:cf:45:c3:a6:0a:b9:88:2c:56:a7:b1:d3: + d3:0d:44:aa:93:a4:05:4d:ce:9f:01:b0:c6:1e:e4:ea:6b:92: + 6f:93:dd:98:cf:fb:1d:06:72:ac:d4:99:e7:f2:b4:11:57:bd: + 9d:63:e5:dc +-----BEGIN X509 CRL----- +MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMxEDAOBgNV +BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3Ro +MRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTE2MDgxMTIwMDczOFoX +DTE5MDUwODIwMDczOFowFDASAgECFw0xNjA4MTEyMDA3MzhaoA4wDDAKBgNVHRQE +AwIBATANBgkqhkiG9w0BAQsFAAOCAQEANcZ/V5rlhloVGuLlK59UeSpYUaISDE5T +WOuZ48LuK9cj5DxNCquucZvOscF1obblMl8QsHIoLnSxmd1HUyD2moNcvSCwqt8y +9pVUmJ5ZllV7CnS+lGZEtzKC8OsW+DCGFp9zQ5iCtV6tWMDIedqtsbTX+zTBzDpn +r6RWWnBcLR9zFniSAQbjLPvxutWP+b7d4UrO3srmLZYJJAZAnhAVLvLNhdaEiNuc +Snt1egYOQAIgYH6R95JTHjR66u7f582onqZhtFZQTdyxeA2Gz0XDpgq5iCxWp7HT +0w1EqpOkBU3OnwGwxh7k6muSb5PdmM/7HQZyrNSZ5/K0EVe9nWPl3A== +-----END X509 CRL----- +Certificate Revocation List (CRL): + Version 2 (0x1) + Signature Algorithm: sha256WithRSAEncryption + Issuer: /C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com + Last Update: Aug 11 20:07:38 2016 GMT + Next Update: May 8 20:07:38 2019 GMT + CRL extensions: + X509v3 CRL Number: + 3 +No Revoked Certificates. + Signature Algorithm: sha256WithRSAEncryption + 14:85:d5:c8:db:62:74:48:94:5e:dc:52:0f:5e:43:8b:29:83: + 32:e0:7a:4c:5c:76:e3:7e:c1:87:74:40:b2:6f:f8:33:4c:2c: + 32:08:f0:5f:d9:85:b3:20:05:34:5d:15:4d:ba:45:bc:2d:9c: + ae:40:d0:d8:9a:b3:a1:4f:0b:94:ce:c4:23:c6:bf:a2:f8:a6: + 02:4c:6d:ad:5a:59:b3:83:55:dd:37:91:f6:75:d4:6f:83:5f: + 1c:29:94:cd:01:09:dc:38:d8:6c:c0:9f:1e:76:9d:f9:8f:70: + 0d:48:e5:99:82:90:3a:36:f1:33:17:69:73:8a:ee:a7:22:4c: + 58:93:a1:dc:59:b9:44:8f:88:99:0b:c4:d3:74:aa:02:9a:84: + 36:48:d8:a0:05:73:bc:14:32:1e:76:23:85:c5:94:56:b2:2c: + 61:3b:07:d7:bd:0c:27:f7:d7:23:40:bd:0c:6c:c7:e0:f7:28: + 74:67:98:20:93:72:16:b6:6e:67:3f:9e:c9:34:c5:64:09:bf: + b1:ab:87:0c:80:b6:1f:89:d8:0e:67:c2:c7:19:df:ee:9f:b2: + e6:fb:64:3d:82:7a:47:e2:8d:a3:93:1d:29:f6:94:db:83:2f: + b6:0a:a0:da:77:e3:56:ec:d7:d2:22:3c:88:4d:4a:87:de:b5: + 1c:eb:7b:08 +-----BEGIN X509 CRL----- +MIIB+DCB4QIBATANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UEBhMCVVMxEDAOBgNV +BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTATBgNVBAoMDHdvbGZTU0xf +MjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0ODEYMBYGA1UEAwwPd3d3Lndv +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0xNjA4 +MTEyMDA3MzhaFw0xOTA1MDgyMDA3MzhaoA4wDDAKBgNVHRQEAwIBAzANBgkqhkiG +9w0BAQsFAAOCAQEAFIXVyNtidEiUXtxSD15DiymDMuB6TFx2437Bh3RAsm/4M0ws +MgjwX9mFsyAFNF0VTbpFvC2crkDQ2JqzoU8LlM7EI8a/ovimAkxtrVpZs4NV3TeR +9nXUb4NfHCmUzQEJ3DjYbMCfHnad+Y9wDUjlmYKQOjbxMxdpc4rupyJMWJOh3Fm5 +RI+ImQvE03SqApqENkjYoAVzvBQyHnYjhcWUVrIsYTsH170MJ/fXI0C9DGzH4Pco +dGeYIJNyFrZuZz+eyTTFZAm/sauHDIC2H4nYDmfCxxnf7p+y5vtkPYJ6R+KNo5Md +KfaU24Mvtgqg2nfjVuzX0iI8iE1Kh961HOt7CA== +-----END X509 CRL----- diff --git a/certs/crl/include.am b/certs/crl/include.am index 7adca32255..47f0d5a25a 100644 --- a/certs/crl/include.am +++ b/certs/crl/include.am @@ -6,7 +6,8 @@ EXTRA_DIST += \ certs/crl/crl.pem \ certs/crl/cliCrl.pem \ certs/crl/eccSrvCRL.pem \ - certs/crl/eccCliCRL.pem + certs/crl/eccCliCRL.pem \ + certs/crl/crl2.pem EXTRA_DIST += \ certs/crl/crl.revoked diff --git a/certs/dsaparams.pem b/certs/dsaparams.pem new file mode 100644 index 0000000000..973e896824 --- /dev/null +++ b/certs/dsaparams.pem @@ -0,0 +1,9 @@ +-----BEGIN DSA PARAMETERS----- +MIIBHwKBgQDN3iVogFMN5XfW0pA5P5CiPzOUbuhPK2OrMKsVuhHqil2NzLjUodXB +R51ac2piSdEGB2f2L6M5vU4NtNMiI4TskyZaSe58iUhmTejo2FD7pXGfIhjl5gtG +h2buUo9GT7UDzu3jvuW1gdJZ6cCtTdBNJve6UOjJj/4kGT0up1I8bQIVAPtH++yB +IMgc6Uq6BG8Zm5TugmfTAoGBAJuVu4XFWEoynKpEhdZo3D4U9M5to0k46tZhSJJa +QJVJOKrhOSloWEeKSwHhLo5sY29AylA/jAuZ5HJCuLHCJkjxnIPGNy5arhEJ2fOt +H2+trVDjeDLm3o6qv9EAn7MCEhmiFewUGFwOJs75rsx7tdEm/IX+FJO2nX124zWX +Ht7E +-----END DSA PARAMETERS----- diff --git a/certs/ecc-privkey.pem b/certs/ecc-privkey.pem new file mode 100644 index 0000000000..1d46e903d0 --- /dev/null +++ b/certs/ecc-privkey.pem @@ -0,0 +1,4 @@ +-----BEGIN EC PRIVATE KEY----- +MDECAQEEIEW2aQJznGyFoThbcujox6zEA41TNQT6bCjcNI3hqAmMoAoGCCqGSM49 +AwEH +-----END EC PRIVATE KEY----- diff --git a/certs/external/ca-verisign-g5.pem b/certs/external/ca-verisign-g5.pem index 707ff085b8..7829f6595f 100644 --- a/certs/external/ca-verisign-g5.pem +++ b/certs/external/ca-verisign-g5.pem @@ -26,3 +26,17 @@ WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq -----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG +A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz +cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 +MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV +BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN +ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE +BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is +I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G +CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i +2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ +2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ +-----END CERTIFICATE----- diff --git a/certs/include.am b/certs/include.am index eedd53aa22..e9b8e5c5d8 100644 --- a/certs/include.am +++ b/certs/include.am @@ -9,6 +9,7 @@ EXTRA_DIST += \ certs/client-keyEnc.pem \ certs/client-key.pem \ certs/ecc-key.pem \ + certs/ecc-privkey.pem \ certs/ecc-keyPkcs8Enc.pem \ certs/ecc-key-comp.pem \ certs/ecc-keyPkcs8.pem \ @@ -24,6 +25,7 @@ EXTRA_DIST += \ certs/server-ecc-rsa.pem \ certs/server-keyEnc.pem \ certs/server-key.pem \ + certs/server-keyPkcs8.der \ certs/server-keyPkcs8Enc12.pem \ certs/server-keyPkcs8Enc2.pem \ certs/server-keyPkcs8Enc.pem \ @@ -31,7 +33,8 @@ EXTRA_DIST += \ certs/server-revoked-cert.pem \ certs/server-revoked-key.pem \ certs/wolfssl-website-ca.pem \ - certs/test-servercert.p12 + certs/test-servercert.p12 \ + certs/dsaparams.pem EXTRA_DIST += \ certs/ca-key.der \ certs/ca-cert.der \ @@ -51,10 +54,12 @@ EXTRA_DIST += \ certs/server-ecc-comp.der \ certs/server-ecc.der \ certs/server-ecc-rsa.der \ - certs/server-cert-chain.der + certs/server-cert-chain.der dist_doc_DATA+= certs/taoCert.txt EXTRA_DIST+= certs/ntru-key.raw +include certs/test/include.am include certs/test-pathlen/include.am +include certs/test/include.am diff --git a/certs/renewcerts.sh b/certs/renewcerts.sh index 9125636484..6bad02d66f 100755 --- a/certs/renewcerts.sh +++ b/certs/renewcerts.sh @@ -16,6 +16,7 @@ # 1024/client-cert.pem # server-ecc-comp.pem # client-ca.pem +# test/digsigku.pem # updates the following crls: # crl/cliCrl.pem # crl/crl.pem @@ -128,6 +129,23 @@ function run_renewcerts(){ cat ca_tmp.pem >> server-revoked-cert.pem rm ca_tmp.pem ########################################################### + ########## update and sign server-duplicate-policy.pem #### + ########################################################### + echo "Updating server-duplicate-policy.pem" + echo "" + #pipe the following arguments to openssl req... + echo -e "US\nMontana\nBozeman\nwolfSSL\ntesting duplicate policy\nwww.wolfssl.com\ninfo@wolfssl.com\n.\n.\n" | openssl req -new -key server-key.pem -nodes > ./test/server-duplicate-policy-req.pem + + openssl x509 -req -in ./test/server-duplicate-policy-req.pem -extfile wolfssl.cnf -extensions policy_test -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 02 > ./test/server-duplicate-policy.pem + + rm ./test/server-duplicate-policy-req.pem + + openssl x509 -in ca-cert.pem -text > ca_tmp.pem + openssl x509 -in ./test/server-duplicate-policy.pem -text > srv_tmp.pem + mv srv_tmp.pem ./test/server-duplicate-policy.pem + cat ca_tmp.pem >> ./test/server-duplicate-policy.pem + rm ca_tmp.pem + ########################################################### #### update and sign (1024-bit) server-cert.pem ########### ########################################################### echo "Updating 1024-bit server-cert.pem" @@ -208,6 +226,22 @@ function run_renewcerts(){ echo "" cat client-cert.pem client-ecc-cert.pem > client-ca.pem + ############################################################ + ###### update the self-signed test/digsigku.pem ########## + ############################################################ + echo "Updating test/digsigku.pem" + echo "" + #pipe the following arguments to openssl req... + echo -e "US\nWashington\nSeattle\nFoofarah\nArglebargle\nfoobarbaz\ninfo@worlss.com\n.\n.\n" | openssl req -new -key ecc-key.pem -nodes -sha1 -out digsigku.csr + + + openssl x509 -req -in digsigku.csr -days 1000 -extfile wolfssl.cnf -extensions digsigku -signkey ecc-key.pem -sha1 -set_serial 16393466893990650224 -out digsigku.pem + rm digsigku.csr + + openssl x509 -in digsigku.pem -text > tmp.pem + mv tmp.pem digsigku.pem + mv digsigku.pem test/digsigku.pem + ############################################################ ########## make .der files from .pem files ################# ############################################################ diff --git a/certs/renewcerts/wolfssl.cnf b/certs/renewcerts/wolfssl.cnf index 47ad4ba93b..079ec5ec87 100644 --- a/certs/renewcerts/wolfssl.cnf +++ b/certs/renewcerts/wolfssl.cnf @@ -148,6 +148,28 @@ subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo +# Test of rejecting duplicate policy extension OIDs +[ policy_test ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints=CA:FALSE +certificatePolicies=1.2.3.4,@policy_add + +[ policy_add ] +policyIdentifier=1.2.3.4 +CPS.1="www.wolfssl.com" +userNotice.1=@policy_usr + +[ policy_usr ] +explicitText="Test of duplicate OIDs with different qualifiers" + +# create certificate without the digitalSignature bit set and uses sha1 sig +[ digsigku ] +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid:always,issuer:always +basicConstraints=critical, CA:TRUE +keyUsage=critical, nonRepudiation, keyEncipherment + #tsa default [ tsa ] default_tsa = tsa_config1 diff --git a/certs/server-keyPkcs8.der b/certs/server-keyPkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..5a5873543466614225e07a472bd26f158d8872f1 GIT binary patch literal 1219 zcmV;!1U&mNf&{+;0RS)!1_>&LNQUrsW5^Br2+u}0)hbn0Kk<9;a5TO zac#HKML{P4WyVFW^1LK4xRuT?PS*Auh`fBC`>1Ds{#=|g73;pSn3#nP7F+0aj|*8&3p009Dm0RaG- z&@>NHVg*nE@1N~tZoVb1>CD z*rKe4LoUSiWL`gsbq^8PQ6)~F*s7z>V6) zEL3(mBV)-BGPjehuf7>|mVspEwYZ5wLD6l{92@u>tZB`^clFrV6j(7Us6w5 zI#qu%z!^hOKd#Pi7xNCEK*~<76+6j!>A+byb8wsre91aUGN;%{bqa;T!u=I<+L;L| zX_}u3alfzxri^-8Z%A5HJI1k77vJXsfq?+aliqg~UAJ6ZeAtkwm@U?64r8;U+@{Qn zYNVnPjE;LqEV4^C+y)qZ>i%}2)S>A=4b2;0uV0>)TU!sIe6O>cklR;tI_0Su8^nN;-MFwz0r&hq!A{2I>*ke$MkkjJ7ft8XmL5DdS zLkk$CQy)1RUmrufhicz$(;@)=BA9Sa8W|}9fq?*uK~^YHo?q0S3p<#jRPtV zFhk(+cy#??8%znz=4dK$tsLJ&yjI(#q`oz9q+ZWY`~X#%Iz1!LXIk|l__Zm}L=o#X hE=Ionju^6EsJ|I9q4nGY=6sqT41B4u4k0%?@vt|dO7Z{z literal 0 HcmV?d00001 diff --git a/certs/test/cert-ext-ia.cfg b/certs/test/cert-ext-ia.cfg new file mode 100644 index 0000000000..8721916b33 --- /dev/null +++ b/certs/test/cert-ext-ia.cfg @@ -0,0 +1,18 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +x509_extensions = v3_ca + +[ req_distinguished_name ] +C = AU +ST = Queensland +L = Brisbane +O = wolfSSL Inc +OU = Engineering +CN = www.wolfssl.com +emailAddress = support@www.wolfsssl.com + +[ v3_ca ] +inhibitAnyPolicy = critical,1 +nsComment = "Testing inhibit any" + diff --git a/certs/test/cert-ext-ia.der b/certs/test/cert-ext-ia.der new file mode 100644 index 0000000000000000000000000000000000000000..73ea7c0a86f18a8789a72c2caa3c83bed8189f9e GIT binary patch literal 1030 zcmXqLVqr39VtTcJnTe5!iIbr(#&5IIjlRPMylk9WZ60mkc^MhGSs4r(ml$#zaI!In zvaks=Iffbv8wi3p96VfsrKzcT#W{(2DTaau{2)Pg9uB9X%;KcPyi`LG10j$Q7Y}!N zeok6&u#bXgUNTISn}^#qFFi9aHMJ-+FWpeWKn$donTNl;yj%~YzPLC?FF8NgP~AWk z?i@}=F^S^Rf`a^_5(k7jh(ZH7ab81n14BatBV$uTV~Z#-*T}#U${i}+Xkt`CjsQkh z2IeM4eg=akMlPl%Mn;AMQ#l@nJANw6-G0f{QJpdMnCrSvdsGZ|Og*RXckP=@$DW$` zzgMK!|BIOuSo*!|6#H{i{r-o0s}JbctWH@W{^wL|^{xksPmA>O_1bPsExxrzI(TQi z{dGxRRsV;{$${P6DfVlfcPy2OG15l{hJoZvo~b(!`yh8J<7!wIhi{}E(z>RIjnVI z;WV#353fi?A760bU~&b&i@AZ(v<4&PsSC?@316CC{3urSWESsX%Y-FcHe@nC?w`pA_pumWdj42kztF->a6I6HFx?>_O5Hp5@7sX zdM7LN;hCp;7j_=kHu|NU{o%Nd{+b*P?Q)LaCW#sEqT(l&aJ`)#Vq(l;*q51dJEU5) z#&=Pewd^j7-BUc$Lf9e<*c6tjOG+%-YtE}FaK+!xUTo^^^VbAp;!hvlwLm&Ai6{Kg zd53qe^G- DsJ(j1 literal 0 HcmV?d00001 diff --git a/certs/test/cert-ext-nc.cfg b/certs/test/cert-ext-nc.cfg new file mode 100644 index 0000000000..b27f3f4fe2 --- /dev/null +++ b/certs/test/cert-ext-nc.cfg @@ -0,0 +1,18 @@ +[ req ] +distinguished_name = req_distinguished_name +prompt = no +x509_extensions = v3_ca + +[ req_distinguished_name ] +C = AU +ST = Queensland +L = Brisbane +O = wolfSSL Inc +OU = Engineering +CN = www.wolfssl.com +emailAddress = support@www.wolfsssl.com + +[ v3_ca ] +nameConstraints = critical,permitted;email:.wolfssl.com +nsComment = "Testing name constraints" + diff --git a/certs/test/cert-ext-nc.der b/certs/test/cert-ext-nc.der new file mode 100644 index 0000000000000000000000000000000000000000..ff944476d5564054aec33f6ea7572170d309cfd6 GIT binary patch literal 1052 zcmXqLVv#UtVrE#t%*4pV#L2L$Fxht+|JyDDUN%mxHjlRNyo`+8tPBQ?OANUUIN6v( zS=fY`977F-4Fo|P4j!(+($v(v;+(|16hlD+evlwL4~J7xW^qztUaFypfe=WDi-)^B zKPN3X*hj%LFBvAv&BN`Qm!6rInp%{Zmu@IwAO=#)%)?(^UakjHUtFA{mzBO}9ssT>c(9X}Q3ZolN}sLq&r%yr$TJt_t}rk>OHyY@|{V^7We z-z(DV|HaG+EdAbfiv78%e*eS0)d%!zR;R2G|8pv~de;NRr$u`CdTlqR7T;PU9lSH% z{<DSDi+1cs*E-U6|H0xPBy_CLi<2*a}%>~i5DXwo9Nl#xl?QLxgcR}<2 zmrruO-n@O!;+0H(_`Z@$p(lO4+W)jen5Hgla(r;MD1(vr7Y}p9@1$;t=P{M$HjlrZo$GE-cH;ewL4AbqiLTRKv8WZNZu}8v@|G127^|)j!++U zg>Y?k1JnlRbyXXzHltC5=)QWZI%Es?MM5=Zq(KOF#1?i7`K^j#4NyE&>2PDASsijh zv4)Nb9>RIym{8z);fPBZuMh-XV2t8VtEn^Rmfj(d@5S7RKtgeSwIHg3B$Hy`fq<+E zT?I<&tt!`!{m+N4&5!o5&v6@&buZk#8ryQh7rT^JBx?3hQatqh(<(CwG9=_mET9Wk zDArl~t(yd4ZrG`>u8(#jA4!FV2B%rO4#I3$~7p-v3)JYH8lYOqXxE~?RWc`kI6A_`cG4{W~Vz&s34 zmc4l4F`hUWj1x7qgUG{j5rE+ z5P5`CdM_1)JO;2CB?KBWNSFDcP=!eg?EnKX_Q-~Ly+qPPNxNhq>2Mj@hX%%jub~>@ zPQ2@(1c{Knp1nZ%VY3ArWMU?70n`9C%P?ExHJ}3@TvDL0x8CGUeMf|fR@Q}U-CCf# zswlF?XO0O1 z=2Pi{vZ8MDZE85~mPO4<5Lxfy9X#m@t>hhC@U{4;n?}(u`&GZ_SMX26FZxI5wt)jD ztMHfmA7l@(MXb#42M<@elPg0W8_oR8@Av27f0xg4jH~>!{1aFE{cNoNE6ZZBI+{GW zI$Rm{ufSCzimQa*4%bXx5slA5Q@0b_oNOneI0HEdK5kU}YSL{lw@#Zug}@Mn@-+%d zR9HwwK`JPq8E6WSf3juB%oK&Ot^gE1O-5gMnRY8 zB${M^mr!xIpy9p-{4hvzcn1JuI!#9-n}8jx0U?1cHrYTPv^gUUS^z#y9FWm6*oH0$ z@W$zs2gw;4hkNM8fp8Ly0Yf+hsQe-*={zEU3HDGyg&fS$^s2JixS1nz-KY>`|D!wS$x{A2(c`VLC%uE>Mi zDqI5c!g(D$VUPg;1@3?VfK%XLi<6M*kq*MPIJE=XI?o3}Ba>JFj{z@%Y5`ydI7H+( z0tN!a3;+xa6Q@D&7y{HOuLISw4~h|LT%pnR8m|ywHRld+5TGo;LkJiIUI90d!Y=Y4 z6$ISn#*2Uzlmnm^PQp&a6<7?vKqMv)A#x!C{kzKJWF#C&hI5b@uqa$`MGp3&$lZo6 z*n*Qi&;qUlNMzUi%W>!JI9h@zVF(VfkPcV`7jR1jiJ%-%JRm`Z=Sb_yK8PwV89-aS zFyI@B^guc23Ty@Yf(vyH#JJoby08?1Ky`Kc4`+0|h2TKYOMu556%A_@(3Bbn-PYTL z%oBv00!%}VbjkyhRXx5NIm2Uevr!BDQUT*pKPV(LQk?ZbMhFV(x>FwEMV-a34*ghT z@(I?MbZ|#fqAxLV(6HYf-#+fKiwBEGFMjXn@_UO}dTQSZ8)j|zTe{Del9IsI9ufPq zzNtxN$*Gx%WhLTJmc{?*mzmN2M$`JLB93As`9lB9A?*v@Uv)%uRqF=vzkb^hi&&7$ zCS^|PQ2qs8c-WVRrZZI(nGQC>XUWiXS!J52O0r@o#*+UpXB&MvU6bicNl0q+4NPE- zzJ7^~K3_ufn6$L*Sf6XWz8arj}-2ntkMf z()Huc=QVxl`AeVf-28?-`()6rS}^DRri*p=&prNRX!YB5H};;oJJzzge9poXTYsMQ z$j%>Ke_`yk<`K_S4m*E6HTmkd51dOlcbfKPf0p>u>r<|r-FQjcc=`Ho_guU2$<*f4 z^_%7Fkt3$R8yk~7`q_^L-`+D}!P`y0NuGV~X?y0kri9kLdwb@gyfyRR+VaDUZ66#D z{-QGa$H8f9&QE(j`nufjSoyTTH@7}@rR3t+ti&W=g73w(KVfT|*+5j+$V{K_v*Z+( zgddi{CkFC~Wb{cYt4U4EOGQKU@eN2eS;fxs9c=_Zq;FS(AI18lrsQQLB@Ry>+;slL z@C|#O-n9J9W8bLyVAimStFuAyL;e$jkGImujN~E7gC9TPzWm1N%LhMUeg7IX{+`$@ zi*nbrqDPTdU&6Cvidltq?Bww0CQtqIsqalX^vI2u8glf@hhN^Y^6poyjG{W{tqb4v zCOy}8O-1vEM|0h4zTIiVXP&ur>(OVHq=kg^kG@({J0-pL5(;!Rs9opj~#04 zYkB;_6Yhj9PaWED=HazN)=e68^vu6rX`E1#J1V{Z;qw=UkIVkU^}E7@_HFs+g@P2R z<=5Npe>nHG?dwlGc=e^nil#?4?ax@Ak@^o=nf3M8x81Yxuv?M7Va4|gSKZk1(2a5_ jP2N@d+OTQM9=cXgyk0L|S8@E}#A|!*`tX&H?W%tRC_e%% literal 0 HcmV?d00001 diff --git a/certs/test/digsigku.pem b/certs/test/digsigku.pem index edc30ba3d1..08eb8b2f5a 100644 --- a/certs/test/digsigku.pem +++ b/certs/test/digsigku.pem @@ -1,17 +1,16 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: - e3:81:4b:48:a5:70:61:70 - Signature Algorithm: ecdsa-with-SHA1 + Serial Number: 16393466893990650224 (0xe3814b48a5706170) + Signature Algorithm: ecdsa-with-SHA1 Issuer: C=US, ST=Washington, L=Seattle, O=Foofarah, OU=Arglebargle, CN=foobarbaz/emailAddress=info@worlss.com Validity - Not Before: Sep 10 00:45:36 2014 GMT - Not After : Jun 6 00:45:36 2017 GMT + Not Before: May 3 00:07:20 2017 GMT + Not After : Jan 28 00:07:20 2020 GMT Subject: C=US, ST=Washington, L=Seattle, O=Foofarah, OU=Arglebargle, CN=foobarbaz/emailAddress=info@worlss.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey - EC Public Key: + Public-Key: (256 bit) pub: 04:bb:33:ac:4c:27:50:4a:c6:4a:a5:04:c3:3c:de: 9f:36:db:72:2d:ce:94:ea:2b:fa:cb:20:09:39:2c: @@ -19,34 +18,40 @@ Certificate: 21:7f:f0:cf:18:da:91:11:02:34:86:e8:20:58:33: 0b:80:34:89:d8 ASN1 OID: prime256v1 + NIST CURVE: P-256 X509v3 extensions: X509v3 Subject Key Identifier: 5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 X509v3 Authority Key Identifier: keyid:5D:5D:26:EF:AC:7E:36:F9:9B:76:15:2B:4A:25:02:23:EF:B2:89:30 + DirName:/C=US/ST=Washington/L=Seattle/O=Foofarah/OU=Arglebargle/CN=foobarbaz/emailAddress=info@worlss.com + serial:E3:81:4B:48:A5:70:61:70 X509v3 Basic Constraints: critical CA:TRUE X509v3 Key Usage: critical Non Repudiation, Key Encipherment Signature Algorithm: ecdsa-with-SHA1 - 30:46:02:21:00:f4:36:ee:86:21:d5:c7:1f:2d:0d:bb:29:ae: - c1:74:ff:a3:ce:41:fe:cb:93:eb:ff:ef:fe:e3:4d:20:e5:18: - 65:02:21:00:b1:39:13:12:e2:b5:19:f2:8f:5b:40:ac:7a:5c: - e2:a6:e3:d3:e6:9f:79:3c:29:d8:c6:7d:88:f4:60:0c:48:00 + 30:46:02:21:00:fe:d6:30:36:fb:43:39:51:d7:4a:02:24:5e: + b4:b1:11:e3:83:66:00:fc:24:12:1a:7e:a8:05:77:ca:f7:24: + 2d:02:21:00:fb:59:c3:e9:6e:9b:f6:a2:46:0b:d8:ad:33:fb: + 89:2d:80:d6:1d:68:1f:f7:d7:93:f1:0b:7a:6b:81:f5:af:62 -----BEGIN CERTIFICATE----- -MIICfTCCAiOgAwIBAgIJAOOBS0ilcGFwMAkGByqGSM49BAEwgZExCzAJBgNVBAYT +MIIDKTCCAs+gAwIBAgIJAOOBS0ilcGFwMAkGByqGSM49BAEwgZExCzAJBgNVBAYT AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMREwDwYD VQQKDAhGb29mYXJhaDEUMBIGA1UECwwLQXJnbGViYXJnbGUxEjAQBgNVBAMMCWZv -b2JhcmJhejEeMBwGCSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMB4XDTE0MDkx -MDAwNDUzNloXDTE3MDYwNjAwNDUzNlowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQI +b2JhcmJhejEeMBwGCSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMB4XDTE3MDUw +MzAwMDcyMFoXDTIwMDEyODAwMDcyMFowgZExCzAJBgNVBAYTAlVTMRMwEQYDVQQI DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMREwDwYDVQQKDAhGb29mYXJh aDEUMBIGA1UECwwLQXJnbGViYXJnbGUxEjAQBgNVBAMMCWZvb2JhcmJhejEeMBwG CSqGSIb3DQEJARYPaW5mb0B3b3Jsc3MuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D AQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFb -l5Ihf/DPGNqREQI0huggWDMLgDSJ2KNjMGEwHQYDVR0OBBYEFF1dJu+sfjb5m3YV -K0olAiPvsokwMB8GA1UdIwQYMBaAFF1dJu+sfjb5m3YVK0olAiPvsokwMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgVgMAkGByqGSM49BAEDSQAwRgIhAPQ2 -7oYh1ccfLQ27Ka7BdP+jzkH+y5Pr/+/+400g5RhlAiEAsTkTEuK1GfKPW0Cselzi -puPT5p95PCnYxn2I9GAMSAA= +l5Ihf/DPGNqREQI0huggWDMLgDSJ2KOCAQ0wggEJMB0GA1UdDgQWBBRdXSbvrH42 ++Zt2FStKJQIj77KJMDCBxgYDVR0jBIG+MIG7gBRdXSbvrH42+Zt2FStKJQIj77KJ +MKGBl6SBlDCBkTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAO +BgNVBAcMB1NlYXR0bGUxETAPBgNVBAoMCEZvb2ZhcmFoMRQwEgYDVQQLDAtBcmds +ZWJhcmdsZTESMBAGA1UEAwwJZm9vYmFyYmF6MR4wHAYJKoZIhvcNAQkBFg9pbmZv +QHdvcmxzcy5jb22CCQDjgUtIpXBhcDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIFYDAJBgcqhkjOPQQBA0kAMEYCIQD+1jA2+0M5UddKAiRetLER44NmAPwk +Ehp+qAV3yvckLQIhAPtZw+lum/aiRgvYrTP7iS2A1h1oH/fXk/ELemuB9a9i -----END CERTIFICATE----- diff --git a/certs/test/gen-ext-certs.sh b/certs/test/gen-ext-certs.sh new file mode 100644 index 0000000000..20b61e9c93 --- /dev/null +++ b/certs/test/gen-ext-certs.sh @@ -0,0 +1,69 @@ +#!/bin/sh + +TMP="/tmp/`basename $0`" + +gen_cert() { + openssl req -x509 -keyform DER -key certs/server-key.der \ + -outform DER -out $OUT -config $CONFIG \ + >$TMP 2>&1 + + if [ "$?" = "0" -a -f $OUT ]; then + echo "Created: $OUT" + else + cat $TMP + echo "Failed: $OUT" + fi + + rm $TMP +} + +OUT=certs/test/cert-ext-nc.der +KEYFILE=certs/test/cert-ext-nc-key.der +CONFIG=certs/test/cert-ext-nc.cfg +tee >$CONFIG <$CONFIG <> $OPTION_FILE echo "" >> $OPTION_FILE echo -#backwards compatability for those who have included options or version +#backwards compatibility for those who have included options or version touch cyassl/options.h echo "/* cyassl options.h" > cyassl/options.h echo " * generated from wolfssl/options.h" >> cyassl/options.h @@ -3308,6 +3596,7 @@ echo " * AES: $ENABLED_AES" echo " * AES-NI: $ENABLED_AESNI" echo " * AES-GCM: $ENABLED_AESGCM" echo " * AES-CCM: $ENABLED_AESCCM" +echo " * AES-CTR: $ENABLED_AESCTR" echo " * DES3: $ENABLED_DES3" echo " * IDEA: $ENABLED_IDEA" echo " * Camellia: $ENABLED_CAMELLIA" @@ -3351,12 +3640,15 @@ echo " * CODING: $ENABLED_CODING" echo " * MEMORY: $ENABLED_MEMORY" echo " * I/O POOL: $ENABLED_IOPOOL" echo " * LIGHTY: $ENABLED_LIGHTY" +echo " * HAPROXY: $ENABLED_HAPROXY" echo " * STUNNEL: $ENABLED_STUNNEL" +echo " * NGINX: $ENABLED_NGINX" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" echo " * SCTP: $ENABLED_SCTP" echo " * Old TLS Versions: $ENABLED_OLD_TLS" echo " * SSL version 3.0: $ENABLED_SSLV3" +echo " * TLS v1.3: $ENABLED_TLS13" echo " * OCSP: $ENABLED_OCSP" echo " * OCSP Stapling: $ENABLED_CERTIFICATE_STATUS_REQUEST" echo " * OCSP Stapling v2: $ENABLED_CERTIFICATE_STATUS_REQUEST_V2" @@ -3391,6 +3683,8 @@ echo " * Async Crypto: $ENABLED_ASYNCCRYPT" echo " * Cavium: $ENABLED_CAVIUM" echo " * ARM ASM: $ENABLED_ARMASM" echo " * AES Key Wrap: $ENABLED_AESKEYWRAP" +echo " * Write duplicate: $ENABLED_WRITEDUP" +echo " * Intel Quick Assist: $ENABLED_INTEL_QA" echo "" echo "---" diff --git a/cyassl/ctaocrypt/settings.h b/cyassl/ctaocrypt/settings.h index c12a962ffd..4de8b13ca9 100644 --- a/cyassl/ctaocrypt/settings.h +++ b/cyassl/ctaocrypt/settings.h @@ -246,7 +246,7 @@ /* Micrium will use Visual Studio for compilation but not the Win32 API */ #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) \ - && !defined(EBSNET) && !defined(CYASSL_EROAD) + && !defined(EBSNET) && !defined(CYASSL_EROAD) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif diff --git a/cyassl/openssl/include.am b/cyassl/openssl/include.am index f5c3c56e97..c0a6d125f8 100644 --- a/cyassl/openssl/include.am +++ b/cyassl/openssl/include.am @@ -32,6 +32,7 @@ nobase_include_HEADERS+= \ cyassl/openssl/rand.h \ cyassl/openssl/rsa.h \ cyassl/openssl/sha.h \ + cyassl/openssl/ssl23.h \ cyassl/openssl/ssl.h \ cyassl/openssl/stack.h \ cyassl/openssl/ui.h \ diff --git a/cyassl/openssl/ssl23.h b/cyassl/openssl/ssl23.h new file mode 100644 index 0000000000..f8aa85681f --- /dev/null +++ b/cyassl/openssl/ssl23.h @@ -0,0 +1,3 @@ +/* ssl23.h for openssl */ + +#include diff --git a/examples/client/client.c b/examples/client/client.c index 7d5b43e2a9..e4d26216d6 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -42,11 +42,6 @@ #include -#if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER) - /* in case memory tracker wants stats */ - #define WOLFSSL_TRACK_MEMORY -#endif - #include #include @@ -57,6 +52,8 @@ static int devId = INVALID_DEVID; #endif +#define DEFAULT_TIMEOUT_SEC 2 + /* 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 @@ -73,7 +70,7 @@ #endif -static void NonBlockingSSL_Connect(WOLFSSL* ssl) +static int NonBlockingSSL_Connect(WOLFSSL* ssl) { #ifndef WOLFSSL_CALLBACKS int ret = wolfSSL_connect(ssl); @@ -96,7 +93,7 @@ static void NonBlockingSSL_Connect(WOLFSSL* ssl) #ifdef WOLFSSL_ASYNC_CRYPT else if (error == WC_PENDING_E) { ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } + if (ret < 0) break; } #endif @@ -108,11 +105,11 @@ static void NonBlockingSSL_Connect(WOLFSSL* ssl) } if ((select_ret == TEST_RECV_READY) || - (select_ret == TEST_ERROR_READY)) { + (select_ret == TEST_ERROR_READY) || error == WC_PENDING_E) { #ifndef WOLFSSL_CALLBACKS ret = wolfSSL_connect(ssl); #else - ret = wolfSSL_connect_ex(ssl,handShakeCB,timeoutCB,timeout); + ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout); #endif error = wolfSSL_get_error(ssl, 0); } @@ -129,8 +126,8 @@ static void NonBlockingSSL_Connect(WOLFSSL* ssl) error = SSL_FATAL_ERROR; } } - if (ret != SSL_SUCCESS) - err_sys("SSL_connect failed"); + + return ret; } @@ -164,10 +161,15 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* time passed in number of connects give average */ int times = benchmark; int loops = resumeSession ? 2 : 1; - int i = 0; + int i = 0, err, ret; #ifndef NO_SESSION_CACHE WOLFSSL_SESSION* benchSession = NULL; #endif +#ifdef WOLFSSL_TLS13 + byte* reply[80]; + char msg[] = "hello wolfssl!"; +#endif + (void)resumeSession; while (loops--) { @@ -182,6 +184,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, if (ssl == NULL) err_sys("unable to get SSL object"); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); #ifndef NO_SESSION_CACHE @@ -191,8 +194,33 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } - if (wolfSSL_connect(ssl) != SSL_SUCCESS) + + do { + err = 0; /* reset error */ + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != SSL_SUCCESS) { err_sys("SSL_connect failed"); + } + + #ifdef WOLFSSL_TLS13 + if (resumeSession) { + if (wolfSSL_write(ssl, msg, sizeof(msg)-1) <= 0) + err_sys("SSL_write failed"); + + if (wolfSSL_read(ssl, reply, sizeof(reply)-1) <= 0) + err_sys("SSL_read failed"); + } + #endif wolfSSL_shutdown(ssl); #ifndef NO_SESSION_CACHE @@ -224,17 +252,32 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; WOLFSSL* ssl; - int ret; + int ret = 0, err = 0; start = current_time(1); ssl = wolfSSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL object"); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } - if (wolfSSL_connect(ssl) == SSL_SUCCESS) { + + do { + err = 0; /* reset error */ + ret = wolfSSL_connect(ssl); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret == SSL_SUCCESS) { /* Perform throughput test */ char *tx_buffer, *rx_buffer; @@ -242,14 +285,18 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, conn_time = current_time(0) - start; /* Allocate TX/RX buffers */ - tx_buffer = (char*)malloc(TEST_BUFFER_SIZE); - rx_buffer = (char*)malloc(TEST_BUFFER_SIZE); - if(tx_buffer && rx_buffer) { + tx_buffer = (char*)XMALLOC(TEST_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + rx_buffer = (char*)XMALLOC(TEST_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tx_buffer && rx_buffer) { WC_RNG rng; /* Startup the RNG */ + #if !defined(HAVE_FIPS) && defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_InitRng_ex(&rng, NULL, devId); + #else ret = wc_InitRng(&rng); - if(ret == 0) { + #endif + if (ret == 0) { int xfer_bytes; /* Generate random data to send */ @@ -261,7 +308,7 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, /* Perform TX and RX of bytes */ xfer_bytes = 0; - while(throughput > xfer_bytes) { + while (throughput > xfer_bytes) { int len, rx_pos, select_ret; /* Determine packet size */ @@ -269,25 +316,45 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, /* Perform TX */ start = current_time(1); - if (wolfSSL_write(ssl, tx_buffer, len) != len) { - int writeErr = wolfSSL_get_error(ssl, 0); - printf("wolfSSL_write error %d!\n", writeErr); - err_sys("wolfSSL_write failed"); + do { + err = 0; /* reset error */ + ret = wolfSSL_write(ssl, tx_buffer, len); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != len) { + printf("SSL_write bench error %d!\n", err); + err_sys("SSL_write failed"); } tx_time += current_time(0) - start; /* Perform RX */ - select_ret = tcp_select(sockfd, 1); /* Timeout=1 second */ + select_ret = tcp_select(sockfd, DEFAULT_TIMEOUT_SEC); if (select_ret == TEST_RECV_READY) { start = current_time(1); rx_pos = 0; - while(rx_pos < len) { - ret = wolfSSL_read(ssl, &rx_buffer[rx_pos], len - rx_pos); - if(ret <= 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("wolfSSL_read error %d!\n", readErr); - err_sys("wolfSSL_read failed"); + while (rx_pos < len) { + ret = wolfSSL_read(ssl, &rx_buffer[rx_pos], + len - rx_pos); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read bench error %d\n", err); + err_sys("SSL_read failed"); } } else { @@ -299,6 +366,10 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, /* Compare TX and RX buffers */ if(XMEMCMP(tx_buffer, rx_buffer, len) != 0) { + free(tx_buffer); + tx_buffer = NULL; + free(rx_buffer); + rx_buffer = NULL; err_sys("Compare TX and RX buffers failed"); } @@ -313,8 +384,8 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, else { err_sys("Client buffer malloc failed"); } - if(tx_buffer) free(tx_buffer); - if(rx_buffer) free(rx_buffer); + if(tx_buffer) XFREE(tx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if(rx_buffer) XFREE(rx_buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { err_sys("wolfSSL_connect failed"); @@ -354,15 +425,13 @@ static int StartTLS_Init(SOCKET_T* sockfd) if (sockfd == NULL) return BAD_FUNC_ARG; - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); - /* S: 220 SMTP service ready */ - if (recv(*sockfd, tmpBuf, sizeof(tmpBuf), 0) < 0) + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0) err_sys("failed to read STARTTLS command\n"); if (!XSTRNCMP(tmpBuf, starttlsCmd[0], XSTRLEN(starttlsCmd[0]))) { printf("%s\n", tmpBuf); - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); } else { err_sys("incorrect STARTTLS command received"); } @@ -373,12 +442,12 @@ static int StartTLS_Init(SOCKET_T* sockfd) err_sys("failed to send STARTTLS EHLO command\n"); /* S: 250 offers a warm hug of welcome */ - if (recv(*sockfd, tmpBuf, sizeof(tmpBuf), 0) < 0) + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0) err_sys("failed to read STARTTLS command\n"); if (!XSTRNCMP(tmpBuf, starttlsCmd[2], XSTRLEN(starttlsCmd[2]))) { printf("%s\n", tmpBuf); - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); } else { err_sys("incorrect STARTTLS command received"); } @@ -390,12 +459,12 @@ static int StartTLS_Init(SOCKET_T* sockfd) } /* S: 220 Go ahead */ - if (recv(*sockfd, tmpBuf, sizeof(tmpBuf), 0) < 0) + XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); + if (recv(*sockfd, tmpBuf, sizeof(tmpBuf)-1, 0) < 0) err_sys("failed to read STARTTLS command\n"); if (!XSTRNCMP(tmpBuf, starttlsCmd[4], XSTRLEN(starttlsCmd[4]))) { printf("%s\n", tmpBuf); - XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); } else { err_sys("incorrect STARTTLS command received, expected 220"); } @@ -406,7 +475,7 @@ static int StartTLS_Init(SOCKET_T* sockfd) /* Closes down the SMTP connection */ static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) { - int ret; + int ret, err = 0; char tmpBuf[256]; if (ssl == NULL) @@ -417,13 +486,38 @@ static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) XMEMSET(tmpBuf, 0, sizeof(tmpBuf)); /* C: QUIT */ - if (wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])) != - (int)XSTRLEN(starttlsCmd[5])) + do { + ret = wolfSSL_write(ssl, starttlsCmd[5], (int)XSTRLEN(starttlsCmd[5])); + if (ret < 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != (int)XSTRLEN(starttlsCmd[5])) { err_sys("failed to send SMTP QUIT command\n"); + } /* S: 221 2.0.0 Service closing transmission channel */ - if (wolfSSL_read(ssl, tmpBuf, sizeof(tmpBuf)) < 0) + do { + ret = wolfSSL_read(ssl, tmpBuf, sizeof(tmpBuf)); + if (ret < 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret < 0) { err_sys("failed to read SMTP closing down response\n"); + } printf("%s\n", tmpBuf); @@ -446,9 +540,9 @@ static void Usage(void) CLIENT_DEFAULT_VERSION); printf("-V Prints valid ssl version numbers, SSLv3(0) - TLS1.2(3)\n"); printf("-l Cipher suite list (: delimited)\n"); - printf("-c Certificate file, default %s\n", cliCert); - printf("-k Key file, default %s\n", cliKey); - printf("-A Certificate Authority file, default %s\n", caCert); + printf("-c Certificate file, default %s\n", cliCertFile); + printf("-k Key file, default %s\n", cliKeyFile); + printf("-A Certificate Authority file, default %s\n", caCertFile); #ifndef NO_DH printf("-Z Minimum DH key bits, default %d\n", DEFAULT_MIN_DHKEY_BITS); @@ -459,7 +553,6 @@ static void Usage(void) #endif printf("-B Benchmark throughput using bytes and print stats\n"); printf("-s Use pre Shared keys\n"); - printf("-t Track wolfSSL memory use\n"); printf("-d Disable peer checks\n"); printf("-D Override Date Errors example\n"); printf("-e List Every cipher suite available, \n"); @@ -482,6 +575,7 @@ static void Usage(void) printf("-f Fewer packets/group messages\n"); printf("-x Disable client cert/key loading\n"); printf("-X Driven by eXternal test case\n"); + printf("-j Use verify callback override\n"); #ifdef SHOW_SIZES printf("-z Print structure sizes\n"); #endif @@ -523,6 +617,18 @@ static void Usage(void) #ifdef HAVE_WNR printf("-q Whitewood config file, default %s\n", wnrConfig); #endif + printf("-H Force use of the default cipher suite list\n"); +#ifdef WOLFSSL_TLS13 + printf("-J Use HelloRetryRequest to choose group for KE\n"); + printf("-K Key Exchange for PSK not using (EC)DHE\n"); + printf("-I Update keys and IVs before sending data\n"); +#ifndef NO_DH + printf("-y Key Share with FFDHE named groups only\n"); +#endif +#ifdef HAVE_ECC + printf("-Y Key Share with ECC named groups only\n"); +#endif +#endif /* WOLFSSL_TLS13 */ } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -545,7 +651,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif char reply[80]; - int input; int msgSz = (int)XSTRLEN(msg); int resumeSz = (int)XSTRLEN(resumeMsg); @@ -578,7 +683,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif int scr = 0; /* allow secure renegotiation */ int forceScr = 0; /* force client initiaed scr */ - int trackMemory = 0; int useClientCert = 1; int fewerPackets = 0; int atomicUser = 0; @@ -588,12 +692,14 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; - const char* verifyCert = caCert; - const char* ourCert = cliCert; - const char* ourKey = cliKey; + int useDefCipherList = 0; + const char* verifyCert = caCertFile; + const char* ourCert = cliCertFile; + const char* ourKey = cliKeyFile; int doSTARTTLS = 0; char* starttlsProt = NULL; + int useVerifyCb = 0; #ifdef WOLFSSL_TRUST_PEER_CERT const char* trustCert = NULL; @@ -615,7 +721,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_EXTENDED_MASTER byte disableExtMasterSecret = 0; #endif - +#ifdef WOLFSSL_TLS13 + int helloRetry = 0; + int onlyKeyShare = 0; + int noPskDheKe = 0; +#endif + int updateKeysIVs = 0; #ifdef HAVE_OCSP int useOcsp = 0; @@ -625,6 +736,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; #endif + char buffer[WOLFSSL_MAX_ERROR_SZ]; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -632,9 +744,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA - verifyCert = (char*)eccCert; - ourCert = (char*)cliEccCert; - ourKey = (char*)cliEccKey; + verifyCert = (char*)eccCertFile; + ourCert = (char*)cliEccCertFile; + ourKey = (char*)cliEccKeyFile; #endif (void)resumeSz; (void)session; @@ -652,13 +764,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void)minDhKeyBits; (void)alpnList; (void)alpn_opt; + (void)updateKeysIVs; StackTrap(); #ifndef WOLFSSL_VXWORKS - while ((ch = mygetopt(argc, argv, - "?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:TnoO:aB:W:E:M:q:")) - != -1) { + /* Not used: t, Q */ + while ((ch = mygetopt(argc, argv, "?" + "ab:c:defgh:ijk:l:mnop:q:rsuv:wxyz" + "A:B:CDE:F:GHIJKL:M:NO:PRS:TUVW:XYZ:")) != -1) { switch (ch) { case '?' : Usage(); @@ -702,12 +816,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) usePsk = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif - break; - #ifdef WOLFSSL_TRUST_PEER_CERT case 'E' : trustCert = myoptarg; @@ -757,7 +865,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case 'v' : version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); exit(MY_EX_USAGE); } @@ -771,6 +879,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) cipherList = myoptarg; break; + case 'H' : + useDefCipherList = 1; + break; + case 'A' : verifyCert = myoptarg; break; @@ -930,6 +1042,40 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case 'J' : + #ifdef WOLFSSL_TLS13 + helloRetry = 1; + #endif + break; + + case 'K' : + #ifdef WOLFSSL_TLS13 + noPskDheKe = 1; + #endif + break; + + case 'I' : + #ifdef WOLFSSL_TLS13 + updateKeysIVs = 1; + #endif + break; + + case 'y' : + #if defined(WOLFSSL_TLS13) && !defined(NO_DH) + onlyKeyShare = 1; + #endif + break; + + case 'Y' : + #if defined(WOLFSSL_TLS13) && defined(HAVE_ECC) + onlyKeyShare = 2; + #endif + break; + + case 'j' : + useVerifyCb = 1; + break; + default: Usage(); exit(MY_EX_USAGE); @@ -1024,11 +1170,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } } -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - InitMemoryTracker(); -#endif - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) err_sys("can't load whitewood net random config file"); @@ -1058,6 +1199,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case 3: method = wolfTLSv1_2_client_method(); break; + #ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_client_method(); + break; + #endif #endif #ifdef WOLFSSL_DTLS @@ -1086,13 +1232,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef SINGLE_THREADED if (wolfSSL_CTX_new_rng(ctx) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("Single Threaded new rng at CTX failed"); } #endif - if (cipherList) { - if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) + if (cipherList && !useDefCipherList) { + if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 1"); + } } #ifdef WOLFSSL_LEANPSK @@ -1127,8 +1276,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) - !=SSL_SUCCESS) + !=SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 2"); + } } #endif if (useClientCert) { @@ -1138,10 +1289,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (useAnon) { #ifdef HAVE_ANON - if (cipherList == NULL) { + if (cipherList == NULL || (cipherList && useDefCipherList)) { wolfSSL_CTX_allow_anon_cipher(ctx); - if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS) + if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") + != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 4"); + } } #endif if (useClientCert) { @@ -1162,6 +1316,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (cipherList == NULL) { /* don't use EDH, can't sniff tmp keys */ if (wolfSSL_CTX_set_cipher_list(ctx, "AES128-SHA") != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("client can't set cipher list 3"); } } @@ -1169,6 +1324,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_OCSP if (useOcsp) { + #ifdef HAVE_IO_TIMEOUT + wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC); + #endif + if (ocspUrl != NULL) { wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE @@ -1183,61 +1342,71 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_SetCACb(ctx, CaCb); #endif -#ifdef VERIFY_CALLBACK - wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); -#endif #if !defined(NO_CERTS) if (useClientCert){ #if !defined(NO_FILESYSTEM) - if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS) + if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) + != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("can't load client cert file, check file and run from" " wolfSSL home dir"); + } if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) - != SSL_SUCCESS) + != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("can't load client private key file, check file and run " "from wolfSSL home dir"); + } #else load_buffer(ctx, ourCert, WOLFSSL_CERT_CHAIN); load_buffer(ctx, ourKey, WOLFSSL_KEY); #endif /* !defined(NO_FILESYSTEM) */ } - if (!usePsk && !useAnon) { + if (!usePsk && !useAnon && !useVerifyCb) { #if !defined(NO_FILESYSTEM) - if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) + != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("can't load ca file, Please run from wolfSSL home dir"); + } #else load_buffer(ctx, verifyCert, WOLFSSL_CA); #endif /* !defined(NO_FILESYSTEM) */ #ifdef HAVE_ECC /* load ecc verify too, echoserver uses it by default w/ ecc */ #if !defined(NO_FILESYSTEM) - if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, eccCertFile, 0) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); + } #else - load_buffer(ctx, eccCert, WOLFSSL_CA); + load_buffer(ctx, eccCertFile, WOLFSSL_CA); #endif /* !defined(NO_FILESYSTEM) */ #endif /* HAVE_ECC */ #if defined(WOLFSSL_TRUST_PEER_CERT) && !defined(NO_FILESYSTEM) if (trustCert) { if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, SSL_FILETYPE_PEM)) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("can't load trusted peer cert file"); } } #endif /* WOLFSSL_TRUST_PEER_CERT && !NO_FILESYSTEM */ } - if (!usePsk && !useAnon && doPeerCheck == 0) + if (useVerifyCb) + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); + else if (!usePsk && !useAnon && doPeerCheck == 0) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); - if (!usePsk && !useAnon && overrideDateErrors == 1) + else if (!usePsk && !useAnon && overrideDateErrors == 1) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb); #endif /* !defined(NO_CERTS) */ #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -1245,27 +1414,37 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_SNI if (sniHostName) if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) - != SSL_SUCCESS) + != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("UseSNI failed"); + } #endif #ifdef HAVE_MAX_FRAGMENT if (maxFragment) - if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS) + if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("UseMaxFragment failed"); + } #endif #ifdef HAVE_TRUNCATED_HMAC if (truncatedHMAC) - if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) + if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("UseTruncatedHMAC failed"); + } #endif #ifdef HAVE_SESSION_TICKET - if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) + if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("UseSessionTicket failed"); + } #endif #ifdef HAVE_EXTENDED_MASTER if (disableExtMasterSecret) - if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != SSL_SUCCESS) + if (wolfSSL_CTX_DisableExtendedMasterSecret(ctx) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); err_sys("DisableExtendedMasterSecret failed"); + } #endif if (benchmark) { @@ -1288,39 +1467,55 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); #endif + #if defined(OPENSSL_EXTRA) + if (wolfSSL_CTX_get_read_ahead(ctx) != 0) { + wolfSSL_CTX_free(ctx); + err_sys("bad read ahead default value"); + } + if (wolfSSL_CTX_set_read_ahead(ctx, 1) != SSL_SUCCESS) { + wolfSSL_CTX_free(ctx); + err_sys("error setting read ahead value"); + } + #endif + + #ifdef WOLFSSL_TLS13 + if (noPskDheKe) + wolfSSL_CTX_no_dhe_psk(ctx); + #endif + ssl = wolfSSL_new(ctx); - if (ssl == NULL) + if (ssl == NULL) { + wolfSSL_CTX_free(ctx); err_sys("unable to get SSL object"); + } #ifdef OPENSSL_EXTRA wolfSSL_KeepArrays(ssl); #endif - #ifdef HAVE_SUPPORTED_CURVES /* add curves to supported curves extension */ - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp256r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP384R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp384r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP521R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp521r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP224R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp224r1"); - } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP192R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp192r1"); + #ifdef WOLFSSL_TLS13 + if (!helloRetry) { + if (onlyKeyShare == 0 || onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != SSL_SUCCESS) { + err_sys("unable to use DH 2048-bit parameters"); + } + #endif } - if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP160R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp160r1"); + if (onlyKeyShare == 0 || onlyKeyShare == 2) { + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) + != SSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); + } + if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP384R1) + != SSL_SUCCESS) { + err_sys("unable to use curve secp384r1"); + } } + } + else { + wolfSSL_NoKeyShares(ssl); + } #endif #ifdef HAVE_SESSION_TICKET @@ -1338,8 +1533,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) switch (statusRequest) { case WOLFSSL_CSR_OCSP: if (wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP, - WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS) + WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("UseCertificateStatusRequest failed"); + } break; } @@ -1353,14 +1551,20 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) case WOLFSSL_CSR2_OCSP: if (wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE) - != SSL_SUCCESS) + != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("UseCertificateStatusRequest failed"); + } break; case WOLFSSL_CSR2_OCSP_MULTI: if (wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP_MULTI, 0) - != SSL_SUCCESS) + != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("UseCertificateStatusRequest failed"); + } break; } @@ -1371,30 +1575,51 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("error in setting fd"); } /* STARTTLS */ if (doSTARTTLS) { if (StartTLS_Init(&sockfd) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("error during STARTTLS protocol"); } } #ifdef HAVE_CRL if (disableCRL == 0) { - if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS) + #ifdef HAVE_IO_TIMEOUT + wolfIO_SetTimeout(DEFAULT_TIMEOUT_SEC); + #endif + + if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("can't enable crl check"); - if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS) + } + if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) + != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("can't load crl, check crlfile and date validity"); - if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) + } + if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("can't set crl callback"); + } } #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { - if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) + if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("can't enable secure renegotiation"); + } } #endif #ifdef ATOMIC_USER @@ -1411,58 +1636,66 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (nonBlocking) { wolfSSL_set_using_nonblock(ssl, 1); tcp_set_nonblocking(&sockfd); - NonBlockingSSL_Connect(ssl); + ret = NonBlockingSSL_Connect(ssl); } else { 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 */ + err = 0; /* reset error */ ret = wolfSSL_connect(ssl); if (ret != SSL_SUCCESS) { err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } - } 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)); - err_sys("wolfSSL_connect failed"); - /* see note at top of README */ - /* if you're getting an error here */ - } + } while (err == WC_PENDING_E); } #else - timeout.tv_sec = 2; + timeout.tv_sec = DEFAULT_TIMEOUT_SEC; timeout.tv_usec = 0; - NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ + ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif + if (ret != SSL_SUCCESS) { + printf("wolfSSL_connect error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + err_sys("wolfSSL_connect failed"); + /* see note at top of README */ + /* if you're getting an error here */ + } + showPeer(ssl); #ifdef OPENSSL_EXTRA { - byte* rnd; - byte* pt; - int size; + byte* rnd; + byte* pt; + size_t size; /* get size of buffer then print */ size = wolfSSL_get_client_random(NULL, NULL, 0); - if (size < 0) { + if (size == 0) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("error getting client random buffer size"); } rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (rnd == NULL) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("error creating client random buffer"); } size = wolfSSL_get_client_random(ssl, rnd, size); - if (size < 0) { + if (size == 0) { XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("error getting client random buffer"); } @@ -1476,6 +1709,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (doSTARTTLS) { if (XSTRNCMP(starttlsProt, "smtp", 4) == 0) { if (SMTP_Shutdown(ssl, wc_shutdown) != SSL_SUCCESS) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("error closing STARTTLS connection"); } } @@ -1512,10 +1747,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) " nonblocking yet"); } else { if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) { - char buffer[WOLFSSL_MAX_ERROR_SZ]; err = wolfSSL_get_error(ssl, 0); printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("wolfSSL_Rehandshake failed"); } } @@ -1535,27 +1771,75 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) /* allow some time for exporting the session */ #ifdef WOLFSSL_SESSION_EXPORT_DEBUG - #ifdef USE_WINDOWS_API - Sleep(500); - #elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); - #else - sleep(1); - #endif +#ifdef USE_WINDOWS_API + Sleep(500); +#elif defined(WOLFSSL_TIRTOS) + Task_sleep(1); +#else + sleep(1); +#endif #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ - if (wolfSSL_write(ssl, msg, msgSz) != msgSz) + +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs) + wolfSSL_update_keys(ssl); +#endif + + do { + err = 0; /* reset error */ + ret = wolfSSL_write(ssl, msg, msgSz); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != msgSz) { + printf("SSL_write msg error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("SSL_write failed"); + } - input = wolfSSL_read(ssl, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; + do { + err = 0; /* reset error */ + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E || err == SSL_ERROR_WANT_READ); + if (ret > 0) { + reply[ret] = 0; printf("Server response: %s\n", reply); if (sendGET) { /* get html */ while (1) { - input = wolfSSL_read(ssl, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; + do { + err = 0; /* reset error */ + ret = wolfSSL_read(ssl, reply, sizeof(reply)-1); + if (ret <= 0) { + err = wolfSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; printf("%s\n", reply); } else @@ -1563,11 +1847,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } } } - else if (input < 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("wolfSSL_read error %d!\n", readErr); - err_sys("wolfSSL_read failed"); + if (ret < 0) { + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read reply error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + err_sys("SSL_read failed"); } } @@ -1575,8 +1861,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (resumeSession) { session = wolfSSL_get_session(ssl); sslResume = wolfSSL_new(ctx); - if (sslResume == NULL) + if (sslResume == NULL) { + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); err_sys("unable to get SSL object"); + } } #endif @@ -1605,6 +1894,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume); if (wolfSSL_set_fd(sslResume, sockfd) != SSL_SUCCESS) { + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); err_sys("error in setting fd"); } #ifdef HAVE_ALPN @@ -1616,8 +1907,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { - if (wolfSSL_UseSecureRenegotiation(sslResume) != SSL_SUCCESS) + if (wolfSSL_UseSecureRenegotiation(sslResume) != SSL_SUCCESS) { + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); err_sys("can't enable secure renegotiation"); + } } #endif wolfSSL_set_session(sslResume, session); @@ -1625,30 +1919,20 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB, (void*)"resumed session"); #endif - #ifdef HAVE_SUPPORTED_CURVES /* add curves to supported curves extension */ - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP256R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp256r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP384R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp384r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP521R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp521r1"); - } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP224R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp224r1"); + + #ifdef WOLFSSL_TLS13 + #ifdef HAVE_FFDHE_2048 + if (wolfSSL_UseKeyShare(sslResume, WOLFSSL_FFDHE_2048) != SSL_SUCCESS) { + err_sys("unable to use DH 2048-bit parameters"); } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP192R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp192r1"); + #endif + if (wolfSSL_UseKeyShare(sslResume, + WOLFSSL_ECC_SECP256R1) != SSL_SUCCESS) { + err_sys("unable to use curve secp256r1"); } - if (wolfSSL_UseSupportedCurve(sslResume, WOLFSSL_ECC_SECP160R1) - != SSL_SUCCESS) { - err_sys("unable to set curve secp160r1"); + if (wolfSSL_UseKeyShare(sslResume, + WOLFSSL_ECC_SECP384R1) != SSL_SUCCESS) { + err_sys("unable to use curve secp384r1"); } #endif @@ -1656,15 +1940,37 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (nonBlocking) { wolfSSL_set_using_nonblock(sslResume, 1); tcp_set_nonblocking(&sockfd); - NonBlockingSSL_Connect(sslResume); + ret = NonBlockingSSL_Connect(sslResume); + } + else { + do { + err = 0; /* reset error */ + ret = wolfSSL_connect(sslResume); + if (ret != SSL_SUCCESS) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, + WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); } - else if (wolfSSL_connect(sslResume) != SSL_SUCCESS) - err_sys("SSL resume failed"); #else - timeout.tv_sec = 2; + timeout.tv_sec = DEFAULT_TIMEOUT_SEC; timeout.tv_usec = 0; - NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ + ret = NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif + if (ret != SSL_SUCCESS) { + printf("wolfSSL_connect resume error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); + err_sys("wolfSSL_connect resume failed"); + } + showPeer(sslResume); if (wolfSSL_session_reused(sslResume)) @@ -1701,47 +2007,104 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ - if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz) + do { + err = 0; /* reset error */ + ret = wolfSSL_write(sslResume, resumeMsg, resumeSz); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != resumeSz) { + printf("SSL_write resume error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); err_sys("SSL_write failed"); + } if (nonBlocking) { /* give server a chance to bounce a message back to client */ - #ifdef USE_WINDOWS_API - Sleep(500); - #elif defined(WOLFSSL_TIRTOS) - Task_sleep(1); - #else - sleep(1); - #endif + #ifdef USE_WINDOWS_API + Sleep(500); + #elif defined(WOLFSSL_TIRTOS) + Task_sleep(1); + #else + sleep(1); + #endif } - input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); - - if (input > 0) { - reply[input] = 0; - printf("Server resume response: %s\n", reply); - - if (sendGET) { /* get html */ - while (1) { - input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); - if (input > 0) { - reply[input] = 0; - printf("%s\n", reply); + do { + err = 0; /* reset error */ + ret = wolfSSL_read(sslResume, reply, sizeof(reply)-1); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; + printf("Server resume response: %s\n", reply); + + if (sendGET) { /* get html */ + while (1) { + do { + err = 0; /* reset error */ + ret = wolfSSL_read(sslResume, reply, sizeof(reply)-1); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, + WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; + printf("%s\n", reply); + } + else + break; } - else - break; } } - } else if (input < 0) { - int readErr = wolfSSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("wolfSSL_read error %d!\n", readErr); - err_sys("wolfSSL_read failed"); + if (ret < 0) { + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read resume error %d, %s\n", err, + wolfSSL_ERR_error_string(err, buffer)); + wolfSSL_free(sslResume); + wolfSSL_CTX_free(ctx); + err_sys("SSL_read failed"); + } } - } /* try to send session break */ - wolfSSL_write(sslResume, msg, msgSz); + do { + err = 0; /* reset error */ + ret = wolfSSL_write(sslResume, msg, msgSz); + if (ret <= 0) { + err = wolfSSL_get_error(sslResume, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(sslResume, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); ret = wolfSSL_shutdown(sslResume); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) @@ -1760,11 +2123,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfAsync_DevClose(&devId); #endif -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - ShowMemoryTracker(); -#endif /* USE_WOLFSSL_MEMORY */ - /* There are use cases when these assignments are not read. To avoid * potential confusion those warnings have been handled here. */ @@ -1773,7 +2131,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) (void) verifyCert; (void) ourCert; (void) ourKey; - (void) trackMemory; + (void) useVerifyCb; #if !defined(WOLFSSL_TIRTOS) return 0; diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 1c06efa83b..09f0286ec2 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -23,7 +23,7 @@ #ifdef HAVE_CONFIG_H #include #endif - + #include /* let's use cyassl layer AND cyassl openssl layer */ @@ -35,7 +35,7 @@ #include #if !defined(WOLFSSL_MDK_ARM) - #include "cmsis_os.h" + #include "cmsis_os.h" #include "rl_net.h" #else #include "rtl.h" @@ -81,16 +81,17 @@ void echoclient_test(void* args) int argc = 0; char** argv = 0; word16 port = yasslPort; + char buffer[CYASSL_MAX_ERROR_SZ]; ((func_args*)args)->return_code = -1; /* error state */ - + #ifndef WOLFSSL_MDK_SHELL argc = ((func_args*)args)->argc; argv = ((func_args*)args)->argv; #endif if (argc >= 2) { - fin = fopen(argv[1], "r"); + fin = fopen(argv[1], "r"); inCreated = 1; } if (argc >= 3) { @@ -105,7 +106,7 @@ void echoclient_test(void* args) doDTLS = 1; #endif -#ifdef CYASSL_LEANPSK +#ifdef CYASSL_LEANPSK doPSK = 1; #endif @@ -130,16 +131,16 @@ void echoclient_test(void* args) #ifndef NO_FILESYSTEM #ifndef NO_RSA - if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) + if (SSL_CTX_load_verify_locations(ctx, caCertFile, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #endif #ifdef HAVE_ECC - if (SSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) + if (SSL_CTX_load_verify_locations(ctx, eccCertFile, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #endif #elif !defined(NO_CERTS) if (!doPSK) - load_buffer(ctx, caCert, WOLFSSL_CA); + load_buffer(ctx, caCertFile, WOLFSSL_CA); #endif #if defined(CYASSL_SNIFFER) @@ -173,15 +174,15 @@ void echoclient_test(void* args) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); tcp_connect(&sockfd, yasslIP, port, doDTLS, 0, ssl); - + SSL_set_fd(ssl, sockfd); #if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER) /* let echoserver bind first, TODO: add Windows signal like pthreads does */ @@ -189,31 +190,46 @@ void echoclient_test(void* args) #endif 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 = SSL_connect(ssl); if (ret != SSL_SUCCESS) { err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - + } while (err == WC_PENDING_E); if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; - printf("err = %d, %s\n", err, ERR_error_string(err, buffer)); + printf("SSL_connect error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_connect failed"); } while (fgets(msg, sizeof(msg), fin) != 0) { - + sendSz = (int)XSTRLEN(msg); - if (SSL_write(ssl, msg, sendSz) != sendSz) + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, msg, sendSz); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != sendSz) { + printf("SSL_write msg error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_write failed"); + } if (strncmp(msg, "quit", 4) == 0) { fputs("sending server shutdown command: quit!\n", fout); @@ -225,29 +241,39 @@ void echoclient_test(void* args) break; } - #ifndef WOLFSSL_MDK_SHELL - while (sendSz) { - int got; - if ( (got = SSL_read(ssl, reply, sizeof(reply)-1)) > 0) { - reply[got] = 0; + #ifndef WOLFSSL_MDK_SHELL + while (sendSz) + #endif + { + do { + err = 0; /* reset error */ + ret = SSL_read(ssl, reply, sizeof(reply)-1); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret > 0) { + reply[ret] = 0; fputs(reply, fout); fflush(fout) ; - sendSz -= got; + sendSz -= ret; } - else + else { + printf("SSL_read msg error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys("SSL_read failed"); + + #ifndef WOLFSSL_MDK_SHELL break; - } - #else - { - int got; - if ( (got = SSL_read(ssl, reply, sizeof(reply)-1)) > 0) { - reply[got] = 0; - fputs(reply, fout); - fflush(fout) ; - sendSz -= got; + #endif } } - #endif } @@ -255,7 +281,19 @@ void echoclient_test(void* args) strncpy(msg, "break", 6); sendSz = (int)strlen(msg); /* try to tell server done */ - SSL_write(ssl, msg, sendSz); + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, msg, sendSz); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); #else SSL_shutdown(ssl); #endif @@ -272,7 +310,7 @@ void echoclient_test(void* args) if (outCreated) fclose(fout); CloseSocket(sockfd); - ((func_args*)args)->return_code = 0; + ((func_args*)args)->return_code = 0; } @@ -311,7 +349,7 @@ void echoclient_test(void* args) return args.return_code; } - + #endif /* NO_MAIN_DRIVER */ diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 432525806c..7c1d126d3b 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -36,8 +36,8 @@ #if !defined(WOLFSSL_MDK_ARM) #include "cmsis_os.h" - #include "rl_fs.h" - #include "rl_net.h" + #include "rl_fs.h" + #include "rl_net.h" #else #include "rtl.h" #include "wolfssl_MDK_ARM.h" @@ -91,6 +91,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) word16 port; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; + char buffer[CYASSL_MAX_ERROR_SZ]; #ifdef ECHO_OUT FILE* fout = stdout; @@ -165,23 +166,23 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) if (doPSK == 0) { #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA) /* ntru */ - if (CyaSSL_CTX_use_certificate_file(ctx, ntruCert, SSL_FILETYPE_PEM) + if (CyaSSL_CTX_use_certificate_file(ctx, ntruCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load ntru cert file, " "Please run from wolfSSL home dir"); - if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ntruKey) + if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ntruKeyFile) != SSL_SUCCESS) err_sys("can't load ntru key file, " "Please run from wolfSSL home dir"); #elif defined(HAVE_ECC) && !defined(CYASSL_SNIFFER) /* ecc */ - if (CyaSSL_CTX_use_certificate_file(ctx, eccCert, SSL_FILETYPE_PEM) + if (CyaSSL_CTX_use_certificate_file(ctx, eccCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server cert file, " "Please run from wolfSSL home dir"); - if (CyaSSL_CTX_use_PrivateKey_file(ctx, eccKey, SSL_FILETYPE_PEM) + if (CyaSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server key file, " "Please run from wolfSSL home dir"); @@ -189,12 +190,12 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) /* do nothing, just don't load cert files */ #else /* normal */ - if (CyaSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) + if (CyaSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server cert file, " "Please run from wolfSSL home dir"); - if (CyaSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM) + if (CyaSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server key file, " "Please run from wolfSSL home dir"); @@ -202,8 +203,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) } /* doPSK */ #elif !defined(NO_CERTS) if (!doPSK) { - load_buffer(ctx, svrCert, WOLFSSL_CERT); - load_buffer(ctx, svrKey, WOLFSSL_KEY); + load_buffer(ctx, svrCertFile, WOLFSSL_CERT); + load_buffer(ctx, svrKeyFile, WOLFSSL_KEY); } #endif @@ -232,8 +233,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -241,7 +242,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) SignalReady(args, port); while (!shutDown) { - CYASSL* ssl = 0; + CYASSL* ssl = NULL; + CYASSL* write_ssl = NULL; /* may have separate w/ HAVE_WRITE_DUP */ char command[SVR_COMMAND_SIZE+1]; int echoSz = 0; int clientfd; @@ -276,29 +278,27 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) wolfSSL_dtls_set_peer(ssl, &client, client_len); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) - CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + CyaSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher than PSK */ #endif 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 = CyaSSL_accept(ssl); if (ret != SSL_SUCCESS) { err = CyaSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - + } while (err == WC_PENDING_E); if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; - err = CyaSSL_get_error(ssl, 0); - printf("error = %d, %s\n", err, CyaSSL_ERR_error_string(err, buffer)); + printf("SSL_accept error = %d, %s\n", err, + CyaSSL_ERR_error_string(err, buffer)); printf("SSL_accept failed\n"); CyaSSL_free(ssl); CloseSocket(clientfd); @@ -308,7 +308,41 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) showPeer(ssl); #endif - while ( (echoSz = CyaSSL_read(ssl, command, sizeof(command)-1)) > 0) { +#ifdef HAVE_WRITE_DUP + write_ssl = wolfSSL_write_dup(ssl); + if (write_ssl == NULL) { + printf("wolfSSL_write_dup failed\n"); + CyaSSL_free(ssl); + CloseSocket(clientfd); + continue; + } +#else + write_ssl = ssl; +#endif + + while (1) { + do { + err = 0; /* reset error */ + ret = CyaSSL_read(ssl, command, sizeof(command)-1); + if (ret <= 0) { + err = CyaSSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret <= 0) { + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read echo error %d, %s!\n", err, + CyaSSL_ERR_error_string(err, buffer)); + } + break; + } + + echoSz = ret; if (firstRead == 1) { firstRead = 0; /* browser may send 1 byte 'G' to start */ @@ -321,7 +355,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) strncpy(command, "GET", 4); /* fall through to normal GET */ } - + if ( strncmp(command, "quit", 4) == 0) { printf("client sent quit command: shutting down!\n"); shutDown = 1; @@ -343,7 +377,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) char header[] = "\n
\n";
                 char body[]   = "greetings from wolfSSL\n";
                 char footer[] = "\r\n\r\n";
-            
+
                 strncpy(command, type, sizeof(type));
                 echoSz = sizeof(type) - 1;
 
@@ -354,21 +388,57 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
                 strncpy(&command[echoSz], footer, sizeof(footer));
                 echoSz += (int)sizeof(footer);
 
-                if (CyaSSL_write(ssl, command, echoSz) != echoSz)
-                    err_sys("SSL_write failed");
+                do {
+                    err = 0; /* reset error */
+                    ret = CyaSSL_write(write_ssl, command, echoSz);
+                    if (ret <= 0) {
+                        err = CyaSSL_get_error(write_ssl, 0);
+                    #ifdef WOLFSSL_ASYNC_CRYPT
+                        if (err == WC_PENDING_E) {
+                            ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW);
+                            if (ret < 0) break;
+                        }
+                    #endif
+                    }
+                } while (err == WC_PENDING_E);
+                if (ret != echoSz) {
+                    printf("SSL_write get error = %d, %s\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                    err_sys("SSL_write get failed");
+                }
                 break;
             }
             command[echoSz] = 0;
 
-            #ifdef ECHO_OUT
-                fputs(command, fout);
-            #endif
+        #ifdef ECHO_OUT
+            fputs(command, fout);
+        #endif
+
+            do {
+                err = 0; /* reset error */
+                ret = CyaSSL_write(write_ssl, command, echoSz);
+                if (ret <= 0) {
+                    err = CyaSSL_get_error(write_ssl, 0);
+                #ifdef WOLFSSL_ASYNC_CRYPT
+                    if (err == WC_PENDING_E) {
+                        ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW);
+                        if (ret < 0) break;
+                    }
+                #endif
+                }
+            } while (err == WC_PENDING_E);
 
-            if (CyaSSL_write(ssl, command, echoSz) != echoSz)
-                err_sys("SSL_write failed");
+            if (ret != echoSz) {
+                printf("SSL_write echo error = %d, %s\n", err,
+                        CyaSSL_ERR_error_string(err, buffer));
+                err_sys("SSL_write echo failed");
+            }
         }
 #ifndef CYASSL_DTLS
         CyaSSL_shutdown(ssl);
+#endif
+#ifdef HAVE_WRITE_DUP
+        CyaSSL_free(write_ssl);
 #endif
         CyaSSL_free(ssl);
         CloseSocket(clientfd);
@@ -445,7 +515,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args)
         return args.return_code;
     }
 
-        
+
 #endif /* NO_MAIN_DRIVER */
 
 
diff --git a/examples/server/server.c b/examples/server/server.c
index d39db80703..4ef51341f8 100644
--- a/examples/server/server.c
+++ b/examples/server/server.c
@@ -30,11 +30,6 @@
     #include    /* ecc_fp_free */
 #endif
 
-#if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
-    /* in case memory tracker wants stats */
-    #define WOLFSSL_TRACK_MEMORY
-#endif
-
 #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)
         #include 
         #include 
@@ -74,7 +69,19 @@
     int myHsDoneCb(WOLFSSL* ssl, void* user_ctx);
 #endif
 
-
+static const char webServerMsg[] =
+    "HTTP/1.1 200 OK\n"
+    "Content-Type: text/html\n"
+    "Connection: close\n"
+    "\n"
+    "\n"
+    "\n"
+    "Welcome to wolfSSL!\n"
+    "\n"
+    "\n"
+    "

wolfSSL has successfully performed handshake!

\n" + "\n" + "\n"; static int NonBlockingSSL_Accept(SSL* ssl) { @@ -85,25 +92,35 @@ static int NonBlockingSSL_Accept(SSL* ssl) #endif int error = SSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); - int select_ret; + int select_ret = 0; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || - error == SSL_ERROR_WANT_WRITE)) { + error == SSL_ERROR_WANT_WRITE || + error == WC_PENDING_E)) { int currTimeout = 1; if (error == SSL_ERROR_WANT_READ) { /* printf("... server would read block\n"); */ - } else { + } + else if (error == SSL_ERROR_WANT_WRITE) { /* printf("... server would write block\n"); */ } + #ifdef WOLFSSL_ASYNC_CRYPT + else if (error == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif -#ifdef CYASSL_DTLS - currTimeout = CyaSSL_dtls_get_current_timeout(ssl); -#endif - select_ret = tcp_select(sockfd, currTimeout); + if (error != WC_PENDING_E) { + #ifdef CYASSL_DTLS + currTimeout = CyaSSL_dtls_get_current_timeout(ssl); + #endif + select_ret = tcp_select(sockfd, currTimeout); + } if ((select_ret == TEST_RECV_READY) || - (select_ret == TEST_ERROR_READY)) { + (select_ret == TEST_ERROR_READY) || error == WC_PENDING_E) { #ifndef CYASSL_CALLBACKS ret = SSL_accept(ssl); #else @@ -115,12 +132,12 @@ static int NonBlockingSSL_Accept(SSL* ssl) else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { error = SSL_ERROR_WANT_READ; } -#ifdef CYASSL_DTLS + #ifdef CYASSL_DTLS else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && CyaSSL_dtls_got_timeout(ssl) >= 0) { error = SSL_ERROR_WANT_READ; } -#endif + #endif else { error = SSL_FATAL_ERROR; } @@ -132,60 +149,92 @@ static int NonBlockingSSL_Accept(SSL* ssl) /* Echo number of bytes specified by -e arg */ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int throughput) { - int ret = 0; - char* buffer = (char*)malloc(TEST_BUFFER_SIZE); - if(buffer) { - double start = 0, rx_time = 0, tx_time = 0; - int xfer_bytes = 0; - while((echoData && throughput == 0) || (!echoData && xfer_bytes < throughput)) { - int select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ - if (select_ret == TEST_RECV_READY) { - int len = min(TEST_BUFFER_SIZE, throughput - xfer_bytes); - int rx_pos = 0; - if(throughput) { - start = current_time(1); - } - while(rx_pos < len) { - ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos); - if (ret <= 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("SSL_read error %d!\n", readErr); - err_sys("SSL_read failed"); - } + int ret = 0, err; + double start = 0, rx_time = 0, tx_time = 0; + int xfer_bytes = 0, select_ret, len, rx_pos; + char* buffer; + + buffer = (char*)malloc(TEST_BUFFER_SIZE); + if (!buffer) { + err_sys("Server buffer malloc failed"); + } + + while ((echoData && throughput == 0) || + (!echoData && xfer_bytes < throughput)) + { + select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ + if (select_ret == TEST_RECV_READY) { + + len = min(TEST_BUFFER_SIZE, throughput - xfer_bytes); + rx_pos = 0; + + if (throughput) { + start = current_time(1); + } + + /* Read data */ + while (rx_pos < len) { + ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos); + if (ret < 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; } - else { - rx_pos += ret; + else + #endif + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read echo error %d\n", err); + err_sys("SSL_read failed"); } } - if(throughput) { - rx_time += current_time(0) - start; - start = current_time(1); - } - if (SSL_write(ssl, buffer, len) != len) { - err_sys("SSL_write failed"); + else { + rx_pos += ret; } - if(throughput) { - tx_time += current_time(0) - start; + } + if (throughput) { + rx_time += current_time(0) - start; + start = current_time(1); + } + + /* Write data */ + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, buffer, len); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif } + } while (err == WC_PENDING_E); + if (ret != len) { + printf("SSL_write echo error %d\n", err); + err_sys("SSL_write failed"); + } - xfer_bytes += len; + if (throughput) { + tx_time += current_time(0) - start; } - } - free(buffer); - - if(throughput) { - printf("wolfSSL Server Benchmark %d bytes\n" - "\tRX %8.3f ms (%8.3f MBps)\n" - "\tTX %8.3f ms (%8.3f MBps)\n", - throughput, - tx_time * 1000, throughput / tx_time / 1024 / 1024, - rx_time * 1000, throughput / rx_time / 1024 / 1024 - ); + + xfer_bytes += len; } } - else { - err_sys("Server buffer malloc failed"); + + free(buffer); + + if (throughput) { + printf("wolfSSL Server Benchmark %d bytes\n" + "\tRX %8.3f ms (%8.3f MBps)\n" + "\tTX %8.3f ms (%8.3f MBps)\n", + throughput, + tx_time * 1000, throughput / tx_time / 1024 / 1024, + rx_time * 1000, throughput / rx_time / 1024 / 1024 + ); } return EXIT_SUCCESS; @@ -201,12 +250,12 @@ static void Usage(void) printf("-v SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n", SERVER_DEFAULT_VERSION); printf("-l Cipher suite list (: delimited)\n"); - printf("-c Certificate file, default %s\n", svrCert); - printf("-k Key file, default %s\n", svrKey); - printf("-A Certificate Authority file, default %s\n", cliCert); + printf("-c Certificate file, default %s\n", svrCertFile); + printf("-k Key file, default %s\n", svrKeyFile); + printf("-A Certificate Authority file, default %s\n", cliCertFile); printf("-R Create Ready file for external monitor default none\n"); #ifndef NO_DH - printf("-D Diffie-Hellman Params file, default %s\n", dhParam); + printf("-D Diffie-Hellman Params file, default %s\n", dhParamFile); printf("-Z Minimum DH key bits, default %d\n", DEFAULT_MIN_DHKEY_BITS); #endif @@ -252,6 +301,13 @@ static void Usage(void) #endif #ifdef HAVE_WNR printf("-q Whitewood config file, default %s\n", wnrConfig); +#endif + printf("-g Return basic HTML web page\n"); + printf("-C The number of connections to accept, default: 1\n"); + printf("-H Force use of the default cipher suite list\n"); +#ifdef WOLFSSL_TLS13 + printf("-K Key Exchange for PSK not using (EC)DHE\n"); + printf("-U Update keys and IVs before sending\n"); #endif } @@ -269,6 +325,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #else const char msg[] = "I hear you fa shizzle!\n"; #endif + int useWebServerMsg = 0; char input[80]; int ch; int version = SERVER_DEFAULT_VERSION; @@ -284,13 +341,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; - int trackMemory = 0; int fewerPackets = 0; int pkCallbacks = 0; int wc_shutdown = 0; int resume = 0; int resumeCount = 0; - int loopIndefinitely = 0; + int loops = 1; int echoData = 0; int throughput = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; @@ -304,10 +360,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; - const char* verifyCert = cliCert; - const char* ourCert = svrCert; - const char* ourKey = svrKey; - const char* ourDhParam = dhParam; + int useDefCipherList = 0; + const char* verifyCert = cliCertFile; + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; + const char* ourDhParam = dhParamFile; tcp_ready* readySignal = NULL; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -332,6 +389,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; #endif + char buffer[CYASSL_MAX_ERROR_SZ]; +#ifdef WOLFSSL_TLS13 + int noPskDheKe = 0; +#endif + int updateKeysIVs = 0; #ifdef WOLFSSL_STATIC_MEMORY #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \ @@ -348,9 +410,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA - verifyCert = (char*)cliEccCert; - ourCert = (char*)eccCert; - ourKey = (char*)eccKey; + verifyCert = (char*)cliEccCertFile; + ourCert = (char*)eccCertFile; + ourKey = (char*)eccKeyFile; #endif (void)pkCallbacks; (void)needDH; @@ -367,6 +429,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void)alpn_opt; (void)crlFlags; (void)readySignal; + (void)updateKeysIVs; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); @@ -375,8 +438,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - while ((ch = mygetopt(argc, argv, - "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { + /* Not Used: h, m, t, x, y, z, F, J, M, Q, T, V, W, X, Y */ + while ((ch = mygetopt(argc, argv, "?" + "abc:defgijk:l:nop:q:rsuv:w" + "A:B:C:D:E:GHIKL:NO:PR:S:UYZ:")) != -1) { switch (ch) { case '?' : Usage(); @@ -398,12 +463,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) usePskPlus = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif - break; - case 'n' : useNtruKey = 1; break; @@ -450,7 +509,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) case 'v' : version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); exit(MY_EX_USAGE); } @@ -460,6 +519,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) cipherList = myoptarg; break; + case 'H' : + useDefCipherList = 1; + break; + case 'A' : verifyCert = myoptarg; break; @@ -541,7 +604,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'i' : - loopIndefinitely = 1; + loops = -1; + break; + + case 'C' : + loops = atoi(myoptarg); + if (loops <= 0) { + Usage(); + exit(MY_EX_USAGE); + } break; case 'e' : @@ -568,6 +639,22 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif break; + case 'g' : + useWebServerMsg = 1; + break; + + case 'K' : + #ifdef WOLFSSL_TLS13 + noPskDheKe = 1; + #endif + break; + + case 'U' : + #ifdef WOLFSSL_TLS13 + updateKeysIVs = 1; + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -598,11 +685,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } } -#if defined(USE_CYASSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - InitMemoryTracker(); -#endif - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) err_sys("can't load whitewood net random config file"); @@ -635,6 +717,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; #endif +#ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_server_method_ex; + break; +#endif + #ifdef CYASSL_DTLS #ifndef NO_OLD_TLS case -1: @@ -689,9 +777,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif - if (cipherList) + if (cipherList && !useDefCipherList) { if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 1"); + } #ifdef CYASSL_LEANPSK if (!usePsk) { @@ -795,7 +884,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (useAnon) { #ifdef HAVE_ANON CyaSSL_CTX_allow_anon_cipher(ctx); - if (cipherList == NULL) { + if (cipherList == NULL || (cipherList && useDefCipherList)) { if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS) err_sys("server can't set cipher list 4"); } @@ -846,25 +935,31 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_TLS13 + if (noPskDheKe) + wolfSSL_CTX_no_dhe_psk(ctx); +#endif + while (1) { /* allow resume option */ - if(resumeCount > 1) { + if (resumeCount > 1) { if (dtlsUDP == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - } else { + } + else { tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP); clientfd = sockfd; } - if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) { + if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) { err_sys("tcp accept failed"); } } @@ -882,6 +977,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ssl = SSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL"); + #ifdef OPENSSL_EXTRA + wolfSSL_KeepArrays(ssl); + #endif #if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) { @@ -990,38 +1088,69 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #endif - 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 */ #ifndef CYASSL_CALLBACKS - if (nonBlocking) { - ret = NonBlockingSSL_Accept(ssl); - } - else { + if (nonBlocking) { + ret = NonBlockingSSL_Accept(ssl); + } + else { + do { + err = 0; /* reset error */ ret = SSL_accept(ssl); - } + if (ret != SSL_SUCCESS) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + } #else - ret = NonBlockingSSL_Accept(ssl); + ret = NonBlockingSSL_Accept(ssl); #endif - if (ret != SSL_SUCCESS) { - err = SSL_get_error(ssl, 0); - } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; err = SSL_get_error(ssl, 0); - printf("error = %d, %s\n", err, ERR_error_string(err, buffer)); + printf("SSL_accept error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_accept failed"); } showPeer(ssl); + if (SSL_state(ssl) != 0) { + err_sys("SSL in error state"); + } + +#ifdef OPENSSL_EXTRA + { + byte* rnd; + byte* pt; + size_t size; + + /* get size of buffer then print */ + size = wolfSSL_get_server_random(NULL, NULL, 0); + if (size == 0) { + err_sys("error getting server random buffer size"); + } + + rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rnd == NULL) { + err_sys("error creating server random buffer"); + } + + size = wolfSSL_get_server_random(ssl, rnd, size); + if (size == 0) { + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err_sys("error getting server random buffer"); + } + + printf("Server Random : "); + for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt); + printf("\n"); + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif #ifdef HAVE_ALPN if (alpnList != NULL) { @@ -1047,21 +1176,69 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) free(list); } #endif - if(echoData == 0 && throughput == 0) { - ret = SSL_read(ssl, input, sizeof(input)-1); + if (echoData == 0 && throughput == 0) { + const char* write_msg; + int write_msg_sz; + + /* Read data */ + do { + err = 0; /* reset error */ + ret = SSL_read(ssl, input, sizeof(input)-1); + if (ret < 0) { + err = SSL_get_error(ssl, 0); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read input error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys("SSL_read failed"); + } + } + } while (err == WC_PENDING_E); if (ret > 0) { - input[ret] = 0; + input[ret] = 0; /* null terminate message */ printf("Client message: %s\n", input); + } +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs) + wolfSSL_update_keys(ssl); +#endif + + /* Write data */ + if (!useWebServerMsg) { + write_msg = msg; + write_msg_sz = sizeof(msg); } - else if (ret < 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) - err_sys("SSL_read failed"); + else { + write_msg = webServerMsg; + write_msg_sz = sizeof(webServerMsg); } - - if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, write_msg, write_msg_sz); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E || err == SSL_ERROR_WANT_WRITE); + if (ret != write_msg_sz) { + printf("SSL_write msg error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_write failed"); + } } else { ServerEchoData(ssl, clientfd, echoData, throughput); @@ -1103,7 +1280,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } resumeCount = 0; - if(!loopIndefinitely) { + if (loops > 0 && --loops == 0) { break; /* out of while loop, done with normal and resume option */ } } /* while(1) */ @@ -1120,11 +1297,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ecc_fp_free(); /* free per thread cache */ #endif -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - ShowMemoryTracker(); -#endif - #ifdef CYASSL_TIRTOS fdCloseSession(Task_self()); #endif @@ -1147,7 +1319,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void) useNtruKey; (void) ourDhParam; (void) ourCert; - (void) trackMemory; #ifndef CYASSL_TIRTOS return 0; #endif diff --git a/fips-check.sh b/fips-check.sh index 31e8a51d37..d6d88375c8 100755 --- a/fips-check.sh +++ b/fips-check.sh @@ -9,14 +9,17 @@ # This should check out all the approved versions. The command line # option selects the version. # -# $ ./fips-check [version] +# $ ./fips-check [version] [keep] # -# - version: linux (default), ios, android, windows, freertos +# - version: linux (default), ios, android, windows, freertos, linux-ecc +# +# - keep: (default off) XXX-fips-test temp dir around for inspection # function Usage() { - echo "Usage: $0 [platform]" - echo "Where \"platform\" is one of linux (default), ios, android, windows, freertos" + echo "Usage: $0 [platform] [keep]" + echo "Where \"platform\" is one of linux (default), ios, android, windows, freertos, openrtos-3.9.2, linux-ecc" + echo "Where \"keep\" means keep (default off) XXX-fips-test temp dir around for inspection" } LINUX_FIPS_VERSION=v3.2.6 @@ -24,6 +27,11 @@ LINUX_FIPS_REPO=git@github.com:wolfSSL/fips.git LINUX_CTAO_VERSION=v3.2.6 LINUX_CTAO_REPO=git@github.com:cyassl/cyassl.git +LINUX_ECC_FIPS_VERSION=v3.10.3 +LINUX_ECC_FIPS_REPO=git@github.com:wolfSSL/fips.git +LINUX_ECC_CTAO_VERSION=v3.2.6 +LINUX_ECC_CTAO_REPO=git@github.com:cyassl/cyassl.git + IOS_FIPS_VERSION=v3.4.8a IOS_FIPS_REPO=git@github.com:wolfSSL/fips.git IOS_CTAO_VERSION=v3.4.8.fips @@ -44,6 +52,11 @@ FREERTOS_FIPS_REPO=git@github.com:wolfSSL/fips.git FREERTOS_CTAO_VERSION=v3.6.1 FREERTOS_CTAO_REPO=git@github.com:cyassl/cyassl.git +OPENRTOS_3_9_2_FIPS_VERSION=v3.9.2-OpenRTOS +OPENRTOS_3_9_2_FIPS_REPO=git@github.com:wolfSSL/fips.git +OPENRTOS_3_9_2_CTAO_VERSION=v3.6.1 +OPENRTOS_3_9_2_CTAO_REPO=git@github.com:cyassl/cyassl.git + FIPS_SRCS=( fips.c fips_test.c ) WC_MODS=( aes des3 sha sha256 sha512 rsa hmac random ) TEST_DIR=XXX-fips-test @@ -52,6 +65,8 @@ WC_SRC_PATH=ctaocrypt/src if [ "x$1" == "x" ]; then PLATFORM="linux"; else PLATFORM=$1; fi +if [ "x$2" == "xkeep" ]; then KEEP="yes"; else KEEP="no"; fi + case $PLATFORM in ios) FIPS_VERSION=$IOS_FIPS_VERSION @@ -77,12 +92,25 @@ freertos) CTAO_VERSION=$FREERTOS_CTAO_VERSION CTAO_REPO=$FREERTOS_CTAO_REPO ;; +openrtos-3.9.2) + FIPS_VERSION=$OPENRTOS_3_9_2_FIPS_VERSION + FIPS_REPO=$OPENRTOS_3_9_2_FIPS_REPO + CTAO_VERSION=$OPENRTOS_3_9_2_CTAO_VERSION + CTAO_REPO=$OPENRTOS_3_9_2_CTAO_REPO + FIPS_CONFLICTS=( aes hmac random sha256 ) + ;; linux) FIPS_VERSION=$LINUX_FIPS_VERSION FIPS_REPO=$LINUX_FIPS_REPO CTAO_VERSION=$LINUX_CTAO_VERSION CTAO_REPO=$LINUX_CTAO_REPO ;; +linux-ecc) + FIPS_VERSION=$LINUX_ECC_FIPS_VERSION + FIPS_REPO=$LINUX_ECC_FIPS_REPO + CTAO_VERSION=$LINUX_ECC_CTAO_VERSION + CTAO_REPO=$LINUX_ECC_CTAO_REPO + ;; *) Usage exit 1 @@ -134,7 +162,22 @@ fi make test [ $? -ne 0 ] && echo "\n\nTest failed. Debris left for analysis." && exit 1 +if [ ${#FIPS_CONFLICTS[@]} -ne 0 ]; +then + echo "Due to the way this package is compiled by the customer duplicate" + echo "source file names are an issue, renaming:" + for FNAME in ${FIPS_CONFLICTS[@]} + do + echo "wolfcrypt/src/$FNAME.c to wolfcrypt/src/wc_$FNAME.c" + mv ./wolfcrypt/src/$FNAME.c ./wolfcrypt/src/wc_$FNAME.c + done + echo "Confirming files were renamed..." + ls -la ./wolfcrypt/src/wc_*.c +fi + # Clean up popd -rm -rf $TEST_DIR - +if [ "x$KEEP" == "xno" ]; +then + rm -rf $TEST_DIR +fi diff --git a/gencertbuf.pl b/gencertbuf.pl index 09c6114c26..e7dc9f7d63 100755 --- a/gencertbuf.pl +++ b/gencertbuf.pl @@ -55,6 +55,7 @@ [ "./certs/dh2048.der", "dh_key_der_2048" ], [ "./certs/dsa2048.der", "dsa_key_der_2048" ], [ "./certs/rsa2048.der", "rsa_key_der_2048" ], + [ "./certs/ca-key.der", "ca_key_der_2048" ], [ "./certs/ca-cert.der", "ca_cert_der_2048" ], [ "./certs/server-key.der", "server_key_der_2048" ], [ "./certs/server-cert.der", "server_cert_der_2048" ] diff --git a/mcapi/crypto.c b/mcapi/crypto.c index d0216035d2..8ccf00460e 100644 --- a/mcapi/crypto.c +++ b/mcapi/crypto.c @@ -52,9 +52,7 @@ int CRYPT_MD5_Initialize(CRYPT_MD5_CTX* md5) if (md5 == NULL) return BAD_FUNC_ARG; - wc_InitMd5((Md5*)md5); - - return 0; + return wc_InitMd5((Md5*)md5); } @@ -65,9 +63,7 @@ int CRYPT_MD5_DataAdd(CRYPT_MD5_CTX* md5, const unsigned char* input, if (md5 == NULL || input == NULL) return BAD_FUNC_ARG; - wc_Md5Update((Md5*)md5, input, sz); - - return 0; + return wc_Md5Update((Md5*)md5, input, sz); } @@ -77,9 +73,7 @@ int CRYPT_MD5_Finalize(CRYPT_MD5_CTX* md5, unsigned char* digest) if (md5 == NULL || digest == NULL) return BAD_FUNC_ARG; - wc_Md5Final((Md5*)md5, digest); - - return 0; + return wc_Md5Final((Md5*)md5, digest); } diff --git a/mcapi/crypto.h b/mcapi/crypto.h index 6db1dd2113..4d71a3f269 100644 --- a/mcapi/crypto.h +++ b/mcapi/crypto.h @@ -34,7 +34,7 @@ /* MD5 */ typedef struct CRYPT_MD5_CTX { - int holder[24]; /* big enough to hold internal, but check on init */ + int holder[28]; /* big enough to hold internal, but check on init */ } CRYPT_MD5_CTX; int CRYPT_MD5_Initialize(CRYPT_MD5_CTX*); @@ -42,13 +42,13 @@ int CRYPT_MD5_DataAdd(CRYPT_MD5_CTX*, const unsigned char*, unsigned int); int CRYPT_MD5_Finalize(CRYPT_MD5_CTX*, unsigned char*); enum { - CRYPT_MD5_DIGEST_SIZE = 16 + CRYPT_MD5_DIGEST_SIZE = 16 }; /* SHA */ typedef struct CRYPT_SHA_CTX { - int holder[24]; /* big enough to hold internal, but check on init */ + int holder[28]; /* big enough to hold internal, but check on init */ } CRYPT_SHA_CTX; int CRYPT_SHA_Initialize(CRYPT_SHA_CTX*); @@ -62,7 +62,7 @@ enum { /* SHA-256 */ typedef struct CRYPT_SHA256_CTX { - int holder[28]; /* big enough to hold internal, but check on init */ + int holder[32]; /* big enough to hold internal, but check on init */ } CRYPT_SHA256_CTX; int CRYPT_SHA256_Initialize(CRYPT_SHA256_CTX*); @@ -70,13 +70,13 @@ int CRYPT_SHA256_DataAdd(CRYPT_SHA256_CTX*, const unsigned char*, unsigned int); int CRYPT_SHA256_Finalize(CRYPT_SHA256_CTX*, unsigned char*); enum { - CRYPT_SHA256_DIGEST_SIZE = 32 + CRYPT_SHA256_DIGEST_SIZE = 32 }; /* SHA-384 */ typedef struct CRYPT_SHA384_CTX { - long long holder[32]; /* big enough to hold internal, but check on init */ + long long holder[36]; /* big enough to hold internal, but check on init */ } CRYPT_SHA384_CTX; int CRYPT_SHA384_Initialize(CRYPT_SHA384_CTX*); @@ -98,13 +98,13 @@ int CRYPT_SHA512_DataAdd(CRYPT_SHA512_CTX*, const unsigned char*, unsigned int); int CRYPT_SHA512_Finalize(CRYPT_SHA512_CTX*, unsigned char*); enum { - CRYPT_SHA512_DIGEST_SIZE = 64 + CRYPT_SHA512_DIGEST_SIZE = 64 }; /* HMAC */ typedef struct CRYPT_HMAC_CTX { - long long holder[69]; /* big enough to hold internal, but check on init */ + long long holder[72]; /* 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); @@ -113,10 +113,10 @@ int CRYPT_HMAC_Finalize(CRYPT_HMAC_CTX*, unsigned char*); /* HMAC types */ enum { - CRYPT_HMAC_SHA = 1, - CRYPT_HMAC_SHA256 = 2, - CRYPT_HMAC_SHA384 = 5, - CRYPT_HMAC_SHA512 = 4 + CRYPT_HMAC_SHA = 1, + CRYPT_HMAC_SHA256 = 2, + CRYPT_HMAC_SHA384 = 5, + CRYPT_HMAC_SHA512 = 4 }; @@ -128,7 +128,7 @@ int CRYPT_HUFFMAN_DeCompress(unsigned char*, unsigned int, const unsigned char*, /* flag to use static huffman */ enum { - CRYPT_HUFFMAN_COMPRESS_STATIC = 1 + CRYPT_HUFFMAN_COMPRESS_STATIC = 1 }; @@ -144,7 +144,7 @@ int CRYPT_RNG_BlockGenerate(CRYPT_RNG_CTX*, unsigned char*, unsigned int); /* TDES */ typedef struct CRYPT_TDES_CTX { - int holder[100]; /* big enough to hold internal, but check on init */ + int holder[104]; /* big enough to hold internal, but check on init */ } CRYPT_TDES_CTX; int CRYPT_TDES_KeySet(CRYPT_TDES_CTX*, const unsigned char*, @@ -158,13 +158,13 @@ int CRYPT_TDES_CBC_Decrypt(CRYPT_TDES_CTX*, unsigned char*, /* key direction flags for setup */ enum { CRYPT_TDES_ENCRYPTION = 0, - CRYPT_TDES_DECRYPTION = 1 + CRYPT_TDES_DECRYPTION = 1 }; /* AES */ typedef struct CRYPT_AES_CTX { - int holder[76]; /* big enough to hold internal, but check on init */ + int holder[78]; /* big enough to hold internal, but check on init */ } CRYPT_AES_CTX; /* key */ @@ -262,7 +262,7 @@ int CRYPT_ERROR_StringGet(int, char*); #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif diff --git a/mcapi/mcapi_test.c b/mcapi/mcapi_test.c index 0a6d77e740..5f1e4549e6 100644 --- a/mcapi/mcapi_test.c +++ b/mcapi/mcapi_test.c @@ -214,25 +214,30 @@ static int check_md5(void) { CRYPT_MD5_CTX mcMd5; Md5 defMd5; + int ret; byte mcDigest[CRYPT_MD5_DIGEST_SIZE]; byte defDigest[MD5_DIGEST_SIZE]; CRYPT_MD5_Initialize(&mcMd5); - wc_InitMd5(&defMd5); + ret = wc_InitMd5(&defMd5); - CRYPT_MD5_DataAdd(&mcMd5, ourData, OUR_DATA_SIZE); - wc_Md5Update(&defMd5, ourData, OUR_DATA_SIZE); + if (ret == 0) { + CRYPT_MD5_DataAdd(&mcMd5, ourData, OUR_DATA_SIZE); + ret = wc_Md5Update(&defMd5, ourData, OUR_DATA_SIZE); + } - CRYPT_MD5_Finalize(&mcMd5, mcDigest); - wc_Md5Final(&defMd5, defDigest); + if (ret == 0) { + CRYPT_MD5_Finalize(&mcMd5, mcDigest); + ret = wc_Md5Final(&defMd5, defDigest); + } if (memcmp(mcDigest, defDigest, CRYPT_MD5_DIGEST_SIZE) != 0) { printf("md5 final memcmp fialed\n"); return -1; - } + } printf("md5 mcapi test passed\n"); - return 0; + return ret; } @@ -261,7 +266,7 @@ static int check_sha(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { printf("sha final memcmp failed\n"); return -1; - } + } printf("sha mcapi test passed\n"); return 0; @@ -301,7 +306,7 @@ static int check_sha256(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { printf("sha256 final memcmp fialed\n"); return -1; - } + } printf("sha256 mcapi test passed\n"); return 0; @@ -341,7 +346,7 @@ static int check_sha384(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { printf("sha384 final memcmp fialed\n"); return -1; - } + } printf("sha384 mcapi test passed\n"); return 0; @@ -381,7 +386,7 @@ static int check_sha512(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { printf("sha512 final memcmp fialed\n"); return -1; - } + } printf("sha512 mcapi test passed\n"); return 0; @@ -424,7 +429,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { printf("hmac sha final memcmp fialed\n"); return -1; - } + } printf("hmac sha mcapi test passed\n"); /* SHA-256 */ @@ -452,7 +457,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { printf("hmac sha256 final memcmp fialed\n"); return -1; - } + } printf("hmac sha256 mcapi test passed\n"); /* SHA-384 */ @@ -480,7 +485,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { printf("hmac sha384 final memcmp fialed\n"); return -1; - } + } printf("hmac sha384 mcapi test passed\n"); /* SHA-512 */ @@ -508,7 +513,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { printf("hmac sha512 final memcmp fialed\n"); return -1; - } + } printf("hmac sha512 mcapi test passed\n"); return 0; @@ -621,7 +626,7 @@ static int check_compress(void) static int check_rng(void) { int ret; - int i; + int i; byte in[RANDOM_BYTE_SZ]; byte out[RANDOM_BYTE_SZ]; @@ -1326,7 +1331,7 @@ static int check_rsa(void) return -1; } - ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); + ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); if (ret < 0) { printf("mcapi rsa private derypt failed\n"); return -1; @@ -1348,7 +1353,7 @@ static int check_rsa(void) printf("mcapi rsa free failed\n"); return -1; } - + printf("rsa mcapi test passed\n"); return 0; @@ -1358,7 +1363,7 @@ static int check_rsa(void) /* check mcapi ecc */ static int check_ecc(void) { - CRYPT_ECC_CTX userA; + CRYPT_ECC_CTX userA; CRYPT_ECC_CTX userB; int ret; byte sharedA[100]; @@ -1463,7 +1468,7 @@ static int check_ecc(void) printf("mcapi ecc public export failed\n"); return -1; } - + ret = CRYPT_ECC_PublicImport(&userB, sharedA, usedA); if (ret != 0) { printf("mcapi ecc public import failed\n"); diff --git a/mplabx/benchmark_main.c b/mplabx/benchmark_main.c index 5c4c8651ec..c7a31b4be2 100644 --- a/mplabx/benchmark_main.c +++ b/mplabx/benchmark_main.c @@ -53,7 +53,7 @@ void bench_md5(void); void bench_sha(void); void bench_sha256(void); void bench_sha512(void); -void bench_ripemd(void); +int bench_ripemd(void); void bench_rsa(void); void bench_rsaKeyGen(void); diff --git a/rpm/spec.in b/rpm/spec.in index e7871d05be..182491a1fd 100644 --- a/rpm/spec.in +++ b/rpm/spec.in @@ -72,8 +72,8 @@ mkdir -p $RPM_BUILD_ROOT/ %{_docdir}/wolfssl/README.txt %{_libdir}/libwolfssl.la %{_libdir}/libwolfssl.so -%{_libdir}/libwolfssl.so.3 -%{_libdir}/libwolfssl.so.3.6.0 +%{_libdir}/libwolfssl.so.12 +%{_libdir}/libwolfssl.so.12.0.0 %files devel %defattr(-,root,root,-) @@ -159,6 +159,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/cyassl/openssl/rsa.h %{_includedir}/cyassl/openssl/sha.h %{_includedir}/cyassl/openssl/ssl.h +%{_includedir}/cyassl/openssl/ssl23.h %{_includedir}/cyassl/openssl/stack.h %{_includedir}/cyassl/openssl/ui.h %{_includedir}/cyassl/openssl/x509.h @@ -172,6 +173,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/callbacks.h %{_includedir}/wolfssl/certs_test.h %{_includedir}/wolfssl/crl.h +%{_includedir}/wolfssl/io.h %{_includedir}/wolfssl/wolfcrypt/aes.h %{_includedir}/wolfssl/wolfcrypt/cmac.h %{_includedir}/wolfssl/wolfcrypt/arc4.h @@ -229,8 +231,10 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/visibility.h %{_includedir}/wolfssl/wolfcrypt/wc_encrypt.h %{_includedir}/wolfssl/wolfcrypt/wolfevent.h +%{_includedir}/wolfssl/wolfcrypt/wolfmath.h %{_includedir}/wolfssl/error-ssl.h %{_includedir}/wolfssl/ocsp.h +%{_includedir}/wolfssl/openssl/aes.h %{_includedir}/wolfssl/openssl/asn1.h %{_includedir}/wolfssl/openssl/bio.h %{_includedir}/wolfssl/openssl/bn.h @@ -262,6 +266,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/openssl/rsa.h %{_includedir}/wolfssl/openssl/sha.h %{_includedir}/wolfssl/openssl/ssl.h +%{_includedir}/wolfssl/openssl/ssl23.h %{_includedir}/wolfssl/openssl/stack.h %{_includedir}/wolfssl/openssl/ui.h %{_includedir}/wolfssl/openssl/x509.h @@ -275,6 +280,12 @@ mkdir -p $RPM_BUILD_ROOT/ %{_libdir}/pkgconfig/wolfssl.pc %changelog +* Thu May 04 2017 Jacob Barthelmeh +- Added header for wolfssl/io.h, wolfssl/openssl/ssl23.h, cyassl/openssl/ssl23.h +* Thu Feb 09 2017 Jacob Barthelmeh +- Added header for wolfssl/wolfcrypt/wolfmath.h +* Fri Nov 11 2016 Jacob Barthelmeh +- Added header for wolfssl/openssl/aes.h * Fri Oct 28 2016 Jacob Barthelmeh - Added header for pkcs12 * Fri Sep 23 2016 John Safranek diff --git a/scripts/include.am b/scripts/include.am index 0a49b14af0..442d758f72 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -62,6 +62,10 @@ dist_noinst_SCRIPTS+= scripts/openssl.test endif endif +if BUILD_TLS13 +dist_noinst_SCRIPTS+= scripts/tls13.test +endif + EXTRA_DIST += scripts/testsuite.pcap \ scripts/ping.test diff --git a/scripts/openssl.test b/scripts/openssl.test index 1a013518b7..83c2ad0847 100755 --- a/scripts/openssl.test +++ b/scripts/openssl.test @@ -82,7 +82,7 @@ found_free_port=0 while [ "$counter" -lt 20 ]; do echo -e "\nTrying to start openssl server on port $openssl_port...\n" - openssl s_server -accept $openssl_port -cert ./certs/server-cert.pem -key ./certs/server-key.pem -quiet -CAfile ./certs/client-ca.pem -www -dhparam ./certs/dh2048.pem -dcert ./certs/server-ecc.pem -dkey ./certs/ecc-key.pem -verify 10 -verify_return_error -cipher "ALL:eNULL" & + openssl s_server -accept $openssl_port -cert ./certs/server-cert.pem -key ./certs/server-key.pem -quiet -CAfile ./certs/client-ca.pem -www -dhparam ./certs/dh2048.pem -dcert ./certs/server-ecc.pem -dkey ./certs/ecc-key.pem -verify 10 -verify_return_error -psk 1a2b3c4d -cipher "ALL:eNULL" & server_pid=$! # wait to see if s_server successfully starts before continuing sleep 0.1 @@ -215,12 +215,19 @@ do continue fi + # check for psk suite and turn on client psk if so + psk = "" + case $wolfSuite in + *PSK*) + psk="-s " ;; + esac + if [ $version -lt 4 ] then - ./examples/client/client -p $openssl_port -g -r -l $wolfSuite -v $version + ./examples/client/client -p $openssl_port -g -r -l $wolfSuite -v $version $psk else # do all versions - ./examples/client/client -p $openssl_port -g -r -l $wolfSuite + ./examples/client/client -p $openssl_port -g -r -l $wolfSuite $psk fi client_result=$? diff --git a/scripts/tls13.test b/scripts/tls13.test new file mode 100755 index 0000000000..27a891f587 --- /dev/null +++ b/scripts/tls13.test @@ -0,0 +1,312 @@ +#!/bin/sh + +# tls13.test +# copyright wolfSSL 2016 + +# getting unique port is modeled after resume.test script +# need a unique port since may run the same time as testsuite +# use server port zero hack to get one +port=0 +no_pid=-1 +server_pid=$no_pid +counter=0 +# let's use absolute path to a local dir (make distcheck may be in sub dir) +# also let's add some randomness by adding pid in case multiple 'make check's +# per source tree +ready_file=`pwd`/wolfssl_psk_ready$$ + +echo "ready file $ready_file" + +create_port() { + while [ ! -s $ready_file -a "$counter" -lt 50 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $ready_file; then + echo -e "found ready file, starting client..." + + # get created port 0 ephemeral port + port=`cat $ready_file` + else + echo -e "NO ready file ending test..." + do_cleanup + fi +} + +remove_ready_file() { + if test -e $ready_file; then + echo -e "removing existing ready file" + rm $ready_file + fi +} + +do_cleanup() { + echo "in cleanup" + + if [ $server_pid != $no_pid ] + then + echo "killing server" + kill -9 $server_pid + fi + remove_ready_file +} + +do_trap() { + echo "got trap" + do_cleanup + exit -1 +} + +trap do_trap INT TERM + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# Usual TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 not enabled" + do_cleanup + exit 1 +fi +echo "" + +# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 HelloRetryRequest" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -J -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 HelloRetryRequest not working" + do_cleanup + exit 1 +fi +echo "" + +# Resumption TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 resumption" +port=0 +./examples/server/server -v 4 -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 resumption not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and ECC certificates. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - ECC certificates" +port=0 +./examples/server/server -v 4 -A certs/client-ecc-cert.pem -c certs/server-ecc.pem -k certs/ecc-key.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -A certs/server-ecc.pem -c certs/client-ecc-cert.pem -k certs/ecc-client-key.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 ECC certificates not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and DH Key. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - DH Key Exchange" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -y -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 DH Key Exchange not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and ECC Key. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - ECC Key Exchange" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -Y -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 ECDH Key Exchange not working" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suites" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-8-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - only TLS v1.3" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-GCM SHA-256" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-GCM-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-GCM SHA-256" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - AES256-GCM SHA-384" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES256-GCM-SHA384 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES256-GCM SHA-384" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - CHACHA20-POLY1305 SHA-256" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-CHACHA20-POLY1305-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - CHACHA20-POLY1305 SHA-256" + do_cleanup + exit 1 +fi +echo "" + +./examples/client/client -v 4 -e 2>&1 | grep -- '-CCM' +if [ $? -eq 0 ]; then + # TLS 1.3 cipher suites server / client. + echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-CCM SHA-256" + port=0 + ./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-CCM-SHA256 & + server_pid=$! + create_port + ./examples/client/client -v 4 -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-CCM SHA-256" + do_cleanup + exit 1 + fi + echo "" + + # TLS 1.3 cipher suites server / client. + echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-CCM-8 SHA-256" + port=0 + ./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-CCM-8-SHA256 & + server_pid=$! + create_port + ./examples/client/client -v 4 -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-CCM-8 SHA-256" + do_cleanup + exit 1 + fi + echo "" +fi + +# TLS 1.3 server / TLS 1.2 client. +echo -e "\n\nTLS v1.3 server downgrading to TLS v1.2" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 3 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 server downgrading to TLS v1.2" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.2 server / TLS 1.3 client. +echo -e "\n\nTLS v1.3 client downgrading to TLS v1.2" +port=0 +./examples/server/server -v 3 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 client downgrading to TLS v1.2" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data. +echo -e "\n\nTLS v1.3 KeyUpdate" +port=0 +./examples/server/server -v 4 -U -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -I -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 KeyUpdate" + do_cleanup + exit 1 +fi +echo "" + +echo -e "\nALL Tests Passed" + +exit 0 + diff --git a/src/bio.c b/src/bio.c new file mode 100644 index 0000000000..aa02a9adac --- /dev/null +++ b/src/bio.c @@ -0,0 +1,446 @@ +/* bio.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 + */ + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg) +{ + (void)bio; + (void)cmd; + (void)larg; + (void)parg; + + WOLFSSL_ENTER("BIO_ctrl"); + return 1; +} + + +/* Return the number of pending bytes in read and write buffers */ +size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("BIO_ctrl_pending"); + if (bio == NULL) { + return 0; + } + + if (bio->ssl != NULL) { + return (long)wolfSSL_pending(bio->ssl); + } + + if (bio->type == BIO_MEMORY) { + return bio->memLen; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) { + /* in wrap around state where begining of buffer is being + * overwritten */ + return pair->wrSz - pair->rdIdx + pair->wrIdx; + } + else { + /* simple case where has not wrapped around */ + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr) +{ + WOLFSSL_ENTER("BIO_get_mem_ptr"); + + if (bio == NULL || ptr == NULL) { + return SSL_FAILURE; + } + + *ptr = (WOLFSSL_BUF_MEM*)(bio->mem); + return SSL_SUCCESS; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg) +{ + (void) bp; + (void) cmd; + (void) larg; + (void) iarg; + WOLFSSL_ENTER("BIO_int_ctrl"); + return 0; +} + + +int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size"); + + if (bio == NULL || bio->type != BIO_BIO || size < 0) { + return SSL_FAILURE; + } + + /* if already in pair then do not change size */ + if (bio->pair != NULL) { + WOLFSSL_MSG("WOLFSSL_BIO is paired, free from pair before changing"); + return SSL_FAILURE; + } + + bio->wrSz = (int)size; + if (bio->wrSz < 0) { + WOLFSSL_MSG("Unexpected negative size value"); + return SSL_FAILURE; + } + + if (bio->mem != NULL) { + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + } + + bio->mem = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + WOLFSSL_MSG("Memory allocation error"); + return SSL_FAILURE; + } + bio->wrIdx = 0; + bio->rdIdx = 0; + + return SSL_SUCCESS; +} + + +/* Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vise + * versa. Creating something similar to a two way pipe. + * Reading and writing between the two BIOs is not thread safe, they are + * expected to be used by the same thread. */ +int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) +{ + WOLFSSL_ENTER("wolfSSL_BIO_make_bio_pair"); + + if (b1 == NULL || b2 == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG); + return SSL_FAILURE; + } + + /* both are expected to be of type BIO and not already paired */ + if (b1->type != BIO_BIO || b2->type != BIO_BIO || + b1->pair != NULL || b2->pair != NULL) { + WOLFSSL_MSG("Expected type BIO and not already paired"); + return SSL_FAILURE; + } + + /* set default write size if not already set */ + if (b1->mem == NULL && wolfSSL_BIO_set_write_buf_size(b1, + WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { + return SSL_FAILURE; + } + + if (b2->mem == NULL && wolfSSL_BIO_set_write_buf_size(b2, + WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { + return SSL_FAILURE; + } + + b1->pair = b2; + b2->pair = b1; + + return SSL_SUCCESS; +} + + +int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) +{ + WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); + + if (b == NULL) { + return SSL_FAILURE; + } + + b->readRq = 0; + + return SSL_SUCCESS; +} + + +/* Does not advance read index pointer */ +int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf) +{ + WOLFSSL_ENTER("wolfSSL_BIO_nread0"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + /* if paired read from pair */ + if (bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + + /* case where have wrapped around write buffer */ + *buf = (char*)pair->mem + pair->rdIdx; + if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) { + return pair->wrSz - pair->rdIdx; + } + else { + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +/* similar to wolfSSL_BIO_nread0 but advances the read index */ +int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nread"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + /* special case if asking to read 0 bytes */ + if (num == 0) { + *buf = (char*)bio->pair->mem + bio->pair->rdIdx; + return 0; + } + + /* get amount able to read and set buffer pointer */ + sz = wolfSSL_BIO_nread0(bio, buf); + if (sz == 0) { + return WOLFSSL_BIO_ERROR; + } + + if (num < sz) { + sz = num; + } + bio->pair->rdIdx += sz; + + /* check if have read to the end of the buffer and need to reset */ + if (bio->pair->rdIdx == bio->pair->wrSz) { + bio->pair->rdIdx = 0; + if (bio->pair->wrIdx == bio->pair->wrSz) { + bio->pair->wrIdx = 0; + } + } + + /* check if read up to write index, if so then reset indexs */ + if (bio->pair->rdIdx == bio->pair->wrIdx) { + bio->pair->rdIdx = 0; + bio->pair->wrIdx = 0; + } + } + + return sz; +} + + +int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nwrite"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + if (bio->pair != NULL) { + if (num == 0) { + *buf = (char*)bio->mem + bio->wrIdx; + return 0; + } + + if (bio->wrIdx < bio->rdIdx) { + /* if wrapped around only write up to read index. In this case + * rdIdx is always greater then wrIdx so sz will not be negative. */ + sz = bio->rdIdx - bio->wrIdx; + } + else if (bio->rdIdx > 0 && bio->wrIdx == bio->rdIdx) { + return WOLFSSL_BIO_ERROR; /* no more room to write */ + } + else { + /* write index is past read index so write to end of buffer */ + sz = bio->wrSz - bio->wrIdx; + + if (sz <= 0) { + /* either an error has occured with write index or it is at the + * end of the write buffer. */ + if (bio->rdIdx == 0) { + /* no more room, nothing has been read */ + return WOLFSSL_BIO_ERROR; + } + + bio->wrIdx = 0; + + /* check case where read index is not at 0 */ + if (bio->rdIdx > 0) { + sz = bio->rdIdx; /* can write up to the read index */ + } + else { + sz = bio->wrSz; /* no restriction other then buffer size */ + } + } + } + + if (num < sz) { + sz = num; + } + *buf = (char*)bio->mem + bio->wrIdx; + bio->wrIdx += sz; + + /* if at the end of the buffer and space for wrap around then set + * write index back to 0 */ + if (bio->wrIdx == bio->wrSz && bio->rdIdx > 0) { + bio->wrIdx = 0; + } + } + + return sz; +} + + +/* Reset BIO to initial state */ +int wolfSSL_BIO_reset(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_reset"); + + if (bio == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + /* -1 is consistent failure even for FILE type */ + return WOLFSSL_BIO_ERROR; + } + + switch (bio->type) { + #ifndef NO_FILESYSTEM + case BIO_FILE: + XREWIND(bio->file); + return 0; + #endif + + case BIO_BIO: + bio->rdIdx = 0; + bio->wrIdx = 0; + return 0; + + default: + WOLFSSL_MSG("Unknown BIO type needs added to reset function"); + } + + return WOLFSSL_BIO_ERROR; +} + +#ifndef NO_FILESYSTEM +long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_fp"); + + if (bio == NULL || fp == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG); + return SSL_FAILURE; + } + + if (bio->type != BIO_FILE) { + return SSL_FAILURE; + } + + bio->close = (byte)c; + bio->file = fp; + + return SSL_SUCCESS; +} + + +long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_fp"); + + if (bio == NULL || fp == NULL) { + return SSL_FAILURE; + } + + if (bio->type != BIO_FILE) { + return SSL_FAILURE; + } + + *fp = bio->file; + + return SSL_SUCCESS; +} + +/* overwrites file */ +int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) +{ + WOLFSSL_ENTER("wolfSSL_BIO_write_filename"); + + if (bio == NULL || name == NULL) { + return SSL_FAILURE; + } + + if (bio->type == BIO_FILE) { + if (bio->file != NULL && bio->close == BIO_CLOSE) { + XFCLOSE(bio->file); + } + + bio->file = XFOPEN(name, "w"); + if (bio->file == NULL) { + return SSL_FAILURE; + } + bio->close = BIO_CLOSE; + + return SSL_SUCCESS; + } + + return SSL_FAILURE; +} + + +int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) +{ + WOLFSSL_ENTER("wolfSSL_BIO_seek"); + + if (bio == NULL) { + return -1; + } + + /* offset ofs from begining of file */ + if (bio->type == BIO_FILE && XFSEEK(bio->file, ofs, SEEK_SET) < 0) { + return -1; + } + + return 0; +} +#endif /* NO_FILESYSTEM */ + + +long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_mem_eof_return"); + + if (bio != NULL) { + bio->eof = v; + } + + return 0; +} diff --git a/src/crl.c b/src/crl.c old mode 100644 new mode 100755 index 2fbcde08c3..40a2c3160a --- a/src/crl.c +++ b/src/crl.c @@ -34,11 +34,6 @@ #include #include -#ifndef NO_FILESYSTEM - #include - #include -#endif - #include #ifdef HAVE_CRL_MONITOR @@ -79,7 +74,8 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) /* Initialize CRL Entry */ -static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) { WOLFSSL_ENTER("InitCRL_Entry"); @@ -94,6 +90,34 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) crle->certs = dcrl->certs; /* take ownsership */ dcrl->certs = NULL; crle->totalCerts = dcrl->totalCerts; + crle->verified = verified; + if (!verified) { + crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; + crle->signatureSz = dcrl->sigLength; + crle->signatureOID = dcrl->signatureOID; + crle->toBeSigned = XMALLOC(crle->tbsSz, heap, DYNAMIC_TYPE_CRL_ENTRY); + if (crle->toBeSigned == NULL) + return -1; + crle->signature = XMALLOC(crle->signatureSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->signature == NULL) { + XFREE(crle->toBeSigned, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); + XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; return 0; } @@ -111,6 +135,10 @@ static void FreeCRL_Entry(CRL_Entry* crle, void* heap) XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); tmp = next; } + if (crle->signature != NULL) + XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); + if (crle->toBeSigned != NULL) + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); (void)heap; } @@ -154,15 +182,12 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) } -/* Is the cert ok with CRL, return 0 on success */ -int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry) { CRL_Entry* crle; int foundEntry = 0; int ret = 0; - WOLFSSL_ENTER("CheckCertCRL"); - if (wc_LockMutex(&crl->crlLock) != 0) { WOLFSSL_MSG("wc_LockMutex failed"); return BAD_MUTEX_E; @@ -175,6 +200,95 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) int doNextDate = 1; WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca; + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyId[KEYID_SIZE] + #endif + byte issuerHash[CRL_DIGEST_SIZE]; + byte* tbs = NULL; + word32 tbsSz = crle->tbsSz; + byte* sig = NULL; + word32 sigSz = crle->signatureSz; + word32 sigOID = crle->signatureOID; + SignatureCtx sigCtx; + + tbs = XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (tbs == NULL) { + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + sig = XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (sig == NULL) { + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + + XMEMCPY(tbs, crle->toBeSigned, tbsSz); + XMEMCPY(sig, crle->signature, sigSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + XMEMCMPY(extAuthKeyId, crle->extAuthKeyId, + sizeof(extAuthKeyId)); + #endif + XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); + + wc_UnLockMutex(&crl->crlLock); + + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (crle->extAuthKeyIdSet) + ca = GetCA(crl->cm, extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(crl->cm, issuerHash); + #else /* NO_SKID */ + ca = GetCA(crl->cm, issuerHash); + #endif /* NO_SKID */ + if (ca == NULL) { + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz, + sigOID, ca, crl->heap); + + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + crle = crl->crlList; + while (crle) { + if (XMEMCMP(crle->issuerHash, cert->issuerHash, + CRL_DIGEST_SIZE) == 0) { + + if (ret == 0) + crle->verified = 1; + else + crle->verified = ret; + + XFREE(crle->toBeSigned, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->toBeSigned = NULL; + XFREE(crle->signature, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->signature = NULL; + break; + } + crle = crle->next; + } + if (crle == NULL || crle->verified < 0) + break; + } + else if (crle->verified < 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + ret = crle->verified; + break; + } + WOLFSSL_MSG("Checking next date validity"); #ifdef WOLFSSL_NO_CRL_NEXT_DATE @@ -182,13 +296,17 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) doNextDate = 0; /* skip */ #endif - if (doNextDate && !ValidateDate(crle->nextDate, - crle->nextDateFormat, AFTER)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - ret = ASN_AFTER_DATE_E; + if (doNextDate) { + #ifndef NO_ASN_TIME + if (!ValidateDate(crle->nextDate,crle->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + ret = ASN_AFTER_DATE_E; + } + #endif } - else + if (ret == 0) { foundEntry = 1; + } break; } crle = crle->next; @@ -209,9 +327,39 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) wc_UnLockMutex(&crl->crlLock); + *pFoundEntry = foundEntry; + + return ret; +} + +/* Is the cert ok with CRL, return 0 on success */ +int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +{ + int foundEntry = 0; + int ret = 0; + + WOLFSSL_ENTER("CheckCertCRL"); + + ret = CheckCertCRLList(crl, cert, &foundEntry); + +#ifdef HAVE_CRL_IO + if (foundEntry == 0) { + /* perform embedded lookup */ + if (crl->crlIOCb) { + ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, + cert->extCrlInfoSz); + if (ret >= 0) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif + if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); ret = CRL_MISSING; + if (crl->cm->cbMissingCRL) { char url[256]; @@ -224,17 +372,18 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) else { WOLFSSL_MSG("CRL url too long"); } + crl->cm->cbMissingCRL(url); } } - return ret; } /* Add Decoded CRL, 0 on success */ -static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) +static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, + int verified) { CRL_Entry* crle; @@ -246,7 +395,7 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) return -1; } - if (InitCRL_Entry(crle, dcrl) < 0) { + if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { WOLFSSL_MSG("Init CRL Entry failed"); XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return -1; @@ -267,7 +416,8 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) /* Load CRL File of type, SSL_SUCCESS on ok */ -int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) +int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, + int noVerify) { int ret = SSL_SUCCESS; const byte* myBuffer = buff; /* if DER ok, otherwise switch */ @@ -310,11 +460,11 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); - if (ret != 0) { + if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) { WOLFSSL_MSG("ParseCRL error"); } else { - ret = AddCRL(crl, dcrl); + ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); } @@ -790,74 +940,61 @@ static int StartMonitorCRL(WOLFSSL_CRL* crl) #endif /* HAVE_CRL_MONITOR */ -#ifndef NO_FILESYSTEM +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) /* Load CRL path files of type, SSL_SUCCESS on ok */ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) { - struct dirent* entry; - DIR* dir; - int ret = SSL_SUCCESS; + int ret = SSL_SUCCESS; + char* name = NULL; #ifdef WOLFSSL_SMALL_STACK - char* name; + ReadDirCtx* readCtx = NULL; #else - char name[MAX_FILENAME_SZ]; + ReadDirCtx readCtx[1]; #endif WOLFSSL_ENTER("LoadCRL"); if (crl == NULL) return BAD_FUNC_ARG; - dir = opendir(path); - if (dir == NULL) { - WOLFSSL_MSG("opendir path crl load failed"); - return BAD_PATH_ERROR; - } - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) return MEMORY_E; #endif - while ( (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - continue; - } - if (s.st_mode & S_IFREG) { - - if (type == SSL_FILETYPE_PEM) { - if (XSTRSTR(entry->d_name, ".pem") == NULL) { - WOLFSSL_MSG("not .pem file, skipping"); - continue; - } + /* try to load each regular file in path */ + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + int skip = 0; + if (type == SSL_FILETYPE_PEM) { + if (XSTRSTR(name, ".pem") == NULL) { + WOLFSSL_MSG("not .pem file, skipping"); + skip = 1; } - else { - if (XSTRSTR(entry->d_name, ".der") == NULL && - XSTRSTR(entry->d_name, ".crl") == NULL) { - - WOLFSSL_MSG("not .der or .crl file, skipping"); - continue; - } + } + else { + if (XSTRSTR(name, ".der") == NULL && + XSTRSTR(name, ".crl") == NULL) + { + WOLFSSL_MSG("not .der or .crl file, skipping"); + skip = 1; } + } - if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) - != SSL_SUCCESS) { - WOLFSSL_MSG("CRL file load failed, continuing"); - } + if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) + != SSL_SUCCESS) { + WOLFSSL_MSG("CRL file load failed, continuing"); } + + ret = wc_ReadDirNext(readCtx, path, &name); } + wc_ReadDirClose(readCtx); + ret = SSL_SUCCESS; /* load failures not reported, for backwards compat */ #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif if (monitor & WOLFSSL_CRL_MONITOR) { @@ -873,9 +1010,19 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) pathBuf[pathLen] = '\0'; /* Null Terminate */ if (type == SSL_FILETYPE_PEM) { + /* free old path before setting a new one */ + if (crl->monitors[0].path) { + XFREE(crl->monitors[0].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } crl->monitors[0].path = pathBuf; crl->monitors[0].type = SSL_FILETYPE_PEM; } else { + /* free old path before setting a new one */ + if (crl->monitors[1].path) { + XFREE(crl->monitors[1].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } crl->monitors[1].path = pathBuf; crl->monitors[1].type = SSL_FILETYPE_ASN1; } @@ -891,12 +1038,21 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) } } - closedir(dir); - return ret; } -#endif /* NO_FILESYSTEM */ +#else +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + (void)crl; + (void)path; + (void)type; + (void)monitor; + + /* stub for scenario where file system is not supported */ + return NOT_COMPILED_IN; +} +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ #endif /* HAVE_CRL */ #endif /* !WOLFCRYPT_ONLY */ diff --git a/src/include.am b/src/include.am index 82be0c1a0d..b8dd4951d0 100644 --- a/src/include.am +++ b/src/include.am @@ -120,7 +120,8 @@ src_libwolfssl_la_SOURCES += \ wolfcrypt/src/wc_encrypt.c \ wolfcrypt/src/wc_port.c \ wolfcrypt/src/error.c \ - wolfcrypt/src/signature.c + wolfcrypt/src/signature.c \ + wolfcrypt/src/wolfmath.c if BUILD_MEMORY src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c @@ -261,7 +262,8 @@ src_libwolfssl_la_SOURCES += \ src/io.c \ src/keys.c \ src/ssl.c \ - src/tls.c + src/tls.c \ + src/tls13.c if BUILD_OCSP src_libwolfssl_la_SOURCES += src/ocsp.c diff --git a/src/internal.c b/src/internal.c old mode 100644 new mode 100755 index efce9c4913..d88716f467 --- a/src/internal.c +++ b/src/internal.c @@ -65,12 +65,6 @@ #include #endif -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } @@ -91,7 +85,6 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #ifndef NO_WOLFSSL_CLIENT static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*, word32); - static int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, word32); static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*, word32); #ifndef NO_CERTS @@ -106,14 +99,10 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #ifndef NO_WOLFSSL_SERVER - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32); static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32); #if !defined(NO_RSA) || defined(HAVE_ECC) static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); #endif - #ifdef HAVE_STUNNEL - static int SNI_Callback(WOLFSSL* ssl); - #endif #ifdef WOLFSSL_DTLS static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte); #endif /* WOLFSSL_DTLS */ @@ -126,15 +115,34 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #endif -typedef enum { +enum processReply { doProcessInit = 0, #ifndef NO_WOLFSSL_SERVER runProcessOldClientHello, #endif getRecordLayerHeader, getData, + decryptMessage, + verifyMessage, runProcessingOneMessage -} processReply; +}; + +/* sub-states for build message */ +enum buildMsgState { + BUILD_MSG_BEGIN = 0, + BUILD_MSG_SIZE, + BUILD_MSG_HASH, + BUILD_MSG_VERIFY_MAC, + BUILD_MSG_ENCRYPT, +}; + +/* sub-states for cipher operations */ +enum cipherState { + CIPHER_STATE_BEGIN = 0, + CIPHER_STATE_DO, + CIPHER_STATE_END, +}; + #ifndef NO_OLD_TLS static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, @@ -142,24 +150,10 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, #endif -#ifndef NO_CERTS -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); -#endif - #ifdef HAVE_QSH int QSH_Init(WOLFSSL* ssl); #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - int IsTLS(const WOLFSSL* ssl) { @@ -180,6 +174,11 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl) return 0; } +int IsAtLeastTLSv1_3(const ProtocolVersion pv) +{ + return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); +} + static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) { @@ -345,7 +344,8 @@ static INLINE void c16toa(word16 u16, byte* c) #if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ - || defined(HAVE_AESGCM) || defined(WOLFSSL_SESSION_EXPORT) + || defined(HAVE_AESGCM) || defined(WOLFSSL_SESSION_EXPORT) \ + || defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET) /* convert 32 bit integer to opaque */ static INLINE void c32toa(word32 u32, byte* c) { @@ -869,9 +869,15 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) #ifdef HAVE_SESSION_TICKET exp[idx++] = options->createTicket; exp[idx++] = options->useTicket; +#ifdef WOLFSSL_TLS13 + exp[idx++] = options->noTicketTls13; +#endif #else exp[idx++] = 0; exp[idx++] = 0; +#ifdef WOLFSSL_TLS13 + exp[idx++] = 0; +#endif #endif exp[idx++] = options->processReply; exp[idx++] = options->cipherSuite0; @@ -883,7 +889,7 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = options->minDowngrade; exp[idx++] = options->connectState; exp[idx++] = options->acceptState; - exp[idx++] = options->keyShareState; + exp[idx++] = options->asyncState; /* version of connection */ exp[idx++] = ssl->version.major; @@ -988,11 +994,17 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) idx++; #endif #ifdef HAVE_SESSION_TICKET - options->createTicket = exp[idx++]; /* Server to create new Ticket */ - options->useTicket = exp[idx++]; /* Use Ticket not session cache */ + options->createTicket = exp[idx++]; /* Server to create new Ticket */ + options->useTicket = exp[idx++]; /* Use Ticket not session cache */ +#ifdef WOLFSSL_TLS13 + options->noTicketTls13 = exp[idx++]; /* Server won't create new Ticket */ +#endif #else idx++; idx++; +#ifdef WOLFSSL_TLS13 + idx++; +#endif #endif options->processReply = exp[idx++]; options->cipherSuite0 = exp[idx++]; @@ -1004,7 +1016,7 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) options->minDowngrade = exp[idx++]; options->connectState = exp[idx++]; options->acceptState = exp[idx++]; - options->keyShareState = exp[idx++]; + options->asyncState = exp[idx++]; /* version of connection */ if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { @@ -1078,12 +1090,12 @@ static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) /* import ip address idx, and ipSz are unsigned but cast for enum */ ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN; - if (ipSz > sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { + if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { return BUFFER_E; } XMEMSET(ip, 0, sizeof(ip)); XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; - ip[ipSz] = '\0'; + ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */ ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN; /* sanity check for a function to call, then use it to import peer info */ @@ -1402,6 +1414,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) WOLFSSL_MSG("Bad Cert Manager New"); return BAD_CERT_MANAGER_ERROR; } + #ifdef OPENSSL_EXTRA + /* setup WOLFSSL_X509_STORE */ + ctx->x509_store.cm = ctx->cm; + #endif #endif #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) @@ -1435,9 +1451,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) /* In case contexts are held in array and don't want to free actual ctx */ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 int i; - - (void)i; +#endif #ifdef HAVE_WOLF_EVENT wolfEventQueue_Free(&ctx->event_queue); @@ -1448,35 +1464,51 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES); #ifndef NO_DH - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); -#endif + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); +#endif /* !NO_DH */ #ifdef SINGLE_THREADED if (ctx->rng) { wc_FreeRng(ctx->rng); XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG); } -#endif +#endif /* SINGLE_THREADED */ #ifndef NO_CERTS FreeDer(&ctx->privateKey); FreeDer(&ctx->certificate); #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); - if (ctx->ourCert) { + if (ctx->ourCert && ctx->ownOurCert) { + FreeX509(ctx->ourCert); XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); } - #endif + #endif /* KEEP_OUR_CERT */ FreeDer(&ctx->certChain); wolfSSL_CertManagerFree(ctx->cm); -#endif + #ifdef OPENSSL_EXTRA + while (ctx->ca_names != NULL) { + WOLFSSL_STACK *next = ctx->ca_names->next; + wolfSSL_X509_NAME_free(ctx->ca_names->data.name); + XFREE(ctx->ca_names->data.name, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->ca_names = next; + } + #endif + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + while (ctx->x509Chain != NULL) { + WOLFSSL_STACK *next = ctx->x509Chain->next; + wolfSSL_X509_free(ctx->x509Chain->data.x509); + XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->x509Chain = next; + } + #endif +#endif /* !NO_CERTS */ #ifdef HAVE_TLS_EXTENSIONS TLSX_FreeAll(ctx->extensions, ctx->heap); #ifndef NO_WOLFSSL_SERVER - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) if (ctx->certOcspRequest) { @@ -1485,29 +1517,28 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) } #endif -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 for (i = 0; i < MAX_CHAIN_DEPTH; i++) { if (ctx->chainOcspRequest[i]) { FreeOcspRequest(ctx->chainOcspRequest[i]); XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST); } } -#endif - -#endif /* NO_WOLFSSL_SERVER */ +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ +#endif /* !NO_WOLFSSL_SERVER */ #endif /* HAVE_TLS_EXTENSIONS */ + #ifdef WOLFSSL_STATIC_MEMORY if (ctx->heap != NULL) { #ifdef WOLFSSL_HEAP_TEST /* avoid derefrencing a test value */ - if (ctx->heap != (void*)WOLFSSL_HEAP_TEST) { + if (ctx->heap != (void*)WOLFSSL_HEAP_TEST) #endif - WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap); - wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex); -#ifdef WOLFSSL_HEAP_TEST + { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap); + wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex); } -#endif } #endif /* WOLFSSL_STATIC_MEMORY */ } @@ -1597,31 +1628,25 @@ void FreeCiphers(WOLFSSL* ssl) { (void)ssl; #ifdef BUILD_ARC4 - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_Arc4AsyncFree(ssl->encrypt.arc4); - wc_Arc4AsyncFree(ssl->decrypt.arc4); - } - #endif + wc_Arc4Free(ssl->encrypt.arc4); + wc_Arc4Free(ssl->decrypt.arc4); XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_DES3 - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_Des3AsyncFree(ssl->encrypt.des3); - wc_Des3AsyncFree(ssl->decrypt.des3); - } - #endif + wc_Des3Free(ssl->encrypt.des3); + wc_Des3Free(ssl->decrypt.des3); XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_AES - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_AesAsyncFree(ssl->encrypt.aes); - wc_AesAsyncFree(ssl->decrypt.aes); - } + wc_AesFree(ssl->encrypt.aes); + wc_AesFree(ssl->decrypt.aes); + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES); + XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES); + XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES); + XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES); #endif XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); @@ -1685,7 +1710,8 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[idx++] = sha256_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif - #if !defined(NO_SHA) && !defined(NO_OLD_TLS) + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) suites->hashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif @@ -1704,7 +1730,8 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[idx++] = sha256_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; #endif - #if !defined(NO_SHA) && !defined(NO_OLD_TLS) + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) suites->hashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; #endif @@ -1728,6 +1755,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR; +#ifdef WOLFSSL_TLS13 + int tls1_3 = IsAtLeastTLSv1_3(pv); +#endif int dtls = 0; int haveRSAsig = 1; @@ -1811,6 +1841,43 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif +#ifdef WOLFSSL_TLS13 +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256; + } +#endif +#endif /* WOLFSSL_TLS13 */ + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; @@ -1955,7 +2022,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSAsig) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; } @@ -1983,7 +2050,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - if (tls1_2 && haveRSAsig) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; } @@ -2158,14 +2225,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { + if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { + if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; } @@ -2196,14 +2263,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveRSA) { + if (tls && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSA) { + if (tls && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256; } @@ -2504,7 +2571,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif -#ifdef BUILD_TLS_DHE_WITH_RSA_CAMELLIA_256_CBC_SHA +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA; @@ -2589,6 +2656,13 @@ void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap) /* Initialize wolfSSL X509 type */ void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap) { + if (x509 == NULL) { + WOLFSSL_MSG("Null parameter passed in!"); + return; + } + + XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); + x509->heap = heap; InitX509Name(&x509->issuer, 0); InitX509Name(&x509->subject, 0); @@ -2644,6 +2718,12 @@ void FreeX509(WOLFSSL_X509* x509) #ifdef OPENSSL_EXTRA XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); + if (x509->authInfo != NULL) { + XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); + } + if (x509->extKeyUsageSrc != NULL) { + XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); + } #endif /* OPENSSL_EXTRA */ if (x509->altNames) FreeAltNames(x509->altNames, NULL); @@ -2678,11 +2758,7 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2697,8 +2773,9 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, return ret; } -int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, - byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx) +int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, + int hashAlgo, RsaKey* key, const byte* keyBuf, word32 keySz, + void* ctx) { int ret; @@ -2706,6 +2783,8 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, (void)keyBuf; (void)keySz; (void)ctx; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("RsaVerify"); @@ -2716,17 +2795,43 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, else #endif /*HAVE_PK_CALLBACKS */ { - ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); +#ifdef WOLFSSL_TLS13 + #ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + switch (hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + mgf = WC_MGF1SHA512; + #endif + break; + case sha384_mac: + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + mgf = WC_MGF1SHA384; + #endif + break; + case sha256_mac: + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + mgf = WC_MGF1SHA256; + #endif + break; + } + ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key); + } + else + #endif +#endif + 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2770,11 +2875,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, /* 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2814,11 +2915,7 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, /* 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2859,11 +2956,7 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, /* 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2908,11 +3001,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2925,7 +3014,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx) { - int ret, verify; + int ret; (void)ssl; (void)keyBuf; @@ -2937,27 +3026,23 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccVerifyCb) { ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz, - &verify, ctx); + &ssl->eccVerifyRes, ctx); } else #endif /* HAVE_PK_CALLBACKS */ { - ret = wc_ecc_verify_hash(in, inSz, out, outSz, &verify, key); + ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } else #endif /* WOLFSSL_ASYNC_CRYPT */ { - ret = (ret != 0 || verify == 0) ? VERIFY_SIGN_ERROR : 0; + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; } WOLFSSL_LEAVE("EccVerify", ret); @@ -2997,10 +3082,10 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, } else if (ssl->options.side == WOLFSSL_SERVER_END) { if (ssl->specs.static_ecdh) { - if (ssl->sigKey == NULL) { + if (ssl->hsKey == NULL) { return NO_PRIVATE_KEY; } - tmpKey = (struct ecc_key*)ssl->sigKey; + tmpKey = (struct ecc_key*)ssl->hsKey; } else { if (!ssl->eccTempKeyPresent) { @@ -3052,11 +3137,8 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_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, &priv_key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3079,17 +3161,20 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) keySz = peer->dp->size; } - /* TODO: Implement _ex version here */ - ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ssl->ecdhCurveOID > 0) { + ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, + wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); + } + else { + ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ret == 0) + ssl->ecdhCurveOID = key->dp->oidSum; + } /* 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; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3105,60 +3190,67 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) #if !defined(NO_CERTS) || !defined(NO_PSK) #if !defined(NO_DH) -int DhGenKeyPair(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, +int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz) { int ret; - DhKey dhKey; - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); - if (ret == 0) { - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); + WOLFSSL_ENTER("DhGenKeyPair"); + + ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz); + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); } - wc_FreeDhKey(&dhKey); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhGenKeyPair", ret); return ret; } -int DhAgree(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, - byte* priv, word32* privSz, - byte* pub, word32* pubSz, +int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, byte* agree, word32* agreeSz) { int ret; - DhKey dhKey; - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); - if (ret == 0 && pub) { - /* for DH, encSecret is Yc, agree is pre-master */ - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); - } - if (ret == 0) { - ret = wc_DhAgree(&dhKey, agree, agreeSz, priv, *privSz, otherPub, otherPubSz); + (void)ssl; + + WOLFSSL_ENTER("DhAgree"); + + ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub, otherPubSz); + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); } - wc_FreeDhKey(&dhKey); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhAgree", ret); return ret; } - #endif /* !NO_DH */ #endif /* !NO_CERTS || !NO_PSK */ - /* This function inherits a WOLFSSL_CTX's fields into an SSL object. It is used during initialization and to switch an ssl's CTX with wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK + unless writeDup is on. + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + SSL_SUCCESS return value on success */ -int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) { byte havePSK = 0; byte haveAnon = 0; @@ -3166,13 +3258,16 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) byte haveRSA = 0; (void) haveAnon; /* Squash unused var warnings */ - if(!ssl || !ctx || ssl->suites == NULL) + if (!ssl || !ctx) + return BAD_FUNC_ARG; + + if (ssl->suites == NULL && !writeDup) return BAD_FUNC_ARG; newSSL = ssl->ctx == NULL; /* Assign after null check */ #ifndef NO_PSK - if (ctx->server_hint[0] && ssl->arrays == NULL) { + if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) { return BAD_FUNC_ARG; /* needed for copy below */ } #endif @@ -3208,17 +3303,19 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ECC ssl->eccTempKeySz = ctx->eccTempKeySz; ssl->pkCurveOID = ctx->pkCurveOID; + ssl->ecdhCurveOID = ctx->ecdhCurveOID; #endif +#ifdef OPENSSL_EXTRA + ssl->options.mask = ctx->mask; +#endif ssl->timeout = ctx->timeout; ssl->verifyCallback = ctx->verifyCallback; ssl->options.side = ctx->method->side; ssl->options.downgrade = ctx->method->downgrade; ssl->options.minDowngrade = ctx->minDowngrade; - if (ssl->options.side == WOLFSSL_SERVER_END) - ssl->options.haveDH = ctx->haveDH; - + ssl->options.haveDH = ctx->haveDH; ssl->options.haveNTRU = ctx->haveNTRU; ssl->options.haveECDSAsig = ctx->haveECDSAsig; ssl->options.haveECC = ctx->haveECC; @@ -3245,6 +3342,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.sessionCacheOff = ctx->sessionCacheOff; ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + ssl->options.internalCacheOff = ctx->internalCacheOff; +#endif ssl->options.verifyPeer = ctx->verifyPeer; ssl->options.verifyNone = ctx->verifyNone; @@ -3257,16 +3357,17 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.groupMessages = ctx->groupMessages; #ifndef NO_DH - if (ssl->options.side == WOLFSSL_SERVER_END) { - ssl->buffers.serverDH_P = ctx->serverDH_P; - ssl->buffers.serverDH_G = ctx->serverDH_G; - } + ssl->buffers.serverDH_P = ctx->serverDH_P; + ssl->buffers.serverDH_G = ctx->serverDH_G; #endif #ifndef NO_CERTS /* ctx still owns certificate, certChain, key, dh, and cm */ ssl->buffers.certificate = ctx->certificate; ssl->buffers.certChain = ctx->certChain; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = ctx->certChainCnt; +#endif ssl->buffers.key = ctx->privateKey; #endif @@ -3274,55 +3375,144 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->devId = ctx->devId; #endif + if (writeDup == 0) { + #ifndef NO_PSK - if (ctx->server_hint[0]) { /* set in CTX */ - XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN); - ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; - } + if (ctx->server_hint[0]) { /* set in CTX */ + XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ + } #endif /* NO_PSK */ - if (ctx->suites) - *ssl->suites = *ctx->suites; - else - XMEMSET(ssl->suites, 0, sizeof(Suites)); + if (ctx->suites) + *ssl->suites = *ctx->suites; + else + XMEMSET(ssl->suites, 0, sizeof(Suites)); - /* make sure server has DH parms, and add PSK if there, add NTRU too */ - if (ssl->options.side == WOLFSSL_SERVER_END) - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + /* make sure server has DH parms, and add PSK if there, add NTRU too */ + if (ssl->options.side == WOLFSSL_SERVER_END) + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); - else - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE, + else + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) - /* make sure server has cert and key unless using PSK or Anon - * This should be true even if just switching ssl ctx */ - if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) - if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer || - !ssl->buffers.key || !ssl->buffers.key->buffer) { - WOLFSSL_MSG("Server missing certificate and/or private key"); - return NO_PRIVATE_KEY; - } + /* make sure server has cert and key unless using PSK or Anon + * This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) + if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer + || !ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("Server missing certificate and/or private key"); + return NO_PRIVATE_KEY; + } #endif + } /* writeDup check */ + #ifdef WOLFSSL_SESSION_EXPORT #ifdef WOLFSSL_DTLS ssl->dtls_export = ctx->dtls_export; /* export function for session */ #endif #endif +#ifdef OPENSSL_EXTRA + ssl->readAhead = ctx->readAhead; +#endif + return SSL_SUCCESS; } +int InitHandshakeHashes(WOLFSSL* ssl) +{ + int ret; + + /* make sure existing handshake hashes are free'd */ + if (ssl->hsHashes != NULL) { + FreeHandshakeHashes(ssl); + } + + /* allocate handshake hashes */ + ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, + DYNAMIC_TYPE_HASHES); + if (ssl->hsHashes == NULL) { + WOLFSSL_MSG("HS_Hashes Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes)); + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifndef NO_SHA + ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#endif /* !NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif + + return ret; +} + +void FreeHandshakeHashes(WOLFSSL* ssl) +{ + if (ssl->hsHashes) { +#ifndef NO_OLD_TLS + #ifndef NO_MD5 + wc_Md5Free(&ssl->hsHashes->hashMd5); + #endif + #ifndef NO_SHA + wc_ShaFree(&ssl->hsHashes->hashSha); + #endif +#endif /* !NO_OLD_TLS */ + #ifndef NO_SHA256 + wc_Sha256Free(&ssl->hsHashes->hashSha256); + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384Free(&ssl->hsHashes->hashSha384); + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512Free(&ssl->hsHashes->hashSha512); + #endif + + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes = NULL; + } +} + /* init everything to 0, NULL, default values before calling anything that may fail so that destructor has a "good" state to cleanup + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + 0 on success */ -int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) { int ret; @@ -3433,6 +3623,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->rfd = -1; /* set to invalid descriptor */ ssl->wfd = -1; + ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */ ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ @@ -3442,12 +3633,17 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ #endif + /* initialize states */ ssl->options.serverState = NULL_STATE; ssl->options.clientState = NULL_STATE; ssl->options.connectState = CONNECT_BEGIN; ssl->options.acceptState = ACCEPT_BEGIN; ssl->options.handShakeState = NULL_STATE; ssl->options.processReply = doProcessInit; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + ssl->encrypt.state = CIPHER_STATE_BEGIN; + ssl->decrypt.state = CIPHER_STATE_BEGIN; #ifdef WOLFSSL_DTLS #ifdef WOLFSSL_SCTP @@ -3476,6 +3672,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_EXTENDED_MASTER ssl->options.haveEMS = ctx->haveEMS; #endif + ssl->options.useClientOrder = ctx->useClientOrder; + +#ifdef WOLFSSL_TLS13 +#ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = ctx->noTicketTls13; +#endif + ssl->options.noPskDheKe = ctx->noPskDheKe; +#endif #ifdef HAVE_TLS_EXTENSIONS #ifdef HAVE_MAX_FRAGMENT @@ -3483,6 +3687,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif #ifdef HAVE_ALPN ssl->alpn_client_list = NULL; + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + ssl->alpnSelect = ctx->alpnSelect; + ssl->alpnSelectArg = ctx->alpnSelectArg; + #endif +#endif +#ifdef HAVE_SUPPORTED_CURVES + ssl->options.userCurves = ctx->userCurves; #endif #endif /* HAVE_TLS_EXTENSIONS */ @@ -3497,68 +3708,38 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* all done with init, now can return errors, call other stuff */ - /* arrays */ - ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, + if (!writeDup) { + /* arrays */ + ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, DYNAMIC_TYPE_ARRAYS); - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays Memory error"); - return MEMORY_E; - } - XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->arrays->preMasterSecret == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); - /* suites */ - ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + /* suites */ + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, DYNAMIC_TYPE_SUITES); - if (ssl->suites == NULL) { - WOLFSSL_MSG("Suites Memory error"); - return MEMORY_E; + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } } /* Initialize SSL with the appropriate fields from it's ctx */ - /* requires valid arrays and suites */ - if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS) + /* requires valid arrays and suites unless writeDup ing */ + if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != SSL_SUCCESS) return ret; ssl->options.dtls = ssl->version.major == DTLS_MAJOR; - /* hsHashes */ - ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, - DYNAMIC_TYPE_HASHES); - if (ssl->hsHashes == NULL) { - WOLFSSL_MSG("HS_Hashes Memory error"); - return MEMORY_E; - } - -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - wc_InitMd5(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - ret = wc_InitSha(&ssl->hsHashes->hashSha); - if (ret != 0) { - return ret; - } -#endif -#endif -#ifndef NO_SHA256 - ret = wc_InitSha256(&ssl->hsHashes->hashSha256); - if (ret != 0) { - return ret; - } -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_InitSha384(&ssl->hsHashes->hashSha384); - if (ret != 0) { - return ret; - } -#endif -#ifdef WOLFSSL_SHA512 - ret = wc_InitSha512(&ssl->hsHashes->hashSha512); - if (ret != 0) { - return ret; - } -#endif - #ifdef SINGLE_THREADED ssl->rng = ctx->rng; /* CTX may have one, if so use it */ #endif @@ -3570,11 +3751,12 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) WOLFSSL_MSG("RNG Memory error"); return MEMORY_E; } + XMEMSET(ssl->rng, 0, sizeof(WC_RNG)); ssl->options.weOwnRng = 1; /* FIPS RNG API does not accept a heap hint */ #ifndef HAVE_FIPS - if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) { + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) { WOLFSSL_MSG("RNG Init error"); return ret; } @@ -3586,6 +3768,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif } + if (writeDup) { + /* all done */ + return 0; + } + + /* hsHashes */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) { ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0); @@ -3611,12 +3803,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* free use of temporary arrays */ void FreeArrays(WOLFSSL* ssl, int keep) { - if (ssl->arrays && keep) { - /* keeps session id for user retrieval */ - XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); - ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; - } if (ssl->arrays) { + if (keep) { + /* keeps session id for user retrieval */ + XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + } + if (ssl->arrays->preMasterSecret) { + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->arrays->preMasterSecret = NULL; + } XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays->pendingMsg = NULL; ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */ @@ -3625,7 +3821,111 @@ void FreeArrays(WOLFSSL* ssl, int keep) ssl->arrays = NULL; } -static void FreeKeyExchange(WOLFSSL* ssl) +void FreeKey(WOLFSSL* ssl, int type, void** pKey) +{ + if (ssl && pKey && *pKey) { + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + wc_FreeRsaKey((RsaKey*)*pKey); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + wc_ecc_free((ecc_key*)*pKey); + break; + #endif /* HAVE_ECC */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + wc_FreeDhKey((DhKey*)*pKey); + break; + #endif /* !NO_DH */ + default: + break; + } + XFREE(*pKey, ssl->heap, type); + + /* Reset pointer */ + *pKey = NULL; + } +} + +int AllocKey(WOLFSSL* ssl, int type, void** pKey) +{ + int ret = BAD_FUNC_ARG; + int sz = 0; + + if (ssl == NULL || pKey == NULL) { + return BAD_FUNC_ARG; + } + + /* Sanity check key destination */ + if (*pKey != NULL) { + WOLFSSL_MSG("Key already present!"); + return BAD_STATE_E; + } + + /* Determine size */ + switch (type) { + case DYNAMIC_TYPE_RSA: + #ifndef NO_RSA + sz = sizeof(RsaKey); + #endif /* ! NO_RSA */ + break; + case DYNAMIC_TYPE_ECC: + #ifdef HAVE_ECC + sz = sizeof(ecc_key); + #endif /* HAVE_ECC */ + break; + case DYNAMIC_TYPE_DH: + #ifndef NO_DH + sz = sizeof(DhKey); + #endif /* !NO_DH */ + break; + default: + return BAD_FUNC_ARG; + } + + if (sz == 0) { + return NOT_COMPILED_IN; + } + + /* Allocate memeory for key */ + *pKey = XMALLOC(sz, ssl->heap, type); + if (*pKey == NULL) { + return MEMORY_E; + } + + /* Initialize key */ + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* HAVE_ECC */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + /* On error free handshake key */ + if (ret != 0) { + FreeKey(ssl, type, pKey); + } + + return ret; +} + +void FreeKeyExchange(WOLFSSL* ssl) { /* Cleanup signature buffer */ if (ssl->buffers.sig.buffer) { @@ -3641,33 +3941,21 @@ static void FreeKeyExchange(WOLFSSL* ssl) ssl->buffers.digest.length = 0; } - /* Free sigKey */ - if (ssl->sigKey) { - switch (ssl->sigType) - { - #ifndef NO_RSA - case DYNAMIC_TYPE_RSA: - { - wc_FreeRsaKey((RsaKey*)ssl->sigKey); - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_RSA); - break; - } - #endif /* ! NO_RSA */ - #ifdef HAVE_ECC - case DYNAMIC_TYPE_ECC: - { - wc_ecc_free((ecc_key*)ssl->sigKey); - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_ECC); - break; - } - #endif /* HAVE_ECC */ - default: - break; - } - /* Reset type and pointer */ - ssl->sigType = 0; - ssl->sigKey = NULL; + /* Free handshake key */ + FreeKey(ssl, ssl->hsType, &ssl->hsKey); + +#ifndef NO_DH + /* Free temp DH key */ + FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key); +#endif + + /* Cleanup async */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->async.freeArgs) { + ssl->async.freeArgs(ssl, ssl->async.args); + ssl->async.freeArgs = NULL; } +#endif } /* In case holding SSL object in array and don't want to free actual ssl */ @@ -3687,23 +3975,23 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); } XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + FreeHandshakeHashes(ssl); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); /* clear keys struct after session */ - ForceZero(&(ssl->keys), sizeof(Keys)); + ForceZero(&ssl->keys, sizeof(Keys)); #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); /* parameters (p,g) may be owned by ctx */ if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); } #endif /* !NO_DH */ #ifndef NO_CERTS @@ -3711,10 +3999,8 @@ void SSL_ResourceFree(WOLFSSL* ssl) wolfSSL_UnloadCertsKeys(ssl); #endif #ifndef NO_RSA - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - } + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, FORCED_FREE); @@ -3743,21 +4029,12 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeStreams(ssl); #endif #ifdef HAVE_ECC - if (ssl->peerEccKey) { - if (ssl->peerEccKeyPresent) - wc_ecc_free(ssl->peerEccKey); - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - } - if (ssl->peerEccDsaKey) { - if (ssl->peerEccDsaKeyPresent) - wc_ecc_free(ssl->peerEccDsaKey); - XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); - } - if (ssl->eccTempKey) { - if (ssl->eccTempKeyPresent) - wc_ecc_free(ssl->eccTempKey); - XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); - } + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; #endif /* HAVE_ECC */ #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC @@ -3793,6 +4070,14 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->session.ticketLen = 0; } #endif +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(ssl->extSession); +#endif +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + FreeWriteDup(ssl); + } +#endif #ifdef WOLFSSL_STATIC_MEMORY /* check if using fixed io buffers and free them */ @@ -3835,15 +4120,6 @@ void SSL_ResourceFree(WOLFSSL* ssl) /* Free any handshake resources no longer needed */ void FreeHandshakeResources(WOLFSSL* ssl) { -#ifndef NO_MD5 - wc_Md5Free(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - wc_ShaFree(&ssl->hsHashes->hashSha); -#endif -#ifndef NO_SHA256 - wc_Sha256Free(&ssl->hsHashes->hashSha25); -#endif #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { @@ -3861,8 +4137,7 @@ void FreeHandshakeResources(WOLFSSL* ssl) ssl->suites = NULL; /* hsHashes */ - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); - ssl->hsHashes = NULL; + FreeHandshakeHashes(ssl); /* RNG */ if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) { @@ -3890,56 +4165,32 @@ void FreeHandshakeResources(WOLFSSL* ssl) #ifndef NO_RSA /* peerRsaKey */ - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - ssl->peerRsaKey = NULL; - } + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif #ifdef HAVE_ECC - if (ssl->peerEccKey) - { - if (ssl->peerEccKeyPresent) { - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - } - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccKey = NULL; - } - if (ssl->peerEccDsaKey) - { - if (ssl->peerEccDsaKeyPresent) { - wc_ecc_free(ssl->peerEccDsaKey); - ssl->peerEccDsaKeyPresent = 0; - } - XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccDsaKey = NULL; - } - if (ssl->eccTempKey) - { - if (ssl->eccTempKeyPresent) { - wc_ecc_free(ssl->eccTempKey); - ssl->eccTempKeyPresent = 0; - } - XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->eccTempKey = NULL; - } + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; #endif /* HAVE_ECC */ #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_Priv.buffer = NULL; - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_Pub.buffer = NULL; /* parameters (p,g) may be owned by ctx */ if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_G.buffer = NULL; - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_P.buffer = NULL; } #endif /* !NO_DH */ @@ -4008,7 +4259,7 @@ void FreeSSL(WOLFSSL* ssl, void* heap) #if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ - || defined(HAVE_AESGCM) + || defined(HAVE_AESGCM) || defined(WOLFSSL_DTLS) static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) { if (verify) { @@ -4112,6 +4363,7 @@ DtlsMsg* DtlsMsgNew(word32 sz, void* heap) { DtlsMsg* msg = NULL; + (void)heap; msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG); if (msg != NULL) { @@ -4168,6 +4420,7 @@ static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data, DtlsFrag* newFrag; word32 added = end - *begin + 1; + (void)heap; newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap, DYNAMIC_TYPE_DTLS_FRAG); if (newFrag != NULL) { @@ -4506,7 +4759,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 0, 0); + handshake, 0, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -4730,7 +4983,7 @@ ProtocolVersion MakeDTLSv1_2(void) #ifndef NO_CERTS -static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) { int ret = 0; @@ -4774,7 +5027,7 @@ static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) /* add output to md5 and sha handshake hashes, exclude record header */ -static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) +int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) { int ret = 0; const byte* adj; @@ -4824,10 +5077,12 @@ static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) /* add input to md5 and sha handshake hashes, include handshake header */ -static int HashInput(WOLFSSL* ssl, const byte* input, int sz) +int HashInput(WOLFSSL* ssl, const byte* input, int sz) { int ret = 0; - const byte* adj = input - HANDSHAKE_HEADER_SZ; + const byte* adj; + + adj = input - HANDSHAKE_HEADER_SZ; sz += HANDSHAKE_HEADER_SZ; (void)adj; @@ -4839,6 +5094,10 @@ static int HashInput(WOLFSSL* ssl, const byte* input, int sz) } #endif + if (ssl->hsHashes == NULL) { + return BAD_FUNC_ARG; + } + #ifndef NO_OLD_TLS #ifndef NO_SHA wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); @@ -4882,7 +5141,12 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl } rl->type = type; rl->pvMajor = ssl->version.major; /* type and version same in each */ - rl->pvMinor = ssl->version.minor; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + rl->pvMinor = TLSv1_MINOR; + else +#endif + rl->pvMinor = ssl->version.minor; #ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE if (ssl->options.side == WOLFSSL_CLIENT_END @@ -5092,6 +5356,14 @@ int SendBuffered(WOLFSSL* ssl) return SOCKET_ERROR_E; } +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.outputBuffer.idx == 0) { + WOLFSSL_MSG("Data to send"); + WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.length); + } +#endif + while (ssl->buffers.outputBuffer.length > 0) { int sent = ssl->ctx->CBIOSend(ssl, (char*)ssl->buffers.outputBuffer.buffer + @@ -5158,9 +5430,15 @@ int SendBuffered(WOLFSSL* ssl) static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) { byte* tmp; +#if WOLFSSL_GENERAL_ALIGNMENT > 0 byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : RECORD_HEADER_SZ; - byte align = WOLFSSL_GENERAL_ALIGNMENT; + byte align = WOLFSSL_GENERAL_ALIGNMENT; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by the header, if the user wants encrypted alignment they need to define their alignment requirement */ @@ -5169,14 +5447,19 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) while (align < hdrSz) align *= 2; } +#endif - tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align, - ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); WOLFSSL_MSG("growing output buffer\n"); - if (!tmp) return MEMORY_E; + if (tmp == NULL) + return MEMORY_E; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) tmp += align - hdrSz; +#endif if (ssl->buffers.outputBuffer.length) XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, @@ -5187,10 +5470,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) ssl->buffers.outputBuffer.offset, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); ssl->buffers.outputBuffer.dynamicFlag = 1; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) ssl->buffers.outputBuffer.offset = align - hdrSz; else +#endif ssl->buffers.outputBuffer.offset = 0; + ssl->buffers.outputBuffer.buffer = tmp; ssl->buffers.outputBuffer.bufferSize = size + ssl->buffers.outputBuffer.length; @@ -5202,8 +5489,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) { byte* tmp; - byte hdrSz = DTLS_RECORD_HEADER_SZ; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0; + byte hdrSz = DTLS_RECORD_HEADER_SZ; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by the dtls record header, if the user wants encrypted alignment they need to define their alignment requirement. in tls we read record header @@ -5213,19 +5506,24 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) while (align < hdrSz) align *= 2; } +#endif if (usedLength < 0 || size < 0) { WOLFSSL_MSG("GrowInputBuffer() called with negative number"); return BAD_FUNC_ARG; } - tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap, - DYNAMIC_TYPE_IN_BUFFER); + tmp = (byte*)XMALLOC(size + usedLength + align, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); WOLFSSL_MSG("growing input buffer\n"); - if (!tmp) return MEMORY_E; + if (tmp == NULL) + return MEMORY_E; + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) tmp += align - hdrSz; +#endif if (usedLength) XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + @@ -5236,10 +5534,13 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) ssl->heap,DYNAMIC_TYPE_IN_BUFFER); ssl->buffers.inputBuffer.dynamicFlag = 1; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) ssl->buffers.inputBuffer.offset = align - hdrSz; else +#endif ssl->buffers.inputBuffer.offset = 0; + ssl->buffers.inputBuffer.buffer = tmp; ssl->buffers.inputBuffer.bufferSize = size + usedLength; ssl->buffers.inputBuffer.idx = 0; @@ -5252,7 +5553,6 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) /* check available size into output buffer, make room if needed */ int CheckAvailableSize(WOLFSSL *ssl, int size) { - if (size < 0) { WOLFSSL_MSG("CheckAvailableSize() called with negative number"); return BAD_FUNC_ARG; @@ -5311,8 +5611,41 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif +#ifdef OPENSSL_EXTRA + /* case where specific protocols are turned off */ + if (!ssl->options.dtls && ssl->options.mask > 0) { + if (rh->pvMinor == SSLv3_MINOR && + (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("Option set to not allow SSLv3"); + return VERSION_ERROR; + } + if (rh->pvMinor == TLSv1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("Option set to not allow TLSv1"); + return VERSION_ERROR; + } + if (rh->pvMinor == TLSv1_1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("Option set to not allow TLSv1.1"); + return VERSION_ERROR; + } + if (rh->pvMinor == TLSv1_2_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("Option set to not allow TLSv1.2"); + return VERSION_ERROR; + } + } +#endif /* OPENSSL_EXTRA */ + /* catch version mismatch */ - if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){ +#ifndef WOLFSSL_TLS13 + if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor) +#else + if (rh->pvMajor != ssl->version.major || + (rh->pvMinor != ssl->version.minor && + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR))) +#endif + { if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE) @@ -5392,7 +5725,7 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, *type = input[idx++]; c24to32(input + idx, size); - idx += BYTE3_LEN; + idx += OPAQUE24_LEN; ato16(input + idx, &ssl->keys.dtls_peer_handshake_number); idx += DTLS_HANDSHAKE_SEQ_SZ; @@ -5415,7 +5748,8 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, #endif -#ifndef NO_OLD_TLS +#if !defined(NO_OLD_TLS) || \ + (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1)) /* fill with MD5 pad size since biggest required */ static const byte PAD1[PAD_MD5] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, @@ -5433,82 +5767,104 @@ static const byte PAD2[PAD_MD5] = 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }; +#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */ + +#ifndef NO_OLD_TLS /* calculate MD5 hash for finished */ #ifdef WOLFSSL_TI_HASH #include #endif -static void BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { - + int ret; byte md5_result[MD5_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; #else - Md5 md5[1]; - Md5 md5_2[1]; + Md5 md5[1]; #endif /* make md5 inner */ - md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ - - wc_Md5Update(&ssl->hsHashes->hashMd5, sender, SIZEOF_SENDER); - wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); - wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); - wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); + if (ret == 0) + ret = wc_Md5Update(md5, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); /* make md5 outer */ - wc_InitMd5(md5_2) ; - wc_Md5Update(md5_2, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(md5_2, PAD2, PAD_MD5); - wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); - wc_Md5Final(md5_2, hashes->md5); + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, hashes->md5); + wc_Md5Free(md5); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; } /* calculate SHA hash for finished */ -static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { + int ret; byte sha_result[SHA_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Sha* sha = (Sha*)XMALLOC(sizeof(Sha), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; #else - Sha sha[1]; - Sha sha2[1] ; + Sha sha[1]; #endif /* make sha inner */ - sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ - - wc_ShaUpdate(&ssl->hsHashes->hashSha, sender, SIZEOF_SENDER); - wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); - wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); - wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); /* make sha outer */ - wc_InitSha(sha2) ; - wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(sha2, PAD2, PAD_SHA); - wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); - wc_ShaFinal(sha2, hashes->sha); + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, hashes->sha); + wc_ShaFree(sha); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; } #endif @@ -5516,28 +5872,25 @@ static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret = 0; +#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SMALL_STACK - #ifdef WOLFSSL_SHA384 - Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + Sha384* sha384; #else - #ifdef WOLFSSL_SHA384 - Sha384 sha384[1]; - #endif -#endif + Sha384 sha384[1]; +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* WOLFSSL_SHA384 */ + + if (ssl == NULL) + return BAD_FUNC_ARG; +#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SMALL_STACK - if (ssl == NULL - #ifdef WOLFSSL_SHA384 - || sha384 == NULL - #endif - ) { - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL) return MEMORY_E; - } -#endif +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* WOLFSSL_SHA384 */ /* store current states, building requires get_digest which resets state */ #ifdef WOLFSSL_SHA384 @@ -5551,8 +5904,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #endif #ifndef NO_OLD_TLS if (!ssl->options.tls) { - BuildMD5(ssl, hashes, sender); - BuildSHA(ssl, hashes, sender); + ret = BuildMD5(ssl, hashes, sender); + if (ret == 0) { + ret = BuildSHA(ssl, hashes, sender); + } } #endif @@ -5563,9 +5918,9 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #endif } -#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif #endif @@ -5810,8 +6165,6 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : if (requirement == REQUIRES_RSA) return 1; - if (requirement == REQUIRES_RSA_SIG) - return 1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : @@ -5880,7 +6233,29 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 0; } /* switch */ } /* if */ - if (first != ECC_BYTE && first != CHACHA_BYTE) { /* normal suites */ + + /* Distinct TLS v1.3 cipher suites with cipher and digest only. */ + if (first == TLS13_BYTE) { + + switch (second) { +#ifdef WOLFSSL_TLS13 + case TLS_AES_128_GCM_SHA256: + case TLS_AES_256_GCM_SHA384: + case TLS_CHACHA20_POLY1305_SHA256: + case TLS_AES_128_CCM_SHA256: + case TLS_AES_128_CCM_8_SHA256: + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires " + "TLS v1.3"); + return 0; + } + } + + if (first != ECC_BYTE && first != CHACHA_BYTE && + first != TLS13_BYTE) { /* normal suites */ switch (second) { #ifndef NO_RSA @@ -6099,7 +6474,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) *.z.com matches y.z.com but not x.y.z.com return 1 on success */ -static int MatchDomainName(const char* pattern, int len, const char* str) +int MatchDomainName(const char* pattern, int len, const char* str) { char p, s; @@ -6114,8 +6489,8 @@ static int MatchDomainName(const char* pattern, int len, const char* str) if (p == '*') { while (--len > 0 && - (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') - ; + (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') { + } if (len == 0) p = '\0'; @@ -6145,7 +6520,7 @@ static int MatchDomainName(const char* pattern, int len, const char* str) /* try to find an altName match to domain, return 1 on success */ -static int CheckAltNames(DecodedCert* dCert, char* domain) +int CheckAltNames(DecodedCert* dCert, char* domain) { int match = 0; DNS_entry* altName = NULL; @@ -6156,7 +6531,7 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) altName = dCert->altNames; while (altName) { - WOLFSSL_MSG(" individual AltName check"); + WOLFSSL_MSG("\tindividual AltName check"); if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){ match = 1; @@ -6170,7 +6545,79 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) } -#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) +#ifdef OPENSSL_EXTRA +/* Check that alternative names, if they exists, match the domain. + * Fail if there are wild patterns and they didn't match. + * Check the common name if no alternative names matched. + * + * dCert Decoded cert to get the alternative names from. + * domain Domain name to compare against. + * checkCN Whether to check the common name. + * returns whether there was a problem in matching. + */ +static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN) +{ + int match; + DNS_entry* altName = NULL; + + WOLFSSL_MSG("Checking AltNames"); + + if (dCert) + altName = dCert->altNames; + + *checkCN = altName == NULL; + match = 0; + while (altName) { + WOLFSSL_MSG("\tindividual AltName check"); + + if (MatchDomainName(altName->name, (int)XSTRLEN(altName->name), + domain)) { + match = 1; + *checkCN = 0; + break; + } + /* No matches and wild pattern match failed. */ + else if (altName->name[0] == '*' && match == 0) + match = -1; + + altName = altName->next; + } + + return match != -1; +} + +/* Check the domain name matches the subject alternative name or the subject + * name. + * + * dcert Decoded certificate. + * domainName The domain name. + * domainNameLen The length of the domain name. + * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success. + */ +int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen) +{ + int checkCN; + + /* Assume name is NUL terminated. */ + (void)domainNameLen; + + if (CheckForAltNames(dCert, domainName, &checkCN) == 0) { + WOLFSSL_MSG("DomainName match on alt names failed too"); + return DOMAIN_NAME_MISMATCH; + } + if (checkCN == 1) { + if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + domainName) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + return DOMAIN_NAME_MISMATCH; + } + } + + return 0; +} +#endif + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) /* Copy parts X509 needs from Decoded cert, 0 on success */ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) @@ -6279,7 +6726,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) ret = MEMORY_E; } - if (dCert->signature != NULL && dCert->sigLength != 0) { + if (dCert->signature != NULL && dCert->sigLength != 0 && + dCert->sigLength <= MAX_ENCODED_SIG_SZ) { x509->sig.buffer = (byte*)XMALLOC( dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE); if (x509->sig.buffer == NULL) { @@ -6309,6 +6757,23 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->pathLength = dCert->pathLength; x509->keyUsage = dCert->extKeyUsage; + x509->CRLdistSet = dCert->extCRLdistSet; + x509->CRLdistCrit = dCert->extCRLdistCrit; + x509->CRLInfo = dCert->extCrlInfo; + x509->CRLInfoSz = dCert->extCrlInfoSz; + x509->authInfoSet = dCert->extAuthInfoSet; + x509->authInfoCrit = dCert->extAuthInfoCrit; + if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) { + x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->authInfo != NULL) { + XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz); + x509->authInfoSz = dCert->extAuthInfoSz; + } + else { + ret = MEMORY_E; + } + } x509->basicConstSet = dCert->extBasicConstSet; x509->basicConstCrit = dCert->extBasicConstCrit; x509->basicConstPlSet = dCert->pathLengthSet; @@ -6342,10 +6807,33 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } x509->keyUsageSet = dCert->extKeyUsageSet; x509->keyUsageCrit = dCert->extKeyUsageCrit; + if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) { + x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz, + x509->heap, DYNAMIC_TYPE_X509_EXT); + if (x509->extKeyUsageSrc != NULL) { + XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc, + dCert->extExtKeyUsageSz); + x509->extKeyUsageSz = dCert->extExtKeyUsageSz; + x509->extKeyUsageCrit = dCert->extExtKeyUsageCrit; + x509->extKeyUsageCount = dCert->extExtKeyUsageCount; + } + else { + ret = MEMORY_E; + } + } #ifdef WOLFSSL_SEP x509->certPolicySet = dCert->extCertPolicySet; x509->certPolicyCrit = dCert->extCertPolicyCrit; #endif /* WOLFSSL_SEP */ + #ifdef WOLFSSL_CERT_EXT + { + int i; + for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++) + XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i], + MAX_CERTPOL_SZ); + x509->certPoliciesNb = dCert->extCertPoliciesNb; + } + #endif /* WOLFSSL_CERT_EXT */ #endif /* OPENSSL_EXTRA */ #ifdef HAVE_ECC x509->pkCurveOID = dCert->pkCurveOID; @@ -6356,699 +6844,1036 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) #endif /* KEEP_PEER_CERT || SESSION_CERTS */ +typedef struct ProcPeerCertArgs { + buffer* certs; +#ifdef WOLFSSL_TLS13 + buffer* exts; /* extentions */ +#endif + DecodedCert* dCert; + char* domain; + word32 idx; + word32 begin; + int totalCerts; /* number of certs in certs buffer */ + int count; + int dCertInit; + int certIdx; + int fatal; + int lastErr; +#ifdef WOLFSSL_TLS13 + byte ctxSz; +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + byte haveTrustPeer; /* was cert verified by loaded trusted peer cert */ +#endif +} ProcPeerCertArgs; -static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, - word32 size) +static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) { - word32 listSz; - word32 begin = *inOutIdx; - int ret = 0; - int anyError = 0; - int totalCerts = 0; /* number of certs in certs buffer */ - int count; - buffer certs[MAX_CHAIN_DEPTH]; + ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs; -#ifdef WOLFSSL_SMALL_STACK - char* domain = NULL; - DecodedCert* dCert = NULL; - WOLFSSL_X509_STORE_CTX* store = NULL; + (void)ssl; + + if (args->domain) { + XFREE(args->domain, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->domain = NULL; + } + if (args->certs) { + XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->certs = NULL; + } +#ifdef WOLFSSL_TLS13 + if (args->exts) { + XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->exts = NULL; + } +#endif + if (args->dCert) { + if (args->dCertInit) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->dCert = NULL; + } +} + +int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); #else - char domain[ASN_NAME_MAX]; - DecodedCert dCert[1]; - WOLFSSL_X509_STORE_CTX store[1]; + ProcPeerCertArgs args[1]; #endif #ifdef WOLFSSL_TRUST_PEER_CERT byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */ #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo); + WOLFSSL_ENTER("ProcessPeerCerts"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_ppc; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ProcPeerCertArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeProcPeerCertArgs; #endif + } - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; + switch (ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + word32 listSz; - c24to32(input + *inOutIdx, &listSz); - *inOutIdx += OPAQUE24_LEN; + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("Certificate", &ssl->timeoutInfo); + #endif - if (listSz > MAX_RECORD_SIZE) - return BUFFER_E; + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + byte ctxSz; - if ((*inOutIdx - begin) + listSz != size) - return BUFFER_ERROR; + /* Certificate Request Context */ + if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz) + return BUFFER_ERROR; + ctxSz = *(input + args->idx); + args->idx++; + if ((args->idx - args->begin) + ctxSz > totalSz) + return BUFFER_ERROR; + #ifndef NO_WOLFSSL_CLIENT + /* Must be empty when received from server. */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ctxSz != 0) { + return INVALID_CERT_CTX_E; + } + } + #endif + #ifndef NO_WOLFSSL_SERVER + /* Must contain value sent in request when received from client. */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->clientCertCtx.length != ctxSz || + XMEMCMP(ssl->clientCertCtx.buffer, + input + args->idx, ctxSz) != 0) { + return INVALID_CERT_CTX_E; + } + } + #endif + args->idx += ctxSz; + + /* allocate buffer for cert extensions */ + args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->exts == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + } + #endif - WOLFSSL_MSG("Loading peer's cert chain"); - /* first put cert chain into buffer so can verify top down - we're sent bottom up */ - while (listSz) { - word32 certSz; + /* allocate buffer for certs */ + args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH); - if (totalCerts >= MAX_CHAIN_DEPTH) - return MAX_CHAIN_ERROR; + /* Certificate List */ + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + c24to32(input + args->idx, &listSz); + args->idx += OPAQUE24_LEN; + if (listSz > MAX_RECORD_SIZE) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + if ((args->idx - args->begin) + listSz != totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; + WOLFSSL_MSG("Loading peer's cert chain"); + /* first put cert chain into buffer so can verify top down + we're sent bottom up */ + while (listSz) { + word32 certSz; - c24to32(input + *inOutIdx, &certSz); - *inOutIdx += OPAQUE24_LEN; + if (args->totalCerts >= MAX_CHAIN_DEPTH) { + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + #endif + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } - if ((*inOutIdx - begin) + certSz > size) - return BUFFER_ERROR; + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } - certs[totalCerts].length = certSz; - certs[totalCerts].buffer = input + *inOutIdx; + c24to32(input + args->idx, &certSz); + args->idx += OPAQUE24_LEN; -#ifdef SESSION_CERTS - if (ssl->session.chain.count < MAX_CHAIN_DEPTH && - certSz < MAX_X509_SIZE) { - ssl->session.chain.certs[ssl->session.chain.count].length = certSz; - XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer, - input + *inOutIdx, certSz); - ssl->session.chain.count++; - } else { - WOLFSSL_MSG("Couldn't store chain cert for session"); - } -#endif + if ((args->idx - args->begin) + certSz > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } - *inOutIdx += certSz; - listSz -= certSz + CERT_HEADER_SZ; + args->certs[args->totalCerts].length = certSz; + args->certs[args->totalCerts].buffer = input + args->idx; - totalCerts++; - WOLFSSL_MSG(" Put another cert into chain"); - } + #ifdef SESSION_CERTS + if (ssl->session.chain.count < MAX_CHAIN_DEPTH && + certSz < MAX_X509_SIZE) { + ssl->session.chain.certs[ + ssl->session.chain.count].length = certSz; + XMEMCPY(ssl->session.chain.certs[ + ssl->session.chain.count].buffer, + input + args->idx, certSz); + ssl->session.chain.count++; + } + else { + WOLFSSL_MSG("Couldn't store chain cert for session"); + } + #endif /* SESSION_CERTS */ - count = totalCerts; + args->idx += certSz; + listSz -= certSz + CERT_HEADER_SZ; -#ifdef WOLFSSL_SMALL_STACK - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (dCert == NULL) - return MEMORY_E; -#endif + #ifdef WOLFSSL_TLS13 + /* Extensions */ + if (ssl->options.tls1_3) { + word16 extSz; -#ifdef WOLFSSL_TRUST_PEER_CERT - /* if using trusted peer certs check before verify chain and CA test */ - if (count > 0) { - TrustedPeerCert* tp = NULL; - - InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); - #ifndef NO_SKID - if (dCert->extAuthKeyIdSet) { - tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId, - WC_MATCH_SKID); - } - else { /* if the cert has no SKID try to match by name */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, - WC_MATCH_NAME); + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) + return BUFFER_ERROR; + ato16(input + args->idx, &extSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + extSz > totalSz) + return BUFFER_ERROR; + /* Store extension data info for later processing. */ + args->exts[args->totalCerts].length = extSz; + args->exts[args->totalCerts].buffer = input + args->idx; + args->idx += extSz; + listSz -= extSz + OPAQUE16_LEN; + } + #endif + + args->totalCerts++; + WOLFSSL_MSG("\tPut another cert into chain"); + } /* while (listSz) */ + + args->count = args->totalCerts; + args->certIdx = 0; + + args->dCertInit = 0; + args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->dCert == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); } - #else /* NO_SKID */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, - WC_MATCH_NAME); - #endif /* NO SKID */ - WOLFSSL_MSG("Checking for trusted peer cert"); - - if (tp == NULL) { - /* no trusted peer cert */ - WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); - FreeDecodedCert(dCert); - } else if (MatchTrustedPeer(tp, dCert)){ - WOLFSSL_MSG("Found matching trusted peer cert"); - haveTrustPeer = 1; - } else { - WOLFSSL_MSG("Trusted peer cert did not match!"); - FreeDecodedCert(dCert); - } - } - if (!haveTrustPeer) { /* do not verify chain if trusted peer cert found */ -#endif /* WOLFSSL_TRUST_PEER_CERT */ - /* verify up to peer's first */ - while (count > 1) { - buffer myCert = certs[count - 1]; - byte* subjectHash; + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); - #ifndef NO_SKID - subjectHash = dCert->extSubjKeyId; - #else - subjectHash = dCert->subjectHash; - #endif + case TLS_ASYNC_BUILD: + { + if (args->count > 0) { + #ifdef WOLFSSL_TRUST_PEER_CERT + if (args->certIdx == 0) { + /* if using trusted peer certs check before verify chain + and CA test */ + TrustedPeerCert* tp; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + args->dCertInit = 1; + } - /* Check key sizes for certs. Is redundent check since ProcessBuffer - also performs this check. */ - if (!ssl->options.verifyNone) { - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - if (ssl->options.minRsaKeySz < 0 || - dCert->pubKeySize < (word16)ssl->options.minRsaKeySz) { - WOLFSSL_MSG("RSA key size in cert chain error"); - ret = RSA_KEY_SIZE_E; + ret = ParseCertRelative(args->dCert, CERT_TYPE, 0, + ssl->ctx->cm); + if (ret != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + goto exit_ppc; } - break; - #endif /* !NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - if (ssl->options.minEccKeySz < 0 || - dCert->pubKeySize < (word16)ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size in cert chain error"); - ret = ECC_KEY_SIZE_E; + + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) { + tp = GetTrustedPeer(ssl->ctx->cm, + args->dCert->extSubjKeyId, WC_MATCH_SKID); + } + else { /* if the cert has no SKID try to match by name */ + tp = GetTrustedPeer(ssl->ctx->cm, + args->dCert->subjectHash, WC_MATCH_NAME); + } + #else /* NO_SKID */ + tp = GetTrustedPeer(ssl->ctx->cm, args->dCert->subjectHash, + WC_MATCH_NAME); + #endif /* NO SKID */ + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. " + "Checking CAs"); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } else if (MatchTrustedPeer(tp, args->dCert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + haveTrustPeer = 1; + } else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* verify up to peer's first */ + /* do not verify chain if trusted peer cert found */ + while (args->count > 1 + #ifdef WOLFSSL_TRUST_PEER_CERT + && !haveTrustPeer + #endif /* WOLFSSL_TRUST_PEER_CERT */ + ) { + byte* subjectHash; + + args->certIdx = args->count - 1; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + args->dCertInit = 1; } - break; - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Key size not checked"); - break; /* key not being checked for size if not in switch */ - } - } + ret = ParseCertRelative(args->dCert, CERT_TYPE, + !ssl->options.verifyNone, ssl->ctx->cm); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + goto exit_ppc; + } + #endif - if (ret == 0 && dCert->isCA == 0) { - WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); - } - else if (ret == 0 && ssl->options.verifyNone) { - WOLFSSL_MSG("Chain cert not verified by option, not adding as CA"); - } - else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { - DerBuffer* add = NULL; - ret = AllocDer(&add, myCert.length, CA_TYPE, ssl->heap); - if (ret < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } + #ifndef NO_SKID + subjectHash = args->dCert->extSubjKeyId; + #else + subjectHash = args->dCert->subjectHash; + #endif - WOLFSSL_MSG("Adding CA from chain"); + /* Check key sizes for certs. Is redundent check since + ProcessBuffer also performs this check. */ + if (!ssl->options.verifyNone) { + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + if (ssl->options.minRsaKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minRsaKeySz) { + WOLFSSL_MSG( + "RSA key size in cert chain error"); + ret = RSA_KEY_SIZE_E; + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + if (ssl->options.minEccKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Key size not checked"); + /* key not being checked for size if not in + switch */ + break; + } /* switch (dCert->keyOID) */ + } /* if (!ssl->options.verifyNone) */ - XMEMCPY(add->buffer, myCert.buffer, myCert.length); + if (ret == 0 && args->dCert->isCA == 0) { + WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); + } + else if (ret == 0 && ssl->options.verifyNone) { + WOLFSSL_MSG("Chain cert not verified by option, not adding as CA"); + } + else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { + DerBuffer* add = NULL; + ret = AllocDer(&add, args->certs[args->certIdx].length, + CA_TYPE, ssl->heap); + if (ret < 0) + goto exit_ppc; + + WOLFSSL_MSG("Adding CA from chain"); + + XMEMCPY(add->buffer, args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length); + + /* already verified above */ + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); + if (ret == 1) { + ret = 0; /* SSL_SUCCESS for external */ + } + } + else if (ret != 0) { + WOLFSSL_MSG("Failed to verify CA from chain"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_INVALID_CA; + #endif + } + else { + WOLFSSL_MSG("Verified CA from chain and already had it"); + } - /* already verified above */ - ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); - if (ret == 1) ret = 0; /* SSL_SUCCESS for external */ - } - else if (ret != 0) { - WOLFSSL_MSG("Failed to verify CA from chain"); - } - else { - WOLFSSL_MSG("Verified CA from chain and already had it"); - } + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (ret == 0) { + int doCrlLookup = 1; + #ifdef HAVE_OCSP + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + ret = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 0, ssl->heap); + } + else /* skips OCSP and force CRL check */ + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + if (ssl->ctx->cm->ocspEnabled && + ssl->ctx->cm->ocspCheckAll) { + WOLFSSL_MSG("Doing Non Leaf OCSP check"); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, args->dCert, + NULL); + doCrlLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + doCrlLookup = 0; + WOLFSSL_MSG("\tOCSP Lookup not ok"); + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (ret == 0 && doCrlLookup && + ssl->ctx->cm->crlEnabled && + ssl->ctx->cm->crlCheckAll) { + WOLFSSL_MSG("Doing Non Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + } + } + #endif /* HAVE_CRL */ + (void)doCrlLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (ret == 0) { - int doCrlLookup = 1; - -#ifdef HAVE_OCSP - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) - ret = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 0, - ssl->heap); - else /* skips OCSP and force CRL check */ - #endif - if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) { - WOLFSSL_MSG("Doing Non Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - doCrlLookup = 0; - WOLFSSL_MSG("\tOCSP Lookup not ok"); - } - } -#endif /* HAVE_OCSP */ + if (ret != 0 && args->lastErr == 0) { + args->lastErr = ret; /* save error from last time */ + ret = 0; /* reset error */ + } -#ifdef HAVE_CRL - if (ret == 0 && doCrlLookup && ssl->ctx->cm->crlEnabled - && ssl->ctx->cm->crlCheckAll) { - WOLFSSL_MSG("Doing Non Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + args->count--; + } /* while (count > 0 && !haveTrustPeer) */ + } /* if (count > 0) */ - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - } + /* Check for error */ + if (ret != 0) { + goto exit_ppc; } -#else - (void)doCrlLookup; -#endif /* HAVE_CRL */ - } -#endif /* HAVE_OCSP || HAVE_CRL */ - - if (ret != 0 && anyError == 0) - anyError = ret; /* save error from last time */ - FreeDecodedCert(dCert); - count--; - } + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; -#ifdef WOLFSSL_TRUST_PEER_CERT - } /* end of if (haveTrustPeer) -- a check for if already verified */ -#endif + case TLS_ASYNC_DO: + { + /* peer's, may not have one if blank client cert sent by TLSv1.2 */ + if (args->count > 0) { + WOLFSSL_MSG("Verifying Peer's cert"); - /* peer's, may not have one if blank client cert sent by TLSv1.2 */ - if (count) { - buffer myCert = certs[0]; - int fatal = 0; + args->certIdx = 0; - WOLFSSL_MSG("Verifying Peer's cert"); + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length, ssl->heap); + args->dCertInit = 1; + } -#ifdef WOLFSSL_TRUST_PEER_CERT - if (!haveTrustPeer) { /* do not parse again if previously verified */ -#endif - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); -#ifdef WOLFSSL_TRUST_PEER_CERT - } -#endif + #ifdef WOLFSSL_TRUST_PEER_CERT + if (!haveTrustPeer) + #endif + { /* only parse if not already present in dCert from above */ + ret = ParseCertRelative(args->dCert, CERT_TYPE, + !ssl->options.verifyNone, ssl->ctx->cm); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + goto exit_ppc; + } + #endif + } - if (ret == 0) { - WOLFSSL_MSG("Verified Peer's cert"); - fatal = 0; - } - else if (ret == ASN_PARSE_E) { - WOLFSSL_MSG("Got Peer cert ASN PARSE ERROR, fatal"); - fatal = 1; - } - else { - WOLFSSL_MSG("Failed to verify Peer's cert"); - if (ssl->verifyCallback) { - WOLFSSL_MSG("\tCallback override available, will continue"); - fatal = 0; - } - else { - WOLFSSL_MSG("\tNo callback override available, fatal"); - fatal = 1; - } - } + if (ret == 0) { + WOLFSSL_MSG("Verified Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_OK; + #endif + args->fatal = 0; + } + else if (ret == ASN_PARSE_E || ret == BUFFER_E) { + WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + args->fatal = 1; + } + else { + WOLFSSL_MSG("Failed to verify Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + #endif + if (ssl->verifyCallback) { + WOLFSSL_MSG( + "\tCallback override available, will continue"); + args->fatal = 0; + } + else { + WOLFSSL_MSG("\tNo callback override available, fatal"); + args->fatal = 1; + } + } -#ifdef HAVE_SECURE_RENEGOTIATION - if (fatal == 0 && ssl->secure_renegotiation - && ssl->secure_renegotiation->enabled) { + #ifdef HAVE_SECURE_RENEGOTIATION + if (args->fatal == 0 && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (IsEncryptionOn(ssl, 0)) { + /* compare against previous time */ + if (XMEMCMP(args->dCert->subjectHash, + ssl->secure_renegotiation->subject_hash, + SHA_DIGEST_SIZE) != 0) { + WOLFSSL_MSG( + "Peer sent different cert during scr, fatal"); + args->fatal = 1; + ret = SCR_DIFFERENT_CERT_E; + } + } - if (IsEncryptionOn(ssl, 0)) { - /* compare against previous time */ - if (XMEMCMP(dCert->subjectHash, - ssl->secure_renegotiation->subject_hash, - SHA_DIGEST_SIZE) != 0) { - WOLFSSL_MSG("Peer sent different cert during scr, fatal"); - fatal = 1; - ret = SCR_DIFFERENT_CERT_E; + /* cache peer's hash */ + if (args->fatal == 0) { + XMEMCPY(ssl->secure_renegotiation->subject_hash, + args->dCert->subjectHash, SHA_DIGEST_SIZE); + } } - } + #endif /* HAVE_SECURE_RENEGOTIATION */ - /* cache peer's hash */ - if (fatal == 0) { - XMEMCPY(ssl->secure_renegotiation->subject_hash, - dCert->subjectHash, SHA_DIGEST_SIZE); - } - } -#endif + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (args->fatal == 0) { + int doLookup = 1; -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (fatal == 0) { - int doLookup = 1; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + args->fatal = TLSX_CSR_InitRequest(ssl->extensions, + args->dCert, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + args->fatal = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 1, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + } - if (ssl->options.side == WOLFSSL_CLIENT_END) { -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (ssl->status_request) { - fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert, - ssl->heap); - doLookup = 0; + #ifdef HAVE_OCSP + if (doLookup && ssl->ctx->cm->ocspEnabled) { + WOLFSSL_MSG("Doing Leaf OCSP check"); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, + args->dCert, NULL); + doLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + WOLFSSL_MSG("\tOCSP Lookup not ok"); + args->fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (doLookup && ssl->ctx->cm->crlEnabled) { + WOLFSSL_MSG("Doing Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + args->fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_CRL */ + (void)doLookup; } -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { - fatal = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 1, - ssl->heap); - doLookup = 0; + #endif /* HAVE_OCSP || HAVE_CRL */ + + #ifdef KEEP_PEER_CERT + if (args->fatal == 0) { + /* set X509 format for peer cert */ + int copyRet = CopyDecodedToX509(&ssl->peerCert, + args->dCert); + if (copyRet == MEMORY_E) + args->fatal = 1; + } + #endif /* KEEP_PEER_CERT */ + + #ifndef IGNORE_KEY_EXTENSIONS + if (args->dCert->extKeyUsageSet) { + if ((ssl->specs.kea == rsa_kea) && + (ssl->options.side == WOLFSSL_CLIENT_END) && + (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { + ret = KEYUSE_ENCIPHER_E; + } + if ((ssl->specs.sig_algo == rsa_sa_algo || + (ssl->specs.sig_algo == ecc_dsa_sa_algo && + !ssl->specs.static_ecdh)) && + (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { + WOLFSSL_MSG("KeyUse Digital Sig not set"); + ret = KEYUSE_SIGNATURE_E; + } } -#endif - } -#ifdef HAVE_OCSP - if (doLookup && ssl->ctx->cm->ocspEnabled) { - WOLFSSL_MSG("Doing Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); - doLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - WOLFSSL_MSG("\tOCSP Lookup not ok"); - fatal = 0; + if (args->dCert->extExtKeyUsageSet) { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Server Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + else { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Client Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } } - } -#endif /* HAVE_OCSP */ + #endif /* IGNORE_KEY_EXTENSIONS */ -#ifdef HAVE_CRL - if (doLookup && ssl->ctx->cm->crlEnabled) { - WOLFSSL_MSG("Doing Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - fatal = 0; + if (args->fatal) { + ssl->error = ret; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + goto exit_ppc; } - } -#endif /* HAVE_CRL */ - (void)doLookup; - } -#endif /* HAVE_OCSP || HAVE_CRL */ -#ifdef KEEP_PEER_CERT - { - /* set X509 format for peer cert even if fatal */ - int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert); - if (copyRet == MEMORY_E) - fatal = 1; - } -#endif + ssl->options.havePeerCert = 1; + } /* if (count > 0) */ -#ifndef IGNORE_KEY_EXTENSIONS - if (dCert->extKeyUsageSet) { - if ((ssl->specs.kea == rsa_kea) && - (ssl->options.side == WOLFSSL_CLIENT_END) && - (dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { - ret = KEYUSE_ENCIPHER_E; - } - if ((ssl->specs.sig_algo == rsa_sa_algo || - (ssl->specs.sig_algo == ecc_dsa_sa_algo && - !ssl->specs.static_ecdh)) && - (dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { - WOLFSSL_MSG("KeyUse Digital Sig not set"); - ret = KEYUSE_SIGNATURE_E; + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; } - } - if (dCert->extExtKeyUsageSet) { - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Server Auth not set"); - ret = EXTKEYUSE_AUTH_E; - } - } - else { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Client Auth not set"); - ret = EXTKEYUSE_AUTH_E; - } - } - } -#endif /* IGNORE_KEY_EXTENSIONS */ + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - if (fatal) { - FreeDecodedCert(dCert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - ssl->error = ret; - return ret; - } - ssl->options.havePeerCert = 1; + case TLS_ASYNC_VERIFY: + { + if (args->count > 0) { + args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->domain == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } -#ifdef WOLFSSL_SMALL_STACK - domain = (char*)XMALLOC(ASN_NAME_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (domain == NULL) { - FreeDecodedCert(dCert); - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - /* store for callback use */ - if (dCert->subjectCNLen < ASN_NAME_MAX) { - XMEMCPY(domain, dCert->subjectCN, dCert->subjectCNLen); - domain[dCert->subjectCNLen] = '\0'; - } - else - domain[0] = '\0'; + /* store for callback use */ + if (args->dCert->subjectCNLen < ASN_NAME_MAX) { + XMEMCPY(args->domain, args->dCert->subjectCN, args->dCert->subjectCNLen); + args->domain[args->dCert->subjectCNLen] = '\0'; + } + else { + args->domain[0] = '\0'; + } - if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { - if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, (char*)ssl->buffers.domainName.buffer) == 0) { - WOLFSSL_MSG("DomainName match on common name failed"); - if (CheckAltNames(dCert, + WOLFSSL_MSG("DomainName match on common name failed"); + if (CheckAltNames(args->dCert, (char*)ssl->buffers.domainName.buffer) == 0 ) { - WOLFSSL_MSG("DomainName match on alt names failed too"); - ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */ + WOLFSSL_MSG( + "DomainName match on alt names failed too"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } } - } - } - /* decode peer key */ - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - { - word32 idx = 0; - int keyRet = 0; + /* decode peer key */ + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 keyIdx = 0; + int keyRet = 0; - if (ssl->peerRsaKey == NULL) { - ssl->peerRsaKey = (RsaKey*)XMALLOC(sizeof(RsaKey), - ssl->heap, DYNAMIC_TYPE_RSA); if (ssl->peerRsaKey == NULL) { - WOLFSSL_MSG("PeerRsaKey Memory error"); - keyRet = MEMORY_E; - } else { + keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + } else if (ssl->peerRsaKeyPresent) { + /* don't leak on reuse */ + wc_FreeRsaKey(ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, - ssl->heap, ssl->devId); + ssl->heap, ssl->devId); } - } else if (ssl->peerRsaKeyPresent) { - /* don't leak on reuse */ - wc_FreeRsaKey(ssl->peerRsaKey); - ssl->peerRsaKeyPresent = 0; - keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, ssl->heap, ssl->devId); - } - if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey, - &idx, ssl->peerRsaKey, dCert->pubKeySize) != 0) { - ret = PEER_KEY_ERROR; - } - else { - ssl->peerRsaKeyPresent = 1; - #ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - ssl->buffers.peerRsaKey.buffer = - (byte*)XMALLOC(dCert->pubKeySize, - ssl->heap, DYNAMIC_TYPE_RSA); - if (ssl->buffers.peerRsaKey.buffer == NULL) - ret = MEMORY_ERROR; - else { - XMEMCPY(ssl->buffers.peerRsaKey.buffer, - dCert->publicKey, dCert->pubKeySize); - ssl->buffers.peerRsaKey.length = - dCert->pubKeySize; - } - #endif /* NO_RSA */ - #endif /*HAVE_PK_CALLBACKS */ - } + if (keyRet != 0 || wc_RsaPublicKeyDecode( + args->dCert->publicKey, &keyIdx, ssl->peerRsaKey, + args->dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerRsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + ssl->buffers.peerRsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_RSA); + if (ssl->buffers.peerRsaKey.buffer == NULL) { + ret = MEMORY_ERROR; + } + else { + XMEMCPY(ssl->buffers.peerRsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerRsaKey.length = + args->dCert->pubKeySize; + } + #endif /* NO_RSA */ + #endif /* HAVE_PK_CALLBACKS */ + } - /* check size of peer RSA key */ - if (ret == 0 && ssl->peerRsaKeyPresent && - !ssl->options.verifyNone && - wc_RsaEncryptSize(ssl->peerRsaKey) + /* check size of peer RSA key */ + if (ret == 0 && ssl->peerRsaKeyPresent && + !ssl->options.verifyNone && + wc_RsaEncryptSize(ssl->peerRsaKey) < ssl->options.minRsaKeySz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Peer RSA key is too small"); - } - - } - break; - #endif /* NO_RSA */ - #ifdef HAVE_NTRU - case NTRUk: - { - if (dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { - ret = PEER_KEY_ERROR; + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Peer RSA key is too small"); + } + break; } - else { - XMEMCPY(ssl->peerNtruKey, dCert->publicKey, - dCert->pubKeySize); - ssl->peerNtruKeyLen = (word16)dCert->pubKeySize; - ssl->peerNtruKeyPresent = 1; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { + ret = PEER_KEY_ERROR; + } + else { + XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->peerNtruKeyLen = + (word16)args->dCert->pubKeySize; + ssl->peerNtruKeyPresent = 1; + } + break; } - } - break; - #endif /* HAVE_NTRU */ - #ifdef HAVE_ECC - case ECDSAk: - { - int curveId; - if (ssl->peerEccDsaKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + int curveId; + int keyRet = 0; if (ssl->peerEccDsaKey == NULL) { - WOLFSSL_MSG("PeerEccDsaKey Memory error"); - return MEMORY_E; + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + } else if (ssl->peerEccDsaKeyPresent) { + /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + keyRet = wc_ecc_init_ex(ssl->peerEccDsaKey, + ssl->heap, ssl->devId); } - 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_ex(ssl->peerEccDsaKey, ssl->heap, - ssl->devId); - } - curveId = wc_ecc_get_oid(dCert->keyOID, NULL, NULL); - if (wc_ecc_import_x963_ex(dCert->publicKey, - dCert->pubKeySize, ssl->peerEccDsaKey, curveId) != 0) { - ret = PEER_KEY_ERROR; - } - else { - ssl->peerEccDsaKeyPresent = 1; - #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC - ssl->buffers.peerEccDsaKey.buffer = - (byte*)XMALLOC(dCert->pubKeySize, - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->buffers.peerEccDsaKey.buffer == NULL) - ret = MEMORY_ERROR; - else { - XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, - dCert->publicKey, dCert->pubKeySize); - ssl->buffers.peerEccDsaKey.length = - dCert->pubKeySize; - } - #endif /* HAVE_ECC */ - #endif /*HAVE_PK_CALLBACKS */ - } + curveId = wc_ecc_get_oid(args->dCert->keyOID, NULL, NULL); + if (keyRet != 0 || + wc_ecc_import_x963_ex(args->dCert->publicKey, + args->dCert->pubKeySize, ssl->peerEccDsaKey, + curveId) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEccDsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + ssl->buffers.peerEccDsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEccDsaKey.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEccDsaKey.length = + args->dCert->pubKeySize; + } + #endif /* HAVE_ECC */ + #endif /*HAVE_PK_CALLBACKS */ + } - /* check size of peer ECC key */ - if (ret == 0 && ssl->peerEccDsaKeyPresent && + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEccDsaKeyPresent && !ssl->options.verifyNone && wc_ecc_size(ssl->peerEccDsaKey) < ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Peer ECC key is too small"); + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; } + #endif /* HAVE_ECC */ + default: + break; + } + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + + /* release since we don't need it anymore */ + if (args->dCert) { + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->dCert = NULL; } - break; - #endif /* HAVE_ECC */ - default: - break; - } + } /* if (count > 0) */ - FreeDecodedCert(dCert); - } + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + #ifdef WOLFSSL_SMALL_STACK + WOLFSSL_X509_STORE_CTX* store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( + sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (store == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + #else + WOLFSSL_X509_STORE_CTX store[1]; + #endif -#ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); - store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (store == NULL) { - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); + /* load last error */ + if (args->lastErr != 0 && ret == 0) { + ret = args->lastErr; + } - if (anyError != 0 && ret == 0) - ret = anyError; + if (ret != 0) { + if (!ssl->options.verifyNone) { + int why = bad_certificate; - if (ret != 0) { - if (!ssl->options.verifyNone) { - int why = bad_certificate; - - if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) - why = certificate_expired; - if (ssl->verifyCallback) { - int ok; - - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; - store->certs = certs; - store->totalCerts = totalCerts; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#else - store->current_cert = NULL; -#endif -#if defined(HAVE_FORTRESS) || defined(HAVE_STUNNEL) - store->ex_data = ssl; -#endif - ok = ssl->verifyCallback(0, store); - if (ok) { - WOLFSSL_MSG("Verify callback overriding error!"); - ret = 0; + if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) { + why = certificate_expired; + } + if (ssl->verifyCallback) { + int ok; + + store->error = ret; + store->error_depth = args->totalCerts; + store->discardSessionCerts = 0; + store->domain = args->domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #ifdef KEEP_PEER_CERT + if (ssl->peerCert.subject.sz > 0) + store->current_cert = &ssl->peerCert; + else + store->current_cert = NULL; + #else + store->current_cert = NULL; + #endif /* KEEP_PEER_CERT */ + #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS) + store->ex_data = ssl; + #endif + ok = ssl->verifyCallback(0, store); + if (ok) { + WOLFSSL_MSG("Verify callback overriding error!"); + ret = 0; + } + #ifdef SESSION_CERTS + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + } + #endif /* SESSION_CERTS */ + } + if (ret != 0) { + SendAlert(ssl, alert_fatal, why); /* try to send */ + ssl->options.isClosed = 1; + } } + ssl->error = ret; + } + #ifdef WOLFSSL_ALWAYS_VERIFY_CB + else { + if (ssl->verifyCallback) { + int ok; + + store->error = ret; + #ifdef WOLFSSL_WPAS + store->error_depth = 0; + #else + store->error_depth = args->totalCerts; + #endif + store->discardSessionCerts = 0; + store->domain = args->domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #ifdef KEEP_PEER_CERT + if (ssl->peerCert.subject.sz > 0) + store->current_cert = &ssl->peerCert; + else + store->current_cert = NULL; + #endif + store->ex_data = ssl; + + ok = ssl->verifyCallback(1, store); + if (!ok) { + WOLFSSL_MSG("Verify callback overriding valid certificate!"); + ret = -1; + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->options.isClosed = 1; + } #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + } + #endif /* SESSION_CERTS */ } - #endif } - if (ret != 0) { - SendAlert(ssl, alert_fatal, why); /* try to send */ - ssl->options.isClosed = 1; + #endif /* WOLFSSL_ALWAYS_VERIFY_CB */ + + if (ssl->options.verifyNone && + (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { + WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); + ret = ssl->error = 0; } - } - ssl->error = ret; - } -#ifdef WOLFSSL_ALWAYS_VERIFY_CB - else { - if (ssl->verifyCallback) { - int ok; - - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; - store->certs = certs; - store->totalCerts = totalCerts; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#endif - store->ex_data = ssl; - - ok = ssl->verifyCallback(1, store); - if (!ok) { - WOLFSSL_MSG("Verify callback overriding valid certificate!"); - ret = -1; - SendAlert(ssl, alert_fatal, bad_certificate); - ssl->options.isClosed = 1; + + if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_CERT_COMPLETE; } - #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; + + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; } - #endif + + #ifdef WOLFSSL_SMALL_STACK + XFREE(store, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* Set final index */ + *inOutIdx = args->idx; + + break; } - } -#endif + default: + ret = INPUT_CASE_ERROR; + break; + } /* switch(ssl->options.asyncState) */ - if (ssl->options.verifyNone && - (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { - WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); - ret = ssl->error = 0; - } +exit_ppc: - if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) - ssl->options.serverState = SERVER_CERT_COMPLETE; + WOLFSSL_LEAVE("ProcessPeerCerts", ret); - if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate = 0; + + return ret; } +#endif /* WOLFSSL_ASYNC_CRYPT */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + FreeProcPeerCertArgs(ssl, args); + FreeKeyExchange(ssl); return ret; } +static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + return ProcessPeerCerts(ssl, input, inOutIdx, size); +} static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) @@ -7088,7 +7913,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, do { #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->status_request) { - request = TLSX_CSR_GetRequest(ssl->extensions); + request = (OcspRequest*)TLSX_CSR_GetRequest( + ssl->extensions); ssl->status_request = 0; break; } @@ -7096,8 +7922,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 if (ssl->status_request_v2) { - request = TLSX_CSR2_GetRequest(ssl->extensions, - status_type, 0); + request = (OcspRequest*)TLSX_CSR2_GetRequest( + ssl->extensions, status_type, 0); ssl->status_request_v2 = 0; break; } @@ -7110,9 +7936,9 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (status == NULL || response == NULL) { @@ -7127,17 +7953,22 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) != 0) - || (response->responseStatus != OCSP_SUCCESSFUL) - || (response->status->status != CERT_GOOD) - || (CompareOcspReqResp(request, response) != 0)) + if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->responseStatus != OCSP_SUCCESSFUL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->status->status == CERT_REVOKED) + ret = OCSP_CERT_REVOKED; + else if (response->status->status != CERT_GOOD) ret = BAD_CERTIFICATE_STATUS_ERROR; *inOutIdx += status_length; #ifdef WOLFSSL_SMALL_STACK - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif } @@ -7150,7 +7981,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, case WOLFSSL_CSR2_OCSP_MULTI: { OcspRequest* request; word32 list_length = status_length; - byte index = 0; + byte idx = 0; #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -7170,16 +8001,16 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, } while(0); #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (status == NULL || response == NULL) { if (status) - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (response) - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_ERROR; } @@ -7204,21 +8035,21 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) - != 0) + if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, + 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) || (response->status->status != CERT_GOOD)) ret = BAD_CERTIFICATE_STATUS_ERROR; while (ret == 0) { - request = TLSX_CSR2_GetRequest(ssl->extensions, - status_type, index++); + request = (OcspRequest*)TLSX_CSR2_GetRequest( + ssl->extensions, status_type, idx++); if (request == NULL) ret = BAD_CERTIFICATE_STATUS_ERROR; else if (CompareOcspReqResp(request, response) == 0) break; - else if (index == 1) /* server cert must be OK */ + else if (idx == 1) /* server cert must be OK */ ret = BAD_CERTIFICATE_STATUS_ERROR; } @@ -7578,7 +8409,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_MSG("Finished received before ChangeCipher"); return NO_CHANGE_CIPHER_E; } - break; case change_cipher_hs: @@ -7654,6 +8484,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ENTER("DoHandShakeMsgType"); +#ifdef WOLFSSL_TLS13 + if (type == hello_retry_request) { + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } +#endif + /* make sure can read the message */ if (*inOutIdx + size > totalSz) return INCOMPLETE_DATA; @@ -7768,12 +8605,12 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case server_hello_done: WOLFSSL_MSG("processing server hello done"); - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerHelloDone", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("ServerHelloDone", &ssl->timeoutInfo); - #endif + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHelloDone", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("ServerHelloDone", &ssl->timeoutInfo); + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; @@ -7822,6 +8659,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DECODE_E; } +#ifdef WOLFSSL_ASYNC_CRYPT /* if async, offset index so this msg will be processed again */ if (ret == WC_PENDING_E) { *inOutIdx -= HANDSHAKE_HEADER_SZ; @@ -7831,6 +8669,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif } +#endif WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); return ret; @@ -7926,7 +8765,6 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return ret; } - #ifdef WOLFSSL_DTLS static INLINE int DtlsCheckWindow(WOLFSSL* ssl) @@ -7986,6 +8824,12 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) word32 idx = diff / DTLS_WORD_BITS; word32 newDiff = diff % DTLS_WORD_BITS; + /* verify idx is valid for window array */ + if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) { + WOLFSSL_MSG("Invalid DTLS windows index"); + return 0; + } + if (window[idx] & (1 << (newDiff - 1))) { WOLFSSL_MSG("Current record sequence number already received."); return 0; @@ -8261,6 +9105,20 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, } +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implmentation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automaticlly depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparision to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * out output buffer to hold encrypted data + * input data to encrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) { @@ -8280,14 +9138,14 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, XMEMSET(poly, 0, sizeof(poly)); XMEMSET(add, 0, sizeof(add)); - if (ssl->options.oldPoly != 0) { - /* get nonce */ - WriteSEQ(ssl, CUR_ORDER, nonce + CHACHA20_OLD_OFFSET); - } - /* opaque SEQ number stored for AD */ WriteSEQ(ssl, CUR_ORDER, add); + if (ssl->options.oldPoly != 0) { + /* get nonce. SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + /* Store the type, version. Unfortunately, they are in * the input buffer ahead of the plaintext. */ #ifdef WOLFSSL_DTLS @@ -8398,6 +9256,20 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, } +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implmentation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automaticlly depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparision to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * plain output buffer to hold decrypted data + * input data to decrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { @@ -8424,14 +9296,14 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, XMEMSET(nonce, 0, sizeof(nonce)); XMEMSET(add, 0, sizeof(add)); - if (ssl->options.oldPoly != 0) { - /* get nonce */ - WriteSEQ(ssl, PEER_ORDER, nonce + CHACHA20_OLD_OFFSET); - } - /* sequence number field is 64-bits */ WriteSEQ(ssl, PEER_ORDER, add); + if (ssl->options.oldPoly != 0) { + /* get nonce, SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + /* get AD info */ /* Store the type, version. */ add[AEAD_TYPE_OFFSET] = ssl->curRL.type; @@ -8526,336 +9398,506 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* HAVE_AEAD */ -static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) +static INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, + word16 sz, int asyncOkay) { int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#else + (void)asyncOkay; +#endif (void)out; (void)input; (void)sz; - if (ssl->encrypt.setup == 0) { - WOLFSSL_MSG("Encrypt ciphers not setup"); - return ENCRYPT_ERROR; - } + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); + break; + #endif -#ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); -#endif + #ifdef BUILD_DES3 + case wolfssl_triple_des: + ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + asyncDev = &ssl->encrypt.des3->asyncDev; + if (asyncOkay) + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); + } + #endif + break; + #endif - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + asyncDev = &ssl->encrypt.aes->asyncDev; + if (asyncOkay) + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); break; + } #endif + break; + #endif - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); - break; + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthEncryptFunc aes_auth_fn; + const byte* additionalSrc; + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmEncrypt : wc_AesCcmEncrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmEncrypt; + #else + aes_auth_fn = wc_AesCcmEncrypt; #endif + additionalSrc = input - 5; - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); - break; + XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits */ + WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional); + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } + #endif + XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET, + additionalSrc, 3); + + /* Store the length of the plain text minus the explicit + * IV length minus the authentication tag size. */ + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->encrypt.nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ret = aes_auth_fn(ssl->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.nonce, AESGCM_NONCE_SZ, + out + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->encrypt.additional, AEAD_AUTH_DATA_SZ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + asyncDev = &ssl->encrypt.aes->asyncDev; + if (asyncOkay) + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); + } #endif + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - const byte* additionalSrc = input - 5; + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); + break; + #endif - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); + break; + #endif - /* sequence number field is 64-bits */ - WriteSEQ(ssl, CUR_ORDER, additional); + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); + break; + #endif - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - additionalSrc -= DTLS_HANDSHAKE_EXTRA; - } - #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); - - /* Store the length of the plain text minus the explicit - * IV length minus the authentication tag size. */ - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - ret = wc_AesGcmEncrypt(ssl->encrypt.aes, - out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AESGCM_NONCE_SZ); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADEncrypt(ssl, out, input, sz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != out) { + XMEMMOVE(out, input, sz); + } + break; + #endif + + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + ret = ENCRYPT_ERROR; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async is not okay, then block */ + if (ret == WC_PENDING_E && !asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } +#endif + + return ret; +} + +static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, + int asyncOkay) +{ + int ret = 0; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay && ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } +#endif + + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->encrypt.setup == 0) { + WOLFSSL_MSG("Encrypt ciphers not setup"); + return ENCRYPT_ERROR; + } + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->encrypt.additional == NULL) + ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->encrypt.additional == NULL || + ssl->encrypt.nonce == NULL) { + return MEMORY_E; } - break; + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + ret = EncryptDo(ssl, out, input, sz, asyncOkay); + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, then leave and return will resume below */ + if (ret == WC_PENDING_E) { + return ret; + } #endif + } + FALL_THROUGH; - #ifdef HAVE_AESCCM - /* AEAD CCM uses same size as macros for AESGCM */ - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - const byte* additionalSrc = input - 5; + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + { + /* finalize authentication cipher */ + AeadIncrementExpIV(ssl); - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + if (ssl->encrypt.nonce) + ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); - /* sequence number field is 64-bits */ - WriteSEQ(ssl, CUR_ORDER, additional); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - additionalSrc -= DTLS_HANDSHAKE_EXTRA; - } - #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); - - /* Store the length of the plain text minus the explicit - * IV length minus the authentication tag size. */ - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - ret = wc_AesCcmEncrypt(ssl->encrypt.aes, - out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; + + return ret; +} + +static INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + int ret = 0; + + (void)plain; + (void)input; + (void)sz; + + switch (ssl->specs.bulk_cipher_algorithm) + { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); + break; + #endif + + #ifdef BUILD_DES3 + case wolfssl_triple_des: + ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + break; + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthDecryptFunc aes_auth_fn; + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmDecrypt : wc_AesCcmDecrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmDecrypt; + #else + aes_auth_fn = wc_AesCcmDecrypt; + #endif + + XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits */ + WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional); + + ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, + AESGCM_EXP_IV_SZ); + if ((ret = aes_auth_fn(ssl->decrypt.aes, + plain + AESGCM_EXP_IV_SZ, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.nonce, AESGCM_NONCE_SZ, + input + sz - ssl->specs.aead_mac_size, ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AESGCM_NONCE_SZ); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + &ssl->decrypt.aes->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + break; } - break; - #endif + #endif + } + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); - break; - #endif + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); + break; + #endif - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); - break; - #endif + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); + break; + #endif - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); - break; - #endif + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); + break; + #endif - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: - ret = ChachaAEADEncrypt(ssl, out, input, sz); - break; - #endif + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADDecrypt(ssl, plain, input, sz); + break; + #endif - #ifdef HAVE_NULL_CIPHER - case wolfssl_cipher_null: - if (input != out) { - XMEMMOVE(out, input, sz); - } - break; - #endif + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != plain) { + XMEMMOVE(plain, input, sz); + } + break; + #endif - #ifdef HAVE_IDEA - case wolfssl_idea: - ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); - break; - #endif + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); + break; + #endif - default: - WOLFSSL_MSG("wolfSSL Encrypt programming error"); - ret = ENCRYPT_ERROR; + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + ret = DECRYPT_ERROR; } return ret; } - - static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { int ret = 0; - (void)plain; - (void)input; - (void)sz; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; - if (ssl->decrypt.setup == 0) { - WOLFSSL_MSG("Decrypt ciphers not setup"); - return DECRYPT_ERROR; + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; } - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); - break; - #endif + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->decrypt.setup == 0) { + WOLFSSL_MSG("Decrypt ciphers not setup"); + return DECRYPT_ERROR; + } + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->decrypt.additional == NULL) + ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->decrypt.additional == NULL || + ssl->decrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); - break; - #endif + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + case CIPHER_STATE_DO: + { + ret = DecryptDo(ssl, plain, input, sz); - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); - break; - #endif + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, PEER_ORDER, additional); - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); - if (wc_AesGcmDecrypt(ssl->decrypt.aes, - plain + AESGCM_EXP_IV_SZ, - input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - if (!ssl->options.dtls) - SendAlert(ssl, alert_fatal, bad_record_mac); - ret = VERIFY_MAC_ERROR; - } - ForceZero(nonce, AESGCM_NONCE_SZ); + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave and return below */ + if (ret == WC_PENDING_E) { + return ret; } - break; #endif + } + FALL_THROUGH; + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM nonce is cleared */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + if (ssl->decrypt.nonce) + ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ); - #ifdef HAVE_AESCCM - /* AESGCM AEAD macros use same size as AESCCM */ - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, PEER_ORDER, additional); - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); - if (wc_AesCcmDecrypt(ssl->decrypt.aes, - plain + AESGCM_EXP_IV_SZ, - input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - if (!ssl->options.dtls) - SendAlert(ssl, alert_fatal, bad_record_mac); + if (ret < 0) ret = VERIFY_MAC_ERROR; - } - ForceZero(nonce, AESGCM_NONCE_SZ); } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ break; - #endif - - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); - break; - #endif - - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); - break; - #endif - - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); - break; - #endif - - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: - ret = ChachaAEADDecrypt(ssl, plain, input, sz); - break; - #endif - - #ifdef HAVE_NULL_CIPHER - case wolfssl_cipher_null: - if (input != plain) { - XMEMMOVE(plain, input, sz); - } - break; - #endif + } + } - #ifdef HAVE_IDEA - case wolfssl_idea: - ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); - break; - #endif + /* Reset state */ + ssl->decrypt.state = CIPHER_STATE_BEGIN; - default: - WOLFSSL_MSG("wolfSSL Decrypt programming error"); - ret = DECRYPT_ERROR; + /* handle mac error case */ + if (ret == VERIFY_MAC_ERROR) { + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); } return ret; } +/* Check conditions for a cipher to have an explicit IV. + * + * ssl The SSL/TLS object. + * returns 1 if the cipher in use has an explicit IV and 0 otherwise. + */ +static INLINE int CipherHasExpIV(WOLFSSL *ssl) +{ +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return 0; +#endif + return (ssl->specs.cipher_type == aead) && + (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha); +} /* check cipher text size for sanity */ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) @@ -8883,8 +9925,8 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) } else if (ssl->specs.cipher_type == aead) { minLength = ssl->specs.aead_mac_size; /* authTag size */ - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ + if (CipherHasExpIV(ssl)) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ } if (encryptSz < minLength) { @@ -8903,11 +9945,11 @@ static INLINE void Md5Rounds(int rounds, const byte* data, int sz) Md5 md5; int i; - wc_InitMd5(&md5); + wc_InitMd5(&md5); /* no error check on purpose, dummy round */ for (i = 0; i < rounds; i++) wc_Md5Update(&md5, data, sz); - wc_Md5Free(&md5) ; /* in case needed to release resources */ + wc_Md5Free(&md5); /* in case needed to release resources */ } @@ -8922,7 +9964,7 @@ static INLINE void ShaRounds(int rounds, const byte* data, int sz) for (i = 0; i < rounds; i++) wc_ShaUpdate(&sha, data, sz); - wc_ShaFree(&sha) ; /* in case needed to release resources */ + wc_ShaFree(&sha); /* in case needed to release resources */ } #endif @@ -8940,7 +9982,7 @@ static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) wc_Sha256Update(&sha256, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha256Free(&sha256) ; /* in case needed to release resources */ + wc_Sha256Free(&sha256); /* in case needed to release resources */ } #endif @@ -8959,7 +10001,7 @@ static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) wc_Sha384Update(&sha384, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha384Free(&sha384) ; /* in case needed to release resources */ + wc_Sha384Free(&sha384); /* in case needed to release resources */ } #endif @@ -8978,7 +10020,7 @@ static INLINE void Sha512Rounds(int rounds, const byte* data, int sz) wc_Sha512Update(&sha512, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha512Free(&sha512) ; /* in case needed to release resources */ + wc_Sha512Free(&sha512); /* in case needed to release resources */ } #endif @@ -9144,9 +10186,11 @@ static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, return VERIFY_MAC_ERROR; } + /* treat any faulure as verify MAC error */ if (ret != 0) - return VERIFY_MAC_ERROR; - return 0; + ret = VERIFY_MAC_ERROR; + + return ret; } @@ -9172,7 +10216,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) ivExtra = ssl->specs.block_size; } else if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + if (CipherHasExpIV(ssl)) ivExtra = AESGCM_EXP_IV_SZ; } @@ -9222,9 +10266,10 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, if (ssl->hsInfoOn) AddPacketName("Alert", &ssl->handShakeInfo); if (ssl->toInfoOn) - /* add record header back on to info + 2 byte level, data */ + /* add record header back on to info + alert bytes level/code */ AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx - - RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap); + RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE, + ssl->heap); #endif /* make sure can read the message */ @@ -9242,9 +10287,17 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, WOLFSSL_MSG("Got alert"); if (*type == close_notify) { - WOLFSSL_MSG(" close notify"); + WOLFSSL_MSG("\tclose notify"); ssl->options.closeNotify = 1; } +#ifdef WOLFSSL_TLS13 + if (*type == decode_error) { + WOLFSSL_MSG(" decode error"); + } + if (*type == illegal_parameter) { + WOLFSSL_MSG(" illegal parameter"); + } +#endif WOLFSSL_ERROR(*type); if (IsEncryptionOn(ssl, 0)) { if (*inOutIdx + ssl->keys.padSz > totalSz) @@ -9317,6 +10370,14 @@ static int GetInputData(WOLFSSL *ssl, word32 size) } while (ssl->buffers.inputBuffer.length < size); +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.inputBuffer.idx == 0) { + WOLFSSL_MSG("Data received"); + WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.length); + } +#endif + return 0; } @@ -9398,7 +10459,7 @@ int ProcessReply(WOLFSSL* ssl) int ret = 0, type, readSz; int atomicUser = 0; word32 startIdx = 0; -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) int used; #endif @@ -9422,10 +10483,10 @@ int ProcessReply(WOLFSSL* ssl) readSz = RECORD_HEADER_SZ; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - readSz = DTLS_RECORD_HEADER_SZ; - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + readSz = DTLS_RECORD_HEADER_SZ; + #endif /* get header or return error */ if (!ssl->options.dtls) { @@ -9436,9 +10497,10 @@ int ProcessReply(WOLFSSL* ssl) /* read ahead may already have header */ used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; - if (used < readSz) + if (used < readSz) { if ((ret = GetInputData(ssl, readSz)) < 0) return ret; + } #endif } @@ -9455,15 +10517,15 @@ int ProcessReply(WOLFSSL* ssl) /* sanity checks before getting size at front */ if (ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 2] != OLD_HELLO_ID) { + ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) { WOLFSSL_MSG("Not a valid old client hello"); return PARSE_ERROR; } if (ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 3] != SSLv3_MAJOR && + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR && ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 3] != DTLS_MAJOR) { + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) { WOLFSSL_MSG("Not a valid version in old client hello"); return PARSE_ERROR; } @@ -9479,6 +10541,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = getRecordLayerHeader; continue; } + FALL_THROUGH; /* in the WOLFSSL_SERVER case, run the old client hello */ case runProcessOldClientHello: @@ -9513,6 +10576,7 @@ int ProcessReply(WOLFSSL* ssl) } #endif /* OLD_HELLO_ALLOWED */ + FALL_THROUGH; /* get the record layer header */ case getRecordLayerHeader: @@ -9540,6 +10604,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; ssl->options.processReply = getData; + FALL_THROUGH; /* retrieve record layer data */ case getData: @@ -9559,14 +10624,16 @@ int ProcessReply(WOLFSSL* ssl) #endif } - ssl->options.processReply = runProcessingOneMessage; + ssl->options.processReply = decryptMessage; startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */ + FALL_THROUGH; - /* the record layer is here */ - case runProcessingOneMessage: + /* decrypt message */ + case decryptMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) { + bufferStatic* in = &ssl->buffers.inputBuffer; - if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) - { ret = SanityCheckCipherText(ssl, ssl->curSize); if (ret < 0) return ret; @@ -9574,84 +10641,135 @@ int ProcessReply(WOLFSSL* ssl) if (atomicUser) { #ifdef ATOMIC_USER ret = ssl->ctx->DecryptVerifyCb(ssl, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, + in->buffer + in->idx, + in->buffer + in->idx, ssl->curSize, ssl->curRL.type, 1, &ssl->keys.padSz, ssl->DecryptVerifyCtx); - if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) - ssl->buffers.inputBuffer.idx += ssl->specs.block_size; - /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; #endif /* ATOMIC_USER */ } else { - ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->curSize); - if (ret < 0) { - WOLFSSL_MSG("Decrypt failed"); - WOLFSSL_ERROR(ret); - #ifdef WOLFSSL_DTLS - /* If in DTLS mode, if the decrypt fails for any - * reason, pretend the datagram never happened. */ - if (ssl->options.dtls) { - ssl->options.processReply = doProcessInit; - ssl->buffers.inputBuffer.idx = - ssl->buffers.inputBuffer.length; - } - #endif /* WOLFSSL_DTLS */ - return DECRYPT_ERROR; + if (!ssl->options.tls1_3) { + ret = Decrypt(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); } + else { + #ifdef WOLFSSL_TLS13 + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); + #else + ret = DECRYPT_ERROR; + #endif /* WOLFSSL_TLS13 */ + } + } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + + if (ret >= 0) { + /* handle success */ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) ssl->buffers.inputBuffer.idx += ssl->specs.block_size; /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + if (CipherHasExpIV(ssl)) ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + } + else { + WOLFSSL_MSG("Decrypt failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + } + #endif /* WOLFSSL_DTLS */ + + return DECRYPT_ERROR; + } + } + + ssl->options.processReply = verifyMessage; + FALL_THROUGH; + /* verify digest of message */ + case verifyMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) { + if (!atomicUser) { ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, ssl->curSize, ssl->curRL.type, &ssl->keys.padSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret < 0) { + WOLFSSL_MSG("VerifyMac failed"); + WOLFSSL_ERROR(ret); + return DECRYPT_ERROR; + } } - if (ret < 0) { - WOLFSSL_MSG("VerifyMac failed"); - WOLFSSL_ERROR(ret); - return DECRYPT_ERROR; - } + ssl->keys.encryptSz = ssl->curSize; ssl->keys.decryptedCur = 1; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + /* Get the real content type from the end of the data. */ + ssl->keys.padSz++; + ssl->curRL.type = ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.length - ssl->keys.padSz]; + } +#endif } - #ifdef WOLFSSL_DTLS + ssl->options.processReply = runProcessingOneMessage; + FALL_THROUGH; + + /* the record layer is here */ + case runProcessingOneMessage: + + #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { DtlsUpdateWindow(ssl); } - #endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_DTLS */ WOLFSSL_MSG("received record layer msg"); switch (ssl->curRL.type) { case handshake : /* debugging in DoHandShakeMsg */ - if (!ssl->options.dtls) { + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ret = DoDtlsHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#endif + } + else if (!IsAtLeastTLSv1_3(ssl->version)) { ret = DoHandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); } else { -#ifdef WOLFSSL_DTLS - ret = DoDtlsHandShakeMsg(ssl, +#ifdef WOLFSSL_TLS13 + ret = DoTls13HandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); +#else + ret = BUFFER_ERROR; #endif } if (ret != 0) @@ -9679,7 +10797,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; } else { -#ifdef WOLFSSL_DTLS + #ifdef WOLFSSL_DTLS /* Check for duplicate CCS message in DTLS mode. * DTLS allows for duplicate messages, and it should be * skipped. Also skip if out of order. */ @@ -9699,7 +10817,7 @@ int ProcessReply(WOLFSSL* ssl) } ssl->buffers.inputBuffer.idx++; break; -#endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_DTLS */ } } @@ -9754,6 +10872,12 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.dtlsHsRetain = 0; } #endif + #ifdef WOLFSSL_TLS13 + if (ssl->keys.keyUpdateRespond) { + WOLFSSL_MSG("No KeyUpdate from peer seen"); + return SANITY_MSG_E; + } + #endif if ((ret = DoApplicationData(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx)) @@ -9795,18 +10919,18 @@ int ProcessReply(WOLFSSL* ssl) /* more messages per record */ else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) { WOLFSSL_MSG("More messages in record"); - #ifdef WOLFSSL_DTLS - /* read-ahead but dtls doesn't bundle messages per record */ - if (ssl->options.dtls) { - ssl->options.processReply = doProcessInit; - continue; - } - #endif + ssl->options.processReply = runProcessingOneMessage; if (IsEncryptionOn(ssl, 0)) { WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); - ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) { + ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + return FATAL_ERROR; + } } continue; @@ -9863,9 +10987,10 @@ int SendChangeCipher(WOLFSSL* ssl) input[0] = 1; /* turn it on */ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - change_cipher_spec, 0, 0); - if (sendSz < 0) + change_cipher_spec, 0, 0, 0); + if (sendSz < 0) { return sendSz; + } } #ifdef WOLFSSL_DTLS @@ -9924,127 +11049,200 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, WriteSEQ(ssl, verify, seq); if (ssl->specs.mac_algorithm == md5_mac) { - wc_InitMd5(&md5); + ret = wc_InitMd5_ex(&md5, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + /* inner */ - wc_Md5Update(&md5, macSecret, digestSz); - wc_Md5Update(&md5, PAD1, padSz); - wc_Md5Update(&md5, seq, SEQ_SZ); - wc_Md5Update(&md5, conLen, sizeof(conLen)); + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD1, padSz); + ret |= wc_Md5Update(&md5, seq, SEQ_SZ); + ret |= wc_Md5Update(&md5, conLen, sizeof(conLen)); /* in buffer */ - wc_Md5Update(&md5, in, sz); - wc_Md5Final(&md5, result); + ret |= wc_Md5Update(&md5, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + /* outer */ - wc_Md5Update(&md5, macSecret, digestSz); - wc_Md5Update(&md5, PAD2, padSz); - wc_Md5Update(&md5, result, digestSz); - wc_Md5Final(&md5, digest); + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD2, padSz); + ret |= wc_Md5Update(&md5, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_Md5Free(&md5); } else { - ret = wc_InitSha(&sha); + ret = wc_InitSha_ex(&sha, ssl->heap, ssl->devId); if (ret != 0) return ret; + /* inner */ - wc_ShaUpdate(&sha, macSecret, digestSz); - wc_ShaUpdate(&sha, PAD1, padSz); - wc_ShaUpdate(&sha, seq, SEQ_SZ); - wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD1, padSz); + ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ); + ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen)); /* in buffer */ - wc_ShaUpdate(&sha, in, sz); - wc_ShaFinal(&sha, result); + ret |= wc_ShaUpdate(&sha, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + /* outer */ - wc_ShaUpdate(&sha, macSecret, digestSz); - wc_ShaUpdate(&sha, PAD2, padSz); - wc_ShaUpdate(&sha, result, digestSz); - wc_ShaFinal(&sha, digest); + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD2, padSz); + ret |= wc_ShaUpdate(&sha, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_ShaFree(&sha); } return 0; } +#endif /* NO_OLD_TLS */ + #ifndef NO_CERTS -static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) + +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) +static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) { + int ret; byte md5_result[MD5_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #else - Md5 md5[1]; - Md5 md5_2[1]; + Md5 md5[1]; #endif /* make md5 inner */ - md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ - wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); - wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); - wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */ + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); /* make md5 outer */ - wc_InitMd5(md5_2) ; - wc_Md5Update(md5_2, ssl->arrays->masterSecret, SECRET_LEN); - wc_Md5Update(md5_2, PAD2, PAD_MD5); - wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); - - wc_Md5Final(md5_2, digest); + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, digest); + wc_Md5Free(md5); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif -} + return ret; +} +#endif /* !NO_MD5 && !NO_OLD_TLS */ -static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) +static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) { + int ret; byte sha_result[SHA_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Sha* sha = (Sha*)XMALLOC(sizeof(Sha), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #else - Sha sha[1]; - Sha sha2[1]; + Sha sha[1]; #endif /* make sha inner */ - sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ - wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); - wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); - wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); /* make sha outer */ - wc_InitSha(sha2) ; - wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(sha2, PAD2, PAD_SHA); - wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); - - wc_ShaFinal(sha2, digest); + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, digest); + wc_ShaFree(sha); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; } -#endif /* NO_CERTS */ -#endif /* NO_OLD_TLS */ - - -#ifndef NO_CERTS +#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */ -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) { int ret = 0; (void)hashes; if (ssl->options.tls) { -#if ! defined( NO_OLD_TLS ) - wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); - wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); -#endif + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) + ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); + if (ret != 0) + return ret; + #endif if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, @@ -10066,145 +11264,228 @@ static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) #endif } } -#if ! defined( NO_OLD_TLS ) else { - BuildMD5_CertVerify(ssl, hashes->md5); - BuildSHA_CertVerify(ssl, hashes->sha); + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = BuildMD5_CertVerify(ssl, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + ret = BuildSHA_CertVerify(ssl, hashes->sha); + if (ret != 0) + return ret; + #endif } -#endif return ret; } #endif /* WOLFSSL_LEANPSK */ +/* Persistable BuildMessage arguments */ +typedef struct BuildMsgArgs { + word32 digestSz; + word32 sz; + word32 pad; + word32 idx; + word32 headerSz; + word16 size; + word32 ivSz; /* TLSv1.1 IV */ + byte iv[AES_BLOCK_SIZE]; /* max size */ +} BuildMsgArgs; + +static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs) +{ + BuildMsgArgs* args = (BuildMsgArgs*)pArgs; + + (void)ssl; + (void)args; + + /* no allocations in BuildMessage */ +} + /* Build SSL Message, encrypted */ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, - int inSz, int type, int hashOutput, int sizeOnly) + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { - word32 digestSz; - word32 sz = RECORD_HEADER_SZ + inSz; - word32 pad = 0, i; - word32 idx = RECORD_HEADER_SZ; - word32 ivSz = 0; /* TLSv1.1 IV */ - word32 headerSz = RECORD_HEADER_SZ; - word16 size; - byte iv[AES_BLOCK_SIZE]; /* max size */ - int ret = 0; - int atomicUser = 0; + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + BuildMsgArgs* args = (BuildMsgArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + BuildMsgArgs args[1]; +#endif + + WOLFSSL_ENTER("BuildMessage"); if (ssl == NULL) { return BAD_FUNC_ARG; } - if (!sizeOnly && (output == NULL || input == NULL) ) { - return BAD_FUNC_ARG; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly); } +#endif - /* catch mistaken sizeOnly parameter */ - if (sizeOnly && (output || input) ) { - WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); - return BAD_FUNC_ARG; + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; + } } - - digestSz = ssl->specs.hash_size; -#ifdef HAVE_TRUNCATED_HMAC - if (ssl->truncated_hmac) - digestSz = min(TRUNCATED_HMAC_SZ, digestSz); #endif - sz += digestSz; -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sz += DTLS_RECORD_EXTRA; - idx += DTLS_RECORD_EXTRA; - headerSz += DTLS_RECORD_EXTRA; + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsgArgs)); + + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsgArgs; + #endif } -#endif -#ifdef ATOMIC_USER - if (ssl->ctx->MacEncryptCb) - atomicUser = 1; -#endif + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + /* catch mistaken sizeOnly parameter */ + if (!sizeOnly && (output == NULL || input == NULL) ) { + return BAD_FUNC_ARG; + } + if (sizeOnly && (output || input) ) { + WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output"); + return BAD_FUNC_ARG; + } - if (ssl->specs.cipher_type == block) { - word32 blockSz = ssl->specs.block_size; - if (ssl->options.tls1_1) { - ivSz = blockSz; - sz += ivSz; + ssl->options.buildMsgState = BUILD_MSG_SIZE; + } + FALL_THROUGH; + case BUILD_MSG_SIZE: + { + args->digestSz = ssl->specs.hash_size; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac) + args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz); + #endif + args->sz += args->digestSz; - if (ivSz > (word32)sizeof(iv)) - return BUFFER_E; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sz += DTLS_RECORD_EXTRA; + args->idx += DTLS_RECORD_EXTRA; + args->headerSz += DTLS_RECORD_EXTRA; + } + #endif + + if (ssl->specs.cipher_type == block) { + word32 blockSz = ssl->specs.block_size; + if (ssl->options.tls1_1) { + args->ivSz = blockSz; + args->sz += args->ivSz; + + if (args->ivSz > (word32)sizeof(args->iv)) + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + args->sz += 1; /* pad byte */ + args->pad = (args->sz - args->headerSz) % blockSz; + args->pad = blockSz - args->pad; + args->sz += args->pad; + } + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + args->ivSz = AESGCM_EXP_IV_SZ; - if (!sizeOnly) { - ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz); + args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz); + } + #endif + + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + + if (args->ivSz > 0) { + ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz); if (ret != 0) - return ret; + goto exit_buildmsg; + } - } - sz += 1; /* pad byte */ - pad = (sz - headerSz) % blockSz; - pad = blockSz - pad; - sz += pad; - } + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + } + #endif -#ifdef HAVE_AEAD - if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ivSz = AESGCM_EXP_IV_SZ; + args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ + AddRecordHeader(output, args->size, (byte)type, ssl); - sz += (ivSz + ssl->specs.aead_mac_size - digestSz); - if (!sizeOnly) { - XMEMCPY(iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - } - } -#endif - /* done with size calculations */ - if (sizeOnly) { - return sz; - } - if (sz > (word32)outSz) { - WOLFSSL_MSG("Oops, want to write past output buffer size"); - return BUFFER_E; - } - size = (word16)(sz - headerSz); /* include mac and digest */ - AddRecordHeader(output, size, (byte)type, ssl); + /* write to output */ + if (args->ivSz) { + XMEMCPY(output + args->idx, args->iv, + min(args->ivSz, sizeof(args->iv))); + args->idx += args->ivSz; + } + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; - /* write to output */ - if (ivSz) { - XMEMCPY(output + idx, iv, min(ivSz, sizeof(iv))); - idx += ivSz; - } - XMEMCPY(output + idx, input, inSz); - idx += inSz; + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + case BUILD_MSG_HASH: + { + word32 i; - if (type == handshake && hashOutput) { - ret = HashOutput(ssl, output, headerSz + inSz, ivSz); - if (ret != 0) - return ret; - } + if (type == handshake && hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + } + if (ssl->specs.cipher_type == block) { + word32 tmpIdx = args->idx + args->digestSz; - if (ssl->specs.cipher_type == block) { - word32 tmpIdx = idx + digestSz; + for (i = 0; i <= args->pad; i++) + output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */ + } - for (i = 0; i <= pad; i++) - output[tmpIdx++] = (byte)pad; /* pad byte gets pad value too */ - } + ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_VERIFY_MAC: + { + /* User Record Layer Callback handling */ + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx, + output + args->headerSz + args->ivSz, inSz, type, 0, + output + args->headerSz, output + args->headerSz, args->size, + ssl->MacEncryptCtx); + goto exit_buildmsg; + } + #endif - if (atomicUser) { /* User Record Layer Callback handling */ -#ifdef ATOMIC_USER - if ( (ret = ssl->ctx->MacEncryptCb(ssl, output + idx, - output + headerSz + ivSz, inSz, type, 0, - output + headerSz, output + headerSz, size, - ssl->MacEncryptCtx)) != 0) - return ret; -#endif - } - else { - if (ssl->specs.cipher_type != aead) { -#ifdef HAVE_TRUNCATED_HMAC - if (ssl->truncated_hmac && ssl->specs.hash_size > digestSz) { + if (ssl->specs.cipher_type != aead) { + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && ssl->specs.hash_size > args->digestSz) { #ifdef WOLFSSL_SMALL_STACK byte* hmac = NULL; #else @@ -10212,36 +11493,64 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif #ifdef WOLFSSL_SMALL_STACK - hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, + hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (hmac == NULL) - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_buildmsg); #endif - ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz, + ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz, inSz, type, 0); - XMEMCPY(output + idx, hmac, digestSz); + XMEMCPY(output + args->idx, hmac, args->digestSz); #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - } else -#endif - ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, - type, 0); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + } + else + #endif + ret = ssl->hmac(ssl, output + args->idx, output + args->headerSz + args->ivSz, + inSz, type, 0); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + if (ret != 0) + goto exit_buildmsg; + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; } - if (ret != 0) - return ret; + FALL_THROUGH; + case BUILD_MSG_ENCRYPT: + { + ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size, + asyncOkay); + break; + } + } - if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0) - return ret; +exit_buildmsg: + + WOLFSSL_LEAVE("BuildMessage", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; } +#endif - return sz; + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsgArgs(ssl, args); + + return ret; } @@ -10310,7 +11619,7 @@ int SendFinished(WOLFSSL* ssl) #endif sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, - handshake, 1, 0); + handshake, 1, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -10540,7 +11849,7 @@ int SendCertificate(WOLFSSL* ssl) } sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); if (inputSz > 0) XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -10549,26 +11858,26 @@ int SendCertificate(WOLFSSL* ssl) return sendSz; } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); #endif + } - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, - ssl->heap); - #endif + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif ssl->buffers.outputBuffer.length += sendSz; if (!ssl->options.groupMessages) @@ -10696,7 +12005,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, switch (type) { case WOLFSSL_CSR2_OCSP_MULTI: length += OPAQUE24_LEN; - /* followed by */ + FALL_THROUGH; /* followed by */ case WOLFSSL_CSR2_OCSP: for (i = 0; i < count; i++) @@ -10743,7 +12052,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (sendSz < 0) @@ -10793,13 +12102,13 @@ int SendCertificateStatus(WOLFSSL* ssl) (void) ssl; - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST - status_type = ssl->status_request; - #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + status_type = ssl->status_request; +#endif - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - status_type = status_type ? status_type : ssl->status_request_v2; - #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + status_type = status_type ? status_type : ssl->status_request_v2; +#endif switch (status_type) { @@ -10807,7 +12116,8 @@ int SendCertificateStatus(WOLFSSL* ssl) #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) /* case WOLFSSL_CSR_OCSP: */ - case WOLFSSL_CSR2_OCSP: { + case WOLFSSL_CSR2_OCSP: + { OcspRequest* request = ssl->ctx->certOcspRequest; buffer response; @@ -10817,7 +12127,7 @@ int SendCertificateStatus(WOLFSSL* ssl) if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) return 0; - if (!request || ssl->buffers.weOwnCert) { + if (request == NULL || ssl->buffers.weOwnCert) { DerBuffer* der = ssl->buffers.certificate; #ifdef WOLFSSL_SMALL_STACK DecodedCert* cert = NULL; @@ -10829,15 +12139,15 @@ int SendCertificateStatus(WOLFSSL* ssl) if (der->buffer == NULL || der->length == 0) return 0; - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return MEMORY_E; - #endif + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -10845,44 +12155,50 @@ int SendCertificateStatus(WOLFSSL* ssl) else { request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return MEMORY_E; - } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + if (request) { + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } } - else if (!ssl->buffers.weOwnCert && 0 == wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->certOcspRequest) - ssl->ctx->certOcspRequest = request; - wc_UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + ret = MEMORY_E; } } FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } if (ret == 0) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &response); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } if (response.buffer) { if (ret == 0) @@ -10896,14 +12212,16 @@ int SendCertificateStatus(WOLFSSL* ssl) if (request != ssl->ctx->certOcspRequest) XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + + break; } - break; #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2 - case WOLFSSL_CSR2_OCSP_MULTI: { + case WOLFSSL_CSR2_OCSP_MULTI: + { OcspRequest* request = ssl->ctx->certOcspRequest; buffer responses[1 + MAX_CHAIN_DEPTH]; int i = 0; @@ -10916,25 +12234,25 @@ int SendCertificateStatus(WOLFSSL* ssl) if (!request || ssl->buffers.weOwnCert) { DerBuffer* der = ssl->buffers.certificate; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif /* unable to fetch status. skip. */ if (der->buffer == NULL || der->length == 0) return 0; - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return MEMORY_E; - #endif + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -10942,45 +12260,50 @@ int SendCertificateStatus(WOLFSSL* ssl) else { request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return MEMORY_E; - } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + if (request) { + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } } - else if (!ssl->buffers.weOwnCert && 0 == wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->certOcspRequest) - ssl->ctx->certOcspRequest = request; - - wc_UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + ret = MEMORY_E; } } FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } if (ret == 0) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[0]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } } if (request != ssl->ctx->certOcspRequest) @@ -10990,16 +12313,16 @@ int SendCertificateStatus(WOLFSSL* ssl) || ssl->buffers.weOwnCertChain)) { buffer der; word32 idx = 0; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif XMEMSET(&der, 0, sizeof(buffer)); #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (cert == NULL) return MEMORY_E; @@ -11016,7 +12339,7 @@ int SendCertificateStatus(WOLFSSL* ssl) break; InitDecodedCert(cert, der.buffer, der.length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -11026,36 +12349,47 @@ int SendCertificateStatus(WOLFSSL* ssl) request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); if (request == NULL) { + FreeDecodedCert(cert); + ret = MEMORY_E; break; } ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap,DYNAMIC_TYPE_OCSP_REQUEST); - break; + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCertChain) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->chainOcspRequest[i] == NULL) + ssl->ctx->chainOcspRequest[i] = request; + wc_UnLockMutex(ocspLock); + } + } } - else if (!ssl->buffers.weOwnCertChain && 0 == - wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->chainOcspRequest[i]) - ssl->ctx->chainOcspRequest[i] = request; - - wc_UnLockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + FreeDecodedCert(cert); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + break; } + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[i + 1]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } if (request != ssl->ctx->chainOcspRequest[i]) - XFREE(request, ssl->heap,DYNAMIC_TYPE_OCSP_REQUEST); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); i++; } @@ -11063,42 +12397,46 @@ int SendCertificateStatus(WOLFSSL* ssl) FreeDecodedCert(cert); } - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } else { while (ret == 0 && NULL != (request = ssl->ctx->chainOcspRequest[i])) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[++i]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } } } if (responses[0].buffer) { if (ret == 0) ret = BuildCertificateStatus(ssl, status_type, - responses, i + 1); + responses, (byte)i + 1); for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) if (responses[i].buffer) XFREE(responses[i].buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); } - } - break; + break; + } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #endif /* NO_WOLFSSL_SERVER */ default: - break; + break; } return ret; @@ -11198,10 +12536,25 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) sendBuffer = comp; } #endif - sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, - application_data, 0, 0); - if (sendSz < 0) + if (!ssl->options.tls1_3) { + sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); + } + else { +#ifdef WOLFSSL_TLS13 + sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0); +#else + sendSz = BUFFER_ERROR; +#endif + } + if (sendSz < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (sendSz == WC_PENDING_E) + ssl->error = sendSz; + #endif return BUILD_MSG_ERROR; + } ssl->buffers.outputBuffer.length += sendSz; @@ -11235,8 +12588,10 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) WOLFSSL_ENTER("ReceiveData()"); - if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) + /* reset error state */ + if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) { ssl->error = 0; + } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -11256,10 +12611,12 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) int err; WOLFSSL_MSG("Handshake not complete, trying to finish"); if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) { + #ifdef WOLFSSL_ASYNC_CRYPT /* if async would block return WANT_WRITE */ if (ssl->error == WC_PENDING_E) { return WOLFSSL_CBIO_ERR_WANT_READ; } + #endif return err; } } @@ -11331,6 +12688,26 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) int outputSz; int dtlsExtra = 0; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + int notifyErr = 0; + + WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling"); + + if (type == close_notify) { + notifyErr = ZERO_RETURN; + } else if (severity == alert_fatal) { + notifyErr = FATAL_ERROR; + } + + if (notifyErr != 0) { + return NotifyWriteSide(ssl, notifyErr); + } + + return 0; + } +#endif + /* if sendalert is called again for nonblocking */ if (ssl->options.sendAlertState != 0) { ret = SendBuffered(ssl); @@ -11365,7 +12742,7 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) other side may not be able to handle it */ if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, - alert, 0, 0); + alert, 0, 0, 0); else { AddRecordHeader(output, ALERT_SIZE, alert, ssl); @@ -11596,8 +12973,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case NOT_CA_ERROR: return "Not a CA by basic constraint error"; - case BAD_PATH_ERROR: - return "Bad path for opendir error"; + case HTTP_TIMEOUT: + return "HTTP timeout for OCSP or CRL req"; case BAD_CERT_MANAGER_ERROR: return "Bad Cert Manager error"; @@ -11767,6 +13144,33 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case DECODE_E: return "Decode handshake message error"; + case WRITE_DUP_READ_E: + return "Write dup write side can't read error"; + + case WRITE_DUP_WRITE_E: + return "Write dup read side can't write error"; + + case INVALID_CERT_CTX_E: + return "Certificate context does not match request or not empty"; + + case BAD_KEY_SHARE_DATA: + return "The Key Share data contains group that was in Client Hello"; + + case MISSING_HANDSHAKE_DATA: + return "The handshake message is missing required data"; + + case BAD_BINDER: + return "Binder value does not match value server calculated"; + + case EXT_NOT_ALLOWED: + return "Extension type not allowed in handshake message type"; + + case INVALID_PARAMETER: + return "The security parameter is invalid"; + + case KEY_SHARE_ERROR: + return "Key share extension did not contain a valid named group"; + default : return "unknown error number"; } @@ -12222,6 +13626,27 @@ static const char* const cipher_names[] = #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA "EDH-RSA-DES-CBC3-SHA", #endif + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + "TLS13-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + "TLS13-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + "TLS13-CHACHA20-POLY1305-SHA256", +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + "TLS13-AES128-CCM-SHA256", +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + "TLS13-AES128-CCM-8-SHA256", +#endif + }; @@ -12668,6 +14093,27 @@ static int cipher_name_idx[] = #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, #endif + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + TLS_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + TLS_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + TLS_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + TLS_AES_128_CCM_SHA256, +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + TLS_AES_128_CCM_8_SHA256, +#endif + }; @@ -12944,8 +14390,38 @@ const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite, } /* ECC and AES CCM/GCM */ #endif /* HAVE_ECC || HAVE_AESCCM*/ + if (cipherSuite0 == TLS13_BYTE) { + /* TLS v1.3 suites */ + switch (cipherSuite) { +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_AESGCM + case TLS_AES_128_GCM_SHA256 : + return "TLS_AES_128_GCM_SHA256"; + case TLS_AES_256_GCM_SHA384 : + return "TLS_AES_256_GCM_SHA384"; + #endif + + #ifdef HAVE_CHACHA + case TLS_CHACHA20_POLY1305_SHA256 : + return "TLS_CHACHA20_POLY1305_SHA256"; + #endif + + #ifdef HAVE_AESCCM + case TLS_AES_128_CCM_SHA256 : + return "TLS_AES_128_CCM_SHA256"; + case TLS_AES_128_CCM_8_SHA256 : + return "TLS_AES_256_CCM_8_SHA256"; + #endif +#endif + + default: + return "NONE"; + } + } + if (cipherSuite0 != ECC_BYTE && - cipherSuite0 != CHACHA_BYTE) { + cipherSuite0 != CHACHA_BYTE && + cipherSuite0 != TLS13_BYTE) { /* normal suites */ switch (cipherSuite) { @@ -13142,11 +14618,11 @@ Set the enabled cipher suites. @param [out] suites Suites structure. @param [in] list List of cipher suites, only supports full name from - cipher_name[] delimited by ':'. + cipher_names[] delimited by ':'. @return true on success, else false. */ -int SetCipherList(Suites* suites, const char* list) +int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) { int ret = 0; int idx = 0; @@ -13161,7 +14637,8 @@ int SetCipherList(Suites* suites, const char* list) return 0; } - if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0) + if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || + XSTRNCMP(next, "DEFAULT", 7) == 0) return 1; /* wolfSSL defualt */ do { @@ -13179,17 +14656,35 @@ int SetCipherList(Suites* suites, const char* list) for (i = 0; i < suiteSz; i++) { if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) { - suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE + #ifdef WOLFSSL_DTLS + /* don't allow stream ciphers with DTLS */ + if (ctx->method->version.major == DTLS_MAJOR) { + if (XSTRSTR(name, "RC4") || + XSTRSTR(name, "HC128") || + XSTRSTR(name, "RABBIT")) + { + WOLFSSL_MSG("Stream ciphers not supported with DTLS"); + continue; + } + + } + #endif /* WOLFSSL_DTLS */ + + suites->suites[idx++] = (XSTRSTR(name, "TLS13")) ? TLS13_BYTE + : (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE : (XSTRSTR(name, "QSH")) ? QSH_BYTE : (XSTRSTR(name, "EC")) ? ECC_BYTE : (XSTRSTR(name, "CCM")) ? ECC_BYTE : 0x00; /* normal */ - suites->suites[idx++] = (byte)cipher_name_idx[i]; /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA * suites don't necessarily have RSA in the name. */ - if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) + if (XSTRSTR(name, "TLS13")) { + haveRSAsig = 1; + haveECDSAsig = 1; + } + else if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) haveECDSAsig = 1; else if (XSTRSTR(name, "ADH")) haveAnon = 1; @@ -13209,20 +14704,32 @@ int SetCipherList(Suites* suites, const char* list) InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon); } + (void)ctx; + return ret; } #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) -static void PickHashSigAlgo(WOLFSSL* ssl, - const byte* hashSigAlgo, word32 hashSigAlgoSz) +void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) { word32 i; ssl->suites->sigAlgo = ssl->specs.sig_algo; - ssl->suites->hashAlgo = sha_mac; + + /* set defaults */ + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_ALLOW_TLS_SHA1 + ssl->suites->hashAlgo = sha_mac; + #else + ssl->suites->hashAlgo = sha256_mac; + #endif + } + else { + ssl->suites->hashAlgo = sha_mac; + } /* i+1 since peek a byte ahead for type */ - for (i = 0; (i+1) < hashSigAlgoSz; i += 2) { + for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { if (hashSigAlgo[i+1] == ssl->specs.sig_algo) { if (hashSigAlgo[i] == sha_mac) { break; @@ -13246,6 +14753,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif } + else if (ssl->specs.sig_algo == 0) { + ssl->suites->hashAlgo = ssl->specs.mac_algorithm; + } } } #endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ @@ -13348,7 +14858,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, XMEMCPY(info->packets[info->numberPackets].value, data, sz); else { info->packets[info->numberPackets].bufferValue = - XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); + (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); if (!info->packets[info->numberPackets].bufferValue) /* let next alloc catch, just don't fill, not fatal here */ info->packets[info->numberPackets].valueSz = 0; @@ -13410,6 +14920,12 @@ static void PickHashSigAlgo(WOLFSSL* ssl, int ret; word16 extSz = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return SendTls13ClientHello(ssl); +#endif + if (ssl->suites == NULL) { WOLFSSL_MSG("Bad suites pointer in SendClientHello"); return SUITES_ERROR; @@ -13485,23 +15001,23 @@ static void PickHashSigAlgo(WOLFSSL* ssl, output[idx++] = ssl->version.minor; ssl->chVersion = ssl->version; /* store in case changed */ - /* then random */ + /* then random */ if (ssl->options.connectState == CONNECT_BEGIN) { ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); if (ret != 0) return ret; - /* store random */ + /* store random */ XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); } else { #ifdef WOLFSSL_DTLS - /* send same random on hello again */ + /* send same random on hello again */ XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); #endif } idx += RAN_LEN; - /* then session id */ + /* then session id */ output[idx++] = (byte)idSz; if (idSz) { XMEMCPY(output + idx, ssl->session.sessionID, @@ -13509,7 +15025,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, idx += ssl->session.sessionIDSz; } - /* then DTLS cookie */ + /* then DTLS cookie */ #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { byte cookieSz = ssl->arrays->cookieSz; @@ -13521,13 +15037,13 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } } #endif - /* then cipher suites */ + /* then cipher suites */ c16toa(ssl->suites->suiteSz, output + idx); - idx += 2; + idx += OPAQUE16_LEN; XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); idx += ssl->suites->suiteSz; - /* last, compression */ + /* last, compression */ output[idx++] = COMP_LEN; if (ssl->options.usingCompression) output[idx++] = ZLIB_COMPRESSION; @@ -13582,7 +15098,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (sendSz < 0) @@ -13691,42 +15207,40 @@ static void PickHashSigAlgo(WOLFSSL* ssl, return ret; } - static int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, - word32 helloSz) + /* Check the version in the received message is valid and set protocol + * version to use. + * + * ssl The SSL/TLS object. + * pv The protocol version from the packet. + * returns 0 on success, otherwise failure. + */ + int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv) { - byte cs0; /* cipher suite bytes 0, 1 */ - byte cs1; - ProtocolVersion pv; - byte compression; - word32 i = *inOutIdx; - word32 begin = i; - -#ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#ifdef WOLFSSL_TLS13 + /* TODO: [TLS13] Remove this. + * Translate the draft TLS v1.3 version to final version. + */ + if (pv.major == TLS_DRAFT_MAJOR) { + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + } #endif - /* protocol version, random and session id length check */ - if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) - return BUFFER_ERROR; - - /* protocol version */ - XMEMCPY(&pv, input + i, OPAQUE16_LEN); - i += OPAQUE16_LEN; - + /* Check for upgrade attack. */ if (pv.minor > ssl->version.minor) { WOLFSSL_MSG("Server using higher version, fatal error"); return VERSION_ERROR; } - else if (pv.minor < ssl->version.minor) { + if (pv.minor < ssl->version.minor) { WOLFSSL_MSG("server using lower version"); + /* Check for downgrade attack. */ if (!ssl->options.downgrade) { - WOLFSSL_MSG(" no downgrade allowed, fatal error"); + WOLFSSL_MSG("\tno downgrade allowed, fatal error"); return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } @@ -13739,25 +15253,66 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif + /* Checks made - OK to downgrade. */ if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { /* turn off tls 1.1+ */ - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } } + return 0; + } + + int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) + { + byte cs0; /* cipher suite bytes 0, 1 */ + byte cs1; + ProtocolVersion pv; + byte compression; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(pv)) + return DoTls13ServerHello(ssl, input, inOutIdx, helloSz); +#endif + /* random */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); i += RAN_LEN; @@ -13818,7 +15373,6 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_TLS_EXTENSIONS if ( (i - begin) < helloSz) { if (TLSX_SupportExtensions(ssl)) { - int ret = 0; word16 totalExtSz; if ((i - begin) + OPAQUE16_LEN > helloSz) @@ -13911,7 +15465,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { - int secretSz = SECRET_LEN, ret; + int secretSz = SECRET_LEN; ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) @@ -13922,20 +15476,20 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if (ssl->options.resuming) { if (DSH_CheckSessionId(ssl)) { if (SetCipherSpecs(ssl) == 0) { - int ret = -1; XMEMCPY(ssl->arrays->masterSecret, ssl->session.masterSecret, SECRET_LEN); - #ifdef NO_OLD_TLS + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + ret = -1; /* default value */ + #ifndef NO_TLS + if (ssl->options.tls) ret = DeriveTlsKeys(ssl); - #else - #ifndef NO_TLS - if (ssl->options.tls) - ret = DeriveTlsKeys(ssl); - #endif - if (!ssl->options.tls) - ret = DeriveKeys(ssl); - #endif + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif /* NO_OLD_TLS */ ssl->options.serverState = SERVER_HELLODONE_COMPLETE; return ret; @@ -14139,71 +15693,78 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #endif /* HAVE_ECC */ -static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, - word32* inOutIdx, word32 size) -{ - int ret = 0; - word16 length = 0; - word32 idx = *inOutIdx, begin = *inOutIdx; +/* Persistable DoServerKeyExchange arguments */ +typedef struct DskeArgs { + byte* output; /* not allocated */ +#if !defined(NO_DH) || defined(HAVE_ECC) + byte* verifySig; +#endif + word32 idx; + word32 begin; #ifndef NO_RSA - int typeH = 0; + int typeH; #endif - byte* output = NULL; - byte sigAlgo = ssl->specs.sig_algo; - word16 sigSz = 0; #if !defined(NO_DH) || defined(HAVE_ECC) - byte* verifySig = NULL; + word16 verifySigSz; #endif + word16 sigSz; + byte sigAlgo; +} DskeArgs; - (void)output; - (void)sigAlgo; - (void)sigSz; +static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs) +{ + DskeArgs* args = (DskeArgs*)pArgs; - WOLFSSL_ENTER("DoServerKeyExchange"); + (void)ssl; + (void)args; + +#if !defined(NO_DH) || defined(HAVE_ECC) + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } +#endif +} +static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + int ret = 0; #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; + DskeArgs* args = (DskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + DskeArgs args[1]; +#endif - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); + WOLFSSL_ENTER("DoServerKeyExchange"); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { /* Check for error */ - if (ret < 0) { + 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; - #ifndef NO_RSA - typeH = ssl->async.hashAlgo; - #endif - 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 { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DskeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + args->sigAlgo = ssl->specs.sig_algo; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDskeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) @@ -14218,38 +15779,42 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case psk_kea: { int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->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; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; break; } #endif /* !NO_PSK */ #ifndef NO_DH case diffie_hellman_kea: { + word16 length; + /* p */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14260,7 +15825,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.serverDH_P.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_P.buffer) { ssl->buffers.serverDH_P.length = length; } @@ -14268,25 +15833,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; ssl->options.dhKeySz = length; /* g */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_G.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_G.buffer) { ssl->buffers.serverDH_G.length = length; } @@ -14294,23 +15860,24 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; /* pub */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_Pub.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Pub.buffer) { ssl->buffers.serverDH_Pub.length = length; } @@ -14318,8 +15885,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; break; } #endif /* !NO_DH */ @@ -14328,24 +15896,27 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, { byte b; int curveId, curveOid; + word16 length; - if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - b = input[idx++]; + b = input[args->idx++]; if (b != named_curve) { ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); } - idx += 1; /* curve type, eat leading 0 */ - b = input[idx++]; + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } + ssl->ecdhCurveOID = curveOid; - length = input[idx++]; - if ((idx - begin) + length > size) { + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14372,12 +15943,12 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + idx, length, + if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); } - idx += length; + args->idx += length; ssl->peerEccKeyPresent = 1; break; } @@ -14386,33 +15957,35 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case dhe_psk_kea: { int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->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; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; /* p */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14423,7 +15996,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_P.buffer) { ssl->buffers.serverDH_P.length = length; } @@ -14431,25 +16004,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; ssl->options.dhKeySz = length; /* g */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_G.buffer) { ssl->buffers.serverDH_G.length = length; } @@ -14457,23 +16031,24 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; /* pub */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Pub.buffer) { ssl->buffers.serverDH_Pub.length = length; } @@ -14481,8 +16056,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; break; } #endif /* !NO_DH || !NO_PSK */ @@ -14492,75 +16068,79 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, byte b; int curveOid, curveId; int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->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; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ - idx += length; + args->idx += length; - if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* Check curve name and ID */ - b = input[idx++]; + b = input[args->idx++]; if (b != named_curve) { ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); } - idx += 1; /* curve type, eat leading 0 */ - b = input[idx++]; + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } - length = input[idx++]; - if ((idx - begin) + length > size) { + length = input[args->idx++]; + if ((args->idx - args->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); + 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); + 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); + 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, + if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); } - idx += length; + args->idx += length; ssl->peerEccKeyPresent = 1; break; } @@ -14575,10 +16155,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { switch(ssl->specs.kea) { @@ -14604,37 +16185,40 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } - verifySz = (word16)(idx - begin); + verifySz = (word16)(args->idx - args->begin); if (verifySz > MAX_DH_SZ) { ERROR_OUT(BUFFER_ERROR, exit_dske); } if (IsAtLeastTLSv1_2(ssl)) { - if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > + size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - hashAlgo = input[idx++]; - sigAlgo = input[idx++]; + hashAlgo = input[args->idx++]; + args->sigAlgo = input[args->idx++]; switch (hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif + #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 + #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 + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) hashType = WC_HASH_TYPE_SHA; #endif break; @@ -14650,7 +16234,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, /* only using sha and md5 for rsa */ #ifndef NO_OLD_TLS hashType = WC_HASH_TYPE_SHA; - if (sigAlgo == rsa_sa_algo) { + if (args->sigAlgo == rsa_sa_algo) { hashType = WC_HASH_TYPE_MD5_SHA; } #else @@ -14658,18 +16242,18 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #endif } #ifndef NO_RSA - typeH = wc_HashGetOID(hashType); + args->typeH = wc_HashGetOID(hashType); #endif /* signature */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &args->verifySigSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->verifySigSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14696,7 +16280,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN); XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], - input + begin, verifySz); /* message */ + input + args->begin, verifySz); /* message */ /* Perform hash */ ret = wc_Hash(hashType, @@ -14706,7 +16290,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, goto exit_dske; } - switch (sigAlgo) + switch (args->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: @@ -14730,7 +16314,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, default: ret = ALGO_ID_E; - } /* switch (sigAlgo) */ + } /* switch (args->sigAlgo) */ #endif /* NO_DH && !HAVE_ECC */ break; @@ -14745,10 +16329,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -14770,23 +16355,25 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } - if (verifySig == NULL) { - verifySig = (byte*)XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->verifySigSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->verifySig == NULL) { ERROR_OUT(MEMORY_E, exit_dske); } - XMEMCPY(verifySig, input + idx, length); + XMEMCPY(args->verifySig, input + args->idx, + args->verifySigSz); } - switch (sigAlgo) + switch (args->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: { ret = RsaVerify(ssl, - verifySig, length, - &output, + args->verifySig, args->verifySigSz, + &args->output, + rsa_sa_algo, no_mac, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -14798,7 +16385,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ); if (ret >= 0) { - sigSz = (word16)ret; + args->sigSz = (word16)ret; ret = 0; } break; @@ -14808,7 +16395,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case ecc_dsa_sa_algo: { ret = EccVerify(ssl, - verifySig, length, + args->verifySig, args->verifySigSz, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->peerEccDsaKey, @@ -14820,6 +16407,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, NULL, 0, NULL #endif ); + break; } #endif /* HAVE_ECC */ @@ -14840,10 +16428,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -14866,9 +16455,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* increment index after verify is done */ - idx += length; + args->idx += args->verifySigSz; - switch(sigAlgo) + switch(args->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: @@ -14891,9 +16480,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, encSigSz = wc_EncodeSignature(encodedSig, ssl->buffers.digest.buffer, - ssl->buffers.digest.length, typeH); - if (encSigSz != sigSz || !output || - XMEMCMP(output, encodedSig, + ssl->buffers.digest.length, args->typeH); + if (encSigSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { ret = VERIFY_SIGN_ERROR; } @@ -14904,9 +16493,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, goto exit_dske; } } - else if (sigSz != FINISHED_SZ || !output || - XMEMCMP(output, ssl->buffers.digest.buffer, - FINISHED_SZ) != 0) { + else if (args->sigSz != FINISHED_SZ || + !args->output || + XMEMCMP(args->output, + ssl->buffers.digest.buffer, + FINISHED_SZ) != 0) { ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske); } break; @@ -14933,13 +16524,14 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { if (IsEncryptionOn(ssl, 0)) { - idx += ssl->keys.padSz; + args->idx += ssl->keys.padSz; } /* QSH extensions */ @@ -14949,17 +16541,17 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, int qshSz; /* extension name */ - ato16(input + idx, &name); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &name); + args->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 + idx, + if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx, size, 0)) < 0) { ERROR_OUT(qshSz, exit_dske); } - idx += qshSz; + args->idx += qshSz; } else { /* unknown extension sent server ignored handshake */ @@ -14968,69 +16560,39 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } #endif - /* Check for error */ - if (ret != 0) { - goto exit_dske; - } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { /* return index */ - *inOutIdx = idx; + *inOutIdx = args->idx; ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; break; } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dske: WOLFSSL_LEAVE("DoServerKeyExchange", ret); - /* Handle cleanup for stack variables here */ - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ 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; - #ifndef NO_RSA - ssl->async.hashAlgo = typeH; - #endif - ssl->async.sigAlgo = sigAlgo; - #if !defined(NO_DH) || defined(HAVE_ECC) - ssl->async.data = verifySig; - #endif - /* 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; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ -#if !defined(NO_DH) || defined(HAVE_ECC) - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } -#endif - /* Final cleanup */ + FreeDskeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -15171,6 +16733,11 @@ static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, int ret = 0; word16 size = *szOut; + (void)in; + (void)szIn; + (void)out; + (void)szOut; + WOLFSSL_MSG("Encrypting QSH key material"); switch (key->name) { @@ -15193,12 +16760,16 @@ static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, /* Decrypt using Quantum Safe Handshake algorithms */ -int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, - byte* out, word16* szOut) +int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut) { int ret = 0; word16 size = *szOut; + (void)in; + (void)szIn; + (void)out; + (void)szOut; + WOLFSSL_MSG("Decrypting QSH key material"); switch (key->name) { @@ -15225,12 +16796,14 @@ int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, */ static word32 QSH_MaxSecret(QSHKey* key) { + int ret = 0; +#ifdef HAVE_NTRU byte isNtru = 0; word16 inSz = 48; word16 outSz; DRBG_HANDLE drbg = 0; byte bufIn[48]; - int ret = 0; +#endif if (key == NULL || key->pub.length == 0) return 0; @@ -15252,6 +16825,7 @@ static word32 QSH_MaxSecret(QSHKey* key) return 0; } +#ifdef HAVE_NTRU if (isNtru) { ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); if (ret != DRBG_OK) @@ -15262,10 +16836,11 @@ static word32 QSH_MaxSecret(QSHKey* key) return NTRU_ENCRYPT_ERROR; } ntru_crypto_drbg_uninstantiate(drbg); - return outSz; + ret = outSz; } +#endif - return 0; + return ret; } /* Generate the secret byte material for pms @@ -15406,59 +16981,67 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) #endif /* HAVE_QSH */ +typedef struct SckeArgs { + byte* output; /* not allocated */ + byte* encSecret; + byte* input; + word32 encSz; + word32 length; + int sendSz; + int inputSz; +} SckeArgs; + +static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs) +{ + SckeArgs* args = (SckeArgs*)pArgs; + + (void)ssl; + + if (args->encSecret) { + XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->encSecret = NULL; + } + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; + } +} + 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; - - (void)length; +#ifdef WOLFSSL_ASYNC_CRYPT + SckeArgs* args = (SckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + SckeArgs args[1]; +#endif 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); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); 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) { + if (ret < 0) goto exit_scke; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - encSecret = ssl->async.data; - encSz = ssl->async.sigSz; - - /* 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; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SckeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSckeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { switch (ssl->specs.kea) { #ifndef NO_RSA @@ -15524,20 +17107,14 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif /* 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); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, - ssl->peerEccKey); + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey); + break; #endif /* HAVE_ECC && !NO_PSK */ #ifdef HAVE_NTRU @@ -15580,19 +17157,14 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* 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); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, peerKey); + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey); + break; } #endif /* HAVE_ECC */ @@ -15607,15 +17179,16 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { - encSz = MAX_ENCRYPT_SZ; - encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encSecret == NULL) { + args->encSz = MAX_ENCRYPT_SZ; + args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->encSecret == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } @@ -15640,11 +17213,31 @@ int SendClientKeyExchange(WOLFSSL* ssl) case diffie_hellman_kea: { ssl->buffers.sig.length = ENCRYPT_LEN; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + args->encSecret, &args->encSz); break; } #endif /* !NO_DH */ @@ -15659,23 +17252,25 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - encSz = (word32)XSTRLEN(ssl->arrays->client_identity); - if (encSz > MAX_PSK_ID_LEN) { + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ + args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (args->encSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } - XMEMCPY(encSecret, - ssl->arrays->client_identity, encSz); + XMEMCPY(args->encSecret, ssl->arrays->client_identity, + args->encSz); /* make psk pre master secret */ /* length of key + length 0s + length of key + key */ c16toa((word16)ssl->arrays->psk_keySz, pms); - pms += 2; + pms += OPAQUE16_LEN; XMEMSET(pms, 0, ssl->arrays->psk_keySz); pms += ssl->arrays->psk_keySz; c16toa((word16)ssl->arrays->psk_keySz, pms); - pms += 2; + pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) + + (2 * OPAQUE16_LEN); ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ break; @@ -15685,7 +17280,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) case dhe_psk_kea: { word32 esSz = 0; - output = encSecret; + args->output = args->encSecret; ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, ssl->arrays->server_hint, ssl->arrays->client_identity, @@ -15694,6 +17289,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ esSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (esSz > MAX_PSK_ID_LEN) { @@ -15701,19 +17297,39 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->buffers.sig.length = ENCRYPT_LEN; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - c16toa((word16)esSz, output); - output += OPAQUE16_LEN; - XMEMCPY(output, ssl->arrays->client_identity, esSz); - output += esSz; - encSz = esSz + OPAQUE16_LEN; + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; - *length = 0; + args->length = 0; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + args->output + OPAQUE16_LEN, &args->length); break; } #endif /* !NO_DH && !NO_PSK */ @@ -15721,7 +17337,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) case ecdhe_psk_kea: { word32 esSz = 0; - output = encSecret; + args->output = args->encSecret; /* Send PSK client identity */ ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, @@ -15731,21 +17347,25 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ 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; + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; /* length is used for public key size */ - *length = MAX_ENCRYPT_SZ; + args->length = MAX_ENCRYPT_SZ; + + /* Create shared ECC key leaving room at the begining + of buffer for size of shared key. */ + ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ @@ -15754,12 +17374,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif - /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - output + OPAQUE8_LEN, length); + /* Place ECC key in output buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } + break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -15773,14 +17394,16 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->arrays->preMasterSz = SECRET_LEN; - encSz = MAX_ENCRYPT_SZ; + args->encSz = MAX_ENCRYPT_SZ; break; } #endif /* HAVE_NTRU */ #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - #ifdef HAVE_PK_CALLBACKS + ssl->arrays->preMasterSz = ENCRYPT_LEN; + + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { break; @@ -15788,8 +17411,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - encSecret + OPAQUE8_LEN, &encSz); + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } @@ -15807,10 +17430,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -15819,7 +17443,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) { ret = RsaEnc(ssl, ssl->arrays->preMasterSecret, SECRET_LEN, - encSecret, &encSz, + args->encSecret, &args->encSz, ssl->peerRsaKey, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.peerRsaKey.buffer, @@ -15829,19 +17453,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) 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, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret, @@ -15858,13 +17478,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) #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, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, @@ -15875,13 +17490,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { - /* Create shared ECC key leaving room at the begining - of buffer for size of shared key. */ - ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; - - ret = EccSharedSecret(ssl, - (ecc_key*)ssl->sigKey, ssl->peerEccKey, - output + OPAQUE8_LEN, length, + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSharedSecret(ssl, key, ssl->peerEccKey, + args->output + OPAQUE8_LEN, &args->length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, &ssl->arrays->preMasterSz, WOLFSSL_CLIENT_END, @@ -15908,8 +17519,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->peerNtruKey, ssl->arrays->preMasterSz, ssl->arrays->preMasterSecret, - (word16*)&encSz, - encSecret); + (word16*)&args->encSz, + args->encSecret); ntru_crypto_drbg_uninstantiate(drbg); if (rc != NTRU_OK) { ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke); @@ -15921,14 +17532,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { + ecc_key* key = (ecc_key*)ssl->hsKey; ecc_key* peerKey = (ssl->specs.static_ecdh) ? ssl->peerEccDsaKey : ssl->peerEccKey; - ssl->arrays->preMasterSz = ENCRYPT_LEN; - ret = EccSharedSecret(ssl, - (ecc_key*)ssl->sigKey, peerKey, - encSecret + OPAQUE8_LEN, &encSz, + key, peerKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, WOLFSSL_CLIENT_END, @@ -15938,6 +17548,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) NULL #endif ); + break; } #endif /* HAVE_ECC */ @@ -15952,10 +17563,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -15980,15 +17592,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; + byte* pms = ssl->arrays->preMasterSecret; /* validate args */ - if (output == NULL || *length == 0) { + if (args->output == NULL || args->length == 0) { ERROR_OUT(BAD_FUNC_ARG, exit_scke); } - c16toa((word16)*length, output); - encSz += *length + OPAQUE16_LEN; + c16toa((word16)args->length, args->output); + args->encSz += args->length + OPAQUE16_LEN; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -16011,13 +17623,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) byte* pms = ssl->arrays->preMasterSecret; /* validate args */ - if (output == NULL || *length > ENCRYPT_LEN) { + if (args->output == NULL || args->length > ENCRYPT_LEN) { ERROR_OUT(BAD_FUNC_ARG, exit_scke); } /* place size of public key in output buffer */ - *output = (byte)*length; - encSz += *length + OPAQUE8_LEN; + *args->output = (byte)args->length; + args->encSz += args->length + OPAQUE8_LEN; /* Create pre master secret is the concatination of eccSize + eccSharedKey + pskSize + pskKey */ @@ -16046,8 +17658,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) case ecc_diffie_hellman_kea: { /* place size of public key in buffer */ - *encSecret = (byte)encSz; - encSz += OPAQUE8_LEN; + *args->encSecret = (byte)args->encSz; + args->encSz += OPAQUE8_LEN; break; } #endif /* HAVE_ECC */ @@ -16062,10 +17674,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { word32 tlsSz = 0; word32 idx = 0; @@ -16087,50 +17700,50 @@ int SendClientKeyExchange(WOLFSSL* ssl) tlsSz = 0; } - idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - sendSz = encSz + tlsSz + idx; + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->encSz + tlsSz + idx; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; } #endif if (IsEncryptionOn(ssl, 1)) { - sendSz += MAX_MSG_EXTRA; + args->sendSz += MAX_MSG_EXTRA; } #ifdef HAVE_QSH - encSz += qshSz; - sendSz += qshSz; + args->encSz += qshSz; + args->sendSz += qshSz; #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_scke; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { byte idxSave = idx; - idx = sendSz - qshSz; + idx = args->sendSz - qshSz; if (QSH_KeyExchangeWrite(ssl, 0) != 0) { ERROR_OUT(MEMORY_E, exit_scke); } /* extension type */ - c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ - if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) { + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + idx) > qshSz - OPAQUE16_LEN) { ERROR_OUT(MEMORY_E, exit_scke); } @@ -16138,52 +17751,69 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif - AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl); + AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl); #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { - encSz -= qshSz; + args->encSz -= qshSz; } #endif if (tlsSz) { - c16toa((word16)encSz, &output[idx]); - idx += 2; + c16toa((word16)args->encSz, &args->output[idx]); + idx += OPAQUE16_LEN; } - XMEMCPY(output + idx, encSecret, encSz); - idx += encSz; + XMEMCPY(args->output + idx, args->encSecret, args->encSz); + idx += args->encSz; if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */ - - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { + args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->input == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (sendSz < 0) { - ERROR_OUT(sendSz, exit_scke); - } + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); } - else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) { + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 1); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) goto exit_scke; + #endif + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scke; + } #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { goto exit_scke; } } @@ -16194,21 +17824,10 @@ int SendClientKeyExchange(WOLFSSL* ssl) AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); + args->output, args->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; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); @@ -16224,45 +17843,24 @@ int SendClientKeyExchange(WOLFSSL* ssl) } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ 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) { - return WC_PENDING_E; - } - } + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; #endif /* 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 */ + FreeSckeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -16270,173 +17868,218 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifndef NO_CERTS +/* Decode the private key - RSA or ECC - and creates a key object. + * The signature type is set as well. + * The maximum length of a signature is returned. + * + * ssl The SSL/TLS object. + * length The length of a signature. + * returns 0 on success, otherwise failure. + */ +int DecodePrivateKey(WOLFSSL *ssl, word16* length) +{ + int ret; + int keySz; + word32 idx; -int SendCertificateVerify(WOLFSSL* ssl) + /* make sure private key exists */ + if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) { + WOLFSSL_MSG("Private key missing!"); + ERROR_OUT(NO_PRIVATE_KEY, exit_dpk); + } + +#ifndef NO_RSA + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + WOLFSSL_MSG("Trying RSA private key"); + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an RSA private key. */ + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (RsaKey*)ssl->hsKey, ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using RSA private key"); + + /* It worked so check it meeets minimum key size requirements. */ + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); + if (keySz < 0) { /* check if keySz has error case */ + ERROR_OUT(keySz, exit_dpk); + } + + if (keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)keySz; + + goto exit_dpk; + } +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +#ifndef NO_RSA + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif /* !NO_RSA */ + + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + +#ifndef NO_RSA + WOLFSSL_MSG("Trying ECC private key, RSA didn't work"); +#else + WOLFSSL_MSG("Trying ECC private key"); +#endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ECC private key. */ + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + WOLFSSL_MSG("Bad client cert type"); + goto exit_dpk; + } + + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); +#endif + +exit_dpk: + return ret; +} + + +typedef struct ScvArgs { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + byte* input; + word32 idx; + word32 extraSz; + word32 sigSz; + int sendSz; + int length; + int inputSz; +} ScvArgs; + +static void FreeScvArgs(WOLFSSL* ssl, void* pArgs) { - byte* output = NULL; - int sendSz = 0, length = 0, ret; - byte* verify = NULL; - word32 idx = 0; - word32 extraSz = 0; + ScvArgs* args = (ScvArgs*)pArgs; + + (void)ssl; + #ifndef NO_RSA - byte* verifySig = NULL; + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } +#endif + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; + } +} + +int SendCertificateVerify(WOLFSSL* ssl) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ScvArgs* args = (ScvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + ScvArgs args[1]; #endif WOLFSSL_ENTER("SendCertificateVerify"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); 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) { + 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; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ScvArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScvArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { return 0; /* sent blank cert, can't verify */ } - sendSz = MAX_CERT_VERIFY_SZ; + args->sendSz = MAX_CERT_VERIFY_SZ; if (IsEncryptionOn(ssl, 1)) { - sendSz += MAX_MSG_EXTRA; + args->sendSz += MAX_MSG_EXTRA; } /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_scv; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { - int keySz; - int typeH = 0; + 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); + /* Decode private key. */ + ret = DecodePrivateKey(ssl, (word16*)&args->length); 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 */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + args->extraSz = 0; /* tls 1.2 hash/sig */ /* build encoded signature buffer */ ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ; @@ -16448,8 +18091,8 @@ int SendCertificateVerify(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif @@ -16470,37 +18113,41 @@ int SendCertificateVerify(WOLFSSL* ssl) #endif /* !NO_OLD_TLS */ if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = ssl->suites->hashAlgo; - verify[1] = (ssl->sigType == DYNAMIC_TYPE_ECC) ? + args->verify[0] = ssl->suites->hashAlgo; + args->verify[1] = (ssl->hsType == DYNAMIC_TYPE_ECC) ? ecc_dsa_sa_algo : rsa_sa_algo; - extraSz = HASH_SIG_SIZE; + args->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; + 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; + 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; + 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; + ssl->buffers.digest.buffer = + ssl->hsHashes->certHashes.sha512; typeH = SHA512h; break; #endif /* WOLFSSL_SHA512 */ @@ -16508,9 +18155,9 @@ int SendCertificateVerify(WOLFSSL* ssl) } #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); + /* if old TLS load MD5 and SHA hash as value to sign */ + XMEMCPY(ssl->buffers.sig.buffer, + (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ); } #endif @@ -16519,9 +18166,9 @@ int SendCertificateVerify(WOLFSSL* ssl) } #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (ssl->hsType == DYNAMIC_TYPE_RSA) { ssl->buffers.sig.length = FINISHED_SZ; - ssl->sigLen = ENCRYPT_LEN; + args->sigSz = ENCRYPT_LEN; if (IsAtLeastTLSv1_2(ssl)) { ssl->buffers.sig.length = wc_EncodeSignature( @@ -16529,22 +18176,26 @@ int SendCertificateVerify(WOLFSSL* ssl) ssl->buffers.digest.length, typeH); } - c16toa((word16)length, verify + extraSz); /* prepend hdr */ + /* prepend hdr */ + c16toa((word16)args->length, args->verify + args->extraSz); } #endif /* !NO_RSA */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { #ifdef HAVE_ECC - if (ssl->sigType == DYNAMIC_TYPE_ECC) { + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSign(ssl, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - (ecc_key*)ssl->sigKey, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -16556,14 +18207,16 @@ int SendCertificateVerify(WOLFSSL* ssl) } #endif /* HAVE_ECC */ #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + /* restore verify pointer */ - verify = &output[idx]; + args->verify = &args->output[args->idx]; ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - verify + extraSz + VERIFY_HEADER, &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -16581,39 +18234,45 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { /* restore verify pointer */ - verify = &output[idx]; + args->verify = &args->output[args->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, + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + args->length = ssl->buffers.sig.length; + /* prepend hdr */ + c16toa((word16)ssl->buffers.sig.length, args->verify + + args->extraSz); + XMEMCPY(args->verify + args->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, + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (verifySig == NULL) { + if (args->verifySig == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } - XMEMCPY(verifySig, verify + extraSz + VERIFY_HEADER, - ssl->sigLen); + XMEMCPY(args->verifySig, args->verify + args->extraSz + + VERIFY_HEADER, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + key + ); } #endif /* !NO_RSA */ @@ -16623,77 +18282,93 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { - AddHeaders(output, length + extraSz + VERIFY_HEADER, - certificate_verify, ssl); + if (args->output == NULL) { + ERROR_OUT(BUFFER_ERROR, exit_scv); + } + AddHeaders(args->output, args->length + args->extraSz + + VERIFY_HEADER, certificate_verify, ssl); - sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + - extraSz + VERIFY_HEADER; + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + args->length + args->extraSz + VERIFY_HEADER; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = sendSz - RECORD_HEADER_SZ; + args->inputSz = args->sendSz - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->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); + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->input, args->inputSz, handshake, + 1, 0, 1); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_scv; + #endif - if (sendSz < 0) { - ret = sendSz; + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scv; } #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsMsgPoolSave(ssl, output, sendSz); + ret = DtlsMsgPoolSave(ssl, args->output, args->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); + args->output, args->sendSz, ssl->heap); #endif - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); @@ -16702,49 +18377,25 @@ int SendCertificateVerify(WOLFSSL* ssl) } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_scv: WOLFSSL_LEAVE("SendCertificateVerify", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ 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; + return ret; } -#endif +#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 */ + FreeScvArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -16754,7 +18405,7 @@ int SendCertificateVerify(WOLFSSL* ssl) #ifdef HAVE_SESSION_TICKET -int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, +static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { word32 begin = *inOutIdx; @@ -16850,6 +18501,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int sendSz; int ret; byte sessIdSz = ID_LEN; + byte echoId = 0; /* ticket echo id flag */ + byte cacheOff = 0; /* session cache off flag */ length = VERSION_SZ + RAN_LEN + ID_LEN + ENUM_LEN @@ -16857,7 +18510,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + ENUM_LEN; #ifdef HAVE_TLS_EXTENSIONS - length += TLSX_GetResponseSize(ssl); + length += TLSX_GetResponseSize(ssl, server_hello); #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket) { /* echo session id sz can be 0,32 or bogus len inbetween */ @@ -16866,7 +18519,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Bad bogus session id len"); return BUFFER_ERROR; } - length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + if (!IsAtLeastTLSv1_3(ssl->version)) + length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + echoId = 1; } #endif /* HAVE_SESSION_TICKET */ #else @@ -16875,6 +18530,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif + /* is the session cahce off at build or runtime */ +#ifdef NO_SESSION_CACHE + cacheOff = 1; +#else + if (ssl->options.sessionCacheOff == 1) { + cacheOff = 1; + } +#endif + + /* if no session cache don't send a session ID unless we're echoing + * an ID as part of session tickets */ + if (echoId == 0 && cacheOff == 1) { + length -= ID_LEN; /* adjust ID_LEN assumption */ + sessIdSz = 0; + } + /* check for avalaible size */ if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0) return ret; @@ -16914,6 +18585,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, idx += RAN_LEN; output[idx++] = sessIdSz; XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz); + ssl->arrays->sessionIDSz = sessIdSz; } else { /* If resuming, use info from SSL */ @@ -16946,7 +18618,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* last, extensions */ #ifdef HAVE_TLS_EXTENSIONS - TLSX_WriteResponse(ssl, output + idx); + TLSX_WriteResponse(ssl, output + idx, server_hello); #else #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { @@ -16979,6 +18651,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); @@ -17083,80 +18756,102 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* HAVE_ECC */ - - int SendServerKeyExchange(WOLFSSL* ssl) - { - int ret; - int sendSz = 0; - byte *output = NULL; - word32 idx = 0, sigSz = 0, length = 0; + typedef struct SskeArgs { + byte* output; /* not allocated */ #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) - byte *sigDataBuf = NULL; - word32 sigDataSz = 0; + byte* sigDataBuf; #endif #if defined(HAVE_ECC) - byte *exportBuf = NULL; - word32 exportSz = 0; + byte* exportBuf; + #endif + #ifndef NO_RSA + byte* verifySig; + #endif + word32 idx; + word32 tmpSigSz; + word32 length; + word32 sigSz; + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + word32 sigDataSz; + #endif + #if defined(HAVE_ECC) + word32 exportSz; #endif - #ifdef HAVE_QSH - word32 qshSz = 0; - if (ssl->peerQSHKeyPresent) { - qshSz = QSH_KeyGetSize(ssl); + word32 qshSz; + #endif + int sendSz; + } SskeArgs; + + static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs) + { + SskeArgs* args = (SskeArgs*)pArgs; + + (void)ssl; + + #if defined(HAVE_ECC) + if (args->exportBuf) { + XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->exportBuf = NULL; + } + #endif + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + if (args->sigDataBuf) { + XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->sigDataBuf = NULL; } #endif #ifndef NO_RSA - byte* verifySig = NULL; + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } #endif + (void)args; + } - (void)ssl; - (void)sigSz; - (void)length; - (void)idx; + int SendServerKeyExchange(WOLFSSL* ssl) + { + int ret; + #ifdef WOLFSSL_ASYNC_CRYPT + SskeArgs* args = (SskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + SskeArgs args[1]; + #endif WOLFSSL_ENTER("SendServerKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); 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) { + if (ret < 0) goto exit_sske; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - idx = ssl->async.idx; - sigSz = ssl->async.sigSz; - length = ssl->async.length; - #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; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SskeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSskeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + args->qshSz = QSH_KeyGetSize(ssl); + } + #endif + /* Do some checks / debug msgs */ switch(ssl->specs.kea) { @@ -17175,7 +18870,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(0, exit_sske); } - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } @@ -17212,8 +18909,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Pub.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Pub.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } @@ -17222,25 +18919,39 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Priv.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Priv.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } } - ret = DhGenKeyPair(ssl, + ssl->options.dhKeySz = + (word16)ssl->buffers.serverDH_P.length; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_sske; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length, ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_sske; + } + + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, &ssl->buffers.serverDH_Priv.length, ssl->buffers.serverDH_Pub.buffer, &ssl->buffers.serverDH_Pub.length); break; } - #endif /* !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA)) */ + #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */ #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: /* Fall through to create temp ECC key */ @@ -17251,19 +18962,16 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* need ephemeral key now, create it if missing */ if (ssl->eccTempKey == NULL) { /* alloc/init on demand */ - ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->eccTempKey == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - ERROR_OUT(MEMORY_E, exit_sske); - } - ret = wc_ecc_init_ex(ssl->eccTempKey, ssl->heap, ssl->devId); - if (ret != 0) + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->eccTempKey); + if (ret != 0) { goto exit_sske; + } } if (ssl->eccTempKeyPresent == 0) { - /* TODO: Need to first do wc_EccPrivateKeyDecode, then we know curve dp */ + /* 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; @@ -17283,10 +18991,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { #if (!defined(NO_DH) && !defined(NO_RSA)) || defined(HAVE_ECC) word32 preSigSz, preSigIdx; @@ -17297,52 +19006,58 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_PSK case psk_kea: { - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; if (ssl->arrays->server_hint[0] == 0) { ERROR_OUT(0, exit_sske); /* don't send */ } /* include size part */ - length = (word32)XSTRLEN(ssl->arrays->server_hint); - if (length > MAX_PSK_ID_LEN) { + args->length = (word32)XSTRLEN(ssl->arrays->server_hint); + if (args->length > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* key data */ #ifdef HAVE_QSH - c16toa((word16)(length - qshSz - HINT_LEN_SZ), output + idx); + c16toa((word16)(args->length - args->qshSz - + HINT_LEN_SZ), args->output + args->idx); #else - c16toa((word16)(length - HINT_LEN_SZ), output + idx); + c16toa((word16)(args->length - HINT_LEN_SZ), + args->output + args->idx); #endif - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, length - HINT_LEN_SZ); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, + args->length - HINT_LEN_SZ); break; } #endif /* !NO_PSK */ @@ -17351,8 +19066,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { word32 hintLen; - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = LENGTH_SZ * 3 + /* p, g, pub */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3 + /* p, g, pub */ ssl->buffers.serverDH_P.length + ssl->buffers.serverDH_G.length + ssl->buffers.serverDH_Pub.length; @@ -17362,58 +19077,67 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (hintLen > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* key data */ - c16toa((word16)hintLen, output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); - idx += hintLen; + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; /* add p, g, pub */ - c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length); - idx += ssl->buffers.serverDH_P.length; + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + args->idx += ssl->buffers.serverDH_P.length; /* g */ - c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - idx += ssl->buffers.serverDH_G.length; + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + args->idx += ssl->buffers.serverDH_G.length; /* pub */ - c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, - ssl->buffers.serverDH_Pub.length); + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); /* No need to update idx, since sizes are already set */ - /* idx += ssl->buffers.serverDH_Pub.length; */ + /* args->idx += ssl->buffers.serverDH_Pub.length; */ break; } #endif /* !defined(NO_DH) && !defined(NO_PSK) */ @@ -17423,59 +19147,62 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 hintLen; /* curve type, named curve, length(1) */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; - exportSz = MAX_EXPORT_ECC_SZ; - exportBuf = (byte*)XMALLOC(exportSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) { + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &exportSz) != 0) { + if (wc_ecc_export_x963(ssl->eccTempKey, args->exportBuf, + &args->exportSz) != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); } - length += exportSz; + args->length += args->exportSz; /* include size part */ hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); if (hintLen > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* key data */ - c16toa((word16)hintLen, output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); - idx += hintLen; + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; /* ECC key exchange data */ - output[idx++] = named_curve; - output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ssl->eccTempKey); - output[idx++] = (byte)exportSz; - XMEMCPY(output + idx, exportBuf, exportSz); + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + args->output[args->idx++] = SetCurveId(ssl->eccTempKey); + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, + args->exportSz); break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -17485,23 +19212,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, enum wc_HashType hashType = WC_HASH_TYPE_NONE; /* curve type, named curve, length(1) */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; /* Export temp ECC key and add to length */ - exportSz = MAX_EXPORT_ECC_SZ; - exportBuf = (byte*)XMALLOC(exportSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) { + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &exportSz) != 0) { + if (wc_ecc_export_x963(ssl->eccTempKey, args->exportBuf, + &args->exportSz) != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); } - length += exportSz; + args->length += args->exportSz; - preSigSz = length; - preSigIdx = idx; + preSigSz = args->length; + preSigIdx = args->idx; switch(ssl->specs.sig_algo) { @@ -17511,31 +19239,26 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 i = 0; int keySz; - ssl->sigKey = 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_ex((RsaKey*)ssl->sigKey, - ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } - 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->hsKey, + ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_sske); } - sigSz = (word32)keySz; + args->tmpSigSz = (word32)keySz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("RSA signature key size too small"); ERROR_OUT(RSA_KEY_SIZE_E, exit_sske); @@ -17546,27 +19269,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_dsa_sa_algo: { word32 i = 0; - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); - if (ret != 0) + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { goto exit_sske; + } - ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (ecc_key*)ssl->sigKey, - ssl->buffers.key->length); + ret = wc_EccPrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - sigSz = wc_ecc_sig_size((ecc_key*)ssl->sigKey); /* worst case estimate */ + /* worst case estimate */ + args->tmpSigSz = wc_ecc_sig_size( + (ecc_key*)ssl->hsKey); /* check the minimum ECC key size */ - if (wc_ecc_size((ecc_key*)ssl->sigKey) < + if (wc_ecc_size((ecc_key*)ssl->hsKey) < ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key size too small"); ret = ECC_KEY_SIZE_E; @@ -17579,69 +19302,71 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* switch(ssl->specs.sig_algo) */ /* sig length */ - length += LENGTH_SZ; - length += sigSz; + args->length += LENGTH_SZ; + args->length += args->tmpSigSz; if (IsAtLeastTLSv1_2(ssl)) { - length += HASH_SIG_SIZE; + args->length += HASH_SIG_SIZE; } - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* record and message headers will be added below, when we're sure of the sig length */ /* key exchange data */ - output[idx++] = named_curve; - output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ssl->eccTempKey); - output[idx++] = (byte)exportSz; - XMEMCPY(output + idx, exportBuf, exportSz); - idx += exportSz; + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + args->output[args->idx++] = SetCurveId(ssl->eccTempKey); + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz); + args->idx += args->exportSz; /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; + args->output[args->idx++] = ssl->suites->hashAlgo; + args->output[args->idx++] = ssl->suites->sigAlgo; switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) hashType = WC_HASH_TYPE_SHA; #endif break; @@ -17670,37 +19395,42 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_FUZZER if (ssl->fuzzerCb) { - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, - FUZZ_SIGNATURE, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); } #endif /* 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) { + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->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); + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, + 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); } /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, + ret = wc_Hash(hashType, + args->sigDataBuf, args->sigDataSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length); if (ret != 0) { goto exit_sske; } - ssl->sigLen = sigSz; + args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ switch (ssl->specs.sig_algo) @@ -17720,22 +19450,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif + #ifdef WOLFSSL_SHA512 + typeH = SHA512h; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif + #ifdef WOLFSSL_SHA384 + typeH = SHA384h; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif + #ifndef NO_SHA256 + typeH = SHA256h; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) typeH = SHAh; #endif break; @@ -17743,8 +19475,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + 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, @@ -17753,8 +19487,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* write sig size here */ - c16toa((word16)ssl->sigLen, output + idx); - idx += LENGTH_SZ; + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; break; } #endif /* !NO_RSA */ @@ -17771,50 +19506,46 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { enum wc_HashType hashType = WC_HASH_TYPE_NONE; - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = LENGTH_SZ * 3; /* p, g, pub */ - length += ssl->buffers.serverDH_P.length + - ssl->buffers.serverDH_G.length + - ssl->buffers.serverDH_Pub.length; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3; /* p, g, pub */ + args->length += ssl->buffers.serverDH_P.length + + ssl->buffers.serverDH_G.length + + ssl->buffers.serverDH_Pub.length; - preSigIdx = idx; - preSigSz = length; + preSigIdx = args->idx; + preSigSz = args->length; if (!ssl->options.usingAnon_cipher) { word32 i = 0; int keySz; - ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } - ssl->sigType = DYNAMIC_TYPE_RSA; - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, - ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } /* sig length */ - length += LENGTH_SZ; - - if (!ssl->buffers.key->buffer) { - ERROR_OUT(NO_PRIVATE_KEY, exit_sske); - } + args->length += LENGTH_SZ; - 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->hsKey, ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_sske); } - sigSz = (word32)keySz; - length += sigSz; + args->tmpSigSz = (word32)keySz; + args->length += args->tmpSigSz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("RSA key size too small"); @@ -17822,60 +19553,68 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (IsAtLeastTLSv1_2(ssl)) { - length += HASH_SIG_SIZE; + args->length += HASH_SIG_SIZE; } } - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* add p, g, pub */ - c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length); - idx += ssl->buffers.serverDH_P.length; + args->idx += ssl->buffers.serverDH_P.length; /* g */ - c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, ssl->buffers.serverDH_G.length); - idx += ssl->buffers.serverDH_G.length; + args->idx += ssl->buffers.serverDH_G.length; /* pub */ - c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length); - idx += ssl->buffers.serverDH_Pub.length; + args->idx += ssl->buffers.serverDH_Pub.length; #ifdef HAVE_FUZZER if (ssl->fuzzerCb) { - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, - FUZZ_SIGNATURE, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); } #endif @@ -17885,27 +19624,29 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; + args->output[args->idx++] = ssl->suites->hashAlgo; + args->output[args->idx++] = ssl->suites->sigAlgo; switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) hashType = WC_HASH_TYPE_SHA; #endif break; @@ -17930,19 +19671,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* signature size */ - c16toa((word16)sigSz, output + idx); - idx += LENGTH_SZ; + c16toa((word16)args->tmpSigSz, args->output + args->idx); + args->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) { + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->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); + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); ssl->buffers.sig.buffer = (byte*)XMALLOC( @@ -17953,13 +19697,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, + ret = wc_Hash(hashType, + args->sigDataBuf, args->sigDataSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length); if (ret != 0) { goto exit_sske; } - ssl->sigLen = sigSz; + args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ switch (ssl->suites->sigAlgo) @@ -17979,22 +19724,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif + #ifdef WOLFSSL_SHA512 + typeH = SHA512h; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif + #ifdef WOLFSSL_SHA384 + typeH = SHA384h; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif + #ifndef NO_SHA256 + typeH = SHA256h; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) typeH = SHAh; #endif break; @@ -18002,8 +19749,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + 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, @@ -18025,10 +19774,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -18059,12 +19809,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->output + args->idx, + &args->sigSz, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -18078,12 +19830,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !NO_RSA */ case ecc_dsa_sa_algo: { + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + LENGTH_SZ + idx, - &ssl->sigLen, - (ecc_key*)ssl->sigKey, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -18107,6 +19861,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + if (ssl->options.usingAnon_cipher) { break; } @@ -18114,9 +19870,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->output + args->idx, + &args->sigSz, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -18141,10 +19897,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -18177,35 +19934,41 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { - if (verifySig == NULL) { - if (ssl->sigLen == 0) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + if (args->sigSz == 0) { ERROR_OUT(BAD_COND_E, exit_sske); } - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (!args->verifySig) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(verifySig, output + idx, ssl->sigLen); + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + key + ); break; } #endif case ecc_dsa_sa_algo: { /* Now that we know the real sig size, write it. */ - c16toa((word16)ssl->sigLen, output + idx); + c16toa((word16)args->sigSz, + args->output + args->idx); /* And adjust length and sendSz from estimates */ - length += ssl->sigLen - sigSz; - sendSz += ssl->sigLen - sigSz; + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; break; } default: @@ -18222,28 +19985,33 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + if (ssl->options.usingAnon_cipher) { break; } - if (verifySig == NULL) { - if (ssl->sigLen == 0) { + if (args->verifySig == NULL) { + if (args->sigSz == 0) { ERROR_OUT(BAD_COND_E, exit_sske); } - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + if (!args->verifySig) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(verifySig, output + idx, ssl->sigLen); + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + key + ); break; } #endif @@ -18259,26 +20027,29 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { - if (qshSz > 0) { - idx = sendSz - qshSz; + if (args->qshSz > 0) { + args->idx = args->sendSz - args->qshSz; if (QSH_KeyExchangeWrite(ssl, 1) != 0) { ERROR_OUT(MEMORY_E, exit_sske); } /* extension type */ - c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); - idx += OPAQUE16_LEN; + c16toa(TLSX_QUANTUM_SAFE_HYBRID, + args->output + args->idx); + args->idx += OPAQUE16_LEN; /* write to output and check amount written */ - if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) { + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + args->idx) > + args->qshSz - OPAQUE16_LEN) { ERROR_OUT(MEMORY_E, exit_sske); } } @@ -18289,8 +20060,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->specs.kea == ecdhe_psk_kea || ssl->specs.kea == ecc_diffie_hellman_kea) { /* Check output to make sure it was set */ - if (output) { - AddHeaders(output, length, server_key_exchange, ssl); + if (args->output) { + AddHeaders(args->output, args->length, + server_key_exchange, ssl); } else { ERROR_OUT(BUFFER_ERROR, exit_sske); @@ -18300,7 +20072,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { goto exit_sske; } } @@ -18309,7 +20081,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, DtlsSEQIncrement(ssl, CUR_ORDER); #endif - ret = HashOutput(ssl, output, sendSz, 0); + ret = HashOutput(ssl, args->output, args->sendSz, 0); if (ret != 0) { goto exit_sske; } @@ -18319,23 +20091,19 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); } if (ssl->toInfoOn) { - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, - sendSz, ssl->heap); + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, + args->output, args->sendSz, ssl->heap); } #endif - /* Check for error */ - if (ret != 0) { - goto exit_sske; - } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); } @@ -18345,57 +20113,20 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_sske: WOLFSSL_LEAVE("SendServerKeyExchange", ret); - /* Handle cleanup for stack variables here */ - #if defined(HAVE_ECC) - if (exportBuf) { - XFREE(exportBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - exportBuf = NULL; - } - #endif - #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) - if (sigDataBuf) { - XFREE(sigDataBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - sigDataBuf = NULL; - } - #endif - - #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.length = length; - ssl->async.sigSz = sigSz; - #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 + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; + #endif /* WOLFSSL_ASYNC_CRYPT */ /* Final cleanup */ + FreeSskeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -18528,12 +20259,50 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END) { + /* Try to establish a key share. */ + int ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + else if (ret != 0) + return 0; + } +#endif + return 1; } #ifndef NO_WOLFSSL_SERVER - static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i, + word16 j) + { + if (ssl->suites->suites[i] == peerSuites->suites[j] && + ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { + + if (VerifyServerSuite(ssl, i)) { + int result; + WOLFSSL_MSG("Verified suite validity"); + ssl->options.cipherSuite0 = ssl->suites->suites[i]; + ssl->options.cipherSuite = ssl->suites->suites[i+1]; + result = SetCipherSpecs(ssl); + if (result == 0) + PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + peerSuites->hashSigAlgoSz); + return result; + } + else { + WOLFSSL_MSG("Could not verify suite validity, continue"); + } + } + + return MATCH_SUITE_ERROR; + } + + int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) { + int ret; word16 i, j; WOLFSSL_ENTER("MatchSuite"); @@ -18544,27 +20313,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->suites == NULL) return SUITES_ERROR; - /* start with best, if a match we are good */ - for (i = 0; i < ssl->suites->suiteSz; i += 2) - for (j = 0; j < peerSuites->suiteSz; j += 2) - if (ssl->suites->suites[i] == peerSuites->suites[j] && - ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { - - if (VerifyServerSuite(ssl, i)) { - int result; - WOLFSSL_MSG("Verified suite validity"); - ssl->options.cipherSuite0 = ssl->suites->suites[i]; - ssl->options.cipherSuite = ssl->suites->suites[i+1]; - result = SetCipherSpecs(ssl); - if (result == 0) - PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); - return result; - } - else { - WOLFSSL_MSG("Could not verify suite validity, continue"); - } + + if (!ssl->options.useClientOrder) { + /* Server order */ + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; + } + } + } + else { + /* Client order */ + for (j = 0; j < peerSuites->suiteSz; j += 2) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; } + } + } return MATCH_SUITE_ERROR; } @@ -18626,26 +20395,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); /* turn off tls 1.1+ */ ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } #ifndef NO_RSA haveRSA = 1; #endif @@ -18661,7 +20434,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* suite size */ ato16(&input[idx], &clSuites.suiteSz); - idx += 2; + idx += OPAQUE16_LEN; if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) return BUFFER_ERROR; @@ -18669,14 +20442,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* session size */ ato16(&input[idx], &sessionSz); - idx += 2; + idx += OPAQUE16_LEN; if (sessionSz > ID_LEN) return BUFFER_ERROR; /* random size */ ato16(&input[idx], &randomSz); - idx += 2; + idx += OPAQUE16_LEN; if (randomSz > RAN_LEN) return BUFFER_ERROR; @@ -18685,10 +20458,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) { byte first = input[idx++]; if (!first) { /* implicit: skip sslv2 type */ - XMEMCPY(&clSuites.suites[j], &input[idx], 2); - j += 2; + XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN); + j += SUITE_LEN; } - idx += 2; + idx += SUITE_LEN; } clSuites.suiteSz = j; @@ -18729,6 +20502,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Session lookup for resume failed"); ssl->options.resuming = 0; } else { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); return UNSUPPORTED_SUITE; @@ -18761,7 +20537,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* OLD_HELLO_ALLOWED */ - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { byte b; @@ -18776,6 +20552,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte peerCookieSz = 0; byte cookieType; byte cookieSz = 0; + + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS @@ -18810,7 +20588,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.dtlsCookieSecret.length); if (ret != 0) return ret; ret = wc_HmacUpdate(&cookieHmac, - ssl->buffers.dtlsCtx.peer.sa, + (const byte*)ssl->buffers.dtlsCtx.peer.sa, ssl->buffers.dtlsCtx.peer.sz); if (ret != 0) return ret; ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN); @@ -18832,27 +20610,31 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { /* turn off tls 1.1+ */ - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } #ifndef NO_RSA haveRSA = 1; #endif @@ -19089,12 +20871,13 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_TLS_EXTENSIONS /* tls extensions */ - if ((ret = TLSX_Parse(ssl, (byte *) input + i, - totalExtSz, 1, &clSuites))) + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + client_hello, &clSuites))) return ret; -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) if((ret=SNI_Callback(ssl))) return ret; + ssl->options.side = WOLFSSL_SERVER_END; #endif /*HAVE_STUNNEL*/ i += totalExtSz; @@ -19179,8 +20962,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, "using EMS"); return EXT_MASTER_SECRET_NEEDED_E; } +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif } else { +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); return UNSUPPORTED_SUITE; @@ -19212,63 +21001,65 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_RSA) || defined(HAVE_ECC) + typedef struct DcvArgs { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + } DcvArgs; + + static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs) + { + DcvArgs* args = (DcvArgs*)pArgs; + + (void)ssl; + (void)args; + } + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret = 0; - byte* output = NULL; - word32 sendSz = 0; - word16 sz = 0; - word32 sigSz = 0; - byte hashAlgo = sha_mac; - byte sigAlgo = anonymous_sa_algo; - word32 idx = *inOutIdx, begin = *inOutIdx; + int ret = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + DcvArgs* args = (DcvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DcvArgs args[1]; + #endif WOLFSSL_ENTER("DoCertificateVerify"); - (void)sigSz; - (void)output; - (void)sendSz; - #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); 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) { + if (ret < 0) goto exit_dcv; - } - 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++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DcvArgs)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcvArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) @@ -19278,79 +21069,100 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { if (IsAtLeastTLSv1_2(ssl)) { - if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } - hashAlgo = input[idx++]; - sigAlgo = input[idx++]; + args->hashAlgo = input[args->idx++]; + args->sigAlgo = input[args->idx++]; } - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } - ato16(input + idx, &sz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + sz > size || sz > ENCRYPT_LEN) { + if ((args->idx - args->begin) + args->sz > size || + args->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"); + /* make sure a default is defined */ + #if !defined(NO_SHA) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + #elif !defined(NO_SHA256) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA384) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA512) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #else + #error No digest enabled for ECC sig verify + #endif + if (IsAtLeastTLSv1_2(ssl)) { - if (sigAlgo != ecc_dsa_sa_algo) { + if (args->sigAlgo != ecc_dsa_sa_algo) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); } - if (hashAlgo == sha256_mac) { + switch (args->hashAlgo) { + case 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) { + break; + case 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) { + break; + case sha512_mac: #ifdef WOLFSSL_SHA512 ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; ssl->buffers.digest.length = SHA512_DIGEST_SIZE; #endif + break; } } } #endif /* HAVE_ECC */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_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, + input + args->idx, + args->sz, + &args->output, + rsa_sa_algo, no_mac, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -19361,7 +21173,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ); if (ret >= 0) { - sendSz = ret; + args->sendSz = ret; ret = 0; } } @@ -19371,7 +21183,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Doing ECC peer cert verify"); ret = EccVerify(ssl, - input + idx, sz, + input + args->idx, args->sz, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->peerEccDsaKey, #ifdef HAVE_PK_CALLBACKS @@ -19391,75 +21203,92 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { if (IsAtLeastTLSv1_2(ssl)) { #ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; + byte* encodedSig = NULL; #else - byte encodedSig[MAX_ENCODED_SIG_SZ]; + byte encodedSig[MAX_ENCODED_SIG_SZ]; #endif - int typeH = SHAh; + int typeH = SHAh; + /* make sure a default is defined */ + #if !defined(NO_SHA) ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; ssl->buffers.digest.length = SHA_DIGEST_SIZE; + #elif !defined(NO_SHA256) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA384) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA512) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #else + #error No digest enabled for RSA sig verify + #endif #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (encodedSig == NULL) { ERROR_OUT(MEMORY_E, exit_dcv); } #endif - if (sigAlgo != rsa_sa_algo) { + if (args->sigAlgo != rsa_sa_algo) { WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); } - switch (hashAlgo) { - #ifndef NO_SHA256 + switch (args->hashAlgo) { case sha256_mac: + #ifndef NO_SHA256 typeH = SHA256h; ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #endif /* !NO_SHA256 */ break; - #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 case sha384_mac: + #ifdef WOLFSSL_SHA384 typeH = SHA384h; ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #endif /* WOLFSSL_SHA384 */ break; - #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 case sha512_mac: + #ifdef WOLFSSL_SHA512 typeH = SHA512h; ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #endif /* WOLFSSL_SHA512 */ break; - #endif /* WOLFSSL_SHA512 */ } /* switch */ - sigSz = wc_EncodeSignature(encodedSig, - ssl->buffers.digest.buffer, ssl->buffers.digest.length, - typeH); + args->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) { + if (args->sendSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, + min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) { ret = VERIFY_CERT_ERROR; } #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif } else { - if (sendSz != FINISHED_SZ || !output || XMEMCMP(output, + if (args->sendSz != FINISHED_SZ || !args->output || + XMEMCMP(args->output, &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) { ret = VERIFY_CERT_ERROR; } @@ -19468,57 +21297,41 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !NO_RSA */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { ssl->options.havePeerVerify = 1; /* Set final index */ - idx += sz; - *inOutIdx = idx; + args->idx += args->sz; + *inOutIdx = args->idx; /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ - case KEYSHARE_END: + case TLS_ASYNC_END: { break; } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dcv: WOLFSSL_LEAVE("DoCertificateVerify", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ 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; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -19527,6 +21340,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.digest.length = 0; /* Final cleanup */ + FreeDcvArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -19536,14 +21350,15 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int SendServerHelloDone(WOLFSSL* ssl) { - byte *output; - int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int ret; + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - #endif /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -19554,27 +21369,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddHeaders(output, 0, server_hello_done, ssl); - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return 0; - } + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return 0; + } - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif ret = HashOutput(ssl, output, sendSz, 0); if (ret != 0) return ret; -#ifdef WOLFSSL_CALLBACKS + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHelloDone", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz, ssl->heap); -#endif + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; ssl->buffers.outputBuffer.length += sendSz; @@ -19596,6 +21411,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte msecret[SECRET_LEN]; /* master secret */ word32 timestamp; /* born on */ word16 haveEMS; /* have extended master secret */ +#ifdef WOLFSSL_TLS13 + word32 ageAdd; /* Obfuscation of age */ + byte namedGroup; /* Named group used */ +#endif } InternalTicket; /* fit within SESSION_TICKET_LEN */ @@ -19609,7 +21428,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } ExternalTicket; /* create a new session ticket, 0 on success */ - static int CreateTicket(WOLFSSL* ssl) + int CreateTicket(WOLFSSL* ssl) { InternalTicket it; ExternalTicket* et = (ExternalTicket*)ssl->session.ticket; @@ -19626,9 +21445,25 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, it.suite[0] = ssl->options.cipherSuite0; it.suite[1] = ssl->options.cipherSuite; - XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); - c32toa(LowResTimer(), (byte*)&it.timestamp); - it.haveEMS = ssl->options.haveEMS; + if (!ssl->options.tls1_3) { + XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); + c32toa(LowResTimer(), (byte*)&it.timestamp); + it.haveEMS = ssl->options.haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Client adds to ticket age to obfuscate. */ + ret = wc_RNG_GenerateBlock(ssl->rng, (void*)&it.ageAdd, + sizeof(it.ageAdd)); + if (ret != 0) + return BAD_TICKET_ENCRYPT; + ssl->session.ticketAdd = it.ageAdd; + it.namedGroup = ssl->session.namedGroup; + it.timestamp = TimeNowInMilliseconds(); + /* Resumption master secret. */ + XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN); +#endif + } /* build external */ XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket)); @@ -19721,10 +21556,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* get master secret */ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { - XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); - /* Copy the haveExtendedMasterSecret property from the ticket to - * the saved session, so the property may be checked later. */ - ssl->session.haveEMS = it->haveEMS; + if (!IsAtLeastTLSv1_3(ssl->version)) { + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + /* Copy the haveExtendedMasterSecret property from the ticket to + * the saved session, so the property may be checked later. */ + ssl->session.haveEMS = it->haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Restore information to renegotiate. */ + ssl->session.ticketSeen = it->timestamp; + ssl->session.ticketAdd = it->ageAdd; + ssl->session.cipherSuite0 = it->suite[0]; + ssl->session.cipherSuite = it->suite[1]; + /* Resumption master secret. */ + XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN); + ssl->session.namedGroup = it->namedGroup; +#endif + } } return ret; @@ -19847,62 +21696,61 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_DTLS */ + typedef struct DckeArgs { + byte* output; /* not allocated */ + word32 length; + word32 idx; + word32 begin; + word32 sigSz; + } DckeArgs; + + static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs) + { + DckeArgs* args = (DckeArgs*)pArgs; + + (void)ssl; + (void)args; + } + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret; - word32 length = 0; - word32 idx = *inOutIdx, begin = *inOutIdx; - byte* output_lcl = NULL; - byte** output = &output_lcl; - - /* suppress possible compiler warnings */ - (void)input; - (void)size; - (void)length; - (void)idx; - (void)output; + int ret; + #ifdef WOLFSSL_ASYNC_CRYPT + DckeArgs* args = (DckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DckeArgs args[1]; + #endif WOLFSSL_ENTER("DoClientKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - /* use async pointer for output */ - output = &ssl->async.output; - - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); 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) { + if (ret < 0) goto exit_dcke; - } - else { - /* Restore variables needed for async */ - idx = ssl->async.idx; - length = ssl->async.length; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif /* WOLFSSL_ASYNC_CRYPT */ { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DckeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDckeArgs; + #endif } /* Do Client Key Exchange State Machine */ - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { /* Sanity checks */ if (ssl->options.side != WOLFSSL_SERVER_END) { @@ -19927,7 +21775,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) { if (!ssl->options.havePeerCert && - !ssl->options.usingPSK_cipher){ + !ssl->options.usingPSK_cipher) { WOLFSSL_MSG("client didn't present peer cert"); return NO_PEER_CERT; } @@ -19947,7 +21795,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_kea: { - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); } break; @@ -19967,7 +21817,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_NTRU case ntru_kea: { - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); } break; @@ -20018,10 +21870,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { switch (ssl->specs.kea) { #ifndef NO_RSA @@ -20030,29 +21883,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 i = 0; int keySz; - ssl->sigKey = XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_dcke); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dcke; } ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + &i, (RsaKey*)ssl->hsKey, ssl->buffers.key->length); if (ret != 0) { goto exit_dcke; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_dcke); } - length = (word32)keySz; + args->length = (word32)keySz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("Peer RSA key is too small"); @@ -20063,25 +21909,25 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.tls) { word16 check; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &check); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &check); + args->idx += OPAQUE16_LEN; - if ((word32)check != length) { + if ((word32)check != args->length) { WOLFSSL_MSG("RSA explicit size doesn't match"); ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); } } - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { WOLFSSL_MSG("RSA message too big"); ERROR_OUT(BUFFER_ERROR, exit_dcke); } - *output = NULL; + args->output = NULL; break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -20091,25 +21937,26 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte* pms = ssl->arrays->preMasterSecret; word16 ci_sz; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &ci_sz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &ci_sz); + args->idx += OPAQUE16_LEN; if (ci_sz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + ci_sz > size) { + if ((args->idx - args->begin) + ci_sz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - XMEMCPY(ssl->arrays->client_identity, input + idx, ci_sz); - idx += ci_sz; + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, ci_sz); + args->idx += ci_sz; - ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0; + ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, ssl->arrays->client_identity, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); @@ -20131,7 +21978,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + ssl->arrays->preMasterSz = + (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2); break; } #endif /* !NO_PSK */ @@ -20139,27 +21987,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ntru_kea: { word16 cipherLen; - word16 plainLen = sizeof(ssl->arrays->preMasterSecret); + word16 plainLen = ENCRYPT_LEN; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &cipherLen); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &cipherLen); + args->idx += OPAQUE16_LEN; if (cipherLen > MAX_NTRU_ENCRYPT_SZ) { ERROR_OUT(NTRU_KEY_ERROR, exit_dcke); } - if ((idx - begin) + cipherLen > size) { + if ((args->idx - args->begin) + cipherLen > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } if (NTRU_OK != ntru_crypto_ntru_decrypt( (word16) ssl->buffers.key->length, ssl->buffers.key->buffer, cipherLen, - input + idx, &plainLen, + input + args->idx, &plainLen, ssl->arrays->preMasterSecret)) { ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); } @@ -20168,7 +22016,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); } - idx += cipherLen; + args->idx += cipherLen; ssl->arrays->preMasterSz = plainLen; break; } @@ -20182,14 +22030,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->specs.static_ecdh) { word32 i = 0; - ssl->sigKey = XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_dcke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dcke; } @@ -20197,10 +22039,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = wc_EccPrivateKeyDecode( ssl->buffers.key->buffer, &i, - (ecc_key*)ssl->sigKey, + (ecc_key*)ssl->hsKey, ssl->buffers.key->length); if (ret == 0) { - private_key = (ecc_key*)ssl->sigKey; + private_key = (ecc_key*)ssl->hsKey; if (wc_ecc_size(private_key) < ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key too small"); @@ -20210,16 +22052,18 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* import peer ECC key */ - if ((idx - begin) + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - length = input[idx++]; + args->length = input[args->idx++]; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } + ssl->arrays->preMasterSz = ENCRYPT_LEN; + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -20235,14 +22079,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, 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_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dcke; } @@ -20256,12 +22094,16 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, private_key->dp->id)) { + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, private_key->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } ssl->peerEccKeyPresent = 1; + + if (ret != 0) { + goto exit_dcke; + } break; } #endif /* HAVE_ECC */ @@ -20270,18 +22112,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { word16 clientPubSz; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientPubSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientPubSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + clientPubSz > size) { + if ((args->idx - args->begin) + clientPubSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ssl->sigLen = clientPubSz; + args->sigSz = clientPubSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); break; } #endif /* !NO_DH */ @@ -20291,38 +22145,51 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 clientSz; /* Read in the PSK hint */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; if (clientSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - XMEMCPY(ssl->arrays->client_identity, input + idx, clientSz); - idx += clientSz; - ssl->arrays->client_identity[ - min(clientSz, MAX_PSK_ID_LEN-1)] = 0; + XMEMCPY(ssl->arrays->client_identity, input + args->idx, + clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ /* Read in the DHE business */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ssl->sigLen = clientSz; + args->sigSz = clientSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + break; } #endif /* !NO_DH && !NO_PSK */ @@ -20332,36 +22199,37 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 clientSz; /* Read in the PSK hint */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; if (clientSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } XMEMCPY(ssl->arrays->client_identity, - input + idx, clientSz); - idx += clientSz; - ssl->arrays->client_identity[ - min(clientSz, MAX_PSK_ID_LEN-1)] = 0; + input + args->idx, clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ /* import peer ECC key */ - if ((idx - begin) + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - length = input[idx++]; + args->length = input[args->idx++]; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } + args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN; + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -20376,14 +22244,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, 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_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dcke; } @@ -20397,9 +22259,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } } - - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, ssl->eccTempKey->dp->id)) { + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, ssl->eccTempKey->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } @@ -20417,21 +22278,23 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch (ssl->specs.kea) { #ifndef NO_RSA case rsa_kea: { + RsaKey* key = (RsaKey*)ssl->hsKey; ret = RsaDec(ssl, - input + idx, - length, - output, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + input + args->idx, + args->length, + &args->output, + &args->sigSz, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -20460,15 +22323,13 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { ecc_key* private_key = ssl->eccTempKey; if (ssl->specs.static_ecdh) { - private_key = (ecc_key*)ssl->sigKey; + private_key = (ecc_key*)ssl->hsKey; } - ssl->arrays->preMasterSz = ENCRYPT_LEN; - /* Generate shared secret */ ret = EccSharedSecret(ssl, private_key, ssl->peerEccKey, - input + idx, &length, + input + args->idx, &args->length, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, WOLFSSL_SERVER_END, @@ -20484,19 +22345,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #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, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientPubSz, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); break; @@ -20505,21 +22358,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #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, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientSz, - pms + OPAQUE16_LEN, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, &ssl->arrays->preMasterSz); break; } @@ -20527,14 +22371,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { - ssl->sigLen = ENCRYPT_LEN - OPAQUE16_LEN; - /* Generate shared secret */ ret = EccSharedSecret(ssl, ssl->eccTempKey, ssl->peerEccKey, - input + idx, &length, + input + args->idx, &args->length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->sigLen, + &args->sigSz, WOLFSSL_SERVER_END, #ifdef HAVE_PK_CALLBACKS ssl->EccSharedSecretCtx @@ -20555,20 +22397,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch (ssl->specs.kea) { #ifndef NO_RSA case rsa_kea: { /* Add the signature length to idx */ - idx += length; + args->idx += args->length; - if (ssl->sigLen == SECRET_LEN && *output != NULL) { - XMEMCPY(ssl->arrays->preMasterSecret, *output, SECRET_LEN); + if (args->sigSz == SECRET_LEN && args->output != NULL) { + XMEMCPY(ssl->arrays->preMasterSecret, args->output, SECRET_LEN); if (ssl->arrays->preMasterSecret[0] != ssl->chVersion.major || ssl->arrays->preMasterSecret[1] != ssl->chVersion.minor) { ERROR_OUT(PMS_VERSION_ERROR, exit_dcke); @@ -20596,15 +22439,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_diffie_hellman_kea: { /* skip past the imported peer key */ - idx += length; + args->idx += args->length; break; } #endif /* HAVE_ECC */ #ifndef NO_DH case diffie_hellman_kea: { - word16 clientPubSz = (word16)ssl->sigLen; - idx += clientPubSz; + args->idx += (word16)args->sigSz; break; } #endif /* !NO_DH */ @@ -20612,9 +22454,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case dhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; - word16 clientSz = ssl->sigLen; + word16 clientSz = (word16)args->sigSz; - idx += clientSz; + args->idx += clientSz; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -20633,8 +22475,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, 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; + 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 */ @@ -20642,13 +22486,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecdhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; /* skip past the imported peer key */ - idx += length; + args->idx += args->length; /* Add preMasterSecret */ - c16toa((word16)ssl->sigLen, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN + ssl->sigLen; + c16toa(clientSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN + clientSz; pms += ssl->arrays->preMasterSz; /* Use the PSK hint to look up the PSK and add it to the @@ -20681,29 +22526,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { #ifdef HAVE_QSH word16 name; if (ssl->options.haveQSH) { /* extension name */ - ato16(input + idx, &name); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; if (name == TLSX_QUANTUM_SAFE_HYBRID) { int qshSz; /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, - input + idx, - size - idx + begin, 1)) < 0) { + input + args->idx, + size - args->idx + args->begin, 1)) < 0) { ERROR_OUT(qshSz, exit_dcke); } - idx += qshSz; + args->idx += qshSz; } else { /* unknown extension sent client ignored handshake */ @@ -20719,13 +22565,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { /* Set final index */ - *inOutIdx = idx; + *inOutIdx = args->idx; ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; #ifndef NO_CERTS @@ -20734,36 +22581,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif break; - } /* KEYSHARE_END */ + } /* TLS_ASYNC_END */ default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dcke: WOLFSSL_LEAVE("DoClientKeyExchange", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ 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; - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_client_key_exchange = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -20772,14 +22605,15 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->arrays->preMasterSz = 0; /* Final cleanup */ + FreeDckeArgs(ssl, args); FreeKeyExchange(ssl); return ret; } -#ifdef HAVE_STUNNEL - static int SNI_Callback(WOLFSSL* ssl) +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + int SNI_Callback(WOLFSSL* ssl) { /* Stunnel supports a custom sni callback to switch an SSL's ctx * when SNI is received. Call it now if exists */ @@ -20794,9 +22628,85 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } return 0; } -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLGSSL_NGINX */ #endif /* NO_WOLFSSL_SERVER */ + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) +{ + int ret = 0; + WC_ASYNC_DEV* asyncDev; + WOLF_EVENT* event; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* check for pending async */ + asyncDev = ssl->async.dev; + if (asyncDev) { + /* grab event pointer */ + event = &asyncDev->event; + + ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL); + if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) { + + /* advance key share state if doesn't need called again */ + if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) { + (*state)++; + } + + /* clear event */ + XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT)); + + /* clear async dev */ + ssl->async.dev = NULL; + } + } + else { + ret = WC_NOT_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret); + + return ret; +} + +int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags) +{ + int ret; + WOLF_EVENT* event; + + if (ssl == NULL || asyncDev == NULL) { + return BAD_FUNC_ARG; + } + + /* grab event pointer */ + event = &asyncDev->event; + + /* init event */ + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags); + if (ret == 0) { + ssl->async.dev = asyncDev; + + /* place event into queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event); + } + + /* success means return WC_PENDING_E */ + if (ret == 0) { + ret = WC_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret); + + return ret; +} + +#endif /* WOLFSSL_ASYNC_CRYPT */ + + #undef ERROR_OUT #endif /* WOLFCRYPT_ONLY */ diff --git a/src/io.c b/src/io.c index bbfd971af1..8b9a9b960e 100644 --- a/src/io.c +++ b/src/io.c @@ -36,188 +36,30 @@ #include #include +#include + +#if defined(HAVE_HTTP_CLIENT) + #include /* atoi(), strtol() */ +#endif + +/* +Possible IO enable options: + * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off + allows user to define their own using + wolfSSL_SetIORecv and wolfSSL_SetIOSend + * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: off + * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off + (unless HAVE_OCSP or HAVE_CRL_IO defined) + * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off + */ /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove automatic setting of default I/O functions EmbedSend() and EmbedReceive() but they'll still need SetCallback xxx() at end of file */ -#ifndef WOLFSSL_USER_IO - -#ifdef HAVE_LIBZ - #include "zlib.h" -#endif - -#ifndef USE_WINDOWS_API - #ifdef WOLFSSL_LWIP - /* lwIP needs to be configured to use sockets API in this mode */ - /* LWIP_SOCKET 1 in lwip/opt.h or in build */ - #include "lwip/sockets.h" - #include - #ifndef LWIP_PROVIDE_ERRNO - #define LWIP_PROVIDE_ERRNO 1 - #endif - #elif defined(FREESCALE_MQX) - #include - #include - #elif defined(FREESCALE_KSDK_MQX) - #include - #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) - #if !defined(WOLFSSL_MDK_ARM) - #include "cmsis_os.h" - #include "rl_net.h" - #else - #include - #endif - #include "errno.h" - #define SOCKET_T int - #elif defined(WOLFSSL_TIRTOS) - #include - #elif defined(FREERTOS_TCP) - #include "FreeRTOS_Sockets.h" - #elif defined(WOLFSSL_IAR_ARM) - /* nothing */ - #elif defined(WOLFSSL_VXWORKS) - #include - #include - #elif defined(WOLFSSL_ATMEL) - #include "socket/include/socket.h" - #else - #include - #include - #ifndef EBSNET - #include - #endif - #include - - #if defined(HAVE_RTP_SYS) - #include - #elif defined(EBSNET) - #include "rtipapi.h" /* errno */ - #include "socket.h" - #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) - #include - #include - #include - #include - #ifdef __PPU - #include - #else - #include - #endif - #endif - #endif -#endif /* USE_WINDOWS_API */ - -#ifdef __sun - #include -#endif - -#ifdef USE_WINDOWS_API - /* no epipe yet */ - #ifndef WSAEPIPE - #define WSAEPIPE -12345 - #endif - #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK - #define SOCKET_EAGAIN WSAETIMEDOUT - #define SOCKET_ECONNRESET WSAECONNRESET - #define SOCKET_EINTR WSAEINTR - #define SOCKET_EPIPE WSAEPIPE - #define SOCKET_ECONNREFUSED WSAENOTCONN - #define SOCKET_ECONNABORTED WSAECONNABORTED - #define close(s) closesocket(s) -#elif defined(__PPU) - #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK - #define SOCKET_EAGAIN SYS_NET_EAGAIN - #define SOCKET_ECONNRESET SYS_NET_ECONNRESET - #define SOCKET_EINTR SYS_NET_EINTR - #define SOCKET_EPIPE SYS_NET_EPIPE - #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED - #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED -#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - #if MQX_USE_IO_OLD - /* RTCS old I/O doesn't have an EWOULDBLOCK */ - #define SOCKET_EWOULDBLOCK EAGAIN - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED - #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED - #else - #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK - #define SOCKET_EAGAIN NIO_EAGAIN - #define SOCKET_ECONNRESET NIO_ECONNRESET - #define SOCKET_EINTR NIO_EINTR - #define SOCKET_EPIPE NIO_EPIPE - #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED - #define SOCKET_ECONNABORTED NIO_ECONNABORTED - #endif -#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) - #if !defined(WOLFSSL_MDK_ARM) - #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK - #define SOCKET_EAGAIN BSD_ERROR_LOCKED - #define SOCKET_ECONNRESET BSD_ERROR_CLOSED - #define SOCKET_EINTR BSD_ERROR - #define SOCKET_EPIPE BSD_ERROR - #define SOCKET_ECONNREFUSED BSD_ERROR - #define SOCKET_ECONNABORTED BSD_ERROR - #else - #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK - #define SOCKET_EAGAIN SCK_ELOCKED - #define SOCKET_ECONNRESET SCK_ECLOSED - #define SOCKET_EINTR SCK_ERROR - #define SOCKET_EPIPE SCK_ERROR - #define SOCKET_ECONNREFUSED SCK_ERROR - #define SOCKET_ECONNABORTED SCK_ERROR - #endif -#elif defined(WOLFSSL_PICOTCP) - #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN - #define SOCKET_EAGAIN PICO_ERR_EAGAIN - #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET - #define SOCKET_EINTR PICO_ERR_EINTR - #define SOCKET_EPIPE PICO_ERR_EIO - #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED - #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN -#elif defined(FREERTOS_TCP) - #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK - #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK - #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR - #define SOCKET_EINTR FREERTOS_SOCKET_ERROR - #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR - #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR - #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR -#else - #define SOCKET_EWOULDBLOCK EWOULDBLOCK - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET ECONNRESET - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED ECONNREFUSED - #define SOCKET_ECONNABORTED ECONNABORTED -#endif /* USE_WINDOWS_API */ - - -#ifdef DEVKITPRO - /* from network.h */ - int net_send(int, const void*, int, unsigned int); - int net_recv(int, void*, int, unsigned int); - #define SEND_FUNCTION net_send - #define RECV_FUNCTION net_recv -#elif defined(WOLFSSL_LWIP) - #define SEND_FUNCTION lwip_send - #define RECV_FUNCTION lwip_recv -#elif defined(WOLFSSL_PICOTCP) - #define SEND_FUNCTION pico_send - #define RECV_FUNCTION pico_recv -#elif defined(FREERTOS_TCP) - #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) - #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) -#else - #define SEND_FUNCTION send - #define RECV_FUNCTION recv -#endif +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) /* Translates return codes returned from * send() and recv() if need be. @@ -257,14 +99,18 @@ static INLINE int LastError(void) #endif } +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#ifdef USE_WOLFSSL_IO + /* The receive embedded callback * return : nb bytes read, or error */ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) { - int recvd; - int err; int sd = *(int*)ctx; + int recvd; #ifdef WOLFSSL_DTLS { @@ -287,42 +133,39 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) } #endif - recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); - - recvd = TranslateReturnCode(recvd, sd); - + recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); if (recvd < 0) { - err = LastError(); + int err = LastError(); WOLFSSL_MSG("Embed Receive error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { - WOLFSSL_MSG(" Would block"); + WOLFSSL_MSG("\tWould block"); return WOLFSSL_CBIO_ERR_WANT_READ; } else { - WOLFSSL_MSG(" Socket timeout"); + WOLFSSL_MSG("\tSocket timeout"); return WOLFSSL_CBIO_ERR_TIMEOUT; } } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG(" Connection refused"); + WOLFSSL_MSG("\tConnection refused"); return WOLFSSL_CBIO_ERR_WANT_READ; } else if (err == SOCKET_ECONNABORTED) { - WOLFSSL_MSG(" Connection aborted"); + WOLFSSL_MSG("\tConnection aborted"); return WOLFSSL_CBIO_ERR_CONN_CLOSE; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -341,35 +184,30 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) { int sd = *(int*)ctx; int sent; - int len = sz; - int err; - - sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags); - - sent = TranslateReturnCode(sent, sd); + sent = wolfIO_Send(sd, buf, sz, ssl->wflags); if (sent < 0) { - err = LastError(); + int err = LastError(); WOLFSSL_MSG("Embed Send error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG(" Would Block"); + WOLFSSL_MSG("\tWould Block"); return WOLFSSL_CBIO_ERR_WANT_WRITE; } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG(" Socket EPIPE"); + WOLFSSL_MSG("\tSocket EPIPE"); return WOLFSSL_CBIO_ERR_CONN_CLOSE; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -382,12 +220,6 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) #include -#ifdef USE_WINDOWS_API - #define XSOCKLENT int -#else - #define XSOCKLENT socklen_t -#endif - #define SENDTO_FUNCTION sendto #define RECVFROM_FUNCTION recvfrom @@ -402,7 +234,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) int err; int sd = dtlsCtx->rfd; int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); - struct sockaddr_storage peer; + SOCKADDR_S peer; XSOCKLENT peerSz = sizeof(peer); WOLFSSL_ENTER("EmbedReceiveFrom()"); @@ -425,7 +257,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) } recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, - (struct sockaddr*)&peer, &peerSz); + (SOCKADDR*)&peer, &peerSz); recvd = TranslateReturnCode(recvd, sd); @@ -435,28 +267,28 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { if (wolfSSL_get_using_nonblock(ssl)) { - WOLFSSL_MSG(" Would block"); + WOLFSSL_MSG("\tWould block"); return WOLFSSL_CBIO_ERR_WANT_READ; } else { - WOLFSSL_MSG(" Socket timeout"); + WOLFSSL_MSG("\tSocket timeout"); return WOLFSSL_CBIO_ERR_TIMEOUT; } } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG(" Connection refused"); + WOLFSSL_MSG("\tConnection refused"); return WOLFSSL_CBIO_ERR_WANT_READ; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -464,7 +296,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) if (dtlsCtx->peer.sz > 0 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { - WOLFSSL_MSG(" Ignored packet from invalid peer"); + WOLFSSL_MSG("\tIgnored packet from invalid peer"); return WOLFSSL_CBIO_ERR_WANT_READ; } } @@ -487,7 +319,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedSendTo()"); sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, - (const struct sockaddr*)dtlsCtx->peer.sa, + (const SOCKADDR*)dtlsCtx->peer.sa, dtlsCtx->peer.sz); sent = TranslateReturnCode(sent, sd); @@ -497,23 +329,23 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) WOLFSSL_MSG("Embed Send To error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG(" Would Block"); + WOLFSSL_MSG("\tWould Block"); return WOLFSSL_CBIO_ERR_WANT_WRITE; } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG(" Socket EPIPE"); + WOLFSSL_MSG("\tSocket EPIPE"); return WOLFSSL_CBIO_ERR_CONN_CLOSE; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -528,7 +360,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) { int sd = ssl->wfd; - struct sockaddr_storage peer; + SOCKADDR_S peer; XSOCKLENT peerSz = sizeof(peer); byte digest[SHA_DIGEST_SIZE]; int ret = 0; @@ -536,7 +368,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) (void)ctx; XMEMSET(&peer, 0, sizeof(peer)); - if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) { + if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) { WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); return GEN_COOKIE_E; } @@ -553,29 +385,6 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) } #ifdef WOLFSSL_SESSION_EXPORT - #ifndef XINET_NTOP - #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) - #endif - #ifndef XINET_PTON - #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) - #endif - #ifndef XHTONS - #define XHTONS(a) htons((a)) - #endif - #ifndef XNTOHS - #define XNTOHS(a) ntohs((a)) - #endif - - #ifndef WOLFSSL_IP4 - #define WOLFSSL_IP4 AF_INET - #endif - #ifndef WOLFSSL_IP6 - #define WOLFSSL_IP6 AF_INET6 - #endif - - typedef struct sockaddr_storage SOCKADDR_S; - typedef struct sockaddr_in SOCKADDR_IN; - typedef struct sockaddr_in6 SOCKADDR_IN6; /* get the peer information in human readable form (ip, port, family) * default function assumes BSD sockets @@ -613,12 +422,14 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) break; case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), ip, *ipSz) == NULL) { WOLFSSL_MSG("XINET_NTOP error"); return SOCKET_ERROR_E; } *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); + #endif /* WOLFSSL_IPV6 */ break; default: @@ -665,6 +476,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) break; case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 if (XINET_PTON(addr.ss_family, ip, &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { WOLFSSL_MSG("XINET_PTON error"); @@ -678,6 +490,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) WOLFSSL_MSG("Import DTLS peer info error"); return ret; } + #endif /* WOLFSSL_IPV6 */ break; default: @@ -690,92 +503,184 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) #endif /* WOLFSSL_SESSION_EXPORT */ #endif /* WOLFSSL_DTLS */ -#ifdef HAVE_OCSP -#include /* atoi() */ +int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) +{ + int recvd; + recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags); + recvd = TranslateReturnCode(recvd, sd); + + return recvd; +} -static int Word16ToString(char* d, word16 number) +int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) { - int i = 0; + int sent; + int len = sz; - if (d != NULL) { - word16 order = 10000; - word16 digit; + sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, wrFlags); + sent = TranslateReturnCode(sent, sd); - if (number == 0) { - d[i++] = '0'; + return sent; +} + +#endif /* USE_WOLFSSL_IO */ + + +#ifdef HAVE_HTTP_CLIENT + +#ifndef HAVE_IO_TIMEOUT + #define io_timeout_sec 0 +#else + + #ifndef DEFAULT_TIMEOUT_SEC + #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */ + #endif + + static int io_timeout_sec = DEFAULT_TIMEOUT_SEC; + + void wolfIO_SetTimeout(int to_sec) + { + io_timeout_sec = to_sec; + } + + int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking) + { + int ret = 0; + + #ifdef USE_WINDOWS_API + unsigned long blocking = non_blocking; + ret = ioctlsocket(sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + ret = -1; + #else + ret = fcntl(sockfd, F_GETFL, 0); + if (ret >= 0) { + if (non_blocking) + ret |= O_NONBLOCK; + else + ret &= ~O_NONBLOCK; + ret = fcntl(sockfd, F_SETFL, ret); } - else { - while (order) { - digit = number / order; - if (i > 0 || digit != 0) { - d[i++] = (char)digit + '0'; - } - if (digit != 0) - number %= digit * order; - if (order > 1) - order /= 10; - else - order = 0; - } + #endif + if (ret < 0) { + WOLFSSL_MSG("wolfIO_SetBlockingMode failed"); + } + + return ret; + } + + #ifdef _MSC_VER + /* 4204: non-constant aggregate initializer (nfds = sockfd + 1) */ + #pragma warning(disable: 4204) + #endif + int wolfIO_Select(SOCKET_T sockfd, int to_sec) + { + fd_set fds; + SOCKET_T nfds = sockfd + 1; + struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; + int ret; + + FD_ZERO(&fds); + FD_SET(sockfd, &fds); + + ret = select(nfds, &fds, &fds, NULL, &timeout); + if (ret == 0) { + #ifdef DEBUG_HTTP + printf("Timeout: %d\n", ret); + #endif + return HTTP_TIMEOUT; + } + else if (ret > 0) { + if (FD_ISSET(sockfd, &fds)) + return 0; } - d[i] = 0; + return SOCKET_ERROR_E; } +#endif /* HAVE_IO_TIMEOUT */ + +static int wolfIO_Word16ToString(char* d, word16 number) +{ + int i = 0; + word16 order = 10000; + word16 digit; + + if (d == NULL) + return i; + + if (number == 0) + d[i++] = '0'; + else { + while (order) { + digit = number / order; + if (i > 0 || digit != 0) + d[i++] = (char)digit + '0'; + if (digit != 0) + number %= digit * order; + + order = (order > 1) ? order / 10 : 0; + } + } + d[i] = 0; /* null terminate */ return i; } - -static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) +int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) { - struct sockaddr_storage addr; - int sockaddr_len = sizeof(struct sockaddr_in); +#ifdef HAVE_SOCKADDR + int ret = 0; + SOCKADDR_S addr; + int sockaddr_len = sizeof(SOCKADDR_IN); +#ifdef HAVE_GETADDRINFO + ADDRINFO hints; + ADDRINFO* answer = NULL; + char strPort[6]; +#else + HOSTENT* entry; + SOCKADDR_IN *sin; +#endif + XMEMSET(&addr, 0, sizeof(addr)); - #ifdef HAVE_GETADDRINFO - { - struct addrinfo hints; - struct addrinfo* answer = NULL; - char strPort[6]; +#ifdef WOLFIO_DEBUG + printf("TCP Connect: %s:%d\n", ip, port); +#endif - XMEMSET(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; +#ifdef HAVE_GETADDRINFO + XMEMSET(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; - if (Word16ToString(strPort, port) == 0) { - WOLFSSL_MSG("invalid port number for OCSP responder"); - return -1; - } + if (wolfIO_Word16ToString(strPort, port) == 0) { + WOLFSSL_MSG("invalid port number for responder"); + return -1; + } - if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { - WOLFSSL_MSG("no addr info for OCSP responder"); - return -1; - } + if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { + WOLFSSL_MSG("no addr info for responder"); + return -1; + } - sockaddr_len = answer->ai_addrlen; - XMEMCPY(&addr, answer->ai_addr, sockaddr_len); - freeaddrinfo(answer); + sockaddr_len = answer->ai_addrlen; + XMEMCPY(&addr, answer->ai_addr, sockaddr_len); + freeaddrinfo(answer); +#else + entry = gethostbyname(ip); + sin = (SOCKADDR_IN *)&addr; + if (entry) { + sin->sin_family = AF_INET; + sin->sin_port = XHTONS(port); + XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); } - #else /* HAVE_GETADDRINFO */ - { - struct hostent* entry = gethostbyname(ip); - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; - - if (entry) { - sin->sin_family = AF_INET; - sin->sin_port = htons(port); - XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], - entry->h_length); - } - else { - WOLFSSL_MSG("no addr info for OCSP responder"); - return -1; - } + else { + WOLFSSL_MSG("no addr info for responder"); + return -1; } - #endif /* HAVE_GETADDRINFO */ +#endif *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); @@ -791,248 +696,427 @@ static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) } #endif - if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) { - WOLFSSL_MSG("OCSP responder tcp connect failed"); - return -1; +#ifdef HAVE_IO_TIMEOUT + /* if timeout value provided then set socket non-blocking */ + if (to_sec > 0) { + wolfIO_SetBlockingMode(*sockfd, 1); } +#else + (void)to_sec; +#endif - return 0; -} - - -static int build_http_request(const char* domainName, const char* path, - int ocspReqSz, byte* buf, int bufSize) -{ - word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen; - char ocspReqSzStr[6]; - - domainNameLen = (word32)XSTRLEN(domainName); - pathLen = (word32)XSTRLEN(path); - ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz); - - completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84; - if (completeLen > (word32)bufSize) - return 0; + ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len); +#ifdef HAVE_IO_TIMEOUT + if (ret != 0) { + if ((errno == EINPROGRESS) && (to_sec > 0)) { + /* wait for connect to complete */ + ret = wolfIO_Select(*sockfd, to_sec); - XSTRNCPY((char*)buf, "POST ", 5); - buf += 5; - XSTRNCPY((char*)buf, path, pathLen); - buf += pathLen; - XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17); - buf += 17; - XSTRNCPY((char*)buf, domainName, domainNameLen); - buf += domainNameLen; - XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18); - buf += 18; - XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen); - buf += ocspReqSzStrLen; - XSTRNCPY((char*)buf, - "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44); - - return completeLen; + /* restore blocking mode */ + wolfIO_SetBlockingMode(*sockfd, 0); + } + } +#endif + if (ret != 0) { + WOLFSSL_MSG("Responder tcp connect failed"); + return -1; + } + return ret; +#else + (void)sockfd; + (void)ip; + (void)port; + (void)to_sec; + return -1; +#endif /* HAVE_SOCKADDR */ } +#ifndef HTTP_SCRATCH_BUFFER_SIZE + #define HTTP_SCRATCH_BUFFER_SIZE 512 +#endif +#ifndef MAX_URL_ITEM_SIZE + #define MAX_URL_ITEM_SIZE 80 +#endif -static int decode_url(const char* url, int urlSz, - char* outName, char* outPath, word16* outPort) +int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath, + word16* outPort) { int result = -1; - if (outName != NULL && outPath != NULL && outPort != NULL) - { - if (url == NULL || urlSz == 0) - { + if (url == NULL || urlSz == 0) { + if (outName) *outName = 0; + if (outPath) *outPath = 0; + if (outPort) *outPort = 0; - } - else - { - int i, cur; - - /* need to break the url down into scheme, address, and port */ - /* "http://example.com:8080/" */ - /* "http://[::1]:443/" */ - if (XSTRNCMP(url, "http://", 7) == 0) { - cur = 7; - } else cur = 0; - - i = 0; - if (url[cur] == '[') { - cur++; - /* copy until ']' */ - while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { - outName[i++] = url[cur++]; - } - cur++; /* skip ']' */ + } + else { + int i, cur; + + /* need to break the url down into scheme, address, and port */ + /* "http://example.com:8080/" */ + /* "http://[::1]:443/" */ + if (XSTRNCMP(url, "http://", 7) == 0) { + cur = 7; + } else cur = 0; + + i = 0; + if (url[cur] == '[') { + cur++; + /* copy until ']' */ + while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { + if (outName) + outName[i] = url[cur]; + i++; cur++; } - else { - while (url[cur] != 0 && url[cur] != ':' && - url[cur] != '/' && cur < urlSz) { - outName[i++] = url[cur++]; - } + cur++; /* skip ']' */ + } + else { + while (url[cur] != 0 && url[cur] != ':' && + url[cur] != '/' && cur < urlSz) { + if (outName) + outName[i] = url[cur]; + i++; cur++; } + } + if (outName) outName[i] = 0; - /* Need to pick out the path after the domain name */ - - if (cur < urlSz && url[cur] == ':') { - char port[6]; - int j; - word32 bigPort = 0; - i = 0; - cur++; - while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && - i < 6) { - port[i++] = url[cur++]; - } + /* Need to pick out the path after the domain name */ - for (j = 0; j < i; j++) { - if (port[j] < '0' || port[j] > '9') return -1; - bigPort = (bigPort * 10) + (port[j] - '0'); - } - *outPort = (word16)bigPort; + if (cur < urlSz && url[cur] == ':') { + char port[6]; + int j; + word32 bigPort = 0; + i = 0; + cur++; + while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && + i < 6) { + port[i++] = url[cur++]; } - else - *outPort = 80; - if (cur < urlSz && url[cur] == '/') { - i = 0; - while (cur < urlSz && url[cur] != 0 && i < 80) { - outPath[i++] = url[cur++]; - } - outPath[i] = 0; + for (j = 0; j < i; j++) { + if (port[j] < '0' || port[j] > '9') return -1; + bigPort = (bigPort * 10) + (port[j] - '0'); } - else { - outPath[0] = '/'; - outPath[1] = 0; + if (outPort) + *outPort = (word16)bigPort; + } + else if (outPort) + *outPort = 80; + + + if (cur < urlSz && url[cur] == '/') { + i = 0; + while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) { + if (outPath) + outPath[i] = url[cur]; + i++; cur++; } - result = 0; + if (outPath) + outPath[i] = 0; } + else if (outPath) { + outPath[0] = '/'; + outPath[1] = 0; + } + + result = 0; } return result; } +static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz, + int chunkSz, char* start, int len, int dynType, void* heap) +{ + byte* newRecvBuf = NULL; + int newRecvSz = *recvBufSz + chunkSz; + int pos = 0; -/* return: >0 OCSP Response Size - * -1 error */ -static int process_http_response(int sfd, byte** respBuf, - byte* httpBuf, int httpBufSz, void* heap) + WOLFSSL_MSG("Processing HTTP response"); +#ifdef WOLFIO_DEBUG + printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz); +#endif + + newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType); + if (newRecvBuf == NULL) { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed"); + return MEMORY_E; + } + + /* if buffer already exists, then we are growing it */ + if (*recvBuf) { + XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz); + XFREE(*recvBuf, heap, dynType); + pos += *recvBufSz; + *recvBuf = NULL; + } + + /* copy the remainder of the httpBuf into the respBuf */ + if (len != 0) { + XMEMCPY(&newRecvBuf[pos], start, len); + pos += len; + } + + /* receive the remainder of chunk */ + while (len < chunkSz) { + int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0); + if (rxSz > 0) { + len += rxSz; + pos += rxSz; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed"); + XFREE(newRecvBuf, heap, dynType); + return -1; + } + } + + *recvBuf = newRecvBuf; + *recvBufSz = newRecvSz; + + return 0; +} + +int wolfIO_HttpProcessResponse(int sfd, const char* appStr, + byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap) { - int result; + int result = 0; int len = 0; char *start, *end; - byte *recvBuf = NULL; - int recvBufSz = 0; - enum phr_state { phr_init, phr_http_start, phr_have_length, - phr_have_type, phr_wait_end, phr_http_end + int respBufSz = 0; + int isChunked = 0, chunkSz = 0; + enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, + phr_wait_end, phr_get_chunk_len, phr_get_chunk_data, + phr_http_end } state = phr_init; + *respBuf = NULL; start = end = NULL; do { + if (state == phr_get_chunk_data) { + /* get chunk of data */ + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, + chunkSz, start, len, dynType, heap); + + state = (result != 0) ? phr_http_end : phr_get_chunk_len; + end = NULL; + len = 0; + } + + /* read data if no \r\n or first time */ if (end == NULL) { - result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); + result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); if (result > 0) { len += result; start = (char*)httpBuf; start[len] = 0; } else { - WOLFSSL_MSG("process_http_response recv http from peer failed"); + WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed"); return -1; } } - end = XSTRSTR(start, "\r\n"); + end = XSTRSTR(start, "\r\n"); /* locate end */ + /* handle incomplete rx */ if (end == NULL) { if (len != 0) XMEMMOVE(httpBuf, start, len); start = end = NULL; } + /* when start is "\r\n" */ else if (end == start) { - if (state == phr_wait_end) { - state = phr_http_end; - len -= 2; - start += 2; + /* if waiting for end or need chunk len */ + if (state == phr_wait_end || state == phr_get_chunk_len) { + state = (isChunked) ? phr_get_chunk_len : phr_http_end; + len -= 2; start += 2; /* skip \r\n */ } else { - WOLFSSL_MSG("process_http_response header ended early"); + WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early"); return -1; } } else { - *end = 0; + *end = 0; /* null terminate */ len -= (int)(end - start) + 2; /* adjust len to remove the first line including the /r/n */ - if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { - start += 9; - if (XSTRNCASECMP(start, "200 OK", 6) != 0 || - state != phr_init) { - WOLFSSL_MSG("process_http_response not OK"); - return -1; - } - state = phr_http_start; - } - else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { - start += 13; - while (*start == ' ' && *start != '\0') start++; - if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { - WOLFSSL_MSG("process_http_response not ocsp-response"); - return -1; - } - - if (state == phr_http_start) state = phr_have_type; - else if (state == phr_have_length) state = phr_wait_end; - else { - WOLFSSL_MSG("process_http_response type invalid state"); - return -1; - } - } - else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { - start += 15; - while (*start == ' ' && *start != '\0') start++; - recvBufSz = atoi(start); - - if (state == phr_http_start) state = phr_have_length; - else if (state == phr_have_type) state = phr_wait_end; - else { - WOLFSSL_MSG("process_http_response length invalid state"); - return -1; - } - } + #ifdef WOLFIO_DEBUG + printf("HTTP Resp: %s\n", start); + #endif + switch (state) { + case phr_init: + if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { + start += 9; + if (XSTRNCASECMP(start, "200 OK", 6) != 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK"); + return -1; + } + state = phr_http_start; + } + break; + case phr_http_start: + case phr_have_length: + case phr_have_type: + if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { + start += 13; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, appStr, XSTRLEN(appStr)) != 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch"); + return -1; + } + state = (state == phr_http_start) ? phr_have_type : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { + start += 15; + while (*start == ' ' && *start != '\0') start++; + chunkSz = atoi(start); + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) { + start += 18; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, "chunked", 7) == 0) { + isChunked = 1; + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + } + break; + case phr_get_chunk_len: + chunkSz = (int)strtol(start, NULL, 16); /* hex format */ + state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data; + break; + case phr_get_chunk_data: + /* processing for chunk data done above, since \r\n isn't required */ + case phr_wait_end: + case phr_http_end: + /* do nothing */ + break; + } /* switch (state) */ + + /* skip to end plus \r\n */ start = end + 2; } } while (state != phr_http_end); - recvBuf = (byte*)XMALLOC(recvBufSz, heap, DYNAMIC_TYPE_OCSP); - if (recvBuf == NULL) { - WOLFSSL_MSG("process_http_response couldn't create response buffer"); - return -1; + if (!isChunked) { + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz, + start, len, dynType, heap); } - /* copy the remainder of the httpBuf into the respBuf */ - if (len != 0) - XMEMCPY(recvBuf, start, len); - - /* receive the OCSP response data */ - while (len < recvBufSz) { - result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0); - if (result > 0) - len += result; - else { - WOLFSSL_MSG("process_http_response recv ocsp from peer failed"); - return -1; - } + if (result >= 0) { + result = respBufSz; + } + else { + WOLFSSL_ERROR(result); } - *respBuf = recvBuf; - return recvBufSz; + return result; } +int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName, + const char* path, int pathLen, int reqSz, const char* contentType, + byte* buf, int bufSize) +{ + word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen; + char reqSzStr[6]; + char* req = (char*)buf; + const char* blankStr = " "; + const char* http11Str = " HTTP/1.1"; + const char* hostStr = "\r\nHost: "; + const char* contentLenStr = "\r\nContent-Length: "; + const char* contentTypeStr = "\r\nContent-Type: "; + const char* doubleCrLfStr = "\r\n\r\n"; + word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen, + contentTypeStrLen, doubleCrLfStrLen; + + reqTypeLen = (word32)XSTRLEN(reqType); + domainNameLen = (word32)XSTRLEN(domainName); + reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz); + contentTypeLen = (word32)XSTRLEN(contentType); + + blankStrLen = (word32)XSTRLEN(blankStr); + http11StrLen = (word32)XSTRLEN(http11Str); + hostStrLen = (word32)XSTRLEN(hostStr); + contentLenStrLen = (word32)XSTRLEN(contentLenStr); + contentTypeStrLen = (word32)XSTRLEN(contentTypeStr); + doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr); + + /* determine max length and check it */ + maxLen = + reqTypeLen + + blankStrLen + + pathLen + + http11StrLen + + hostStrLen + + domainNameLen + + contentLenStrLen + + reqSzStrLen + + contentTypeStrLen + + contentTypeLen + + doubleCrLfStrLen + + 1 /* null term */; + if (maxLen > (word32)bufSize) + return 0; + + XSTRNCPY((char*)buf, reqType, reqTypeLen); + buf += reqTypeLen; + XSTRNCPY((char*)buf, blankStr, blankStrLen+1); + buf += blankStrLen; + XSTRNCPY((char*)buf, path, pathLen); + buf += pathLen; + XSTRNCPY((char*)buf, http11Str, http11StrLen+1); + buf += http11StrLen; + if (domainNameLen > 0) { + XSTRNCPY((char*)buf, hostStr, hostStrLen+1); + buf += hostStrLen; + XSTRNCPY((char*)buf, domainName, domainNameLen); + buf += domainNameLen; + } + if (reqSz > 0 && reqSzStrLen > 0) { + XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1); + buf += contentLenStrLen; + XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen); + buf += reqSzStrLen; + } + if (contentTypeLen > 0) { + XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1); + buf += contentTypeStrLen; + XSTRNCPY((char*)buf, contentType, contentTypeLen); + buf += contentTypeLen; + } + XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1); + buf += doubleCrLfStrLen; -#define SCRATCH_BUFFER_SIZE 512 +#ifdef WOLFIO_DEBUG + printf("HTTP %s: %s", reqType, req); +#endif + + /* calculate actual length based on original and new pointer */ + return (int)((char*)buf - req); +} + + +#ifdef HAVE_OCSP + +int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path, + int ocspReqSz, byte* buf, int bufSize) +{ + return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path), + ocspReqSz, "application/ocsp-request", buf, bufSize); +} + +/* return: >0 OCSP Response Size + * -1 error */ +int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf, + byte* httpBuf, int httpBufSz, void* heap) +{ + return wolfIO_HttpProcessResponse(sfd, "application/ocsp-response", + respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap); +} /* in default wolfSSL callback ctx is the heap pointer */ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, @@ -1045,19 +1129,19 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, char* path; char* domainName; #else - char path[80]; - char domainName[80]; + char path[MAX_URL_ITEM_SIZE]; + char domainName[MAX_URL_ITEM_SIZE]; #endif #ifdef WOLFSSL_SMALL_STACK - path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); + path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (path == NULL) - return -1; + return MEMORY_E; - domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (domainName == NULL) { XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return -1; + return MEMORY_E; } #endif @@ -1067,37 +1151,37 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, else if (ocspRespBuf == NULL) { WOLFSSL_MSG("Cannot save OCSP response"); } - else if (decode_url(url, urlSz, domainName, path, &port) < 0) { + else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) { WOLFSSL_MSG("Unable to decode OCSP URL"); } else { /* Note, the library uses the EmbedOcspRespFree() callback to * free this buffer. */ - int httpBufSz = SCRATCH_BUFFER_SIZE; - byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, - DYNAMIC_TYPE_OCSP); + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP); if (httpBuf == NULL) { WOLFSSL_MSG("Unable to create OCSP response buffer"); } else { - httpBufSz = build_http_request(domainName, path, ocspReqSz, + httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz, httpBuf, httpBufSz); - if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) { + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd <= 0)) { WOLFSSL_MSG("OCSP Responder connection failed"); } - else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) != + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != httpBufSz) { WOLFSSL_MSG("OCSP http request failed"); } - else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != + else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != ocspReqSz) { WOLFSSL_MSG("OCSP ocsp request failed"); } else { - ret = process_http_response(sfd, ocspRespBuf, httpBuf, - SCRATCH_BUFFER_SIZE, ctx); + ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE, ctx); } close(sfd); @@ -1113,7 +1197,6 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, return ret; } - /* in default callback ctx is heap hint */ void EmbedOcspRespFree(void* ctx, byte *resp) { @@ -1122,11 +1205,96 @@ void EmbedOcspRespFree(void* ctx, byte *resp) (void)ctx; } +#endif /* HAVE_OCSP */ + +#if defined(HAVE_CRL) && defined(HAVE_CRL_IO) + +int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, byte* buf, int bufSize) +{ + return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "", + buf, bufSize); +} + +int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf, + int httpBufSz) +{ + int result; + byte *respBuf = NULL; + + result = wolfIO_HttpProcessResponse(sfd, "application/pkix-crl", + &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap); + if (result >= 0) { + result = BufferLoadCRL(crl, respBuf, result, SSL_FILETYPE_ASN1, 0); + } + XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL); + + return result; +} +int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) +{ + SOCKET_T sfd = 0; + word16 port; + int ret = -1; +#ifdef WOLFSSL_SMALL_STACK + char* domainName; +#else + char domainName[MAX_URL_ITEM_SIZE]; #endif -#endif /* WOLFSSL_USER_IO */ +#ifdef WOLFSSL_SMALL_STACK + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + return MEMORY_E; + } +#endif + + if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) { + WOLFSSL_MSG("Unable to decode CRL URL"); + } + else { + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap, + DYNAMIC_TYPE_CRL); + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create CRL response buffer"); + } + else { + httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName, + httpBuf, httpBufSz); + + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd <= 0)) { + WOLFSSL_MSG("CRL connection failed"); + } + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) + != httpBufSz) { + WOLFSSL_MSG("CRL http get failed"); + } + else { + ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE); + } + + close(sfd); + XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* HAVE_CRL && HAVE_CRL_IO */ + +#endif /* HAVE_HTTP_CLIENT */ + + WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) { @@ -1328,5 +1496,5 @@ void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) } #endif /* HAVE_NETX */ -#endif /* WOLFCRYPT_ONLY */ +#endif /* WOLFCRYPT_ONLY */ diff --git a/src/keys.c b/src/keys.c index a1095b1eb5..92b03d6510 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1053,8 +1053,109 @@ int SetCipherSpecs(WOLFSSL* ssl) return UNSUPPORTED_SUITE; } /* switch */ } /* if */ - if (ssl->options.cipherSuite0 != ECC_BYTE && - ssl->options.cipherSuite0 != CHACHA_BYTE) { /* normal suites */ + + /* TLSi v1.3 cipher suites, 0x13 */ + if (ssl->options.cipherSuite0 == TLS13_BYTE) { + switch (ssl->options.cipherSuite) { + +#ifdef WOLFSSL_TLS13 + #ifdef BUILD_TLS_AES_128_GCM_SHA256 + case TLS_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_256_GCM_SHA384 + case TLS_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + case TLS_CHACHA20_POLY1305_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_SHA256 + case TLS_AES_128_CCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + case TLS_AES_128_CCM_8_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; + #endif +#endif /* WOLFSSL_TLS13 */ + } + } + + if (ssl->options.cipherSuite0 != ECC_BYTE && + ssl->options.cipherSuite0 != CHACHA_BYTE && + ssl->options.cipherSuite0 != TLS13_BYTE) { /* normal suites */ switch (ssl->options.cipherSuite) { #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA @@ -1653,7 +1754,7 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif - + #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA case TLS_RSA_WITH_HC_128_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; @@ -1667,7 +1768,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; - + break; #endif @@ -1684,7 +1785,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; - + break; #endif @@ -1701,7 +1802,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - + break; #endif @@ -1718,7 +1819,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - + break; #endif @@ -1827,7 +1928,7 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif - + #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; @@ -1978,7 +2079,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = IDEA_KEY_SIZE; ssl->specs.block_size = IDEA_BLOCK_SIZE; ssl->specs.iv_size = IDEA_IV_SIZE; - + break; #endif @@ -1993,8 +2094,11 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifndef NO_TLS ssl->options.tls = 1; ssl->hmac = TLS_hmac; - if (ssl->version.minor >= 2) + if (ssl->version.minor >= 2) { ssl->options.tls1_1 = 1; + if (ssl->version.minor >= 4) + ssl->options.tls1_3 = 1; + } #endif } @@ -2049,7 +2153,7 @@ static int SetPrefix(byte* sha_input, int idx) break; default: WOLFSSL_MSG("Set Prefix error, bad input"); - return 0; + return 0; } return 1; } @@ -2070,22 +2174,20 @@ 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 WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_Arc4AsyncInit(enc->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + + if (enc) { + if (wc_Arc4Init(enc->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; } - if (dec) { - if (wc_Arc4AsyncInit(dec->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + } + if (dec) { + if (wc_Arc4Init(dec->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (side == WOLFSSL_CLIENT_END) { if (enc) wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz); @@ -2103,9 +2205,9 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_ARC4 */ + - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) /* Check that the max implicit iv size is suffecient */ #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */ @@ -2165,7 +2267,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ + #ifdef HAVE_HC128 /* check that buffer sizes are sufficient */ @@ -2214,8 +2317,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif - +#endif /* HAVE_HC128 */ + #ifdef BUILD_RABBIT /* check that buffer sizes are sufficient */ #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */ @@ -2263,8 +2366,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif - +#endif /* BUILD_RABBIT */ + #ifdef BUILD_DES3 /* check that buffer sizes are sufficient */ #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */ @@ -2274,30 +2377,34 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_triple_des) { int desRet = 0; - if (enc && enc->des3 == NULL) - enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->des3 == NULL) - return MEMORY_E; - if (dec && dec->des3 == NULL) - dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->des3 == NULL) - return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_Des3AsyncInit(enc->des3, devId) != 0) { - WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + if (enc) { + if (enc->des3 == NULL) + enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (enc->des3 == NULL) + return MEMORY_E; + XMEMSET(enc->des3, 0, sizeof(Des3)); + } + if (dec) { + if (dec->des3 == NULL) + dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (dec->des3 == NULL) + return MEMORY_E; + XMEMSET(dec->des3, 0, sizeof(Des3)); + } + + if (enc) { + if (wc_Des3Init(enc->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; } - if (dec) { - if (wc_Des3AsyncInit(dec->des3, devId) != 0) { - WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + } + if (dec) { + if (wc_Des3Init(dec->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (side == WOLFSSL_CLIENT_END) { if (enc) { desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key, @@ -2327,7 +2434,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_DES3 */ #ifdef BUILD_AES /* check that buffer sizes are sufficient */ @@ -2338,30 +2445,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes) { int aesRet = 0; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_AesAsyncInit(enc->aes, devId) != 0) { - WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; } - if (dec) { - if (wc_AesAsyncInit(dec->aes, devId) != 0) { - WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (side == WOLFSSL_CLIENT_END) { if (enc) { aesRet = wc_AesSetKey(enc->aes, keys->client_write_key, @@ -2395,7 +2505,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_AES */ #ifdef BUILD_AESGCM /* check that buffer sizes are sufficient */ @@ -2412,14 +2522,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) { int gcmRet; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } if (side == WOLFSSL_CLIENT_END) { if (enc) { @@ -2427,14 +2556,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2443,14 +2572,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2458,7 +2587,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_AESGCM */ #ifdef HAVE_AESCCM /* check that buffer sizes are sufficient (CCM is same size as GCM) */ @@ -2475,14 +2604,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) { int CcmRet; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } if (side == WOLFSSL_CLIENT_END) { if (enc) { @@ -2529,7 +2677,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_AESCCM */ #ifdef HAVE_CAMELLIA /* check that buffer sizes are sufficient */ @@ -2581,7 +2729,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_CAMELLIA */ #ifdef HAVE_IDEA /* check that buffer sizes are sufficient */ @@ -2635,7 +2783,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_IDEA */ #ifdef HAVE_NULL_CIPHER if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) { @@ -2681,6 +2829,7 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, if (authentication) authentication->setup = 1; #endif + (void)authentication; (void)heap; (void)keys; (void)specs; @@ -2690,6 +2839,40 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, } #endif /* HAVE_ONE_TIME_AUTH */ +#ifdef HAVE_SECURE_RENEGOTIATION +/* function name is for cache_status++ + * This function was added because of error incrementing enum type when + * compiling with a C++ compiler. + */ +static void CacheStatusPP(SecureRenegotiation* cache) +{ + switch (cache->cache_status) { + case SCR_CACHE_NULL: + cache->cache_status = SCR_CACHE_NEEDED; + break; + + case SCR_CACHE_NEEDED: + cache->cache_status = SCR_CACHE_COPY; + break; + + case SCR_CACHE_COPY: + cache->cache_status = SCR_CACHE_PARTIAL; + break; + + case SCR_CACHE_PARTIAL: + cache->cache_status = SCR_CACHE_COMPLETE; + break; + + case SCR_CACHE_COMPLETE: + WOLFSSL_MSG("SCR Cache state Complete"); + break; + + default: + WOLFSSL_MSG("Unknown cache state!!"); + } +} +#endif /* HAVE_SECURE_RENEGOTIATION */ + /* Set wc_encrypt/wc_decrypt or both sides of key setup * note: use wc_encrypt to avoid shadowing global encrypt @@ -2804,7 +2987,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) } #endif } - ssl->secure_renegotiation->cache_status++; + CacheStatusPP(ssl->secure_renegotiation); } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -2822,7 +3005,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status == SCR_CACHE_NEEDED) { keys = &ssl->secure_renegotiation->tmp_keys; - ssl->secure_renegotiation->cache_status++; + CacheStatusPP(ssl->secure_renegotiation); } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -2857,12 +3040,12 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) #ifndef NO_OLD_TLS int DeriveKeys(WOLFSSL* ssl) { - int length = 2 * ssl->specs.hash_size + + int length = 2 * ssl->specs.hash_size + 2 * ssl->specs.key_size + 2 * ssl->specs.iv_size; int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i; int ret = 0; - + #ifdef WOLFSSL_SMALL_STACK byte* shaOutput; byte* md5Input; @@ -2878,9 +3061,9 @@ int DeriveKeys(WOLFSSL* ssl) Md5 md5[1]; Sha sha[1]; #endif - + #ifdef WOLFSSL_SMALL_STACK - shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, + shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); md5Input = (byte*)XMALLOC(SECRET_LEN + SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2890,7 +3073,7 @@ int DeriveKeys(WOLFSSL* ssl) NULL, DYNAMIC_TYPE_TMP_BUFFER); md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || keyData == NULL || md5 == NULL || sha == NULL) { if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2899,15 +3082,15 @@ int DeriveKeys(WOLFSSL* ssl) if (keyData) XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + return MEMORY_E; } #endif - wc_InitMd5(md5); - - ret = wc_InitSha(sha); - + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } if (ret == 0) { XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN); @@ -2925,14 +3108,21 @@ int DeriveKeys(WOLFSSL* ssl) XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); idx += RAN_LEN; XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN); - - wc_ShaUpdate(sha, shaInput, (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - - KEY_PREFIX + j); - wc_ShaFinal(sha, shaOutput); + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, + (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } XMEMCPY(md5Input + SECRET_LEN, shaOutput, SHA_DIGEST_SIZE); - wc_Md5Update(md5, md5Input, SECRET_LEN + SHA_DIGEST_SIZE); - wc_Md5Final(md5, keyData + i * MD5_DIGEST_SIZE); + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, SECRET_LEN + SHA_DIGEST_SIZE); + } + if (ret == 0) { + ret = wc_Md5Final(md5, keyData + i * MD5_DIGEST_SIZE); + } } if (ret == 0) @@ -3010,7 +3200,7 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) NULL, DYNAMIC_TYPE_TMP_BUFFER); md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || md5 == NULL || sha == NULL) { if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3018,15 +3208,15 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + return MEMORY_E; } #endif - wc_InitMd5(md5); - - ret = wc_InitSha(sha); - + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } if (ret == 0) { XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz); @@ -3047,14 +3237,22 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) idx += RAN_LEN; XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); idx += RAN_LEN; - wc_ShaUpdate(sha, shaInput, idx); - wc_ShaFinal(sha, shaOutput); - + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, idx); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } idx = pmsSz; /* preSz */ XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE); idx += SHA_DIGEST_SIZE; - wc_Md5Update(md5, md5Input, idx); - wc_Md5Final(md5, &ssl->arrays->masterSecret[i * MD5_DIGEST_SIZE]); + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, idx); + } + if (ret == 0) { + ret = wc_Md5Final(md5, + &ssl->arrays->masterSecret[i * MD5_DIGEST_SIZE]); + } } #ifdef SHOW_SECRETS diff --git a/src/ocsp.c b/src/ocsp.c index e8de3d5124..ae45322ed5 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -110,9 +110,9 @@ void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) } -static int xstat2err(int stat) +static int xstat2err(int st) { - switch (stat) { + switch (st) { case CERT_GOOD: return 0; case CERT_REVOKED: @@ -219,9 +219,11 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, ret = OCSP_INVALID_STATUS; } else if (*status) { +#ifndef NO_ASN_TIME if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE) && ((*status)->nextDate[0] != 0) && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER)) +#endif { ret = xstat2err((*status)->status); @@ -244,6 +246,134 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, return ret; } +/* Check that the response for validity. Store result in status. + * + * ocsp Context object for OCSP status. + * response OCSP response message data. + * responseSz Length of OCSP response message data. + * reponseBuffer Buffer object to return the response with. + * status The certificate status object. + * entry The OCSP entry for this certificate. + * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. + */ +static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz, + buffer* responseBuffer, CertStatus* status, + OcspEntry* entry, OcspRequest* ocspRequest) +{ +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + int ret; + int validated = 0; /* ocsp validation flag */ + +#ifdef WOLFSSL_SMALL_STACK + newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (newStatus == NULL || ocspResponse == NULL) { + if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + XMEMSET(newStatus, 0, sizeof(CertStatus)); + + InitOcspResponse(ocspResponse, newStatus, response, responseSz); + ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); + if (ret != 0) { + WOLFSSL_MSG("OcspResponseDecode failed"); + goto end; + } + + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { + WOLFSSL_MSG("OcspResponse status bad"); + goto end; + } + if (ocspRequest != NULL) { + ret = CompareOcspReqResp(ocspRequest, ocspResponse); + if (ret != 0) { + goto end; + } + } + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = responseSz; + XMEMCPY(responseBuffer->buffer, response, responseSz); + } + } + + ret = xstat2err(ocspResponse->status->status); + if (ret == 0) { + validated = 1; + } + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + ret = BAD_MUTEX_E; + goto end; + } + + if (status != NULL) { + if (status->rawOcspResponse) { + XFREE(status->rawOcspResponse, ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + } + + /* Replace existing certificate entry with updated */ + XMEMCPY(status, newStatus, sizeof(CertStatus)); + } + else { + /* Save new certificate entry */ + status = (CertStatus*)XMALLOC(sizeof(CertStatus), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (status != NULL) { + XMEMCPY(status, newStatus, sizeof(CertStatus)); + status->next = entry->status; + entry->status = status; + entry->totalStatus++; + } + } + + if (status && responseBuffer && responseBuffer->buffer) { + status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, + ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + + if (status->rawOcspResponse) { + status->rawOcspResponseSz = responseBuffer->length; + XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, + responseBuffer->length); + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + +end: + if (ret == 0 && validated == 1) { + WOLFSSL_MSG("New OcspResponse validated"); + } else if (ret != OCSP_CERT_REVOKED) { + ret = OCSP_LOOKUP_FAIL; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + +/* 0 on success */ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, buffer* responseBuffer) { @@ -251,19 +381,12 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, CertStatus* status = NULL; byte* request = NULL; int requestSz = 2048; + int responseSz = 0; byte* response = NULL; const char* url = NULL; int urlSz = 0; int ret = -1; -#ifdef WOLFSSL_SMALL_STACK - CertStatus* newStatus; - OcspResponse* ocspResponse; -#else - CertStatus newStatus[1]; - OcspResponse ocspResponse[1]; -#endif - WOLFSSL_ENTER("CheckOcspRequest"); if (responseBuffer) { @@ -279,6 +402,22 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, if (ret != OCSP_INVALID_STATUS) return ret; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ocsp->statusCb != NULL && ocspRequest->ssl != NULL) { + ret = ocsp->statusCb((WOLFSSL*)ocspRequest->ssl, ocsp->cm->ocspIOCtx); + if (ret == 0) { + ret = wolfSSL_get_ocsp_response((WOLFSSL*)ocspRequest->ssl, + &response); + ret = CheckResponse(ocsp, response, ret, responseBuffer, status, + entry, NULL); + if (response != NULL) + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + return ret; + } + return OCSP_LOOKUP_FAIL; + } +#endif + if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') @@ -301,110 +440,392 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return MEMORY_ERROR; } -#ifdef WOLFSSL_SMALL_STACK - newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (newStatus == NULL || ocspResponse == NULL) { - if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); + if (requestSz > 0 && ocsp->cm->ocspIOCb) { + responseSz = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, + request, requestSz, &response); + } - XFREE(request, NULL, DYNAMIC_TYPE_OCSP); + XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_E; + if (responseSz >= 0 && response) { + ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); } -#endif - requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); + if (response != NULL && ocsp->cm->ocspRespFreeCb) + ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); - if (ocsp->cm->ocspIOCb) - ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, - request, requestSz, &response); + WOLFSSL_LEAVE("CheckOcspRequest", ret); + return ret; +} - if (ret >= 0 && response) { - XMEMSET(newStatus, 0, sizeof(CertStatus)); +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - InitOcspResponse(ocspResponse, newStatus, response, ret); - OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap); +int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd) +{ + if (bs == NULL || id == NULL) + return SSL_FAILURE; + + /* Only supporting one certificate status in asn.c. */ + if (CompareOcspReqResp(id, bs) != 0) + return SSL_FAILURE; + + if (status != NULL) + *status = bs->status->status; + if (thisupd != NULL) + *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn; + if (nextupd != NULL) + *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn; + + /* TODO: Not needed for Nginx. */ + if (reason != NULL) + *reason = 0; + if (revtime != NULL) + *revtime = NULL; + + return SSL_SUCCESS; +} - if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) - ret = OCSP_LOOKUP_FAIL; - else { - if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { - if (responseBuffer) { - responseBuffer->buffer = (byte*)XMALLOC(ret, ocsp->cm->heap, - DYNAMIC_TYPE_TMP_BUFFER); +const char *wolfSSL_OCSP_cert_status_str(long s) +{ + switch (s) { + case CERT_GOOD: + return "good"; + case CERT_REVOKED: + return "revoked"; + case CERT_UNKNOWN: + return "unknown"; + default: + return "(UNKNOWN)"; + } +} - if (responseBuffer->buffer) { - responseBuffer->length = ret; - XMEMCPY(responseBuffer->buffer, response, ret); - } - } +int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) +{ + (void)thisupd; + (void)nextupd; + (void)sec; + (void)maxsec; + /* Dates validated in DecodeSingleResponse. */ + return SSL_SUCCESS; +} - ret = xstat2err(ocspResponse->status->status); - - if (wc_LockMutex(&ocsp->ocspLock) != 0) - ret = BAD_MUTEX_E; - else { - if (status != NULL) { - if (status->rawOcspResponse) - XFREE(status->rawOcspResponse, ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - /* Replace existing certificate entry with updated */ - XMEMCPY(status, newStatus, sizeof(CertStatus)); - } - else { - /* Save new certificate entry */ - status = (CertStatus*)XMALLOC(sizeof(CertStatus), - ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); - if (status != NULL) { - XMEMCPY(status, newStatus, sizeof(CertStatus)); - status->next = entry->status; - entry->status = status; - entry->totalStatus++; - } - } - - if (status && responseBuffer && responseBuffer->buffer) { - status->rawOcspResponse = (byte*)XMALLOC( - responseBuffer->length, - ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - if (status->rawOcspResponse) { - status->rawOcspResponseSz = responseBuffer->length; - XMEMCPY(status->rawOcspResponse, - responseBuffer->buffer, - responseBuffer->length); - } - } - - wc_UnLockMutex(&ocsp->ocspLock); - } +void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) +{ + FreeOcspRequest(certId); + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer) +{ + WOLFSSL_OCSP_CERTID* certId; + DecodedCert cert; + WOLFSSL_CERT_MANAGER* cm; + int ret; + DerBuffer* derCert = NULL; + + (void)dgst; + + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) + return NULL; + + ret = AllocDer(&derCert, issuer->derCert->length, + issuer->derCert->type, NULL); + if (ret == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, issuer->derCert->buffer, + issuer->derCert->length); + AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + } + + certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, + DYNAMIC_TYPE_OPENSSL); + if (certId != NULL) { + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else { + ret = InitOcspRequest(certId, &cert, 0, NULL); + if (ret != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; } - else - ret = OCSP_LOOKUP_FAIL; } + FreeDecodedCert(&cert); + } + + wolfSSL_CertManagerFree(cm); + + return certId; +} + +void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) +{ + wolfSSL_OCSP_RESPONSE_free(basicResponse); +} + +/* Signature verified in DecodeBasicOcspResponse. + * But no store available to verify certificate. */ +int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags) +{ + DecodedCert cert; + int ret = SSL_SUCCESS; + + (void)certs; + + if (flags & OCSP_NOVERIFY) + return SSL_SUCCESS; + + InitDecodedCert(&cert, bs->cert, bs->certSz, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0) + ret = SSL_FAILURE; + FreeDecodedCert(&cert); + + return ret; +} + +void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) +{ + if (response->status != NULL) + XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response->source != NULL) + XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response) +{ + byte* data; + byte* p; + int len; + int dataAlloced = 0; + OcspResponse* ret = NULL; + + if (bio == NULL) + return NULL; + + if (bio->type == BIO_MEMORY) { + len = wolfSSL_BIO_get_mem_data(bio, &data); + if (len <= 0 || data == NULL) { + return NULL; + } + } + else if (bio->type == BIO_FILE) { + long i; + long l; + + i = XFTELL(bio->file); + if (i < 0) + return NULL; + XFSEEK(bio->file, 0, SEEK_END); + l = XFTELL(bio->file); + if (l < 0) + return NULL; + XFSEEK(bio->file, i, SEEK_SET); + + /* check calulated length */ + if (l - i <= 0) + return NULL; + + data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) + return NULL; + dataAlloced = 1; + + len = wolfSSL_BIO_read(bio, (char *)data, (int)l); } else - ret = OCSP_LOOKUP_FAIL; + return NULL; -#ifdef WOLFSSL_SMALL_STACK - XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (len > 0) { + p = data; + ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len); + } - if (response != NULL && ocsp->cm->ocspRespFreeCb) - ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); + if (dataAlloced) + XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_LEAVE("CheckOcspRequest", ret); return ret; } +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len) +{ + OcspResponse *resp = NULL; + word32 idx = 0; + int length = 0; + + if (data == NULL) + return NULL; + + if (response != NULL) + resp = *response; + if (resp == NULL) { + resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_OPENSSL); + if (resp == NULL) + return NULL; + XMEMSET(resp, 0, sizeof(OcspResponse)); + } + + resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (resp->source == NULL) { + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (resp->status == NULL) { + XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMCPY(resp->source, *data, len); + resp->maxIdx = len; + + if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) { + wolfSSL_OCSP_RESPONSE_free(resp); + return NULL; + } + + if (GetSequence(*data, &idx, &length, len) >= 0) + (*data) += idx + length; + + return resp; +} + +int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data) +{ + if (data == NULL) + return response->maxIdx; + + XMEMCPY(*data, response->source, response->maxIdx); + return response->maxIdx; +} + +int wolfSSL_OCSP_response_status(OcspResponse *response) +{ + return response->responseStatus; +} + +const char *wolfSSL_OCSP_response_status_str(long s) +{ + switch (s) { + case OCSP_SUCCESSFUL: + return "successful"; + case OCSP_MALFORMED_REQUEST: + return "malformedrequest"; + case OCSP_INTERNAL_ERROR: + return "internalerror"; + case OCSP_TRY_LATER: + return "trylater"; + case OCSP_SIG_REQUIRED: + return "sigrequired"; + case OCSP_UNAUTHROIZED: + return "unauthorized"; + default: + return "(UNKNOWN)"; + } +} + +WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) +{ + WOLFSSL_OCSP_BASICRESP* bs; + + bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, + DYNAMIC_TYPE_OPENSSL); + if (bs == NULL) + return NULL; + + XMEMCPY(bs, response, sizeof(OcspResponse)); + bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->status == NULL || bs->source == NULL) { + if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_OCSP_RESPONSE_free(bs); + bs = NULL; + } + else { + XMEMCPY(bs->status, response->status, sizeof(CertStatus)); + XMEMCPY(bs->source, response->source, response->maxIdx); + } + return bs; +} + +OcspRequest* wolfSSL_OCSP_REQUEST_new(void) +{ + OcspRequest* request; + + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OPENSSL); + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + return request; +} + +void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) +{ + FreeOcspRequest(request); + XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) +{ + word32 size; + + size = EncodeOcspRequest(request, NULL, 0); + if (size <= 0 || data == NULL) + return size; + + return EncodeOcspRequest(request, *data, size); +} + +WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid) +{ + if (req == NULL || cid == NULL) + return NULL; + + FreeOcspRequest(req); + XMEMCPY(req, cid, sizeof(OcspRequest)); + + if (cid->serial != NULL) { + req->serial = (byte*)XMALLOC(cid->serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL || req->url == NULL) { + FreeOcspRequest(req); + return NULL; + } + + XMEMCPY(req->serial, cid->serial, cid->serialSz); + XMEMCPY(req->url, cid->url, cid->urlSz); + } + + wolfSSL_OCSP_REQUEST_free(cid); + + return req; +} + +#endif #else /* HAVE_OCSP */ diff --git a/src/sniffer.c b/src/sniffer.c index 33278f4e02..738e5360fd 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -55,16 +55,6 @@ #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - -static INLINE word32 min(word32 a, word32 b) -{ - return a > b ? b : a; -} - -#endif /* WOLFSSL_HAVE_MIN */ - #ifndef WOLFSSL_SNIFFER_TIMEOUT #define WOLFSSL_SNIFFER_TIMEOUT 900 /* Cache unclosed Sessions for 15 minutes since last used */ @@ -203,21 +193,21 @@ static const char* const msgTable[] = "Got an Alert msg", "Another msg to Process", "Removing Session From Table", - + /* 46 */ "Bad Key File", "Wrong IP Version", "Wrong Protocol type", "Packet Short for header processing", "Got Unknown Record Type", - + /* 51 */ "Can't Open Trace File", "Session in Fatal Error State", "Partial SSL record received", "Buffer Error, malformed input", "Added to Partial Input", - + /* 56 */ "Received a Duplicate Packet", "Received an Out of Order Packet", @@ -488,7 +478,7 @@ static void FreePacketList(PacketBuffer* in) if (in) { PacketBuffer* del; PacketBuffer* packet = in; - + while (packet) { del = packet; packet = packet->next; @@ -504,7 +494,7 @@ static void FreeSnifferSession(SnifferSession* session) if (session) { SSL_free(session->sslClient); SSL_free(session->sslServer); - + FreePacketList(session->cliReassemblyList); FreePacketList(session->srvReassemblyList); @@ -528,7 +518,7 @@ void ssl_FreeSniffer(void) wc_LockMutex(&ServerListMutex); wc_LockMutex(&SessionMutex); - + srv = ServerList; while (srv) { removeServer = srv; @@ -576,8 +566,9 @@ static int HashInit(HsHashes* hash) ret = wc_InitSha(&hash->hashSha); #endif #ifndef NO_MD5 - if (ret == 0) - wc_InitMd5(&hash->hashMd5); + if (ret == 0) { + ret = wc_InitMd5(&hash->hashMd5); + } #endif #endif #ifndef NO_SHA256 @@ -606,8 +597,9 @@ static int HashUpdate(HsHashes* hash, const byte* input, int sz) ret = wc_ShaUpdate(&hash->hashSha, input, sz); #endif #ifndef NO_MD5 - if (ret == 0) - wc_Md5Update(&hash->hashMd5, input, sz); + if (ret == 0) { + ret = wc_Md5Update(&hash->hashMd5, input, sz); + } #endif #endif #ifndef NO_SHA256 @@ -714,7 +706,7 @@ static void InitSession(SnifferSession* session) session->srvReassemblyMemory = 0; session->next = 0; session->ticketID = 0; - + InitFlags(&session->flags); InitFinCapture(&session->finCaputre); #ifdef HAVE_EXTENDED_MASTER @@ -768,9 +760,9 @@ static int SetPassword(char* passwd, int sz, int rw, void* userdata) /* Ethernet Header */ typedef struct EthernetHdr { - byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ - byte src[ETHER_IF_ADDR_LEN]; /* source host address */ - word16 type; /* IP, ARP, etc */ + byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ + byte src[ETHER_IF_ADDR_LEN]; /* source host address */ + word16 type; /* IP, ARP, etc */ } EthernetHdr; @@ -796,8 +788,8 @@ typedef struct IpHdr { typedef struct TcpHdr { word16 srcPort; /* source port */ word16 dstPort; /* destination port */ - word32 sequence; /* sequence number */ - word32 ack; /* acknoledgment number */ + word32 sequence; /* sequence number */ + word32 ack; /* acknoledgment number */ byte offset; /* data offset, reserved */ byte flags; /* option flags */ word16 window; /* window */ @@ -815,8 +807,8 @@ typedef struct TcpHdr { -/* Use platform specific GetError to write to tracfile if tracing */ -static void Trace(int idx) +/* Use platform specific GetError to write to tracfile if tracing */ +static void Trace(int idx) { if (TraceOn) { char myBuffer[MAX_ERROR_LEN]; @@ -881,9 +873,9 @@ static void TracePacket(void) static char* IpToS(word32 addr, char* str) { byte* p = (byte*)&addr; - + SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - + return str; } @@ -1041,7 +1033,7 @@ static int IsServerRegistered(word32 addr) SnifferServer* sniffer; wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->server == addr) { @@ -1050,7 +1042,7 @@ static int IsServerRegistered(word32 addr) } sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); return ret; @@ -1063,18 +1055,18 @@ static int IsPortRegistered(word32 port) { int ret = 0; /* false */ SnifferServer* sniffer; - + wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->port == (int)port) { - ret = 1; + ret = 1; break; } sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); return ret; @@ -1085,9 +1077,9 @@ static int IsPortRegistered(word32 port) static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferServer* sniffer; - + wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src) @@ -1096,9 +1088,9 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) break; sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); - + return sniffer; } @@ -1108,7 +1100,7 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) { word32 hash = ipInfo->src * ipInfo->dst; hash *= tcpInfo->srcPort * tcpInfo->dstPort; - + return hash % HASH_SIZE; } @@ -1117,13 +1109,13 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferSession* session; - time_t currTime = time(NULL); + time_t currTime = time(NULL); word32 row = SessionHash(ipInfo, tcpInfo); assert(row <= HASH_SIZE); - + wc_LockMutex(&SessionMutex); - + session = SessionTable[row]; while (session) { if (session->server == ipInfo->src && session->client == ipInfo->dst && @@ -1134,15 +1126,15 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session->cliPort == tcpInfo->srcPort && session->srvPort == tcpInfo->dstPort) break; - + session = session->next; } if (session) session->lastUsed= currTime; /* keep session alive, remove stale will */ - /* leave alone */ + /* leave alone */ wc_UnLockMutex(&SessionMutex); - + /* determine side */ if (session) { if (ipInfo->dst == session->context->server && @@ -1150,8 +1142,8 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session->flags.side = WOLFSSL_SERVER_END; else session->flags.side = WOLFSSL_CLIENT_END; - } - + } + return session; } @@ -1183,9 +1175,14 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, return -1; } - ret = (int)XFREAD(loadBuf, fileSz, 1, file); + ret = (int)XFREAD(loadBuf, 1, fileSz, file); XFCLOSE(file); + if (ret != fileSz) { + free(loadBuf); + return -1; + } + if (typeKey == SSL_FILETYPE_PEM) { byte* saveBuf = (byte*)malloc(fileSz); int saveBufSz = 0; @@ -1394,11 +1391,11 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) Trace(IP_CHECK_STR); if (version != IPV4) { - SetError(BAD_IPVER_STR, error, NULL, 0); + SetError(BAD_IPVER_STR, error, NULL, 0); return -1; } - if (iphdr->protocol != TCP_PROTOCOL) { + if (iphdr->protocol != TCP_PROTOCOL) { SetError(BAD_PROTO_STR, error, NULL, 0); return -1; } @@ -1435,7 +1432,7 @@ static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error) info->syn = tcphdr->flags & TCP_SYN; info->ack = tcphdr->flags & TCP_ACK; if (info->ack) - info->ackNumber = ntohl(tcphdr->ack); + info->ackNumber = ntohl(tcphdr->ack); if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) { SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0); @@ -1920,12 +1917,12 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } input += bLen; *sslBytes -= bLen; - + if (*sslBytes == 0) { /* no extensions */ return 0; } - + /* skip extensions until session ticket */ /* make sure can read len */ if (SUITE_LEN > *sslBytes) { @@ -1998,7 +1995,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, SSL* ssl; word32 inOutIdx = 0; int ret; - + if (session->flags.side == WOLFSSL_SERVER_END) ssl = session->sslServer; else @@ -2012,7 +2009,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE); return ret; } - + if (ret == 0 && session->flags.cached == 0) { if (session->sslServer->options.haveSessionId) { WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); @@ -2048,7 +2045,7 @@ static int DoHandShake(const byte* input, int* sslBytes, } type = input[0]; size = (input[1] << 16) | (input[2] << 8) | input[3]; - + input += HANDSHAKE_HEADER_SZ; *sslBytes -= HANDSHAKE_HEADER_SZ; startBytes = *sslBytes; @@ -2065,7 +2062,7 @@ static int DoHandShake(const byte* input, int* sslBytes, SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); return -1; } - + #ifdef HAVE_EXTENDED_MASTER if (session->hash) { if (HashUpdate(session->hash, input, size) != 0) { @@ -2175,32 +2172,32 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) wc_Arc4Process(ssl->decrypt.arc4, output, input, sz); break; #endif - + #ifdef BUILD_DES3 case wolfssl_triple_des: ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz); break; #endif - + #ifdef BUILD_AES case wolfssl_aes: ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz); break; #endif - + #ifdef HAVE_HC128 case wolfssl_hc128: wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz); break; #endif - + #ifdef BUILD_RABBIT case wolfssl_rabbit: wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz); break; #endif - #ifdef HAVE_CAMELLIA + #ifdef HAVE_CAMELLIA case wolfssl_camellia: wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz); break; @@ -2216,6 +2213,9 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) case wolfssl_aes_gcm: if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size)) { + /* scratch buffer, sniffer ignores auth tag*/ + byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ]; + byte nonce[AESGCM_NONCE_SZ]; XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); @@ -2225,7 +2225,7 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) input + AESGCM_EXP_IV_SZ, sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, nonce, AESGCM_NONCE_SZ, - NULL, 0, + authTag, sizeof(authTag), NULL, 0) < 0) { Trace(BAD_DECRYPT); ret = -1; @@ -2276,7 +2276,7 @@ static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, if (ssl->specs.cipher_type == block) ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; - + return output; } @@ -2289,20 +2289,20 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, SnifferSession* current; word32 row = rowHint; int haveLock = 0; - + if (ipInfo && tcpInfo) row = SessionHash(ipInfo, tcpInfo); else haveLock = 1; - + assert(row <= HASH_SIZE); Trace(REMOVE_SESSION_STR); - + if (!haveLock) wc_LockMutex(&SessionMutex); - + current = SessionTable[row]; - + while (current) { if (current == session) { if (previous) @@ -2316,7 +2316,7 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, previous = current; current = current->next; } - + if (!haveLock) wc_UnLockMutex(&SessionMutex); } @@ -2327,11 +2327,11 @@ static void RemoveStaleSessions(void) { word32 i; SnifferSession* session; - + for (i = 0; i < HASH_SIZE; i++) { session = SessionTable[i]; while (session) { - SnifferSession* next = session->next; + SnifferSession* next = session->next; if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) { TraceStaleSession(); RemoveSession(session, NULL, NULL, i); @@ -2348,7 +2348,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, { SnifferSession* session = 0; int row; - + Trace(NEW_SESSION_STR); /* create a new one */ session = (SnifferSession*)malloc(sizeof(SnifferSession)); @@ -2380,14 +2380,14 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->cliSeqStart = tcpInfo->sequence; session->cliExpected = 1; /* relative */ session->lastUsed= time(NULL); - + session->context = GetSnifferServer(ipInfo, tcpInfo); if (session->context == NULL) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); free(session); return 0; } - + session->sslServer = SSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); @@ -2405,31 +2405,31 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, } /* put server back into server mode */ session->sslServer->options.side = WOLFSSL_SERVER_END; - + row = SessionHash(ipInfo, tcpInfo); - + /* add it to the session table */ wc_LockMutex(&SessionMutex); - + session->next = SessionTable[row]; SessionTable[row] = session; - + SessionCount++; - + if ( (SessionCount % HASH_SIZE) == 0) { TraceFindingStale(); RemoveStaleSessions(); } - + wc_UnLockMutex(&SessionMutex); - + /* determine headed side */ if (ipInfo->dst == session->context->server && tcpInfo->dstPort == session->context->port) session->flags.side = WOLFSSL_SERVER_END; else - session->flags.side = WOLFSSL_CLIENT_END; - + session->flags.side = WOLFSSL_CLIENT_END; + return session; } @@ -2458,16 +2458,16 @@ static int DoOldHello(SnifferSession* session, const byte* sslFrame, } ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes, - (word16)*rhSize); + (word16)*rhSize); if (ret < 0 && ret != MATCH_SUITE_ERROR) { SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE); return -1; } - + Trace(OLD_CLIENT_OK_STR); XMEMCPY(session->sslClient->arrays->clientRandom, session->sslServer->arrays->clientRandom, RAN_LEN); - + *sslBytes -= *rhSize; return 0; } @@ -2490,38 +2490,38 @@ int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen, const word16* data = (word16*)&pseudo; word32 sum = 0; word16 checksum; - + pseudo.src = ipInfo->src; pseudo.dst = ipInfo->dst; pseudo.rsv = 0; pseudo.protocol = TCP_PROTO; pseudo.length = htons(tcpInfo->length + dataLen); - + /* pseudo header sum */ while (count >= 2) { sum += *data++; count -= 2; } - + count = tcpInfo->length + dataLen; data = (word16*)packet; - + /* main sum */ while (count > 1) { sum += *data++; count -=2; } - + /* get left-over, if any */ packet = (byte*)data; if (count > 0) { sum += *packet; } - + /* fold 32bit sum into 16 bits */ while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); - + checksum = (word16)~sum; /* checksum should now equal 0, since included already calcd checksum */ /* field, but tcp checksum offloading could negate calculation */ @@ -2547,23 +2547,23 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet, } if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0) return -1; - - /* tcp header */ + + /* tcp header */ if (length < (ipInfo->length + TCP_HDR_SZ)) { SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0) return -1; - - /* setup */ + + /* setup */ *sslFrame = packet + ipInfo->length + tcpInfo->length; if (*sslFrame > packet + length) { SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } *sslBytes = (int)(packet + length - *sslFrame); - + return 0; } @@ -2582,7 +2582,7 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* already had existing, so OK */ if (*session) return 1; - + SetError(MEMORY_STR, error, NULL, 0); return -1; } @@ -2598,10 +2598,10 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* don't worry about duplicate ACKs either */ if (sslBytes == 0 && tcpInfo->ack) return 1; - + SetError(BAD_SESSION_STR, error, NULL, 0); return -1; - } + } } return 0; } @@ -2612,27 +2612,27 @@ static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data, int* bytesLeft) { PacketBuffer* pb; - + int added = end - *begin + 1; assert(*begin <= end); - + pb = (PacketBuffer*)malloc(sizeof(PacketBuffer)); if (pb == NULL) return NULL; - + pb->next = 0; pb->begin = *begin; pb->end = end; pb->data = (byte*)malloc(added); - + if (pb->data == NULL) { free(pb); return NULL; } XMEMCPY(pb->data, data, added); - + *bytesLeft -= added; *begin = pb->end + 1; - + return pb; } @@ -2647,7 +2647,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, &session->cliReassemblyList: &session->srvReassemblyList; PacketBuffer* curr = *front; PacketBuffer* prev = curr; - + word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; word32 startSeq = seq; @@ -2670,14 +2670,14 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, *reassemblyMemory += sslBytes; return 1; } - + /* add to front if before current front, up to next->begin */ if (seq < curr->begin) { word32 end = seq + sslBytes - 1; - + if (end >= curr->begin) end = curr->begin - 1; - + if (MaxRecoveryMemory -1 && (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) { SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); @@ -2692,7 +2692,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, *front = add; *reassemblyMemory += sslBytes; } - + /* while we have bytes left, try to find a gap to fill */ while (bytesLeft > 0) { /* get previous packet in list */ @@ -2700,7 +2700,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, prev = curr; curr = curr->next; } - + /* don't add duplicate data */ if (prev->end >= seq) { if ( (seq + bytesLeft - 1) <= prev->end) @@ -2708,18 +2708,18 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, seq = prev->end + 1; bytesLeft = startSeq + sslBytes - seq; } - + if (!curr) /* we're at the end */ added = bytesLeft; - else + else /* we're in between two frames */ added = min((word32)bytesLeft, curr->begin - seq); - + /* data already there */ if (added == 0) continue; - + if (MaxRecoveryMemory != -1 && (int)(*reassemblyMemory + added) > MaxRecoveryMemory) { SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); @@ -2760,7 +2760,7 @@ static int AddFinCapture(SnifferSession* session, word32 sequence) static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, int* sslBytes, const byte** sslFrame, char* error) { - word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? session->cliSeqStart :session->srvSeqStart; word32 real = tcpInfo->sequence - seqStart; word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? @@ -2770,19 +2770,19 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? session->flags.srvSkipPartial : session->flags.cliSkipPartial; - + /* handle rollover of sequence */ if (tcpInfo->sequence < seqStart) real = 0xffffffffU - seqStart + tcpInfo->sequence; - + TraceRelativeSequence(*expected, real); - + if (real < *expected) { Trace(DUPLICATE_STR); if (real + *sslBytes > *expected) { int overlap = *expected - real; Trace(OVERLAP_DUPLICATE_STR); - + /* adjust to expected, remove duplicate */ *sslFrame += overlap; *sslBytes -= overlap; @@ -2792,16 +2792,16 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, * block be sure to also update the block below. */ if (reassemblyList) { word32 newEnd = *expected + *sslBytes; - + if (newEnd > reassemblyList->begin) { Trace(OVERLAP_REASSEMBLY_BEGIN_STR); - + /* remove bytes already on reassembly list */ *sslBytes -= newEnd - reassemblyList->begin; } if (newEnd > reassemblyList->end) { Trace(OVERLAP_REASSEMBLY_END_STR); - + /* may be past reassembly list end (could have more on list) so try to add what's past the front->end */ AddToReassembly(session->flags.side, reassemblyList->end +1, @@ -2865,7 +2865,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, *expected += *sslBytes; if (tcpInfo->fin) *expected += 1; - + return 0; } @@ -2985,16 +2985,16 @@ static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session) static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session) { if (tcpInfo->ack) { - word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? session->srvSeqStart :session->cliSeqStart; word32 real = tcpInfo->ackNumber - seqStart; word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ? session->srvExpected : session->cliExpected; - + /* handle rollover of sequence */ if (tcpInfo->ackNumber < seqStart) real = 0xffffffffU - seqStart + tcpInfo->ackNumber; - + TraceAck(real, expected); if (real > expected) @@ -3022,13 +3022,13 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceServerSyn(tcpInfo->sequence); return 1; } - + /* adjust potential ethernet trailer */ actualLen = ipInfo->total - ipInfo->length - tcpInfo->length; if (*sslBytes > actualLen) { *sslBytes = actualLen; } - + TraceSequence(tcpInfo->sequence, *sslBytes); if (CheckAck(tcpInfo, session) < 0) { if (!RecoveryEnabled) { @@ -3045,13 +3045,13 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, return FixSequence(tcpInfo, session); } } - + if (*ackFault) { Trace(CLEAR_ACK_FAULT); *ackFault = 0; } - return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); + return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); } @@ -3074,19 +3074,19 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, (*session)->flags.finCount += 1; else if (tcpInfo->rst) (*session)->flags.finCount += 2; - + if ((*session)->flags.finCount >= 2) { RemoveSession(*session, ipInfo, tcpInfo, 0); *session = NULL; return 1; } } - + if ((*session)->flags.fatalError == FATAL_ERROR_STATE) { SetError(FATAL_ERROR_STR, error, NULL, 0); return -1; } - + if (skipPartial) { if (FindNextRecordInAssembly(*session, sslFrame, sslBytes, end, error) < 0) { @@ -3098,13 +3098,13 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, Trace(NO_DATA_STR); return 1; } - + /* if current partial data, add to end of partial */ /* if skipping, the data is already at the end of partial */ if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) { Trace(PARTIAL_ADD_STR); - + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); @@ -3168,7 +3168,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, session->sslServer : session->sslClient; word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; - + while (*front && ((*front)->begin == *expected) ) { word32 room = *bufferSize - *length; word32 packetLen = (*front)->end - (*front)->begin + 1; @@ -3180,21 +3180,21 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, } room = *bufferSize - *length; /* bufferSize is now bigger */ } - + if (packetLen <= room) { PacketBuffer* del = *front; byte* buf = *myBuffer; - + XMEMCPY(&buf[*length], (*front)->data, packetLen); *length += packetLen; *expected += packetLen; - + /* remove used packet */ *front = (*front)->next; *reassemblyMemory -= packetLen; FreePacketBuffer(del); - + moreInput = 1; } else @@ -3207,7 +3207,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, } return moreInput; } - + /* Process Message(s) from sslFrame */ @@ -3246,11 +3246,11 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) { /* don't have enough input yet to process full SSL record */ Trace(PARTIAL_INPUT_STR); - + /* store partial if not there already or we advanced */ if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) { if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) { - if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { + if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } @@ -3266,7 +3266,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, sslBytes -= RECORD_HEADER_SZ; recordEnd = sslFrame + rhSize; /* may have more than one record */ inRecordEnd = recordEnd; - + /* decrypt if needed */ if ((session->flags.side == WOLFSSL_SERVER_END && session->flags.serverCipherOn) @@ -3294,7 +3294,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, } doPart: - + switch ((enum ContentType)rh.type) { case handshake: { @@ -3334,7 +3334,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, Trace(GOT_APP_DATA_STR); { word32 inOutIdx = 0; - + ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx); if (ret == 0) { ret = ssl->buffers.clearOutputBuffer.length; @@ -3398,26 +3398,26 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, sslBytes = (int)(end - recordEnd); goto doMessage; } - + /* clear used input */ ssl->buffers.inputBuffer.length = 0; - + /* could have more input ready now */ if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error)) goto doMessage; if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, NO_FORCED_FREE); - + return decoded; } /* See if we need to process any pending FIN captures */ -static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, +static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session) { - if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= + if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= session->cliExpected) { if (session->finCaputre.cliCounted == 0) { session->flags.finCount += 1; @@ -3425,8 +3425,8 @@ static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected); } } - - if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= + + if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= session->srvExpected) { if (session->finCaputre.srvCounted == 0) { session->flags.finCount += 1; @@ -3434,13 +3434,13 @@ static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected); } } - - if (session->flags.finCount >= 2) + + if (session->flags.finCount >= 2) RemoveSession(session, ipInfo, tcpInfo, 0); } -/* If session is in fatal error state free resources now +/* If session is in fatal error state free resources now return true if removed, 0 otherwise */ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session, char* error) @@ -3469,17 +3469,17 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, error) != 0) return -1; - + ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) return 0; /* done for now */ - + ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) return 0; /* done for now */ - + ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, &end, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; @@ -3533,7 +3533,7 @@ int ssl_Trace(const char* traceFile, char* error) } TraceOn = 1; } - else + else TraceOn = 0; return 0; diff --git a/src/ssl.c b/src/ssl.c old mode 100644 new mode 100755 index d02cced244..b8b80b6ce4 --- a/src/ssl.c +++ b/src/ssl.c @@ -93,45 +93,6 @@ #include #endif -#ifndef NO_FILESYSTEM - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) \ - && !defined(EBSNET) - #include - #include - #endif - #ifdef EBSNET - #include "vfapi.h" - #include "vfile.h" - #endif -#endif /* NO_FILESYSTEM */ - -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSSL_HAVE_MIN */ - -#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_HAVE_MAX) -#define WOLFSSL_HAVE_MAX - - static INLINE word32 max(word32 a, word32 b) - { - return a > b ? a : b; - } - -#endif /* WOLFSSL_DTLS && !WOLFSSL_HAVE_MAX */ - #ifndef WOLFSSL_LEANPSK char* mystrnstr(const char* s1, const char* s2, unsigned int n) @@ -372,7 +333,7 @@ int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) } #ifndef HAVE_FIPS - ret = wc_InitRng_ex(rng, ctx->heap); + ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId); #else ret = wc_InitRng(rng); #endif @@ -400,7 +361,7 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL); if (ssl) - if ( (ret = InitSSL(ssl, ctx)) < 0) { + if ( (ret = InitSSL(ssl, ctx, 0)) < 0) { FreeSSL(ssl, ctx->heap); ssl = 0; } @@ -418,6 +379,167 @@ void wolfSSL_free(WOLFSSL* ssl) WOLFSSL_LEAVE("SSL_free", 0); } + +#ifdef HAVE_WRITE_DUP + +/* + * Release resources around WriteDup object + * + * ssl WOLFSSL object + * + * no return, destruction so make best attempt +*/ +void FreeWriteDup(WOLFSSL* ssl) +{ + int doFree = 0; + + WOLFSSL_ENTER("FreeWriteDup"); + + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) { + ssl->dupWrite->dupCount--; + if (ssl->dupWrite->dupCount == 0) { + doFree = 1; + } else { + WOLFSSL_MSG("WriteDup count not zero, no full free"); + } + wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + } + + if (doFree) { + WOLFSSL_MSG("Doing WriteDup full free, count to zero"); + wc_FreeMutex(&ssl->dupWrite->dupMutex); + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + } +} + + +/* + * duplicate existing ssl members into dup needed for writing + * + * dup write only WOLFSSL + * ssl exisiting WOLFSSL + * + * 0 on success +*/ +static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl) +{ + /* shared dupWrite setup */ + ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap, + DYNAMIC_TYPE_WRITEDUP); + if (ssl->dupWrite == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup)); + + if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) { + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + ssl->dupWrite = NULL; + return BAD_MUTEX_E; + } + ssl->dupWrite->dupCount = 2; /* both sides have a count to start */ + dup->dupWrite = ssl->dupWrite ; /* each side uses */ + + /* copy write parts over to dup writer */ + XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs)); + XMEMCPY(&dup->options, &ssl->options, sizeof(Options)); + XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys)); + XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers)); + /* dup side now owns encrypt/write ciphers */ + XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers)); + + dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx; + dup->wfd = ssl->wfd; + dup->wflags = ssl->wflags; + dup->hmac = ssl->hmac; +#ifdef HAVE_TRUNCATED_HMAC + dup->truncated_hmac = ssl->truncated_hmac; +#endif + + /* unique side dup setup */ + dup->dupSide = WRITE_DUP_SIDE; + ssl->dupSide = READ_DUP_SIDE; + + return 0; +} + + +/* + * duplicate a WOLFSSL object post handshake for writing only + * turn exisitng object into read only. Allows concurrent access from two + * different threads. + * + * ssl exisiting WOLFSSL object + * + * return dup'd WOLFSSL object on success +*/ +WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl) +{ + WOLFSSL* dup = NULL; + int ret = 0; + + (void)ret; + WOLFSSL_ENTER("wolfSSL_write_dup"); + + if (ssl == NULL) { + return ssl; + } + + if (ssl->options.handShakeDone == 0) { + WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete"); + return NULL; + } + + if (ssl->dupWrite) { + WOLFSSL_MSG("wolfSSL_write_dup already called once"); + return NULL; + } + + dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL); + if (dup) { + if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } else if ( (ret = DupSSL(dup, ssl) < 0)) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } + } + + WOLFSSL_LEAVE("wolfSSL_write_dup", ret); + + return dup; +} + + +/* + * Notify write dup side of fatal error or close notify + * + * ssl WOLFSSL object + * err Notify err + * + * 0 on success +*/ +int NotifyWriteSide(WOLFSSL* ssl, int err) +{ + int ret; + + WOLFSSL_ENTER("NotifyWriteSide"); + + ret = wc_LockMutex(&ssl->dupWrite->dupMutex); + if (ret == 0) { + ssl->dupWrite->dupErr = err; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + return ret; +} + + +#endif /* HAVE_WRITE_DUP */ + + #ifdef HAVE_POLY1305 /* set if to use old poly 1 for yes 0 to use new poly */ int wolfSSL_use_old_poly(WOLFSSL* ssl, int value) @@ -438,6 +560,10 @@ int wolfSSL_set_fd(WOLFSSL* ssl, int fd) WOLFSSL_ENTER("SSL_set_fd"); + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + ret = wolfSSL_set_read_fd(ssl, fd); if (ret == SSL_SUCCESS) { ret = wolfSSL_set_write_fd(ssl, fd); @@ -541,6 +667,19 @@ int wolfSSL_get_ciphers(char* buf, int len) return SSL_SUCCESS; } +const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len) +{ + const char* cipher; + + if (ssl == NULL) + return NULL; + + cipher = wolfSSL_get_cipher_name_from_suite(ssl->options.cipherSuite, + ssl->options.cipherSuite0); + len = min(len, (int)(XSTRLEN(cipher) + 1)); + XMEMCPY(buf, cipher, len); + return buf; +} int wolfSSL_get_fd(const WOLFSSL* ssl) { @@ -713,38 +852,38 @@ int wolfSSL_GetObjectSize(void) printf("sizeof suites = %lu\n", sizeof(Suites)); printf("sizeof ciphers(2) = %lu\n", sizeof(Ciphers)); #ifndef NO_RC4 - printf(" sizeof arc4 = %lu\n", sizeof(Arc4)); + printf("\tsizeof arc4 = %lu\n", sizeof(Arc4)); #endif - printf(" sizeof aes = %lu\n", sizeof(Aes)); + printf("\tsizeof aes = %lu\n", sizeof(Aes)); #ifndef NO_DES3 - printf(" sizeof des3 = %lu\n", sizeof(Des3)); + printf("\tsizeof des3 = %lu\n", sizeof(Des3)); #endif #ifndef NO_RABBIT - printf(" sizeof rabbit = %lu\n", sizeof(Rabbit)); + printf("\tsizeof rabbit = %lu\n", sizeof(Rabbit)); #endif #ifdef HAVE_CHACHA - printf(" sizeof chacha = %lu\n", sizeof(ChaCha)); + printf("\tsizeof chacha = %lu\n", sizeof(ChaCha)); #endif printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs)); printf("sizeof keys = %lu\n", sizeof(Keys)); printf("sizeof Hashes(2) = %lu\n", sizeof(Hashes)); #ifndef NO_MD5 - printf(" sizeof MD5 = %lu\n", sizeof(Md5)); + printf("\tsizeof MD5 = %lu\n", sizeof(Md5)); #endif #ifndef NO_SHA - printf(" sizeof SHA = %lu\n", sizeof(Sha)); + printf("\tsizeof SHA = %lu\n", sizeof(Sha)); #endif #ifdef WOLFSSL_SHA224 printf(" sizeof SHA224 = %lu\n", sizeof(Sha224)); #endif #ifndef NO_SHA256 - printf(" sizeof SHA256 = %lu\n", sizeof(Sha256)); + printf("\tsizeof SHA256 = %lu\n", sizeof(Sha256)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA384 = %lu\n", sizeof(Sha384)); + printf("\tsizeof SHA384 = %lu\n", sizeof(Sha384)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA512 = %lu\n", sizeof(Sha512)); + printf("\tsizeof SHA512 = %lu\n", sizeof(Sha512)); #endif printf("sizeof Buffers = %lu\n", sizeof(Buffers)); printf("sizeof Options = %lu\n", sizeof(Options)); @@ -930,7 +1069,7 @@ int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz) if (inSz > maxSize) return INPUT_SIZE_E; - return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1); + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0); } @@ -1004,21 +1143,26 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, if (ssl->options.side != WOLFSSL_SERVER_END) return SIDE_ERROR; - if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + ssl->buffers.serverDH_P.buffer = NULL; + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + ssl->buffers.serverDH_G.buffer = NULL; + } ssl->buffers.weOwnDH = 1; /* SSL owns now */ ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap, - DYNAMIC_TYPE_DH); + DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_P.buffer == NULL) return MEMORY_E; ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap, - DYNAMIC_TYPE_DH); + DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_G.buffer == NULL) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + ssl->buffers.serverDH_P.buffer = NULL; return MEMORY_E; } @@ -1054,16 +1198,16 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, if (pSz < ctx->minDhKeySz) return DH_KEY_SIZE_E; - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); - ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); + ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); if (ctx->serverDH_P.buffer == NULL) return MEMORY_E; - ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); + ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); if (ctx->serverDH_G.buffer == NULL) { - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); return MEMORY_E; } @@ -1120,6 +1264,36 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#ifdef HAVE_WRITE_DUP + { /* local variable scope */ + int dupErr = 0; /* local copy */ + + ret = 0; + + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + WOLFSSL_MSG("Read dup side cannot write"); + return WRITE_DUP_WRITE_E; + } + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) { + return BAD_MUTEX_E; + } + dupErr = ssl->dupWrite->dupErr; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + if (ret != 0) { + ssl->error = ret; /* high priority fatal error */ + return SSL_FATAL_ERROR; + } + if (dupErr != 0) { + WOLFSSL_MSG("Write dup error from other side"); + ssl->error = dupErr; + return SSL_FATAL_ERROR; + } + } +#endif + #ifdef HAVE_ERRNO_H errno = 0; #endif @@ -1144,6 +1318,13 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) { + WOLFSSL_MSG("Write dup side cannot read"); + return WRITE_DUP_READ_E; + } +#endif + #ifdef HAVE_ERRNO_H errno = 0; #endif @@ -1164,6 +1345,21 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) #endif ret = ReceiveData(ssl, (byte*)data, sz, peek); +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + if (ssl->error != 0 && ssl->error != WANT_READ && + ssl->error != WC_PENDING_E) { + int notifyErr; + + WOLFSSL_MSG("Notifying write side of fatal read error"); + notifyErr = NotifyWriteSide(ssl, ssl->error); + if (notifyErr < 0) { + ret = ssl->error = notifyErr; + } + } + } +#endif + WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); if (ret < 0) @@ -1338,7 +1534,7 @@ int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - options, ssl->heap); + options, ssl->heap, ssl->devId); } @@ -1349,7 +1545,7 @@ int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, - options, ctx->heap); + options, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ @@ -1362,7 +1558,7 @@ int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, - options, ssl->heap); + options, ssl->heap, ssl->devId); } @@ -1373,7 +1569,7 @@ int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type, - options, ctx->heap); + options, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ @@ -1404,10 +1600,23 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) case WOLFSSL_ECC_BRAINPOOLP512R1: break; +#ifdef WOLFSSL_TLS13 + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + if (!IsAtLeastTLSv1_3(ssl->version)) + return SSL_SUCCESS; + break; +#endif + default: return BAD_FUNC_ARG; } + ssl->options.userCurves = 1; + return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); } @@ -1434,10 +1643,21 @@ int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) case WOLFSSL_ECC_BRAINPOOLP512R1: break; +#ifdef WOLFSSL_TLS13 + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + break; +#endif + default: return BAD_FUNC_ARG; } + ctx->userCurves = 1; + return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap); } @@ -1496,7 +1716,6 @@ int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name) #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_QSH */ - /* Application-Layer Protocol Negotiation */ #ifdef HAVE_ALPN @@ -1669,31 +1888,9 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - wc_InitMd5(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - ret = wc_InitSha(&ssl->hsHashes->hashSha); - if (ret !=0) - return ret; -#endif -#endif /* NO_OLD_TLS */ -#ifndef NO_SHA256 - ret = wc_InitSha256(&ssl->hsHashes->hashSha256); - if (ret !=0) - return ret; -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_InitSha384(&ssl->hsHashes->hashSha384); - if (ret !=0) - return ret; -#endif -#ifdef WOLFSSL_SHA512 - ret = wc_InitSha512(&ssl->hsHashes->hashSha512); + ret = InitHandshakeHashes(ssl); if (ret !=0) return ret; -#endif ret = wolfSSL_negotiate(ssl); return ret; @@ -1772,7 +1969,8 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, return SSL_SUCCESS; } -WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, + word32 bufSz) { if (ssl == NULL || (buf == NULL && bufSz > 0)) return BAD_FUNC_ARG; @@ -1790,7 +1988,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) if(ssl->session.isDynamic) XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = XMALLOC(bufSz, ssl->heap, + ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if(!ssl->session.ticket) { ssl->session.ticket = ssl->session.staticTicket; @@ -1909,38 +2107,49 @@ int wolfSSL_shutdown(WOLFSSL* ssl) if (ssl->options.quietShutdown) { WOLFSSL_MSG("quiet shutdown, no close notify sent"); - return SSL_SUCCESS; + ret = SSL_SUCCESS; } - - /* try to send close notify, not an error if can't */ - if (!ssl->options.isClosed && !ssl->options.connReset && - !ssl->options.sentNotify) { - ssl->error = SendAlert(ssl, alert_warning, close_notify); - if (ssl->error < 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + else { + /* try to send close notify, not an error if can't */ + if (!ssl->options.isClosed && !ssl->options.connReset && + !ssl->options.sentNotify) { + ssl->error = SendAlert(ssl, alert_warning, close_notify); + if (ssl->error < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.sentNotify = 1; /* don't send close_notify twice */ + if (ssl->options.closeNotify) + ret = SSL_SUCCESS; + else { + ret = SSL_SHUTDOWN_NOT_DONE; + WOLFSSL_LEAVE("SSL_shutdown()", ret); + return ret; + } } - ssl->options.sentNotify = 1; /* don't send close_notify twice */ - if (ssl->options.closeNotify) - ret = SSL_SUCCESS; - else - ret = SSL_SHUTDOWN_NOT_DONE; - WOLFSSL_LEAVE("SSL_shutdown()", ret); - return ret; + /* call wolfSSL_shutdown again for bidirectional shutdown */ + if (ssl->options.sentNotify && !ssl->options.closeNotify) { + ret = wolfSSL_read(ssl, &tmp, 0); + if (ret < 0) { + WOLFSSL_ERROR(ssl->error); + ret = SSL_FATAL_ERROR; + } else if (ssl->options.closeNotify) { + ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ + ret = SSL_SUCCESS; + } + } } - /* call wolfSSL_shutdown again for bidirectional shutdown */ - if (ssl->options.sentNotify && !ssl->options.closeNotify) { - ret = wolfSSL_read(ssl, &tmp, 0); - if (ret < 0) { - WOLFSSL_ERROR(ssl->error); +#ifdef OPENSSL_EXTRA + /* reset WOLFSSL structure state for possible re-use */ + if (ret == SSL_SUCCESS) { + if (wolfSSL_clear(ssl) != SSL_SUCCESS) { + WOLFSSL_MSG("could not clear WOLFSSL"); ret = SSL_FATAL_ERROR; - } else if (ssl->options.closeNotify) { - ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ - ret = SSL_SUCCESS; } } +#endif WOLFSSL_LEAVE("SSL_shutdown()", ret); @@ -1948,6 +2157,17 @@ int wolfSSL_shutdown(WOLFSSL* ssl) } +/* get current error state value */ +int wolfSSL_state(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + return ssl->error; +} + + int wolfSSL_get_error(WOLFSSL* ssl, int ret) { WOLFSSL_ENTER("SSL_get_error"); @@ -2051,6 +2271,66 @@ void wolfSSL_FreeArrays(WOLFSSL* ssl) } } +/* Set option to indicate that the resources are not to be freed after + * handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.keepResources = 1; + + return 0; +} + +/* Free the handshake resources after handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + FreeHandshakeResources(ssl); + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS context object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->useClientOrder = 1; + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_UseClientSuites(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.useClientOrder = 1; + + return 0; +} const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) { @@ -2148,7 +2428,6 @@ const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl) return NULL; } - int wolfSSL_GetKeySize(WOLFSSL* ssl) { if (ssl) @@ -2243,7 +2522,6 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl) #endif /* ATOMIC_USER */ #ifndef NO_CERTS - int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) { int ret = BAD_FUNC_ARG; @@ -2267,6 +2545,7 @@ int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) if (*pDer == NULL) { return MEMORY_ERROR; } + XMEMSET(*pDer, 0, sizeof(DerBuffer) + length); der = *pDer; der->type = type; @@ -2355,8 +2634,10 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) #ifdef HAVE_OCSP if (cm->ocsp) FreeOCSP(cm->ocsp, 1); + XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL); #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(WOLFSSL_HAPROXY) if (cm->ocsp_stapling) FreeOCSP(cm->ocsp_stapling, 1); #endif @@ -2480,41 +2761,157 @@ int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +static struct cipher{ + unsigned char type; + const char *name; +} cipher_tbl[] = { + #ifndef NO_AES -static const char *EVP_AES_128_CBC = "AES-128-CBC"; -static const char *EVP_AES_192_CBC = "AES-192-CBC"; -static const char *EVP_AES_256_CBC = "AES-256-CBC"; + {AES_128_CBC_TYPE, "AES-128-CBC"}, + {AES_192_CBC_TYPE, "AES-192-CBC"}, + {AES_256_CBC_TYPE, "AES-256-CBC"}, #if defined(OPENSSL_EXTRA) - static const char *EVP_AES_128_CTR = "AES-128-CTR"; - static const char *EVP_AES_192_CTR = "AES-192-CTR"; - static const char *EVP_AES_256_CTR = "AES-256-CTR"; + {AES_128_CTR_TYPE, "AES-128-CTR"}, + {AES_192_CTR_TYPE, "AES-192-CTR"}, + {AES_256_CTR_TYPE, "AES-256-CTR"}, + + {AES_128_ECB_TYPE, "AES-128-ECB"}, + {AES_192_ECB_TYPE, "AES-192-ECB"}, + {AES_256_ECB_TYPE, "AES-256-ECB"}, #endif -static const int EVP_AES_SIZE = 11; + #endif #ifndef NO_DES3 -static const char *EVP_DES_CBC = "DES-CBC"; -static const int EVP_DES_SIZE = 7; + {DES_CBC_TYPE, "DES-CBC"}, + {DES_ECB_TYPE, "DES-ECB"}, -static const char *EVP_DES_EDE3_CBC = "DES-EDE3-CBC"; -static const int EVP_DES_EDE3_SIZE = 12; + {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC"}, + {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB"}, #endif #ifdef HAVE_IDEA -static const char *EVP_IDEA_CBC = "IDEA-CBC"; -static const int EVP_IDEA_SIZE = 8; + {IDEA_CBC_TYPE, "IDEA-CBC"}, #endif + { 0, NULL} +} ; -/* our KeyPemToDer password callback, password in userData */ -static INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) { - (void)rw; - if (userdata == NULL) - return 0; + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"DES-CBC", "DES"}, + {"DES-CBC", "des"}, + {"DES-EDE3-CBC", "DES3"}, + {"DES-EDE3-CBC", "des3"}, + {"DES-EDE3-ECB", "des-ede3-ecb"}, + {"IDEA-CBC", "IDEA"}, + {"IDEA-CBC", "idea"}, + {"AES-128-CBC", "AES128"}, + {"AES-128-CBC", "aes128"}, + {"AES-192-CBC", "AES192"}, + {"AES-192-CBC", "aes192"}, + {"AES-256-CBC", "AES256"}, + {"AES-256-CBC", "aes256"}, + { NULL, NULL} + }; + + const struct cipher *ent ; + const struct alias *al ; + + WOLFSSL_ENTER("EVP_get_cipherbyname"); + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } - XSTRNCPY(passwd, (char*)userdata, sz); - return min((word32)sz, (word32)XSTRLEN((char*)userdata)); + for( ent = cipher_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (WOLFSSL_EVP_CIPHER *)ent->name; + } + + return NULL; +} + + +#ifndef NO_AES +static char *EVP_AES_128_CBC; +static char *EVP_AES_192_CBC; +static char *EVP_AES_256_CBC; +#if defined(OPENSSL_EXTRA) + static char *EVP_AES_128_CTR; + static char *EVP_AES_192_CTR; + static char *EVP_AES_256_CTR; + + static char *EVP_AES_128_ECB; + static char *EVP_AES_192_ECB; + static char *EVP_AES_256_ECB; +#endif +static const int EVP_AES_SIZE = 11; +#endif + +#ifndef NO_DES3 +static char *EVP_DES_CBC; +static char *EVP_DES_ECB; +static const int EVP_DES_SIZE = 7; + +static char *EVP_DES_EDE3_CBC; +static char *EVP_DES_EDE3_ECB; +static const int EVP_DES_EDE3_SIZE = 12; +#endif + +#ifdef HAVE_IDEA +static char *EVP_IDEA_CBC; +static const int EVP_IDEA_SIZE = 8; +#endif + +void wolfSSL_EVP_init(void) +{ +#ifndef NO_AES + EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC"); + EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC"); + EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC"); + +#if defined(OPENSSL_EXTRA) + EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR"); + EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR"); + EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR"); + + EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB"); + EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB"); + EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB"); +#endif +#endif + +#ifndef NO_DES3 + EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC"); + EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB"); + + EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC"); + EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB"); +#endif + +#ifdef HAVE_IDEA + EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC"); +#endif +} + +/* our KeyPemToDer password callback, password in userData */ +static INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) +{ + (void)rw; + + if (userdata == NULL) + return 0; + + XSTRNCPY(passwd, (char*)userdata, sz); + return min((word32)sz, (word32)XSTRLEN((char*)userdata)); } #endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ @@ -2611,6 +3008,12 @@ void wolfSSL_ERR_print_errors_fp(FILE* fp, int err) fprintf(fp, "%s", data); } +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +void wolfSSL_ERR_dump_errors_fp(FILE* fp) +{ + wc_ERR_print_errors_fp(fp); +} +#endif #endif @@ -2814,20 +3217,29 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) { Signer* signers; int ret = 0; - word32 row = HashSigner(hash); + word32 row; - if (wc_LockMutex(&cm->caLock) != 0) - return ret; + if (cm == NULL || hash == NULL) { + return ret; + } + + row = HashSigner(hash); + + if (wc_LockMutex(&cm->caLock) != 0) { + return ret; + } signers = cm->caTable[row]; while (signers) { byte* subjectHash; - #ifndef NO_SKID - subjectHash = signers->subjectKeyIdHash; - #else - subjectHash = signers->subjectNameHash; - #endif + + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { - ret = 1; + ret = 1; /* success */ break; } signers = signers->next; @@ -3032,7 +3444,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } - WOLFSSL_MSG(" Parsed new trusted peer cert"); + WOLFSSL_MSG("\tParsed new trusted peer cert"); peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap, DYNAMIC_TYPE_CERT); @@ -3062,7 +3474,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) #endif if (AlreadyTrustedPeer(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + WOLFSSL_MSG("\tAlready have this CA, not adding again"); (void)ret; } else { @@ -3117,7 +3529,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) wc_UnLockMutex(&cm->tpLock); } else { - WOLFSSL_MSG(" Trusted Peer Cert Mutex Lock failed"); + WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed"); FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); FreeTrustedPeer(peerCert, cm->heap); @@ -3125,12 +3537,12 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) } } - WOLFSSL_MSG(" Freeing parsed trusted peer cert"); + WOLFSSL_MSG("\tFreeing parsed trusted peer cert"); FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG(" Freeing der trusted peer cert"); + WOLFSSL_MSG("\tFreeing der trusted peer cert"); FreeDer(&der); - WOLFSSL_MSG(" OK Freeing der trusted peer cert"); + WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert"); WOLFSSL_LEAVE("AddTrustedPeer", ret); return SSL_SUCCESS; @@ -3165,7 +3577,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) InitDecodedCert(cert, der->buffer, der->length, cm->heap); ret = ParseCert(cert, CA_TYPE, verify, cm); - WOLFSSL_MSG(" Parsed new CA"); + WOLFSSL_MSG("\tParsed new CA"); #ifndef NO_SKID subjectHash = cert->extSubjKeyId; @@ -3181,7 +3593,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (cm->minRsaKeySz < 0 || cert->pubKeySize < (word16)cm->minRsaKeySz) { ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG(" CA RSA key size error"); + WOLFSSL_MSG("\tCA RSA key size error"); } break; #endif /* !NO_RSA */ @@ -3190,19 +3602,19 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (cm->minEccKeySz < 0 || cert->pubKeySize < (word16)cm->minEccKeySz) { ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG(" CA ECC key size error"); + WOLFSSL_MSG("\tCA ECC key size error"); } break; #endif /* HAVE_ECC */ default: - WOLFSSL_MSG(" No key size check done on CA"); + WOLFSSL_MSG("\tNo key size check done on CA"); break; /* no size check if key type is not in switch */ } } if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { - WOLFSSL_MSG(" Can't add as CA if not actually one"); + WOLFSSL_MSG("\tCan't add as CA if not actually one"); ret = NOT_CA_ERROR; } #ifndef ALLOW_INVALID_CERTSIGN @@ -3210,12 +3622,12 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { /* Intermediate CA certs are required to have the keyCertSign * extension set. User loaded root certs are not. */ - WOLFSSL_MSG(" Doesn't have key usage certificate signing"); + WOLFSSL_MSG("\tDoesn't have key usage certificate signing"); ret = NOT_CA_ERROR; } #endif else if (ret == 0 && AlreadySigner(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + WOLFSSL_MSG("\tAlready have this CA, not adding again"); (void)ret; } else if (ret == 0) { @@ -3225,10 +3637,14 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) ret = MEMORY_ERROR; else { signer->keyOID = cert->keyOID; - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } signer->pathLength = cert->pathLength; signer->pathLengthSet = cert->pathLengthSet; #ifndef IGNORE_NAME_CONSTRAINTS @@ -3265,21 +3681,21 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) cm->caCacheCallback(der->buffer, (int)der->length, type); } else { - WOLFSSL_MSG(" CA Mutex Lock failed"); + WOLFSSL_MSG("\tCA Mutex Lock failed"); ret = BAD_MUTEX_E; FreeSigner(signer, cm->heap); } } } - WOLFSSL_MSG(" Freeing Parsed CA"); + WOLFSSL_MSG("\tFreeing Parsed CA"); FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - WOLFSSL_MSG(" Freeing der CA"); + WOLFSSL_MSG("\tFreeing der CA"); FreeDer(pDer); - WOLFSSL_MSG(" OK Freeing der CA"); + WOLFSSL_MSG("\t\tOK Freeing der CA"); WOLFSSL_LEAVE("AddCA", ret); @@ -3452,7 +3868,7 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, ret = wc_Des3_CbcDecryptWithKey(der->buffer, der->buffer, der->length, key, info->iv); #endif /* NO_DES3 */ -#if !defined(NO_AES) && defined(HAVE_AES_CBC) +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT) if (XSTRNCMP(info->name, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, key, AES_128_KEY_SIZE, info->iv); @@ -3462,7 +3878,7 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, else if (XSTRNCMP(info->name, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, key, AES_256_KEY_SIZE, info->iv); -#endif /* !NO_AES && HAVE_AES_CBC */ +#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */ #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3584,6 +4000,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; + case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; break; case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; @@ -3792,6 +4209,9 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, { int ret = 0; void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); +#ifdef WOLFSSL_TLS13 + int cnt = 0; +#endif /* we may have a user cert chain, try to consume */ if (type == CERT_TYPE && info->consumed < sz) { @@ -3802,7 +4222,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif byte* chainBuffer = staticBuffer; int dynamicBuffer = 0; - word32 bufferSz = FILE_BUFFER_SIZE; + word32 bufferSz = sizeof(staticBuffer); long consumed = info->consumed; word32 idx = 0; int gotOne = 0; @@ -3849,6 +4269,9 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, } if (ret == 0) { gotOne = 1; +#ifdef WOLFSSL_TLS13 + cnt++; +#endif if ((idx + part->length) > bufferSz) { WOLFSSL_MSG(" Cert Chain bigger than buffer"); ret = BUFFER_E; @@ -3892,12 +4315,18 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer, idx); ssl->buffers.weOwnCertChain = 1; } +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = cnt; +#endif } else if (ctx) { FreeDer(&ctx->certChain); ret = AllocDer(&ctx->certChain, idx, type, heap); if (ret == 0) { XMEMCPY(ctx->certChain->buffer, chainBuffer, idx); } +#ifdef WOLFSSL_TLS13 + ctx->certChainCnt = cnt; +#endif } } @@ -3918,7 +4347,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, int ret = 0; int eccKey = 0; int rsaKey = 0; + int resetSuites = 0; void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + int devId = ctx ? ctx->devId : ((ssl) ? ssl->devId : INVALID_DEVID); #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -3945,6 +4376,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, return MEMORY_E; #endif + XMEMSET(info, 0, sizeof(EncryptedInfo)); info->set = 0; info->ctx = ctx; info->consumed = 0; @@ -4081,9 +4513,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) { FreeDer(&ctx->certificate); /* Make sure previous is free'd */ #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); if (ctx->ourCert) { - XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + if (ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } ctx->ourCert = NULL; } #endif @@ -4127,19 +4561,21 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, return MEMORY_E; #endif - ret = wc_InitRsaKey(key, 0); + ret = wc_InitRsaKey_ex(key, heap, devId); if (ret == 0) { if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length) != 0) { #ifdef HAVE_ECC /* could have DER ECC (or pkcs8 ecc), no easy way to tell */ eccKey = 1; /* so try it out */ + #else + WOLFSSL_MSG("RSA decode failed and ECC not enabled to try"); + ret = SSL_BAD_FILE; #endif - if (!eccKey) - ret = SSL_BAD_FILE; } else { /* check that the size of the RSA key is enough */ int RsaSz = wc_RsaEncryptSize((RsaKey*)key); + if (ssl) { if (RsaSz < ssl->options.minRsaKeySz) { ret = RSA_KEY_SIZE_E; @@ -4154,10 +4590,15 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } rsaKey = 1; (void)rsaKey; /* for no ecc builds */ + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + resetSuites = 1; + } } - } - wc_FreeRsaKey(key); + wc_FreeRsaKey(key); + } #ifdef WOLFSSL_SMALL_STACK XFREE(key, heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -4173,7 +4614,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, word32 idx = 0; ecc_key key; - wc_ecc_init(&key); + ret = wc_ecc_init_ex(&key, heap, devId); + if (ret != 0) { + return ret; + } + if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, der->length) != 0) { wc_ecc_free(&key); @@ -4198,10 +4643,16 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, wc_ecc_free(&key); eccKey = 1; - if (ctx) - ctx->haveStaticECC = 1; - if (ssl) + if (ssl) { ssl->options.haveStaticECC = 1; + } + else if (ctx) { + ctx->haveStaticECC = 1; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } } #endif /* HAVE_ECC */ } @@ -4224,21 +4675,31 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (DecodeToKey(cert, 0) < 0) { WOLFSSL_MSG("Decode to key failed"); + FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return SSL_BAD_FILE; } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + if (ssl && ssl->ctx->haveECDSAsig) { + WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off"); + ssl->options.haveECDSAsig = 0; /* may turn back on next */ + } + switch (cert->signatureOID) { case CTC_SHAwECDSA: case CTC_SHA256wECDSA: case CTC_SHA384wECDSA: case CTC_SHA512wECDSA: WOLFSSL_MSG("ECDSA cert signature"); - if (ctx) - ctx->haveECDSAsig = 1; if (ssl) ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; break; default: WOLFSSL_MSG("Not ECDSA cert signature"); @@ -4246,24 +4707,24 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #ifdef HAVE_ECC - if (ctx) { - ctx->pkCurveOID = cert->pkCurveOID; + if (ssl) { + ssl->pkCurveOID = cert->pkCurveOID; #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { - ctx->haveECC = 1; + ssl->options.haveECC = 1; } #else - ctx->haveECC = ctx->haveECDSAsig; + ssl->options.haveECC = ssl->options.haveECDSAsig; #endif } - if (ssl) { - ssl->pkCurveOID = cert->pkCurveOID; + else if (ctx) { + ctx->pkCurveOID = cert->pkCurveOID; #ifndef WC_STRICT_SIG if (cert->keyOID == ECDSAk) { - ssl->options.haveECC = 1; + ctx->haveECC = 1; } #else - ssl->options.haveECC = ssl->options.haveECDSAsig; + ctx->haveECC = ctx->haveECDSAsig; #endif } #endif @@ -4322,6 +4783,26 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } + if (ssl && resetSuites) { + word16 havePSK = 0; + word16 haveRSA = 0; + + #ifndef NO_PSK + if (ssl->options.havePSK) { + havePSK = 1; + } + #endif + #ifndef NO_RSA + haveRSA = 1; + #endif + + /* let's reset suites */ + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + return SSL_SUCCESS; } @@ -4341,6 +4822,25 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, &consumed, 0); +#ifdef WOLFSSL_WPAS +#ifdef HAVE_CRL + if (ret < 0) { + DerBuffer* der = NULL; + EncryptedInfo info; + + WOLFSSL_MSG("Trying a CRL"); + if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info, + NULL) == 0) { + WOLFSSL_MSG(" Proccessed a CRL"); + wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, + der->length,SSL_FILETYPE_ASN1, 0); + FreeDer(&der); + used += info.consumed; + continue; + } + } +#endif +#endif if (ret < 0) { if(consumed > 0) { /* Made progress in file */ @@ -4437,7 +4937,7 @@ int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm, } } - return BufferLoadCRL(cm->crl, buff, sz, type); + return BufferLoadCRL(cm->crl, buff, sz, type, 0); } @@ -4491,7 +4991,12 @@ int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) cm->crl = NULL; return SSL_FAILURE; } + + #ifdef HAVE_CRL_IO + cm->crl->crlIOCb = EmbedCrlLookup; + #endif } + cm->crlEnabled = 1; if (options & WOLFSSL_CRL_CHECKALL) cm->crlCheckAll = 1; @@ -4558,9 +5063,10 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, info, &eccKey); if (ret != 0) { FreeDer(&der); - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } InitDecodedCert(cert, der->buffer, der->length, cm->heap); @@ -4909,12 +5415,12 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, } dynamic = 1; } - else if (sz < 0) { + else if (sz <= 0) { XFCLOSE(file); return SSL_BAD_FILE; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else { if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) @@ -4922,7 +5428,7 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); #ifdef HAVE_CRL else if (type == CRL_TYPE) - ret = BufferLoadCRL(crl, myBuffer, sz, format); + ret = BufferLoadCRL(crl, myBuffer, sz, format, 0); #endif else ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL, @@ -4944,7 +5450,6 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, int ret = SSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations"); - (void)path; if (ctx == NULL || (file == NULL && path == NULL) ) return SSL_FAILURE; @@ -4953,95 +5458,35 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, ret = ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); if (ret == SSL_SUCCESS && path) { - /* try to load each regular file in path */ - #ifdef USE_WINDOWS_API - WIN32_FIND_DATAA FindFileData; - HANDLE hFind; - #ifdef WOLFSSL_SMALL_STACK - char* name = NULL; - #else - char name[MAX_FILENAME_SZ]; - #endif - +#ifndef NO_WOLFSSL_DIR + char* name = NULL; #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) + ReadDirCtx* readCtx = NULL; + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) return MEMORY_E; - #endif - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ - 4); - XSTRNCAT(name, "\\*", 3); - - hFind = FindFirstFileA(name, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) { - WOLFSSL_MSG("FindFirstFile for path verify locations failed"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return BAD_PATH_ERROR; - } - - do { - if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 3); - XSTRNCAT(name, "\\", 2); - XSTRNCAT(name, FindFileData.cFileName, MAX_FILENAME_SZ/2); - - ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL); - } - } while (ret == SSL_SUCCESS && FindNextFileA(hFind, &FindFileData)); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - FindClose(hFind); - #elif !defined(NO_WOLFSSL_DIR) - struct dirent* entry; - DIR* dir = opendir(path); - #ifdef WOLFSSL_SMALL_STACK - char* name = NULL; #else - char name[MAX_FILENAME_SZ]; - #endif - - if (dir == NULL) { - WOLFSSL_MSG("opendir path verify locations failed"); - return BAD_PATH_ERROR; - } - - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) { - closedir(dir); - return MEMORY_E; - } + ReadDirCtx readCtx[1]; #endif - while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - } else if (s.st_mode & S_IFREG) - ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL); + /* try to load each regular file in path */ + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL); + if (ret != SSL_SUCCESS) + break; + ret = wc_ReadDirNext(readCtx, path, &name); } + wc_ReadDirClose(readCtx); #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - closedir(dir); + XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif +#else + ret = NOT_COMPILED_IN; +#endif } return ret; @@ -5089,7 +5534,7 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, sz = XFTELL(file); XREWIND(file); - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { WOLFSSL_MSG("CertManagerVerify file bad size"); XFCLOSE(file); return SSL_BAD_FILE; @@ -5105,7 +5550,7 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, dynamic = 1; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format); @@ -5220,6 +5665,17 @@ int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb) return SSL_SUCCESS; } +#ifdef HAVE_CRL_IO +int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb) +{ + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->crl->crlIOCb = cb; + + return SSL_SUCCESS; +} +#endif int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, int type, int monitor) @@ -5278,6 +5734,16 @@ int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) return BAD_FUNC_ARG; } +#ifdef HAVE_CRL_IO +int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) + return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options) { @@ -5319,6 +5785,17 @@ int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) return BAD_FUNC_ARG; } +#ifdef HAVE_CRL_IO +int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif + #endif /* HAVE_CRL */ @@ -5372,7 +5849,7 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) sz = XFTELL(file); XREWIND(file); - if (sz < 0) { + if (sz <= 0) { ret = SSL_BAD_FILE; } else if (sz > (long)sizeof(staticBuffer)) { @@ -5388,7 +5865,7 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) } if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) { + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { ret = SSL_BAD_FILE; } else { @@ -5458,7 +5935,7 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, sz = XFTELL(file); XREWIND(file); - if (sz < 0) { + if (sz <= 0) { ret = SSL_BAD_FILE; } else if (sz > (long)sizeof(staticBuffer)) { @@ -5473,7 +5950,7 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, dynamic = 1; } if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, @@ -5625,12 +6102,12 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, } dynamic = 1; } - else if (sz < 0) { + else if (sz <= 0) { XFCLOSE(file); return SSL_BAD_FILE; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else { if (ssl) @@ -5668,230 +6145,755 @@ int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) #ifdef OPENSSL_EXTRA /* put SSL type in extra for now, not very common */ -int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) { - WOLFSSL_ENTER("wolfSSL_use_certificate_file"); - if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, - ssl, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; + WOLFSSL_EVP_PKEY* local; - return SSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + local = wolfSSL_PKEY_new(); + if (local == NULL) { + return NULL; + } + + local->type = type; + local->pkey_sz = (int)inSz; + local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (local->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(local); + local = NULL; + } + else { + XMEMCPY(local->pkey.ptr, *in, inSz); + } + + if (out != NULL) { + *out = local; + } + + return local; } -int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) +long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) { - WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); - if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, - ssl, 0, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; - + WOLFSSL_STUB("wolfSSL_ctrl"); + (void)ssl; + (void)cmd; + (void)opt; + (void)pt; return SSL_FAILURE; } -int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) +long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) { - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); - if (ProcessFile(ssl->ctx, file, SSL_FILETYPE_PEM, CERT_TYPE, - ssl, 1, NULL) == SSL_SUCCESS) - return SSL_SUCCESS; - - return SSL_FAILURE; + WOLFSSL_STUB("wolfSSL_CTX_ctrl"); + (void)ctx; + (void)cmd; + (void)opt; + (void)pt; + return SSL_FAILURE; } +#ifndef NO_CERTS +int wolfSSL_check_private_key(const WOLFSSL* ssl) +{ + DecodedCert der; + word32 size; + byte* buff; + int ret; - -#if !defined(NO_WOLFSSL_CLIENT) -/* Return the amount of random bytes copied over or error case. - * ssl : ssl struct after handshake - * out : buffer to hold random bytes - * outSz : either 0 (return max buffer sz) or size of out buffer + if (ssl == NULL) { + return SSL_FAILURE; + } + + size = ssl->buffers.certificate->length; + buff = ssl->buffers.certificate->buffer; + InitDecodedCert(&der, buff, size, ssl->heap); + if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) { + FreeDecodedCert(&der); + return SSL_FAILURE; + } + + size = ssl->buffers.key->length; + buff = ssl->buffers.key->buffer; + ret = wc_CheckPrivateKey(buff, size, &der); + FreeDecodedCert(&der); + return ret; +} + + +/* Looks for the extension matching the passed in nid * - * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information. + * c : if not null then is set to status value -2 if multiple occurances + * of the extension are found, -1 if not found, 0 if found and not + * critical, and 1 if found and critical. + * nid : Extension OID to be found. + * idx : if NULL return first extension found match, otherwise start search at + * idx location and set idx to the location of extension returned. + * returns NULL or a pointer to an WOLFSSL_STACK holding extension structure + * + * NOTE code for decoding extensions is in asn.c DecodeCertExtensions -- + * use already decoded extension in this function to avoid decoding twice. + * Currently we do not make use of idx since getting pre decoded extensions. */ -int wolfSSL_get_client_random(WOLFSSL* ssl, unsigned char* out, int outSz) +void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx) { - int size; + WOLFSSL_STACK* sk = NULL; + WOLFSSL_ASN1_OBJECT* obj = NULL; - /* return max size of buffer */ - if (outSz == 0) { - return RAN_LEN; - } + WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i"); - if (ssl == NULL || out == NULL || outSz < 0) { - return BAD_FUNC_ARG; + if (x509 == NULL) { + return NULL; } - if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays struct not saved after handshake"); - return BAD_FUNC_ARG; + if (c != NULL) { + *c = -1; /* default to not found */ } - if (outSz > RAN_LEN) { - size = RAN_LEN; - } - else { - size = outSz; + sk = (STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( + sizeof(STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + return NULL; } + XMEMSET(sk, 0, sizeof(STACK_OF(WOLFSSL_ASN1_OBJECT))); - XMEMCPY(out, ssl->arrays->clientRandom, size); - return size; -} -#endif /* !defined(NO_WOLFSSL_CLIENT) */ + switch (nid) { + case BASIC_CA_OID: + if (x509->basicConstSet) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (c != NULL) { + *c = x509->basicConstCrit; + } + obj->type = BASIC_CA_OID; + } + else { + WOLFSSL_MSG("No Basic Constraint set"); + } + break; -#ifdef HAVE_ECC + case ALT_NAMES_OID: + { + DNS_entry* dns; -/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ -int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) -{ - if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) - return BAD_FUNC_ARG; + if (x509->subjAltNameSet && x509->altNames != NULL) { + /* alt names are DNS_entry structs */ + if (c != NULL) { + if (x509->altNames->next != NULL) { + *c = -2; /* more then one found */ + } + else { + *c = x509->subjAltNameCrit; + } + } - ctx->eccTempKeySz = sz; + dns = x509->altNames; + while (dns != NULL) { + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = ALT_NAMES_OID; + obj->obj = (byte*)dns->name; + dns = dns->next; + /* last dns in list add at end of function */ + if (dns != NULL) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != + SSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + } + } + else { + WOLFSSL_MSG("No Alt Names set"); + } + } + break; - return SSL_SUCCESS; -} + case CRL_DIST_OID: + if (x509->CRLdistSet && x509->CRLInfo != NULL) { + if (c != NULL) { + *c = x509->CRLdistCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CRL_DIST_OID; + obj->obj = x509->CRLInfo; + obj->objSz = x509->CRLInfoSz; + } + else { + WOLFSSL_MSG("No CRL dist set"); + } + break; + case AUTH_INFO_OID: + if (x509->authInfoSet && x509->authInfo != NULL) { + if (c != NULL) { + *c = x509->authInfoCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = AUTH_INFO_OID; + obj->obj = x509->authInfo; + obj->objSz = x509->authInfoSz; + } + else { + WOLFSSL_MSG("No Auth Info set"); + } + break; -/* Set Temp SSL EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ -int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) -{ - if (ssl == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) - return BAD_FUNC_ARG; + case AUTH_KEY_OID: + if (x509->authKeyIdSet) { + if (c != NULL) { + *c = x509->authKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = AUTH_KEY_OID; + obj->obj = x509->authKeyId; + obj->objSz = x509->authKeyIdSz; + } + else { + WOLFSSL_MSG("No Auth Key set"); + } + break; - ssl->eccTempKeySz = sz; + case SUBJ_KEY_OID: + if (x509->subjKeyIdSet) { + if (c != NULL) { + *c = x509->subjKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = SUBJ_KEY_OID; + obj->obj = x509->subjKeyId; + obj->objSz = x509->subjKeyIdSz; + } + else { + WOLFSSL_MSG("No Subject Key set"); + } + break; - return SSL_SUCCESS; -} + case CERT_POLICY_OID: + #ifdef WOLFSSL_CERT_EXT + { + int i; -#endif /* HAVE_ECC */ + if (x509->certPoliciesNb > 0) { + if (c != NULL) { + if (x509->certPoliciesNb > 1) { + *c = -2; + } + else { + *c = 0; + } + } + for (i = 0; i < x509->certPoliciesNb - 1; i++) { + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CERT_POLICY_OID; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) + != SSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CERT_POLICY_OID; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + } + #else + #ifdef WOLFSSL_SEP + if (x509->certPolicySet) { + if (c != NULL) { + *c = x509->certPolicyCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CERT_POLICY_OID; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + #else + WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT"); + #endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_CERT_EXT */ + break; + case KEY_USAGE_OID: + if (x509->keyUsageSet) { + if (c != NULL) { + *c = x509->keyUsageCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = KEY_USAGE_OID; + obj->obj = (byte*)&(x509->keyUsage); + obj->objSz = sizeof(word16); + } + else { + WOLFSSL_MSG("No Key Usage set"); + } + break; + case INHIBIT_ANY_OID: + WOLFSSL_MSG("INHIBIT ANY extension not supported"); + break; -int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file, - int format) -{ - WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file"); + case EXT_KEY_USAGE_OID: + if (x509->extKeyUsageSrc != NULL) { + if (c != NULL) { + if (x509->extKeyUsageCount > 1) { + *c = -2; + } + else { + *c = x509->extKeyUsageCrit; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = EXT_KEY_USAGE_OID; + obj->obj = x509->extKeyUsageSrc; + obj->objSz = x509->extKeyUsageSz; + } + else { + WOLFSSL_MSG("No Extended Key Usage set"); + } + break; - return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format); -} + case NAME_CONS_OID: + WOLFSSL_MSG("Name Constraint OID extension not supported"); + break; + case PRIV_KEY_USAGE_PERIOD_OID: + WOLFSSL_MSG("Private Key Usage Period extension not supported"); + break; -int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) -{ - WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file"); + case SUBJECT_INFO_ACCESS: + WOLFSSL_MSG("Subject Info Access extension not supported"); + break; - return wolfSSL_use_PrivateKey_file(ssl, file, format); -} + case POLICY_MAP_OID: + WOLFSSL_MSG("Policy Map extension not supported"); + break; -#endif /* OPENSSL_EXTRA */ + case POLICY_CONST_OID: + WOLFSSL_MSG("Policy Constraint extension not supported"); + break; -#ifdef HAVE_NTRU + case ISSUE_ALT_NAMES_OID: + WOLFSSL_MSG("Issue Alt Names extension not supported"); + break; -int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file"); - if (ctx == NULL) - return SSL_FAILURE; + case TLS_FEATURE_OID: + WOLFSSL_MSG("TLS Feature extension not supported"); + break; - if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) - == SSL_SUCCESS) { - ctx->haveNTRU = 1; - return SSL_SUCCESS; + default: + WOLFSSL_MSG("Unsupported/Unknown extension OID"); } - return SSL_FAILURE; -} - -#endif /* HAVE_NTRU */ + if (obj != NULL) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != SSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + else { /* no ASN1 object found for extension, free stack */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + (void)idx; -#endif /* NO_FILESYSTEM */ + return sk; +} -void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) +/* this function makes the assumption that out buffer is big enough for digest*/ +static int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out, + unsigned int* outSz, const WOLFSSL_EVP_MD* evp, + WOLFSSL_ENGINE* eng) { - WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); - if (mode & SSL_VERIFY_PEER) { - ctx->verifyPeer = 1; - ctx->verifyNone = 0; /* in case previously set */ - } + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int hashSz; - if (mode == SSL_VERIFY_NONE) { - ctx->verifyNone = 1; - ctx->verifyPeer = 0; /* in case previously set */ + if (XSTRLEN(evp) < 3) { + /* do not try comparing strings if size is too small */ + return SSL_FAILURE; } - if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) - ctx->failNoCert = 1; + if (XSTRNCMP("SHA", evp, 3) == 0) { + if (XSTRLEN(evp) > 3) { + if (XSTRNCMP("SHA256", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA256; + } + else if (XSTRNCMP("SHA384", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA384; + } + else if (XSTRNCMP("SHA512", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA512; + } + else { + WOLFSSL_MSG("Unknown SHA hash"); + } + } + else { + hash = WC_HASH_TYPE_SHA; + } + } + else if (XSTRNCMP("MD2", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD2; + } + else if (XSTRNCMP("MD4", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD4; + } + else if (XSTRNCMP("MD5", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD5; + } - if (mode & SSL_VERIFY_FAIL_EXCEPT_PSK) { - ctx->failNoCert = 0; /* fail on all is set to fail on PSK */ - ctx->failNoCertxPSK = 1; + hashSz = wc_HashGetDigestSize(hash); + if (hashSz < 0) { + WOLFSSL_LEAVE("wolfSSL_EVP_Digest", hashSz); + return SSL_FAILURE; } + *outSz = hashSz; - ctx->verifyCallback = vc; + (void)eng; + if (wc_Hash(hash, in, inSz, out, *outSz) == 0) { + return SSL_SUCCESS; + } + else { + return SSL_FAILURE; + } } -void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) +int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, + unsigned char* buf, unsigned int* len) { - WOLFSSL_ENTER("wolfSSL_set_verify"); - if (mode & SSL_VERIFY_PEER) { - ssl->options.verifyPeer = 1; - ssl->options.verifyNone = 0; /* in case previously set */ - } + WOLFSSL_ENTER("wolfSSL_X509_digest"); - if (mode == SSL_VERIFY_NONE) { - ssl->options.verifyNone = 1; - ssl->options.verifyPeer = 0; /* in case previously set */ + if (x509 == NULL || digest == NULL) { + return SSL_FAILURE; } - if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) - ssl->options.failNoCert = 1; + return wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf, + len, digest, NULL); +} - if (mode & SSL_VERIFY_FAIL_EXCEPT_PSK) { - ssl->options.failNoCert = 0; /* fail on all is set to fail on PSK */ - ssl->options.failNoCertxPSK = 1; + +int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); + if (ssl == NULL || pkey == NULL ) { + return SSL_FAILURE; } - ssl->verifyCallback = vc; + return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, SSL_FILETYPE_ASN1); } -/* store user ctx for verify callback */ -void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) +int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der, + long derSz) { - WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); - if (ssl) - ssl->verifyCbCtx = ctx; + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return SSL_FAILURE; + } + + (void)pri; /* type of private key */ + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, SSL_FILETYPE_ASN1); } -/* store context CA Cache addition callback */ -void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) +#ifndef NO_RSA +int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) { - if (ctx && ctx->cm) - ctx->cm->caCacheCallback = cb; + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return SSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, SSL_FILETYPE_ASN1); } +#endif +int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, int derSz) +{ + long idx; -#if defined(PERSIST_CERT_CACHE) + WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); + if (der != NULL && ssl != NULL) { + if (ProcessBuffer(NULL, der, derSz, SSL_FILETYPE_ASN1, CERT_TYPE, ssl, + &idx, 0) == SSL_SUCCESS) + return SSL_SUCCESS; + } -#if !defined(NO_FILESYSTEM) + (void)idx; + return SSL_FAILURE; +} -/* Persist cert cache to file */ -int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) + +int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) { - WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); + long idx; - if (ctx == NULL || fname == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_use_certificate"); + if (x509 != NULL && ssl != NULL && x509->derCert != NULL) { + if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, + SSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == SSL_SUCCESS) + return SSL_SUCCESS; + } - return CM_SaveCertCache(ctx->cm, fname); + (void)idx; + return SSL_FAILURE; +} +#endif /* NO_CERTS */ + + +int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) +{ + WOLFSSL_ENTER("wolfSSL_use_certificate_file"); + if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, + ssl, 0, NULL) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_FAILURE; +} + + +int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); + if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, + ssl, 0, NULL) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_FAILURE; +} + + +int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); + if (ProcessFile(ssl->ctx, file, SSL_FILETYPE_PEM, CERT_TYPE, + ssl, 1, NULL) == SSL_SUCCESS) + return SSL_SUCCESS; + + return SSL_FAILURE; +} + + +#ifdef HAVE_ECC + +/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ +int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) +{ + if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) + return BAD_FUNC_ARG; + + ctx->eccTempKeySz = sz; + + return SSL_SUCCESS; +} + + +/* Set Temp SSL EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ +int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) +{ + if (ssl == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) + return BAD_FUNC_ARG; + + ssl->eccTempKeySz = sz; + + return SSL_SUCCESS; +} + +#endif /* HAVE_ECC */ + + + + +int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file, + int format) +{ + WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file"); + + return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format); +} + + +int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) +{ + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file"); + + return wolfSSL_use_PrivateKey_file(ssl, file, format); +} + + +/* Copies the master secret over to out buffer. If outSz is 0 returns the size + * of master secret. + * + * ses : a session from completed TLS/SSL handshake + * out : buffer to hold copy of master secret + * outSz : size of out buffer + * returns : number of bytes copied into out buffer on success + * less then or equal to 0 is considered a failure case + */ +int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz) +{ + int size; + + if (outSz == 0) { + return SECRET_LEN; + } + + if (ses == NULL || out == NULL || outSz < 0) { + return 0; + } + + if (outSz > SECRET_LEN) { + size = SECRET_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ses->masterSecret, size); + return size; +} + + +int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses) +{ + (void)ses; + return SECRET_LEN; +} + +#endif /* OPENSSL_EXTRA */ + +#ifdef HAVE_NTRU + +int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file"); + if (ctx == NULL) + return SSL_FAILURE; + + if (ProcessFile(ctx, file, SSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) + == SSL_SUCCESS) { + ctx->haveNTRU = 1; + return SSL_SUCCESS; + } + + return SSL_FAILURE; +} + +#endif /* HAVE_NTRU */ + + +#endif /* NO_FILESYSTEM */ + + +void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); + if (mode & SSL_VERIFY_PEER) { + ctx->verifyPeer = 1; + ctx->verifyNone = 0; /* in case previously set */ + } + + if (mode == SSL_VERIFY_NONE) { + ctx->verifyNone = 1; + ctx->verifyPeer = 0; /* in case previously set */ + } + + if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ctx->failNoCert = 1; + + if (mode & SSL_VERIFY_FAIL_EXCEPT_PSK) { + ctx->failNoCert = 0; /* fail on all is set to fail on PSK */ + ctx->failNoCertxPSK = 1; + } + + ctx->verifyCallback = vc; +} + + +void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) +{ + WOLFSSL_ENTER("wolfSSL_set_verify"); + if (mode & SSL_VERIFY_PEER) { + ssl->options.verifyPeer = 1; + ssl->options.verifyNone = 0; /* in case previously set */ + } + + if (mode == SSL_VERIFY_NONE) { + ssl->options.verifyNone = 1; + ssl->options.verifyPeer = 0; /* in case previously set */ + } + + if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ssl->options.failNoCert = 1; + + if (mode & SSL_VERIFY_FAIL_EXCEPT_PSK) { + ssl->options.failNoCert = 0; /* fail on all is set to fail on PSK */ + ssl->options.failNoCertxPSK = 1; + } + + ssl->verifyCallback = vc; +} + + +/* store user ctx for verify callback */ +void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); + if (ssl) + ssl->verifyCbCtx = ctx; +} + + +/* store context CA Cache addition callback */ +void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) +{ + if (ctx && ctx->cm) + ctx->cm->caCacheCallback = cb; +} + + +#if defined(PERSIST_CERT_CACHE) + +#if !defined(NO_FILESYSTEM) + +/* Persist cert cache to file */ +int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) +{ + WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); + + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; + + return CM_SaveCertCache(ctx->cm, fname); } @@ -5988,6 +6990,9 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) session = GetSessionClient(ssl, id, len); if (session) { if (SetSession(ssl, session) != SSL_SUCCESS) { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif WOLFSSL_MSG("SetSession failed"); session = NULL; } @@ -6000,6 +7005,10 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); } + #ifdef HAVE_EXT_CACHE + else + wolfSSL_SESSION_free(session); + #endif return SSL_SUCCESS; } @@ -6327,9 +7336,14 @@ long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) if (mode == SSL_SESS_CACHE_OFF) ctx->sessionCacheOff = 1; - if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR) + if ((mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) ctx->sessionCacheFlushOff = 1; +#ifdef HAVE_EXT_CACHE + if ((mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + ctx->internalCacheOff = 1; +#endif + return SSL_SUCCESS; } @@ -6799,14 +7813,14 @@ int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) XMEMSET(ctx->suites, 0, sizeof(Suites)); } - return (SetCipherList(ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; + return (SetCipherList(ctx, ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; } int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) { WOLFSSL_ENTER("wolfSSL_set_cipher_list"); - return (SetCipherList(ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; + return (SetCipherList(ssl->ctx, ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; } @@ -6879,6 +7893,8 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, const byte* secret, word32 secretSz) { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); if (ssl == NULL) { @@ -6917,18 +7933,35 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } /* If the supplied secret is NULL, randomly generate a new secret. */ - if (secret == NULL) - wc_RNG_GenerateBlock(ssl->rng, + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->buffers.dtlsCookieSecret.buffer, secretSz); + } else XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); - return 0; + return ret; } #endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ +#ifdef OPENSSL_EXTRA + WOLFSSL_METHOD* wolfSSLv23_method(void) { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("wolfSSLv23_method"); +#ifndef NO_WOLFSSL_CLIENT + m = wolfSSLv23_client_method(); +#else + m = wolfSSLv23_server_method(); +#endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } +#endif /* OPENSSL_EXTRA */ /* client only parts */ #ifndef NO_WOLFSSL_CLIENT @@ -6994,6 +8027,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_ENTER("DTLSv1_2_client_method_ex"); if (method) InitSSL_Method(method, MakeDTLSv1_2()); + (void)heap; return method; } #endif @@ -7013,6 +8047,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return result; } + /* please see note at top of README if you get an error from connect */ int wolfSSL_connect(WOLFSSL* ssl) { @@ -7024,6 +8059,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, errno = 0; #endif + if (ssl == NULL) + return BAD_FUNC_ARG; + if (ssl->options.side != WOLFSSL_CLIENT_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); return SSL_FATAL_ERROR; @@ -7068,6 +8106,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.connectState = CLIENT_HELLO_SENT; WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; case CLIENT_HELLO_SENT : neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : @@ -7097,45 +8136,24 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = HELLO_AGAIN; WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; case HELLO_AGAIN : if (ssl->options.certOnly) return SSL_SUCCESS; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); +#endif + #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { /* re-init hashes, exclude first hello and verify request */ -#ifndef NO_OLD_TLS - wc_InitMd5(&ssl->hsHashes->hashMd5); - if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha)) - != 0) { + if ((ssl->error = InitHandshakeHashes(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } -#endif - if (IsAtLeastTLSv1_2(ssl)) { - #ifndef NO_SHA256 - if ( (ssl->error = wc_InitSha256( - &ssl->hsHashes->hashSha256)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - #ifdef WOLFSSL_SHA384 - if ( (ssl->error = wc_InitSha384( - &ssl->hsHashes->hashSha384)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - #ifdef WOLFSSL_SHA512 - if ( (ssl->error = wc_InitSha512( - &ssl->hsHashes->hashSha512)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - } if ( (ssl->error = SendClientHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; @@ -7145,6 +8163,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = HELLO_AGAIN_REPLY; WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; case HELLO_AGAIN_REPLY : #ifdef WOLFSSL_DTLS @@ -7168,6 +8187,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = FIRST_REPLY_DONE; WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; case FIRST_REPLY_DONE : #ifndef NO_CERTS @@ -7182,6 +8202,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.connectState = FIRST_REPLY_FIRST; WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; case FIRST_REPLY_FIRST : if (!ssl->options.resuming) { @@ -7194,6 +8215,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = FIRST_REPLY_SECOND; WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; case FIRST_REPLY_SECOND : #ifndef NO_CERTS @@ -7207,6 +8229,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.connectState = FIRST_REPLY_THIRD; WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; case FIRST_REPLY_THIRD : if ( (ssl->error = SendChangeCipher(ssl)) != 0) { @@ -7216,6 +8239,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_MSG("sent: change cipher spec"); ssl->options.connectState = FIRST_REPLY_FOURTH; WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; case FIRST_REPLY_FOURTH : if ( (ssl->error = SendFinished(ssl)) != 0) { @@ -7225,6 +8249,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_MSG("sent: finished"); ssl->options.connectState = FINISHED_DONE; WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; case FINISHED_DONE : /* get response */ @@ -7236,6 +8261,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = SECOND_REPLY_DONE; WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + FALL_THROUGH; case SECOND_REPLY_DONE: #ifndef NO_HANDSHAKE_DONE_CB @@ -7250,7 +8276,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* NO_HANDSHAKE_DONE_CB */ if (!ssl->options.dtls) { - FreeHandshakeResources(ssl); + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } #ifdef WOLFSSL_DTLS else { @@ -7342,14 +8370,22 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, InitSSL_Method(method, MakeDTLSv1_2()); method->side = WOLFSSL_SERVER_END; } + (void)heap; return method; } #endif + int wolfSSL_accept(WOLFSSL* ssl) { word16 havePSK = 0; word16 haveAnon = 0; + +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_accept_TLSv13(ssl); +#endif + WOLFSSL_ENTER("SSL_accept()"); #ifdef HAVE_ERRNO_H @@ -7423,20 +8459,47 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } +#ifdef WOLFSSL_TLS13 ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; case ACCEPT_CLIENT_HELLO_DONE : - ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; - WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case ACCEPT_HELLO_RETRY_REQUEST_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_FIRST_REPLY_DONE : +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } +#endif if ( (ssl->error = SendServerHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } ssl->options.acceptState = SERVER_HELLO_SENT; WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; case SERVER_HELLO_SENT : #ifndef NO_CERTS @@ -7448,6 +8511,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.acceptState = CERT_SENT; WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; case CERT_SENT : #ifndef NO_CERTS @@ -7459,6 +8523,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.acceptState = CERT_STATUS_SENT; WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; case CERT_STATUS_SENT : if (!ssl->options.resuming) @@ -7468,18 +8533,22 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = KEY_EXCHANGE_SENT; WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); + FALL_THROUGH; case KEY_EXCHANGE_SENT : #ifndef NO_CERTS - if (!ssl->options.resuming) - if (ssl->options.verifyPeer) + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } + } + } #endif ssl->options.acceptState = CERT_REQ_SENT; WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; case CERT_REQ_SENT : if (!ssl->options.resuming) @@ -7489,6 +8558,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = SERVER_HELLO_DONE; WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); + FALL_THROUGH; case SERVER_HELLO_DONE : if (!ssl->options.resuming) { @@ -7500,6 +8570,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_SECOND_REPLY_DONE : #ifdef HAVE_SESSION_TICKET @@ -7512,6 +8583,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* HAVE_SESSION_TICKET */ ssl->options.acceptState = TICKET_SENT; WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; case TICKET_SENT: if ( (ssl->error = SendChangeCipher(ssl)) != 0) { @@ -7520,6 +8592,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = CHANGE_CIPHER_SENT; WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); + FALL_THROUGH; case CHANGE_CIPHER_SENT : if ( (ssl->error = SendFinished(ssl)) != 0) { @@ -7529,6 +8602,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.acceptState = ACCEPT_FINISHED_DONE; WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; case ACCEPT_FINISHED_DONE : if (ssl->options.resuming) @@ -7540,6 +8614,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_THIRD_REPLY_DONE : #ifndef NO_HANDSHAKE_DONE_CB @@ -7554,7 +8629,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* NO_HANDSHAKE_DONE_CB */ if (!ssl->options.dtls) { - FreeHandshakeResources(ssl); + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } #ifdef WOLFSSL_DTLS else { @@ -7602,7 +8679,6 @@ int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) #endif /* NO_HANDSHAKE_DONE_CB */ - int wolfSSL_Cleanup(void) { int ret = SSL_SUCCESS; @@ -7634,9 +8710,10 @@ int wolfSSL_Cleanup(void) if (wc_FreeMutex(&count_mutex) != 0) ret = BAD_MUTEX_E; -#if defined(HAVE_ECC) && defined(FP_ECC) - wc_ecc_fp_free(); -#endif + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + ret = WC_CLEANUP_E; + } return ret; } @@ -7678,6 +8755,8 @@ int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to) if (ssl == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ssl->timeout = to; return SSL_SUCCESS; @@ -7690,6 +8769,8 @@ int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) if (ctx == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ctx->timeout = to; return SSL_SUCCESS; @@ -7709,10 +8790,26 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) WOLFSSL_ENTER("GetSessionClient"); + if (ssl->ctx->sessionCacheOff) + return NULL; + if (ssl->options.side == WOLFSSL_SERVER_END) return NULL; len = min(SERVER_ID_LEN, (word32)len); + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©); + if (ret != NULL) + return ret; + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, len, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -7763,6 +8860,32 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #endif /* NO_CLIENT_CACHE */ +/* Restore the master secret and session information for certificates. + * + * ssl The SSL/TLS object. + * session The cached session to restore. + * masterSecret The master secret from the cached session. + * restoreSessionCerts Restoring session certificates is required. + */ +static INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, + byte* masterSecret, byte restoreSessionCerts) +{ + (void)ssl; + (void)restoreSessionCerts; + + if (masterSecret) + XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); +#ifdef SESSION_CERTS + /* If set, we should copy the session certs into the ssl object + * from the session we are returning so we can resume */ + if (restoreSessionCerts) { + ssl->session.chain = session->chain; + ssl->session.version = session->version; + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; + } +#endif /* SESSION_CERTS */ +} WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) @@ -7792,6 +8915,21 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, else id = ssl->session.sessionID; +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + /* Attempt to retrieve the session from the external cache. */ + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (ret != NULL) { + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + return ret; + } + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -7821,19 +8959,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, if (LowResTimer() < (current->bornOn + current->timeout)) { WOLFSSL_MSG("Session valid"); ret = current; - if (masterSecret) - XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN); -#ifdef SESSION_CERTS - /* If set, we should copy the session certs into the ssl object - * from the session we are returning so we can resume */ - if (restoreSessionCerts) { - ssl->session.chain = ret->chain; - ssl->session.version = ret->version; - ssl->session.cipherSuite0 = ret->cipherSuite0; - ssl->session.cipherSuite = ret->cipherSuite; - } -#endif /* SESSION_CERTS */ - + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); } else { WOLFSSL_MSG("Session timed out"); } @@ -7895,10 +9021,29 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) } #ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_TLS13 + if (wc_LockMutex(&session_mutex) != 0) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + return BAD_MUTEX_E; + } + + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; + copyInto->namedGroup = copyFrom->namedGroup; + copyInto->ticketSeen = copyFrom->ticketSeen; + copyInto->ticketAdd = copyFrom->ticketAdd; + XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN); + + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == SSL_SUCCESS) + ret = BAD_MUTEX_E; + } +#endif /* If doing dynamic copy, need to alloc outside lock, then inside a lock * confirm the size still matches and memcpy */ if (doDynamicCopy) { - tmpBuff = XMALLOC(ticketLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); if (!tmpBuff) return MEMORY_ERROR; @@ -7914,7 +9059,7 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) } if (ret == SSL_SUCCESS) { - copyInto->ticket = tmpBuff; + copyInto->ticket = (byte*)tmpBuff; copyInto->isDynamic = 1; XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen); } @@ -7924,9 +9069,11 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) copyInto->ticket = copyInto->staticTicket; } - if (wc_UnLockMutex(&session_mutex) != 0) { - if (ret == SSL_SUCCESS) - ret = BAD_MUTEX_E; + if (doDynamicCopy) { + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == SSL_SUCCESS) + ret = BAD_MUTEX_E; + } } if (ret != SSL_SUCCESS) { @@ -7951,7 +9098,8 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) if (ret == SSL_SUCCESS) { ssl->options.resuming = 1; -#ifdef SESSION_CERTS +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET) && !defined(NO_PSK)) ssl->version = session->version; ssl->options.cipherSuite0 = session->cipherSuite0; ssl->options.cipherSuite = session->cipherSuite; @@ -7971,12 +9119,14 @@ static int get_locked_session_stats(word32* active, word32* total, int AddSession(WOLFSSL* ssl) { - word32 row, idx; + word32 row = 0; + word32 idx = 0; int error = 0; #ifdef HAVE_SESSION_TICKET byte* tmpBuff = NULL; int ticLen = 0; #endif + WOLFSSL_SESSION* session; if (ssl->options.sessionCacheOff) return 0; @@ -7989,44 +9139,70 @@ int AddSession(WOLFSSL* ssl) return 0; #endif - row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return error; - } - #ifdef HAVE_SESSION_TICKET ticLen = ssl->session.ticketLen; /* Alloc Memory here so if Malloc fails can exit outside of lock */ if(ticLen > SESSION_TICKET_LEN) { - tmpBuff = XMALLOC(ticLen, ssl->heap, + tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if(!tmpBuff) return MEMORY_E; } #endif - if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_EXT_CACHE + if (ssl->options.internalCacheOff) { + /* Create a new session object to be stored. */ + session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (session == NULL) { #ifdef HAVE_SESSION_TICKET - XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); #endif - return BAD_MUTEX_E; + return MEMORY_E; + } + XMEMSET(session, 0, sizeof(WOLFSSL_SESSION)); + session->isAlloced = 1; } + else +#endif + { + /* Use the session object in the cache for external cache if required. + */ + row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % + SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return error; + } - idx = SessionCache[row].nextIdx++; + if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return BAD_MUTEX_E; + } + + idx = SessionCache[row].nextIdx++; #ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; #endif + session = &SessionCache[row].Sessions[idx]; + } - XMEMCPY(SessionCache[row].Sessions[idx].masterSecret, - ssl->arrays->masterSecret, SECRET_LEN); - SessionCache[row].Sessions[idx].haveEMS = ssl->options.haveEMS; - XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, - ID_LEN); - SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; + if (!ssl->options.tls1_3) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + else + XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; - SessionCache[row].Sessions[idx].timeout = ssl->timeout; - SessionCache[row].Sessions[idx].bornOn = LowResTimer(); + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); #ifdef HAVE_SESSION_TICKET /* Check if another thread modified ticket since alloc */ @@ -8036,32 +9212,28 @@ int AddSession(WOLFSSL* ssl) if (error == 0) { /* Cleanup cache row's old Dynamic buff if exists */ - if(SessionCache[row].Sessions[idx].isDynamic) { - XFREE(SessionCache[row].Sessions[idx].ticket, - ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - SessionCache[row].Sessions[idx].ticket = NULL; + if(session->isDynamic) { + XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = NULL; } /* If too large to store in static buffer, use dyn buffer */ if (ticLen > SESSION_TICKET_LEN) { - SessionCache[row].Sessions[idx].ticket = tmpBuff; - SessionCache[row].Sessions[idx].isDynamic = 1; + session->ticket = tmpBuff; + session->isDynamic = 1; } else { - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; } } if (error == 0) { - SessionCache[row].Sessions[idx].ticketLen = ticLen; - XMEMCPY(SessionCache[row].Sessions[idx].ticket, - ssl->session.ticket, ticLen); + session->ticketLen = ticLen; + XMEMCPY(session->ticket, ssl->session.ticket, ticLen); } else { /* cleanup, reset state */ - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; - SessionCache[row].Sessions[idx].ticketLen = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; + session->ticketLen = 0; if (tmpBuff) { XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); tmpBuff = NULL; @@ -8071,19 +9243,35 @@ int AddSession(WOLFSSL* ssl) #ifdef SESSION_CERTS if (error == 0) { - SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count; - XMEMCPY(SessionCache[row].Sessions[idx].chain.certs, - ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH); - - SessionCache[row].Sessions[idx].version = ssl->version; - SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0; - SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite; + session->chain.count = ssl->session.chain.count; + XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * MAX_CHAIN_DEPTH); } #endif /* SESSION_CERTS */ +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET) && !defined(NO_PSK)) + if (error == 0) { + session->version = ssl->version; + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; + } +#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & !NO_PSK) */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) if (error == 0) { - SessionCache[row].totalCount++; - if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) - SessionCache[row].nextIdx = 0; + session->namedGroup = ssl->session.namedGroup; + session->ticketSeen = ssl->session.ticketSeen; + session->ticketAdd = ssl->session.ticketAdd; + } +#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + SessionCache[row].totalCount++; + if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) + SessionCache[row].nextIdx = 0; + } } #ifndef NO_CLIENT_CACHE if (error == 0) { @@ -8092,48 +9280,70 @@ int AddSession(WOLFSSL* ssl) WOLFSSL_MSG("Adding client cache entry"); - SessionCache[row].Sessions[idx].idLen = ssl->session.idLen; - XMEMCPY(SessionCache[row].Sessions[idx].serverID, - ssl->session.serverID, ssl->session.idLen); + session->idLen = ssl->session.idLen; + XMEMCPY(session->serverID, ssl->session.serverID, + ssl->session.idLen); - clientRow = HashSession(ssl->session.serverID, ssl->session.idLen, - &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - } else { - clientIdx = ClientCache[clientRow].nextIdx++; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + clientRow = HashSession(ssl->session.serverID, + ssl->session.idLen, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + } else { + clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = + ClientCache[clientRow].Clients[clientIdx].serverRow = (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = + ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + } } } else - SessionCache[row].Sessions[idx].idLen = 0; + session->idLen = 0; } #endif /* NO_CLIENT_CACHE */ #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - if (error == 0) { - word32 active = 0; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + word32 active = 0; - error = get_locked_session_stats(&active, NULL, NULL); - if (error == SSL_SUCCESS) { - error = 0; /* back to this function ok */ + error = get_locked_session_stats(&active, NULL, NULL); + if (error == SSL_SUCCESS) { + error = 0; /* back to this function ok */ - if (active > PeakSessions) - PeakSessions = active; + if (active > PeakSessions) + PeakSessions = active; + } } } #endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ - if (wc_UnLockMutex(&session_mutex) != 0) - return BAD_MUTEX_E; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (wc_UnLockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + } + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) + ssl->ctx->new_sess_cb(ssl, session); + if (ssl->options.internalCacheOff) + wolfSSL_SESSION_free(session); +#endif return error; } @@ -8713,8 +9923,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (hint == 0) ctx->server_hint[0] = 0; else { - XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN); - ctx->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + XSTRNCPY(ctx->server_hint, hint, sizeof(ctx->server_hint)); + ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } return SSL_SUCCESS; } @@ -8730,8 +9940,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (hint == 0) ssl->arrays->server_hint[0] = 0; else { - XSTRNCPY(ssl->arrays->server_hint, hint, MAX_PSK_ID_LEN); - ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + XSTRNCPY(ssl->arrays->server_hint, hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } return SSL_SUCCESS; } @@ -8872,6 +10083,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) FreeDer(&der); ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, NULL, NULL); +#ifdef WOLFSSL_WPAS + #ifndef NO_DSA + if (ret < 0) { + ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap, + NULL, NULL); + } + #endif +#endif } if (ret == 0) { @@ -9025,12 +10244,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + /* returns previous set cache size which stays constant */ long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz) { /* cache size fixed at compile time in wolfSSL */ (void)ctx; (void)sz; - return 0; + WOLFSSL_MSG("session cache is set at compile time"); + #ifndef NO_SESSION_CACHE + return SESSIONS_PER_ROW * SESSION_ROWS; + #else + return 0; + #endif } @@ -9064,15 +10289,71 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, STACK_OF(WOLFSSL_X509_NAME)* names) { - (void)ctx; - (void)names; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list"); + + if (ctx != NULL) + ctx->ca_names = names; } + STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s) + { + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list"); + + if (s == NULL) + return NULL; + + return s->ca_names; + } STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) { - (void)fname; - return 0; + WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "r"); + if (bio == NULL) + return NULL; + + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + subjectName = wolfSSL_X509_get_subject_name(cert); + if (subjectName == NULL) + break; + + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + break; + + /* Need a persistent copy of the subject name. */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + break; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + /* Clear pointers so freeing certificate doesn't free memory. */ + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* Put node on the front of the list. */ + node->num = (list == NULL) ? 1 : list->num + 1; + node->next = list; + list = node; + + wolfSSL_X509_free(cert); + cert = NULL; + } + + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + return list; } @@ -9121,6 +10402,31 @@ int wolfSSL_set_compression(WOLFSSL* ssl) word16 havePSK = 0; WOLFSSL_ENTER("SSL_set_accept_state"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + ecc_key key; + word32 idx = 0; + + if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { + wc_ecc_init(&key); + if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key, + ssl->buffers.key->length) != 0) { + ssl->options.haveECDSAsig = 0; + ssl->options.haveECC = 0; + ssl->options.haveStaticECC = 0; + } + wc_ecc_free(&key); + } + #endif + + #ifndef NO_DH + if (!ssl->options.haveDH && ssl->ctx->haveDH) { + ssl->buffers.serverDH_P = ssl->ctx->serverDH_P; + ssl->buffers.serverDH_G = ssl->ctx->serverDH_G; + ssl->options.haveDH = 1; + } + #endif + } ssl->options.side = WOLFSSL_SERVER_END; /* reset suites in case user switched */ @@ -9172,11 +10478,20 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) + { + (void)ctx; + WOLFSSL_ENTER("wolfSSL_CTX_get_options"); + WOLFSSL_MSG("wolfSSL options are set through API calls and macros"); + + return 0; + } + + long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) { - /* goahead calls with 0, do nothing */ WOLFSSL_ENTER("SSL_CTX_set_options"); - (void)ctx; + ctx->mask |= opt; return opt; } @@ -9216,12 +10531,37 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) + { + if (ctx == NULL) { + return NULL; + } + + return &(ctx->x509_store); + } + + +#ifndef NO_CERTS + void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) + { + if (ctx == NULL || str == NULL) { + return; + } + + /* free cert manager if have one */ + if (ctx->cm != NULL) { + wolfSSL_CertManagerFree(ctx->cm); + } + ctx->cm = str->cm; + ctx->x509_store.cache = str->cache; + } + WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( WOLFSSL_X509_STORE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert"); - if(ctx) + if (ctx) return ctx->current_cert; return NULL; } @@ -9243,6 +10583,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return ctx->error_depth; return SSL_FATAL_ERROR; } +#endif WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void) @@ -9265,6 +10606,30 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void) + { + static WOLFSSL_BIO_METHOD bio_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_bio"); + bio_meth.type = BIO_BIO; + + return &bio_meth; + } + + +#ifndef NO_FILESYSTEM + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) + { + static WOLFSSL_BIO_METHOD file_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_file"); + file_meth.type = BIO_FILE; + + return &file_meth; + } +#endif + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) { static WOLFSSL_BIO_METHOD meth; @@ -9276,6 +10641,17 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_s_socket"); + meth.type = BIO_SOCKET; + + return &meth; + } + + WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF) { WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, @@ -9283,15 +10659,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("BIO_new_socket"); if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = BIO_SOCKET; bio->close = (byte)closeF; - bio->eof = 0; - bio->ssl = 0; bio->fd = sfd; - bio->prev = 0; - bio->next = 0; bio->mem = NULL; - bio->memLen = 0; } return bio; } @@ -9309,28 +10681,41 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF) { - WOLFSSL_ENTER("BIO_set_ssl"); - b->ssl = ssl; - b->close = (byte)closeF; + WOLFSSL_ENTER("wolfSSL_BIO_set_ssl"); + + if (b != NULL) { + b->ssl = ssl; + b->close = (byte)closeF; /* add to ssl for bio free if SSL_free called before/instead of free_all? */ + } return 0; } + long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF) + { + WOLFSSL_ENTER("wolfSSL_BIO_set_fd"); + + if (b != NULL) { + b->fd = fd; + b->close = (byte)closeF; + } + + return SSL_SUCCESS; + } + + WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) { WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, DYNAMIC_TYPE_OPENSSL); WOLFSSL_ENTER("BIO_new"); if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = method->type; - bio->close = 0; - bio->eof = 0; bio->ssl = NULL; bio->mem = NULL; - bio->memLen = 0; - bio->fd = 0; bio->prev = NULL; bio->next = NULL; } @@ -9338,12 +10723,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) + int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p) { + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data"); + if (bio == NULL || p == NULL) return SSL_FATAL_ERROR; - *p = bio->mem; + *(byte **)p = bio->mem; return bio->memLen; } @@ -9384,17 +10771,31 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_BIO_free(WOLFSSL_BIO* bio) { /* unchain?, doesn't matter in goahead since from free all */ - WOLFSSL_ENTER("BIO_free"); + WOLFSSL_ENTER("wolfSSL_BIO_free"); if (bio) { + /* remove from pair by setting the paired bios pair to NULL */ + if (bio->pair != NULL) { + bio->pair->pair = NULL; + } + if (bio->close) { if (bio->ssl) wolfSSL_free(bio->ssl); if (bio->fd) CloseSocket(bio->fd); } + + #ifndef NO_FILESYSTEM + if (bio->type == BIO_FILE && bio->close == BIO_CLOSE) { + if (bio->file) { + XFCLOSE(bio->file); + } + } + #endif + if (bio->mem) - XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL); - XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + XFREE(bio, bio->heap, DYNAMIC_TYPE_OPENSSL); } return 0; } @@ -9412,15 +10813,46 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) + { + int sz; + char* pt; + + sz = wolfSSL_BIO_nread(bio, &pt, len); + + if (sz > 0) { + XMEMCPY(buf, pt, sz); + } + + return sz; + } + + int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) { int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; - WOLFSSL_ENTER("BIO_read"); + WOLFSSL_ENTER("wolfSSL_BIO_read"); + + if (bio && bio->type == BIO_BIO) { + return wolfSSL_BIO_BIO_read(bio, buf, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == BIO_FILE) { + return (int)XFREAD(buf, 1, len, bio->file); + } + #endif + if (bio && bio->type == BIO_MEMORY) { + len = min(len, bio->memLen); + XMEMCPY(buf, bio->mem, len); + return len; + } + /* already got eof, again is error */ - if (front->eof) + if (bio && front->eof) return SSL_FATAL_ERROR; while(bio && ((ssl = bio->ssl) == 0) ) @@ -9440,19 +10872,78 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) + static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, + int len) { - int ret; - WOLFSSL* ssl = 0; - WOLFSSL_BIO* front = bio; + /* internal function where arguments have already been sanity checked */ + int sz; + char* buf; - WOLFSSL_ENTER("BIO_write"); - /* already got eof, again is error */ - if (front->eof) - return SSL_FATAL_ERROR; + sz = wolfSSL_BIO_nwrite(bio, &buf, len); - while(bio && ((ssl = bio->ssl) == 0) ) - bio = bio->next; + /* test space for write */ + if (sz <= 0) { + WOLFSSL_MSG("No room left to write"); + return sz; + } + + XMEMCPY(buf, data, sz); + + return sz; + } + + + int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) + { + int ret; + WOLFSSL* ssl = 0; + WOLFSSL_BIO* front = bio; + byte* p; + + WOLFSSL_ENTER("wolfSSL_BIO_write"); + + if (bio && bio->type == BIO_BIO) { + return wolfSSL_BIO_BIO_write(bio, data, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == BIO_FILE) { + return (int)XFWRITE(data, 1, len, bio->file); + } + #endif + + if (bio && bio->type == BIO_MEMORY) { + /* Make buffer big enough to hold new data. */ + if (bio->mem == NULL) { + bio->mem = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) + return -1; + p = bio->mem; + } + else { + p = (byte*)XMALLOC(len + bio->memLen, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (p == NULL) + return -1; + XMEMCPY(p, bio->mem, bio->memLen); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = p; + p += bio->memLen; + } + + /* Put data on the end of the buffer. */ + XMEMCPY(p, data, len); + bio->memLen += len; + + return len; + } + + /* already got eof, again is error */ + if (bio && front->eof) + return SSL_FATAL_ERROR; + + while(bio && ((ssl = bio->ssl) == 0) ) + bio = bio->next; if (ssl == 0) return BAD_FUNC_ARG; @@ -9501,7 +10992,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, pem_password_cb cb) + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb) { WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb"); if (ctx != NULL) { @@ -9526,8 +11017,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) unsigned long wolfSSL_ERR_get_error(void) { - /* TODO: */ - return 0; + WOLFSSL_ENTER("wolfSSL_ERR_get_error"); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL, + NULL, NULL); + wc_RemoveErrorNode(-1); + return ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } #ifndef NO_MD5 @@ -9558,10 +11059,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (void)type; WOLFSSL_ENTER("wolfSSL_EVP_BytesToKey"); - wc_InitMd5(md5); + + if (wc_InitMd5(md5) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } /* only support MD5 for now */ - if (XSTRNCMP(md, "MD5", 3) != 0) return 0; + if (XSTRNCMP(md, "MD5", 3) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } /* only support CBC DES and AES for now */ #ifndef NO_DES3 @@ -9650,6 +11162,79 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA +#if !defined(NO_WOLFSSL_SERVER) +size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->serverRandom, size); + return size; +} +#endif /* !defined(NO_WOLFSSL_SERVER) */ + + +#if !defined(NO_WOLFSSL_CLIENT) +/* Return the amount of random bytes copied over or error case. + * ssl : ssl struct after handshake + * out : buffer to hold random bytes + * outSz : either 0 (return max buffer sz) or size of out buffer + * + * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information. + */ +size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->clientRandom, size); + return size; +} +#endif /* !defined(NO_WOLFSSL_CLIENT) */ + + unsigned long wolfSSLeay(void) { return SSLEAY_VERSION_NUMBER; @@ -9667,11 +11252,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_MD5 void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5) { + int ret; typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1]; (void)sizeof(md5_test); WOLFSSL_ENTER("MD5_Init"); - wc_InitMd5((Md5*)md5); + ret = wc_InitMd5((Md5*)md5); + (void)ret; } @@ -9858,12 +11445,89 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #endif /* WOLFSSL_SHA512 */ + static struct s_ent{ + const unsigned char macType; + const char *name; + } md_tbl[] = { + #ifndef NO_MD5 + {MD5, "MD5"}, + #endif /* NO_MD5 */ + + #ifndef NO_SHA + {SHA, "SHA"}, + #endif /* NO_SHA */ + + #ifdef WOLFSSL_SHA224 + {SHA224, "SHA224"}, + #endif /* WOLFSSL_SHA224 */ + + {SHA256, "SHA256"}, + + #ifdef WOLFSSL_SHA384 + {SHA384, "SHA384"}, + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + {SHA512, "SHA512"}, + #endif /* WOLFSSL_SHA512 */ + + {0, NULL} + } ; + +const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) +{ + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"MD5", "ssl3-md5"}, + {"SHA1", "ssl3-sha1"}, + { NULL, NULL} + }; + + const struct alias *al ; + const struct s_ent *ent ; + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for( ent = md_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (EVP_MD *)ent->name; + } + return NULL; +} + +static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type) +{ + const struct s_ent *ent ; + for( ent = md_tbl; ent->macType != 0; ent++) + if(type == ent->macType) { + return (WOLFSSL_EVP_MD *)ent->name; + } + return 0; +} + +int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + for( ent = md_tbl; ent->name != NULL; ent++) + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->macType; + } + return 0; +} + #ifndef NO_MD5 const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) { - static const char* type = "MD5"; + const char* type = EVP_get_digestbyname("MD5"); WOLFSSL_ENTER("EVP_md5"); return type; } @@ -9874,7 +11538,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_SHA const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) { - static const char* type = "SHA"; + const char* type = EVP_get_digestbyname("SHA"); WOLFSSL_ENTER("EVP_sha1"); return type; } @@ -9884,7 +11548,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void) { - static const char* type = "SHA224"; + const char* type = EVP_get_digestbyname("SHA224"); WOLFSSL_ENTER("EVP_sha224"); return type; } @@ -9894,7 +11558,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) { - static const char* type = "SHA256"; + const char* type = EVP_get_digestbyname("SHA256"); WOLFSSL_ENTER("EVP_sha256"); return type; } @@ -9903,7 +11567,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) { - static const char* type = "SHA384"; + const char* type = EVP_get_digestbyname("SHA384"); WOLFSSL_ENTER("EVP_sha384"); return type; } @@ -9914,19 +11578,45 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) { - static const char* type = "SHA512"; + const char* type = EVP_get_digestbyname("SHA512"); WOLFSSL_ENTER("EVP_sha512"); return type; } #endif /* WOLFSSL_SHA512 */ + WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void) + { + WOLFSSL_EVP_MD_CTX* ctx; + WOLFSSL_ENTER("EVP_MD_CTX_new"); + ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ctx){ + wolfSSL_EVP_MD_CTX_init(ctx); + } + return ctx; + } + + WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) + { + if (ctx) { + WOLFSSL_ENTER("EVP_MD_CTX_free"); + wolfSSL_EVP_MD_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) { WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); - (void)ctx; - /* do nothing */ + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX)); + } + + const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx) + { + if (!ctx) + return NULL; + return (const WOLFSSL_EVP_MD *)wolfSSL_EVP_get_md(ctx->macType); } #ifndef NO_AES @@ -9972,6 +11662,25 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return EVP_AES_256_CTR; } + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb"); + return EVP_AES_128_ECB; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb"); + return EVP_AES_192_ECB; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb"); + return EVP_AES_256_ECB; + } #endif /* NO_AES */ #ifndef NO_DES3 @@ -9980,13 +11689,25 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); return EVP_DES_CBC; } - - +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ecb"); + return EVP_DES_ECB; + } +#endif const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); return EVP_DES_EDE3_CBC; } +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb"); + return EVP_DES_EDE3_ECB; + } +#endif #endif /* NO_DES3 */ const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) @@ -10065,13 +11786,19 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("no type set"); return 0; /* failure */ } + ctx->bufUsed = 0; + ctx->lastUsed = 0; + ctx->flags = 0; #ifndef NO_AES + /* printf("cipherType=%d\n", ctx->cipherType); */ if (ctx->cipherType == AES_128_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_CBC); + WOLFSSL_MSG("EVP_AES_128_CBC"); ctx->cipherType = AES_128_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10088,9 +11815,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_192_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_CBC); + WOLFSSL_MSG("EVP_AES_192_CBC"); ctx->cipherType = AES_192_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10107,9 +11836,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_256_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_CBC); + WOLFSSL_MSG("EVP_AES_256_CBC"); ctx->cipherType = AES_256_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10127,14 +11858,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef WOLFSSL_AES_COUNTER else if (ctx->cipherType == AES_128_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_CTR); + WOLFSSL_MSG("EVP_AES_128_CTR"); ctx->cipherType = AES_128_CTR_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION); if (ret != 0) return ret; } @@ -10146,14 +11879,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_192_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_CTR); + WOLFSSL_MSG("EVP_AES_192_CTR"); ctx->cipherType = AES_192_CTR_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); + AES_ENCRYPTION); if (ret != 0) return ret; } @@ -10165,14 +11900,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_256_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_CTR); + WOLFSSL_MSG("EVP_AES_256_CTR"); ctx->cipherType = AES_256_CTR_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); + AES_ENCRYPTION); if (ret != 0) return ret; } @@ -10183,14 +11920,65 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } } #endif /* WOLFSSL_AES_CTR */ + else if (ctx->cipherType == AES_128_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_ECB"); + ctx->cipherType = AES_128_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + else if (ctx->cipherType == AES_192_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_ECB"); + ctx->cipherType = AES_192_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + if(ctx->enc) + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + else if (ctx->cipherType == AES_256_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_ECB"); + ctx->cipherType = AES_256_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } #endif /* NO_AES */ #ifndef NO_DES3 if (ctx->cipherType == DES_CBC_TYPE || (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_CBC); + WOLFSSL_MSG("EVP_DES_CBC"); ctx->cipherType = DES_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10203,12 +11991,32 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (iv && key == NULL) wc_Des_SetIV(&ctx->cipher.des, iv); } +#ifdef WOLFSSL_DES_ECB + else if (ctx->cipherType == DES_ECB_TYPE || + (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_ECB"); + ctx->cipherType = DES_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + } +#endif else if (ctx->cipherType == DES_EDE3_CBC_TYPE || (type && XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_EDE3_CBC); + WOLFSSL_MSG("EVP_DES_EDE3_CBC"); ctx->cipherType = DES_EDE3_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10224,12 +12032,30 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return ret; } } + else if (ctx->cipherType == DES_EDE3_ECB_TYPE || + (type && + XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_EDE3_ECB"); + ctx->cipherType = DES_EDE3_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + } #endif /* NO_DES3 */ #ifndef NO_RC4 if (ctx->cipherType == ARC4_TYPE || (type && XSTRNCMP(type, "ARC4", 4) == 0)) { WOLFSSL_MSG("ARC4"); ctx->cipherType = ARC4_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_STREAM_CIPHER; if (ctx->keyLen == 0) /* user may have already set */ ctx->keyLen = 16; /* default to 128 */ if (key) @@ -10240,8 +12066,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef HAVE_IDEA if (ctx->cipherType == IDEA_CBC_TYPE || (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { - WOLFSSL_MSG(EVP_IDEA_CBC); + WOLFSSL_MSG("EVP_IDEA_CBC"); ctx->cipherType = IDEA_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = IDEA_KEY_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -10328,6 +12155,17 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len); break; #endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif #ifdef WOLFSSL_AES_COUNTER case AES_128_CTR_TYPE : case AES_192_CTR_TYPE : @@ -10345,14 +12183,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl) else wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); break; - case DES_EDE3_CBC_TYPE : if (ctx->enc) ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); else ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); break; +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_ECB_TYPE : + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); + break; #endif +#endif /* !NO_DES3 */ #ifndef NO_RC4 case ARC4_TYPE : @@ -10380,13 +12225,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (ret != 0) { WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); - return 0; /* failuer */ + return 0; /* failure */ } WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); return SSL_SUCCESS; /* success */ } +#include "wolfcrypt/src/evp.c" + /* store for external read of iv, SSL_SUCCESS on success */ int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) @@ -10526,39 +12373,52 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* type) { WOLFSSL_ENTER("EVP_DigestInit"); + + if (ctx == NULL || type == NULL) { + return BAD_FUNC_ARG; + } + + + #ifdef WOLFSSL_ASYNC_CRYPT + /* compile-time validation of ASYNC_CTX_SIZE */ + typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? + 1 : -1]; + (void)sizeof(async_test); + #endif + if (XSTRNCMP(type, "SHA256", 6) == 0) { ctx->macType = SHA256; - wolfSSL_SHA256_Init((SHA256_CTX*)&ctx->hash); + wolfSSL_SHA256_Init(&(ctx->hash.sha256)); } #ifdef WOLFSSL_SHA224 else if (XSTRNCMP(type, "SHA224", 6) == 0) { ctx->macType = SHA224; - wolfSSL_SHA224_Init((SHA224_CTX*)&ctx->hash); + wolfSSL_SHA224_Init(&(ctx->hash.sha224)); } #endif #ifdef WOLFSSL_SHA384 else if (XSTRNCMP(type, "SHA384", 6) == 0) { ctx->macType = SHA384; - wolfSSL_SHA384_Init((SHA384_CTX*)&ctx->hash); + wolfSSL_SHA384_Init(&(ctx->hash.sha384)); } #endif #ifdef WOLFSSL_SHA512 else if (XSTRNCMP(type, "SHA512", 6) == 0) { ctx->macType = SHA512; - wolfSSL_SHA512_Init((SHA512_CTX*)&ctx->hash); + wolfSSL_SHA512_Init(&(ctx->hash.sha512)); } #endif #ifndef NO_MD5 else if (XSTRNCMP(type, "MD5", 3) == 0) { ctx->macType = MD5; - wolfSSL_MD5_Init((MD5_CTX*)&ctx->hash); + wolfSSL_MD5_Init(&(ctx->hash.md5)); } #endif #ifndef NO_SHA /* has to be last since would pick or 224, 256, 384, or 512 too */ else if (XSTRNCMP(type, "SHA", 3) == 0) { ctx->macType = SHA; - wolfSSL_SHA_Init((SHA_CTX*)&ctx->hash); + wolfSSL_SHA_Init(&(ctx->hash.sha)); } #endif /* NO_SHA */ else @@ -10689,6 +12549,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #else Hmac hmac[1]; #endif + void* heap = NULL; WOLFSSL_ENTER("HMAC"); if (!md) @@ -10702,22 +12563,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return NULL; #ifdef WOLFSSL_SMALL_STACK - hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_TMP_BUFFER); if (hmac == NULL) return NULL; #endif - if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) - if (wc_HmacUpdate(hmac, d, n) == 0) - if (wc_HmacFinal(hmac, md) == 0) { - if (md_len) - *md_len = (type == MD5) ? (int)MD5_DIGEST_SIZE - : (int)SHA_DIGEST_SIZE; - ret = md; + if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) { + if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) { + if (wc_HmacUpdate(hmac, d, n) == 0) { + if (wc_HmacFinal(hmac, md) == 0) { + if (md_len) + *md_len = (type == MD5) ? (int)MD5_DIGEST_SIZE + : (int)SHA_DIGEST_SIZE; + ret = md; + } } + } + wc_HmacFree(hmac); + } #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; @@ -10725,7 +12591,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_ERR_clear_error(void) { - /* TODO: */ + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + wc_ClearErrorNodes(); +#endif } @@ -10857,12 +12727,58 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_clear(WOLFSSL* ssl) { - (void)ssl; - /* TODO: GetErrors().Remove(); */ - return SSL_SUCCESS; - } - - + if (ssl == NULL) { + return SSL_FAILURE; + } + + ssl->options.isClosed = 0; + ssl->options.connReset = 0; + ssl->options.sentNotify = 0; + + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.handShakeDone = 0; + /* ssl->options.processReply = doProcessInit; */ + + ssl->keys.encryptionOn = 0; + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + + if (ssl->hsHashes != NULL) { +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + wc_InitMd5(&ssl->hsHashes->hashMd5); +#endif +#ifndef NO_SHA + if (wc_InitSha(&ssl->hsHashes->hashSha) != 0) + return SSL_FAILURE; +#endif +#endif +#ifndef NO_SHA256 + if (wc_InitSha256(&ssl->hsHashes->hashSha256) != 0) + return SSL_FAILURE; +#endif +#ifdef WOLFSSL_SHA384 + if (wc_InitSha384(&ssl->hsHashes->hashSha384) != 0) + return SSL_FAILURE; +#endif +#ifdef WOLFSSL_SHA512 + if (wc_InitSha512(&ssl->hsHashes->hashSha512) != 0) + return SSL_FAILURE; +#endif + } + +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif + + return SSL_SUCCESS; + } + + long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) { word32 tmptime; @@ -10927,9 +12843,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) { - /* TODO: maybe? */ (void)ctx; - return (~0); + #ifndef NO_SESSION_CACHE + return SESSIONS_PER_ROW * SESSION_ROWS; + #else + return 0; + #endif } unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, @@ -10943,18 +12862,86 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return 0; } + WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb( + WOLFSSL_CTX *ctx) + { + if (ctx == NULL || ctx->passwd_cb == NULL) { + return NULL; + } + + return ctx->passwd_cb; + } + + + WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata( + WOLFSSL_CTX *ctx) + { + if (ctx == NULL) { + return NULL; + } + + return ctx->userdata; + } + #endif /* OPENSSL_EXTRA */ #if defined(KEEP_PEER_CERT) + #ifdef SESSION_CERTS + /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object. + * + * x509 WOLFSSL_X509 object to decode into. + * in X509 DER data. + * len Length of the X509 DER data. + * returns the new certificate on success, otherwise NULL. + */ + static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif + + /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. + */ + InitDecodedCert(cert, (byte*)in, len, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) { + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + FreeDecodedCert(cert); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } + #endif + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_peer_certificate"); if (ssl->peerCert.issuer.sz) return &ssl->peerCert; - else - return 0; +#ifdef SESSION_CERTS + else if (ssl->session.chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, + ssl->session.chain.certs[0].length) == 0) { + return &ssl->peerCert; + } + } +#endif + return 0; } #endif /* KEEP_PEER_CERT */ @@ -11012,7 +12999,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("X509_get_issuer_name"); - if(cert) + if (cert && cert->issuer.sz != 0) return &cert->issuer; return NULL; } @@ -11021,7 +13008,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); - if(cert) + if (cert && cert->subject.sz != 0) return &cert->subject; return NULL; } @@ -11255,8 +13242,10 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) if (buf != NULL && text != NULL) { textSz = min(textSz, len); - XMEMCPY(buf, text, textSz); - buf[textSz] = '\0'; + if (textSz > 0) { + XMEMCPY(buf, text, textSz - 1); + buf[textSz - 1] = '\0'; + } } WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); @@ -11279,7 +13268,8 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) if (name->fullName.fullName && name->fullName.fullNameLen > 0) { switch (nid) { case ASN_COMMON_NAME: - ret = name->fullName.cnIdx; + if (pos != name->fullName.cnIdx) + ret = name->fullName.cnIdx; break; default: WOLFSSL_MSG("NID not yet implemented"); @@ -11636,7 +13626,6 @@ void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk) { } #endif /* NO_CERTS && OPENSSL_EXTRA */ - WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) { WOLFSSL_X509 *newX509 = NULL; @@ -11707,8 +13696,8 @@ WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); if (fileBuffer != NULL) { - int ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret > 0) { + int ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret == sz) { newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); } XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); @@ -11764,8 +13753,8 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) return NULL; } - ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret < 0) { + ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret != sz) { XFCLOSE(file); if (dynamic) XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); @@ -11902,6 +13891,7 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL, ssl->ctx->certificate->buffer, ssl->ctx->certificate->length); + ssl->ctx->ownOurCert = 1; } return ssl->ctx->ourCert; } @@ -11914,6 +13904,149 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA +/* return 1 on success 0 on fail */ +int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, + WOLFSSL_ASN1_OBJECT* obj) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || obj == NULL) { + return SSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.obj == NULL) { + sk->data.obj = obj; + sk->num += 1; + return SSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return SSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.obj = sk->data.obj; + node->next = sk->next; + sk->next = node; + sk->data.obj = obj; + sk->num += 1; + + return SSL_SUCCESS; +} + + +WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop( + STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_ASN1_OBJECT* obj; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + obj = sk->data.obj; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.obj = node->data.obj; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_ASN1); + } + else { /* last obj in stack */ + sk->data.obj = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return obj; +} + + +#ifndef NO_ASN +WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) +{ + WOLFSSL_ASN1_OBJECT* obj; + + obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL, + DYNAMIC_TYPE_ASN1); + if (obj == NULL) { + return NULL; + } + + XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT)); + return obj; +} + + +void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) +{ + if (obj == NULL) { + return; + } + + if (obj->dynamic == 1) { + if (obj->obj != NULL) { + WOLFSSL_MSG("Freeing ASN1 OBJECT data"); + XFREE(obj->obj, obj->heap, DYNAMIC_TYPE_ASN1); + } + } + + XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); +} + + +/* free structure for x509 stack */ +void wolfSSL_sk_ASN1_OBJECT_free(STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_ASN1_OBJECT_free(sk->data.obj); + } + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} + +int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in) +{ + /* + ASN1_STRING_to_UTF8() converts the string in to UTF8 format, + the converted data is allocated in a buffer in *out. + The length of out is returned or a negative error code. + The buffer *out should be free using OPENSSL_free(). + */ + (void)out; + (void)in; + WOLFSSL_STUB("ASN1_STRING_to_UTF8"); + return -1; +} +#endif /* NO_ASN */ + + int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, unsigned int len) { @@ -11926,8 +14059,23 @@ int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, void wolfSSL_set_connect_state(WOLFSSL* ssl) { - (void)ssl; - /* client by default */ + word16 haveRSA = 1; + word16 havePSK = 0; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.side = WOLFSSL_CLIENT_END; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } } #endif @@ -11949,8 +14097,21 @@ int wolfSSL_session_reused(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { + if (session == NULL) + return; + +#ifdef HAVE_EXT_CACHE + if (session->isAlloced) { + #ifdef HAVE_SESSION_TICKET + if (session->isDynamic) + XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else /* No need to free since cache is static */ (void)session; +#endif } #endif @@ -11967,6 +14128,8 @@ const char* wolfSSL_get_version(WOLFSSL* ssl) return "TLSv1.1"; case TLSv1_2_MINOR : return "TLSv1.2"; + case TLSv1_3_MINOR : + return "TLSv1.3"; default: return "unknown"; } @@ -12056,59 +14219,303 @@ const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) return wolfSSL_get_cipher_name_internal(ssl); } - -#ifdef OPENSSL_EXTRA - -char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) -{ - (void)cipher; - (void)in; - (void)len; - return 0; -} - - -#ifndef NO_SESSION_CACHE - -WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) -{ - /* sessions are stored statically, no need for reference count */ - return wolfSSL_get_session(ssl); -} - -#endif /* NO_SESSION_CACHE */ - -#ifndef NO_CERTS -void wolfSSL_X509_free(WOLFSSL_X509* x509) -{ - WOLFSSL_ENTER("wolfSSL_X509_free"); - ExternalFreeX509(x509); -} -#endif /* NO_CERTS */ - - -/* was do nothing */ -/* -void OPENSSL_free(void* buf) +#ifdef HAVE_ECC +/* Return the name of the curve used for key exchange as a printable string. + * + * ssl The SSL/TLS object. + * returns NULL if ECDH was not used, otherwise the name as a string. + */ +const char* wolfSSL_get_curve_name(WOLFSSL* ssl) { - (void)buf; + if (ssl == NULL) + return NULL; + if (ssl->specs.kea != ecdhe_psk_kea && + ssl->specs.kea != ecc_diffie_hellman_kea) + return NULL; + if (ssl->ecdhCurveOID == 0) + return NULL; + return wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); } -*/ +#endif +#ifdef OPENSSL_EXTRA -int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, - int* ssl) +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) { - (void)url; - (void)host; - (void)port; - (void)path; - (void)ssl; - return 0; -} + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + if (cipher == NULL || in == NULL) + return NULL; -WOLFSSL_METHOD* wolfSSLv2_client_method(void) + switch (cipher->ssl->specs.kea) { + case no_kea: + keaStr = "None"; + break; +#ifndef NO_RSA + case rsa_kea: + keaStr = "RSA"; + break; +#endif +#ifndef NO_DH + case diffie_hellman_kea: + keaStr = "DHE"; + break; +#endif + case fortezza_kea: + keaStr = "FZ"; + break; +#ifndef NO_PSK + case psk_kea: + keaStr = "PSK"; + break; + #ifndef NO_DH + case dhe_psk_kea: + keaStr = "DHEPSK"; + break; + #endif + #ifdef HAVE_ECC + case ecdhe_psk_kea: + keaStr = "ECDHEPSK"; + break; + #endif +#endif +#ifdef HAVE_NTRU + case ntru_kea: + keaStr = "NTRU"; + break; +#endif +#ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; +#endif + default: + keaStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.sig_algo) { + case anonymous_sa_algo: + authStr = "None"; + break; +#ifndef NO_RSA + case rsa_sa_algo: + authStr = "RSA"; + break; +#endif +#ifndef NO_DSA + case dsa_sa_algo: + authStr = "DSA"; + break; +#endif +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + authStr = "ECDSA"; + break; +#endif + default: + authStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.bulk_cipher_algorithm) { + case wolfssl_cipher_null: + encStr = "None"; + break; +#ifndef NO_RC4 + case wolfssl_rc4: + encStr = "RC4(128)"; + break; +#endif +#ifndef NO_DES3 + case wolfssl_triple_des: + encStr = "3DES(168)"; + break; +#endif +#ifdef HAVE_IDEA + case wolfssl_idea: + encStr = "IDEA(128)"; + break; +#endif +#ifndef NO_AES + case wolfssl_aes: + if (cipher->ssl->specs.key_size == 128) + encStr = "AES(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AES(256)"; + else + encStr = "AES(?)"; + break; + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESGCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESGCM(256)"; + else + encStr = "AESGCM(?)"; + break; + #endif + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESCCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESCCM(256)"; + else + encStr = "AESCCM(?)"; + break; + #endif +#endif +#ifdef HAVE_CHACHA + case wolfssl_chacha: + encStr = "CHACHA20/POLY1305(256)"; + break; +#endif +#ifdef HAVE_CAMELLIA + case wolfssl_camellia: + if (cipher->ssl->specs.key_size == 128) + encStr = "Camellia(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "Camellia(256)"; + else + encStr = "Camellia(?)"; + break; +#endif +#if defined(HAVE_HC128) && !defined(NO_HC128) + case wolfssl_hc128: + encStr = "HC128(128)"; + break; +#endif +#if defined(HAVE_RABBIT) && !defined(NO_RABBIT) + case wolfssl_rabbit: + encStr = "RABBIT(128)"; + break; +#endif + default: + encStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.mac_algorithm) { + case no_mac: + macStr = "None"; + break; +#ifndef NO_MD5 + case md5_mac: + macStr = "MD5"; + break; +#endif +#ifndef NO_SHA + case sha_mac: + macStr = "SHA1"; + break; +#endif +#ifdef HAVE_SHA224 + case sha224_mac: + macStr = "SHA224"; + break; +#endif +#ifndef NO_SHA256 + case sha256_mac: + macStr = "SHA256"; + break; +#endif +#ifdef HAVE_SHA384 + case sha384_mac: + macStr = "SHA384"; + break; +#endif +#ifdef HAVE_SHA512 + case sha512_mac: + macStr = "SHA512"; + break; +#endif +#ifdef HAVE_BLAKE2 + case blake2b_mac: + macStr = "BLAKE2b"; + break; +#endif + default: + macStr = "unknown"; + break; + } + + /* Build up the string by copying onto the end. */ + XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " ", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Kx=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, keaStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Au=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, authStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Enc=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, encStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Mac=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, macStr, len); + in[len-1] = '\0'; + + return ret; +} + + +#ifndef NO_SESSION_CACHE + +WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + /* sessions are stored statically, no need for reference count */ + return wolfSSL_get_session(ssl); +} + +#endif /* NO_SESSION_CACHE */ + +#ifndef NO_CERTS +void wolfSSL_X509_free(WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_X509_free"); + ExternalFreeX509(x509); +} +#endif /* NO_CERTS */ + + +int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, + int* ssl) +{ + (void)url; + (void)host; + (void)port; + (void)path; + (void)ssl; + return 0; +} + + +WOLFSSL_METHOD* wolfSSLv2_client_method(void) { return 0; } @@ -12159,7 +14566,8 @@ WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) { - (void)bio; + if (bio && bio->type == BIO_MEMORY) + return bio->memLen; return 0; } @@ -12241,7 +14649,6 @@ WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) return 0; } - int wolfSSL_COMP_add_compression_method(int method, void* data) { (void)method; @@ -12290,44 +14697,163 @@ int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, - const char* file, long len) + const char* file, long type) { +#ifndef NO_FILESYSTEM + int ret = SSL_FAILURE; + XFILE fp; + long sz; + byte* pem = NULL; + byte* curr = NULL; + byte* prev = NULL; + WOLFSSL_X509* x509; + + if (type != X509_FILETYPE_PEM) + return BAD_FUNC_ARG; + + fp = XFOPEN(file, "r"); + if (fp == NULL) + return BAD_FUNC_ARG; + + XFSEEK(fp, 0, XSEEK_END); + sz = XFTELL(fp); + XREWIND(fp); + + if (sz <= 0) + goto end; + + pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ret = MEMORY_ERROR; + goto end; + } + + /* Read in file which may be CRLs or certificates. */ + if (XFREAD(pem, (size_t)sz, 1, fp) != 1) + goto end; + + prev = curr = pem; + do { + if (XSTRNSTR((char*)curr, BEGIN_X509_CRL, (unsigned int)sz) != NULL) { +#ifdef HAVE_CRL + WOLFSSL_CERT_MANAGER* cm = lookup->store->cm; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != SSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + goto end; + } + } + + ret = BufferLoadCRL(cm->crl, curr, sz, SSL_FILETYPE_PEM, 1); + if (ret != SSL_SUCCESS) + goto end; +#endif + curr = (byte*)XSTRNSTR((char*)curr, END_X509_CRL, (unsigned int)sz); + } + else if (XSTRNSTR((char*)curr, BEGIN_CERT, (unsigned int)sz) != NULL) { + x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz, + SSL_FILETYPE_PEM); + if (x509 == NULL) + goto end; + ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509); + wolfSSL_X509_free(x509); + if (ret != SSL_SUCCESS) + goto end; + curr = (byte*)XSTRNSTR((char*)curr, END_CERT, (unsigned int)sz); + } + else + goto end; + + if (curr == NULL) + goto end; + + curr++; + sz -= (long)(curr - prev); + prev = curr; + } + while (ret == SSL_SUCCESS); + +end: + if (pem != NULL) + XFREE(pem, 0, DYNAMIC_TYPE_TMP_BUFFER); + XFCLOSE(fp); + return ret; +#else (void)lookup; (void)file; - (void)len; - return 0; + (void)type; + return SSL_FAILURE; +#endif } WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 }; + return &meth; } - WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 }; + return &meth; } - WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509_LOOKUP_METHOD* m) { - (void)store; + /* Method is a dummy value and is not needed. */ (void)m; - return 0; + /* Make sure the lookup has a back reference to the store. */ + store->lookup.store = store; + return &store->lookup; } #ifndef NO_CERTS +WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) +{ + WOLFSSL_X509* localX509 = NULL; + unsigned char* mem = NULL; + int ret; + word32 size; + + WOLFSSL_ENTER("wolfSSL_d2i_X509_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + return NULL; + } + size = ret; + + localX509 = wolfSSL_X509_d2i(NULL, mem, size); + if (localX509 == NULL) { + return NULL; + } + + if (x509 != NULL) { + *x509 = localX509; + } + + return localX509; +} + #if !defined(NO_ASN) && !defined(NO_PWDBASED) WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) { WC_PKCS12* localPkcs12 = NULL; - const unsigned char* mem = NULL; + unsigned char* mem = NULL; int ret; word32 size; @@ -12416,7 +14942,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WC_DerCertList* current = certList; *ca = (STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(STACK_OF(WOLFSSL_X509)), - heap, DYNAMIC_TYPE_PKCS); + heap, DYNAMIC_TYPE_X509); if (*ca == NULL) { if (pk != NULL) { XFREE(pk, heap, DYNAMIC_TYPE_PKCS); @@ -12442,7 +14968,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_X509* x509; x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_X509); InitX509(x509, 1, heap); InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { @@ -12506,7 +15032,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, /* Decode cert and place in X509 struct */ if (certData != NULL) { *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_X509); if (*cert == NULL) { if (pk != NULL) { XFREE(pk, heap, DYNAMIC_TYPE_PKCS); @@ -12542,8 +15068,9 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, /* get key type */ ret = BAD_STATE_E; if (pk != NULL) { /* decode key if present */ + /* using dynamic type public key because of wolfSSL_EVP_PKEY_free */ *pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), - heap, DYNAMIC_TYPE_PKCS); + heap, DYNAMIC_TYPE_PUBLIC_KEY); if (*pkey == NULL) { wolfSSL_X509_free(*cert); *cert = NULL; if (ca != NULL) { @@ -12582,7 +15109,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(*pkey, heap, DYNAMIC_TYPE_PKCS); *pkey = NULL; + XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; XFREE(pk, heap, DYNAMIC_TYPE_PKCS); return 0; } @@ -12593,7 +15120,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(*pkey, heap, DYNAMIC_TYPE_PKCS); *pkey = NULL; + XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; XFREE(pk, heap, DYNAMIC_TYPE_PKCS); WOLFSSL_MSG("Bad PKCS12 key format"); return 0; @@ -12610,7 +15137,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(*pkey, heap, DYNAMIC_TYPE_PKCS); *pkey = NULL; + XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; XFREE(pk, heap, DYNAMIC_TYPE_PKCS); WOLFSSL_MSG("Bad PKCS12 key format"); return 0; @@ -12637,6 +15164,18 @@ void wolfSSL_PKCS12_PBE_add(void) WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add"); } + + +WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) +{ + if (ctx == NULL) { + return NULL; + } + + return ctx->chain; +} + + int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) { int result = SSL_FATAL_ERROR; @@ -12678,6 +15217,8 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); store = NULL; } + else + store->isDynamic = 1; } return store; @@ -12686,7 +15227,7 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { - if (store != NULL) { + if (store != NULL && store->isDynamic) { if (store->cm != NULL) wolfSSL_CertManagerFree(store->cm); XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); @@ -12694,6 +15235,23 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) } +int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) +{ + int ret = SSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags"); + + if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) { + ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag); + } + + (void)store; + (void)flag; + + return ret; +} + + int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) { (void)store; @@ -12732,8 +15290,11 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, if (ctx != NULL) { ctx->store = store; ctx->current_cert = x509; + ctx->chain = sk; ctx->domain = NULL; +#ifdef HAVE_EX_DATA ctx->ex_data = NULL; +#endif ctx->userCtx = NULL; ctx->error = 0; ctx->error_depth = 0; @@ -12751,6 +15312,8 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) wolfSSL_X509_STORE_free(ctx->store); if (ctx->current_cert != NULL) wolfSSL_FreeX509(ctx->current_cert); + if (ctx->chain != NULL) + wolfSSL_sk_X509_free(ctx->chain); XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); } } @@ -12841,6 +15404,20 @@ void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) } +WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new() +{ + WOLFSSL_EVP_PKEY* pkey; + + pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey != NULL) { + XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); + } + + return pkey; +} + + void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) { if (key != NULL) { @@ -12885,29 +15462,58 @@ WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) { - (void)x509; - return 0; + WOLFSSL_ASN1_INTEGER* a; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber"); + + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a == NULL) + return NULL; + + /* Make sure there is space for the data, ASN.1 type and length. */ + if (x509->serialSz > (int)(sizeof(WOLFSSL_ASN1_INTEGER) - 2)) { + XFREE(a, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + a->data[i++] = ASN_INTEGER; + a->data[i++] = (unsigned char)x509->serialSz; + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + + return a; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) { - (void)bio; - (void)asnTime; - return 0; + char buf[MAX_TIME_STRING_SZ]; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, sizeof(buf)); + wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)); + + return 0; } +#endif -#if defined(WOLFSSL_MYSQL_COMPATIBLE) -char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) { int format; int dateLen; - byte* date = (byte*)time; + byte* date = (byte*)t; WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); - if (time == NULL || buf == NULL || len < 5) { + if (t == NULL || buf == NULL || len < 5) { WOLFSSL_MSG("Bad argument"); return NULL; } @@ -12944,11 +15550,10 @@ long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) } - void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ctx != NULL && idx == 0) return ctx->ex_data; #else @@ -12976,12 +15581,23 @@ void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, unsigned long wolfSSL_ERR_peek_error(void) { + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + +#ifdef OPENSSL_EXTRA + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); +#else return 0; +#endif } int wolfSSL_ERR_GET_REASON(unsigned long err) { +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + /* Nginx looks for this error to know to stop parsing certificates. */ + if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE)) + return PEM_R_NO_START_LINE; +#endif (void)err; return 0; } @@ -13018,3574 +15634,3312 @@ int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) } -long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) +unsigned long wolfSSL_set_options(WOLFSSL* ssl, unsigned long op) { - (void)ctx; - return 0; -} + WOLFSSL_ENTER("wolfSSL_set_options"); + if (ssl == NULL) { + return 0; + } -long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; -} + /* if SSL_OP_ALL then turn all bug workarounds one */ + if ((op & SSL_OP_ALL) == SSL_OP_ALL) { + WOLFSSL_MSG("\tSSL_OP_ALL"); + op |= SSL_OP_MICROSOFT_SESS_ID_BUG; + op |= SSL_OP_NETSCAPE_CHALLENGE_BUG; + op |= SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; + op |= SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; + op |= SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; + op |= SSL_OP_MSIE_SSLV2_RSA_PADDING; + op |= SSL_OP_SSLEAY_080_CLIENT_DH_BUG; + op |= SSL_OP_TLS_D5_BUG; + op |= SSL_OP_TLS_BLOCK_PADDING_BUG; + op |= SSL_OP_TLS_ROLLBACK_BUG; + op |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + } -long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; -} + ssl->options.mask |= op; + /* by default cookie exchange is on with DTLS */ + if ((ssl->options.mask & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) { + WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); + } -long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; -} + if ((ssl->options.mask & SSL_OP_NO_SSLv2) == SSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + } + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); + if (ssl->version.minor == TLSv1_2_MINOR) + ssl->version.minor = TLSv1_1_MINOR; + } -long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; -} + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); + if (ssl->version.minor == TLSv1_1_MINOR) + ssl->version.minor = TLSv1_MINOR; + } + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; + } -long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; -} + if ((ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); + } + if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); + ssl->options.usingCompression = 0; + #else + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in"); + #endif + } -long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; + return ssl->options.mask; } -long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) +unsigned long wolfSSL_get_options(const WOLFSSL* ssl) { - (void)ctx; - return 0; -} - + WOLFSSL_ENTER("wolfSSL_get_options"); -long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; + return ssl->options.mask; } - -long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s) { - (void)ctx; + (void)s; return 0; } - -long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s) { - (void)ctx; + (void)s; return 0; } -long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) -{ - (void)ctx; - return 0; -} - -#ifndef NO_DES3 -void wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, - WOLFSSL_DES_key_schedule* key) +#ifndef NO_DH +long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) { -#ifdef WOLFSSL_CHECK_DESKEY - wolfSSL_DES_set_key_checked(myDes, key); -#else - wolfSSL_DES_set_key_unchecked(myDes, key); -#endif -} + int pSz, gSz; + byte *p, *g; + int ret = 0; + WOLFSSL_ENTER("wolfSSL_set_tmp_dh"); + if (!ssl || !dh) + return BAD_FUNC_ARG; -/* return true in fail case (1) */ -static int DES_check(word32 mask, word32 mask2, unsigned char* key) -{ - word32 value[2]; + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); - /* sanity check on length made in wolfSSL_DES_set_key_checked */ - value[0] = mask; - value[1] = mask2; - return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0; -} + if (pSz <= 0 || gSz <= 0) + return SSL_FATAL_ERROR; + p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + if (!p) + return MEMORY_E; -/* check that the key is odd parity and is not a weak key */ -void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, - WOLFSSL_DES_key_schedule* key) -{ - if (myDes == NULL || key == NULL) { - WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked"); + g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + if (!g) { + XFREE(p, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + return MEMORY_E; } - else { - word32 i, mask, mask2; - word32 sz = sizeof(WOLFSSL_DES_key_schedule); - - /* sanity check before call to DES_check */ - if (sz != (sizeof(word32) * 2)) { - WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size"); - return; - } - - /* check odd parity */ - for (i = 0; i < sz; i++) { - unsigned char c = *((unsigned char*)key + i); - if (((c & 0x01) ^ - ((c >> 1) & 0x01) ^ - ((c >> 2) & 0x01) ^ - ((c >> 3) & 0x01) ^ - ((c >> 4) & 0x01) ^ - ((c >> 5) & 0x01) ^ - ((c >> 6) & 0x01) ^ - ((c >> 7) & 0x01)) != 1) { - WOLFSSL_MSG("Odd parity test fail"); - return; - } - } - - /* check is not weak. Weak key list from Nist - "Recommendation for the Triple - Data Encryption Algorithm - (TDEA) Block Cipher" */ - mask = 0x01010101; mask2 = 0x01010101; - if (DES_check(mask, mask2, *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } - - mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE; - if (DES_check(mask, mask2, *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } - - mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1; - if (DES_check(mask, mask2, *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } - - mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E; - if (DES_check(mask, mask2, *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } - - /* semi-weak *key check (list from same Nist paper) */ - mask = 0x011F011F; mask2 = 0x010E010E; - if (DES_check(mask, mask2, *key) || - DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } - - mask = 0x01E001E0; mask2 = 0x01F101F1; - if (DES_check(mask, mask2, *key) || - DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } - mask = 0x01FE01FE; mask2 = 0x01FE01FE; - if (DES_check(mask, mask2, *key) || - DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); - mask = 0x1FE01FE0; mask2 = 0x0EF10EF1; - if (DES_check(mask, mask2, *key) || - DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } + if (pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); - mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE; - if (DES_check(mask, mask2, *key) || - DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { - WOLFSSL_MSG("Weak key found"); - return; - } + XFREE(p, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(g, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); - /* passed tests, now copy over key */ - XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); - } + return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; } +#endif /* !NO_DH */ -void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes, - WOLFSSL_DES_key_schedule* key) +#ifdef HAVE_PK_CALLBACKS +long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) { - if (myDes != NULL && key != NULL) { - XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + if (ssl == NULL) { + return SSL_FAILURE; } -} + ssl->loggingCtx = arg; + return SSL_SUCCESS; +} +#endif /* HAVE_PK_CALLBACKS */ -void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) +#ifdef WOLFSSL_HAPROXY +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length) { - (void)myDes; - WOLFSSL_STUB("wolfSSL_DES_set_odd_parity"); + const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length); + return c; } +#endif - -void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, - WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int len) +/*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st) { - (void)desa; - (void)desb; - (void)key; - (void)len; - WOLFSSL_STUB("wolfSSL_DES_ecb_encrypt"); + (void)st; + WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero"); + //wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); + return SSL_FAILURE; } -#endif /* NO_DES3 */ -int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) { - (void)bio; - (void)format; - return 0; + (void)s; + (void)type; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_type"); + return SSL_FAILURE; } - -int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) { - (void)bio; - (void)a; - return 0; + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); + return SSL_FAILURE; } - -int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) { - (void)rev; - return 0; + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return SSL_FAILURE; } - -void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) { - (void)rev; - (void)i; - return 0; + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + return SSL_FAILURE; } - -/* stunnel 4.28 needs */ -void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, - WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) +/*** TBD ***/ +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) { - (void)ctx; - (void)f; + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); + return SSL_FAILURE; } - -void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, - int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) +/*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len) { - (void)ctx; - (void)f; + (void)s; + (void)sid; + (void)sid_len; + WOLFSSL_STUB("SSL_SESSION_set1_id"); + return SSL_FAILURE; } +/*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len) +{ + (void)s; + (void)sid_ctx; + (void)sid_ctx_len; + WOLFSSL_STUB("SSL_SESSION_set1_id_context"); + return SSL_FAILURE; +} -void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, - WOLFSSL_SESSION*)) +/*** TBD ***/ +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x) { - (void)ctx; - (void)f; + (void)x; + WOLFSSL_STUB("X509_get0_tbs_sigalg"); + return NULL; } +/*** TBD ***/ +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor) +{ + (void)paobj; + (void)pptype; + (void)ppval; + (void)algor; + WOLFSSL_STUB("X509_ALGOR_get0"); +} -int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) +/*** TBD ***/ +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x) { - (void)sess; - (void)p; - return sizeof(WOLFSSL_SESSION); + (void)x; + WOLFSSL_STUB("X509_get_X509_PUBKEY"); + return NULL; } +/*** TBD ***/ +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub) +{ + (void)ppkalg; + (void)pk; + (void)ppklen; + (void)pa; + (void)pub; + WOLFSSL_STUB("X509_PUBKEY_get0_param"); + return SSL_FAILURE; +} -WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, - const unsigned char** p, long i) +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) { - (void)p; - (void)i; - if (sess) - return *sess; + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); return NULL; } +/*** TBD ***/ +WOLFSSL_API int EVP_PKEY_bits(WOLFSSL_EVP_PKEY *pkey) +{ + (void)pkey; + WOLFSSL_STUB("EVP_PKEY_bits"); + return SSL_FAILURE; +} -long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) +/*** TBD ***/ +WOLFSSL_API int i2d_X509(WOLFSSL_X509 *x, unsigned char **out) { - WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); - return sess->timeout; + (void)x; + (void)out; + WOLFSSL_STUB("i2d_X509"); + return -1; } +/*** TBD ***/ +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) +{ + (void)buf; + (void)buf_len; + (void)a; + WOLFSSL_STUB("i2t_ASN1_OBJECT"); + return -1; +} -long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count) { - WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - return sess->bornOn; + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_finished"); + return SSL_FAILURE; } +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_peer_finished"); + return SSL_FAILURE; +} -#endif /* OPENSSL_EXTRA */ +/*** TBD ***/ +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)) +{ + (void)ctx; + (void)dh; + WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback"); +} +/*** TBD ***/ +WOLFSSL_API STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + WOLFSSL_STUB("SSL_COMP_get_compression_methods"); + return NULL; +} -#ifdef KEEP_PEER_CERT -char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509) +/*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p) { - if (x509 == NULL) - return NULL; + (void)p; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_num"); + return -1; +} - return x509->subjectCN; +#if !defined(NO_FILESYSTEM) +/*** TBD ***/ +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_X509"); + return NULL; } -#endif /* KEEP_PEER_CERT */ -#ifdef OPENSSL_EXTRA +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_PrivateKey"); + return NULL; +} +#endif -#ifdef FORTRESS -int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) +/*** TBD ***/ +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir) { - int ret = SSL_FATAL_ERROR; + (void)ctx; + (void)file; + (void)dir; + WOLFSSL_STUB("X509_STORE_load_locations"); + return SSL_FAILURE; +} - WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); - if (ssl != NULL && fname != NULL) - { - #ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; - byte staticBuffer[1]; /* force heap usage */ - #else - EncryptedInfo info[1]; - byte staticBuffer[FILE_BUFFER_SIZE]; - #endif - byte* myBuffer = staticBuffer; - int dynamic = 0; - XFILE file = XBADFILE; - long sz = 0; - int eccKey = 0; - WOLFSSL_CTX* ctx = ssl->ctx; - WOLFSSL_X509* peer_cert = &ssl->peerCert; - DerBuffer* fileDer = NULL; +/*** TBD ***/ +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx) +{ + (void)ciphers; + (void)idx; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value"); + return NULL; +} - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) - return SSL_BAD_FILE; +WOLFSSL_API void ERR_load_SSL_strings(void) +{ - XFSEEK(file, 0, XSEEK_END); - sz = XFTELL(file); - XREWIND(file); +} - if (sz > (long)sizeof(staticBuffer)) { - WOLFSSL_MSG("Getting dynamic buffer"); - myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); - dynamic = 1; - } +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) +{ + if (s == NULL || resp == NULL) + return 0; - #ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) - ret = MEMORY_E; - else - #endif - { - info->set = 0; - info->ctx = ctx; - info->consumed = 0; + *resp = s->ocspResp; + return s->ocspRespSz; +} - if ((myBuffer != NULL) && - (sz > 0) && - (XFREAD(myBuffer, sz, 1, file) > 0) && - (PemToDer(myBuffer, sz, CERT_TYPE, - &fileDer, ctx->heap, info, &eccKey) == 0) && - (fileDer->length != 0) && - (fileDer->length == peer_cert->derCert->length) && - (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, - fileDer->length) == 0)) - { - ret = 0; - } +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, + unsigned char *resp, int len) +{ + if (s == NULL) + return SSL_FAILURE; - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } + s->ocspResp = resp; + s->ocspRespSz = len; - FreeDer(&fileDer); + return SSL_SUCCESS; +} - if (dynamic) - XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); - XFCLOSE(file); +long wolfSSL_get_verify_result(const WOLFSSL *ssl) +{ + if (ssl == NULL) { + return SSL_FAILURE; } - return ret; + return ssl->peerVerifyRet; } -#endif -static WC_RNG globalRNG; -static int initGlobalRNG = 0; +long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} -/* SSL_SUCCESS on ok */ -int wolfSSL_RAND_seed(const void* seed, int len) +long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) { + (void)ctx; + return 0; +} - WOLFSSL_MSG("wolfSSL_RAND_seed"); - (void)seed; - (void)len; +long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} - if (initGlobalRNG == 0) { - if (wc_InitRng(&globalRNG) < 0) { - WOLFSSL_MSG("wolfSSL Init Global RNG failed"); - return 0; - } - initGlobalRNG = 1; - } - return SSL_SUCCESS; +long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; } -/* SSL_SUCCESS on ok */ -int wolfSSL_RAND_bytes(unsigned char* buf, int num) +long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) { - int ret = 0; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif + (void)ctx; + return 0; +} - WOLFSSL_ENTER("wolfSSL_RAND_bytes"); -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return ret; -#endif +long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else if (initGlobalRNG) - rng = &globalRNG; - if (rng) { - if (wc_RNG_GenerateBlock(rng, buf, num) != 0) - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - else - ret = SSL_SUCCESS; - } +long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} -WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) +long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) { - static int ctx; /* wolfcrypt doesn't now need ctx */ + (void)ctx; + return 0; +} - WOLFSSL_MSG("wolfSSL_BN_CTX_new"); - return (WOLFSSL_BN_CTX*)&ctx; +long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; } -void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) + +long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) { (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_CTX_init"); + return 0; } -void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) +long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) { (void)ctx; - WOLFSSL_MSG("wolfSSL_BN_CTX_free"); - - /* do free since static ctx that does nothing */ + return 0; } -static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) +long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) { - WOLFSSL_MSG("InitwolfSSL_BigNum"); - if (bn) { - bn->neg = 0; - bn->internal = NULL; - } + (void)ctx; + return 0; } -WOLFSSL_BIGNUM* wolfSSL_BN_new(void) +#ifndef NO_CERTS +long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { - WOLFSSL_BIGNUM* external; - mp_int* mpi; + byte* chain = NULL; + long chainSz = 0; + int derSz; + const byte* der; + int ret; + int idx = 0; + DerBuffer *derBuffer = NULL; - WOLFSSL_MSG("wolfSSL_BN_new"); + WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); - mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (mpi == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure"); - return NULL; + if (ctx == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; } - external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, - DYNAMIC_TYPE_BIGINT); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); - return NULL; + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL || derSz <= 0) { + WOLFSSL_MSG("Error getting X509 DER"); + return SSL_FAILURE; } - InitwolfSSL_BigNum(external); - external->internal = mpi; - if (mp_init(mpi) != MP_OKAY) { - wolfSSL_BN_free(external); - return NULL; + if (ctx->certificate == NULL) { + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, SSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1); + if (ret != SSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return SSL_FAILURE; + } } + else { + /* TODO: Do this elsewhere. */ + ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap); + if (ret != 0) { + WOLFSSL_MSG("Memory Error"); + return SSL_FAILURE; + } + XMEMCPY(derBuffer->buffer, der, derSz); + ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone); + if (ret != SSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return SSL_FAILURE; + } - return external; -} + /* adding cert to existing chain */ + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + chainSz += ctx->certChain->length; + } + chainSz += OPAQUE24_LEN + derSz; + chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (chain == NULL) { + WOLFSSL_MSG("Memory Error"); + return SSL_FAILURE; + } -void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_free"); - if (bn) { - if (bn->internal) { - mp_clear((mp_int*)bn->internal); - XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); - bn->internal = NULL; + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); + idx = ctx->certChain->length; } - XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); - bn = NULL; - } -} + c32to24(derSz, chain + idx); + idx += OPAQUE24_LEN, + XMEMCPY(chain + idx, der, derSz); + idx += derSz; + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chain, idx); + } + } -void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_clear_free"); + /* on success WOLFSSL_X509 memory is responsibility of ctx */ + wolfSSL_X509_free(x509); + if (chain != NULL) + XFREE(chain, ctx->heap, CERT_TYPE); - wolfSSL_BN_free(bn); + return SSL_SUCCESS; } -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, - const WOLFSSL_BIGNUM* b) +long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) { - WOLFSSL_MSG("wolfSSL_BN_sub"); - - if (r == NULL || a == NULL || b == NULL) - return 0; - - if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, - (mp_int*)r->internal) == MP_OKAY) - return SSL_SUCCESS; + if (ctx == NULL || ctx->cm == NULL) { + return SSL_FAILURE; + } - WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); - return 0; + ctx->cm->ocspIOCtx = arg; + return SSL_SUCCESS; } +#endif /* NO_CERTS */ -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, - const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) -{ - (void)c; - WOLFSSL_MSG("wolfSSL_BN_mod"); - - if (r == NULL || a == NULL || b == NULL) - return 0; - - if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, - (mp_int*)r->internal) == MP_OKAY) - return SSL_SUCCESS; - WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); +/*** TBC ***/ +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) +{ + (void)ctx; return 0; } -const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) -{ - static WOLFSSL_BIGNUM* bn_one = NULL; - - WOLFSSL_MSG("wolfSSL_BN_value_one"); - - if (bn_one == NULL) { - bn_one = wolfSSL_BN_new(); - if (bn_one) - mp_set_int((mp_int*)bn_one->internal, 1); - } - - return bn_one; -} - -/* return compliant with OpenSSL - * size of BIGNUM in bytes, 0 if error */ -int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) +int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) { - WOLFSSL_MSG("wolfSSL_BN_num_bytes"); - - if (bn == NULL || bn->internal == NULL) + if (ctx == NULL) { return SSL_FAILURE; + } - return mp_unsigned_bin_size((mp_int*)bn->internal); + return ctx->readAhead; } -/* return compliant with OpenSSL - * size of BIGNUM in bits, 0 if error */ -int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_num_bits"); - - if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; - - return mp_count_bits((mp_int*)bn->internal); -} -/* return compliant with OpenSSL - * 1 if BIGNUM is zero, 0 else */ -int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) +int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) { - WOLFSSL_MSG("wolfSSL_BN_is_zero"); - - if (bn == NULL || bn->internal == NULL) + if (ctx == NULL) { return SSL_FAILURE; + } - if (mp_iszero((mp_int*)bn->internal) == MP_YES) - return SSL_SUCCESS; + ctx->readAhead = (byte)v; - return SSL_FAILURE; + return SSL_SUCCESS; } -/* return compliant with OpenSSL - * 1 if BIGNUM is one, 0 else */ -int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) -{ - WOLFSSL_MSG("wolfSSL_BN_is_one"); - - if (bn == NULL || bn->internal == NULL) - return SSL_FAILURE; - if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) - return SSL_SUCCESS; - - return SSL_FAILURE; -} - -/* return compliant with OpenSSL - * 1 if BIGNUM is odd, 0 else */ -int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) +long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, + void* arg) { - WOLFSSL_MSG("wolfSSL_BN_is_odd"); - - if (bn == NULL || bn->internal == NULL) + if (ctx == NULL) { return SSL_FAILURE; + } - if (mp_isodd((mp_int*)bn->internal) == MP_YES) - return SSL_SUCCESS; - - return SSL_FAILURE; + ctx->userPRFArg = arg; + return SSL_SUCCESS; } -/* return compliant with OpenSSL - * -1 if a < b, 0 if a == b and 1 if a > b - */ -int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) + +#ifndef NO_DES3 +/* 0 on success */ +int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) { - int ret; +#ifdef WOLFSSL_CHECK_DESKEY + return wolfSSL_DES_set_key_checked(myDes, key); +#else + wolfSSL_DES_set_key_unchecked(myDes, key); + return 0; +#endif +} - WOLFSSL_MSG("wolfSSL_BN_cmp"); - if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) - return SSL_FATAL_ERROR; - ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); +/* return true in fail case (1) */ +static int DES_check(word32 mask, word32 mask2, unsigned char* key) +{ + word32 value[2]; - return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1)); + /* sanity check on length made in wolfSSL_DES_set_key_checked */ + value[0] = mask; + value[1] = mask2; + return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0; } -/* return compliant with OpenSSL - * length of BIGNUM in bytes, -1 if error */ -int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) -{ - WOLFSSL_MSG("wolfSSL_BN_bn2bin"); - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("NULL bn error"); - return SSL_FATAL_ERROR; +/* check that the key is odd parity and is not a weak key + * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */ +int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ + if (myDes == NULL || key == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked"); + return -2; } + else { + word32 i, mask, mask2; + word32 sz = sizeof(WOLFSSL_DES_key_schedule); - if (r == NULL) - return mp_unsigned_bin_size((mp_int*)bn->internal); - - if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { - WOLFSSL_MSG("mp_to_unsigned_bin error"); - return SSL_FATAL_ERROR; - } + /* sanity check before call to DES_check */ + if (sz != (sizeof(word32) * 2)) { + WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size"); + return -2; + } - return mp_unsigned_bin_size((mp_int*)bn->internal); -} + /* check odd parity */ + for (i = 0; i < sz; i++) { + unsigned char c = *((unsigned char*)key + i); + if (((c & 0x01) ^ + ((c >> 1) & 0x01) ^ + ((c >> 2) & 0x01) ^ + ((c >> 3) & 0x01) ^ + ((c >> 4) & 0x01) ^ + ((c >> 5) & 0x01) ^ + ((c >> 6) & 0x01) ^ + ((c >> 7) & 0x01)) != 1) { + WOLFSSL_MSG("Odd parity test fail"); + return -1; + } + } + /* check is not weak. Weak key list from Nist + "Recommendation for the Triple + Data Encryption Algorithm + (TDEA) Block Cipher" */ + mask = 0x01010101; mask2 = 0x01010101; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } -WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, - WOLFSSL_BIGNUM* ret) -{ - int weOwn = 0; + mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } - WOLFSSL_MSG("wolfSSL_BN_bin2bn"); + mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } - /* if ret is null create a BN */ - if (ret == NULL) { - ret = wolfSSL_BN_new(); - weOwn = 1; - if (ret == NULL) - return NULL; - } + mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } - /* check ret and ret->internal then read in value */ - if (ret && ret->internal) { - if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) { - WOLFSSL_MSG("mp_read_unsigned_bin failure"); - if (weOwn) - wolfSSL_BN_free(ret); - return NULL; + /* semi-weak *key check (list from same Nist paper) */ + mask = 0x011F011F; mask2 = 0x010E010E; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; } - } - return ret; -} + mask = 0x01E001E0; mask2 = 0x01F101F1; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } -/* return compliant with OpenSSL - * 1 if success, 0 if error */ -int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) -{ - (void)bn; - (void)n; - WOLFSSL_MSG("wolfSSL_BN_mask_bits"); + mask = 0x01FE01FE; mask2 = 0x01FE01FE; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } - return SSL_FAILURE; + mask = 0x1FE01FE0; mask2 = 0x0EF10EF1; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } + + mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return -2; + } + + /* passed tests, now copy over key */ + XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + + return 0; + } } -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) { - int ret = 0; - int len = bits / 8; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; - byte* buff = NULL; -#else - WC_RNG tmpRNG[1]; - byte buff[1024]; -#endif + if (myDes != NULL && key != NULL) { + XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + } +} - (void)top; - (void)bottom; - WOLFSSL_MSG("wolfSSL_BN_rand"); - if (bits % 8) - len++; +void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) +{ + (void)myDes; + WOLFSSL_STUB("wolfSSL_DES_set_odd_parity"); +} -#ifdef WOLFSSL_SMALL_STACK - buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); - tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buff == NULL || tmpRNG == NULL) { - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } -#endif - if (bn == NULL || bn->internal == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else if (initGlobalRNG) - rng = &globalRNG; +#ifdef WOLFSSL_DES_ECB +/* Encrpyt or decrypt input message desa with key and get output in desb. + * if enc is DES_ENCRYPT,input message is encrypted or + * if enc is DES_DECRYPT,input message is decrypted. + * */ +void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, + WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc) +{ + Des myDes; - if (rng) { - if (wc_RNG_GenerateBlock(rng, buff, len) != 0) - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - else { - buff[0] |= 0x80 | 0x40; - buff[len-1] |= 0x01; + WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt"); - if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) - WOLFSSL_MSG("mp read bin failed"); - else - ret = SSL_SUCCESS; + if (desa == NULL || key == NULL || desb == NULL || + (enc != DES_ENCRYPT && enc != DES_DECRYPT)) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt"); + } else { + if (wc_Des_SetKey(&myDes, (const byte*) key, + (const byte*) NULL, !enc) != 0) { + WOLFSSL_MSG("wc_Des_SetKey return error."); + return; + } + if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, + (const byte*)desa, sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbEncrypt return error."); } } +} +#endif - if (initTmpRng) - wc_FreeRng(tmpRNG); +#endif /* NO_DES3 */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...) +{ + (void)bio; + (void)format; + return 0; +} - return ret; + +int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) +{ + (void)bio; + (void)a; + return 0; } -/* return code compliant with OpenSSL : - * 1 if bit set, 0 else +/* Return the month as a string. + * + * n The number of the month as a two characters (1 based). + * returns the month as a string. */ -int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) +static INLINE const char* MonthStr(const char* n) { - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; - } + static const char monthStr[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1]; +} - if (n > DIGIT_BIT) { - WOLFSSL_MSG("input bit count too large"); - return SSL_FAILURE; - } +int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, + const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) +{ + const char* p = (const char *)(asnTime->data + 2); + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); - return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + /* GetTimeString not always available. */ + wolfSSL_BIO_write(bio, MonthStr(p + 4), 3); + wolfSSL_BIO_write(bio, " ", 1); + /* Day */ + wolfSSL_BIO_write(bio, p + 6, 2); + wolfSSL_BIO_write(bio, " ", 1); + /* Hour */ + wolfSSL_BIO_write(bio, p + 8, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Min */ + wolfSSL_BIO_write(bio, p + 10, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Secs */ + wolfSSL_BIO_write(bio, p + 12, 2); + wolfSSL_BIO_write(bio, " ", 1); + wolfSSL_BIO_write(bio, p, 4); + + return 0; } -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) +int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) { - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; - } + (void)rev; + return 0; +} - if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { - WOLFSSL_MSG("mp_set_int error"); - return SSL_FAILURE; - } - return SSL_SUCCESS; +void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) +{ + (void)rev; + (void)i; + return 0; } -/* SSL_SUCCESS on ok */ -int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) +/* stunnel 4.28 needs */ +void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, + WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) { - int ret = 0; - word32 decSz = 1024; -#ifdef WOLFSSL_SMALL_STACK - byte* decoded = NULL; +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; #else - byte decoded[1024]; + (void)ctx; + (void)f; #endif +} - WOLFSSL_MSG("wolfSSL_BN_hex2bn"); -#ifdef WOLFSSL_SMALL_STACK - decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) - return ret; +void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, + int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) +{ +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else + (void)ctx; + (void)f; #endif +} - if (str == NULL) - WOLFSSL_MSG("Bad function argument"); - else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0) - WOLFSSL_MSG("Bad Base16_Decode error"); - else if (bn == NULL) - ret = decSz; - else { - if (*bn == NULL) - *bn = wolfSSL_BN_new(); - if (*bn == NULL) - WOLFSSL_MSG("BN new failed"); - else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) - WOLFSSL_MSG("Bad bin2bn error"); - else - ret = SSL_SUCCESS; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, + WOLFSSL_SESSION*)) +{ +#ifdef HAVE_EXT_CACHE + ctx->rem_sess_cb = f; +#else + (void)ctx; + (void)f; #endif - - return ret; } - -WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) +#ifdef HAVE_EXT_CACHE +/* convert 32 bit integer to opaque */ +static INLINE void c32toa(word32 u32, byte* c) { - WOLFSSL_BIGNUM* ret; + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} - WOLFSSL_MSG("wolfSSL_BN_dup"); +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} +#endif - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; - } +int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) +{ + int size = 0; +#ifdef HAVE_EXT_CACHE + int idx = 0; +#ifdef SESSION_CERTS + int i; +#endif + unsigned char *data; - ret = wolfSSL_BN_new(); - if (ret == NULL) { - WOLFSSL_MSG("bn new error"); - return NULL; - } + /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + + SECRET_LEN + OPAQUE8_LEN; +#ifdef SESSION_CERTS + /* Peer chain */ + size += OPAQUE8_LEN; + for (i = 0; i < sess->chain.count; i++) + size += OPAQUE16_LEN + sess->chain.certs[i].length; + /* Protocol version + cipher suite */ + size += OPAQUE16_LEN + OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len | ticket */ + size += OPAQUE16_LEN + sess->ticketLen; +#endif - if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - wolfSSL_BN_free(ret); - return NULL; + if (p != NULL) { + if (*p == NULL) + *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); + if (*p == NULL) + return 0; + data = *p; + + c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN; + c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN; + data[idx++] = sess->sessionIDSz; + XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz); + idx += sess->sessionIDSz; + XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; + data[idx++] = sess->haveEMS; +#ifdef SESSION_CERTS + data[idx++] = sess->chain.count; + for (i = 0; i < sess->chain.count; i++) { + c16toa(sess->chain.certs[i].length, data + idx); + idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->chain.certs[i].buffer, + sess->chain.certs[i].length); + idx += sess->chain.certs[i].length; + } + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; + data[idx++] = sess->cipherSuite0; + data[idx++] = sess->cipherSuite; +#endif +#ifndef NO_CLIENT_CACHE + c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->serverID, sess->idLen); + idx += sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->ticket, sess->ticketLen); + idx += sess->ticketLen; +#endif } +#endif - ret->neg = bn->neg; + (void)sess; + (void)p; +#ifdef HAVE_EXT_CACHE + (void)idx; +#endif - return ret; + return size; } - -WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) +#ifdef HAVE_EXT_CACHE +/* convert opaque to 16 bit integer */ +static INLINE void ato16(const byte* c, word16* u16) { - WOLFSSL_MSG("wolfSSL_BN_copy"); - - if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - return NULL; - } - - r->neg = bn->neg; - - return r; + *u16 = (word16) ((c[0] << 8) | (c[1])); } -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) +/* convert opaque to 32 bit integer */ +static INLINE void ato32(const byte* c, word32* u32) { - WOLFSSL_MSG("wolfSSL_BN_set_word"); - - if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { - WOLFSSL_MSG("mp_init_set_int error"); - return SSL_FAILURE; - } - - return SSL_SUCCESS; + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; } +#endif -/* return code compliant with OpenSSL : - * number length in decimal if success, 0 if error - */ -int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +/* TODO: no function to free new session. */ +WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, + const unsigned char** p, long i) { - (void)bn; - (void)str; + WOLFSSL_SESSION* s = NULL; + int ret = 0; +#if defined(HAVE_EXT_CACHE) + int idx; + byte* data; +#ifdef SESSION_CERTS + int j; + word16 length; +#endif +#endif - WOLFSSL_MSG("wolfSSL_BN_dec2bn"); + (void)p; + (void)i; + (void)ret; - return SSL_FAILURE; -} + if (sess != NULL) + s = *sess; +#ifdef HAVE_EXT_CACHE + if (p == NULL || *p == NULL) + return NULL; -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) -char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) -{ - int len = 0; - char *buf; + if (s == NULL) { + s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL) + return NULL; + s->isAlloced = 1; + s->isDynamic = 0; + } - WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + idx = 0; + data = (byte*)*p; - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; + /* bornOn | timeout | sessionID len */ + if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; } + ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; + ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; + s->sessionIDSz = data[idx++]; - if (mp_radix_size((mp_int*)bn->internal, 10, &len) != MP_OKAY) { - WOLFSSL_MSG("mp_radix_size failure"); - return NULL; + /* sessionID | secret | haveEMS */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; } + XMEMCPY(s->sessionID, data + idx, s->sessionIDSz); + idx += s->sessionIDSz; + XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; + s->haveEMS = data[idx++]; - buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); - if (buf == NULL) { - WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); - return NULL; +#ifdef SESSION_CERTS + /* Certificate chain */ + if (i - idx == 0) { + ret = BUFFER_ERROR; + goto end; + } + s->chain.count = data[idx++]; + for (j = 0; j < s->chain.count; j++) { + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &length); idx += OPAQUE16_LEN; + s->chain.certs[j].length = length; + if (i - idx < length) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->chain.certs[j].buffer, data + idx, length); + idx += length; + } + + /* Protocol Version | Cipher suite */ + if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; + s->cipherSuite0 = data[idx++]; + s->cipherSuite = data[idx++]; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; } + ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN; - if (mp_toradix((mp_int*)bn->internal, buf, 10) != MP_OKAY) { - XFREE(buf, NULL, DYNAMIC_TYPE_ECC); - return NULL; + /* ServerID */ + if (i - idx < s->idLen) { + ret = BUFFER_ERROR; + goto end; } - - return buf; -} -#else -char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) -{ - (void)bn; - - WOLFSSL_MSG("wolfSSL_BN_bn2dec"); - - return NULL; -} -#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ - -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) -{ - WOLFSSL_MSG("wolfSSL_BN_lshift"); - - if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; + XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN; + + /* Dispose of ol dynamic ticket and ensure space for new ticket. */ + if (s->isDynamic) + XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (s->ticketLen <= SESSION_TICKET_LEN) + s->ticket = s->staticTicket; + else { + s->ticket = (byte*)XMALLOC(s->ticketLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + if (s->ticket == NULL) { + ret = MEMORY_ERROR; + goto end; + } + s->isDynamic = 1; } - if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_mul_2d error"); - return SSL_FAILURE; + /* ticket */ + if (i - idx < s->ticketLen) { + ret = BUFFER_ERROR; + goto end; } + XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif + (void)idx; - return SSL_SUCCESS; -} + if (sess != NULL) + *sess = s; -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) -{ - WOLFSSL_MSG("wolfSSL_BN_rshift"); + *p += idx; - if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; - } +end: + if (ret != 0 && (sess == NULL || *sess != s)) + wolfSSL_SESSION_free(s); +#endif + return s; +} - if (mp_div_2d((mp_int*)bn->internal, n, - (mp_int*)r->internal, NULL) != MP_OKAY) { - WOLFSSL_MSG("mp_mul_2d error"); - return SSL_FAILURE; - } - return SSL_SUCCESS; +long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); + return sess->timeout; } -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) + +long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) { - WOLFSSL_MSG("wolfSSL_BN_add_word"); + WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); + return sess->bornOn; +} - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; - } - if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_add_d error"); - return SSL_FAILURE; - } +#endif /* OPENSSL_EXTRA */ - return SSL_SUCCESS; -} -/* return code compliant with OpenSSL : - * 1 if success, 0 else - */ -int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) +#ifdef KEEP_PEER_CERT +char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509) { - WOLFSSL_MSG("wolfSSL_BN_add"); - - if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL || - b == NULL || b->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; - } - - if (mp_add((mp_int*)a->internal, (mp_int*)b->internal, - (mp_int*)r->internal) != MP_OKAY) { - WOLFSSL_MSG("mp_add_d error"); - return SSL_FAILURE; - } + if (x509 == NULL) + return NULL; - return SSL_SUCCESS; + return x509->subjectCN; } +#endif /* KEEP_PEER_CERT */ -#ifdef WOLFSSL_KEY_GEN +#ifdef OPENSSL_EXTRA -/* return code compliant with OpenSSL : - * 1 if prime, 0 if not, -1 if error - */ -int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, - WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) +#ifdef FORTRESS +int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) { - int res; - - (void)ctx; - (void)cb; - - WOLFSSL_MSG("wolfSSL_BN_is_prime_ex"); + int ret = SSL_FATAL_ERROR; - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); + if (ssl != NULL && fname != NULL) + { + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; + byte staticBuffer[1]; /* force heap usage */ + #else + EncryptedInfo info[1]; + byte staticBuffer[FILE_BUFFER_SIZE]; + #endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + XFILE file = XBADFILE; + size_t sz = 0; + int eccKey = 0; + WOLFSSL_CTX* ctx = ssl->ctx; + WOLFSSL_X509* peer_cert = &ssl->peerCert; + DerBuffer* fileDer = NULL; - if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) { - WOLFSSL_MSG("mp_prime_is_prime error"); - return SSL_FATAL_ERROR; - } + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return SSL_BAD_FILE; - if (res != MP_YES) { - WOLFSSL_MSG("mp_prime_is_prime not prime"); - return SSL_FAILURE; - } + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); - return SSL_SUCCESS; -} + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); + dynamic = 1; + } -/* return code compliant with OpenSSL : - * (bn mod w) if success, -1 if error - */ -WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, - WOLFSSL_BN_ULONG w) -{ - WOLFSSL_BN_ULONG ret = 0; + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) + ret = MEMORY_E; + else + #endif + { + info->set = 0; + info->ctx = ctx; + info->consumed = 0; - WOLFSSL_MSG("wolfSSL_BN_mod_word"); + if ((myBuffer != NULL) && + (sz > 0) && + (XFREAD(myBuffer, 1, sz, file) == sz) && + (PemToDer(myBuffer, sz, CERT_TYPE, + &fileDer, ctx->heap, info, &eccKey) == 0) && + (fileDer->length != 0) && + (fileDer->length == peer_cert->derCert->length) && + (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, + fileDer->length) == 0)) + { + ret = 0; + } - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; - } + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } - if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) { - WOLFSSL_MSG("mp_add_d error"); - return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; + FreeDer(&fileDer); + + if (dynamic) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + + XFCLOSE(file); } return ret; } -#endif /* #ifdef WOLFSSL_KEY_GEN */ +#endif -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) -char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) -{ - int len = 0; - char *buf; - WOLFSSL_MSG("wolfSSL_BN_bn2hex"); +static WC_RNG globalRNG; +static int initGlobalRNG = 0; - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return NULL; - } +/* SSL_SUCCESS on ok */ +int wolfSSL_RAND_seed(const void* seed, int len) +{ - if (mp_radix_size((mp_int*)bn->internal, 16, &len) != MP_OKAY) { - WOLFSSL_MSG("mp_radix_size failure"); - return NULL; - } + WOLFSSL_MSG("wolfSSL_RAND_seed"); - buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); - if (buf == NULL) { - WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); - return NULL; - } + (void)seed; + (void)len; - if (mp_toradix((mp_int*)bn->internal, buf, 16) != MP_OKAY) { - XFREE(buf, NULL, DYNAMIC_TYPE_ECC); - return NULL; + if (initGlobalRNG == 0) { + if (wc_InitRng(&globalRNG) < 0) { + WOLFSSL_MSG("wolfSSL Init Global RNG failed"); + return 0; + } + initGlobalRNG = 1; } - return buf; + return SSL_SUCCESS; } -#ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) + +/* SSL_SUCCESS on ok */ +int wolfSSL_RAND_bytes(unsigned char* buf, int num) { - char *buf; + int ret = 0; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif - WOLFSSL_MSG("wolfSSL_BN_print_fp"); + WOLFSSL_ENTER("wolfSSL_RAND_bytes"); - if (fp == NULL || bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FAILURE; - } +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return ret; +#endif - buf = wolfSSL_BN_bn2hex(bn); - if (buf == NULL) { - WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); - return SSL_FAILURE; + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; } + else if (initGlobalRNG) + rng = &globalRNG; - fprintf(fp, "%s", buf); - XFREE(buf, NULL, DYNAMIC_TYPE_ECC); - - return SSL_SUCCESS; -} -#endif /* !defined(NO_FILESYSTEM) */ - -#else /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + if (rng) { + if (wc_RNG_GenerateBlock(rng, buf, num) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else + ret = SSL_SUCCESS; + } -char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) -{ - (void)bn; + if (initTmpRng) + wc_FreeRng(tmpRNG); - WOLFSSL_MSG("wolfSSL_BN_bn2hex not implemented"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif - return (char*)""; + return ret; } -#ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) +WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) { - (void)fp; - (void)bn; + static int ctx; /* wolfcrypt doesn't now need ctx */ - WOLFSSL_MSG("wolfSSL_BN_print_fp not implemented"); + WOLFSSL_MSG("wolfSSL_BN_CTX_new"); - return SSL_SUCCESS; + return (WOLFSSL_BN_CTX*)&ctx; } -#endif /* !defined(NO_FILESYSTEM) */ - -#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ -WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) +void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) { - /* ctx is not used, return new Bignum */ (void)ctx; - - WOLFSSL_ENTER("wolfSSL_BN_CTX_get"); - - return wolfSSL_BN_new(); + WOLFSSL_MSG("wolfSSL_BN_CTX_init"); } -void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) + +void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) { (void)ctx; + WOLFSSL_MSG("wolfSSL_BN_CTX_free"); - WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); - WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); + /* do free since static ctx that does nothing */ } -#ifndef NO_DH -static void InitwolfSSL_DH(WOLFSSL_DH* dh) +static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) { - if (dh) { - dh->p = NULL; - dh->g = NULL; - dh->q = NULL; - dh->pub_key = NULL; - dh->priv_key = NULL; - dh->internal = NULL; - dh->inSet = 0; - dh->exSet = 0; + WOLFSSL_MSG("InitwolfSSL_BigNum"); + if (bn) { + bn->neg = 0; + bn->internal = NULL; } } -WOLFSSL_DH* wolfSSL_DH_new(void) +WOLFSSL_BIGNUM* wolfSSL_BN_new(void) { - WOLFSSL_DH* external; - DhKey* key; + WOLFSSL_BIGNUM* external; + mp_int* mpi; - WOLFSSL_MSG("wolfSSL_DH_new"); + WOLFSSL_MSG("wolfSSL_BN_new"); - key = (DhKey*) XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_DH_new malloc DhKey failure"); + mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (mpi == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure"); return NULL; } - external = (WOLFSSL_DH*) XMALLOC(sizeof(WOLFSSL_DH), NULL, - DYNAMIC_TYPE_DH); + external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, + DYNAMIC_TYPE_BIGINT); if (external == NULL) { - WOLFSSL_MSG("wolfSSL_DH_new malloc WOLFSSL_DH failure"); - XFREE(key, NULL, DYNAMIC_TYPE_DH); + WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); + XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); return NULL; } - InitwolfSSL_DH(external); - wc_InitDhKey(key); - external->internal = key; + InitwolfSSL_BigNum(external); + external->internal = mpi; + if (mp_init(mpi) != MP_OKAY) { + wolfSSL_BN_free(external); + return NULL; + } return external; } -void wolfSSL_DH_free(WOLFSSL_DH* dh) +void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) { - WOLFSSL_MSG("wolfSSL_DH_free"); - - if (dh) { - if (dh->internal) { - wc_FreeDhKey((DhKey*)dh->internal); - XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH); - dh->internal = NULL; + WOLFSSL_MSG("wolfSSL_BN_free"); + if (bn) { + if (bn->internal) { + mp_forcezero((mp_int*)bn->internal); + XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); + bn->internal = NULL; } - wolfSSL_BN_free(dh->priv_key); - wolfSSL_BN_free(dh->pub_key); - wolfSSL_BN_free(dh->g); - wolfSSL_BN_free(dh->p); - wolfSSL_BN_free(dh->q); - InitwolfSSL_DH(dh); /* set back to NULLs for safety */ - - XFREE(dh, NULL, DYNAMIC_TYPE_DH); + XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); + bn = NULL; } } -static int SetDhInternal(WOLFSSL_DH* dh) +void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) { - int ret = SSL_FATAL_ERROR; - int pSz = 1024; - int gSz = 1024; -#ifdef WOLFSSL_SMALL_STACK - unsigned char* p = NULL; - unsigned char* g = NULL; -#else - unsigned char p[1024]; - unsigned char g[1024]; -#endif - - WOLFSSL_ENTER("SetDhInternal"); - - if (dh == NULL || dh->p == NULL || dh->g == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (wolfSSL_BN_bn2bin(dh->p, NULL) > pSz) - WOLFSSL_MSG("Bad p internal size"); - else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz) - WOLFSSL_MSG("Bad g internal size"); - else { - #ifdef WOLFSSL_SMALL_STACK - p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("wolfSSL_BN_clear_free"); - if (p == NULL || g == NULL) { - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } - #endif + wolfSSL_BN_free(bn); +} - pSz = wolfSSL_BN_bn2bin(dh->p, p); - gSz = wolfSSL_BN_bn2bin(dh->g, g); - if (pSz <= 0 || gSz <= 0) - WOLFSSL_MSG("Bad BN2bin set"); - else if (wc_DhSetKey((DhKey*)dh->internal, p, pSz, g, gSz) < 0) - WOLFSSL_MSG("Bad DH SetKey"); - else { - dh->inSet = 1; - ret = SSL_SUCCESS; - } +/* SSL_SUCCESS on ok */ +int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b) +{ + WOLFSSL_MSG("wolfSSL_BN_sub"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } + if (r == NULL || a == NULL || b == NULL) + return 0; + if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) == MP_OKAY) + return SSL_SUCCESS; - return ret; + WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); + return 0; } -/* return code compliant with OpenSSL : - * DH prime size in bytes if success, 0 if error - */ -int wolfSSL_DH_size(WOLFSSL_DH* dh) + +/* SSL_SUCCESS on ok */ +int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) { - WOLFSSL_MSG("wolfSSL_DH_size"); + (void)c; + WOLFSSL_MSG("wolfSSL_BN_mod"); - if (dh == NULL) - return SSL_FATAL_ERROR; + if (r == NULL || a == NULL || b == NULL) + return 0; - return wolfSSL_BN_num_bytes(dh->p); + if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) == MP_OKAY) + return SSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); + return 0; } -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) +/* r = (a^p) % m */ +int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) { - int ret = SSL_FAILURE; - word32 pubSz = 768; - word32 privSz = 768; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - unsigned char* pub = NULL; - unsigned char* priv = NULL; - WC_RNG* tmpRNG = NULL; -#else - unsigned char pub [768]; - unsigned char priv[768]; - WC_RNG tmpRNG[1]; -#endif - - WOLFSSL_MSG("wolfSSL_DH_generate_key"); + int ret; -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_ENTER("wolfSSL_BN_mod_exp"); - if (tmpRNG == NULL || pub == NULL || priv == NULL) { - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + (void) ctx; + if (r == NULL || a == NULL || p == NULL || m == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; } -#endif - if (dh == NULL || dh->p == NULL || dh->g == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS) - WOLFSSL_MSG("Bad DH set internal"); - else if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; + if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { + return SSL_SUCCESS; } - if (rng) { - if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz, - pub, &pubSz) < 0) - WOLFSSL_MSG("Bad wc_DhGenerateKeyPair"); - else { - if (dh->pub_key) - wolfSSL_BN_free(dh->pub_key); + WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); + (void)ret; - dh->pub_key = wolfSSL_BN_new(); - if (dh->pub_key == NULL) { - WOLFSSL_MSG("Bad DH new pub"); - } - if (dh->priv_key) - wolfSSL_BN_free(dh->priv_key); + return SSL_FAILURE; +} - dh->priv_key = wolfSSL_BN_new(); +const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) +{ + static WOLFSSL_BIGNUM* bn_one = NULL; - if (dh->priv_key == NULL) { - WOLFSSL_MSG("Bad DH new priv"); - } + WOLFSSL_MSG("wolfSSL_BN_value_one"); - if (dh->pub_key && dh->priv_key) { - if (wolfSSL_BN_bin2bn(pub, pubSz, dh->pub_key) == NULL) - WOLFSSL_MSG("Bad DH bn2bin error pub"); - else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL) - WOLFSSL_MSG("Bad DH bn2bin error priv"); - else - ret = SSL_SUCCESS; + if (bn_one == NULL) { + bn_one = wolfSSL_BN_new(); + if (bn_one) { + if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) { + /* handle error by freeing BN and returning NULL */ + wolfSSL_BN_free(bn_one); + bn_one = NULL; } } } - if (initTmpRng) - wc_FreeRng(tmpRNG); + return bn_one; +} -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +/* return compliant with OpenSSL + * size of BIGNUM in bytes, 0 if error */ +int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_num_bytes"); - return ret; -} + if (bn == NULL || bn->internal == NULL) + return SSL_FAILURE; + return mp_unsigned_bin_size((mp_int*)bn->internal); +} -/* return code compliant with OpenSSL : - * size of shared secret if success, -1 if error - */ -int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, - WOLFSSL_DH* dh) +/* return compliant with OpenSSL + * size of BIGNUM in bits, 0 if error */ +int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) { - int ret = SSL_FATAL_ERROR; - word32 keySz = 0; - word32 pubSz = 1024; - word32 privSz = 1024; -#ifdef WOLFSSL_SMALL_STACK - unsigned char* pub = NULL; - unsigned char* priv = NULL; -#else - unsigned char pub [1024]; - unsigned char priv[1024]; -#endif - - WOLFSSL_MSG("wolfSSL_DH_compute_key"); + WOLFSSL_MSG("wolfSSL_BN_num_bits"); -#ifdef WOLFSSL_SMALL_STACK - pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) - return ret; + if (bn == NULL || bn->internal == NULL) + return SSL_FAILURE; - priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (priv == NULL) { - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } -#endif + return mp_count_bits((mp_int*)bn->internal); +} - if (dh == NULL || dh->priv_key == NULL || otherPub == NULL) - WOLFSSL_MSG("Bad function arguments"); - else if ((keySz = (word32)DH_size(dh)) == 0) - WOLFSSL_MSG("Bad DH_size"); - else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > (int)privSz) - WOLFSSL_MSG("Bad priv internal size"); - else if (wolfSSL_BN_bn2bin(otherPub, NULL) > (int)pubSz) - WOLFSSL_MSG("Bad otherPub size"); - else { - privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv); - pubSz = wolfSSL_BN_bn2bin(otherPub, pub); - - if (privSz <= 0 || pubSz <= 0) - WOLFSSL_MSG("Bad BN2bin set"); - else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, - priv, privSz, pub, pubSz) < 0) - WOLFSSL_MSG("wc_DhAgree failed"); - else - ret = (int)keySz; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +/* return compliant with OpenSSL + * 1 if BIGNUM is zero, 0 else */ +int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_zero"); - return ret; -} -#endif /* NO_DH */ + if (bn == NULL || bn->internal == NULL) + return SSL_FAILURE; + if (mp_iszero((mp_int*)bn->internal) == MP_YES) + return SSL_SUCCESS; -#ifndef NO_DSA -static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa) -{ - if (dsa) { - dsa->p = NULL; - dsa->q = NULL; - dsa->g = NULL; - dsa->pub_key = NULL; - dsa->priv_key = NULL; - dsa->internal = NULL; - dsa->inSet = 0; - dsa->exSet = 0; - } + return SSL_FAILURE; } - -WOLFSSL_DSA* wolfSSL_DSA_new(void) +/* return compliant with OpenSSL + * 1 if BIGNUM is one, 0 else */ +int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) { - WOLFSSL_DSA* external; - DsaKey* key; - - WOLFSSL_MSG("wolfSSL_DSA_new"); - - key = (DsaKey*) XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_DSA_new malloc DsaKey failure"); - return NULL; - } + WOLFSSL_MSG("wolfSSL_BN_is_one"); - external = (WOLFSSL_DSA*) XMALLOC(sizeof(WOLFSSL_DSA), NULL, - DYNAMIC_TYPE_DSA); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_DSA_new malloc WOLFSSL_DSA failure"); - XFREE(key, NULL, DYNAMIC_TYPE_DSA); - return NULL; - } + if (bn == NULL || bn->internal == NULL) + return SSL_FAILURE; - InitwolfSSL_DSA(external); - InitDsaKey(key); - external->internal = key; + if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) + return SSL_SUCCESS; - return external; + return SSL_FAILURE; } - -void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) +/* return compliant with OpenSSL + * 1 if BIGNUM is odd, 0 else */ +int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) { - WOLFSSL_MSG("wolfSSL_DSA_free"); + WOLFSSL_MSG("wolfSSL_BN_is_odd"); - if (dsa) { - if (dsa->internal) { - FreeDsaKey((DsaKey*)dsa->internal); - XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA); - dsa->internal = NULL; - } - wolfSSL_BN_free(dsa->priv_key); - wolfSSL_BN_free(dsa->pub_key); - wolfSSL_BN_free(dsa->g); - wolfSSL_BN_free(dsa->q); - wolfSSL_BN_free(dsa->p); - InitwolfSSL_DSA(dsa); /* set back to NULLs for safety */ + if (bn == NULL || bn->internal == NULL) + return SSL_FAILURE; - XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); - dsa = NULL; - } -} -#endif /* NO_DSA */ + if (mp_isodd((mp_int*)bn->internal) == MP_YES) + return SSL_SUCCESS; -#ifndef NO_RSA -static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) -{ - if (rsa) { - rsa->n = NULL; - rsa->e = NULL; - rsa->d = NULL; - rsa->p = NULL; - rsa->q = NULL; - rsa->dmp1 = NULL; - rsa->dmq1 = NULL; - rsa->iqmp = NULL; - rsa->internal = NULL; - rsa->inSet = 0; - rsa->exSet = 0; - } + return SSL_FAILURE; } - -WOLFSSL_RSA* wolfSSL_RSA_new(void) +/* return compliant with OpenSSL + * -1 if a < b, 0 if a == b and 1 if a > b + */ +int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) { - WOLFSSL_RSA* external; - RsaKey* key; - - WOLFSSL_MSG("wolfSSL_RSA_new"); - - key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure"); - return NULL; - } - - external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL, - DYNAMIC_TYPE_RSA); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure"); - XFREE(key, NULL, DYNAMIC_TYPE_RSA); - return NULL; - } - - InitwolfSSL_Rsa(external); - if (wc_InitRsaKey(key, NULL) != 0) { - WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure"); - XFREE(external, NULL, DYNAMIC_TYPE_RSA); - XFREE(key, NULL, DYNAMIC_TYPE_RSA); - return NULL; - } - external->internal = key; - - return external; -} + int ret; + WOLFSSL_MSG("wolfSSL_BN_cmp"); -void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) -{ - WOLFSSL_MSG("wolfSSL_RSA_free"); + if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) + return SSL_FATAL_ERROR; - if (rsa) { - if (rsa->internal) { - wc_FreeRsaKey((RsaKey*)rsa->internal); - XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA); - rsa->internal = NULL; - } - wolfSSL_BN_free(rsa->iqmp); - wolfSSL_BN_free(rsa->dmq1); - wolfSSL_BN_free(rsa->dmp1); - wolfSSL_BN_free(rsa->q); - wolfSSL_BN_free(rsa->p); - wolfSSL_BN_free(rsa->d); - wolfSSL_BN_free(rsa->e); - wolfSSL_BN_free(rsa->n); - InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */ + ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); - XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); - rsa = NULL; - } + return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1)); } -#endif /* NO_RSA */ - -#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) \ - || !defined(NO_DSA) || defined(HAVE_ECC) -static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) +/* return compliant with OpenSSL + * length of BIGNUM in bytes, -1 if error */ +int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) { - WOLFSSL_MSG("Entering SetIndividualExternal"); + WOLFSSL_MSG("wolfSSL_BN_bn2bin"); - if (mpi == NULL || bn == NULL) { - WOLFSSL_MSG("mpi NULL error"); + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("NULL bn error"); return SSL_FATAL_ERROR; } - if (*bn == NULL) { - *bn = wolfSSL_BN_new(); - if (*bn == NULL) { - WOLFSSL_MSG("SetIndividualExternal alloc failed"); - return SSL_FATAL_ERROR; - } - } + if (r == NULL) + return mp_unsigned_bin_size((mp_int*)bn->internal); - if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); + if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { + WOLFSSL_MSG("mp_to_unsigned_bin error"); return SSL_FATAL_ERROR; } - return SSL_SUCCESS; + return mp_unsigned_bin_size((mp_int*)bn->internal); } -static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) + +WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, + WOLFSSL_BIGNUM* ret) { - WOLFSSL_MSG("Entering SetIndividualInternal"); + int weOwn = 0; - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_MSG("wolfSSL_BN_bin2bn"); - if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) { - WOLFSSL_MSG("mpi NULL error"); - return SSL_FATAL_ERROR; + /* if ret is null create a BN */ + if (ret == NULL) { + ret = wolfSSL_BN_new(); + weOwn = 1; + if (ret == NULL) + return NULL; } - if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - return SSL_FATAL_ERROR; + /* check ret and ret->internal then read in value */ + if (ret && ret->internal) { + if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) { + WOLFSSL_MSG("mp_read_unsigned_bin failure"); + if (weOwn) + wolfSSL_BN_free(ret); + return NULL; + } } - return SSL_SUCCESS; + return ret; } -#endif /* !NO_RSA && !NO_DSA */ - -#ifndef NO_DSA -/* wolfSSL -> OpenSSL */ -static int SetDsaExternal(WOLFSSL_DSA* dsa) +/* return compliant with OpenSSL + * 1 if success, 0 if error */ +int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) { - DsaKey* key; - WOLFSSL_MSG("Entering SetDsaExternal"); + (void)bn; + (void)n; + WOLFSSL_MSG("wolfSSL_BN_mask_bits"); - if (dsa == NULL || dsa->internal == NULL) { - WOLFSSL_MSG("dsa key NULL error"); - return SSL_FATAL_ERROR; - } + return SSL_FAILURE; +} - key = (DsaKey*)dsa->internal; - if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { - WOLFSSL_MSG("dsa p key error"); - return SSL_FATAL_ERROR; - } +/* SSL_SUCCESS on ok */ +int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + int ret = 0; + int len = bits / 8; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* buff = NULL; +#else + WC_RNG tmpRNG[1]; + byte buff[1024]; +#endif - if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { - WOLFSSL_MSG("dsa q key error"); - return SSL_FATAL_ERROR; - } + (void)top; + (void)bottom; + WOLFSSL_MSG("wolfSSL_BN_rand"); - if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { - WOLFSSL_MSG("dsa g key error"); - return SSL_FATAL_ERROR; + if (bits % 8) + len++; + +#ifdef WOLFSSL_SMALL_STACK + buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buff == NULL || tmpRNG == NULL) { + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; } +#endif - if (SetIndividualExternal(&dsa->pub_key, &key->y) != SSL_SUCCESS) { - WOLFSSL_MSG("dsa y key error"); - return SSL_FATAL_ERROR; + if (bn == NULL || bn->internal == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; } + else if (initGlobalRNG) + rng = &globalRNG; - if (SetIndividualExternal(&dsa->priv_key, &key->x) != SSL_SUCCESS) { - WOLFSSL_MSG("dsa x key error"); - return SSL_FATAL_ERROR; + if (rng) { + if (wc_RNG_GenerateBlock(rng, buff, len) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else { + buff[0] |= 0x80 | 0x40; + buff[len-1] |= 0x01; + + if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) + WOLFSSL_MSG("mp read bin failed"); + else + ret = SSL_SUCCESS; + } } - dsa->exSet = 1; + if (initTmpRng) + wc_FreeRng(tmpRNG); - return SSL_SUCCESS; +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; } -/* Openssl -> WolfSSL */ -static int SetDsaInternal(WOLFSSL_DSA* dsa) +/* return code compliant with OpenSSL : + * 1 if bit set, 0 else + */ +int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) { - DsaKey* key; - WOLFSSL_MSG("Entering SetDsaInternal"); + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; + } - if (dsa == NULL || dsa->internal == NULL) { - WOLFSSL_MSG("dsa key NULL error"); - return SSL_FATAL_ERROR; + if (n > DIGIT_BIT) { + WOLFSSL_MSG("input bit count too large"); + return SSL_FAILURE; } - key = (DsaKey*)dsa->internal; + return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); +} - if (dsa->p != NULL && - SetIndividualInternal(dsa->p, &key->p) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) +{ + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; } - if (dsa->q != NULL && - SetIndividualInternal(dsa->q, &key->q) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; + if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { + WOLFSSL_MSG("mp_set_int error"); + return SSL_FAILURE; } - if (dsa->g != NULL && - SetIndividualInternal(dsa->g, &key->g) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa g key error"); - return SSL_FATAL_ERROR; - } + return SSL_SUCCESS; +} - if (dsa->pub_key != NULL) { - if (SetIndividualInternal(dsa->pub_key, &key->y) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa pub_key error"); - return SSL_FATAL_ERROR; - } - /* public key */ - key->type = DSA_PUBLIC; - } +/* SSL_SUCCESS on ok */ +int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + int ret = 0; + word32 decSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + byte* decoded = NULL; +#else + byte decoded[1024]; +#endif - if (dsa->priv_key != NULL) { - if (SetIndividualInternal(dsa->priv_key, &key->x) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa priv_key error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_MSG("wolfSSL_BN_hex2bn"); - /* private key */ - key->type = DSA_PRIVATE; +#ifdef WOLFSSL_SMALL_STACK + decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return ret; +#endif + + if (str == NULL) + WOLFSSL_MSG("Bad function argument"); + else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0) + WOLFSSL_MSG("Bad Base16_Decode error"); + else if (bn == NULL) + ret = decSz; + else { + if (*bn == NULL) + *bn = wolfSSL_BN_new(); + + if (*bn == NULL) + WOLFSSL_MSG("BN new failed"); + else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) + WOLFSSL_MSG("Bad bin2bn error"); + else + ret = SSL_SUCCESS; } - dsa->inSet = 1; +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif - return SSL_SUCCESS; + return ret; } -#endif /* NO_DSA */ -#if !defined(NO_RSA) -#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) -/* WolfSSL -> OpenSSL */ -static int SetRsaExternal(WOLFSSL_RSA* rsa) +WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) { - RsaKey* key; - WOLFSSL_MSG("Entering SetRsaExternal"); - - if (rsa == NULL || rsa->internal == NULL) { - WOLFSSL_MSG("rsa key NULL error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_BIGNUM* ret; - key = (RsaKey*)rsa->internal; + WOLFSSL_MSG("wolfSSL_BN_dup"); - if (SetIndividualExternal(&rsa->n, &key->n) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa n key error"); - return SSL_FATAL_ERROR; + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; } - if (SetIndividualExternal(&rsa->e, &key->e) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa e key error"); - return SSL_FATAL_ERROR; + ret = wolfSSL_BN_new(); + if (ret == NULL) { + WOLFSSL_MSG("bn new error"); + return NULL; } - if (SetIndividualExternal(&rsa->d, &key->d) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa d key error"); - return SSL_FATAL_ERROR; + if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + wolfSSL_BN_free(ret); + return NULL; } - if (SetIndividualExternal(&rsa->p, &key->p) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; - } + ret->neg = bn->neg; - if (SetIndividualExternal(&rsa->q, &key->q) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; - } + return ret; +} - if (SetIndividualExternal(&rsa->dmp1, &key->dP) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa dP key error"); - return SSL_FATAL_ERROR; - } - if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa dQ key error"); - return SSL_FATAL_ERROR; - } +WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_copy"); - if (SetIndividualExternal(&rsa->iqmp, &key->u) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa u key error"); - return SSL_FATAL_ERROR; + if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return NULL; } - rsa->exSet = 1; + r->neg = bn->neg; - return SSL_SUCCESS; + return r; } -/* Openssl -> WolfSSL */ -static int SetRsaInternal(WOLFSSL_RSA* rsa) +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) { - RsaKey* key; - WOLFSSL_MSG("Entering SetRsaInternal"); + WOLFSSL_MSG("wolfSSL_BN_set_word"); - if (rsa == NULL || rsa->internal == NULL) { - WOLFSSL_MSG("rsa key NULL error"); - return SSL_FATAL_ERROR; + if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { + WOLFSSL_MSG("mp_init_set_int error"); + return SSL_FAILURE; } - key = (RsaKey*)rsa->internal; + return SSL_SUCCESS; +} - if (SetIndividualInternal(rsa->n, &key->n) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa n key error"); - return SSL_FATAL_ERROR; - } +/* return code compliant with OpenSSL : + * number length in decimal if success, 0 if error + */ +int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + (void)bn; + (void)str; - if (SetIndividualInternal(rsa->e, &key->e) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa e key error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_MSG("wolfSSL_BN_dec2bn"); - /* public key */ - key->type = RSA_PUBLIC; + return SSL_FAILURE; +} - if (rsa->d != NULL) { - if (SetIndividualInternal(rsa->d, &key->d) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa d key error"); - return SSL_FATAL_ERROR; - } - /* private key */ - key->type = RSA_PRIVATE; - } +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) +{ + int len = 0; + char *buf; - if (rsa->p != NULL && - SetIndividualInternal(rsa->p, &key->p) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa p key error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_MSG("wolfSSL_BN_bn2dec"); - if (rsa->q != NULL && - SetIndividualInternal(rsa->q, &key->q) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa q key error"); - return SSL_FATAL_ERROR; + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; } - if (rsa->dmp1 != NULL && - SetIndividualInternal(rsa->dmp1, &key->dP) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa dP key error"); - return SSL_FATAL_ERROR; + if (mp_radix_size((mp_int*)bn->internal, 10, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; } - if (rsa->dmq1 != NULL && - SetIndividualInternal(rsa->dmq1, &key->dQ) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa dQ key error"); - return SSL_FATAL_ERROR; + buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); + return NULL; } - if (rsa->iqmp != NULL && - SetIndividualInternal(rsa->iqmp, &key->u) != SSL_SUCCESS) { - WOLFSSL_MSG("rsa u key error"); - return SSL_FATAL_ERROR; + if (mp_toradix((mp_int*)bn->internal, buf, 10) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + return NULL; } - rsa->inSet = 1; + return buf; +} +#else +char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) +{ + (void)bn; - return SSL_SUCCESS; + WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + + return NULL; } -#endif /* HAVE_USER_RSA */ +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ -/* return compliant with OpenSSL - * 1 if success, 0 if error +/* return code compliant with OpenSSL : + * 1 if success, 0 else */ -int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, - void* cb) +int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) { - int ret = SSL_FAILURE; - - (void)cb; - (void)bn; - (void)bits; - - WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex"); + WOLFSSL_MSG("wolfSSL_BN_lshift"); - if (rsa == NULL || rsa->internal == NULL) { - /* bit size checked during make key call */ - WOLFSSL_MSG("bad arguments"); + if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ + WOLFSSL_MSG("bn NULL error"); return SSL_FAILURE; } -#ifdef WOLFSSL_KEY_GEN - { - #ifdef WOLFSSL_SMALL_STACK - WC_RNG* rng = NULL; - #else - WC_RNG rng[1]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (rng == NULL) - return SSL_FAILURE; - #endif - - if (wc_InitRng(rng) < 0) - WOLFSSL_MSG("RNG init failed"); - else if (wc_MakeRsaKey((RsaKey*)rsa->internal, - bits, 65537, rng) != MP_OKAY) - WOLFSSL_MSG("wc_MakeRsaKey failed"); - else if (SetRsaExternal(rsa) != SSL_SUCCESS) - WOLFSSL_MSG("SetRsaExternal failed"); - else { - rsa->inSet = 1; - ret = SSL_SUCCESS; - } - - wc_FreeRng(rng); - #ifdef WOLFSSL_SMALL_STACK - XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_mul_2d error"); + return SSL_FAILURE; } -#else - WOLFSSL_MSG("No Key Gen built in"); -#endif - return ret; -} - - -/* SSL_SUCCESS on ok */ -int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) -{ - (void)rsa; - (void)bn; - - WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); - return SSL_SUCCESS; /* on by default */ + return SSL_SUCCESS; } -/* return compliant with OpenSSL - * size of encrypted data if success , -1 if error +/* return code compliant with OpenSSL : + * 1 if success, 0 else */ -int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA* rsa, int padding) +int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) { - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; + WOLFSSL_MSG("wolfSSL_BN_rshift"); - WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); + if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; + } - return SSL_FATAL_ERROR; + if (mp_div_2d((mp_int*)bn->internal, n, + (mp_int*)r->internal, NULL) != MP_OKAY) { + WOLFSSL_MSG("mp_mul_2d error"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; } -/* return compliant with OpenSSL - * size of plain recovered data if success , -1 if error +/* return code compliant with OpenSSL : + * 1 if success, 0 else */ -int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA* rsa, int padding) +int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) { - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; + WOLFSSL_MSG("wolfSSL_BN_add_word"); - WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; + } - return SSL_FATAL_ERROR; + if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; } -/* return compliant with OpenSSL - * RSA modulus size in bytes, -1 if error +/* return code compliant with OpenSSL : + * 1 if success, 0 else */ -int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) +int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) { - WOLFSSL_MSG("wolfSSL_RSA_size"); + WOLFSSL_MSG("wolfSSL_BN_add"); - if (rsa == NULL) - return SSL_FATAL_ERROR; + if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL || + b == NULL || b->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; + } - return wolfSSL_BN_num_bytes(rsa->n); + if (mp_add((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; } -#endif /* NO_RSA */ -#ifndef NO_DSA +#ifdef WOLFSSL_KEY_GEN + /* return code compliant with OpenSSL : - * 1 if success, 0 if error + * 1 if prime, 0 if not, -1 if error */ -int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) +int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, + WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) { - int ret = SSL_FAILURE; + int res; - WOLFSSL_ENTER("wolfSSL_DSA_generate_key"); + (void)ctx; + (void)cb; - if (dsa == NULL || dsa->internal == NULL) { - WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; - } - - if (dsa->inSet == 0) { - WOLFSSL_MSG("No DSA internal set, do it"); + WOLFSSL_MSG("wolfSSL_BN_is_prime_ex"); - if (SetDsaInternal(dsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetDsaInternal failed"); - return ret; - } + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FATAL_ERROR; } -#ifdef WOLFSSL_KEY_GEN - { - int initTmpRng = 0; - WC_RNG *rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG *tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return SSL_FATAL_ERROR; -#endif - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; - } - - if (rng) { - if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY) - WOLFSSL_MSG("wc_MakeDsaKey failed"); - else if (SetDsaExternal(dsa) != SSL_SUCCESS) - WOLFSSL_MSG("SetDsaExternal failed"); - else - ret = SSL_SUCCESS; - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); + if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) { + WOLFSSL_MSG("mp_prime_is_prime error"); + return SSL_FATAL_ERROR; + } -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (res != MP_YES) { + WOLFSSL_MSG("mp_prime_is_prime not prime"); + return SSL_FAILURE; } -#else /* WOLFSSL_KEY_GEN */ - WOLFSSL_MSG("No Key Gen built in"); -#endif - return ret; + + return SSL_SUCCESS; } /* return code compliant with OpenSSL : - * 1 if success, 0 if error + * (bn mod w) if success, -1 if error */ -int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, - unsigned char* seed, int seedLen, - int* counterRet, - unsigned long* hRet, void* cb) +WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, + WOLFSSL_BN_ULONG w) { - int ret = SSL_FAILURE; - - (void)bits; - (void)seed; - (void)seedLen; - (void)counterRet; - (void)hRet; - (void)cb; + WOLFSSL_BN_ULONG ret = 0; - WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex"); + WOLFSSL_MSG("wolfSSL_BN_mod_word"); - if (dsa == NULL || dsa->internal == NULL) { - WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; } -#ifdef WOLFSSL_KEY_GEN - { - int initTmpRng = 0; - WC_RNG *rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG *tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return SSL_FATAL_ERROR; -#endif - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; - } - - if (rng) { - if (wc_MakeDsaParameters(rng, bits, - (DsaKey*)dsa->internal) != MP_OKAY) - WOLFSSL_MSG("wc_MakeDsaParameters failed"); - else if (SetDsaExternal(dsa) != SSL_SUCCESS) - WOLFSSL_MSG("SetDsaExternal failed"); - else - ret = SSL_SUCCESS; - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return (WOLFSSL_BN_ULONG)SSL_FATAL_ERROR; } -#else /* WOLFSSL_KEY_GEN */ - WOLFSSL_MSG("No Key Gen built in"); -#endif return ret; } +#endif /* #ifdef WOLFSSL_KEY_GEN */ -/* return SSL_SUCCESS on success, < 0 otherwise */ -int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, - WOLFSSL_DSA* dsa) +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) { - int ret = SSL_FATAL_ERROR; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif + int len = 0; + char *buf; - WOLFSSL_ENTER("wolfSSL_DSA_do_sign"); + WOLFSSL_MSG("wolfSSL_BN_bn2hex"); - if (d == NULL || sigRet == NULL || dsa == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return ret; + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; } - if (dsa->inSet == 0) - { - WOLFSSL_MSG("No DSA internal set, do it"); - - if (SetDsaInternal(dsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetDsaInternal failed"); - return ret; - } + if (mp_radix_size((mp_int*)bn->internal, 16, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; } -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return SSL_FATAL_ERROR; -#endif - - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; + buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_ECC); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex malloc buffer failure"); + return NULL; } - if (rng) { - if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) - WOLFSSL_MSG("DsaSign failed"); - else - ret = SSL_SUCCESS; + if (mp_toradix((mp_int*)bn->internal, buf, 16) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + return NULL; } - if (initTmpRng) - wc_FreeRng(tmpRNG); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; + return buf; } - -int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, - WOLFSSL_DSA* dsa, int *dsacheck) +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) { - int ret = SSL_FATAL_ERROR; + char *buf; - WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); + WOLFSSL_MSG("wolfSSL_BN_print_fp"); - if (d == NULL || sig == NULL || dsa == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + if (fp == NULL || bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FAILURE; } - if (dsa->inSet == 0) - { - WOLFSSL_MSG("No DSA internal set, do it"); - if (SetDsaInternal(dsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetDsaInternal failed"); - return SSL_FATAL_ERROR; - } + buf = wolfSSL_BN_bn2hex(bn); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); + return SSL_FAILURE; } - ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck); - if (ret != 0 || *dsacheck != 1) { - WOLFSSL_MSG("DsaVerify failed"); - return ret; - } + fprintf(fp, "%s", buf); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); return SSL_SUCCESS; } -#endif /* NO_DSA */ +#endif /* !defined(NO_FILESYSTEM) */ +#else /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ -#ifndef NO_RSA -/* return SSL_SUCCES on ok, 0 otherwise */ -int wolfSSL_RSA_sign(int type, const unsigned char* m, - unsigned int mLen, unsigned char* sigRet, - unsigned int* sigLen, WOLFSSL_RSA* rsa) +char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) { - word32 outLen; - word32 signSz; - int initTmpRng = 0; - WC_RNG* rng = NULL; - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; - byte* encodedSig = NULL; -#else - WC_RNG tmpRNG[1]; - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - - WOLFSSL_MSG("wolfSSL_RSA_sign"); - - if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return 0; - } - - switch (type) { - #ifdef WOLFSSL_MD2 - case NID_md2: type = MD2h; break; - #endif - #ifndef NO_MD5 - case NID_md5: type = MD5h; break; - #endif - #ifndef NO_SHA - case NID_sha1: type = SHAh; break; - #endif - #ifndef NO_SHA256 - case NID_sha256: type = SHA256h; break; - #endif - #ifdef WOLFSSL_SHA384 - case NID_sha384: type = SHA384h; break; - #endif - #ifdef WOLFSSL_SHA512 - case NID_sha512: type = SHA512h; break; - #endif - default: - WOLFSSL_MSG("This NID (md type) not configured or not implemented"); - return 0; - } + (void)bn; - if (rsa->inSet == 0) - { - WOLFSSL_MSG("No RSA internal set, do it"); + WOLFSSL_MSG("wolfSSL_BN_bn2hex need WOLFSSL_KEY_GEN or HAVE_COMP_KEY"); - if (SetRsaInternal(rsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetRsaInternal failed"); - return 0; - } - } + return (char*)""; +} - outLen = (word32)wolfSSL_BN_num_bytes(rsa->n); +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_BN_print_fp(FILE *fp, const WOLFSSL_BIGNUM *bn) +{ + (void)fp; + (void)bn; -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return 0; + WOLFSSL_MSG("wolfSSL_BN_print_fp not implemented"); - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig == NULL) { - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return 0; - } -#endif + return SSL_SUCCESS; +} +#endif /* !defined(NO_FILESYSTEM) */ - if (outLen == 0) - WOLFSSL_MSG("Bad RSA size"); - else if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; - } +WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) +{ + /* ctx is not used, return new Bignum */ + (void)ctx; - if (rng) { + WOLFSSL_ENTER("wolfSSL_BN_CTX_get"); - signSz = wc_EncodeSignature(encodedSig, m, mLen, type); - if (signSz == 0) { - WOLFSSL_MSG("Bad Encode Signature"); - } - else { - *sigLen = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, - (RsaKey*)rsa->internal, rng); - if (*sigLen <= 0) - WOLFSSL_MSG("Bad Rsa Sign"); - else - ret = SSL_SUCCESS; - } + return wolfSSL_BN_new(); +} - } +void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; - if (initTmpRng) - wc_FreeRng(tmpRNG); + WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); + WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); +} -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +#ifndef NO_DH - if (ret == SSL_SUCCESS) - WOLFSSL_MSG("wolfSSL_RSA_sign success"); - else { - WOLFSSL_MSG("wolfSSL_RSA_sign failed"); +static void InitwolfSSL_DH(WOLFSSL_DH* dh) +{ + if (dh) { + dh->p = NULL; + dh->g = NULL; + dh->q = NULL; + dh->pub_key = NULL; + dh->priv_key = NULL; + dh->internal = NULL; + dh->inSet = 0; + dh->exSet = 0; } - return ret; } -int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, - unsigned char* to, WOLFSSL_RSA* rsa, int padding) +WOLFSSL_DH* wolfSSL_DH_new(void) { - int tlen = 0; + WOLFSSL_DH* external; + DhKey* key; - WOLFSSL_MSG("wolfSSL_RSA_public_decrypt"); + WOLFSSL_MSG("wolfSSL_DH_new"); - if (rsa == NULL || rsa->internal == NULL || from == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return 0; + key = (DhKey*) XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_DH_new malloc DhKey failure"); + return NULL; } - if (padding != RSA_PKCS1_PADDING) { - WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding"); - return 0; + external = (WOLFSSL_DH*) XMALLOC(sizeof(WOLFSSL_DH), NULL, + DYNAMIC_TYPE_DH); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_DH_new malloc WOLFSSL_DH failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + return NULL; } - if (rsa->inSet == 0) - { - WOLFSSL_MSG("No RSA internal set, do it"); - - if (SetRsaInternal(rsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetRsaInternal failed"); - return 0; - } + InitwolfSSL_DH(external); + if (wc_InitDhKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + XFREE(external, NULL, DYNAMIC_TYPE_DH); + return NULL; } + external->internal = key; - /* size of 'to' buffer must be size of RSA key */ - tlen = wc_RsaSSL_Verify(from, flen, to, wolfSSL_RSA_size(rsa), - (RsaKey*)rsa->internal); - if (tlen <= 0) - WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed"); - else { - WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success"); - } - return tlen; + return external; } -/* generate p-1 and q-1, SSL_SUCCESS on ok */ -int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) +void wolfSSL_DH_free(WOLFSSL_DH* dh) { - int err; - mp_int tmp; - - WOLFSSL_MSG("wolfSSL_RsaGenAdd"); - - if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL || - rsa->dmp1 == NULL || rsa->dmq1 == NULL) { - WOLFSSL_MSG("rsa no init error"); - return SSL_FATAL_ERROR; - } - - if (mp_init(&tmp) != MP_OKAY) { - WOLFSSL_MSG("mp_init error"); - return SSL_FATAL_ERROR; - } + WOLFSSL_MSG("wolfSSL_DH_free"); - err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp); - if (err != MP_OKAY) { - WOLFSSL_MSG("mp_sub_d error"); - } - else - err = mp_mod((mp_int*)rsa->d->internal, &tmp, - (mp_int*)rsa->dmp1->internal); + if (dh) { + if (dh->internal) { + wc_FreeDhKey((DhKey*)dh->internal); + XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH); + dh->internal = NULL; + } + wolfSSL_BN_free(dh->priv_key); + wolfSSL_BN_free(dh->pub_key); + wolfSSL_BN_free(dh->g); + wolfSSL_BN_free(dh->p); + wolfSSL_BN_free(dh->q); + InitwolfSSL_DH(dh); /* set back to NULLs for safety */ - if (err != MP_OKAY) { - WOLFSSL_MSG("mp_mod error"); - } - else - err = mp_sub_d((mp_int*)rsa->q->internal, 1, &tmp); - if (err != MP_OKAY) { - WOLFSSL_MSG("mp_sub_d error"); + XFREE(dh, NULL, DYNAMIC_TYPE_DH); } - else - err = mp_mod((mp_int*)rsa->d->internal, &tmp, - (mp_int*)rsa->dmq1->internal); - - mp_clear(&tmp); - - if (err == MP_OKAY) - return SSL_SUCCESS; - else - return SSL_FATAL_ERROR; } -#endif /* NO_RSA */ -void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, - const EVP_MD* type) +static int SetDhInternal(WOLFSSL_DH* dh) { - WOLFSSL_MSG("wolfSSL_HMAC_Init"); - - if (ctx == NULL) { - WOLFSSL_MSG("no ctx on init"); - return; - } - - if (type) { - WOLFSSL_MSG("init has type"); + int ret = SSL_FATAL_ERROR; + int pSz = 1024; + int gSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + unsigned char* p = NULL; + unsigned char* g = NULL; +#else + unsigned char p[1024]; + unsigned char g[1024]; +#endif - if (XSTRNCMP(type, "MD5", 3) == 0) { - WOLFSSL_MSG("md5 hmac"); - ctx->type = MD5; - } - else if (XSTRNCMP(type, "SHA256", 6) == 0) { - WOLFSSL_MSG("sha256 hmac"); - ctx->type = SHA256; - } + WOLFSSL_ENTER("SetDhInternal"); - /* has to be last since would pick or 256, 384, or 512 too */ - else if (XSTRNCMP(type, "SHA", 3) == 0) { - WOLFSSL_MSG("sha hmac"); - ctx->type = SHA; + if (dh == NULL || dh->p == NULL || dh->g == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wolfSSL_BN_bn2bin(dh->p, NULL) > pSz) + WOLFSSL_MSG("Bad p internal size"); + else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz) + WOLFSSL_MSG("Bad g internal size"); + else { + #ifdef WOLFSSL_SMALL_STACK + p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (p == NULL || g == NULL) { + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; } + #endif + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if (pSz <= 0 || gSz <= 0) + WOLFSSL_MSG("Bad BN2bin set"); + else if (wc_DhSetKey((DhKey*)dh->internal, p, pSz, g, gSz) < 0) + WOLFSSL_MSG("Bad DH SetKey"); else { - WOLFSSL_MSG("bad init type"); + dh->inSet = 1; + ret = SSL_SUCCESS; } - } - if (key && keylen) { - WOLFSSL_MSG("keying hmac"); - wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, (word32)keylen); - /* OpenSSL compat, no error */ + #ifdef WOLFSSL_SMALL_STACK + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif } -} -void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, - int len) -{ - WOLFSSL_MSG("wolfSSL_HMAC_Update"); - - if (ctx && data) { - WOLFSSL_MSG("updating hmac"); - wc_HmacUpdate(&ctx->hmac, data, (word32)len); - /* OpenSSL compat, no error */ - } + return ret; } - -void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, - unsigned int* len) +/* return code compliant with OpenSSL : + * DH prime size in bytes if success, 0 if error + */ +int wolfSSL_DH_size(WOLFSSL_DH* dh) { - WOLFSSL_MSG("wolfSSL_HMAC_Final"); - - if (ctx && hash) { - WOLFSSL_MSG("final hmac"); - wc_HmacFinal(&ctx->hmac, hash); - /* OpenSSL compat, no error */ - - if (len) { - WOLFSSL_MSG("setting output len"); - switch (ctx->type) { - case MD5: - *len = MD5_DIGEST_SIZE; - break; - - case SHA: - *len = SHA_DIGEST_SIZE; - break; + WOLFSSL_MSG("wolfSSL_DH_size"); - case SHA256: - *len = SHA256_DIGEST_SIZE; - break; + if (dh == NULL) + return SSL_FATAL_ERROR; - default: - WOLFSSL_MSG("bad hmac type"); - } - } - } + return wolfSSL_BN_num_bytes(dh->p); } -void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) { - (void)ctx; - - WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); -} + int ret = SSL_FAILURE; + word32 pubSz = 768; + word32 privSz = 768; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + unsigned char* pub = NULL; + unsigned char* priv = NULL; + WC_RNG* tmpRNG = NULL; +#else + unsigned char pub [768]; + unsigned char priv[768]; + WC_RNG tmpRNG[1]; +#endif + WOLFSSL_MSG("wolfSSL_DH_generate_key"); -const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) -{ - WOLFSSL_MSG("wolfSSL_get_digestbynid"); +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - switch(id) { -#ifndef NO_MD5 - case NID_md5: - return wolfSSL_EVP_md5(); -#endif -#ifndef NO_SHA - case NID_sha1: - return wolfSSL_EVP_sha1(); + if (tmpRNG == NULL || pub == NULL || priv == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } #endif - default: - WOLFSSL_MSG("Bad digest id value"); + + if (dh == NULL || dh->p == NULL || dh->g == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS) + WOLFSSL_MSG("Bad DH set internal"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; } - return NULL; -} + if (rng) { + if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz, + pub, &pubSz) < 0) + WOLFSSL_MSG("Bad wc_DhGenerateKeyPair"); + else { + if (dh->pub_key) + wolfSSL_BN_free(dh->pub_key); + dh->pub_key = wolfSSL_BN_new(); + if (dh->pub_key == NULL) { + WOLFSSL_MSG("Bad DH new pub"); + } + if (dh->priv_key) + wolfSSL_BN_free(dh->priv_key); -WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) -{ - (void)key; - WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA not implemented"); + dh->priv_key = wolfSSL_BN_new(); - return NULL; -} + if (dh->priv_key == NULL) { + WOLFSSL_MSG("Bad DH new priv"); + } + if (dh->pub_key && dh->priv_key) { + if (wolfSSL_BN_bin2bn(pub, pubSz, dh->pub_key) == NULL) + WOLFSSL_MSG("Bad DH bn2bin error pub"); + else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL) + WOLFSSL_MSG("Bad DH bn2bin error priv"); + else + ret = SSL_SUCCESS; + } + } + } -WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) -{ - (void)key; - WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA not implemented"); + if (initTmpRng) + wc_FreeRng(tmpRNG); - return NULL; +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; } -WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) +/* return code compliant with OpenSSL : + * size of shared secret if success, -1 if error + */ +int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, + WOLFSSL_DH* dh) { - (void)key; - WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_EC_KEY not implemented"); + int ret = SSL_FATAL_ERROR; + word32 keySz = 0; + word32 pubSz = 1024; + word32 privSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + unsigned char* pub = NULL; + unsigned char* priv = NULL; +#else + unsigned char pub [1024]; + unsigned char priv[1024]; +#endif - return NULL; -} + WOLFSSL_MSG("wolfSSL_DH_compute_key"); +#ifdef WOLFSSL_SMALL_STACK + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return ret; -void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) -{ - WOLFSSL_MSG("wolfSSL_EVP_X_STATE"); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } +#endif - if (ctx) { - switch (ctx->cipherType) { - case ARC4_TYPE: - WOLFSSL_MSG("returning arc4 state"); - return (void*)&ctx->cipher.arc4.x; + if (dh == NULL || dh->priv_key == NULL || otherPub == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if ((keySz = (word32)DH_size(dh)) == 0) + WOLFSSL_MSG("Bad DH_size"); + else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > (int)privSz) + WOLFSSL_MSG("Bad priv internal size"); + else if (wolfSSL_BN_bn2bin(otherPub, NULL) > (int)pubSz) + WOLFSSL_MSG("Bad otherPub size"); + else { + privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv); + pubSz = wolfSSL_BN_bn2bin(otherPub, pub); - default: - WOLFSSL_MSG("bad x state type"); - return 0; - } + if (privSz <= 0 || pubSz <= 0) + WOLFSSL_MSG("Bad BN2bin set"); + else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, + priv, privSz, pub, pubSz) < 0) + WOLFSSL_MSG("wc_DhAgree failed"); + else + ret = (int)keySz; } - return NULL; +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; } +#endif /* NO_DH */ -int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx) +#ifndef NO_DSA +static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa) { - WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN"); - - if (ctx) { - switch (ctx->cipherType) { - case ARC4_TYPE: - WOLFSSL_MSG("returning arc4 state size"); - return sizeof(Arc4); - - default: - WOLFSSL_MSG("bad x state type"); - return 0; - } + if (dsa) { + dsa->p = NULL; + dsa->q = NULL; + dsa->g = NULL; + dsa->pub_key = NULL; + dsa->priv_key = NULL; + dsa->internal = NULL; + dsa->inSet = 0; + dsa->exSet = 0; } - - return 0; } -#ifndef NO_DES3 - -void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, - unsigned char* iv, int len) +WOLFSSL_DSA* wolfSSL_DSA_new(void) { - (void)len; + WOLFSSL_DSA* external; + DsaKey* key; - WOLFSSL_MSG("wolfSSL_3des_iv"); + WOLFSSL_MSG("wolfSSL_DSA_new"); - if (ctx == NULL || iv == NULL) { - WOLFSSL_MSG("Bad function argument"); - return; + key = (DsaKey*) XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_DSA_new malloc DsaKey failure"); + return NULL; } - if (doset) - wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */ - else - XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); -} + external = (WOLFSSL_DSA*) XMALLOC(sizeof(WOLFSSL_DSA), NULL, + DYNAMIC_TYPE_DSA); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_DSA_new malloc WOLFSSL_DSA failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + return NULL; + } -#endif /* NO_DES3 */ + InitwolfSSL_DSA(external); + if (wc_InitDsaKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + return NULL; + } + external->internal = key; + return external; +} -#ifndef NO_AES -void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, - unsigned char* iv, int len) +void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) { - (void)len; + WOLFSSL_MSG("wolfSSL_DSA_free"); - WOLFSSL_MSG("wolfSSL_aes_ctr_iv"); + if (dsa) { + if (dsa->internal) { + FreeDsaKey((DsaKey*)dsa->internal); + XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA); + dsa->internal = NULL; + } + wolfSSL_BN_free(dsa->priv_key); + wolfSSL_BN_free(dsa->pub_key); + wolfSSL_BN_free(dsa->g); + wolfSSL_BN_free(dsa->q); + wolfSSL_BN_free(dsa->p); + InitwolfSSL_DSA(dsa); /* set back to NULLs for safety */ - if (ctx == NULL || iv == NULL) { - WOLFSSL_MSG("Bad function argument"); - return; + XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); + dsa = NULL; } - - if (doset) - wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ - else - XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); } -#endif /* NO_AES */ - +#endif /* NO_DSA */ -const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) +#ifndef NO_RSA +static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) { - WOLFSSL_MSG("wolfSSL_ripemd160"); - - return NULL; + if (rsa) { + rsa->n = NULL; + rsa->e = NULL; + rsa->d = NULL; + rsa->p = NULL; + rsa->q = NULL; + rsa->dmp1 = NULL; + rsa->dmq1 = NULL; + rsa->iqmp = NULL; + rsa->internal = NULL; + rsa->inSet = 0; + rsa->exSet = 0; + } } -int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) +WOLFSSL_RSA* wolfSSL_RSA_new(void) { - WOLFSSL_MSG("wolfSSL_EVP_MD_size"); + WOLFSSL_RSA* external; + RsaKey* key; - if (type == NULL) { - WOLFSSL_MSG("No md type arg"); - return BAD_FUNC_ARG; - } + WOLFSSL_MSG("wolfSSL_RSA_new"); - if (XSTRNCMP(type, "SHA256", 6) == 0) { - return SHA256_DIGEST_SIZE; - } -#ifndef NO_MD5 - else if (XSTRNCMP(type, "MD5", 3) == 0) { - return MD5_DIGEST_SIZE; - } -#endif -#ifdef WOLFSSL_SHA224 - else if (XSTRNCMP(type, "SHA224", 6) == 0) { - return SHA224_DIGEST_SIZE; - } -#endif -#ifdef WOLFSSL_SHA384 - else if (XSTRNCMP(type, "SHA384", 6) == 0) { - return SHA384_DIGEST_SIZE; + key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure"); + return NULL; } -#endif -#ifdef WOLFSSL_SHA512 - else if (XSTRNCMP(type, "SHA512", 6) == 0) { - return SHA512_DIGEST_SIZE; + + external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL, + DYNAMIC_TYPE_RSA); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure"); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; } -#endif -#ifndef NO_SHA - /* has to be last since would pick or 256, 384, or 512 too */ - else if (XSTRNCMP(type, "SHA", 3) == 0) { - return SHA_DIGEST_SIZE; + + InitwolfSSL_Rsa(external); + if (wc_InitRsaKey(key, NULL) != 0) { + WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; } -#endif + external->internal = key; - return BAD_FUNC_ARG; + return external; } -int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) +void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) { - WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); + WOLFSSL_MSG("wolfSSL_RSA_free"); - switch (ctx->cipherType) { + if (rsa) { + if (rsa->internal) { + wc_FreeRsaKey((RsaKey*)rsa->internal); + XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA); + rsa->internal = NULL; + } + wolfSSL_BN_free(rsa->iqmp); + wolfSSL_BN_free(rsa->dmq1); + wolfSSL_BN_free(rsa->dmp1); + wolfSSL_BN_free(rsa->q); + wolfSSL_BN_free(rsa->p); + wolfSSL_BN_free(rsa->d); + wolfSSL_BN_free(rsa->e); + wolfSSL_BN_free(rsa->n); + InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */ - case AES_128_CBC_TYPE : - case AES_192_CBC_TYPE : - case AES_256_CBC_TYPE : - WOLFSSL_MSG("AES CBC"); - return AES_BLOCK_SIZE; + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); + rsa = NULL; + } +} +#endif /* NO_RSA */ -#ifdef WOLFSSL_AES_COUNTER - case AES_128_CTR_TYPE : - case AES_192_CTR_TYPE : - case AES_256_CTR_TYPE : - WOLFSSL_MSG("AES CTR"); - return AES_BLOCK_SIZE; -#endif - case DES_CBC_TYPE : - WOLFSSL_MSG("DES CBC"); - return DES_BLOCK_SIZE; +/* these defines are to make sure the functions SetIndividualExternal is not + * declared and then not used. */ +#if !defined(NO_ASN) || !defined(NO_DSA) || defined(HAVE_ECC) || \ + (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) +/* when calling SetIndividualExternal, mpi should be cleared by caller if no + * longer used. ie mp_clear(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + */ +static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) +{ + byte dynamic = 0; - case DES_EDE3_CBC_TYPE : - WOLFSSL_MSG("DES EDE3 CBC"); - return DES_BLOCK_SIZE; -#ifdef HAVE_IDEA - case IDEA_CBC_TYPE : - WOLFSSL_MSG("IDEA CBC"); - return IDEA_BLOCK_SIZE; -#endif - case ARC4_TYPE : - WOLFSSL_MSG("ARC4"); - return 0; + WOLFSSL_MSG("Entering SetIndividualExternal"); - case NULL_CIPHER_TYPE : - WOLFSSL_MSG("NULL"); - return 0; + if (mpi == NULL || bn == NULL) { + WOLFSSL_MSG("mpi NULL error"); + return SSL_FATAL_ERROR; + } - default: { - WOLFSSL_MSG("bad type"); + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + WOLFSSL_MSG("SetIndividualExternal alloc failed"); + return SSL_FATAL_ERROR; } + dynamic = 1; + } + + if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + if (dynamic == 1) { + wolfSSL_BN_free(*bn); + } + return SSL_FATAL_ERROR; } - return 0; -} + return SSL_SUCCESS; +} -void wolfSSL_OPENSSL_free(void* p) +static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) { - WOLFSSL_MSG("wolfSSL_OPENSSL_free"); + WOLFSSL_MSG("Entering SetIndividualInternal"); - XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return SSL_FATAL_ERROR; + } + + if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) { + WOLFSSL_MSG("mpi NULL error"); + return SSL_FATAL_ERROR; + } + + if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return SSL_FATAL_ERROR; + } + + return SSL_SUCCESS; } -#if defined(WOLFSSL_KEY_GEN) -static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, byte **cipherInfo) +#ifndef NO_ASN +WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn) { - int ret, paddingSz; - word32 idx, cipherInfoSz; -#ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; -#else - EncryptedInfo info[1]; -#endif - - WOLFSSL_ENTER("EncryptDerKey"); + mp_int mpi; + word32 idx = 0; + int ret; - if (der == NULL || derSz == NULL || cipher == NULL || - passwd == NULL || cipherInfo == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN"); -#ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (info == NULL) { - WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + if (ai == NULL) { + return NULL; } -#endif - info->set = 0; - info->ctx = NULL; - info->consumed = 0; - /* set iv size */ - if (XSTRNCMP(cipher, "DES", 3) == 0) - info->ivSz = DES_IV_SIZE; - else if (XSTRNCMP(cipher, "AES", 3) == 0) - info->ivSz = AES_IV_SIZE; - else { - WOLFSSL_MSG("unsupported cipher"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return SSL_FAILURE; + if ((ret = GetInt(&mpi, ai->data, &idx, sizeof(ai->data))) != 0) { + /* expecting ASN1 format for INTEGER */ + WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret); + return NULL; } - /* set the cipher name on info */ - XSTRNCPY(info->name, cipher, NAME_SZ); + /* mp_clear needs called because mpi is copied and causes memory leak with + * --disable-fastmath */ + ret = SetIndividualExternal(&bn, &mpi); + mp_clear(&mpi); - /* Generate a random salt */ - if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != SSL_SUCCESS) { - WOLFSSL_MSG("generate iv failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return SSL_FAILURE; + if (ret != SSL_SUCCESS) { + return NULL; } + return bn; +} +#endif /* !NO_ASN */ - /* add the padding before encryption */ - paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz); - if (paddingSz == 0) - paddingSz = info->ivSz; - XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz); - (*derSz) += paddingSz; +#if !defined(NO_DSA) && !defined(NO_DH) +WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa) +{ + WOLFSSL_DH* dh; + DhKey* key; - /* encrypt buffer */ - if (wolfssl_encrypt_buffer_key(der, *derSz, - passwd, passwdSz, info) != SSL_SUCCESS) { - WOLFSSL_MSG("encrypt key failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return SSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_DSA_dup_DH"); + + if (dsa == NULL) { + return NULL; } - /* create cipher info : 'cipher_name,Salt(hex)' */ - cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2); - *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (*cipherInfo == NULL) { - WOLFSSL_MSG("malloc failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return SSL_FAILURE; + dh = wolfSSL_DH_new(); + if (dh == NULL) { + return NULL; } - XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz); - XSTRNCAT((char*)*cipherInfo, ",", 1); + key = (DhKey*)dh->internal; - idx = (word32)XSTRLEN((char*)*cipherInfo); - cipherInfoSz -= idx; - ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz); + if (dsa->p != NULL && + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + wolfSSL_DH_free(dh); + return NULL; + } + if (dsa->g != NULL && + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - if (ret != 0) { - WOLFSSL_MSG("Base16_Encode failed"); - XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (SetIndividualExternal(&dh->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + wolfSSL_DH_free(dh); + return NULL; + } + if (SetIndividualExternal(&dh->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + wolfSSL_DH_free(dh); + return NULL; } - return SSL_SUCCESS; + return dh; } -#endif /* defined(WOLFSSL_KEY_GEN) */ +#endif /* !defined(NO_DSA) && !defined(NO_DH) */ -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) +#endif /* !NO_RSA && !NO_DSA */ -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, - unsigned char **pem, int *plen) -{ - byte *derBuf, *tmp, *cipherInfo = NULL; - int der_max_len = 0, derSz = 0; - WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey"); +#ifndef NO_DSA +/* wolfSSL -> OpenSSL */ +static int SetDsaExternal(WOLFSSL_DSA* dsa) +{ + DsaKey* key; + WOLFSSL_MSG("Entering SetDsaExternal"); - if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("dsa key NULL error"); + return SSL_FATAL_ERROR; } - if (rsa->inSet == 0) { - WOLFSSL_MSG("No RSA internal set, do it"); + key = (DsaKey*)dsa->internal; - if (SetRsaInternal(rsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetRsaInternal failed"); - return SSL_FAILURE; - } + if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + return SSL_FATAL_ERROR; } - /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional - * informations - */ - der_max_len = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE; + if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + return SSL_FATAL_ERROR; + } - derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (derBuf == NULL) { - WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + return SSL_FATAL_ERROR; } - /* Key to DER */ - derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, der_max_len); - if (derSz < 0) { - WOLFSSL_MSG("wc_RsaKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (SetIndividualExternal(&dsa->pub_key, &key->y) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa y key error"); + return SSL_FATAL_ERROR; } - /* encrypt DER buffer if required */ - if (passwd != NULL && passwdSz > 0 && cipher != NULL) { - int ret; + if (SetIndividualExternal(&dsa->priv_key, &key->x) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa x key error"); + return SSL_FATAL_ERROR; + } - ret = EncryptDerKey(derBuf, &derSz, cipher, - passwd, passwdSz, &cipherInfo); - if (ret != SSL_SUCCESS) { - WOLFSSL_MSG("EncryptDerKey failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + dsa->exSet = 1; - /* tmp buffer with a max size */ - *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + - sizeof(END_RSA_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; - } - else /* tmp buffer with a max size */ - *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + sizeof(END_RSA_PRIV); + return SSL_SUCCESS; +} - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { - WOLFSSL_MSG("malloc failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; +/* Openssl -> WolfSSL */ +static int SetDsaInternal(WOLFSSL_DSA* dsa) +{ + DsaKey* key; + WOLFSSL_MSG("Entering SetDsaInternal"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("dsa key NULL error"); + return SSL_FATAL_ERROR; } - /* DER to PEM */ - *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, PRIVATEKEY_TYPE); - if (*plen <= 0) { - WOLFSSL_MSG("wc_DerToPemEx failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; - } - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + key = (DsaKey*)dsa->internal; - *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); - if (*pem == NULL) { - WOLFSSL_MSG("malloc failed"); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (dsa->p != NULL && + SetIndividualInternal(dsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return SSL_FATAL_ERROR; } - XMEMSET(*pem, 0, (*plen)+1); - if (XMEMCPY(*pem, tmp, *plen) == NULL) { - WOLFSSL_MSG("XMEMCPY failed"); - XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (dsa->q != NULL && + SetIndividualInternal(dsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return SSL_FATAL_ERROR; } - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return SSL_SUCCESS; -} - - -#ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa, - const EVP_CIPHER *enc, - unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) -{ - byte *pem; - int plen, ret; - - (void)cb; - (void)u; - - WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey"); - if (fp == NULL || rsa == NULL || rsa->internal == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + if (dsa->g != NULL && + SetIndividualInternal(dsa->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + return SSL_FATAL_ERROR; } - ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen); - if (ret != SSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); - return SSL_FAILURE; - } + if (dsa->pub_key != NULL) { + if (SetIndividualInternal(dsa->pub_key, &key->y) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa pub_key error"); + return SSL_FATAL_ERROR; + } - ret = (int)XFWRITE(pem, plen, 1, fp); - if (ret != 1) { - WOLFSSL_MSG("RSA private key file write failed"); - return SSL_FAILURE; + /* public key */ + key->type = DSA_PUBLIC; } - XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - return SSL_SUCCESS; -} -#endif /* NO_FILESYSTEM */ + if (dsa->priv_key != NULL) { + if (SetIndividualInternal(dsa->priv_key, &key->x) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa priv_key error"); + return SSL_FATAL_ERROR; + } -int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg) -{ - (void)bio; - (void)rsa; - (void)cipher; - (void)passwd; - (void)len; - (void)cb; - (void)arg; + /* private key */ + key->type = DSA_PRIVATE; + } - WOLFSSL_MSG("wolfSSL_PEM_write_bio_RSAPrivateKey not implemented"); + dsa->inSet = 1; - return SSL_FAILURE; + return SSL_SUCCESS; } -#endif /* defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) */ +#endif /* NO_DSA */ -#ifdef HAVE_ECC -/* EC_POINT Openssl -> WolfSSL */ -static int SetECPointInternal(WOLFSSL_EC_POINT *p) +#if !defined(NO_RSA) +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) +/* WolfSSL -> OpenSSL */ +static int SetRsaExternal(WOLFSSL_RSA* rsa) { - ecc_point* point; - WOLFSSL_ENTER("SetECPointInternal"); + RsaKey* key; + WOLFSSL_MSG("Entering SetRsaExternal"); - if (p == NULL || p->internal == NULL) { - WOLFSSL_MSG("ECPoint NULL error"); + if (rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("rsa key NULL error"); return SSL_FATAL_ERROR; } - point = (ecc_point*)p->internal; + key = (RsaKey*)rsa->internal; - if (p->X != NULL && SetIndividualInternal(p->X, point->x) != SSL_SUCCESS) { - WOLFSSL_MSG("ecc point X error"); + if (SetIndividualExternal(&rsa->n, &key->n) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); return SSL_FATAL_ERROR; } - if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != SSL_SUCCESS) { - WOLFSSL_MSG("ecc point Y error"); + if (SetIndividualExternal(&rsa->e, &key->e) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); return SSL_FATAL_ERROR; } - if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != SSL_SUCCESS) { - WOLFSSL_MSG("ecc point Z error"); + if (SetIndividualExternal(&rsa->d, &key->d) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); return SSL_FATAL_ERROR; } - p->inSet = 1; - - return SSL_SUCCESS; -} - -/* EC_POINT WolfSSL -> OpenSSL */ -static int SetECPointExternal(WOLFSSL_EC_POINT *p) -{ - ecc_point* point; - - WOLFSSL_ENTER("SetECPointExternal"); - - if (p == NULL || p->internal == NULL) { - WOLFSSL_MSG("ECPoint NULL error"); + if (SetIndividualExternal(&rsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); return SSL_FATAL_ERROR; } - point = (ecc_point*)p->internal; + if (SetIndividualExternal(&rsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return SSL_FATAL_ERROR; + } - if (SetIndividualExternal(&p->X, point->x) != SSL_SUCCESS) { - WOLFSSL_MSG("ecc point X error"); + if (SetIndividualExternal(&rsa->dmp1, &key->dP) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); return SSL_FATAL_ERROR; } - if (SetIndividualExternal(&p->Y, point->y) != SSL_SUCCESS) { - WOLFSSL_MSG("ecc point Y error"); + if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); return SSL_FATAL_ERROR; } - if (SetIndividualExternal(&p->Z, point->z) != SSL_SUCCESS) { - WOLFSSL_MSG("ecc point Z error"); + if (SetIndividualExternal(&rsa->iqmp, &key->u) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); return SSL_FATAL_ERROR; } - p->exSet = 1; + rsa->exSet = 1; return SSL_SUCCESS; } -/* EC_KEY wolfSSL -> OpenSSL */ -static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) +/* Openssl -> WolfSSL */ +static int SetRsaInternal(WOLFSSL_RSA* rsa) { - ecc_key* key; + RsaKey* key; + WOLFSSL_MSG("Entering SetRsaInternal"); - WOLFSSL_ENTER("SetECKeyExternal"); + if (rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("rsa key NULL error"); + return SSL_FATAL_ERROR; + } - if (eckey == NULL || eckey->internal == NULL) { - WOLFSSL_MSG("ec key NULL error"); + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); return SSL_FATAL_ERROR; } - key = (ecc_key*)eckey->internal; + if (SetIndividualInternal(rsa->e, &key->e) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return SSL_FATAL_ERROR; + } - /* set group (nid and idx) */ - eckey->group->curve_nid = ecc_sets[key->idx].id; - eckey->group->curve_idx = key->idx; + /* public key */ + key->type = RSA_PUBLIC; - if (eckey->pub_key->internal != NULL) { - /* set the internal public key */ - if (wc_ecc_copy_point(&key->pubkey, - (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { - WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->d) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); return SSL_FATAL_ERROR; } - /* set the external pubkey (point) */ - if (SetECPointExternal(eckey->pub_key) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); - return SSL_FATAL_ERROR; - } + /* private key */ + key->type = RSA_PRIVATE; } - /* set the external privkey */ - if (key->type == ECC_PRIVATEKEY) { - if (SetIndividualExternal(&eckey->priv_key, &key->k) != SSL_SUCCESS) { - WOLFSSL_MSG("ec priv key error"); - return SSL_FATAL_ERROR; - } + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return SSL_FATAL_ERROR; } - eckey->exSet = 1; - - return SSL_SUCCESS; -} - -/* EC_KEY Openssl -> WolfSSL */ -static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) -{ - ecc_key* key; - - WOLFSSL_ENTER("SetECKeyInternal"); + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return SSL_FATAL_ERROR; + } - if (eckey == NULL || eckey->internal == NULL) { - WOLFSSL_MSG("ec key NULL error"); + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dP) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); return SSL_FATAL_ERROR; } - key = (ecc_key*)eckey->internal; + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQ) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return SSL_FATAL_ERROR; + } - /* validate group */ - if ((eckey->group->curve_idx < 0) || - (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { - WOLFSSL_MSG("invalid curve idx"); + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->u) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); return SSL_FATAL_ERROR; } - /* set group (idx of curve and corresponding domain parameters) */ - key->idx = eckey->group->curve_idx; - key->dp = &ecc_sets[key->idx]; + rsa->inSet = 1; - /* set pubkey (point) */ - if (eckey->pub_key != NULL) { - if (SetECPointInternal(eckey->pub_key) != SSL_SUCCESS) { - WOLFSSL_MSG("ec key pub error"); - return SSL_FATAL_ERROR; - } + return SSL_SUCCESS; +} +#endif /* HAVE_USER_RSA */ - /* public key */ - key->type = ECC_PUBLICKEY; +/* return compliant with OpenSSL + * 1 if success, 0 if error + */ +int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, + void* cb) +{ + int ret = SSL_FAILURE; + + (void)cb; + (void)bn; + (void)bits; + + WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex"); + + if (rsa == NULL || rsa->internal == NULL) { + /* bit size checked during make key call */ + WOLFSSL_MSG("bad arguments"); + return SSL_FAILURE; } - /* set privkey */ - if (eckey->priv_key != NULL) { - if (SetIndividualInternal(eckey->priv_key, &key->k) != SSL_SUCCESS) { - WOLFSSL_MSG("ec key priv error"); - return SSL_FATAL_ERROR; +#ifdef WOLFSSL_KEY_GEN + { + #ifdef WOLFSSL_SMALL_STACK + WC_RNG* rng = NULL; + #else + WC_RNG rng[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rng == NULL) + return SSL_FAILURE; + #endif + + if (wc_InitRng(rng) < 0) + WOLFSSL_MSG("RNG init failed"); + else if (wc_MakeRsaKey((RsaKey*)rsa->internal, + bits, 65537, rng) != MP_OKAY) + WOLFSSL_MSG("wc_MakeRsaKey failed"); + else if (SetRsaExternal(rsa) != SSL_SUCCESS) + WOLFSSL_MSG("SetRsaExternal failed"); + else { + rsa->inSet = 1; + ret = SSL_SUCCESS; } - /* private key */ - key->type = ECC_PRIVATEKEY; + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif } +#else + WOLFSSL_MSG("No Key Gen built in"); +#endif + return ret; +} - eckey->inSet = 1; - return SSL_SUCCESS; +/* SSL_SUCCESS on ok */ +int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) +{ + (void)rsa; + (void)bn; + + WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); + + return SSL_SUCCESS; /* on by default */ } -WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) +/* return compliant with OpenSSL + * size of encrypted data if success , -1 if error + */ +int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); + (void)len; + (void)fr; + (void)to; + (void)rsa; + (void)padding; - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); - return NULL; - } + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); - return key->pub_key; + return SSL_FATAL_ERROR; } -const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) +/* return compliant with OpenSSL + * size of plain recovered data if success , -1 if error + */ +int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); + (void)len; + (void)fr; + (void)to; + (void)rsa; + (void)padding; - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); - return NULL; - } + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); - return key->group; + return SSL_FATAL_ERROR; } +/* return compliant with OpenSSL + * RSA modulus size in bytes, -1 if error + */ +int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) +{ + WOLFSSL_MSG("wolfSSL_RSA_size"); + + if (rsa == NULL) + return SSL_FATAL_ERROR; + + return wolfSSL_BN_num_bytes(rsa->n); +} +#endif /* NO_RSA */ +#ifndef NO_DSA /* return code compliant with OpenSSL : * 1 if success, 0 if error */ -int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, - const WOLFSSL_BIGNUM *priv_key) +int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) { - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); + int ret = SSL_FAILURE; - if (key == NULL || priv_key == NULL) { + WOLFSSL_ENTER("wolfSSL_DSA_generate_key"); + + if (dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("Bad arguments"); return SSL_FAILURE; } - /* free key if previously set */ - if (key->priv_key != NULL) - wolfSSL_BN_free(key->priv_key); + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); - key->priv_key = wolfSSL_BN_dup(priv_key); - if (key->priv_key == NULL) { - WOLFSSL_MSG("key ecc priv key NULL"); - return SSL_FAILURE; + if (SetDsaInternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return ret; + } } - if (SetECKeyInternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyInternal failed"); - wolfSSL_BN_free(key->priv_key); - return SSL_FAILURE; - } +#ifdef WOLFSSL_KEY_GEN + { + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif - return SSL_SUCCESS; -} +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_FATAL_ERROR; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + if (rng) { + if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY) + WOLFSSL_MSG("wc_MakeDsaKey failed"); + else if (SetDsaExternal(dsa) != SSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = SSL_SUCCESS; + } -WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); + if (initTmpRng) + wc_FreeRng(tmpRNG); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); - return NULL; +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif } - - return key->priv_key; +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif + return ret; } -WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, + unsigned char* seed, int seedLen, + int* counterRet, + unsigned long* hRet, void* cb) { - WOLFSSL_EC_KEY *key; - int x; + int ret = SSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); + (void)bits; + (void)seed; + (void)seedLen; + (void)counterRet; + (void)hRet; + (void)cb; - key = wolfSSL_EC_KEY_new(); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); - return NULL; + WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; } - /* set the nid of the curve */ - key->group->curve_nid = nid; +#ifdef WOLFSSL_KEY_GEN + { + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif - /* search and set the corresponding internal curve idx */ - for (x = 0; ecc_sets[x].size != 0; x++) - if (ecc_sets[x].id == key->group->curve_nid) { - key->group->curve_idx = x; - break; - } - - return key; -} - -static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key) -{ - if (key) { - key->group = NULL; - key->pub_key = NULL; - key->priv_key = NULL; - key->internal = NULL; - key->inSet = 0; - key->exSet = 0; - } -} - -WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) -{ - WOLFSSL_EC_KEY *external; - ecc_key* key; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); - - external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL, - DYNAMIC_TYPE_ECC); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); - return NULL; - } - XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY)); - - InitwolfSSL_ECKey(external); - - external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, - DYNAMIC_TYPE_ECC); - if (external->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); - wolfSSL_EC_KEY_free(external); - return NULL; - } - XMEMSET(external->internal, 0, sizeof(ecc_key)); - - wc_ecc_init((ecc_key*)external->internal); - - /* public key */ - external->pub_key = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), - NULL, DYNAMIC_TYPE_ECC); - if (external->pub_key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_POINT failure"); - wolfSSL_EC_KEY_free(external); - return NULL; - } - XMEMSET(external->pub_key, 0, sizeof(WOLFSSL_EC_POINT)); - - key = (ecc_key*)external->internal; - external->pub_key->internal = (ecc_point*)&key->pubkey; - - /* curve group */ - external->group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, - DYNAMIC_TYPE_ECC); - if (external->group == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); - wolfSSL_EC_KEY_free(external); - return NULL; - } - XMEMSET(external->group, 0, sizeof(WOLFSSL_EC_GROUP)); - - /* private key */ - external->priv_key = wolfSSL_BN_new(); - if (external->priv_key == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new failure"); - wolfSSL_EC_KEY_free(external); - return NULL; - } - - return external; -} - -void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); - - if (key != NULL) { - if (key->internal != NULL) { - wc_ecc_free((ecc_key*)key->internal); - XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC); +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_FATAL_ERROR; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; } - wolfSSL_BN_free(key->priv_key); - wolfSSL_EC_POINT_free(key->pub_key); - wolfSSL_EC_GROUP_free(key->group); - InitwolfSSL_ECKey(key); /* set back to NULLs for safety */ - XFREE(key, NULL, DYNAMIC_TYPE_ECC); - key = NULL; - } -} + if (rng) { + if (wc_MakeDsaParameters(rng, bits, + (DsaKey*)dsa->internal) != MP_OKAY) + WOLFSSL_MSG("wc_MakeDsaParameters failed"); + else if (SetDsaExternal(dsa) != SSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = SSL_SUCCESS; + } -int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) -{ - (void)key; - (void)group; + if (initTmpRng) + wc_FreeRng(tmpRNG); - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); - WOLFSSL_MSG("wolfSSL_EC_KEY_set_group TBD"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif - return -1; + return ret; } -int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) +/* return SSL_SUCCESS on success, < 0 otherwise */ +int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, + WOLFSSL_DSA* dsa) { + int ret = SSL_FATAL_ERROR; int initTmpRng = 0; WC_RNG* rng = NULL; #ifdef WOLFSSL_SMALL_STACK @@ -16594,18 +18948,27 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) WC_RNG tmpRNG[1]; #endif - WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); + WOLFSSL_ENTER("wolfSSL_DSA_do_sign"); - if (key == NULL || key->internal == NULL || - key->group == NULL || key->group->curve_idx < 0) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); - return 0; + if (d == NULL || sigRet == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return ret; + } + + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return ret; + } } #ifdef WOLFSSL_SMALL_STACK tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmpRNG == NULL) - return 0; + return SSL_FATAL_ERROR; #endif if (wc_InitRng(tmpRNG) == 0) { @@ -16620,21 +18983,11 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) rng = &globalRNG; } - if (rng == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return 0; - } - - if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal, - key->group->curve_nid) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return 0; + if (rng) { + if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) + WOLFSSL_MSG("DsaSign failed"); + else + ret = SSL_SUCCESS; } if (initTmpRng) @@ -16643,852 +18996,850 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (SetECKeyExternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); - return 0; - } - - return 1; + return ret; } -void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) -{ - (void)key; - (void)asn1_flag; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); - WOLFSSL_MSG("wolfSSL_EC_KEY_set_asn1_flag TBD"); -} -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, - const WOLFSSL_EC_POINT *pub) +int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, + WOLFSSL_DSA* dsa, int *dsacheck) { - ecc_point *pub_p, *key_p; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); + int ret = SSL_FATAL_ERROR; - if (key == NULL || key->internal == NULL || - pub == NULL || pub->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments"); - return SSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); - if (key->inSet == 0) { - if (SetECKeyInternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FAILURE; - } + if (d == NULL || sig == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FATAL_ERROR; } + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); - if (pub->inSet == 0) { - if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + if (SetDsaInternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return SSL_FATAL_ERROR; } } - pub_p = (ecc_point*)pub->internal; - key_p = (ecc_point*)key->pub_key->internal; - - /* create new point if required */ - if (key_p == NULL) - key_p = wc_ecc_new_point(); - - if (key_p == NULL) { - WOLFSSL_MSG("key ecc point NULL"); - return SSL_FAILURE; + ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck); + if (ret != 0 || *dsacheck != 1) { + WOLFSSL_MSG("DsaVerify failed"); + return ret; } - if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { - WOLFSSL_MSG("ecc_copy_point failure"); - return SSL_FAILURE; - } + return SSL_SUCCESS; +} +#endif /* NO_DSA */ - if (SetECKeyExternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FAILURE; - } -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) - wolfssl_EC_POINT_dump("pub", pub); - wolfssl_EC_POINT_dump("key->pub_key", key->pub_key); +#ifndef NO_RSA +/* return SSL_SUCCES on ok, 0 otherwise */ +int wolfSSL_RSA_sign(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA* rsa) +{ + word32 outLen; + word32 signSz; + int initTmpRng = 0; + WC_RNG* rng = NULL; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* encodedSig = NULL; +#else + WC_RNG tmpRNG[1]; + byte encodedSig[MAX_ENCODED_SIG_SZ]; #endif - return SSL_SUCCESS; -} -/* End EC_KEY */ -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) -void wolfssl_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) -{ - char *num; + WOLFSSL_MSG("wolfSSL_RSA_sign"); - WOLFSSL_ENTER("wolfssl_EC_POINT_dump"); + if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } - if (p == NULL) { - fprintf(stderr, "%s = NULL", msg); - return ; + switch (type) { + #ifdef WOLFSSL_MD2 + case NID_md2: type = MD2h; break; + #endif + #ifndef NO_MD5 + case NID_md5: type = MD5h; break; + #endif + #ifndef NO_SHA + case NID_sha1: type = SHAh; break; + #endif + #ifndef NO_SHA256 + case NID_sha256: type = SHA256h; break; + #endif + #ifdef WOLFSSL_SHA384 + case NID_sha384: type = SHA384h; break; + #endif + #ifdef WOLFSSL_SHA512 + case NID_sha512: type = SHA512h; break; + #endif + default: + WOLFSSL_MSG("This NID (md type) not configured or not implemented"); + return 0; } - fprintf(stderr, "%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); - num = wolfSSL_BN_bn2hex(p->X); - fprintf(stderr, "\tX = %s\n", num); - XFREE(num, NULL, DYNAMIC_TYPE_ECC); - num = wolfSSL_BN_bn2hex(p->Y); - fprintf(stderr, "\tY = %s\n", num); - XFREE(num, NULL, DYNAMIC_TYPE_ECC); -} -#endif + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); -/* Start EC_GROUP */ + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } -/* return code compliant with OpenSSL : - * 0 if equal, 1 if not and -1 in case of error - */ -int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, - WOLFSSL_BN_CTX *ctx) -{ - (void)ctx; + outLen = (word32)wolfSSL_BN_num_bytes(rsa->n); - WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return 0; - if (a == NULL || b == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); - return SSL_FATAL_ERROR; + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return 0; } +#endif - /* ok */ - if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid)) - return 0; + if (outLen == 0) + WOLFSSL_MSG("Bad RSA size"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); - /* ko */ - return 1; -} + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } -void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) -{ - WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); + if (rng) { - XFREE(group, NULL, DYNAMIC_TYPE_ECC); - group = NULL; -} + signSz = wc_EncodeSignature(encodedSig, m, mLen, type); + if (signSz == 0) { + WOLFSSL_MSG("Bad Encode Signature"); + } + else { + ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, + (RsaKey*)rsa->internal, rng); + if (ret <= 0) { + WOLFSSL_MSG("Bad Rsa Sign"); + ret = 0; + } + else { + ret = SSL_SUCCESS; + *sigLen = ret; + } + } -void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) -{ - (void)group; - (void)flag; + } - WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag"); - WOLFSSL_MSG("wolfSSL_EC_GROUP_set_asn1_flag TBD"); + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == SSL_SUCCESS) + WOLFSSL_MSG("wolfSSL_RSA_sign success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_sign failed"); + } + return ret; } -WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) + +int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - WOLFSSL_EC_GROUP *g; - int x; + int tlen = 0; - WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt"); - /* curve group */ - g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, - DYNAMIC_TYPE_ECC); - if (g == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); - return NULL; + if (rsa == NULL || rsa->internal == NULL || from == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; } - XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP)); - /* set the nid of the curve */ - g->curve_nid = nid; + if (padding != RSA_PKCS1_PADDING) { + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding"); + return 0; + } - /* search and set the corresponding internal curve idx */ - for (x = 0; ecc_sets[x].size != 0; x++) - if (ecc_sets[x].id == g->curve_nid) { - g->curve_idx = x; - break; + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; } + } - return g; + /* size of 'to' buffer must be size of RSA key */ + tlen = wc_RsaSSL_Verify(from, flen, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal); + if (tlen <= 0) + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed"); + else { + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success"); + } + return tlen; } -/* return code compliant with OpenSSL : - * the curve nid if success, 0 if error - */ -int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) + +/* generate p-1 and q-1, SSL_SUCCESS on ok */ +int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) { - WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name"); + int err; + mp_int tmp; - if (group == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); - return SSL_FAILURE; - } + WOLFSSL_MSG("wolfSSL_RsaGenAdd"); - return group->curve_nid; -} + if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL || + rsa->dmp1 == NULL || rsa->dmq1 == NULL) { + WOLFSSL_MSG("rsa no init error"); + return SSL_FATAL_ERROR; + } -/* return code compliant with OpenSSL : - * the degree of the curve if success, 0 if error - */ -int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) -{ - WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); + if (mp_init(&tmp) != MP_OKAY) { + WOLFSSL_MSG("mp_init error"); + return SSL_FATAL_ERROR; + } - if (group == NULL || group->curve_idx < 0) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); - return SSL_FAILURE; + err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp); + if (err != MP_OKAY) { + WOLFSSL_MSG("mp_sub_d error"); } + else + err = mp_mod((mp_int*)rsa->d->internal, &tmp, + (mp_int*)rsa->dmp1->internal); - switch(group->curve_nid) { - case NID_secp112r1: - case NID_secp112r2: - return 112; - case NID_secp128r1: - case NID_secp128r2: - return 128; - case NID_secp160k1: - case NID_secp160r1: - case NID_secp160r2: - case NID_brainpoolP160r1: - return 160; - case NID_secp192k1: - case NID_brainpoolP192r1: - case NID_X9_62_prime192v1: - return 192; - case NID_secp224k1: - case NID_secp224r1: - case NID_brainpoolP224r1: - return 224; - case NID_secp256k1: - case NID_brainpoolP256r1: - case NID_X9_62_prime256v1: - return 256; - case NID_brainpoolP320r1: - return 320; - case NID_secp384r1: - case NID_brainpoolP384r1: - return 384; - case NID_secp521r1: - case NID_brainpoolP512r1: - return 521; - default: - return SSL_FAILURE; - } -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, - WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) -{ - (void)ctx; - - if (group == NULL || order == NULL || order->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); - return SSL_FAILURE; + if (err != MP_OKAY) { + WOLFSSL_MSG("mp_mod error"); } - - if (mp_init((mp_int*)order->internal) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); - return SSL_FAILURE; + else + err = mp_sub_d((mp_int*)rsa->q->internal, 1, &tmp); + if (err != MP_OKAY) { + WOLFSSL_MSG("mp_sub_d error"); } + else + err = mp_mod((mp_int*)rsa->d->internal, &tmp, + (mp_int*)rsa->dmq1->internal); - if (mp_read_radix((mp_int*)order->internal, - ecc_sets[group->curve_idx].order, 16) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); - mp_clear((mp_int*)order->internal); - return SSL_FAILURE; - } + mp_clear(&tmp); - return SSL_SUCCESS; + if (err == MP_OKAY) + return SSL_SUCCESS; + else + return SSL_FATAL_ERROR; } -/* End EC_GROUP */ +#endif /* NO_RSA */ -/* Start EC_POINT */ -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *p, - unsigned char *out, unsigned int *len) +void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, + const EVP_MD* type) { - int err; - - WOLFSSL_ENTER("wolfSSL_ECPoint_i2d"); + WOLFSSL_MSG("wolfSSL_HMAC_Init"); - if (group == NULL || p == NULL || len == NULL) { - WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); - return SSL_FAILURE; + if (ctx == NULL) { + WOLFSSL_MSG("no ctx on init"); + return; } - if (p->inSet == 0) { - WOLFSSL_MSG("No ECPoint internal set, do it"); + if (type) { + WOLFSSL_MSG("init has type"); - if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); - return SSL_FAILURE; + if (XSTRNCMP(type, "MD5", 3) == 0) { + WOLFSSL_MSG("md5 hmac"); + ctx->type = MD5; + } + else if (XSTRNCMP(type, "SHA256", 6) == 0) { + WOLFSSL_MSG("sha256 hmac"); + ctx->type = SHA256; } - } -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) - if (out != NULL) { - wolfssl_EC_POINT_dump("i2d p", p); + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + WOLFSSL_MSG("sha hmac"); + ctx->type = SHA; + } + else { + WOLFSSL_MSG("bad init type"); + } } -#endif - err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, - out, len); - if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) { - WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); - return SSL_FAILURE; + + if (key && keylen) { + WOLFSSL_MSG("keying hmac"); + + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, + (word32)keylen); + } + /* OpenSSL compat, no error */ } +} - return SSL_SUCCESS; +int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, int len, + const EVP_MD* md, void* impl) +{ + (void)impl; + wolfSSL_HMAC_Init(ctx, key, len, md); + return 1; } -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, - const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p) + +void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, + int len) { - WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); + WOLFSSL_MSG("wolfSSL_HMAC_Update"); - if (group == NULL || p == NULL || p->internal == NULL || in == NULL) { - WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); - return SSL_FAILURE; + if (ctx && data) { + WOLFSSL_MSG("updating hmac"); + wc_HmacUpdate(&ctx->hmac, data, (word32)len); + /* OpenSSL compat, no error */ } +} - if (wc_ecc_import_point_der(in, len, group->curve_idx, - (ecc_point*)p->internal) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_import_point_der failed"); - return SSL_FAILURE; - } - if (p->exSet == 0) { - WOLFSSL_MSG("No ECPoint external set, do it"); +void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len) +{ + WOLFSSL_MSG("wolfSSL_HMAC_Final"); - if (SetECPointExternal(p) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointExternal failed"); - return SSL_FAILURE; + if (ctx && hash) { + WOLFSSL_MSG("final hmac"); + wc_HmacFinal(&ctx->hmac, hash); + /* OpenSSL compat, no error */ + + if (len) { + WOLFSSL_MSG("setting output len"); + switch (ctx->type) { + case MD5: + *len = MD5_DIGEST_SIZE; + break; + + case SHA: + *len = SHA_DIGEST_SIZE; + break; + + case SHA256: + *len = SHA256_DIGEST_SIZE; + break; + + default: + WOLFSSL_MSG("bad hmac type"); + } } } - -#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) - wolfssl_EC_POINT_dump("d2i p", p); -#endif - return SSL_SUCCESS; } -WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) + +void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) { - WOLFSSL_EC_POINT *p; + WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); - WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); + if (ctx) + wc_HmacFree(&ctx->hmac); +} - if (group == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); - return NULL; - } - p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, - DYNAMIC_TYPE_ECC); - if (p == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); - return NULL; - } - XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT)); +const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) +{ + WOLFSSL_MSG("wolfSSL_get_digestbynid"); - p->internal = wc_ecc_new_point(); - if (p->internal == NULL) { - WOLFSSL_MSG("ecc_new_point failure"); - XFREE(p, NULL, DYNAMIC_TYPE_ECC); - return NULL; + switch(id) { +#ifndef NO_MD5 + case NID_md5: + return wolfSSL_EVP_md5(); +#endif +#ifndef NO_SHA + case NID_sha1: + return wolfSSL_EVP_sha1(); +#endif + default: + WOLFSSL_MSG("Bad digest id value"); } - return p; + return NULL; } -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *point, - WOLFSSL_BIGNUM *x, - WOLFSSL_BIGNUM *y, - WOLFSSL_BN_CTX *ctx) + +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) { - (void)ctx; + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA not implemented"); - WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); + return NULL; +} - if (group == NULL || point == NULL || point->internal == NULL || - x == NULL || y == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); - return SSL_FAILURE; - } - if (point->inSet == 0) { - WOLFSSL_MSG("No ECPoint internal set, do it"); +WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) +{ + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA not implemented"); - if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; - } - } - - BN_copy(x, point->X); - BN_copy(y, point->Y); - - return SSL_SUCCESS; + return NULL; } -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, - const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, - const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) + +WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) { - mp_int a, prime; + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_EC_KEY not implemented"); - (void)ctx; - (void)n; + return NULL; +} - WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); - if (group == NULL || r == NULL || r->internal == NULL || - q == NULL || q->internal == NULL || m == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); - return SSL_FAILURE; - } +void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE"); - if (q->inSet == 0) { - WOLFSSL_MSG("No ECPoint internal set, do it"); + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state"); + return (void*)&ctx->cipher.arc4.x; - if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + default: + WOLFSSL_MSG("bad x state type"); + return 0; } } - /* read the curve prime and a */ - if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_POINT_mul init 'prime/A' failed"); - return SSL_FAILURE; - } - if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'prime' curve value failed"); - return SSL_FAILURE; - } - if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'A' curve value failed"); - return SSL_FAILURE; - } + return NULL; +} - /* r = q * m % prime */ - if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, - (ecc_point*)r->internal, &a, &prime, 1) != MP_OKAY) { - WOLFSSL_MSG("ecc_mulmod failure"); - mp_clear(&prime); - return SSL_FAILURE; - } - mp_clear(&a); - mp_clear(&prime); +int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN"); - /* set the external value for the computed point */ - if (SetECPointInternal(r) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state size"); + return sizeof(Arc4); + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } } - return SSL_SUCCESS; + return 0; } -void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) -{ - WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); - wolfSSL_EC_POINT_free(p); -} +#ifndef NO_DES3 -/* return code compliant with OpenSSL : - * 0 if equal, 1 if not and -1 in case of error - */ -int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, - WOLFSSL_BN_CTX *ctx) +void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, + unsigned char* iv, int len) { - int ret; - - (void)ctx; + (void)len; - WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); + WOLFSSL_MSG("wolfSSL_3des_iv"); - if (group == NULL || a == NULL || a->internal == NULL || b == NULL || - b->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); - return SSL_FATAL_ERROR; + if (ctx == NULL || iv == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; } - ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal); - if (ret == MP_EQ) - return 0; - else if (ret == MP_LT || ret == MP_GT) - return 1; - - return SSL_FATAL_ERROR; + if (doset) + wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); } -void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) -{ - WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); - - if (p != NULL) { - if (p->internal == NULL) { - wc_ecc_del_point((ecc_point*)p->internal); - XFREE(p->internal, NULL, DYNAMIC_TYPE_ECC); - p->internal = NULL; - } +#endif /* NO_DES3 */ - wolfSSL_BN_free(p->X); - wolfSSL_BN_free(p->Y); - wolfSSL_BN_free(p->Z); - p->X = NULL; - p->Y = NULL; - p->Z = NULL; - p->inSet = p->exSet = 0; - XFREE(p, NULL, DYNAMIC_TYPE_ECC); - p = NULL; - } -} +#ifndef NO_AES -/* return code compliant with OpenSSL : - * 1 if point at infinity, 0 else - */ -int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *point) +void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, + unsigned char* iv, int len) { - int ret; - - WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); - - if (group == NULL || point == NULL || point->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); - return SSL_FAILURE; - } - if (point->inSet == 0) { - WOLFSSL_MSG("No ECPoint internal set, do it"); + (void)len; - if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; - } - } + WOLFSSL_MSG("wolfSSL_aes_ctr_iv"); - ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); - if (ret <= 0) { - WOLFSSL_MSG("ecc_point_is_at_infinity failure"); - return SSL_FAILURE; + if (ctx == NULL || iv == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; } - return SSL_SUCCESS; + if (doset) + wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); } -/* End EC_POINT */ +#endif /* NO_AES */ -/* Start ECDSA_SIG */ -void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) -{ - WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); - if (sig) { - wolfSSL_BN_free(sig->r); - wolfSSL_BN_free(sig->s); +const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) +{ + WOLFSSL_MSG("wolfSSL_ripemd160"); - XFREE(sig, NULL, DYNAMIC_TYPE_ECC); - } + return NULL; } -WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) -{ - WOLFSSL_ECDSA_SIG *sig; - WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); +int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_size"); - sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, - DYNAMIC_TYPE_ECC); - if (sig == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); - return NULL; + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; } - sig->s = NULL; - sig->r = wolfSSL_BN_new(); - if (sig->r == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); - wolfSSL_ECDSA_SIG_free(sig); - return NULL; + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return SHA256_DIGEST_SIZE; } - - sig->s = wolfSSL_BN_new(); - if (sig->s == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); - wolfSSL_ECDSA_SIG_free(sig); - return NULL; +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return MD5_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return SHA224_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return SHA384_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return SHA512_DIGEST_SIZE; + } +#endif +#ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + return SHA_DIGEST_SIZE; } +#endif - return sig; + return BAD_FUNC_ARG; } -/* return signature structure on success, NULL otherwise */ -WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, - WOLFSSL_EC_KEY *key) + +int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) { - WOLFSSL_ECDSA_SIG *sig = NULL; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); + + switch (ctx->cipherType) { + + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + return AES_BLOCK_SIZE; + +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + return AES_BLOCK_SIZE; #endif - WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + return DES_BLOCK_SIZE; - if (d == NULL || key == NULL || key->internal == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); - return NULL; - } + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + return DES_BLOCK_SIZE; +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + return IDEA_BLOCK_SIZE; +#endif + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + return 0; - /* set internal key if not done */ - if (key->inSet == 0) - { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + return 0; - if (SetECKeyInternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); - return NULL; + default: { + WOLFSSL_MSG("bad type"); } } + return 0; +} -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return NULL; -#endif +int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher) +{ + const char *name = (const char *)cipher; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length"); - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; +#ifndef NO_AES + if ((XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)) { + return AES_BLOCK_SIZE; } - else { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init"); - else - rng = &globalRNG; +#ifdef WOLFSSL_AES_COUNTER + if ((XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)) { + return AES_BLOCK_SIZE; } +#endif +#endif - if (rng) { - mp_int sig_r, sig_s; - - if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) { - if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal, - &sig_r, &sig_s) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_sign_hash_ex failed"); - } - else { - /* put signature blob in ECDSA structure */ - sig = wolfSSL_ECDSA_SIG_new(); - if (sig == NULL) - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed"); - else if (SetIndividualExternal(&(sig->r), &sig_r)!=SSL_SUCCESS){ - WOLFSSL_MSG("ecdsa r key error"); - wolfSSL_ECDSA_SIG_free(sig); - sig = NULL; - } - else if (SetIndividualExternal(&(sig->s), &sig_s)!=SSL_SUCCESS){ - WOLFSSL_MSG("ecdsa s key error"); - wolfSSL_ECDSA_SIG_free(sig); - sig = NULL; - } - - } - mp_clear(&sig_r); - mp_clear(&sig_s); - } +#ifndef NO_DES3 + if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; } +#endif - if (initTmpRng) - wc_FreeRng(tmpRNG); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef HAVE_IDEA + if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; #endif - return sig; + (void)name; + + return 0; } -/* return code compliant with OpenSSL : - * 1 for a valid signature, 0 for an invalid signature and -1 on error +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. */ -int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, - const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) +void wolfSSL_OPENSSL_free(void* p) { - int check_sign = 0; + WOLFSSL_MSG("wolfSSL_OPENSSL_free"); - WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); +} - if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); - return SSL_FATAL_ERROR; +#if defined(WOLFSSL_KEY_GEN) + +static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, byte **cipherInfo) +{ + int ret, paddingSz; + word32 idx, cipherInfoSz; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("EncryptDerKey"); + + if (der == NULL || derSz == NULL || cipher == NULL || + passwd == NULL || cipherInfo == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_FAILURE; } +#endif + info->set = 0; + info->ctx = NULL; + info->consumed = 0; - /* set internal key if not done */ - if (key->inSet == 0) - { - WOLFSSL_MSG("No EC key internal set, do it"); + /* set iv size */ + if (XSTRNCMP(cipher, "DES", 3) == 0) + info->ivSz = DES_IV_SIZE; + else if (XSTRNCMP(cipher, "AES", 3) == 0) + info->ivSz = AES_IV_SIZE; + else { + WOLFSSL_MSG("unsupported cipher"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FAILURE; + } - if (SetECKeyInternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FATAL_ERROR; - } + /* set the cipher name on info */ + XSTRNCPY(info->name, cipher, NAME_SZ); + info->name[NAME_SZ-1] = '\0'; /* null term */ + + /* Generate a random salt */ + if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != SSL_SUCCESS) { + WOLFSSL_MSG("generate iv failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FAILURE; } - if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, - (mp_int*)sig->s->internal, d, dlen, &check_sign, - (ecc_key *)key->internal) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_verify_hash failed"); - return SSL_FATAL_ERROR; + /* add the padding before encryption */ + paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz); + if (paddingSz == 0) + paddingSz = info->ivSz; + XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz); + (*derSz) += paddingSz; + + /* encrypt buffer */ + if (wolfssl_encrypt_buffer_key(der, *derSz, + passwd, passwdSz, info) != SSL_SUCCESS) { + WOLFSSL_MSG("encrypt key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FAILURE; } - else if (check_sign == 0) { - WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + + /* create cipher info : 'cipher_name,Salt(hex)' */ + cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2); + *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (*cipherInfo == NULL) { + WOLFSSL_MSG("malloc failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return SSL_FAILURE; + } + XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz); + XSTRNCAT((char*)*cipherInfo, ",", 1); + + idx = (word32)XSTRLEN((char*)*cipherInfo); + cipherInfoSz -= idx; + ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + if (ret != 0) { + WOLFSSL_MSG("Base16_Encode failed"); + XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); return SSL_FAILURE; } return SSL_SUCCESS; } -/* End ECDSA_SIG */ +#endif /* defined(WOLFSSL_KEY_GEN) */ -/* Start ECDH */ -/* return code compliant with OpenSSL : - * length of computed key if success, -1 if error - */ -int wolfSSL_ECDH_compute_key(void *out, size_t outlen, - const WOLFSSL_EC_POINT *pub_key, - WOLFSSL_EC_KEY *ecdh, - void *(*KDF) (const void *in, size_t inlen, - void *out, size_t *outlen)) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) { - word32 len; - (void)KDF; + byte* keyDer; + int pemSz; + int type; + int ret; - (void)KDF; + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; - WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); - if (out == NULL || pub_key == NULL || pub_key->internal == NULL || - ecdh == NULL || ecdh->internal == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + if (bio == NULL || key == NULL) { + return SSL_FAILURE; } - /* set internal key if not done */ - if (ecdh->inSet == 0) - { - WOLFSSL_MSG("No EC key internal set, do it"); + keyDer = (byte*)key->pkey.ptr; - if (SetECKeyInternal(ecdh) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return SSL_FATAL_ERROR; - } - } + switch (key->type) { + case EVP_PKEY_RSA: + type = PRIVATEKEY_TYPE; + break; - len = (word32)outlen; +#ifndef NO_DSA + case EVP_PKEY_DSA: + type = DSA_PRIVATEKEY_TYPE; + break; +#endif - if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal, - (ecc_point*)pub_key->internal, - (byte *)out, &len) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_shared_secret failed"); - return SSL_FATAL_ERROR; - } + case EVP_PKEY_EC: + type = ECC_PRIVATEKEY_TYPE; + break; - return len; -} -/* End ECDH */ + default: + WOLFSSL_MSG("Unknown Key type!"); + type = PRIVATEKEY_TYPE; + } -#if !defined(NO_FILESYSTEM) -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x) -{ - (void)fp; - (void)x; + pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); + return SSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + bio->memLen = pemSz; - WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented"); + ret = wc_DerToPemEx(keyDer, key->pkey_sz, bio->mem, bio->memLen, + NULL, type); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); + return SSL_FAILURE; + } - return SSL_FAILURE; + return SSL_SUCCESS; } -#endif /* NO_FILESYSTEM */ - -#if defined(WOLFSSL_KEY_GEN) - -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg) -{ - (void)bio; - (void)ecc; - (void)cipher; - (void)passwd; - (void)len; - (void)cb; - (void)arg; - - WOLFSSL_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented"); +#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ - return SSL_FAILURE; -} +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) /* return code compliant with OpenSSL : * 1 if success, 0 if error */ -int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, - const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, - unsigned char **pem, int *plen) +int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) { byte *derBuf, *tmp, *cipherInfo = NULL; int der_max_len = 0, derSz = 0; - WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); + WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey"); - if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { + if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); return SSL_FAILURE; } - if (ecc->inSet == 0) { - WOLFSSL_MSG("No ECC internal set, do it"); + if (rsa->inSet == 0) { + WOLFSSL_MSG("No RSA internal set, do it"); - if (SetECKeyInternal(ecc) != SSL_SUCCESS) { - WOLFSSL_MSG("SetDsaInternal failed"); + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); return SSL_FAILURE; } } - /* 4 > size of pub, priv + ASN.1 additional informations + /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional + * informations */ - der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE; + der_max_len = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE; derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (derBuf == NULL) { @@ -17497,9 +19848,9 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, } /* Key to DER */ - derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len); + derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, der_max_len); if (derSz < 0) { - WOLFSSL_MSG("wc_DsaKeyToDer failed"); + WOLFSSL_MSG("wc_RsaKeyToDer failed"); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return SSL_FAILURE; } @@ -17517,11 +19868,11 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, } /* tmp buffer with a max size */ - *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + - sizeof(END_EC_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; + *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + + sizeof(END_RSA_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; } else /* tmp buffer with a max size */ - *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + sizeof(END_EC_PRIV); + *plen = (derSz * 2) + sizeof(BEGIN_RSA_PRIV) + sizeof(END_RSA_PRIV); tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { @@ -17533,7 +19884,7 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, } /* DER to PEM */ - *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, ECC_PRIVATEKEY_TYPE); + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, PRIVATEKEY_TYPE); if (*plen <= 0) { WOLFSSL_MSG("wc_DerToPemEx failed"); XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -17565,14 +19916,15 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, return SSL_SUCCESS; } + #ifndef NO_FILESYSTEM /* return code compliant with OpenSSL : * 1 if success, 0 if error */ -int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc, - const EVP_CIPHER *enc, - unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) +int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) { byte *pem; int plen, ret; @@ -17580,1978 +19932,4683 @@ int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc, (void)cb; (void)u; - WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey"); + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey"); - if (fp == NULL || ecc == NULL || ecc->internal == NULL) { + if (fp == NULL || rsa == NULL || rsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); return SSL_FAILURE; } - ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); + ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen); if (ret != SSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); + WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); return SSL_FAILURE; } ret = (int)XFWRITE(pem, plen, 1, fp); if (ret != 1) { - WOLFSSL_MSG("ECC private key file write failed"); + WOLFSSL_MSG("RSA private key file write failed"); return SSL_FAILURE; } XFREE(pem, NULL, DYNAMIC_TYPE_KEY); return SSL_SUCCESS; } - #endif /* NO_FILESYSTEM */ -#endif /* defined(WOLFSSL_KEY_GEN) */ - -#endif /* HAVE_ECC */ - - -#ifndef NO_DSA - -#if defined(WOLFSSL_KEY_GEN) -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - pem_password_cb cb, void* arg) +int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) { (void)bio; - (void)dsa; + (void)rsa; (void)cipher; (void)passwd; (void)len; (void)cb; (void)arg; - WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey not implemented"); + WOLFSSL_MSG("wolfSSL_PEM_write_bio_RSAPrivateKey not implemented"); return SSL_FAILURE; } +#endif /* defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) */ -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, - unsigned char **pem, int *plen) -{ - byte *derBuf, *tmp, *cipherInfo = NULL; - int der_max_len = 0, derSz = 0; +#ifdef HAVE_ECC - WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey"); +/* EC_POINT Openssl -> WolfSSL */ +static int SetECPointInternal(WOLFSSL_EC_POINT *p) +{ + ecc_point* point; + WOLFSSL_ENTER("SetECPointInternal"); - if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + if (p == NULL || p->internal == NULL) { + WOLFSSL_MSG("ECPoint NULL error"); + return SSL_FATAL_ERROR; } - if (dsa->inSet == 0) { - WOLFSSL_MSG("No DSA internal set, do it"); + point = (ecc_point*)p->internal; - if (SetDsaInternal(dsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetDsaInternal failed"); - return SSL_FAILURE; - } + if (p->X != NULL && SetIndividualInternal(p->X, point->x) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return SSL_FATAL_ERROR; } - /* 4 > size of pub, priv, p, q, g + ASN.1 additional informations - */ - der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; - - derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (derBuf == NULL) { - WOLFSSL_MSG("malloc failed"); - return SSL_FAILURE; + if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return SSL_FATAL_ERROR; } - /* Key to DER */ - derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len); - if (derSz < 0) { - WOLFSSL_MSG("wc_DsaKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return SSL_FATAL_ERROR; } - /* encrypt DER buffer if required */ - if (passwd != NULL && passwdSz > 0 && cipher != NULL) { - int ret; + p->inSet = 1; - ret = EncryptDerKey(derBuf, &derSz, cipher, - passwd, passwdSz, &cipherInfo); - if (ret != SSL_SUCCESS) { - WOLFSSL_MSG("EncryptDerKey failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + return SSL_SUCCESS; +} - /* tmp buffer with a max size */ - *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + - sizeof(END_DSA_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; - } - else /* tmp buffer with a max size */ - *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + sizeof(END_DSA_PRIV); +/* EC_POINT WolfSSL -> OpenSSL */ +static int SetECPointExternal(WOLFSSL_EC_POINT *p) +{ + ecc_point* point; - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { - WOLFSSL_MSG("malloc failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + WOLFSSL_ENTER("SetECPointExternal"); + + if (p == NULL || p->internal == NULL) { + WOLFSSL_MSG("ECPoint NULL error"); + return SSL_FATAL_ERROR; } - /* DER to PEM */ - *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, DSA_PRIVATEKEY_TYPE); - if (*plen <= 0) { - WOLFSSL_MSG("wc_DerToPemEx failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + point = (ecc_point*)p->internal; + + if (SetIndividualExternal(&p->X, point->x) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return SSL_FATAL_ERROR; } - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); - if (*pem == NULL) { - WOLFSSL_MSG("malloc failed"); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (SetIndividualExternal(&p->Y, point->y) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return SSL_FATAL_ERROR; } - XMEMSET(*pem, 0, (*plen)+1); - if (XMEMCPY(*pem, tmp, *plen) == NULL) { - WOLFSSL_MSG("XMEMCPY failed"); - XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + if (SetIndividualExternal(&p->Z, point->z) != SSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return SSL_FATAL_ERROR; } - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + p->exSet = 1; return SSL_SUCCESS; } -#ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_DSAPrivateKey(FILE *fp, WOLFSSL_DSA *dsa, - const EVP_CIPHER *enc, - unsigned char *kstr, int klen, - pem_password_cb *cb, void *u) +/* EC_KEY wolfSSL -> OpenSSL */ +static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) { - byte *pem; - int plen, ret; - - (void)cb; - (void)u; + ecc_key* key; - WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey"); + WOLFSSL_ENTER("SetECKeyExternal"); - if (fp == NULL || dsa == NULL || dsa->internal == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FAILURE; + if (eckey == NULL || eckey->internal == NULL) { + WOLFSSL_MSG("ec key NULL error"); + return SSL_FATAL_ERROR; } - ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen); - if (ret != SSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); - return SSL_FAILURE; - } + key = (ecc_key*)eckey->internal; - ret = (int)XFWRITE(pem, plen, 1, fp); - if (ret != 1) { - WOLFSSL_MSG("DSA private key file write failed"); - return SSL_FAILURE; - } + /* set group (OID, nid and idx) */ + eckey->group->curve_oid = ecc_sets[key->idx].oidSum; + eckey->group->curve_nid = ecc_sets[key->idx].id; + eckey->group->curve_idx = key->idx; - XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - return SSL_SUCCESS; -} + if (eckey->pub_key->internal != NULL) { + /* set the internal public key */ + if (wc_ecc_copy_point(&key->pubkey, + (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { + WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); + return SSL_FATAL_ERROR; + } -#endif /* NO_FILESYSTEM */ -#endif /* defined(WOLFSSL_KEY_GEN) */ + /* set the external pubkey (point) */ + if (SetECPointExternal(eckey->pub_key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); + return SSL_FATAL_ERROR; + } + } -#ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x) -{ - (void)fp; - (void)x; + /* set the external privkey */ + if (key->type == ECC_PRIVATEKEY) { + if (SetIndividualExternal(&eckey->priv_key, &key->k) != SSL_SUCCESS) { + WOLFSSL_MSG("ec priv key error"); + return SSL_FATAL_ERROR; + } + } - WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented"); + eckey->exSet = 1; - return SSL_FAILURE; + return SSL_SUCCESS; } -#endif /* NO_FILESYSTEM */ - -#endif /* #ifndef NO_DSA */ -WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** key, pem_password_cb cb, void* arg) +/* EC_KEY Openssl -> WolfSSL */ +static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) { - (void)bio; - (void)key; - (void)cb; - (void)arg; + ecc_key* key; - WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey not implemented"); + WOLFSSL_ENTER("SetECKeyInternal"); - return NULL; -} + if (eckey == NULL || eckey->internal == NULL) { + WOLFSSL_MSG("ec key NULL error"); + return SSL_FATAL_ERROR; + } + key = (ecc_key*)eckey->internal; -int wolfSSL_EVP_PKEY_type(int type) -{ - (void)type; + /* validate group */ + if ((eckey->group->curve_idx < 0) || + (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { + WOLFSSL_MSG("invalid curve idx"); + return SSL_FATAL_ERROR; + } - WOLFSSL_MSG("wolfSSL_EVP_PKEY_type not implemented"); + /* set group (idx of curve and corresponding domain parameters) */ + key->idx = eckey->group->curve_idx; + key->dp = &ecc_sets[key->idx]; - return SSL_FATAL_ERROR; -} + /* set pubkey (point) */ + if (eckey->pub_key != NULL) { + if (SetECPointInternal(eckey->pub_key) != SSL_SUCCESS) { + WOLFSSL_MSG("ec key pub error"); + return SSL_FATAL_ERROR; + } + + /* public key */ + key->type = ECC_PUBLICKEY; + } + /* set privkey */ + if (eckey->priv_key != NULL) { + if (SetIndividualInternal(eckey->priv_key, &key->k) != SSL_SUCCESS) { + WOLFSSL_MSG("ec key priv error"); + return SSL_FATAL_ERROR; + } -#if !defined(NO_FILESYSTEM) -WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, - pem_password_cb *cb, void *u) -{ - (void)fp; - (void)x; - (void)cb; - (void)u; + /* private key */ + key->type = ECC_PRIVATEKEY; + } - WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented"); + eckey->inSet = 1; - return NULL; + return SSL_SUCCESS; } -#endif /* NO_FILESYSTEM */ - -#ifndef NO_RSA -#if !defined(NO_FILESYSTEM) -WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x, - pem_password_cb *cb, void *u) +WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) { - (void)fp; - (void)x; - (void)cb; - (void)u; + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); - WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented"); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); + return NULL; + } - return NULL; + return key->pub_key; } -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_PEM_write_RSAPublicKey(FILE *fp, WOLFSSL_RSA *x) +const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) { - (void)fp; - (void)x; + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); - WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented"); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); + return NULL; + } - return SSL_FAILURE; + return key->group; } + /* return code compliant with OpenSSL : * 1 if success, 0 if error */ -int wolfSSL_PEM_write_RSA_PUBKEY(FILE *fp, WOLFSSL_RSA *x) -{ - (void)fp; - (void)x; - - WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented"); - - return SSL_FAILURE; -} -#endif /* NO_FILESYSTEM */ - -/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ -int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz) +int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_BIGNUM *priv_key) { - word32 idx = 0; - int ret; - - WOLFSSL_ENTER("wolfSSL_RSA_LoadDer"); + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); - if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + if (key == NULL || priv_key == NULL) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; } - ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); - if (ret < 0) { - WOLFSSL_MSG("RsaPrivateKeyDecode failed"); - return SSL_FATAL_ERROR; - } + /* free key if previously set */ + if (key->priv_key != NULL) + wolfSSL_BN_free(key->priv_key); - if (SetRsaExternal(rsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetRsaExternal failed"); - return SSL_FATAL_ERROR; + key->priv_key = wolfSSL_BN_dup(priv_key); + if (key->priv_key == NULL) { + WOLFSSL_MSG("key ecc priv key NULL"); + return SSL_FAILURE; } - rsa->inSet = 1; + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + wolfSSL_BN_free(key->priv_key); + return SSL_FAILURE; + } return SSL_SUCCESS; } -#endif /* NO_RSA */ -#ifndef NO_DSA -/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ -int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz) +WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) { - word32 idx = 0; - int ret; - - WOLFSSL_ENTER("wolfSSL_DSA_LoadDer"); + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); - if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); + return NULL; } - ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); - if (ret < 0) { - WOLFSSL_MSG("DsaPrivateKeyDecode failed"); - return SSL_FATAL_ERROR; - } + return key->priv_key; +} - if (SetDsaExternal(dsa) != SSL_SUCCESS) { - WOLFSSL_MSG("SetDsaExternal failed"); - return SSL_FATAL_ERROR; +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) +{ + WOLFSSL_EC_KEY *key; + int x; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); + + key = wolfSSL_EC_KEY_new(); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); + return NULL; } - dsa->inSet = 1; + /* set the nid of the curve */ + key->group->curve_nid = nid; - return SSL_SUCCESS; + /* search and set the corresponding internal curve idx */ + for (x = 0; ecc_sets[x].size != 0; x++) + if (ecc_sets[x].id == key->group->curve_nid) { + key->group->curve_idx = x; + key->group->curve_oid = ecc_sets[x].oidSum; + break; + } + + return key; } -#endif /* NO_DSA */ -#ifdef HAVE_ECC -/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ -int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, - const unsigned char* derBuf, int derSz) +static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key) { - word32 idx = 0; - int ret; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); - - if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) { - WOLFSSL_MSG("Bad function arguments"); - return SSL_FATAL_ERROR; + if (key) { + key->group = NULL; + key->pub_key = NULL; + key->priv_key = NULL; + key->internal = NULL; + key->inSet = 0; + key->exSet = 0; } +} - ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz); - if (ret < 0) { - WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); - return SSL_FATAL_ERROR; - } +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) +{ + WOLFSSL_EC_KEY *external; + ecc_key* key; - if (SetECKeyExternal(key) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECKeyExternal failed"); - return SSL_FATAL_ERROR; + WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); + + external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL, + DYNAMIC_TYPE_ECC); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); + return NULL; } + XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY)); - key->inSet = 1; + InitwolfSSL_ECKey(external); - return SSL_SUCCESS; -} -#endif /* HAVE_ECC */ + external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, + DYNAMIC_TYPE_ECC); + if (external->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + XMEMSET(external->internal, 0, sizeof(ecc_key)); -#endif /* OPENSSL_EXTRA */ + wc_ecc_init((ecc_key*)external->internal); + /* public key */ + external->pub_key = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), + NULL, DYNAMIC_TYPE_ECC); + if (external->pub_key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_POINT failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + XMEMSET(external->pub_key, 0, sizeof(WOLFSSL_EC_POINT)); -#ifdef SESSION_CERTS + key = (ecc_key*)external->internal; + external->pub_key->internal = (ecc_point*)&key->pubkey; + /* curve group */ + external->group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, + DYNAMIC_TYPE_ECC); + if (external->group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + XMEMSET(external->group, 0, sizeof(WOLFSSL_EC_GROUP)); -/* Get peer's certificate chain */ -WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_peer_chain"); - if (ssl) - return &ssl->session.chain; + /* private key */ + external->priv_key = wolfSSL_BN_new(); + if (external->priv_key == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } - return 0; + return external; } - -/* Get peer's certificate chain total count */ -int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain) +void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) { - WOLFSSL_ENTER("wolfSSL_get_chain_count"); - if (chain) - return chain->count; + WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); - return 0; -} + if (key != NULL) { + if (key->internal != NULL) { + wc_ecc_free((ecc_key*)key->internal); + XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC); + } + wolfSSL_BN_free(key->priv_key); + wolfSSL_EC_POINT_free(key->pub_key); + wolfSSL_EC_GROUP_free(key->group); + InitwolfSSL_ECKey(key); /* set back to NULLs for safety */ + XFREE(key, NULL, DYNAMIC_TYPE_ECC); + key = NULL; + } +} -/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */ -int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) +int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) { - WOLFSSL_ENTER("wolfSSL_get_chain_length"); - if (chain) - return chain->certs[idx].length; + (void)key; + (void)group; - return 0; -} + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); + WOLFSSL_MSG("wolfSSL_EC_KEY_set_group TBD"); + return -1; +} -/* Get peer's ASN.1 DER certificate at index (idx) */ -byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) +int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) { - WOLFSSL_ENTER("wolfSSL_get_chain_cert"); - if (chain) - return chain->certs[idx].buffer; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif - return 0; -} + WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); + if (key == NULL || key->internal == NULL || + key->group == NULL || key->group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); + return 0; + } -/* Get peer's wolfSSL X509 certificate at index (idx) */ -WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) -{ - int ret; - WOLFSSL_X509* x509 = NULL; #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; -#else - DecodedCert cert[1]; + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return 0; #endif - WOLFSSL_ENTER("wolfSSL_get_chain_X509"); - if (chain != NULL) { - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert != NULL) - #endif - { - InitDecodedCert(cert, chain->certs[idx].buffer, - chain->certs[idx].length, NULL); + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } - if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) - WOLFSSL_MSG("Failed to parse cert"); - else { - x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, - DYNAMIC_TYPE_X509); - if (x509 == NULL) { - WOLFSSL_MSG("Failed alloc X509"); - } - else { - InitX509(x509, 1, NULL); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; + } - if ((ret = CopyDecodedToX509(x509, cert)) != 0) { - WOLFSSL_MSG("Failed to copy decoded"); - XFREE(x509, NULL, DYNAMIC_TYPE_X509); - x509 = NULL; - } - } - } + if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal, + key->group->curve_nid) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; + } - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - } + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (SetECKeyExternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); + return 0; } - return x509; + return 1; } - -/* Get peer's PEM certificate at index (idx), output to buffer if inLen big - enough else return error (-1). If buffer is NULL only calculate - outLen. Output length is in *outLen SSL_SUCCESS on ok */ -int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, - unsigned char* buf, int inLen, int* outLen) +void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) { - const char header[] = "-----BEGIN CERTIFICATE-----\n"; - const char footer[] = "-----END CERTIFICATE-----\n"; + (void)key; + (void)asn1_flag; - int headerLen = sizeof(header) - 1; - int footerLen = sizeof(footer) - 1; - int i; - int err; - word32 szNeeded = 0; + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); + WOLFSSL_MSG("wolfSSL_EC_KEY_set_asn1_flag TBD"); +} - WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); - if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain)) - return BAD_FUNC_ARG; +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_POINT *pub) +{ + ecc_point *pub_p, *key_p; - /* Null output buffer return size needed in outLen */ - if(!buf) { - if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length, - NULL, &szNeeded) != LENGTH_ONLY_E) + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); + + if (key == NULL || key->internal == NULL || + pub == NULL || pub->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments"); + return SSL_FAILURE; + } + + if (key->inSet == 0) { + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); return SSL_FAILURE; - *outLen = szNeeded + headerLen + footerLen; - return LENGTH_ONLY_E; + } } - /* don't even try if inLen too short */ - if (inLen < headerLen + footerLen + chain->certs[idx].length) - return BAD_FUNC_ARG; + if (pub->inSet == 0) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; + } + } - /* header */ - if (XMEMCPY(buf, header, headerLen) == NULL) - return SSL_FATAL_ERROR; + pub_p = (ecc_point*)pub->internal; + key_p = (ecc_point*)key->pub_key->internal; - i = headerLen; + /* create new point if required */ + if (key_p == NULL) + key_p = wc_ecc_new_point(); - /* body */ - *outLen = inLen; /* input to Base64_Encode */ - if ( (err = Base64_Encode(chain->certs[idx].buffer, - chain->certs[idx].length, buf + i, (word32*)outLen)) < 0) - return err; - i += *outLen; + if (key_p == NULL) { + WOLFSSL_MSG("key ecc point NULL"); + return SSL_FAILURE; + } - /* footer */ - if ( (i + footerLen) > inLen) - return BAD_FUNC_ARG; - if (XMEMCPY(buf + i, footer, footerLen) == NULL) - return SSL_FATAL_ERROR; - *outLen += headerLen + footerLen; + if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { + WOLFSSL_MSG("ecc_copy_point failure"); + return SSL_FAILURE; + } + + if (SetECKeyExternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_FAILURE; + } +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) + wolfssl_EC_POINT_dump("pub", pub); + wolfssl_EC_POINT_dump("key->pub_key", key->pub_key); +#endif return SSL_SUCCESS; } +/* End EC_KEY */ - -/* get session ID */ -const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) +void wolfssl_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) { - WOLFSSL_ENTER("wolfSSL_get_sessionID"); - if (session) - return session->sessionID; - - return NULL; -} - + char *num; -#endif /* SESSION_CERTS */ + WOLFSSL_ENTER("wolfssl_EC_POINT_dump"); -#ifdef HAVE_FUZZER -void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx) -{ - if (ssl) { - ssl->fuzzerCb = cbf; - ssl->fuzzerCtx = fCtx; + if (p == NULL) { + fprintf(stderr, "%s = NULL", msg); + return ; } + + fprintf(stderr, "%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); + num = wolfSSL_BN_bn2hex(p->X); + fprintf(stderr, "\tX = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); + num = wolfSSL_BN_bn2hex(p->Y); + fprintf(stderr, "\tY = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); } #endif -#ifndef NO_CERTS -#ifdef HAVE_PK_CALLBACKS - -#ifdef HAVE_ECC +/* Start EC_GROUP */ -void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb) +/* return code compliant with OpenSSL : + * 0 if equal, 1 if not and -1 in case of error + */ +int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, + WOLFSSL_BN_CTX *ctx) { - if (ctx) - ctx->EccSignCb = cb; -} - + (void)ctx; -void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->EccSignCtx = ctx; -} + WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); + if (a == NULL || b == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); + return SSL_FATAL_ERROR; + } -void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->EccSignCtx; + /* ok */ + if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid)) + return 0; - return NULL; + /* ko */ + return 1; } - -void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb) +void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) { - if (ctx) - ctx->EccVerifyCb = cb; -} - + WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); -void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->EccVerifyCtx = ctx; + XFREE(group, NULL, DYNAMIC_TYPE_ECC); + group = NULL; } - -void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) +void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) { - if (ssl) - return ssl->EccVerifyCtx; - - return NULL; -} + (void)group; + (void)flag; -void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb) -{ - if (ctx) - ctx->EccSharedSecretCb = cb; + WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag"); + WOLFSSL_MSG("wolfSSL_EC_GROUP_set_asn1_flag TBD"); } -void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx) +WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) { - if (ssl) - ssl->EccSharedSecretCtx = ctx; -} + WOLFSSL_EC_GROUP *g; + int x; + WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); -void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->EccSharedSecretCtx; + /* curve group */ + g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, + DYNAMIC_TYPE_ECC); + if (g == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); + return NULL; + } + XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP)); - return NULL; -} -#endif /* HAVE_ECC */ + /* set the nid of the curve */ + g->curve_nid = nid; -#ifndef NO_RSA + /* search and set the corresponding internal curve idx */ + for (x = 0; ecc_sets[x].size != 0; x++) + if (ecc_sets[x].id == g->curve_nid) { + g->curve_idx = x; + g->curve_oid = ecc_sets[x].oidSum; + break; + } -void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) -{ - if (ctx) - ctx->RsaSignCb = cb; + return g; } - -void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx) +/* return code compliant with OpenSSL : + * the curve nid if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) { - if (ssl) - ssl->RsaSignCtx = ctx; -} - + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name"); -void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->RsaSignCtx; + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); + return SSL_FAILURE; + } - return NULL; + return group->curve_nid; } - -void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) +/* return code compliant with OpenSSL : + * the degree of the curve if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) { - if (ctx) - ctx->RsaVerifyCb = cb; -} + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); + if (group == NULL || group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); + return SSL_FAILURE; + } -void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->RsaVerifyCtx = ctx; + switch(group->curve_nid) { + case NID_secp112r1: + case NID_secp112r2: + return 112; + case NID_secp128r1: + case NID_secp128r2: + return 128; + case NID_secp160k1: + case NID_secp160r1: + case NID_secp160r2: + case NID_brainpoolP160r1: + return 160; + case NID_secp192k1: + case NID_brainpoolP192r1: + case NID_X9_62_prime192v1: + return 192; + case NID_secp224k1: + case NID_secp224r1: + case NID_brainpoolP224r1: + return 224; + case NID_secp256k1: + case NID_brainpoolP256r1: + case NID_X9_62_prime256v1: + return 256; + case NID_brainpoolP320r1: + return 320; + case NID_secp384r1: + case NID_brainpoolP384r1: + return 384; + case NID_secp521r1: + case NID_brainpoolP512r1: + return 521; + default: + return SSL_FAILURE; + } } - -void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, + WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) { - if (ssl) - return ssl->RsaVerifyCtx; + (void)ctx; - return NULL; -} + if (group == NULL || order == NULL || order->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); + return SSL_FAILURE; + } -void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) -{ - if (ctx) - ctx->RsaEncCb = cb; -} + if (mp_init((mp_int*)order->internal) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); + return SSL_FAILURE; + } + if (mp_read_radix((mp_int*)order->internal, + ecc_sets[group->curve_idx].order, 16) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); + mp_clear((mp_int*)order->internal); + return SSL_FAILURE; + } -void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->RsaEncCtx = ctx; + return SSL_SUCCESS; } +/* End EC_GROUP */ +/* Start EC_POINT */ -void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + unsigned char *out, unsigned int *len) { - if (ssl) - return ssl->RsaEncCtx; - - return NULL; -} + int err; -void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb) -{ - if (ctx) - ctx->RsaDecCb = cb; -} + WOLFSSL_ENTER("wolfSSL_ECPoint_i2d"); + if (group == NULL || p == NULL || len == NULL) { + WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); + return SSL_FAILURE; + } -void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->RsaDecCtx = ctx; -} + if (p->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); + return SSL_FAILURE; + } + } -void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->RsaDecCtx; +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) + if (out != NULL) { + wolfssl_EC_POINT_dump("i2d p", p); + } +#endif + err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, + out, len); + if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) { + WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); + return SSL_FAILURE; + } - return NULL; + return SSL_SUCCESS; } +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, + const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); -#endif /* NO_RSA */ - -#endif /* HAVE_PK_CALLBACKS */ -#endif /* NO_CERTS */ + if (group == NULL || p == NULL || p->internal == NULL || in == NULL) { + WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); + return SSL_FAILURE; + } + if (wc_ecc_import_point_der(in, len, group->curve_idx, + (ecc_point*)p->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_import_point_der failed"); + return SSL_FAILURE; + } -#ifdef WOLFSSL_HAVE_WOLFSCEP - /* Used by autoconf to see if wolfSCEP is available */ - void wolfSSL_wolfSCEP(void) {} -#endif + if (p->exSet == 0) { + WOLFSSL_MSG("No ECPoint external set, do it"); + if (SetECPointExternal(p) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointExternal failed"); + return SSL_FAILURE; + } + } -#ifdef WOLFSSL_HAVE_CERT_SERVICE - /* Used by autoconf to see if cert service is available */ - void wolfSSL_cert_service(void) {} +#if defined(DEBUG_WOLFSSL) && !defined(NO_FILESYSTEM) + wolfssl_EC_POINT_dump("d2i p", p); #endif + return SSL_SUCCESS; +} +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_EC_POINT *p; -#ifdef OPENSSL_EXTRA /*Lighttp compatibility*/ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) - - unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md) - { - (void) *d; (void) n; (void) *md; - WOLFSSL_ENTER("wolfSSL_SHA1"); - WOLFSSL_STUB("wolfssl_SHA1"); + WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); return NULL; } - char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) { - (void)ctx; - (void)x; - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); - WOLFSSL_STUB("wolfSSL_CTX_use_certificate"); - - return 0; + p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); + return NULL; } + XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT)); - int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) { - (void)ctx; - (void)pkey; - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); - WOLFSSL_STUB("wolfSSL_CTX_use_PrivateKey"); - - return 0; + p->internal = wc_ecc_new_point(); + if (p->internal == NULL) { + WOLFSSL_MSG("ecc_new_point failure"); + XFREE(p, NULL, DYNAMIC_TYPE_ECC); + return NULL; } + return p; +} - int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { - (void)b; - (void)name; - WOLFSSL_ENTER("wolfSSL_BIO_read_filename"); - WOLFSSL_STUB("wolfSSL_BIO_read_filename"); - - return 0; - } +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point, + WOLFSSL_BIGNUM *x, + WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; - WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) { - WOLFSSL_ENTER("wolfSSL_BIO_s_file"); - WOLFSSL_STUB("wolfSSL_BIO_s_file"); + WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); - return NULL; + if (group == NULL || point == NULL || point->internal == NULL || + x == NULL || y == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); + return SSL_FAILURE; } -#ifdef HAVE_ECC - const char * wolf_OBJ_nid2sn(int n) { - int i; - WOLFSSL_ENTER("wolf_OBJ_nid2sn"); + if (point->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); - /* find based on NID and return name */ - for (i = 0; i < ecc_sets[i].size; i++) { - if (n == ecc_sets[i].id) { - return ecc_sets[i].name; - } + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; } - return NULL; } - int wolf_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) { - (void)o; - WOLFSSL_ENTER("wolf_OBJ_obj2nid"); - WOLFSSL_STUB("wolf_OBJ_obj2nid"); - - return 0; - } + BN_copy(x, point->X); + BN_copy(y, point->Y); - int wolf_OBJ_sn2nid(const char *sn) { - int i; - WOLFSSL_ENTER("wolf_OBJ_osn2nid"); + return SSL_SUCCESS; +} - /* find based on name and return NID */ - for (i = 0; i < ecc_sets[i].size; i++) { - if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { - return ecc_sets[i].id; - } - } - return -1; - } -#endif /* HAVE_ECC */ +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, + const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, + const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + mp_int a, prime; + int ret; + (void)ctx; + (void)n; - WOLFSSL_X509 *PEM_read_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { - (void)bp; - (void)x; - (void)cb; - (void)u; - WOLFSSL_ENTER("PEM_read_bio_WOLFSSL_X509"); - WOLFSSL_STUB("PEM_read_bio_WOLFSSL_X509"); + WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); - return NULL; + if (group == NULL || r == NULL || r->internal == NULL || + q == NULL || q->internal == NULL || m == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); + return SSL_FAILURE; } - void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { - (void)ctx; - (void)depth; - WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); - WOLFSSL_STUB("wolfSSL_CTX_set_verify_depth"); + if (q->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal q failed"); + return SSL_FAILURE; + } } - void* wolfSSL_get_app_data( const WOLFSSL *ssl) - { - /* checkout exdata stuff... */ - (void)ssl; - WOLFSSL_ENTER("wolfSSL_get_app_data"); - WOLFSSL_STUB("wolfSSL_get_app_data"); - - return 0; + /* read the curve prime and a */ + if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { + return SSL_FAILURE; } - void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { - (void)ssl; - (void)arg; - WOLFSSL_ENTER("wolfSSL_set_app_data"); - WOLFSSL_STUB("wolfSSL_set_app_data"); - } + ret = mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16); + if (ret == MP_OKAY) + ret = mp_read_radix(&a, ecc_sets[group->curve_idx].Af, 16); - WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) { - (void)ne; - WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object"); - WOLFSSL_STUB("wolfSSL_X509_NAME_ENTRY_get_object"); + /* r = q * m % prime */ + if (ret == MP_OKAY) + ret = wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + (ecc_point*)r->internal, &a, &prime, 1); - return NULL; - } + mp_clear(&a); + mp_clear(&prime); - WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry( - WOLFSSL_X509_NAME *name, int loc) { + if (ret == MP_OKAY) { + /* set the external value for the computed point */ + ret = SetECPointInternal(r); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal r failed"); + } + } + else { + ret = SSL_FAILURE; + } - int maxLoc = name->fullName.fullNameLen; + return ret; +} - WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry"); +void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); - if (loc < 0 || loc > maxLoc) { - WOLFSSL_MSG("Bad argument"); - return NULL; - } + wolfSSL_EC_POINT_free(p); +} - /* common name index case */ - if (loc == name->fullName.cnIdx) { - /* get CN shortcut from x509 since it has null terminator */ - name->cnEntry.data.data = name->x509->subjectCN; - name->cnEntry.data.length = name->fullName.cnLen; - name->cnEntry.data.type = ASN_COMMON_NAME; - name->cnEntry.set = 1; - return &(name->cnEntry); - } +/* return code compliant with OpenSSL : + * 0 if equal, 1 if not and -1 in case of error + */ +int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, + WOLFSSL_BN_CTX *ctx) +{ + int ret; - /* additionall cases to check for go here */ + (void)ctx; - WOLFSSL_MSG("Entry not found or implemented"); - (void)name; - (void)loc; + WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); - return NULL; + if (group == NULL || a == NULL || a->internal == NULL || b == NULL || + b->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); + return SSL_FATAL_ERROR; } -#ifndef NO_CERTS - void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ - FreeX509Name(name, NULL); - WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); - WOLFSSL_STUB("wolfSSL_X509_NAME_free"); - } -#endif /* NO_CERTS */ + ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal); + if (ret == MP_EQ) + return 0; + else if (ret == MP_LT || ret == MP_GT) + return 1; - void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ - (void) sk; - (void) f; - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_pop_free"); - } + return SSL_FATAL_ERROR; +} - int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key){ - (void) x509; - (void) key; - WOLFSSL_ENTER("wolfSSL_X509_check_private_key"); - WOLFSSL_STUB("wolfSSL_X509_check_private_key"); +void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); - return SSL_SUCCESS; - } + if (p != NULL) { + if (p->internal == NULL) { + wc_ecc_del_point((ecc_point*)p->internal); + XFREE(p->internal, NULL, DYNAMIC_TYPE_ECC); + p->internal = NULL; + } - STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ){ - (void) sk; - WOLFSSL_ENTER("wolfSSL_dup_CA_list"); - WOLFSSL_STUB("wolfSSL_dup_CA_list"); + wolfSSL_BN_free(p->X); + wolfSSL_BN_free(p->Y); + wolfSSL_BN_free(p->Z); + p->X = NULL; + p->Y = NULL; + p->Z = NULL; + p->inSet = p->exSet = 0; - return NULL; + XFREE(p, NULL, DYNAMIC_TYPE_ECC); + p = NULL; } +} -#endif /* HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL */ -#endif +/* return code compliant with OpenSSL : + * 1 if point at infinity, 0 else + */ +int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point) +{ + int ret; + WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); -#ifdef OPENSSL_EXTRA -void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); - #ifdef HAVE_STUNNEL - if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) { - return ctx->ex_data[idx]; + if (group == NULL || point == NULL || point->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); + return SSL_FAILURE; } - #else - (void)ctx; - (void)idx; - #endif - return NULL; -} + if (point->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return SSL_FAILURE; + } + } -int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, - void* c) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); - (void)idx; - (void)arg; - (void)a; - (void)b; - (void)c; - return 0; + ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); + if (ret <= 0) { + WOLFSSL_MSG("ecc_point_is_at_infinity failure"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; } +/* End EC_POINT */ -int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) +/* Start ECDSA_SIG */ +void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) { - WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); - #ifdef HAVE_STUNNEL - if (ctx != NULL && idx < MAX_EX_DATA) - { - ctx->ex_data[idx] = data; - return SSL_SUCCESS; - } - #else - (void)ctx; - (void)idx; - (void)data; - #endif - return SSL_FAILURE; -} + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); + if (sig) { + wolfSSL_BN_free(sig->r); + wolfSSL_BN_free(sig->s); -int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) -{ - WOLFSSL_ENTER("wolfSSL_set_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) - if (ssl != NULL && idx < MAX_EX_DATA) - { - ssl->ex_data[idx] = data; - return SSL_SUCCESS; + XFREE(sig, NULL, DYNAMIC_TYPE_ECC); } -#else - (void)ssl; - (void)idx; - (void)data; -#endif - return SSL_FAILURE; } - -int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, - void* cb3) +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) { - WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); - (void)idx; - (void)data; - (void)cb1; - (void)cb2; - (void)cb3; - return 0; -} + WOLFSSL_ECDSA_SIG *sig; + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); -void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) + sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, + DYNAMIC_TYPE_ECC); + if (sig == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); + return NULL; + } + + sig->s = NULL; + sig->r = wolfSSL_BN_new(); + if (sig->r == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); + wolfSSL_ECDSA_SIG_free(sig); + return NULL; + } + + sig->s = wolfSSL_BN_new(); + if (sig->s == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); + wolfSSL_ECDSA_SIG_free(sig); + return NULL; + } + + return sig; +} + +/* return signature structure on success, NULL otherwise */ +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, + WOLFSSL_EC_KEY *key) { - WOLFSSL_ENTER("wolfSSL_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) - if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) - return ssl->ex_data[idx]; + WOLFSSL_ECDSA_SIG *sig = NULL; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; #else - (void)ssl; - (void)idx; + WC_RNG tmpRNG[1]; #endif - return 0; -} -#endif /* OPENSSL_EXTRA */ + WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); -#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) -char * wolf_OBJ_nid2ln(int n) { - (void)n; - WOLFSSL_ENTER("wolf_OBJ_nid2ln"); - WOLFSSL_STUB("wolf_OBJ_nid2ln"); + if (d == NULL || key == NULL || key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); + return NULL; + } - return NULL; -} + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); -int wolf_OBJ_txt2nid(const char* s) { - (void)s; - WOLFSSL_ENTER("wolf_OBJ_txt2nid"); - WOLFSSL_STUB("wolf_OBJ_txt2nid"); + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); + return NULL; + } + } - return 0; -} +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return NULL; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init"); + else + rng = &globalRNG; + } -WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) { - (void)filename; - (void)mode; - WOLFSSL_ENTER("wolfSSL_BIO_new_file"); - WOLFSSL_STUB("wolfSSL_BIO_new_file"); + if (rng) { + mp_int sig_r, sig_s; - return NULL; -} + if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) { + if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal, + &sig_r, &sig_s) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_sign_hash_ex failed"); + } + else { + /* put signature blob in ECDSA structure */ + sig = wolfSSL_ECDSA_SIG_new(); + if (sig == NULL) + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed"); + else if (SetIndividualExternal(&(sig->r), &sig_r)!=SSL_SUCCESS){ + WOLFSSL_MSG("ecdsa r key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + else if (SetIndividualExternal(&(sig->s), &sig_s)!=SSL_SUCCESS){ + WOLFSSL_MSG("ecdsa s key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + + } + mp_free(&sig_r); + mp_free(&sig_s); + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return sig; +} -WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, pem_password_cb *cb, void *u) +/* return code compliant with OpenSSL : + * 1 for a valid signature, 0 for an invalid signature and -1 on error + */ +int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, + const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) { - (void) bp; - (void) x; - (void) cb; - (void) u; + int check_sign = 0; - WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); - WOLFSSL_STUB("wolfSSL_PEM_read_bio_DHparams"); + WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); - return NULL; -} + if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); + return SSL_FATAL_ERROR; + } -int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) { - (void)bp; - (void)x; - WOLFSSL_ENTER("PEM_write_bio_WOLFSSL_X509"); - WOLFSSL_STUB("PEM_write_bio_WOLFSSL_X509"); + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); - return 0; -} + if (SetECKeyInternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_FATAL_ERROR; + } + } + if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, + (mp_int*)sig->s->internal, d, dlen, &check_sign, + (ecc_key *)key->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_verify_hash failed"); + return SSL_FATAL_ERROR; + } + else if (check_sign == 0) { + WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + return SSL_FAILURE; + } -#ifndef NO_DH -/* Intialize ctx->dh with dh's params. Return SSL_SUCCESS on ok */ -long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) -{ - int pSz, gSz; - byte *p, *g; - int ret=0; + return SSL_SUCCESS; +} +/* End ECDSA_SIG */ - WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh"); +/* Start ECDH */ +/* return code compliant with OpenSSL : + * length of computed key if success, -1 if error + */ +int wolfSSL_ECDH_compute_key(void *out, size_t outlen, + const WOLFSSL_EC_POINT *pub_key, + WOLFSSL_EC_KEY *ecdh, + void *(*KDF) (const void *in, size_t inlen, + void *out, size_t *outlen)) +{ + word32 len; + (void)KDF; - if(!ctx || !dh) - return BAD_FUNC_ARG; + (void)KDF; - /* Get needed size for p and g */ - pSz = wolfSSL_BN_bn2bin(dh->p, NULL); - gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); - if(pSz <= 0 || gSz <= 0) + if (out == NULL || pub_key == NULL || pub_key->internal == NULL || + ecdh == NULL || ecdh->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); return SSL_FATAL_ERROR; + } - p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); - if(!p) - return MEMORY_E; + /* set internal key if not done */ + if (ecdh->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); - g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); - if(!g) { - XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); - return MEMORY_E; + if (SetECKeyInternal(ecdh) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return SSL_FATAL_ERROR; + } } - pSz = wolfSSL_BN_bn2bin(dh->p, p); - gSz = wolfSSL_BN_bn2bin(dh->g, g); - - if(pSz >= 0 && gSz >= 0) /* Conversion successful */ - ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); + len = (word32)outlen; - XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(g, ctx->heap, DYNAMIC_TYPE_DH); + if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal, + (ecc_point*)pub_key->internal, + (byte *)out, &len) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + return SSL_FATAL_ERROR; + } - return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; + return len; } -#endif /* NO_DH */ -#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ - +/* End ECDH */ -/* stunnel compatibility functions*/ -#if defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL) -void WOLFSSL_ERR_remove_thread_state(void* pid) +#if !defined(NO_FILESYSTEM) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x) { - (void) pid; - return; -} + (void)fp; + (void)x; + WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented"); -int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); - if(session != NULL && idx < MAX_EX_DATA) { - session->ex_data[idx] = data; - return SSL_SUCCESS; - } return SSL_FAILURE; } +#endif /* NO_FILESYSTEM */ +#if defined(WOLFSSL_KEY_GEN) -int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, - void* cb2, CRYPTO_free_func* cb3) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) { - WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index"); - (void)idx; - (void)cb1; - (void)cb2; - (void)cb3; - if(XSTRNCMP((const char*)data, "redirect index", 14) == 0) { - return 0; - } - else if(XSTRNCMP((const char*)data, "addr index", 10) == 0) { - return 1; - } + (void)bio; + (void)ecc; + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented"); + return SSL_FAILURE; } - -void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, + const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) { - WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); - if (session != NULL && idx < MAX_EX_DATA && idx >= 0) - return session->ex_data[idx]; - return NULL; -} + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); -int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), - void *(*r) (void *, size_t, const char *, - int), void (*f) (void *)) -{ - (void) m; - (void) r; - (void) f; - WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); - WOLFSSL_STUB("wolfSSL_CRYPTO_set_mem_ex_functions"); + if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } - return SSL_FAILURE; -} + if (ecc->inSet == 0) { + WOLFSSL_MSG("No ECC internal set, do it"); + if (SetECKeyInternal(ecc) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return SSL_FAILURE; + } + } -WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, - void (*callback) (int, int, void *), void *cb_arg) -{ - (void)prime_len; - (void)generator; - (void)callback; - (void)cb_arg; - WOLFSSL_ENTER("wolfSSL_DH_generate_parameters"); - WOLFSSL_STUB("wolfSSL_DH_generate_parameters"); + /* 4 > size of pub, priv + ASN.1 additional informations + */ + der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE; - return NULL; + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + + sizeof(END_EC_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; + } + else /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_EC_PRIV) + sizeof(END_EC_PRIV); + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, ECC_PRIVATEKEY_TYPE); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XMEMSET(*pem, 0, (*plen)+1); + + if (XMEMCPY(*pem, tmp, *plen) == NULL) { + WOLFSSL_MSG("XMEMCPY failed"); + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return SSL_SUCCESS; } -int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator, - void (*callback) (int, int, void *)) +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) { - (void)prime_len; - (void)generator; - (void)callback; - (void)dh; - WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex"); - WOLFSSL_STUB("wolfSSL_DH_generate_parameters_ex"); + byte *pem; + int plen, ret; - return -1; + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey"); + + if (fp == NULL || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); + return SSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("ECC private key file write failed"); + return SSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return SSL_SUCCESS; } +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ -void wolfSSL_ERR_load_crypto_strings(void) +#endif /* HAVE_ECC */ + + +#ifndef NO_DSA + +#if defined(WOLFSSL_KEY_GEN) + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) { - WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); - WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); - return; + (void)bio; + (void)dsa; + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey not implemented"); + + return SSL_FAILURE; } +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey"); + + if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return SSL_FAILURE; + } + } + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional informations + */ + der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + + sizeof(END_DSA_PRIV) + HEADER_ENCRYPTED_KEY_SIZE; + } + else /* tmp buffer with a max size */ + *plen = (derSz * 2) + sizeof(BEGIN_DSA_PRIV) + sizeof(END_DSA_PRIV); + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, DSA_PRIVATEKEY_TYPE); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XMEMSET(*pem, 0, (*plen)+1); + + if (XMEMCPY(*pem, tmp, *plen) == NULL) { + WOLFSSL_MSG("XMEMCPY failed"); + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return SSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return SSL_SUCCESS; +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_DSAPrivateKey(FILE *fp, WOLFSSL_DSA *dsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + byte *pem; + int plen, ret; + + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey"); + + if (fp == NULL || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); + return SSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("DSA private key file write failed"); + return SSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return SSL_SUCCESS; +} + +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented"); + + return SSL_FAILURE; +} +#endif /* NO_FILESYSTEM */ + +#endif /* #ifndef NO_DSA */ + +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** key, pem_password_cb* cb, void* arg) +{ + (void)bio; + (void)key; + (void)cb; + (void)arg; + + WOLFSSL_MSG("wolfSSL_PEM_read_bio_PrivateKey not implemented"); + + return NULL; +} + + +int wolfSSL_EVP_PKEY_type(int type) +{ + (void) type; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type always returns EVP_PKEY_RSA"); + return EVP_PKEY_RSA; +} + +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + return EVP_PKEY_type(pkey->type); +} + + +#if !defined(NO_FILESYSTEM) +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, + pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented"); + + return NULL; +} +#endif /* NO_FILESYSTEM */ + +#ifndef NO_RSA + +#if !defined(NO_FILESYSTEM) +WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(FILE *fp, WOLFSSL_RSA **x, + pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented"); + + return NULL; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_RSAPublicKey(FILE *fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented"); + + return SSL_FAILURE; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_RSA_PUBKEY(FILE *fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + + WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented"); + + return SSL_FAILURE; +} +#endif /* NO_FILESYSTEM */ + +/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz) +{ + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_RSA_LoadDer"); + + if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FATAL_ERROR; + } + + ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("RsaPrivateKeyDecode failed"); + return SSL_FATAL_ERROR; + } + + if (SetRsaExternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaExternal failed"); + return SSL_FATAL_ERROR; + } + + rsa->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* NO_RSA */ + + +#ifndef NO_DSA +/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz) +{ + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_DSA_LoadDer"); + + if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FATAL_ERROR; + } + + ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("DsaPrivateKeyDecode failed"); + return SSL_FATAL_ERROR; + } + + if (SetDsaExternal(dsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetDsaExternal failed"); + return SSL_FATAL_ERROR; + } + + dsa->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* NO_DSA */ + +#ifdef HAVE_ECC +/* return SSL_SUCCESS if success, SSL_FATAL_ERROR if error */ +int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, + const unsigned char* derBuf, int derSz) +{ + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); + + if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return SSL_FATAL_ERROR; + } + + ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + return SSL_FATAL_ERROR; + } + + if (SetECKeyExternal(key) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + return SSL_FATAL_ERROR; + } + + key->inSet = 1; + + return SSL_SUCCESS; +} +#endif /* HAVE_ECC */ + +#endif /* OPENSSL_EXTRA */ + + +#ifdef SESSION_CERTS + + +/* Get peer's certificate chain */ +WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_peer_chain"); + if (ssl) + return &ssl->session.chain; + + return 0; +} + + +/* Get peer's certificate chain total count */ +int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain) +{ + WOLFSSL_ENTER("wolfSSL_get_chain_count"); + if (chain) + return chain->count; + + return 0; +} + + +/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */ +int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_chain_length"); + if (chain) + return chain->certs[idx].length; + + return 0; +} + + +/* Get peer's ASN.1 DER certificate at index (idx) */ +byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_chain_cert"); + if (chain) + return chain->certs[idx].buffer; + + return 0; +} + + +/* Get peer's wolfSSL X509 certificate at index (idx) */ +WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) +{ + int ret; + WOLFSSL_X509* x509 = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_get_chain_X509"); + if (chain != NULL) { + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert != NULL) + #endif + { + InitDecodedCert(cert, chain->certs[idx].buffer, + chain->certs[idx].length, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) { + WOLFSSL_MSG("Failed to parse cert"); + } + else { + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (x509 == NULL) { + WOLFSSL_MSG("Failed alloc X509"); + } + else { + InitX509(x509, 1, NULL); + + if ((ret = CopyDecodedToX509(x509, cert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded"); + XFREE(x509, NULL, DYNAMIC_TYPE_X509); + x509 = NULL; + } + } + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + (void)ret; + + return x509; +} + + +/* Get peer's PEM certificate at index (idx), output to buffer if inLen big + enough else return error (-1). If buffer is NULL only calculate + outLen. Output length is in *outLen SSL_SUCCESS on ok */ +int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, + unsigned char* buf, int inLen, int* outLen) +{ + const char header[] = "-----BEGIN CERTIFICATE-----\n"; + const char footer[] = "-----END CERTIFICATE-----\n"; + + int headerLen = sizeof(header) - 1; + int footerLen = sizeof(footer) - 1; + int i; + int err; + word32 szNeeded = 0; + + WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); + if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain)) + return BAD_FUNC_ARG; + + /* Null output buffer return size needed in outLen */ + if(!buf) { + if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length, + NULL, &szNeeded) != LENGTH_ONLY_E) + return SSL_FAILURE; + *outLen = szNeeded + headerLen + footerLen; + return LENGTH_ONLY_E; + } + + /* don't even try if inLen too short */ + if (inLen < headerLen + footerLen + chain->certs[idx].length) + return BAD_FUNC_ARG; + + /* header */ + if (XMEMCPY(buf, header, headerLen) == NULL) + return SSL_FATAL_ERROR; + + i = headerLen; + + /* body */ + *outLen = inLen; /* input to Base64_Encode */ + if ( (err = Base64_Encode(chain->certs[idx].buffer, + chain->certs[idx].length, buf + i, (word32*)outLen)) < 0) + return err; + i += *outLen; + + /* footer */ + if ( (i + footerLen) > inLen) + return BAD_FUNC_ARG; + if (XMEMCPY(buf + i, footer, footerLen) == NULL) + return SSL_FATAL_ERROR; + *outLen += headerLen + footerLen; + + return SSL_SUCCESS; +} + + +/* get session ID */ +const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("wolfSSL_get_sessionID"); + if (session) + return session->sessionID; + + return NULL; +} + + +#endif /* SESSION_CERTS */ + +#ifdef HAVE_FUZZER +void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx) +{ + if (ssl) { + ssl->fuzzerCb = cbf; + ssl->fuzzerCtx = fCtx; + } +} +#endif + +#ifndef NO_CERTS +#ifdef HAVE_PK_CALLBACKS + +#ifdef HAVE_ECC + +void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb) +{ + if (ctx) + ctx->EccSignCb = cb; +} + + +void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccSignCtx = ctx; +} + + +void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccSignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb) +{ + if (ctx) + ctx->EccVerifyCb = cb; +} + + +void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccVerifyCtx = ctx; +} + + +void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccVerifyCtx; + + return NULL; +} + +void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb) +{ + if (ctx) + ctx->EccSharedSecretCb = cb; +} + +void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccSharedSecretCtx = ctx; +} + + +void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccSharedSecretCtx; + + return NULL; +} +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + +void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) +{ + if (ctx) + ctx->RsaSignCb = cb; +} + + +void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaSignCtx = ctx; +} + + +void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaSignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) +{ + if (ctx) + ctx->RsaVerifyCb = cb; +} + + +void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaVerifyCtx = ctx; +} + + +void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaVerifyCtx; + + return NULL; +} + +void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) +{ + if (ctx) + ctx->RsaEncCb = cb; +} + + +void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaEncCtx = ctx; +} + + +void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaEncCtx; + + return NULL; +} + +void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb) +{ + if (ctx) + ctx->RsaDecCb = cb; +} + + +void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaDecCtx = ctx; +} + + +void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaDecCtx; + + return NULL; +} + + +#endif /* NO_RSA */ + +#endif /* HAVE_PK_CALLBACKS */ +#endif /* NO_CERTS */ + + +#ifdef WOLFSSL_HAVE_WOLFSCEP + /* Used by autoconf to see if wolfSCEP is available */ + void wolfSSL_wolfSCEP(void) {} +#endif + + +#ifdef WOLFSSL_HAVE_CERT_SERVICE + /* Used by autoconf to see if cert service is available */ + void wolfSSL_cert_service(void) {} +#endif + + +#ifdef OPENSSL_EXTRA /*Lighttp compatibility*/ + + #ifndef NO_CERTS + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u) + { +#ifndef NO_FILESYSTEM + WOLFSSL_X509* x509 = NULL; + unsigned char* pem = NULL; + int pemSz; + int pemAlloced = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + if (bp == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG); + return NULL; + } + + if (bp->type == BIO_MEMORY) { + pemSz = wolfSSL_BIO_get_mem_data(bp, &pem); + if (pemSz <= 0 || pem == NULL) { + WOLFSSL_MSG("Issue getting WOLFSSL_BIO mem"); + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", pemSz); + return NULL; + } + } + else if (bp->type == BIO_FILE) { + long i; + long l; + + /* Read in next certificate from file but no more. */ + i = XFTELL(bp->file); + if (i < 0) + return NULL; + XFSEEK(bp->file, 0, SEEK_END); + l = XFTELL(bp->file); + if (l < 0) + return NULL; + XFSEEK(bp->file, i, SEEK_SET); + + /* check calulated length */ + if (l - i <= 0) + return NULL; + + pem = (unsigned char*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) + return NULL; + pemAlloced = 1; + + i = 0; + /* TODO: Inefficient + * reading in one byte at a time until see END_CERT + */ + while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) { + i++; + if (i > 26 && XMEMCMP((char *)&pem[i-26], END_CERT, 25) == 0) + break; + } + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (l == 0) + WOLFSSL_ERROR(SSL_NO_PEM_HEADER); + #endif + pemSz = (int)i; + } + else + return NULL; + + x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz, + SSL_FILETYPE_PEM); + + if (x != NULL) { + *x = x509; + } + + if (pemAlloced) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + (void)cb; + (void)u; + + return x509; +#else + (void)bp; + (void)x; + (void)cb; + (void)u; + return NULL; +#endif + } + + + /* + * bp : bio to read X509 from + * x : x509 to write to + * cb : password call back for reading PEM + * u : password + * _AUX is for working with a trusted X509 certificate + */ + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp, + WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + /* AUX info is; trusted/rejected uses, friendly name, private key id, + * and potentially a stack of "other" info. wolfSSL does not store + * friendly name or private key id yet in WOLFSSL_X509 for human + * readibility and does not support extra trusted/rejected uses for + * root CA. */ + return wolfSSL_PEM_read_bio_X509(bp, x, cb, u); + } + #endif /* ifndef NO_CERTS */ + + #ifndef NO_CERTS + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ + FreeX509Name(name, NULL); + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + } + #endif /* NO_CERTS */ + +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_POCO_LIB) || defined (WOLFSSL_HAPROXY) + + unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md) + { + (void) *d; (void) n; (void) *md; + WOLFSSL_ENTER("wolfSSL_SHA1"); + WOLFSSL_STUB("wolfssl_SHA1"); + + return NULL; + } + + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) + { + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); + + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE, + ctx->heap); + if (ret != 0) + return 0; + + XMEMCPY(ctx->certificate->buffer, x->derCert->buffer, + x->derCert->length); +#ifdef KEEP_OUR_CERT + if (ctx->ourCert != NULL && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + ctx->ourCert = x; + ctx->ownOurCert = 0; +#endif + + /* Update the available options with public keys. */ + switch (x->pubKeyOID) { + case RSAk: + ctx->haveRSA = 1; + break; + case ECDSAk: + ctx->haveECC = 1; + ctx->pkCurveOID = x->pkCurveOID; + break; + } + + return SSL_SUCCESS; + } + + int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { + #ifndef NO_FILESYSTEM + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + if ((wolfSSL_BIO_get_fp(b, &fp) == SSL_SUCCESS) && (fp != NULL)) + { + XFCLOSE(fp); + } + + fp = XFOPEN(name, "r"); + if (fp == NULL) + return SSL_BAD_FILE; + + if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != SSL_SUCCESS) { + XFCLOSE(fp); + return SSL_BAD_FILE; + } + + /* file is closed when bio is free'd */ + return SSL_SUCCESS; + #else + (void)name; + (void)b; + return SSL_NOT_IMPLEMENTED; + #endif + } + +#ifdef HAVE_ECC + const char * wolfSSL_OBJ_nid2sn(int n) { + int i; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn"); + + /* find based on NID and return name */ + for (i = 0; i < ecc_sets[i].size; i++) { + if (n == ecc_sets[i].id) { + return ecc_sets[i].name; + } + } + return NULL; + } + + int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) { + (void)o; + WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); + WOLFSSL_STUB("wolfSSL_OBJ_obj2nid"); + + return 0; + } + + int wolfSSL_OBJ_sn2nid(const char *sn) { + int i; + WOLFSSL_ENTER("wolfSSL_OBJ_osn2nid"); + + /* Nginx uses this OpenSSL string. */ + if (XSTRNCMP(sn, "prime256v1", 10) == 0) + sn = "SECP256R1"; + if (XSTRNCMP(sn, "secp384r1", 10) == 0) + sn = "SECP384R1"; + /* find based on name and return NID */ + for (i = 0; i < ecc_sets[i].size; i++) { + if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { + return ecc_sets[i].id; + } + } + return -1; + } +#endif /* HAVE_ECC */ + + + void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { + (void)ctx; + (void)depth; + WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); + WOLFSSL_STUB("wolfSSL_CTX_set_verify_depth"); + + } + + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) { + (void)ssl; + (void)depth; + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); + WOLFSSL_STUB("wolfSSL_set_verify_depth"); + + } + + void* wolfSSL_get_app_data( const WOLFSSL *ssl) { + /* checkout exdata stuff... */ + return wolfSSL_get_ex_data(ssl,0); + } + + int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { + return wolfSSL_set_ex_data(ssl,0,(char *)arg); + } + + WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) { + (void)ne; + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object"); + WOLFSSL_STUB("wolfSSL_X509_NAME_ENTRY_get_object"); + + return NULL; + } + + WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry( + WOLFSSL_X509_NAME *name, int loc) { + + int maxLoc = name->fullName.fullNameLen; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry"); + + if (loc < 0 || loc > maxLoc) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + /* common name index case */ + if (loc == name->fullName.cnIdx) { + /* get CN shortcut from x509 since it has null terminator */ + name->cnEntry.data.data = name->x509->subjectCN; + name->cnEntry.data.length = name->fullName.cnLen; + name->cnEntry.data.type = ASN_COMMON_NAME; + name->cnEntry.set = 1; + return &(name->cnEntry); + } + + /* additionall cases to check for go here */ + + WOLFSSL_MSG("Entry not found or implemented"); + (void)name; + (void)loc; + + return NULL; + } + + void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ + (void) sk; + (void) f; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); + WOLFSSL_STUB("wolfSSL_sk_X509_NAME_pop_free"); + } + + int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key){ + (void) x509; + (void) key; + WOLFSSL_ENTER("wolfSSL_X509_check_private_key"); + WOLFSSL_STUB("wolfSSL_X509_check_private_key"); + + return SSL_SUCCESS; + } + + STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ){ + (void) sk; + WOLFSSL_ENTER("wolfSSL_dup_CA_list"); + WOLFSSL_STUB("wolfSSL_dup_CA_list"); + + return NULL; + } + +#endif /* HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_EXTRA */ + + +#ifdef OPENSSL_EXTRA + +/* wolfSSL uses negative values for error states. This function returns an + * unsigned type so the value returned is the absolute value of the error. + */ +unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + + (void)line; + (void)file; +#if defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || defined(WOLFSSL_HAPROXY) + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + #ifdef WOLFSSL_NGINX + if (ret == -SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #endif + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} + + +#ifndef NO_CERTS +int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); + + if (ctx == NULL || pkey == NULL) { + return SSL_FAILURE; + } + + return wolfSSL_CTX_use_PrivateKey_buffer(ctx, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, PRIVATEKEY_TYPE); +} +#endif /* !NO_CERTS */ + + +void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); + #ifdef HAVE_EX_DATA + if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) { + return ctx->ex_data[idx]; + } + #else + (void)ctx; + (void)idx; + #endif + return NULL; +} + +int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, + void* c) +{ + static int ctx_idx = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + + return ctx_idx++; +} + + +int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); + #ifdef HAVE_EX_DATA + if (ctx != NULL && idx < MAX_EX_DATA) + { + ctx->ex_data[idx] = data; + return SSL_SUCCESS; + } + #else + (void)ctx; + (void)idx; + (void)data; + #endif + return SSL_FAILURE; +} + + +int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_set_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ssl != NULL && idx < MAX_EX_DATA) + { + ssl->ex_data[idx] = data; + return SSL_SUCCESS; + } +#else + (void)ssl; + (void)idx; + (void)data; +#endif + return SSL_FAILURE; +} + + +int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, + void* cb3) +{ + static int ssl_idx = 0; + + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); + (void)idx; + (void)data; + (void)cb1; + (void)cb2; + (void)cb3; + + return ssl_idx++; +} + + +void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) + return ssl->ex_data[idx]; +#else + (void)ssl; + (void)idx; +#endif + return 0; +} + +#ifndef NO_DSA +WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, + pem_password_cb *cb, void *u) +{ + WOLFSSL_DSA* dsa; + DsaKey* key; + int length; + unsigned char* buf; + word32 bufSz; + int ret; + word32 idx = 0; + DerBuffer* pDer; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams"); + + ret = wolfSSL_BIO_get_mem_data(bp, &buf); + if (ret <= 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + return NULL; + } + + bufSz = (word32)ret; + + if (cb != NULL || u != NULL) { + /* + * cb is for a call back when encountering encrypted PEM files + * if cb == NULL and u != NULL then u = null terminated password string + */ + WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM"); + } + + if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL, + NULL)) < 0 ) { + WOLFSSL_MSG("Issue converting from PEM to DER"); + return NULL; + } + + if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + FreeDer(&pDer); + return NULL; + } + + dsa = wolfSSL_DSA_new(); + if (dsa == NULL) { + FreeDer(&pDer); + WOLFSSL_MSG("Error creating DSA struct"); + return NULL; + } + + key = (DsaKey*)dsa->internal; + if (key == NULL) { + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + WOLFSSL_MSG("Error finding DSA key struct"); + return NULL; + } + + if (GetInt(&key->p, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->q, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->g, pDer->buffer, &idx, pDer->length) < 0 ) { + WOLFSSL_MSG("dsa key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (x != NULL) { + *x = dsa; + } + + FreeDer(&pDer); + return dsa; +} +#endif /* NO_DSA */ + +#include "src/bio.c" + +#endif /* OPENSSL_EXTRA */ + + +#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_HAPROXY) +char * wolfSSL_OBJ_nid2ln(int n) { + (void)n; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); + WOLFSSL_STUB("wolfSSL_OBJ_nid2ln"); + + return NULL; +} + +int wolfSSL_OBJ_txt2nid(const char* s) { + (void)s; + WOLFSSL_ENTER("wolfSSL_OBJ_txt2nid"); + WOLFSSL_STUB("wolfSSL_OBJ_txt2nid"); + + return 0; +} + + +WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_BIO* bio; + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + fp = XFOPEN(filename, mode); + if (fp == NULL) + return NULL; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) { + XFCLOSE(fp); + return bio; + } + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != SSL_SUCCESS) { + XFCLOSE(fp); + wolfSSL_BIO_free(bio); + bio = NULL; + } + + /* file is closed when BIO is free'd */ + return bio; +#else + (void)filename; + (void)mode; + return NULL; +#endif +} + + +#ifndef NO_DH +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x, + pem_password_cb *cb, void *u) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_DH* localDh = NULL; + unsigned char* mem = NULL; + word32 size; + long sz; + int ret; + DerBuffer *der = NULL; + byte* p = NULL; + byte* g = NULL; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + int memAlloced = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); + (void)cb; + (void)u; + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + if (bio->type == BIO_MEMORY) { + /* Use the buffer directly. */ + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + goto end; + } + size = ret; + } + else if (bio->type == BIO_FILE) { + /* Read whole file into a new buffer. */ + XFSEEK(bio->file, 0, SEEK_END); + sz = XFTELL(bio->file); + XFSEEK(bio->file, 0, SEEK_SET); + if (sz <= 0L) + goto end; + mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) + goto end; + memAlloced = 1; + + if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0) + goto end; + size = (word32)sz; + } + else { + WOLFSSL_MSG("BIO type not supported for reading DH parameters"); + goto end; + } + + ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL); + if (ret != 0) + goto end; + + /* Use the object passed in, otherwise allocate a new object */ + if (x != NULL) + localDh = *x; + if (localDh == NULL) { + localDh = (WOLFSSL_DH*)XMALLOC(sizeof(WOLFSSL_DH), NULL, + DYNAMIC_TYPE_OPENSSL); + if (localDh == NULL) + goto end; + XMEMSET(localDh, 0, sizeof(WOLFSSL_DH)); + } + + /* Load data in manually */ + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL || g == NULL) + goto end; + + /* Extract the p and g as data from the DER encoded DH parameters. */ + ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz); + if (ret != 0) { + if (x != NULL && localDh != *x) + XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL); + localDh = NULL; + goto end; + } + + if (x != NULL) + *x = localDh; + + /* Put p and g in as big numbers. */ + if (localDh->p != NULL) { + wolfSSL_BN_free(localDh->p); + localDh->p = NULL; + } + if (localDh->g != NULL) { + wolfSSL_BN_free(localDh->g); + localDh->g = NULL; + } + localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL); + localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL); + if (localDh->p == NULL || localDh->g == NULL) { + if (x != NULL && localDh != *x) + wolfSSL_DH_free(localDh); + localDh = NULL; + } + +end: + if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL) FreeDer(&der); + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return localDh; +#else + (void)bio; + (void)x; + (void)cb; + (void)u; + return NULL; +#endif +} +#endif + + +int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) +{ + byte* certDer; + int derSz; + int pemSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509"); + + if (bio == NULL || cert == NULL) { + return SSL_FAILURE; + } + + if (bio->type != BIO_MEMORY) { + WOLFSSL_MSG("BIO type not supported for writing X509 as PEM"); + return SSL_FAILURE; + } + + certDer = cert->derCert->buffer; + derSz = cert->derCert->length; + + /* Get PEM encoded length and allocate memory for it. */ + pemSz = wc_DerToPem(certDer, derSz, NULL, 0, CERT_TYPE); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", pemSz); + return SSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + return SSL_FAILURE; + } + bio->memLen = pemSz; + + ret = wc_DerToPemEx(certDer, derSz, bio->mem, bio->memLen, NULL, CERT_TYPE); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", ret); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + + +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) +/* Intialize ctx->dh with dh's params. Return SSL_SUCCESS on ok */ +long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) +{ + int pSz, gSz; + byte *p, *g; + int ret=0; + + WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh"); + + if(!ctx || !dh) + return BAD_FUNC_ARG; + + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + + if(pSz <= 0 || gSz <= 0) + return SSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + if(!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + if(!g) { + XFREE(p, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + return MEMORY_E; + } + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if(pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); + + XFREE(p, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(g, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + + return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; +} +#endif /* OPENSSL_EXTRA && !NO_DH */ +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_HAPROXY */ + + +/* stunnel compatibility functions*/ +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX)) +void WOLFSSL_ERR_remove_thread_state(void* pid) +{ + (void) pid; + return; +} + +/***TBD ***/ +void wolfSSL_print_all_errors_fp(XFILE *fp) +{ + (void)fp; +} + +int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); +#ifdef HAVE_EX_DATA + if(session != NULL && idx < MAX_EX_DATA) { + session->ex_data[idx] = data; + return SSL_SUCCESS; + } +#endif + return SSL_FAILURE; +} + + +int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, + void* cb2, CRYPTO_free_func* cb3) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index"); + (void)idx; + (void)cb1; + (void)cb2; + (void)cb3; + if(XSTRNCMP((const char*)data, "redirect index", 14) == 0) { + return 0; + } + else if(XSTRNCMP((const char*)data, "addr index", 10) == 0) { + return 1; + } + return SSL_FAILURE; +} + + +void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); +#ifdef HAVE_EX_DATA + if (session != NULL && idx < MAX_EX_DATA && idx >= 0) + return session->ex_data[idx]; +#endif + return NULL; +} + + +int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, + int), void (*f) (void *)) +{ + (void) m; + (void) r; + (void) f; + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); + WOLFSSL_STUB("wolfSSL_CRYPTO_set_mem_ex_functions"); + + return SSL_FAILURE; +} + + +WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg) +{ + (void)prime_len; + (void)generator; + (void)callback; + (void)cb_arg; + WOLFSSL_ENTER("wolfSSL_DH_generate_parameters"); + WOLFSSL_STUB("wolfSSL_DH_generate_parameters"); + + return NULL; +} + +int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator, + void (*callback) (int, int, void *)) +{ + (void)prime_len; + (void)generator; + (void)callback; + (void)dh; + WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex"); + WOLFSSL_STUB("wolfSSL_DH_generate_parameters_ex"); + + return -1; +} + + +void wolfSSL_ERR_load_crypto_strings(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + return; +} + + +unsigned long wolfSSL_ERR_peek_last_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + +#ifdef WOLFSSL_NGINX + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + if (ret == -SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} + + +int wolfSSL_FIPS_mode(void) +{ + WOLFSSL_ENTER("wolfSSL_FIPS_mode"); + WOLFSSL_STUB("wolfSSL_FIPS_mode"); + + return SSL_FAILURE; +} + +int wolfSSL_FIPS_mode_set(int r) +{ + (void)r; + WOLFSSL_ENTER("wolfSSL_FIPS_mode_set"); + WOLFSSL_STUB("wolfSSL_FIPS_mode_set"); + + return SSL_FAILURE; +} + + +int wolfSSL_RAND_set_rand_method(const void *meth) +{ + (void) meth; + WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); + WOLFSSL_STUB("wolfSSL_RAND_set_rand_method"); + + return SSL_FAILURE; +} + + +int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) +{ + int ret = SSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); + if(c != NULL && c->ssl != NULL) { + ret = 8 * c->ssl->specs.key_size; + if(alg_bits != NULL) { + *alg_bits = ret; + } + } + return ret; +} + + +int wolfSSL_sk_X509_NAME_num(const STACK_OF(WOLFSSL_X509_NAME) *s) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); + + if (s == NULL) + return -1; + return (int)s->num; +} + + +int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_num"); + + if (s == NULL) + return -1; + return (int)s->num; +} + + +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, + int indent, unsigned long flags) +{ + int i; + (void)flags; + WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); + + for (i = 0; i < indent; i++) { + if (wolfSSL_BIO_write(bio, " ", 1) != 1) + return SSL_FAILURE; + } + + if (flags == XN_FLAG_RFC2253) { + if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2) + != name->sz - 2) + return SSL_FAILURE; + } + else if (wolfSSL_BIO_write(bio, name->name, name->sz) != name->sz) + return SSL_FAILURE; + + return SSL_SUCCESS; +} + + +WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) +{ + (void)x; + WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr"); + WOLFSSL_STUB("wolfSSL_X509_get0_pubkey_bitstr"); + + return NULL; +} + + +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + (void)ctx; + (void)session; + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + WOLFSSL_STUB("wolfSSL_CTX_add_session"); + + return SSL_SUCCESS; +} + + +int wolfSSL_get_state(const WOLFSSL* ssl) +{ + (void)ssl; + WOLFSSL_ENTER("wolfSSL_get_state"); + WOLFSSL_STUB("wolfSSL_get_state"); + + return SSL_FAILURE; +} + + +void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.name; +} + + +void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.x509; +} + + +int wolfSSL_version(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_version"); + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return SSL3_VERSION; + case TLSv1_MINOR : + case TLSv1_1_MINOR : + case TLSv1_2_MINOR : + case TLSv1_3_MINOR : + return TLS1_VERSION; + default: + return SSL_FAILURE; + } + } + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + case DTLSv1_2_MINOR : + return DTLS1_VERSION; + default: + return SSL_FAILURE; + } + } + return SSL_FAILURE; +} + + +STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +{ + (void)ssl; + WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); + WOLFSSL_STUB("wolfSSL_get_peer_cert_chain"); + + return NULL; +} + + +WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); + return ssl->ctx; +} + +int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz"); + if(!name) + return -1; + return name->sz; +} + + +#ifdef HAVE_SNI +int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) +{ + int ret; + WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name"); + ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, + host_name, XSTRLEN(host_name)); + WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); + return ret; +} + + +#ifndef NO_WOLFSSL_SERVER +const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) +{ + void * serverName = NULL; + if (ssl == NULL) + return NULL; + TLSX_SNI_GetRequest(ssl->extensions, type, &serverName); + return (const char *)serverName; +} +#endif /* NO_WOLFSSL_SERVER */ +#endif /* HAVE_SNI */ + +WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +{ + if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == SSL_SUCCESS) + return ssl->ctx; + return NULL; +} + + +VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); + if(ctx) + return ctx->verifyCallback; + return NULL; +} + + +void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); + if (ctx) + ctx->sniRecvCb = cb; +} + +int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, + CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback"); + if (ctx) { + ctx->sniRecvCb = cb; + return 1; + } + return 0; +} + +void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); + if (ctx) + ctx->sniRecvCbArg = arg; +} + + +long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) +{ + WOLFSSL_ENTER("SSL_CTX_clear_options"); + WOLFSSL_STUB("SSL_CTX_clear_options"); + (void)ctx; + (void)opt; + return opt; +} + +void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*)) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); + WOLFSSL_STUB("wolfSSL_THREADID_set_callback"); + (void)threadid_func; + return; +} + +void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); + WOLFSSL_STUB("wolfSSL_THREADID_set_numeric"); + (void)id; + (void)val; + return; +} + + +STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_NAME* name) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); + WOLFSSL_STUB("wolfSSL_X509_STORE_get1_certs"); + (void)ctx; + (void)name; + return NULL; +} + +void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){ + (void) sk; + (void) f; + WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free"); + WOLFSSL_STUB("wolfSSL_sk_X509_pop_free"); +} + +#endif /* OPENSSL_EXTRA and HAVE_STUNNEL */ +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX))\ + || defined(WOLFSSL_HAPROXY) + + +const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + if(!sess || !idLen) { + WOLFSSL_MSG("Bad func args. Please provide idLen"); + return NULL; + } + *idLen = sess->sessionIDSz; + return sess->sessionID; +} +#endif + +#if (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) +int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) +{ + int mode = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); + + if(!ctx) + return SSL_FATAL_ERROR; + + if (ctx->verifyPeer) + mode |= SSL_VERIFY_PEER; + else if (ctx->verifyNone) + mode |= SSL_VERIFY_NONE; + + if (ctx->failNoCert) + mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + + if (ctx->failNoCertxPSK) + mode |= SSL_VERIFY_FAIL_EXCEPT_PSK; + + WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); + return mode; +} +#endif + +#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = SSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC25519_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE || + pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_FAILURE; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + curve25519_key key; + + if (wc_curve25519_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_init failed"); + else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_curve25519_make_key failed"); + /* export key pair */ + else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub, + pubSz, EC25519_LITTLE_ENDIAN) + != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed"); + else + ret = SSL_SUCCESS; + + wc_curve25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + */ +int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) shared; + (void) sharedSz; + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = SSL_FAILURE; + curve25519_key privkey, pubkey; + + WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); + + if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE || + priv == NULL || privSz < CURVE25519_KEYSIZE || + pub == NULL || pubSz < CURVE25519_KEYSIZE) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; + } + + /* import private key */ + if (wc_curve25519_init(&privkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init privkey failed"); + return ret; + } + if (wc_curve25519_import_private_ex(priv, privSz, &privkey, + EC25519_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_import_private_ex failed"); + wc_curve25519_free(&privkey); + return ret; + } + + /* import public key */ + if (wc_curve25519_init(&pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init pubkey failed"); + wc_curve25519_free(&privkey); + return ret; + } + if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey, + EC25519_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_import_public_ex failed"); + wc_curve25519_free(&privkey); + wc_curve25519_free(&pubkey); + return ret; + } + + if (wc_curve25519_shared_secret_ex(&privkey, &pubkey, + shared, sharedSz, + EC25519_LITTLE_ENDIAN) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + else + ret = SSL_SUCCESS; + + wc_curve25519_free(&privkey); + wc_curve25519_free(&pubkey); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} +#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = SSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_ED25519_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE || + pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return SSL_FATAL_ERROR; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + ed25519_key key; + + if (wc_ed25519_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_ed25519_init failed"); + else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_ed25519_make_key failed"); + /* export private key */ + else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY) + WOLFSSL_MSG("wc_ed25519_export_key failed"); + else + ret = SSL_SUCCESS; + + wc_ed25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * priv is a buffer containing private and public part of key + */ +int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, + unsigned char *sig, unsigned int *sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) priv; + (void) privSz; + (void) sig; + (void) sigSz; + return SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + int ret = SSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_ED25519_sign"); + + if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE || + msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; + } + + /* import key */ + if (wc_ed25519_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init failed"); + return ret; + } + if (wc_ed25519_import_private_key(priv, privSz/2, + priv+(privSz/2), ED25519_PUB_KEY_SIZE, + &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed25519_import_private failed"); + wc_ed25519_free(&key); + return ret; + } + + if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + else + ret = SSL_SUCCESS; + + wc_ed25519_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * pub is a buffer containing public part of key + */ +int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, + const unsigned char *sig, unsigned int sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) pub; + (void) pubSz; + (void) sig; + (void) sigSz; + return SSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + int ret = SSL_FAILURE, check = 0; + + WOLFSSL_ENTER("wolfSSL_ED25519_verify"); + + if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE || + msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return SSL_FAILURE; + } + + /* import key */ + if (wc_ed25519_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init failed"); + return ret; + } + if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed25519_import_public failed"); + wc_ed25519_free(&key); + return ret; + } + + if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz, + &check, &key)) != MP_OKAY) { + WOLFSSL_MSG("wc_ed25519_verify_msg failed"); + } + else if (!check) + WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)"); + else + ret = SSL_SUCCESS; -unsigned long wolfSSL_ERR_peek_last_error(void) -{ - unsigned long l = 0UL; - WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - WOLFSSL_STUB("wolfSSL_ERR_peek_last_error"); + wc_ed25519_free(&key); - return l; + return ret; +#endif /* WOLFSSL_KEY_GEN */ } +#endif /* OPENSSL_EXTRA && HAVE_ED25519 */ -int wolfSSL_FIPS_mode(void) -{ - WOLFSSL_ENTER("wolfSSL_FIPS_mode"); - WOLFSSL_STUB("wolfSSL_FIPS_mode"); +#ifdef WOLFSSL_JNI +int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) +{ + WOLFSSL_ENTER("wolfSSL_set_jobject"); + if (ssl != NULL) + { + ssl->jObjectRef = objPtr; + return SSL_SUCCESS; + } return SSL_FAILURE; } -int wolfSSL_FIPS_mode_set(int r) +void* wolfSSL_get_jobject(WOLFSSL* ssl) { - (void)r; - WOLFSSL_ENTER("wolfSSL_FIPS_mode_set"); - WOLFSSL_STUB("wolfSSL_FIPS_mode_set"); - - return SSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_get_jobject"); + if (ssl != NULL) + return ssl->jObjectRef; + return NULL; } +#endif /* WOLFSSL_JNI */ + -int wolfSSL_RAND_set_rand_method(const void *meth) +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount) { - (void) meth; - WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); - WOLFSSL_STUB("wolfSSL_RAND_set_rand_method"); + if (ctx == NULL) { + return BAD_FUNC_ARG; + } - return SSL_FAILURE; + return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, + events, maxEvents, flags, eventCount); } - -int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) +int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) { - int ret = SSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); - if(c != NULL && c->ssl != NULL) { - ret = 8 * c->ssl->specs.key_size; - if(alg_bits != NULL) { - *alg_bits = ret; - } + int ret, eventCount = 0; + WOLF_EVENT* events[1]; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, + events, sizeof(events)/sizeof(events), flags, &eventCount); + if (ret == 0) { + ret = eventCount; } + return ret; } +#endif /* WOLFSSL_ASYNC_CRYPT */ -int wolfSSL_sk_X509_NAME_num(const STACK_OF(WOLFSSL_X509_NAME) *s) +#ifdef OPENSSL_EXTRA +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) { - (void) s; - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_num"); + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); - return SSL_FAILURE; -} + (void)line; + (void)file; + /* No data or flags stored - error display only in Nginx. */ + if (data != NULL) { + *data = ""; + } + if (flags != NULL) { + *flags = 0; + } -int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s) -{ - (void) s; - WOLFSSL_ENTER("wolfSSL_sk_X509_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_num"); +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + int ret = 0; - return SSL_FAILURE; -} + while (1) { + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + ret = -ret; + if (ret == SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + if (ret != WANT_READ && ret != WANT_WRITE && + ret != ZERO_RETURN && ret != SSL_ERROR_ZERO_RETURN && + ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E) + break; -int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* nm, - int indent, unsigned long flags) -{ - (void)bio; - (void)nm; - (void)indent; - (void)flags; - WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); - WOLFSSL_STUB("wolfSSL_X509_NAME_print_ex"); + wc_RemoveErrorNode(-1); + } - return SSL_FAILURE; + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } +#endif +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) -WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) +STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) { - (void)x; - WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr"); - WOLFSSL_STUB("wolfSSL_X509_get0_pubkey_bitstr"); - + (void)ssl; + WOLFSSL_STUB("wolfSSL_get_ciphers_compat"); return NULL; } - -int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +void wolfSSL_OPENSSL_config(char *config_name) { - (void)ctx; - (void)session; - WOLFSSL_ENTER("wolfSSL_CTX_add_session"); - WOLFSSL_STUB("wolfSSL_CTX_add_session"); - - return SSL_SUCCESS; + WOLFSSL_STUB("wolfSSL_OPENSSL_config"); + (void)config_name; } - -int wolfSSL_get_state(const WOLFSSL* ssl) +int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) { - (void)ssl; - WOLFSSL_ENTER("wolfSSL_get_state"); - WOLFSSL_STUB("wolfSSL_get_state"); - - return SSL_FAILURE; -} - + static int x509_idx = 0; -void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i) -{ - (void)sk; - (void)i; - WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_value"); + WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; - return NULL; + return x509_idx++; } - -void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) +void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) { - (void)sk; - (void)i; - WOLFSSL_ENTER("wolfSSL_sk_X509_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_value"); - + WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) { + return x509->ex_data[idx]; + } + #else + (void)x509; + (void)idx; + #endif return NULL; } - - -int wolfSSL_version(WOLFSSL* ssl) +int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data) { - WOLFSSL_ENTER("wolfSSL_version"); - if (ssl->version.major == SSLv3_MAJOR) { - switch (ssl->version.minor) { - case SSLv3_MINOR : - return SSL3_VERSION; - case TLSv1_MINOR : - case TLSv1_1_MINOR : - case TLSv1_2_MINOR : - return TLS1_VERSION; - default: - return SSL_FAILURE; - } - } - else if (ssl->version.major == DTLS_MAJOR) { - switch (ssl->version.minor) { - case DTLS_MINOR : - case DTLSv1_2_MINOR : - return DTLS1_VERSION; - default: - return SSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_X509_set_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA) + { + x509->ex_data[idx] = data; + return SSL_SUCCESS; } + #else + (void)x509; + (void)idx; + (void)data; + #endif return SSL_FAILURE; } - - -STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len) { - (void)ssl; - WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); - WOLFSSL_STUB("wolfSSL_get_peer_cert_chain"); + WOLFSSL_ENTER("wolfSSL_X509_NAME_digest"); - return NULL; -} + if (name == NULL || type == NULL) + return SSL_FAILURE; + return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName, + name->fullName.fullNameLen, md, len, type, NULL); +} -long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) +long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) { - (void)ctx; - WOLFSSL_ENTER("wolfSSL_CTX_get_options"); - WOLFSSL_STUB("wolfSSL_CTX_get_options"); - - return 0; -} + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); + if (ctx == NULL) + return 0; -WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); - return ssl->ctx; + return ctx->timeout; } -int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name) +#ifdef HAVE_ECC +int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) { - WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz"); - if(!name) - return -1; - return name->sz; -} + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; -const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - WOLFSSL_STUB("wolfSSL_SESSION_get_id"); - if(!sess || !idLen) { - WOLFSSL_MSG("Bad func args. Please provide idLen"); - return NULL; - } - *idLen = sess->sessionIDSz; - return sess->sessionID; + ctx->ecdhCurveOID = ecdh->group->curve_oid; + + return SSL_SUCCESS; } +#endif -#ifdef HAVE_SNI -int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) +/* Assumes that the session passed in is from the cache. */ +int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) { - int ret; - WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name"); - ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, - host_name, XSTRLEN(host_name)); - WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); - return ret; -} + WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + if (ctx == NULL || s == NULL) + return BAD_FUNC_ARG; -#ifndef NO_WOLFSSL_SERVER -const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) -{ - void * serverName = NULL; - if (ssl == NULL) - return NULL; - TLSX_SNI_GetRequest(ssl->extensions, type, &serverName); - return (const char *)serverName; -} -#endif /* NO_WOLFSSL_SERVER */ -#endif /* HAVE_SNI */ +#ifdef HAVE_EXT_CACHE + if (!ctx->internalCacheOff) +#endif + { + /* Don't remove session just timeout session. */ + s->timeout = 0; + } +#ifdef HAVE_EXT_CACHE + if (ctx->rem_sess_cb != NULL) + ctx->rem_sess_cb(ctx, s); +#endif -WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) -{ - if (ssl && ctx && SetSSL_CTX(ssl, ctx) == SSL_SUCCESS) - return ssl->ctx; - return NULL; + return 0; } - -VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) +BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) { - WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); - if(ctx) - return ctx->verifyCallback; + WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ return NULL; } - - -void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) +BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) { - WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); - if (ctx) - ctx->sniRecvCb = cb; + WOLFSSL_ENTER("wolfSSL_SSL_get_wbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; } - -void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) +int wolfSSL_SSL_do_handshake(WOLFSSL *s) { - WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); - if (ctx) - ctx->sniRecvCbArg = arg; -} + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); + if (s == NULL) + return SSL_FAILURE; -long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) -{ - WOLFSSL_ENTER("SSL_CTX_clear_options"); - WOLFSSL_STUB("SSL_CTX_clear_options"); - (void)ctx; - (void)opt; - return opt; + if (s->options.side == WOLFSSL_CLIENT_END) + return wolfSSL_connect(s); + return wolfSSL_accept(s); } -void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*)) +int wolfSSL_SSL_in_init(WOLFSSL *s) { - WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); - WOLFSSL_STUB("wolfSSL_THREADID_set_callback"); - (void)threadid_func; - return; + WOLFSSL_ENTER("wolfSSL_SSL_in_init"); + + if (s == NULL) + return SSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return s->options.connectState < SECOND_REPLY_DONE; + return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE; } -void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) +WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) { - WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); - WOLFSSL_STUB("wolfSSL_THREADID_set_numeric"); - (void)id; - (void)val; - return; -} + WOLFSSL_SESSION *session; + WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); -WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, - WOLFSSL_X509_NAME* name) -{ - WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); - WOLFSSL_STUB("wolfSSL_X509_STORE_get1_certs"); - (void)ctx; - (void)name; - return NULL; -} + if (ssl == NULL) { + return NULL; + } -void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){ - (void) sk; - (void) f; - WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free"); - WOLFSSL_STUB("wolfSSL_sk_X509_pop_free"); -} + session = wolfSSL_get_session((WOLFSSL*)ssl); -#endif /* OPENSSL_EXTRA and HAVE_STUNNEL */ +#ifdef HAVE_EXT_CACHE + ((WOLFSSL*)ssl)->extSession = session; +#endif + return session; +} -#if (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) -int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) +int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) { - int mode = 0; - WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); - - if(!ctx) - return SSL_FATAL_ERROR; + int ret; + DecodedCert dCert; - if (ctx->verifyPeer) - mode |= SSL_VERIFY_PEER; - else if (ctx->verifyNone) - mode |= SSL_VERIFY_NONE; + WOLFSSL_ENTER("wolfSSL_X509_check_host"); - if (ctx->failNoCert) - mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + /* flags and peername not needed for Nginx. */ + (void)flags; + (void)peername; - if (ctx->failNoCertxPSK) - mode |= SSL_VERIFY_FAIL_EXCEPT_PSK; + InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL); + ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL); + if (ret != 0) + return SSL_FAILURE; - WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); - return mode; + ret = CheckHostName(&dCert, (char *)chk, chklen); + FreeDecodedCert(&dCert); + if (ret != 0) + return SSL_FAILURE; + return SSL_SUCCESS; } -#endif -#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519) -/* return 1 if success, 0 if error - * output keys are little endian format - */ -int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, - unsigned char *pub, unsigned int *pubSz) +int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) { -#ifndef WOLFSSL_KEY_GEN - WOLFSSL_MSG("No Key Gen built in"); - (void) priv; - (void) privSz; - (void) pub; - (void) pubSz; - return SSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = SSL_FAILURE; - int initTmpRng = 0; - WC_RNG *rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG *tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif + static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + int i; + word32 j; + word32 len = 0; - WOLFSSL_ENTER("wolfSSL_EC25519_generate_key"); + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); - if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE || - pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) { - WOLFSSL_MSG("Bad arguments"); + if (bp == NULL || a == NULL) return SSL_FAILURE; + + /* Skip ASN.1 INTEGER (type) byte. */ + i = 1; + /* When indefinte length, can't determine length with data available. */ + if (a->data[i] == 0x80) + return 0; + /* One length byte if less than 0x80. */ + if (a->data[i] < 0x80) + len = a->data[i++]; + /* Multiple length byte if greater than 0x80. */ + else if (a->data[i] > 0x80) { + switch (a->data[i++] - 0x80) { + case 4: + len |= a->data[i++] << 24; + FALL_THROUGH; + case 3: + len |= a->data[i++] << 16; + FALL_THROUGH; + case 2: + len |= a->data[i++] << 8; + FALL_THROUGH; + case 1: + len |= a->data[i++]; + break; + default: + /* Not supporting greater than 4 bytes of length. */ + return 0; + } } -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return SSL_FAILURE; -#endif - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; + /* Zero length integer is the value zero. */ + if (len == 0) { + wolfSSL_BIO_write(bp, "00", 2); + return 2; } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; + + /* Don't do negative - just write out every byte. */ + for (j = 0; j < len; i++,j++) { + wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1); + wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1); } - if (rng) { - curve25519_key key; + /* Two nibbles written for each byte. */ + return len * 2; +} - if (wc_curve25519_init(&key) != MP_OKAY) - WOLFSSL_MSG("wc_curve25519_init failed"); - else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY) - WOLFSSL_MSG("wc_curve25519_make_key failed"); - /* export key pair */ - else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub, - pubSz, EC25519_LITTLE_ENDIAN) - != MP_OKAY) - WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed"); - else - ret = SSL_SUCCESS; - wc_curve25519_free(&key); - } +#ifdef HAVE_SESSION_TICKET +/* Expected return values from implementations of OpenSSL ticket key callback. + */ +#define TICKET_KEY_CB_RET_FAILURE -1 +#define TICKET_KEY_CB_RET_NOT_FOUND 0 +#define TICKET_KEY_CB_RET_OK 1 +#define TICKET_KEY_CB_RET_RENEW 2 - if (initTmpRng) - wc_FreeRng(tmpRNG); +/* The ticket key callback as used in OpenSSL is stored here. */ +static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL; -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +/* Implementation of session ticket encryption/decryption using OpenSSL + * callback to initialize the cipher and HMAC. + * + * ssl The SSL/TLS object. + * keyName The key name - used to identify the key to be used. + * iv The IV to use. + * mac The MAC of the encrypted data. + * enc Encrypt ticket. + * encTicket The ticket data. + * encTicketLen The length of the ticket data. + * encLen The encrypted/decrypted ticket length - output length. + * ctx Ignored. Application specific data. + * returns WOLFSSL_TICKET_RET_OK to indicate success, + * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and + * WOLFSSL_TICKET_RET_FATAL on error. + */ +static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) +{ + byte digest[MAX_DIGEST_SIZE]; + WOLFSSL_EVP_CIPHER_CTX evpCtx; + WOLFSSL_HMAC_CTX hmacCtx; + unsigned int mdSz = 0; + int len = 0; + int ret = WOLFSSL_TICKET_RET_FATAL; + int res; + + (void)ctx; + if (ticketKeyCb == NULL) + return WOLFSSL_TICKET_RET_FATAL; + + wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); + /* Initialize the cipher and HMAC. */ + res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc); + if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) + return WOLFSSL_TICKET_RET_FATAL; + + if (enc) + { + /* Encrypt in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of encrypted data. */ + encTicketLen += len; + *encLen = encTicketLen; + + /* HMAC the encrypted data into the parameter 'mac'. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz); + } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz); + if (XMEMCMP(mac, digest, mdSz) != 0) + goto end; + + /* Decrypt the ticket data in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of decrypted data. */ + *encLen = encTicketLen + len; + } + + ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE : + WOLFSSL_TICKET_RET_OK; +end: return ret; -#endif /* WOLFSSL_KEY_GEN */ } -/* return 1 if success, 0 if error - * input and output keys are little endian format +/* Set the callback to use when encrypting/decrypting tickets. + * + * ctx The SSL/TLS context object. + * cb The OpenSSL session ticket callback. + * returns SSL_SUCCESS to indicate success. */ -int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, - const unsigned char *priv, unsigned int privSz, - const unsigned char *pub, unsigned int pubSz) +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +{ + /* Store callback in a global. */ + ticketKeyCb = cb; + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + + return SSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_OCSP +/* Not an OpenSSL API. */ +int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) { -#ifndef WOLFSSL_KEY_GEN - WOLFSSL_MSG("No Key Gen built in"); - (void) shared; - (void) sharedSz; - (void) priv; - (void) privSz; - (void) pub; - (void) pubSz; - return SSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = SSL_FAILURE; - curve25519_key privkey, pubkey; + *response = ssl->ocspResp; + return ssl->ocspRespSz; +} - WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) +{ + return ssl->url; +} - if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE || - priv == NULL || privSz < CURVE25519_KEYSIZE || - pub == NULL || pubSz < CURVE25519_KEYSIZE) { - WOLFSSL_MSG("Bad arguments"); +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) return SSL_FAILURE; - } - /* import private key */ - if (wc_curve25519_init(&privkey) != MP_OKAY) { - WOLFSSL_MSG("wc_curve25519_init privkey failed"); - return ret; + ssl->url = url; + return SSL_SUCCESS; +} + +static INLINE void ato24(const byte* c, word32* u24) +{ + *u24 = (c[0] << 16) | (c[1] << 8) | c[2]; +} + +int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, STACK_OF(X509)** chain) +{ + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; + + if (ctx == NULL || chain == NULL) { + chain = NULL; + return SSL_FAILURE; } - if (wc_curve25519_import_private_ex(priv, privSz, &privkey, - EC25519_LITTLE_ENDIAN) != MP_OKAY) { - WOLFSSL_MSG("wc_curve25519_import_private_ex failed"); - wc_curve25519_free(&privkey); - return ret; + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return SSL_SUCCESS; } - /* import public key */ - if (wc_curve25519_init(&pubkey) != MP_OKAY) { - WOLFSSL_MSG("wc_curve25519_init pubkey failed"); - wc_curve25519_free(&privkey); - return ret; - } - if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey, - EC25519_LITTLE_ENDIAN) != MP_OKAY) { - WOLFSSL_MSG("wc_curve25519_import_public_ex failed"); - wc_curve25519_free(&privkey); - wc_curve25519_free(&pubkey); - return ret; + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return SSL_SUCCESS; } - if (wc_curve25519_shared_secret_ex(&privkey, &pubkey, - shared, sharedSz, - EC25519_LITTLE_ENDIAN) != MP_OKAY) - WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); - else - ret = SSL_SUCCESS; + /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ + for (idx = 0; idx < ctx->certChain->length; ) { + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + return SSL_FAILURE; + node->next = NULL; + + /* 3 byte length | X509 DER data */ + ato24(ctx->certChain->buffer + idx, &length); + idx += 3; + + /* Create a new X509 from DER encoded data. */ + node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx, + length); + if (node->data.x509 == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + /* Return as much of the chain as we created. */ + ctx->x509Chain = *chain; + return SSL_FAILURE; + } + idx += length; - wc_curve25519_free(&privkey); - wc_curve25519_free(&pubkey); + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; + } + else { + (*chain)->num++; + last->next = node; + } - return ret; -#endif /* WOLFSSL_KEY_GEN */ + last = node; + } + + ctx->x509Chain = *chain; + + return SSL_SUCCESS; } -#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */ -#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519) -/* return 1 if success, 0 if error - * output keys are little endian format - */ -int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, - unsigned char *pub, unsigned int *pubSz) +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*cb)(WOLFSSL*, void*)) +{ + if (ctx == NULL || ctx->cm == NULL) + return SSL_FAILURE; + + /* Ensure stapling is on for callback to be used. */ + wolfSSL_CTX_EnableOCSPStapling(ctx); + + if (ctx->cm->ocsp_stapling == NULL) + return SSL_FAILURE; + + ctx->cm->ocsp_stapling->statusCb = cb; + return SSL_SUCCESS; +} + +int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) { -#ifndef WOLFSSL_KEY_GEN - WOLFSSL_MSG("No Key Gen built in"); - (void) priv; - (void) privSz; - (void) pub; - (void) pubSz; - return SSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = SSL_FAILURE; - int initTmpRng = 0; - WC_RNG *rng = NULL; + WOLFSSL_STACK* node; + Signer* ca = NULL; #ifdef WOLFSSL_SMALL_STACK - WC_RNG *tmpRNG = NULL; + DecodedCert* cert = NULL; #else - WC_RNG tmpRNG[1]; + DecodedCert cert[1]; #endif - WOLFSSL_ENTER("wolfSSL_ED25519_generate_key"); + if (issuer == NULL || ctx == NULL || x == NULL) + return SSL_FATAL_ERROR; - if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE || - pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + if (ctx->chain != NULL) { + for (node = ctx->chain; node != NULL; node = node->next) { + if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) { + *issuer = x; + return SSL_SUCCESS; + } + } } + #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpRNG == NULL) - return SSL_FATAL_ERROR; + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return SSL_FAILURE; #endif - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - if (initGlobalRNG == 0) - WOLFSSL_MSG("Global RNG no Init"); - else - rng = &globalRNG; - } - if (rng) { - ed25519_key key; + /* Use existing CA retrieval APIs that use DecodedCert. */ + InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(ctx->store->cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(ctx->store->cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(ctx->store->cm, cert->issuerHash); + #endif /* NO SKID */ + } + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif - if (wc_ed25519_init(&key) != MP_OKAY) - WOLFSSL_MSG("wc_ed25519_init failed"); - else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY) - WOLFSSL_MSG("wc_ed25519_make_key failed"); - /* export private key */ - else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY) - WOLFSSL_MSG("wc_ed25519_export_key failed"); - else - ret = SSL_SUCCESS; + if (ca == NULL) + return SSL_FAILURE; - wc_ed25519_free(&key); - } + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return SSL_FAILURE; - if (initTmpRng) - wc_FreeRng(tmpRNG); + /* Create an empty certificate as CA doesn't have a certificate. */ + XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509)); + /* TODO: store the full certificate and dup when required. */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ - return ret; -#endif /* WOLFSSL_KEY_GEN */ + return SSL_SUCCESS; } -/* return 1 if success, 0 if error - * input and output keys are little endian format - * priv is a buffer containing private and public part of key - */ -int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, - const unsigned char *priv, unsigned int privSz, - unsigned char *sig, unsigned int *sigSz) +void wolfSSL_X509_email_free(STACK_OF(WOLFSSL_STRING) *sk) { -#ifndef WOLFSSL_KEY_GEN - WOLFSSL_MSG("No Key Gen built in"); - (void) msg; - (void) msgSz; - (void) priv; - (void) privSz; - (void) sig; - (void) sigSz; - return SSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - ed25519_key key; - int ret = SSL_FAILURE; + WOLFSSL_STACK *curr; - WOLFSSL_ENTER("wolfSSL_ED25519_sign"); + while (sk != NULL) { + curr = sk; + sk = sk->next; - if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE || - msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; + XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL); } +} - /* import key */ - if (wc_ed25519_init(&key) != MP_OKAY) { - WOLFSSL_MSG("wc_curve25519_init failed"); - return ret; - } - if (wc_ed25519_import_private_key(priv, privSz/2, - priv+(privSz/2), ED25519_PUB_KEY_SIZE, - &key) != MP_OKAY){ - WOLFSSL_MSG("wc_ed25519_import_private failed"); - wc_ed25519_free(&key); - return ret; - } +STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) +{ + WOLFSSL_STACK *list = NULL; - if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY) - WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); - else - ret = SSL_SUCCESS; + if (x->authInfoSz == 0) + return NULL; - wc_ed25519_free(&key); + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (list == NULL) + return NULL; - return ret; -#endif /* WOLFSSL_KEY_GEN */ + list->data.string = (char*)x->authInfo; + list->next = NULL; + + return list; } -/* return 1 if success, 0 if error - * input and output keys are little endian format - * pub is a buffer containing public part of key - */ -int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, - const unsigned char *pub, unsigned int pubSz, - const unsigned char *sig, unsigned int sigSz) +int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject) { -#ifndef WOLFSSL_KEY_GEN - WOLFSSL_MSG("No Key Gen built in"); - (void) msg; - (void) msgSz; - (void) pub; - (void) pubSz; - (void) sig; - (void) sigSz; - return SSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - ed25519_key key; - int ret = SSL_FAILURE, check = 0; - - WOLFSSL_ENTER("wolfSSL_ED25519_verify"); + WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject); + WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer); - if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE || - msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return SSL_FAILURE; - } + if (issuerName == NULL || subjectName == NULL) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; - /* import key */ - if (wc_ed25519_init(&key) != MP_OKAY) { - WOLFSSL_MSG("wc_curve25519_init failed"); - return ret; - } - if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){ - WOLFSSL_MSG("wc_ed25519_import_public failed"); - wc_ed25519_free(&key); - return ret; + /* Literal matching of encoded names and key ids. */ + if (issuerName->sz != subjectName->sz || + XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; } - if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz, - &check, &key)) != MP_OKAY) { - WOLFSSL_MSG("wc_ed25519_verify_msg failed"); + if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) { + if (subject->authKeyIdSz != issuer->subjKeyIdSz || + XMEMCMP(subject->authKeyId, issuer->subjKeyId, + issuer->subjKeyIdSz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } } - else if (!check) - WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)"); - else - ret = SSL_SUCCESS; - - wc_ed25519_free(&key); - return ret; -#endif /* WOLFSSL_KEY_GEN */ + return X509_V_OK; } -#endif /* OPENSSL_EXTRA && HAVE_ED25519 */ +WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) +{ + return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length); +} -#ifdef WOLFSSL_JNI +char* wolfSSL_sk_WOLFSSL_STRING_value(STACK_OF(WOLFSSL_STRING)* strings, + int idx) +{ + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; +} +#endif /* HAVE_OCSP */ -int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) +#ifdef HAVE_ALPN +void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, + unsigned int *len) { - WOLFSSL_ENTER("wolfSSL_set_jobject"); - if (ssl != NULL) - { - ssl->jObjectRef = objPtr; - return SSL_SUCCESS; + word16 nameLen; + + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; } - return SSL_FAILURE; } -void* wolfSSL_get_jobject(WOLFSSL* ssl) +int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, + const unsigned char *in, unsigned int inLen, + const unsigned char *clientNames, + unsigned int clientLen) { - WOLFSSL_ENTER("wolfSSL_get_jobject"); - if (ssl != NULL) - return ssl->jObjectRef; - return NULL; -} + unsigned int i, j; + byte lenIn, lenClient; -#endif /* WOLFSSL_JNI */ + if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL) + return OPENSSL_NPN_UNSUPPORTED; + for (i = 0; i < inLen; i += lenIn) { + lenIn = in[i++]; + for (j = 0; j < clientLen; j += lenClient) { + lenClient = clientNames[j++]; -#ifdef WOLFSSL_ASYNC_CRYPT -int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, - WOLF_EVENT_FLAG flags, int* eventCount) + if (lenIn != lenClient) + continue; + + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } + } + } + + *out = (unsigned char *)clientNames + 1; + *outLen = clientNames[0]; + return OPENSSL_NPN_NO_OVERLAP; +} + +void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) { - if (ctx == NULL) { - return BAD_FUNC_ARG; + if (ctx != NULL) { + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; } +} - return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, - events, maxEvents, flags, eventCount); +void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char + **out, + unsigned int *outlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb"); } -int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) +void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) { - int ret, eventCount = 0; - WOLF_EVENT* events[1]; + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); +} - if (ssl == NULL) { - return BAD_FUNC_ARG; - } +void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len) +{ + (void)s; + (void)data; + (void)len; + WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); +} +#endif /* HAVE_ALPN */ - /* 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 */ - } +#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ - return ret; +#ifdef OPENSSL_EXTRA +int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) +{ + WOLFSSL_STUB("SSL_CTX_set_msg_callback"); + (void)ctx; + (void)cb; + return SSL_FAILURE; } -#endif /* WOLFSSL_ASYNC_CRYPT */ +int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) +{ + WOLFSSL_STUB("SSL_set_msg_callback"); + (void)ssl; + (void)cb; + return SSL_FAILURE; +} +int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg) +{ + WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg"); + (void)ctx; + (void)arg; + return SSL_FAILURE; +} +int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) +{ + WOLFSSL_STUB("SSL_set_msg_callback_arg"); + (void)ssl; + (void)arg; + return SSL_FAILURE; +} +#endif #endif /* WOLFCRYPT_ONLY */ diff --git a/src/tls.c b/src/tls.c old mode 100644 new mode 100755 index c0ca6c1513..df8f7c5b58 --- a/src/tls.c +++ b/src/tls.c @@ -40,6 +40,10 @@ #include #endif +#ifdef HAVE_CURVE25519 + #include +#endif + #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #include @@ -47,6 +51,8 @@ #ifdef HAVE_QSH static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name); +#endif +#if defined(HAVE_NTRU) || defined(HAVE_QSH) static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type); #endif @@ -66,23 +72,13 @@ #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - #ifdef WOLFSSL_SHA384 #define P_HASH_MAX_SIZE SHA384_DIGEST_SIZE #else #define P_HASH_MAX_SIZE SHA256_DIGEST_SIZE #endif + /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ static int p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen, const byte* seed, word32 seedLen, int hash) @@ -157,36 +153,41 @@ static int p_hash(byte* result, word32 resLen, const byte* secret, lastTime = times - 1; - if ((ret = wc_HmacSetKey(hmac, hash, secret, secLen)) == 0) { - if ((ret = wc_HmacUpdate(hmac, seed, seedLen)) == 0) { /* A0 = seed */ - if ((ret = wc_HmacFinal(hmac, previous)) == 0) { /* A1 */ - for (i = 0; i < times; i++) { + ret = wc_HmacInit(hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(hmac, hash, secret, secLen); + if (ret == 0) + ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */ + if (ret == 0) + ret = wc_HmacFinal(hmac, previous); /* A1 */ + if (ret == 0) { + for (i = 0; i < times; i++) { + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacUpdate(hmac, seed, seedLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, current); + if (ret != 0) + break; + + if ((i == lastTime) && lastLen) + XMEMCPY(&result[idx], current, + min(lastLen, P_HASH_MAX_SIZE)); + else { + XMEMCPY(&result[idx], current, len); + idx += len; ret = wc_HmacUpdate(hmac, previous, len); if (ret != 0) break; - ret = wc_HmacUpdate(hmac, seed, seedLen); - if (ret != 0) - break; - ret = wc_HmacFinal(hmac, current); + ret = wc_HmacFinal(hmac, previous); if (ret != 0) break; - - if ((i == lastTime) && lastLen) - XMEMCPY(&result[idx], current, - min(lastLen, P_HASH_MAX_SIZE)); - else { - XMEMCPY(&result[idx], current, len); - idx += len; - ret = wc_HmacUpdate(hmac, previous, len); - if (ret != 0) - break; - ret = wc_HmacFinal(hmac, previous); - if (ret != 0) - break; - } } } } + wc_HmacFree(hmac); } ForceZero(previous, P_HASH_MAX_SIZE); @@ -345,7 +346,6 @@ static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, return ret; } - #ifdef WOLFSSL_SHA384 #define HSHASH_SZ SHA384_DIGEST_SIZE #else @@ -399,21 +399,29 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret; const byte* side; - byte handshake_hash[HSHASH_SZ]; + byte* handshake_hash; word32 hashSz = HSHASH_SZ; + /* using allocate here to allow async hardware to use buffer directly */ + handshake_hash = (byte*)XMALLOC(hashSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (handshake_hash == NULL) + return MEMORY_E; + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) - return ret; + if (ret == 0) { + if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; - if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) - side = tls_client; - else - side = tls_server; + ret = PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, + SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + } - return PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, - SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; } @@ -450,6 +458,21 @@ ProtocolVersion MakeTLSv1_2(void) return pv; } +#ifdef WOLFSSL_TLS13 +/* The TLS v1.3 protocol version. + * + * returns the protocol version data for TLS v1.3. + */ +ProtocolVersion MakeTLSv1_3(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + + return pv; +} +#endif + #ifdef HAVE_EXTENDED_MASTER static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = @@ -544,20 +567,27 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) { int ret; #ifdef HAVE_EXTENDED_MASTER - byte handshake_hash[HSHASH_SZ]; - word32 hashSz = HSHASH_SZ; - if (ssl->options.haveEMS) { + byte* handshake_hash; + word32 hashSz = HSHASH_SZ; + + handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (handshake_hash == NULL) + return MEMORY_E; ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) + if (ret < 0) { + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; + } ret = wolfSSL_MakeTlsExtendedMasterSecret( ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); } else #endif ret = wolfSSL_MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, @@ -642,7 +672,19 @@ static INLINE void c24to32(const word24 u24, word32* u32) *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; } #endif + +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) +/* Convert opaque data to a 32-bit unsigned integer. + * + * c The opaque data holding a 32-bit integer. + * u32 The 32-bit unsigned integer. + */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} #endif +#endif /* HAVE_TLS_EXTENSIONS */ /* convert 32 bit integer to opaque */ static INLINE void c32toa(word32 u32, byte* c) @@ -788,7 +830,7 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int content, int verify) { Hmac hmac; - int ret; + int ret = 0; byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; if (ssl == NULL) @@ -801,21 +843,22 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); - ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); - if (ret != 0) - return ret; - ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); - if (ret != 0) - return ret; - ret = wc_HmacUpdate(&hmac, in, sz); /* content */ - if (ret != 0) - return ret; - ret = wc_HmacFinal(&hmac, digest); + ret = wc_HmacInit(&hmac, NULL, ssl->devId); if (ret != 0) return ret; - return 0; + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); + if (ret == 0) { + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, in, sz); /* content */ + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + } + wc_HmacFree(&hmac); + + return ret; } #ifdef HAVE_TLS_EXTENSIONS @@ -871,12 +914,16 @@ static INLINE word16 TLSX_ToSemaphore(word16 type) /** Checks if a specific light (tls extension) is not set in the semaphore. */ #define IS_OFF(semaphore, light) \ - ((semaphore)[(light) / 8] ^ (byte) (0x01 << ((light) % 8))) + (!(((semaphore)[(light) / 8] & (byte) (0x01 << ((light) % 8))))) /** Turn on a specific light (tls extension) in the semaphore. */ #define TURN_ON(semaphore, light) \ ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8))) +/** Turn off a specific light (tls extension) in the semaphore. */ +#define TURN_OFF(semaphore, light) \ + ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8))) + /** Creates a new extension. */ static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) { @@ -1106,23 +1153,42 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, TLSX *extension; ALPN *alpn = NULL, *list; + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) extension = TLSX_Find(ssl->ctx->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ssl->alpnSelect != NULL) { + const byte* out; + unsigned char outLen; + + if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size, + ssl->alpnSelectArg) == 0) { + WOLFSSL_MSG("ALPN protocol match"); + if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap) + == SSL_SUCCESS) { + if (extension == NULL) { + extension = TLSX_Find(ssl->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + } + } + } + } +#endif + if (extension == NULL || extension->data == NULL) { WOLFSSL_MSG("No ALPN extensions not used or bad"); return isRequest ? 0 /* not using ALPN */ : BUFFER_ERROR; /* unexpected ALPN response */ } - if (OPAQUE16_LEN > length) - return BUFFER_ERROR; - - ato16(input, &size); - offset += OPAQUE16_LEN; - /* validating alpn list length */ if (length != OPAQUE16_LEN + size) return BUFFER_ERROR; @@ -1382,7 +1448,7 @@ static word16 TLSX_SNI_GetSize(SNI* list) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - length += XSTRLEN((char*)sni->data.host_name); + length += (word16)XSTRLEN((char*)sni->data.host_name); break; } } @@ -1404,7 +1470,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - length = XSTRLEN((char*)sni->data.host_name); + length = (word16)XSTRLEN((char*)sni->data.host_name); c16toa(length, output + offset); /* sni length */ offset += OPAQUE16_LEN; @@ -1525,6 +1591,13 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, switch(type) { case WOLFSSL_SNI_HOST_NAME: { int matchStat; +#ifdef WOLFSSL_TLS13 + /* Don't process the second ClientHello SNI extension if there + * was problems with the first. + */ + if (sni->status != 0) + break; +#endif byte matched = cacheOnly || ((XSTRLEN(sni->data.host_name) == size) && (XSTRNCMP(sni->data.host_name, @@ -1616,7 +1689,7 @@ static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); + TLSX* extension; SNI* sni = NULL; if (extensions == NULL || data == NULL) @@ -1625,6 +1698,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL) return MEMORY_E; + extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); if (!extension) { int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); if (ret != 0) { @@ -1666,8 +1740,10 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - *data = sni->data.host_name; - return XSTRLEN((char*)*data); + if (data) { + *data = sni->data.host_name; + return (word16)XSTRLEN((char*)*data); + } } } @@ -2055,7 +2131,7 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, /* request extensions */ if (csr->request.ocsp.nonceSz) - length = EncodeOcspRequestExtensions( + length = (word16)EncodeOcspRequestExtensions( &csr->request.ocsp, output + offset + OPAQUE16_LEN, OCSP_NONCE_EXT_SZ); @@ -2084,20 +2160,21 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!isRequest) { #ifndef NO_WOLFSSL_CLIENT TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; if (!csr) { /* look at context level */ - extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); - csr = extension ? extension->data : NULL; + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; if (!csr) return BUFFER_ERROR; /* unexpected extension */ /* enable extension at ssl level */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, - csr->status_type, csr->options, ssl->heap); + csr->status_type, csr->options, ssl->heap, + ssl->devId); if (ret != SSL_SUCCESS) return ret; @@ -2106,7 +2183,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* propagate nonce */ if (csr->request.ocsp.nonceSz) { OcspRequest* request = - TLSX_CSR_GetRequest(ssl->extensions); + (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); if (request) { XMEMCPY(request->nonce, csr->request.ocsp.nonce, @@ -2159,6 +2236,10 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; } break; + + /* unknown status type */ + default: + return 0; } /* if using status_request and already sending it, skip this one */ @@ -2169,7 +2250,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - 0, ssl->heap); + 0, ssl->heap, ssl->devId); if (ret != SSL_SUCCESS) return ret; /* throw error */ @@ -2185,7 +2266,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; int ret = 0; if (csr) { @@ -2215,7 +2297,8 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap) void* TLSX_CSR_GetRequest(TLSX* extensions) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; if (csr) { switch (csr->status_type) { @@ -2231,14 +2314,19 @@ void* TLSX_CSR_GetRequest(TLSX* extensions) int TLSX_CSR_ForceRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; if (csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + csr->request.ocsp.ssl = ssl; + #endif return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr->request.ocsp, NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2248,7 +2336,7 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, - byte options, void* heap) + byte options, void* heap, int devId) { CertificateStatusRequest* csr = NULL; int ret = 0; @@ -2271,11 +2359,13 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, heap) == 0) { -#else - if (wc_InitRng(&rng) == 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce, MAX_OCSP_NONCE_SZ) == 0) csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; @@ -2401,7 +2491,7 @@ static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, length = 0; if (csr2->request.ocsp[0].nonceSz) - length = EncodeOcspRequestExtensions( + length = (word16)EncodeOcspRequestExtensions( &csr2->request.ocsp[0], output + offset + OPAQUE16_LEN, OCSP_NONCE_EXT_SZ); @@ -2433,14 +2523,14 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!isRequest) { #ifndef NO_WOLFSSL_CLIENT TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data - : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; if (!csr2) { /* look at context level */ - extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2); - csr2 = extension ? extension->data : NULL; + csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; if (!csr2) return BUFFER_ERROR; /* unexpected extension */ @@ -2448,7 +2538,7 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* enable extension at ssl level */ for (; csr2; csr2 = csr2->next) { ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - csr2->status_type, csr2->options, ssl->heap); + csr2->status_type, csr2->options, ssl->heap, ssl->devId); if (ret != SSL_SUCCESS) return ret; @@ -2459,7 +2549,7 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* propagate nonce */ if (csr2->request.ocsp[0].nonceSz) { OcspRequest* request = - TLSX_CSR2_GetRequest(ssl->extensions, + (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, csr2->status_type, 0); if (request) { @@ -2474,7 +2564,6 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, break; } } - } ssl->status_request_v2 = 1; @@ -2548,7 +2637,7 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - status_type, 0, ssl->heap); + status_type, 0, ssl->heap, ssl->devId); if (ret != SSL_SUCCESS) return ret; /* throw error */ @@ -2567,7 +2656,8 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; int ret = 0; for (; csr2; csr2 = csr2->next) { @@ -2576,7 +2666,7 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, if (!isPeer || csr2->requests != 0) break; - /* followed by */ + FALL_THROUGH; /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: { if (csr2->requests < 1 + MAX_CHAIN_DEPTH) { @@ -2602,13 +2692,15 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, } } + (void)cert; return ret; } -void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; for (; csr2; csr2 = csr2->next) { if (csr2->status_type == status_type) { @@ -2618,8 +2710,8 @@ void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) case WOLFSSL_CSR2_OCSP_MULTI: /* requests are initialized in the reverse order */ - return index < csr2->requests - ? &csr2->request.ocsp[csr2->requests - index - 1] + return idx < csr2->requests + ? &csr2->request.ocsp[csr2->requests - idx - 1] : NULL; break; } @@ -2632,7 +2724,8 @@ void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; /* forces only the first one */ if (csr2) { @@ -2641,9 +2734,13 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + csr2->request.ocsp[0].ssl = ssl; + #endif return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr2->request.ocsp[0], NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2653,7 +2750,7 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, - byte options, void* heap) + byte options, void* heap, int devId) { TLSX* extension = NULL; CertificateStatusRequestItemV2* csr2 = NULL; @@ -2683,11 +2780,13 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, heap) == 0) { -#else - if (wc_InitRng(&rng) == 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce, MAX_OCSP_NONCE_SZ) == 0) csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ; @@ -2780,7 +2879,8 @@ static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) for (i = 0; i < ssl->suites->suiteSz; i+= 2) if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE) + ssl->suites->suites[i] == CHACHA_BYTE || + ssl->suites->suites[i] == TLS13_BYTE) return; /* turns semaphore on to avoid sending this extension. */ @@ -2856,18 +2956,46 @@ static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; } +#ifdef WOLFSSL_TLS13 +/* Searches the supported groups extension for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) +{ + TLSX* extension; + EllipticCurve* curve = NULL; + + if ((extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS)) == NULL) + return 0; + + for (curve = (EllipticCurve*)extension->data; curve; curve = curve->next) { + if (curve->name == name) + return 1; + } + return 0; +} +#endif /* WOLFSSL_TLS13 */ + int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { TLSX* extension = (first == ECC_BYTE || first == CHACHA_BYTE) ? TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) : NULL; EllipticCurve* curve = NULL; word32 oid = 0; + word32 defOid = 0; + word32 defSz = 80; /* Maximum known curve size is 66. */ + word32 nextOid = 0; + word32 nextSz = 80; /* Maximum known curve size is 66. */ + word32 currOid = ssl->ecdhCurveOID; + int ephmSuite = 0; word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ int sig = 0; /* validate signature */ int key = 0; /* validate key */ (void)oid; - (void)octets; if (!extension) return 1; /* no suite restriction */ @@ -2880,155 +3008,234 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { switch (curve->name) { #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP160R1: oid = ECC_SECP160R1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R1: + oid = ECC_SECP160R1_OID; + octets = 20; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_SECPR2 - case WOLFSSL_ECC_SECP160R2: oid = ECC_SECP160R2_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R2: + oid = ECC_SECP160R2_OID; + octets = 20; + break; #endif /* HAVE_ECC_SECPR2 */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP160K1: oid = ECC_SECP160K1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160K1: + oid = ECC_SECP160K1_OID; + octets = 20; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP192R1: oid = ECC_SECP192R1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192R1: + oid = ECC_SECP192R1_OID; + octets = 24; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP192K1: oid = ECC_SECP192K1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192K1: + oid = ECC_SECP192K1_OID; + octets = 24; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP224R1: oid = ECC_SECP224R1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224R1: + oid = ECC_SECP224R1_OID; + octets = 28; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP224K1: oid = ECC_SECP224K1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224K1: + oid = ECC_SECP224K1_OID; + octets = 28; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP256R1: oid = ECC_SECP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256R1: + oid = ECC_SECP256R1_OID; + octets = 32; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP256K1: oid = ECC_SECP256K1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256K1: + oid = ECC_SECP256K1_OID; + octets = 32; + break; #endif /* HAVE_ECC_KOBLITZ */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP256R1: oid = ECC_BRAINPOOLP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_BRAINPOOLP256R1: + oid = ECC_BRAINPOOLP256R1_OID; + octets = 32; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP384R1: oid = ECC_SECP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_SECP384R1: + oid = ECC_SECP384R1_OID; + octets = 48; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP384R1: oid = ECC_BRAINPOOLP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_BRAINPOOLP384R1: + oid = ECC_BRAINPOOLP384R1_OID; + octets = 48; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP512R1: oid = ECC_BRAINPOOLP512R1_OID; octets = 64; break; + case WOLFSSL_ECC_BRAINPOOLP512R1: + oid = ECC_BRAINPOOLP512R1_OID; + octets = 64; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP521R1: oid = ECC_SECP521R1_OID; octets = 66; break; + case WOLFSSL_ECC_SECP521R1: + oid = ECC_SECP521R1_OID; + octets = 66; + break; #endif /* !NO_ECC_SECP */ #endif default: continue; /* unsupported curve */ } + /* Set default Oid */ + if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) { + defOid = oid; + defSz = octets; + } + + if (currOid == 0 && ssl->eccTempKeySz == octets) + currOid = oid; + if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) { + nextOid = oid; + nextSz = octets; + } + if (first == ECC_BYTE) { - switch (second) { - /* ECDHE_ECDSA */ - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; - break; + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + sig |= ssl->pkCurveOID == oid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifdef WOLFSSL_STATIC_DH - /* ECDH_ECDSA */ - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - sig |= ssl->pkCurveOID == oid; - key |= ssl->pkCurveOID == oid; - break; + /* ECDH_ECDSA */ + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + sig |= ssl->pkCurveOID == oid; + key |= ssl->pkCurveOID == oid; + break; #endif /* WOLFSSL_STATIC_DH */ #ifndef NO_RSA - /* ECDHE_RSA */ - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - sig = 1; - key |= ssl->eccTempKeySz == octets; - break; + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifdef WOLFSSL_STATIC_DH - /* ECDH_RSA */ - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case TLS_ECDH_RSA_WITH_RC4_128_SHA: - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - sig = 1; - key |= ssl->pkCurveOID == oid; - break; + /* ECDH_RSA */ + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->pkCurveOID == oid; + break; #endif /* WOLFSSL_STATIC_DH */ #endif - default: - sig = 1; - key = 1; - break; - } + default: + sig = 1; + key = 1; + break; + } } /* ChaCha20-Poly1305 ECC cipher suites */ if (first == CHACHA_BYTE) { - switch (second) { - /* ECDHE_ECDSA */ - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : - case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; - break; + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig |= ssl->pkCurveOID == oid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifndef NO_RSA - /* ECDHE_RSA */ - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig = 1; - key |= ssl->eccTempKeySz == octets; - break; + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #endif - default: - sig = 1; - key = 1; - break; - } + default: + sig = 1; + key = 1; + break; + } } } + /* Choose the default if it is at the required strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) { + key = 1; + ssl->ecdhCurveOID = defOid; + } + /* Choose any curve at the required strength. */ + if (ssl->ecdhCurveOID == 0) { + key = 1; + ssl->ecdhCurveOID = currOid; + } + /* Choose the default if it is at the next highest strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == nextSz) + ssl->ecdhCurveOID = defOid; + /* Choose any curve at the next highest strength. */ + if (ssl->ecdhCurveOID == 0) + ssl->ecdhCurveOID = nextOid; + /* No curve and ephemeral ECC suite requires a matching curve. */ + if (ssl->ecdhCurveOID == 0 && ephmSuite) + key = 0; + return sig && key; } @@ -3036,7 +3243,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); + TLSX* extension; EllipticCurve* curve = NULL; int ret = 0; @@ -3046,6 +3253,7 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) if ((ret = TLSX_EllipticCurve_Append(&curve, name, heap)) != 0) return ret; + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); if (!extension) { if ((ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap)) != 0) { @@ -3289,10 +3497,12 @@ int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) #ifdef HAVE_SESSION_TICKET +#ifndef NO_WOLFSSL_CLIENT static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); - SessionTicket* ticket = extension ? extension->data : NULL; + SessionTicket* ticket = extension ? + (SessionTicket*)extension->data : NULL; if (ticket) { /* TODO validate ticket timeout here! */ @@ -3302,6 +3512,7 @@ static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) } } } +#endif /* NO_WOLFSSL_CLIENT */ static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) @@ -3336,7 +3547,9 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != 0) return BUFFER_ERROR; +#ifndef NO_WOLFSSL_CLIENT ssl->expect_session_ticket = 1; +#endif } #ifndef NO_WOLFSSL_SERVER else { @@ -3434,19 +3647,19 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) return SSL_SUCCESS; } -#define STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest -#define STK_GET_SIZE TLSX_SessionTicket_GetSize -#define STK_WRITE TLSX_SessionTicket_Write -#define STK_PARSE TLSX_SessionTicket_Parse -#define STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) +#define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest +#define WOLF_STK_GET_SIZE TLSX_SessionTicket_GetSize +#define WOLF_STK_WRITE TLSX_SessionTicket_Write +#define WOLF_STK_PARSE TLSX_SessionTicket_Parse +#define WOLF_STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) #else -#define STK_FREE(a, b) -#define STK_VALIDATE_REQUEST(a) -#define STK_GET_SIZE(a, b) 0 -#define STK_WRITE(a, b, c) 0 -#define STK_PARSE(a, b, c, d) 0 +#define WOLF_STK_FREE(a, b) +#define WOLF_STK_VALIDATE_REQUEST(a) +#define WOLF_STK_GET_SIZE(a, b) 0 +#define WOLF_STK_WRITE(a, b, c) 0 +#define WOLF_STK_PARSE(a, b, c, d) 0 #endif /* HAVE_SESSION_TICKET */ @@ -3454,10 +3667,12 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) /* Quantum-Safe-Hybrid */ /******************************************************************************/ -#ifdef HAVE_QSH +#if defined(HAVE_NTRU) && defined(HAVE_QSH) static WC_RNG* rng; static wolfSSL_Mutex* rngMutex; +#endif +#ifdef HAVE_QSH static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap) { QSHScheme* current; @@ -4045,87 +4260,2201 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, #endif /* HAVE_QSH */ /******************************************************************************/ -/* TLS Extensions Framework */ +/* Supported Versions */ /******************************************************************************/ -/** Finds an extension in the provided list. */ -TLSX* TLSX_Find(TLSX* list, TLSX_Type type) +#ifdef WOLFSSL_TLS13 +/* Return the size of the SupportedVersions extension's data. + * + * data The SSL/TLS object. + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SupportedVersions_GetSize(byte* data) { - TLSX* extension = list; + (void)data; - while (extension && extension->type != type) - extension = extension->next; + /* TLS v1.2 and TLS v1.3 */ + int cnt = 2; - return extension; +#ifndef NO_OLD_TLS + /* TLS v1 and TLS v1.1 */ + cnt += 2; +#endif + + return OPAQUE8_LEN + cnt * OPAQUE16_LEN; } -/** Releases all extensions in the provided list. */ -void TLSX_FreeAll(TLSX* list, void* heap) +/* Writes the SupportedVersions extension into the buffer. + * + * data The SSL/TLS object. + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SupportedVersions_Write(byte* data, byte* output) { - TLSX* extension; - - while ((extension = list)) { - list = extension->next; + WOLFSSL* ssl = (WOLFSSL*)data; + ProtocolVersion pv = ssl->ctx->method->version; + int i; + /* TLS v1.2 and TLS v1.3 */ + int cnt = 2; - switch (extension->type) { +#ifndef NO_OLD_TLS + /* TLS v1 and TLS v1.1 */ + cnt += 2; +#endif - case TLSX_SERVER_NAME: - SNI_FREE_ALL((SNI*)extension->data, heap); - break; + *(output++) = cnt * OPAQUE16_LEN; + for (i = 0; i < cnt; i++) { + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + if (pv.minor - i == TLSv1_3_MINOR) { + /* The TLS draft major number. */ + *(output++) = TLS_DRAFT_MAJOR; + /* Version of draft supported. */ + *(output++) = TLS_DRAFT_MINOR; + continue; + } - case TLSX_MAX_FRAGMENT_LENGTH: - MFL_FREE_ALL(extension->data, heap); - break; + *(output++) = pv.major; + *(output++) = pv.minor - i; + } - case TLSX_TRUNCATED_HMAC: - /* Nothing to do. */ - break; + return OPAQUE8_LEN + cnt * OPAQUE16_LEN; +} - case TLSX_SUPPORTED_GROUPS: - EC_FREE_ALL((EllipticCurve*)extension->data, heap); - break; +/* Parse the SupportedVersions extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, + word16 length) +{ + ProtocolVersion pv = ssl->ctx->method->version; + int i; + int ret = 0; + int len; - case TLSX_STATUS_REQUEST: - CSR_FREE_ALL(extension->data, heap); - break; + /* Must contain a length and at least one version. */ + if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1) + return BUFFER_ERROR; - case TLSX_STATUS_REQUEST_V2: - CSR2_FREE_ALL(extension->data, heap); - break; + len = *input; - case TLSX_RENEGOTIATION_INFO: - SCR_FREE_ALL(extension->data, heap); - break; + /* Protocol version array must fill rest of data. */ + if (length != OPAQUE8_LEN + len) + return BUFFER_ERROR; - case TLSX_SESSION_TICKET: - STK_FREE(extension->data, heap); - break; + input++; + + /* Find first match. */ + for (i = 0; i < len; i += OPAQUE16_LEN) { + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + if (input[i] == TLS_DRAFT_MAJOR && + input[i + OPAQUE8_LEN] == TLS_DRAFT_MINOR) { + ssl->version.minor = TLSv1_3_MINOR; + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + break; + } - case TLSX_QUANTUM_SAFE_HYBRID: - QSH_FREE_ALL((QSHScheme*)extension->data, heap); - break; + if (input[i] != pv.major) + continue; - case TLSX_APPLICATION_LAYER_PROTOCOL: - ALPN_FREE_ALL((ALPN*)extension->data, heap); - break; +#ifndef NO_OLD_TLS + if (input[i + OPAQUE8_LEN] == TLSv1_MINOR || + input[i + OPAQUE8_LEN] == TLSv1_1_MINOR) { + ssl->version.minor = input[i + OPAQUE8_LEN]; + break; + } +#endif + if (input[i + OPAQUE8_LEN] == TLSv1_2_MINOR) { + ssl->version.minor = input[i + OPAQUE8_LEN]; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + break; + } + if (input[i + OPAQUE8_LEN] == TLSv1_3_MINOR) { + ssl->version.minor = input[i + OPAQUE8_LEN]; + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + break; } - - XFREE(extension, heap, DYNAMIC_TYPE_TLSX); } - (void)heap; + return ret; } -/** Checks if the tls extensions are supported based on the protocol version. */ -int TLSX_SupportExtensions(WOLFSSL* ssl) { - return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR); +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap); } -/** Tells the buffered size of the extensions in a list. */ -static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) -{ +#define SV_GET_SIZE TLSX_SupportedVersions_GetSize +#define SV_WRITE TLSX_SupportedVersions_Write +#define SV_PARSE TLSX_SupportedVersions_Parse + +#else + +#define SV_GET_SIZE(a) 0 +#define SV_WRITE(a, b) 0 +#define SV_PARSE(a, b, c) 0 + +#endif /* WOLFSSL_TLS13 */ + +/******************************************************************************/ +/* Sugnature Algorithms */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Return the size of the SignatureAlgorithms extension's data. + * + * data Unused + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SignatureAlgorithms_GetSize(byte* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + int cnt = 0; + + (void)data; + +#ifndef NO_RSA + #ifndef NO_SHA1 + cnt++; + #endif + #ifndef NO_SHA256 + cnt++; + #endif + #ifdef HAVE_SHA384 + cnt++; + #endif + #ifdef HAVE_SHA512 + cnt++; + #endif + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_3(ssl->version)) { + #ifndef NO_SHA256 + cnt++; + #endif + #ifdef HAVE_SHA384 + cnt++; + #endif + #ifdef HAVE_SHA512 + cnt++; + #endif + } + #endif +#endif + +#ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + cnt++; + #endif + #endif + #if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + cnt++; + #endif + #endif + #if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + cnt++; + #endif + #endif +#endif + + return OPAQUE16_LEN + cnt * OPAQUE16_LEN; +} + +/* Writes the SignatureAlgorithms extension into the buffer. + * + * data Unused + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SignatureAlgorithms_Write(byte* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + int idx = OPAQUE16_LEN; + + +#ifndef NO_RSA + #ifndef NO_SHA1 + output[idx++] = 0x02; + output[idx++] = 0x01; + #endif + #ifndef NO_SHA256 + output[idx++] = 0x04; + output[idx++] = 0x01; + #endif + #ifdef HAVE_SHA384 + output[idx++] = 0x05; + output[idx++] = 0x01; + #endif + #ifdef HAVE_SHA512 + output[idx++] = 0x06; + output[idx++] = 0x01; + #endif + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_3(ssl->version)) { + #ifndef NO_SHA256 + output[idx++] = 0x08; + output[idx++] = 0x04; + #endif + #ifdef HAVE_SHA384 + output[idx++] = 0x08; + output[idx++] = 0x05; + #endif + #ifdef HAVE_SHA512 + output[idx++] = 0x08; + output[idx++] = 0x06; + #endif + } + #endif +#endif + +#ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + output[idx++] = 0x04; + output[idx++] = 0x03; + #endif + #endif + #if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + output[idx++] = 0x05; + output[idx++] = 0x03; + #endif + #endif + #if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + output[idx++] = 0x06; + output[idx++] = 0x03; + #endif + #endif +#endif + + output[0] = (idx - OPAQUE16_LEN) >> 8; + output[1] = idx - OPAQUE16_LEN; + + return idx; +} + +/* Parse the SignatureAlgorithms extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, + word16 length) +{ + int ret = 0; + word16 len; + + (void)ssl; + + /* Must contain a length and at least algorithm. */ + if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0) + return BUFFER_ERROR; + + ato16(input, &len); + + /* Algorithm array must fill rest of data. */ + if (length != OPAQUE16_LEN + len) + return BUFFER_ERROR; + + /* Ignore for now. */ + + return ret; +} + +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap); +} + +#define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize +#define SA_WRITE TLSX_SignatureAlgorithms_Write +#define SA_PARSE TLSX_SignatureAlgorithms_Parse + +#else + +#define SA_GET_SIZE(a) 0 +#define SA_WRITE(a, b) 0 +#define SA_PARSE(a, b, c) 0 + +#endif + +/******************************************************************************/ +/* Key Share */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +#ifndef NO_DH +/* Create a key share entry using named Diffie-Hellman parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; + byte* keyData; + void* key = NULL; + word32 keySz; + word32 dataSz; + const DhParams* params; + DhKey dhKey; + + /* TODO: [TLS13] The key size should come from wolfcrypt. */ + /* Pick the parameters from the named group. */ + switch (kse->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + keySz = 29; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + keySz = 34; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + keySz = 39; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + keySz = 46; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + keySz = 52; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* Allocate space for the public key. */ + dataSz = params->p_len; + keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData == NULL) { + ret = MEMORY_E; + goto end; + } + /* Allocate space for the private key. */ + key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_TLSX); + if (key == NULL) { + ret = MEMORY_E; + goto end; + } + + /* Set key */ + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) + goto end; + + /* Generate a new key pair. */ + ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, key, &keySz, keyData, &dataSz); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + if (params->p_len != dataSz) { + /* Pad the front of the key data with zeros. */ + XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); + XMEMSET(keyData, 0, params->p_len - dataSz); + } + + kse->ke = keyData; + kse->keLen = params->p_len; + kse->key = key; + kse->keyLen = keySz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public DH Key"); + WOLFSSL_BUFFER(keyData, params->p_len); +#endif + +end: + + wc_FreeDhKey(&dhKey); + + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_TLSX); + if (key != NULL) + XFREE(key, ssl->heap, DYNAMIC_TYPE_TLSX); + } + + return ret; +} +#endif + +#ifndef NO_ECC +/* Create a key share entry using named elliptic curve parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; + byte* keyData = NULL; + word32 dataSize; + word32 keySize; + ecc_key* eccKey = NULL; + word16 curveId; + + /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ + /* Translate named group to a curve id. */ + switch (kse->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + keySize = 32; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + keySize = 48; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + keySize = 66; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + { + curve25519_key* key; + /* Allocate an ECC key to hold private key. */ + key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_TLSX); + if (key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + dataSize = keySize = 32; + + /* Make an ECC key. */ + ret = wc_curve25519_init(key); + if (ret != 0) + goto end; + ret = wc_curve25519_make_key(ssl->rng, keySize, key); + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_curve25519_export_public_ex(key, keyData, &dataSize, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->ke = keyData; + kse->keLen = dataSize; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + + goto end; + } + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + dataSize = keySize = 56; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + /* Allocate an ECC key to hold private key. */ + eccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_TLSX); + if (eccKey == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + /* Make an ECC key. */ + ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); + if (ret != 0) + goto end; + ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->ke = keyData; + kse->keLen = dataSize; + kse->key = eccKey; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (eccKey != NULL) + XFREE(eccKey, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_TLSX); + } + return ret; +} +#endif /* !NO_ECC */ + +/* Generate a secret/key using the key share entry. + * + * ssl The SSL/TLS object. + * kse The key share entry holding peer data. + */ +static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) +{ + /* Named FFHE groups have a bit set to identify them. */ + if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK) + return TLSX_KeyShare_GenDhKey(ssl, kse); + return TLSX_KeyShare_GenEccKey(ssl, kse); +} + +/* Free the key share dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) +{ + KeyShareEntry* current; + + while ((current = list) != NULL) { + list = current->next; + XFREE(current->key, heap, DYNAMIC_TYPE_TLSX); + XFREE(current->ke, heap, DYNAMIC_TYPE_TLSX); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded key share extension. + * + * list The linked list of key share extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded key share extension. + */ +static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) +{ + int len = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + /* The named group the server wants to use. */ + if (msgType == hello_retry_request) + return OPAQUE16_LEN; + + /* List of key exchange groups. */ + if (isRequest) + len += OPAQUE16_LEN; + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + len += OPAQUE16_LEN + OPAQUE16_LEN + current->keLen; + } + + return len; +} + +/* Writes the key share extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, + byte msgType) +{ + word16 i = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + if (msgType == hello_retry_request) { + c16toa(list->group, output); + return OPAQUE16_LEN; + } + + /* ClientHello has a list but ServerHello is only the chosen. */ + if (isRequest) + i += OPAQUE16_LEN; + + /* Write out all in the list. */ + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + c16toa(current->group, &output[i]); + i += KE_GROUP_LEN; + c16toa(current->keLen, &output[i]); + i += OPAQUE16_LEN; + XMEMCPY(&output[i], current->ke, current->keLen); + i += current->keLen; + } + /* Write the length of the list if required. */ + if (isRequest) + c16toa(i - OPAQUE16_LEN, output); + + return i; +} + +/* Process the DH key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ +#ifndef NO_DH + int ret; + const DhParams* params; + word16 i; + byte b; + DhKey dhKey; + + switch (keyShareEntry->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + default: + return PEER_KEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer DH Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + if (params->p_len != keyShareEntry->keLen) + return BUFFER_ERROR; + + /* TODO: [TLS13] move this check down into wolfcrypt. */ + /* Check that public DH key is not 0 or 1. */ + b = 0; + for (i = 0; i < params->p_len - 1; i++) + b |= keyShareEntry->ke[i]; + if (b == 0 && (keyShareEntry->ke[i] == 0x00 || + keyShareEntry->ke[i] == 0x01)) { + return PEER_KEY_ERROR; + } + /* Check that public DH key is not mod, mod + 1 or mod - 1. */ + b = 0; + for (i = 0; i < params->p_len - 1; i++) + b |= params->p[i] ^ keyShareEntry->ke[i]; + if (b == 0 && (params->p[i] == keyShareEntry->ke[i] || + params->p[i] - 1 == keyShareEntry->ke[i] || + params->p[i] + 1 == keyShareEntry->ke[i])) { + return PEER_KEY_ERROR; + } + + ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* Set key */ + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) { + wc_FreeDhKey(&dhKey); + return ret; + } + + /* Derive secret from private key and peer's public key. */ + ret = wc_DhAgree(&dhKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + keyShareEntry->key, keyShareEntry->keyLen, + keyShareEntry->ke, keyShareEntry->keLen); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + + wc_FreeDhKey(&dhKey); + + return ret; +#else + return PEER_KEY_ERROR; +#endif +} + +/* Process the ECC key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ +#ifndef NO_ECC + int ret; + int curveId; + ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* find supported curve */ + switch (keyShareEntry->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + { + curve25519_key* key = (curve25519_key*)keyShareEntry->key; + curve25519_key* peerEccKey; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + peerEccKey = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_TLSX); + if (peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve25519_init(peerEccKey); + if (ret != 0) + return ret; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_curve25519_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerEccKey, + EC25519_LITTLE_ENDIAN) != 0) { + return ECC_PEERKEY_ERROR; + } + + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ret = wc_curve25519_shared_secret_ex(key, peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + EC25519_LITTLE_ENDIAN); + wc_curve25519_free(peerEccKey); + XFREE(peerEccKey, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; + } + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + break; + #endif + default: + /* unsupported curve */ + return ECC_PEERKEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, + ssl->peerEccKey, curveId) != 0) { + return ECC_PEERKEY_ERROR; + } + + ssl->arrays->preMasterSz = ENCRYPT_LEN; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); + } while (ret == WC_PENDING_E); + +#if 0 + /* TODO: Switch to support async here and use: */ + ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey, + keyShareEntry->ke, &keyShareEntry->keLen, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + ssl->options.side, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); +#endif + + return ret; +#else + return PEER_KEY_ERROR; +#endif +} + +/* Process the key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_SESSION_TICKET + ssl->session.namedGroup = keyShareEntry->group; +#endif + /* Use Key Share Data from server. */ + if (keyShareEntry->group & NAMED_DH_MASK) + ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry); + else + ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("KE Secret"); + WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); +#endif + + return ret; +} + +/* Parse an entry of the KeyShare extension. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * kse The new key share entry object. + * returns a positive number to indicate amount of data parsed and a negative + * number on error. + */ +static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length, + KeyShareEntry **kse) +{ + int ret; + word16 group; + word16 keLen; + int offset = 0; + byte* ke; + + if (length < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + /* Named group */ + ato16(&input[offset], &group); + offset += OPAQUE16_LEN; + /* Key exchange data - public key. */ + ato16(&input[offset], &keLen); + offset += OPAQUE16_LEN; + if (keLen < 1 || keLen > length - offset) + return BUFFER_ERROR; + + /* Store a copy in the key share object. */ + ke = XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_TLSX); + if (ke == NULL) + return MEMORY_E; + XMEMCPY(ke, &input[offset], keLen); + + /* Populate a key share object in the extension. */ + ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse); + if (ret != 0) + return ret; + + /* Total length of the parsed data. */ + return offset + keLen; +} + +/* Searches the groups sent for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group) +{ + TLSX* extension; + KeyShareEntry* list; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return 0; + + list = (KeyShareEntry*)extension->data; + while (list != NULL) { + if (list->group == group) { + return 1; + } + list = list->next; + } + + return 0; +} + +/* Parse the KeyShare extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + KeyShareEntry *keyShareEntry; + + if (msgType == client_hello) { + int offset = 0; + word16 len; + + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* ClientHello contains zero or more key share entries. */ + ato16(input, &len); + if (len != length - OPAQUE16_LEN) + return BUFFER_ERROR; + offset += OPAQUE16_LEN; + + while (offset < length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length, + &keyShareEntry); + if (ret < 0) + return ret; + + offset += ret; + } + + ret = 0; + } + else if (msgType == server_hello) { + int len; + + /* ServerHello contains one key share entry. */ + len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); + if (len != length) + return BUFFER_ERROR; + + /* Not in list sent if there isn't a private key. */ + if (keyShareEntry->key == NULL) + return BAD_KEY_SHARE_DATA; + + /* Process the entry to calculate the secret. */ + ret = TLSX_KeyShare_Process(ssl, keyShareEntry); + } + else if (msgType == hello_retry_request) { + word16 group; + + if (length != OPAQUE16_LEN) + return BUFFER_ERROR; + + /* The data is the named group the server wants to use. */ + ato16(input, &group); + + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Check if the group was sent. */ + if (TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Try to use the server's group. */ + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + } + else { + /* Not a message type that is allowed to have this extension. */ + return SANITY_MSG_E; + } + + return ret; +} + +/* Create a new key share entry and put it into the list. + * + * list The linked list of key share entries. + * group The named group. + * heap The memory to allocate with. + * keyShareEntry The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap, + KeyShareEntry** keyShareEntry) +{ + KeyShareEntry* kse; + + kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap, + DYNAMIC_TYPE_TLSX); + if (kse == NULL) + return MEMORY_E; + + XMEMSET(kse, 0, sizeof(*kse)); + kse->group = group; + + /* Add it to the back and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = kse; + *keyShareEntry = kse; + + return 0; +} + +/* Use the data to create a new key share object in the extensions. + * + * ssl The SSL/TLS object. + * group The named group. + * len The length of the public key data. + * data The public key data. + * kse The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, + KeyShareEntry **kse) +{ + int ret = 0; + TLSX* extension; + KeyShareEntry* keyShareEntry = NULL; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return MEMORY_E; + } + + /* Try to find the key share entry with this group. */ + keyShareEntry = (KeyShareEntry*)extension->data; + while (keyShareEntry != NULL) { + if (keyShareEntry->group == group) + break; + keyShareEntry = keyShareEntry->next; + } + + /* Create a new key share entry if not found. */ + if (keyShareEntry == NULL) { + ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group, + ssl->heap, &keyShareEntry); + if (ret != 0) + return ret; + } + + if (data != NULL) { + /* Keep the public key data and free when finished. */ + if (keyShareEntry->ke != NULL) + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_TLSX); + keyShareEntry->ke = data; + keyShareEntry->keLen = len; + } + else { + /* Generate a key pair. */ + ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry); + if (ret != 0) + return ret; + } + + if (kse != NULL) + *kse = keyShareEntry; + + return 0; +} + +/* Set an empty Key Share extension. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Empty(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + } + else if (extension->data != NULL) { + TLSX_KeyShare_FreeAll(extension->data, ssl->heap); + extension->data = NULL; + } + + return ret; +} + +/* Returns whether this group is supported. + * + * namedGroup The named group to check. + * returns 1 when supported or 0 otherwise. + */ +static int TLSX_KeyShare_IsSupported(int namedGroup) +{ + switch (namedGroup) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + break; + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + break; + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + break; + #endif + default: + return 0; + } + + return 1; +} + +/* Set a key share that is supported by the client into extensions. + * + * ssl The SSL/TLS object. + * returns BAD_KEY_SHARE_DATA if no supported group has a key share, + * 0 if a supported group has a key share and other values indicate an error. + */ +static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) +{ + int ret; + TLSX* extension; + EllipticCurve* curve = NULL; + + /* Use SupportedGroup's order. */ + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) + curve = (EllipticCurve*)extension->data; + for (; curve != NULL; curve = curve->next) { + if (TLSX_KeyShare_IsSupported(curve->name) && + !TLSX_KeyShare_Find(ssl, curve->name)) { + break; + } + } + if (curve == NULL) + return BAD_KEY_SHARE_DATA; + + /* Delete the old key share data list. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) { + TLSX_KeyShare_FreeAll(extension->data, ssl->heap); + extension->data = NULL; + } + + /* Add in the chosen group. */ + ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); + if (ret != 0) + return ret; + + /* Set extension to be in reponse. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension->resp = 1; + + return 0; +} + +/* Establish the secret based on the key shares received from the client. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Establish(WOLFSSL *ssl) +{ + int ret; + TLSX* extension; + KeyShareEntry* clientKSE = NULL; + KeyShareEntry* serverKSE; + KeyShareEntry* list = NULL; + byte* ke; + word16 keLen; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) + list = (KeyShareEntry*)extension->data; + + /* TODO: [TLS13] Server's preference and sending back SupportedGroups */ + /* Use client's preference. */ + for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { + /* Check consistency now - extensions in any order. */ + if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group)) + return BAD_KEY_SHARE_DATA; + + /* Check if server supports group. */ + if (TLSX_KeyShare_IsSupported(clientKSE->group)) + break; + } + /* No supported group found - send HelloRetryRequest. */ + if (clientKSE == NULL) { + ret = TLSX_KeyShare_SetSupported(ssl); + /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + if (ret == 0) + return KEY_SHARE_ERROR; + return ret; + } + + list = NULL; + /* Generate a new key pair. */ + ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE); + if (ret != 0) + return ret; + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + if (ret != 0) + return ret; + + /* Move private key to client entry. */ + if (clientKSE->key != NULL) + XFREE(clientKSE->key, ssl->heap, DYNAMIC_TYPE_TLSX); + clientKSE->key = serverKSE->key; + serverKSE->key = NULL; + clientKSE->keyLen = serverKSE->keyLen; + + /* Calculate secret. */ + ret = TLSX_KeyShare_Process(ssl, clientKSE); + if (ret != 0) + return ret; + + /* Swap public keys for sending to client. */ + ke = serverKSE->ke; + keLen = serverKSE->keLen; + serverKSE->ke = clientKSE->ke; + serverKSE->keLen = clientKSE->keLen; + clientKSE->ke = ke; + clientKSE->keLen = keLen; + + extension->resp = 1; + + /* Dispose of temporary server extension. */ + TLSX_KeyShare_FreeAll(list, ssl->heap); + + return 0; +} + +#define KS_FREE_ALL TLSX_KeyShare_FreeAll +#define KS_GET_SIZE TLSX_KeyShare_GetSize +#define KS_WRITE TLSX_KeyShare_Write +#define KS_PARSE TLSX_KeyShare_Parse + +#else + +#define KS_FREE_ALL(a, b) +#define KS_GET_SIZE(a, b) 0 +#define KS_WRITE(a, b, c) 0 +#define KS_PARSE(a, b, c, d) 0 + +#endif /* WOLFSSL_TLS13 */ + +/******************************************************************************/ +/* Pre-Shared Key */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* Free the pre-shared key dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap) +{ + PreSharedKey* current; + + while ((current = list) != NULL) { + list = current->next; + XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded pre shared key extension. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +static word16 TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType) +{ + if (msgType == client_hello) { + /* Length of identities + Length of binders. */ + word16 len = OPAQUE16_LEN + OPAQUE16_LEN; + while (list != NULL) { + /* Each entry has: identity, ticket age and binder. */ + len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN + + OPAQUE8_LEN + list->binderLen; + list = list->next; + } + return len; + } + + if (msgType == server_hello) { + return OPAQUE16_LEN; + } + + return 0; +} + +/* The number of bytes to be written for the binders. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType) +{ + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Length of all binders. */ + len = OPAQUE16_LEN; + while (list != NULL) { + len += OPAQUE8_LEN + list->binderLen; + list = list->next; + } + + return len; +} + +/* Writes the pre-shared key extension into the output buffer - binders only. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, + byte msgType) +{ + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Skip length of all binders. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Binder data length. */ + output[idx++] = current->binderLen; + /* Binder data. */ + XMEMCPY(output + idx, current->binder, current->binderLen); + idx += current->binderLen; + + current = current->next; + } + /* Length of the binders. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + return idx; +} + + +/* Writes the pre-shared key extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, + byte msgType) +{ + if (msgType == client_hello) { + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + /* Write identites only. Binders after HMACing over this. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Identity length */ + c16toa(current->identityLen, output + idx); + idx += OPAQUE16_LEN; + /* Identity data */ + XMEMCPY(output + idx, current->identity, current->identityLen); + idx += current->identityLen; + + /* Obfuscated ticket age. */ + c32toa(current->ticketAge, output + idx); + idx += OPAQUE32_LEN; + + current = current->next; + } + /* Length of the identites. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + /* Don't include binders here. + * The binders are based on the hash of all the ClientHello data up to + * and include the identities written above. + */ + idx += TLSX_PreSharedKey_GetSizeBinders(list, msgType); + + return idx; + } + + if (msgType == server_hello) { + word16 i; + + /* Find the index of the chosen identity. */ + for (i=0; list != NULL && !list->chosen; i++) + list = list->next; + if (list == NULL) + return BUILD_MSG_ERROR; + + /* The index of the identity chosen by the server from the list supplied + * by the client. + */ + c16toa(i, output); + return OPAQUE16_LEN; + } + + return 0; +} + +/* Parse the pre-shared key extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + TLSX* extension; + PreSharedKey* list; + + if (msgType == client_hello) { + int ret; + word16 len; + word16 idx = 0; + + /* Length of identities and of binders. */ + if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identities. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_ID_LEN || length - idx < len) + return BUFFER_E; + + /* Create a pre-shared key object for each identity. */ + while (len > 0) { + byte* identity; + word16 identityLen; + word32 age; + + if (len < OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identity. */ + ato16(input + idx, &identityLen); + idx += OPAQUE16_LEN; + if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN) + return BUFFER_E; + /* Cache identity pointer. */ + identity = input + idx; + idx += identityLen; + /* Ticket age. */ + ato32(input + idx, &age); + idx += OPAQUE32_LEN; + + ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, 0, 1, + NULL); + if (ret != 0) + return ret; + + /* Done with this identity. */ + len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN; + } + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Length of binders. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_BINDERS_LEN || length - idx < len) + return BUFFER_E; + + /* Set binder for each identity. */ + while (list != NULL && len > 0) { + /* Length of binder */ + list->binderLen = input[idx++]; + if (list->binderLen < SHA256_DIGEST_SIZE || + list->binderLen > MAX_DIGEST_SIZE) + return BUFFER_E; + if (len < OPAQUE8_LEN + list->binderLen) + return BUFFER_E; + + /* Copy binder into static buffer. */ + XMEMCPY(list->binder, input + idx, list->binderLen); + idx += list->binderLen; + + /* Done with binder entry. */ + len -= OPAQUE8_LEN + list->binderLen; + + /* Next identity. */ + list = list->next; + } + if (list != NULL || len != 0) + return BUFFER_E; + + return 0; + } + + if (msgType == server_hello) { + word16 idx; + + /* Index of identity chosen by server. */ + if (length != OPAQUE16_LEN) + return BUFFER_E; + ato16(input, &idx); + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Mark the identity as chosen. */ + for (; list != NULL && idx > 0; idx--) + list = list->next; + if (list == NULL) + return PSK_KEY_ERROR; + list->chosen = 1; + + if (list->resumption) { + /* Check that the session's details are the same as the server's. */ + if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || + ssl->options.cipherSuite != ssl->session.cipherSuite || + ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor ) { + return PSK_KEY_ERROR; + } + } + /* TODO: [TLS13] More checks of consistency. + * the "key_share", and "signature_algorithms" extensions are + * consistent with the indicated ke_modes and auth_modes values + */ + + return 0; + } + + return SANITY_MSG_E; +} + +/* Create a new pre-shared key and put it into the list. + * + * list The linked list of pre-shared key. + * identity The identity. + * len The length of the identity data. + * heap The memory to allocate with. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity, + word16 len, void *heap, + PreSharedKey** preSharedKey) +{ + PreSharedKey* psk; + + psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX); + if (psk == NULL) + return MEMORY_E; + XMEMSET(psk, 0, sizeof(*psk)); + + /* Make a copy of the identity data. */ + psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX); + if (psk->identity == NULL) { + XFREE(psk, heap, DYNAMIC_TYPE_TLSX); + return MEMORY_E; + } + XMEMCPY(psk->identity, identity, len); + psk->identityLen = len; + + /* Add it to the end and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = psk; + *preSharedKey = psk; + + return 0; +} + +static INLINE byte GetHmacLength(int hmac) +{ + switch (hmac) { + #ifndef NO_SHA256 + case sha256_mac: + return SHA256_DIGEST_SIZE; + #endif + #ifndef NO_SHA384 + case sha384_mac: + return SHA384_DIGEST_SIZE; + #endif + #ifndef NO_SHA512 + case sha512_mac: + return SHA512_DIGEST_SIZE; + #endif + } + return 0; +} + +/* Use the data to create a new pre-shared key object in the extensions. + * + * ssl The SSL/TLS object. + * identity The identity. + * len The length of the identity data. + * age The age of the identity. + * hmac The HMAC algorithm. + * resumption The PSK is for resumption of a session. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age, + byte hmac, byte resumption, + PreSharedKey **preSharedKey) +{ + int ret = 0; + TLSX* extension; + PreSharedKey* psk = NULL; + + /* Find the pre-shared key extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) { + /* Push new pre-shared key extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return MEMORY_E; + } + + /* Try to find the pre-shared key with this identity. */ + psk = (PreSharedKey*)extension->data; + while (psk != NULL) { + if ((psk->identityLen == len) && + (XMEMCMP(psk->identity, identity, len) == 0)) { + break; + } + psk = psk->next; + } + + /* Create a new pre-shared key object if not found. */ + if (psk == NULL) { + ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity, + len, ssl->heap, &psk); + if (ret != 0) + return ret; + } + + /* Update/set age and HMAC algorithm. */ + psk->ticketAge = age; + psk->hmac = hmac; + psk->resumption = resumption; + psk->binderLen = GetHmacLength(psk->hmac); + + if (preSharedKey != NULL) + *preSharedKey = psk; + + return 0; +} + +#define PSK_FREE_ALL TLSX_PreSharedKey_FreeAll +#define PSK_GET_SIZE TLSX_PreSharedKey_GetSize +#define PSK_WRITE TLSX_PreSharedKey_Write +#define PSK_PARSE TLSX_PreSharedKey_Parse + +#else + +#define PSK_FREE_ALL(a, b) +#define PSK_GET_SIZE(a, b) 0 +#define PSK_WRITE(a, b, c) 0 +#define PSK_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* PSK Key Exchange Modes */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) +/* Get the size of the encoded PSK KE modes extension. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded key share extension. + */ +static word16 TLSX_PskKeModes_GetSize(byte modes, byte msgType) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + word16 len = OPAQUE8_LEN; + /* Check whether each possible mode is to be written. */ + if (modes & (1 << PSK_KE)) + len += OPAQUE8_LEN; + if (modes & (1 << PSK_DHE_KE)) + len += OPAQUE8_LEN; + return len; + } + + return SANITY_MSG_E; +} + +/* Writes the PSK KE modes extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = OPAQUE8_LEN; + + /* Write out each possible mode. */ + if (modes & (1 << PSK_KE)) + output[idx++] = PSK_KE; + if (modes & (1 << PSK_DHE_KE)) + output[idx++] = PSK_DHE_KE; + /* Write out length of mode list. */ + output[0] = idx - OPAQUE8_LEN; + + return idx; + } + + return SANITY_MSG_E; +} + +/* Parse the PSK KE modes extension. + * Only in ClientHello. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = 0; + int len; + byte modes = 0; + + /* Ensure length byte exists. */ + if (length < OPAQUE8_LEN) + return BUFFER_E; + + /* Get length of mode list and ensure that is the only data. */ + len = input[0]; + if (length - OPAQUE8_LEN != len) + return BUFFER_E; + + idx = OPAQUE8_LEN; + /* Set a bit for each recognized modes. */ + while (len > 0) { + /* Ignore unrecognized modes. */ + if (input[idx] <= PSK_DHE_KE) + modes |= 1 << input[idx]; + idx++; + len--; + } + + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + + return 0; + } + + return SANITY_MSG_E; +} + +/* Use the data to create a new PSK Key Exchange Modes object in the extensions. + * + * ssl The SSL/TLS object. + * modes The PSK key exchange modes. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes) +{ + int ret = 0; + TLSX* extension; + + /* Find the PSK key exchange modes extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) { + /* Push new PSK key exchange modes extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL, + ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) + return MEMORY_E; + } + + extension->val = modes; + + return 0; +} + +#define PKM_GET_SIZE TLSX_PskKeModes_GetSize +#define PKM_WRITE TLSX_PskKeModes_Write +#define PKM_PARSE TLSX_PskKeModes_Parse + +#else + +#define PKM_GET_SIZE(a, b) 0 +#define PKM_WRITE(a, b, c) 0 +#define PKM_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* TLS Extensions Framework */ +/******************************************************************************/ + +/** Finds an extension in the provided list. */ +TLSX* TLSX_Find(TLSX* list, TLSX_Type type) +{ + TLSX* extension = list; + + while (extension && extension->type != type) + extension = extension->next; + + return extension; +} + +/** Releases all extensions in the provided list. */ +void TLSX_FreeAll(TLSX* list, void* heap) +{ TLSX* extension; + + while ((extension = list)) { + list = extension->next; + + switch (extension->type) { + + case TLSX_SERVER_NAME: + SNI_FREE_ALL((SNI*)extension->data, heap); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + MFL_FREE_ALL(extension->data, heap); + break; + + case TLSX_TRUNCATED_HMAC: + /* Nothing to do. */ + break; + + case TLSX_SUPPORTED_GROUPS: + EC_FREE_ALL((EllipticCurve*)extension->data, heap); + break; + + case TLSX_STATUS_REQUEST: + CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap); + break; + + case TLSX_STATUS_REQUEST_V2: + CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data, + heap); + break; + + case TLSX_RENEGOTIATION_INFO: + SCR_FREE_ALL(extension->data, heap); + break; + + case TLSX_SESSION_TICKET: + WOLF_STK_FREE(extension->data, heap); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + QSH_FREE_ALL((QSHScheme*)extension->data, heap); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + ALPN_FREE_ALL((ALPN*)extension->data, heap); + break; + + case TLSX_SIGNATURE_ALGORITHMS: + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + break; + + case TLSX_KEY_SHARE: + KS_FREE_ALL((KeyShareEntry*)extension->data, heap); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + PSK_FREE_ALL((PreSharedKey*)extension->data, heap); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + break; + #endif +#endif + } + + XFREE(extension, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/** Checks if the tls extensions are supported based on the protocol version. */ +int TLSX_SupportExtensions(WOLFSSL* ssl) { + return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR); +} + +/** Tells the buffered size of the extensions in a list. */ +static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) +{ + TLSX* extension; word16 length = 0; + byte isRequest = (msgType == client_hello); while ((extension = list)) { list = extension->next; @@ -4163,19 +6492,24 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) break; case TLSX_STATUS_REQUEST: - length += CSR_GET_SIZE(extension->data, isRequest); + length += CSR_GET_SIZE( + (CertificateStatusRequest*)extension->data, isRequest); break; case TLSX_STATUS_REQUEST_V2: - length += CSR2_GET_SIZE(extension->data, isRequest); + length += CSR2_GET_SIZE( + (CertificateStatusRequestItemV2*)extension->data, + isRequest); break; case TLSX_RENEGOTIATION_INFO: - length += SCR_GET_SIZE(extension->data, isRequest); + length += SCR_GET_SIZE((SecureRenegotiation*)extension->data, + isRequest); break; case TLSX_SESSION_TICKET: - length += STK_GET_SIZE(extension->data, isRequest); + length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data, + isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: @@ -4186,6 +6520,31 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) length += ALPN_GET_SIZE((ALPN*)extension->data); break; + case TLSX_SIGNATURE_ALGORITHMS: +#ifdef WOLFSSL_TLS13 + length += SA_GET_SIZE(extension->data); +#endif + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + length += SV_GET_SIZE(extension->data); + break; + + case TLSX_KEY_SHARE: + length += KS_GET_SIZE(extension->data, msgType); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + length += PSK_GET_SIZE(extension->data, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + length += PKM_GET_SIZE(extension->val, msgType); + break; + #endif +#endif } /* marks the extension as processed so ctx level */ @@ -4198,11 +6557,12 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) /** Writes the extensions of a list in a buffer. */ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, - byte isRequest) + byte msgType) { TLSX* extension; word16 offset = 0; word16 length_offset = 0; + byte isRequest = (msgType == client_hello); while ((extension = list)) { list = extension->next; @@ -4223,44 +6583,55 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, /* extension data should be written internally. */ switch (extension->type) { case TLSX_SERVER_NAME: - if (isRequest) + if (isRequest) { + WOLFSSL_MSG("SNI extension to write"); offset += SNI_WRITE((SNI*)extension->data, output + offset); + } break; case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension to write"); offset += MFL_WRITE((byte*)extension->data, output + offset); break; case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension to write"); /* always empty. */ break; case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Elliptic Curves extension to write"); offset += EC_WRITE((EllipticCurve*)extension->data, output + offset); break; case TLSX_STATUS_REQUEST: - offset += CSR_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Certificate Status Request extension to write"); + offset += CSR_WRITE((CertificateStatusRequest*)extension->data, + output + offset, isRequest); break; case TLSX_STATUS_REQUEST_V2: - offset += CSR2_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Certificate Status Request v2 extension to write"); + offset += CSR2_WRITE( + (CertificateStatusRequestItemV2*)extension->data, + output + offset, isRequest); break; case TLSX_RENEGOTIATION_INFO: - offset += SCR_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Secure Renegotiation extension to write"); + offset += SCR_WRITE((SecureRenegotiation*)extension->data, + output + offset, isRequest); break; case TLSX_SESSION_TICKET: - offset += STK_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Session Ticket extension to write"); + offset += WOLF_STK_WRITE((SessionTicket*)extension->data, + output + offset, isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write"); if (isRequest) { offset += QSH_WRITE((QSHScheme*)extension->data, output + offset); } @@ -4269,8 +6640,40 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, break; case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension to write"); offset += ALPN_WRITE((ALPN*)extension->data, output + offset); break; + + case TLSX_SIGNATURE_ALGORITHMS: +#ifdef WOLFSSL_TLS13 + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SA_WRITE(extension->data, output + offset); +#endif + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension to write"); + offset += SV_WRITE(extension->data, output + offset); + break; + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension to write"); + offset += KS_WRITE(extension->data, output + offset, msgType); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension to write"); + offset += PSK_WRITE(extension->data, output + offset, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); + offset += PKM_WRITE(extension->val, output + offset, msgType); + break; + #endif +#endif } /* writes extension data length. */ @@ -4322,6 +6725,8 @@ static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) { int ret; + (void)ssl; + switch (type) { #ifdef HAVE_NTRU case WOLFSSL_NTRU_EESS439: @@ -4370,10 +6775,11 @@ static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key) } -#ifdef HAVE_NTRU +#if defined(HAVE_NTRU) || defined(HAVE_QSH) int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) { - int ret; + int ret = -1; +#ifdef HAVE_NTRU int ntruType; /* variable declarations for NTRU*/ @@ -4436,6 +6842,10 @@ int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) temp->next = NULL; TLSX_AddQSHKey(&ssl->QSH_Key, temp); +#endif + + (void)ssl; + (void)type; return ret; } @@ -4470,95 +6880,304 @@ static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) } #endif /* HAVE_QSH */ - int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) { + int ret = 0; byte* public_key = NULL; word16 public_key_len = 0; - #ifdef HAVE_QSH - TLSX* extension; - QSHScheme* qsh; - QSHScheme* next; - #endif - int ret = 0; +#ifdef HAVE_QSH + TLSX* extension; + QSHScheme* qsh; + QSHScheme* next; - #ifdef HAVE_QSH - /* add supported QSHSchemes */ - WOLFSSL_MSG("Adding supported QSH Schemes"); + /* add supported QSHSchemes */ + WOLFSSL_MSG("Adding supported QSH Schemes"); +#endif - /* server will add extension depending on whats parsed from client */ - if (!isServer) { + /* server will add extension depending on whats parsed from client */ + if (!isServer) { +#ifdef HAVE_QSH + /* test if user has set a specific scheme already */ + if (!ssl->user_set_QSHSchemes) { + if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } - /* test if user has set a specific scheme already */ - if (!ssl->user_set_QSHSchemes) { - if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { - if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { - WOLFSSL_MSG("Error creating ntru keys"); - return ret; - } - if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { - WOLFSSL_MSG("Error creating ntru keys"); - return ret; - } - if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { - WOLFSSL_MSG("Error creating ntru keys"); - return ret; - } + /* add NTRU 256 */ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS743); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, + public_key, public_key_len, ssl->heap) + != SSL_SUCCESS) + ret = -1; - /* add NTRU 256 */ + /* add NTRU 196 */ + if (ssl->sendQSHKeys) { public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, WOLFSSL_NTRU_EESS743); - } - if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, - public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) - ret = -1; + &public_key_len, WOLFSSL_NTRU_EESS593); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, + public_key, public_key_len, ssl->heap) + != SSL_SUCCESS) + ret = -1; - /* add NTRU 196 */ - if (ssl->sendQSHKeys) { - public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, WOLFSSL_NTRU_EESS593); - } - if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, - public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) - ret = -1; + /* add NTRU 128 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS439); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, + public_key, public_key_len, ssl->heap) + != SSL_SUCCESS) + ret = -1; + } + else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + /* for each scheme make a client key */ + extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (extension) { + qsh = (QSHScheme*)extension->data; + + while (qsh) { + if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) + return ret; - /* add NTRU 128 */ - if (ssl->sendQSHKeys) { + /* get next now because qsh could be freed */ + next = qsh->next; + + /* find the public key created and add to extension*/ public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, WOLFSSL_NTRU_EESS439); + &public_key_len, qsh->name); + if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, + public_key, public_key_len, + ssl->heap) != SSL_SUCCESS) + ret = -1; + qsh = next; } - if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, - public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) - ret = -1; } - else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { - /* for each scheme make a client key */ - extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); - if (extension) { - qsh = (QSHScheme*)extension->data; - - while (qsh) { - if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) - return ret; - - /* get next now because qsh could be freed */ - next = qsh->next; - - /* find the public key created and add to extension*/ - public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, qsh->name); - if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, - public_key, public_key_len, - ssl->heap) != SSL_SUCCESS) - ret = -1; - qsh = next; - } - } + } +#endif + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + #ifndef HAVE_FIPS + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_SECPR2 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160R2, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #ifdef WOLFSSL_TLS13 + #if defined(HAVE_CURVE25519) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #endif + } +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + } /* is not server */ + + #ifdef WOLFSSL_TLS13 + WOLFSSL_MSG("Adding signature algorithms extension"); + if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, + ssl->heap)) != 0) + return ret; + + if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { + /* Add mandatory TLS v1.3 extension: supported version */ + WOLFSSL_MSG("Adding supported versions extension"); + if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl, + ssl->heap)) != 0) + return ret; + + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_3072 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_4096 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_6144 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_8192 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + ret = 0; + + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ + !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP256R1, 0, NULL, + NULL); + #elif (!defined(NO_ECC384) || defined(HAVE_ALL_CURVES)) && \ + !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP384R1, 0, NULL, + NULL); + #elif (!defined(NO_ECC521) || defined(HAVE_ALL_CURVES)) && \ + !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP521R1, 0, NULL, + NULL); + #elif defined(HAVE_FFDHE_2048) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_2048, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_3072) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_3072, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_4096) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_4096, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_6144) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_6144, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_8192) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_8192, 0, NULL, NULL); + #else + ret = KEY_SHARE_ERROR; + #endif + if (ret != 0) + return ret; + } + + #if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + if (ssl->options.resuming) { + WOLFSSL_SESSION* sess = &ssl->session; + word32 milli; + byte modes; + + /* Determine the MAC algorithm for the cipher suite used. */ + ssl->options.cipherSuite0 = sess->cipherSuite0; + ssl->options.cipherSuite = sess->cipherSuite; + SetCipherSpecs(ssl); + milli = TimeNowInMilliseconds() - sess->ticketSeen + + sess->ticketAdd; + /* Pre-shared key is mandatory extension for resumption. */ + ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, + milli, ssl->specs.mac_algorithm, 1, + ssl->heap); + if (ret != 0) + return ret; + + /* Pre-shared key modes: mandatory extension for resumption. */ + modes = 1 << PSK_KE; + #if !defined(NO_DH) || defined(HAVE_ECC) + if (!ssl->options.noPskDheKe) + modes |= 1 << PSK_DHE_KE; + #endif + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; } - } /* is not server */ + #endif + /* TODO: [TLS13] Add PSKs */ + } + #endif (void)isServer; @@ -4566,6 +7185,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) (void)public_key_len; (void)ssl; + if (ret == SSL_SUCCESS) + ret = 0; + return ret; } @@ -4582,17 +7204,33 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl) EC_VALIDATE_REQUEST(ssl, semaphore); QSH_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); + WOLF_STK_VALIDATE_REQUEST(ssl); +#if defined(WOLFSSL_TLS13) + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + } +#endif if (ssl->extensions) - length += TLSX_GetSize(ssl->extensions, semaphore, 1); + length += TLSX_GetSize(ssl->extensions, semaphore, client_hello); - if (ssl->ctx && ssl->ctx->extensions) - length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1); + if (ssl->ctx && ssl->ctx->extensions) { + length += TLSX_GetSize(ssl->ctx->extensions, semaphore, + client_hello); + } +#ifndef WOLFSSL_TLS13 if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) - length += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ + length += HELLO_EXT_SZ + OPAQUE16_LEN + + ssl->suites->hashSigAlgoSz; +#endif #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) @@ -4617,21 +7255,36 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) offset += OPAQUE16_LEN; /* extensions length */ EC_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); + WOLF_STK_VALIDATE_REQUEST(ssl); QSH_VALIDATE_REQUEST(ssl, semaphore); +#if defined(WOLFSSL_TLS13) + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + } + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif if (ssl->extensions) - offset += TLSX_Write(ssl->extensions, output + offset, - semaphore, 1); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello); if (ssl->ctx && ssl->ctx->extensions) offset += TLSX_Write(ssl->ctx->extensions, output + offset, - semaphore, 1); + semaphore, client_hello); +#ifndef WOLFSSL_TLS13 if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { int i; /* extension type */ - c16toa(HELLO_EXT_SIG_ALGO, output + offset); + c16toa(TLSX_SIGNATURE_ALGORITHMS, output + offset); offset += HELLO_EXT_TYPE_SZ; /* extension data length */ @@ -4647,6 +7300,7 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) output[offset] = ssl->suites->hashSigAlgo[i]; } +#endif #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { @@ -4657,6 +7311,16 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) } #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.resuming) { + #ifndef NO_PSK + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello); + } +#endif + if (offset > OPAQUE16_LEN) c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ } @@ -4669,11 +7333,33 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) #ifndef NO_WOLFSSL_SERVER /** Tells the buffered size of extensions to be sent into the server hello. */ -word16 TLSX_GetResponseSize(WOLFSSL* ssl) +word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType) { word16 length = 0; byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { + case server_hello: +#ifdef WOLFSSL_TLS13 + case hello_retry_request: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + break; + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif + break; + } + #ifdef HAVE_QSH /* change response if not using TLS_QSH */ if (!ssl->options.haveQSH) { @@ -4684,35 +7370,58 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl) #endif #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) + if (ssl->options.haveEMS && msgType == server_hello) length += HELLO_EXT_SZ; #endif if (TLSX_SupportExtensions(ssl)) - length += TLSX_GetSize(ssl->extensions, semaphore, 0); + length += TLSX_GetSize(ssl->extensions, semaphore, msgType); /* All the response data is set at the ssl object only, so no ctx here. */ - if (length) + if (length || (msgType != server_hello)) length += OPAQUE16_LEN; /* for total length storage. */ return length; } /** Writes the server hello extensions into a buffer. */ -word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) +word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType) { word16 offset = 0; if (TLSX_SupportExtensions(ssl) && output) { byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { + case server_hello: +#ifdef WOLFSSL_TLS13 + case hello_retry_request: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + break; + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif + break; + } + offset += OPAQUE16_LEN; /* extensions length */ - offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType); #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) { + if (ssl->options.haveEMS && msgType == server_hello) { c16toa(HELLO_EXT_EXTMS, output + offset); offset += HELLO_EXT_TYPE_SZ; c16toa(0, output + offset); @@ -4720,7 +7429,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) } #endif - if (offset > OPAQUE16_LEN) + if (offset > OPAQUE16_LEN || msgType == encrypted_extensions) c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ } @@ -4730,11 +7439,12 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) #endif /* NO_WOLFSSL_SERVER */ /** Parses a buffer of TLS extensions. */ -int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, +int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, Suites *suites) { int ret = 0; word16 offset = 0; + byte isRequest = (msgType == client_hello); #ifdef HAVE_EXTENDED_MASTER byte pendingEMS = 0; #endif @@ -4762,36 +7472,75 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case TLSX_SERVER_NAME: WOLFSSL_MSG("SNI extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = SNI_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_MAX_FRAGMENT_LENGTH: WOLFSSL_MSG("Max Fragment Length extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return EXT_NOT_ALLOWED; +#endif ret = THM_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_SUPPORTED_GROUPS: WOLFSSL_MSG("Elliptic Curves extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = EC_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_STATUS_REQUEST: WOLFSSL_MSG("Certificate Status Request extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = CSR_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_STATUS_REQUEST_V2: WOLFSSL_MSG("Certificate Status Request v2 extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = CSR2_PARSE(ssl, input + offset, size, isRequest); break; @@ -4799,8 +7548,14 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case HELLO_EXT_EXTMS: WOLFSSL_MSG("Extended Master Secret extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif #ifndef NO_WOLFSSL_SERVER - if (isRequest) + if (isRequest && !IsAtLeastTLSv1_3(ssl->version)) ssl->options.haveEMS = 1; #endif pendingEMS = 1; @@ -4816,22 +7571,42 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case TLSX_SESSION_TICKET: WOLFSSL_MSG("Session Ticket extension received"); - ret = STK_PARSE(ssl, input + offset, size, isRequest); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif + ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return EXT_NOT_ALLOWED; +#endif ret = QSH_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_APPLICATION_LAYER_PROTOCOL: WOLFSSL_MSG("ALPN extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = ALPN_PARSE(ssl, input + offset, size, isRequest); break; - case HELLO_EXT_SIG_ALGO: +#ifndef WOLFSSL_TLS13 + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Extended signature algorithm extension received"); + if (isRequest) { /* do not mess with offset inside the switch! */ if (IsAtLeastTLSv1_2(ssl)) { @@ -4850,6 +7625,77 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, } break; +#endif + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = SV_PARSE(ssl, input + offset, size); + break; + + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension received"); + + if (!IsAtLeastTLSv1_2(ssl)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = SA_PARSE(ssl, input + offset, size); + break; + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = KS_PARSE(ssl, input + offset, size, msgType); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello) { + return EXT_NOT_ALLOWED; + } + ret = PSK_PARSE(ssl, input + offset, size, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = PKM_PARSE(ssl, input + offset, size, msgType); + break; + #endif +#endif } /* offset should be updated here! */ @@ -4929,6 +7775,35 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return method; } +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 client method data. + * + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method(void) + { + return wolfTLSv1_3_client_method_ex(NULL); + } + + /* The TLS v1.3 client method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) + XMALLOC(sizeof(WOLFSSL_METHOD), heap, + DYNAMIC_TYPE_METHOD); + (void)heap; + if (method) { + InitSSL_Method(method, MakeTLSv1_3()); + method->downgrade = 1; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ + WOLFSSL_METHOD* wolfSSLv23_client_method(void) { @@ -4944,7 +7819,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, (void)heap; if (method) { #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); +#else InitSSL_Method(method, MakeTLSv1_2()); +#endif #else #ifndef NO_OLD_TLS InitSSL_Method(method, MakeTLSv1_1()); @@ -5021,6 +7900,34 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return method; } +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 server method data. + * + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method(void) + { + return wolfTLSv1_3_server_method_ex(NULL); + } + + /* The TLS v1.3 server method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + if (method) { + InitSSL_Method(method, MakeTLSv1_3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ WOLFSSL_METHOD* wolfSSLv23_server_method(void) { @@ -5035,7 +7942,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, (void)heap; if (method) { #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); +#else InitSSL_Method(method, MakeTLSv1_2()); +#endif #else #ifndef NO_OLD_TLS InitSSL_Method(method, MakeTLSv1_1()); diff --git a/src/tls13.c b/src/tls13.c new file mode 100644 index 0000000000..85a1791624 --- /dev/null +++ b/src/tls13.c @@ -0,0 +1,5557 @@ +/* tls13.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 + +#ifdef WOLFSSL_TLS13 +#if defined(HAVE_SESSION_TICKET) +#include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#ifdef HAVE_ERRNO_H + #include +#endif + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" +#endif + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + +#ifdef __sun + #include +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +/* Set ret to error value and jump to label. + * + * err The error value to set. + * eLabel The label to jump to. + */ +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN +/* Return the minimum of the two values. + * + * a First value. + * b Second value. + * returns the minimum of a and b. + */ +static INLINE word32 min(word32 a, word32 b) +{ + return a > b ? b : a; +} +#endif /* WOLFSSL_HAVE_MIN */ + +/* Convert 16-bit integer to opaque data. + * + * u16 Unsigned 16-bit value. + * c The buffer to write to. + */ +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} + +/* Convert 32-bit integer to opaque data. + * + * u32 Unsigned 32-bit value. + * c The buffer to write to. + */ +static INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + + +/* Convert 24-bit opaque data into a 32-bit value. + * + * u24 The opaque data holding a 24-bit integer. + * u32 Unsigned 32-bit value. + */ +static INLINE void c24to32(const word24 u24, word32* u32) +{ + *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; +} + + +/* Convert opaque data into a 16-bit value. + * + * c The opaque data. + * u16 Unsigned 16-bit value. + */ +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (word16) ((c[0] << 8) | (c[1])); +} + +#ifndef NO_WOLFSSL_CLIENT +#ifdef HAVE_SESSION_TICKET +/* Convert opaque data into a 32-bit value. + * + * c The opaque data. + * u32 Unsigned 32-bit value. + */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} +#endif +#endif + +/* Extract data using HMAC, salt and input. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF) + * + * prk The generated pseudorandom key. + * salt The salt. + * saltLen The length of the salt. + * ikm The input keying material. + * ikmLen The length of the input keying material. + * mac The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen, + byte* ikm, int ikmLen, int mac) +{ + int ret; + int hash; + int len; + + switch (mac) { + #ifndef NO_SHA256 + case sha256_mac: + hash = SHA256; + len = SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = SHA384; + len = SHA384_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA512 + case sha512_mac: + hash = SHA512; + len = SHA512_DIGEST_SIZE; + break; + #endif + + default: + return BAD_FUNC_ARG; + } + + /* When length is 0 then use zeroed data of digest length. */ + if (ikmLen == 0) { + ikmLen = len; + XMEMSET(ikm, 0, len); + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Salt"); + WOLFSSL_BUFFER(salt, saltLen); + WOLFSSL_MSG("IKM"); + WOLFSSL_BUFFER(ikm, ikmLen); +#endif + + ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("PRK"); + WOLFSSL_BUFFER(prk, len); +#endif + + return ret; +} + +/* Expand data using HMAC, salt and label and info. + * TLS v1.3 defines this function. + * + * okm The generated pseudorandom key - output key material. + * prk The salt - pseudo-random key. + * prkLen The length of the salt - pseudo-random key. + * protocol The TLS protocol label. + * protocolLen The length of the TLS protocol label. + * info The information to expand. + * infoLen The length of the information. + * digest The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int HKDF_Expand_Label(byte* okm, word32 okmLen, + const byte* prk, word32 prkLen, + const byte* protocol, word32 protocolLen, + const byte* label, word32 labelLen, + const byte* info, word32 infoLen, + int digest) +{ + int ret = 0; + int idx = 0; + byte data[MAX_HKDF_LABEL_SZ]; + + /* Output length. */ + data[idx++] = okmLen >> 8; + data[idx++] = okmLen; + /* Length of protocol | label. */ + data[idx++] = protocolLen + labelLen; + /* Protocol */ + XMEMCPY(&data[idx], protocol, protocolLen); + idx += protocolLen; + /* Label */ + XMEMCPY(&data[idx], label, labelLen); + idx += labelLen; + /* Length of hash of messages */ + data[idx++] = infoLen; + /* Hash of messages */ + XMEMCPY(&data[idx], info, infoLen); + idx += infoLen; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("PRK"); + WOLFSSL_BUFFER(prk, prkLen); + WOLFSSL_MSG("Info"); + WOLFSSL_BUFFER(data, idx); +#endif + + ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("OKM"); + WOLFSSL_BUFFER(okm, okmLen); +#endif + + ForceZero(data, idx); + + return ret; +} + +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 9 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, "; + +/* Derive a key from a message. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * msg The message data to derive key from. + * msgLen The length of the message data to derive key from. + * hashAlgo The hash algorithm to use in the HMAC. + * returns 0 on success, otherwise failure. + */ +static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + byte* msg, int msgLen, int hashAlgo) +{ + byte hash[MAX_DIGEST_SIZE]; + Digest digest; + word32 hashSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg; + int ret = BAD_FUNC_ARG; + + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, msg, msgLen); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, hash); + wc_Sha256Free(&digest.sha256); + } + hashSz = SHA256_DIGEST_SIZE; + digestAlg = SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, msg, msgLen); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, hash); + wc_Sha384Free(&digest.sha384); + } + hashSz = SHA384_DIGEST_SIZE; + digestAlg = SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, msg, msgLen); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, hash); + wc_Sha512Free(&digest.sha512); + } + hashSz = SHA512_DIGEST_SIZE; + digestAlg = SHA512; + break; +#endif + + default: + return BAD_FUNC_ARG; + } + + if (ret != 0) + return ret; + + switch (ssl->version.minor) { + case TLSv1_3_MINOR: + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + break; + + default: + return VERSION_ERROR; + } + if (outputLen == -1) + outputLen = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashSz, digestAlg); +} + +/* Derive a key. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * hashAlgo The hash algorithm to use in the HMAC. + * includeMsgs Whether to include a hash of the handshake messages so far. + * returns 0 on success, otherwise failure. + */ +static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + int hashAlgo, int includeMsgs) +{ + int ret = 0; + byte hash[MAX_DIGEST_SIZE]; + word32 hashSz = 0; + word32 hashOutSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg; + + switch (hashAlgo) { + #ifndef NO_SHA256 + case sha256_mac: + hashSz = SHA256_DIGEST_SIZE; + digestAlg = SHA256; + if (includeMsgs) + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashSz = SHA384_DIGEST_SIZE; + digestAlg = SHA384; + if (includeMsgs) + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif + + #ifdef WOLFSSL_SHA512 + case sha512_mac: + hashSz = SHA512_DIGEST_SIZE; + digestAlg = SHA512; + if (includeMsgs) + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + if (ret != 0) + return ret; + + /* Only one protocol version defined at this time. */ + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + + if (outputLen == -1) + outputLen = hashSz; + if (includeMsgs) + hashOutSz = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashOutSz, digestAlg); +} + + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 23 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "external psk binder key"; +/* Derive the binder key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKey(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyLabel, BINDER_KEY_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} + +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 25 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "resumption psk binder key"; +/* Derive the binder resumption key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key - Resumption"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} +#endif + +#ifdef TLS13_SUPPORTS_0RTT +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 27 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "client early traffic secret"; +/* Derive the early traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + + #ifdef TLS13_SUPPORTS_EXPORTERS +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 28 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "early exporter master secret"; +/* Derive the early exporter key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + #endif +#endif + +/* The length of the client hanshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 31 +/* The client hanshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "client handshake traffic secret"; +/* Derive the client handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 31 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "server handshake traffic secret"; +/* Derive the server handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 33 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "client application traffic secret"; +/* Derive the client application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + clientAppLabel, CLIENT_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 33 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "server application traffic secret"; +/* Derive the server application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + serverAppLabel, SERVER_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef TLS13_SUPPORTS_EXPORTERS +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 22 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exporter master secret"; +/* Derive the exporter secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +#ifndef NO_PSK +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 24 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "resumption master secret"; +/* Derive the resumption secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Resumption Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + resumeMasterLabel, RESUME_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +/* Length of the finished label. */ +#define FINISHED_LABEL_SZ 8 +/* Finished label for generating finished key. */ +static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished"; +/* Derive the finished secret. + * + * ssl The SSL/TLS object. + * key The key to use with the HMAC. + * secret The derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret) +{ + WOLFSSL_MSG("Derive Finished Secret"); + return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ, + ssl->specs.mac_algorithm, 0); +} + +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 26 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "application traffic secret"; +/* Update the traffic secret. + * + * ssl The SSL/TLS object. + * secret The previous secret and derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret) +{ + WOLFSSL_MSG("Derive New Application Traffic Secret"); + return DeriveKeyMsg(ssl, secret, -1, secret, + appTrafficLabel, APP_TRAFFIC_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} + +/* Derive the early secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveEarlySecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Early Secret"); +#ifndef NO_PSK + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->psk_key, ssl->arrays->psk_keySz, + ssl->specs.mac_algorithm); +#else + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif +} + +/* Derive the handshake secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveHandshakeSecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Handshake Secret"); + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + ssl->arrays->secret, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +} + +/* Derive the master secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveMasterSecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Master Secret"); + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + ssl->arrays->preMasterSecret, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +} + +/* Calculate the HMAC of message data to this point. + * + * ssl The SSL/TLS object. + * key The HMAC key. + * hash The hash result - verify data. + * returns length of verify data generated. + */ +static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, + word32* pHashSz) +{ + Hmac verifyHmac; + int hashType = SHA256; + int hashSz = SHA256_DIGEST_SIZE; + int ret = BAD_FUNC_ARG; + + /* Get the hash of the previous handshake messages. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + hashType = SHA256; + hashSz = SHA256_DIGEST_SIZE; + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashType = SHA384; + hashSz = SHA384_DIGEST_SIZE; + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + hashType = SHA512; + hashSz = SHA512_DIGEST_SIZE; + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif /* WOLFSSL_SHA512 */ + } + if (ret != 0) + return ret; + + /* Calculate the verify data. */ + ret = wc_HmacInit(&verifyHmac, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size); + if (ret == 0) + ret = wc_HmacUpdate(&verifyHmac, hash, hashSz); + if (ret == 0) + ret = wc_HmacFinal(&verifyHmac, hash); + wc_HmacFree(&verifyHmac); + } + + if (pHashSz) + *pHashSz = hashSz; + + return ret; +} + +/* The length of the label to use when deriving keys. */ +#define WRITE_KEY_LABEL_SZ 3 +/* The length of the label to use when deriving IVs. */ +#define WRITE_IV_LABEL_SZ 2 +/* The label to use when deriving keys. */ +static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key"; +/* The label to use when deriving IVs. */ +static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; + +/* Derive the keys and IVs for TLS v1.3. + * + * ssl The SSL/TLS object. + * sercret handshake_key when deriving keys and IVs for encrypting handshake + * messages. + * traffic_key when deriving first keys and IVs for encrypting + * traffic messages. + * update_traffic_key when deriving next keys and IVs for encrypting + * traffic messages. + * side ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived. + * DECRYPT_SIDE_ONLY when only decryption secret needs to be derived. + * ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived. + * returns 0 on success, otherwise failure. + */ +static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side) +{ + int ret; + int i = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key_data; +#else + byte key_data[MAX_PRF_DIG]; +#endif + int deriveClient = 0; + int deriveServer = 0; + +#ifdef WOLFSSL_SMALL_STACK + key_data = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key_data == NULL) + return MEMORY_E; +#endif + + if (side == ENCRYPT_AND_DECRYPT_SIDE) { + deriveClient = 1; + deriveServer = 1; + } + else { + deriveClient = (ssl->options.side != WOLFSSL_CLIENT_END) ^ + (side == ENCRYPT_SIDE_ONLY); + deriveServer = !deriveClient; + } + + /* Derive the appropriate secret to use in the HKDF. */ + switch (secret) { + case handshake_key: + if (deriveClient) { + ret = DeriveClientHandshakeSecret(ssl, + ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (deriveServer) { + ret = DeriveServerHandshakeSecret(ssl, + ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + + case traffic_key: + if (deriveClient) { + ret = DeriveClientTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (deriveServer) { + ret = DeriveServerTrafficSecret(ssl, ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + + case update_traffic_key: + if (deriveClient) { + ret = DeriveTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (deriveServer) { + ret = DeriveTrafficSecret(ssl, ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + } + + /* Key data = client key | server key | client IV | server IV */ + + /* Derive the client key. */ + WOLFSSL_MSG("Derive Client Key"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.key_size, + ssl->arrays->clientSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + + /* Derive the server key. */ + WOLFSSL_MSG("Derive Server Key"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.key_size, + ssl->arrays->serverSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + + /* Derive the client IV. */ + WOLFSSL_MSG("Derive Client IV"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.iv_size, + ssl->arrays->clientSecret, writeIVLabel, WRITE_IV_LABEL_SZ, + ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.iv_size; + + /* Derive the server IV. */ + WOLFSSL_MSG("Derive Server IV"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.iv_size, + ssl->arrays->serverSecret, writeIVLabel, WRITE_IV_LABEL_SZ, + ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + + /* Store keys and IVs but don't activate them. */ + ret = StoreKeys(ssl, key_data); + +end: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_data, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#if defined(HAVE_SESSION_TICKET) +#if defined(USER_TICKS) +#if 0 + word32 TimeNowInMilliseconds(void) + { + /* + write your own clock tick function if don't want gettimeofday() + needs millisecond accuracy but doesn't have to correlated to EPOCH + */ + } +#endif + +#elif defined(TIME_OVERRIDES) + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) XTIME(0) * 1000; + } +#elif defined(USE_WINDOWS_API) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + static int init = 0; + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (word32)(count.QuadPart / (freq.QuadPart / 1000)); + } + +#elif defined(HAVE_RTP_SYS) + #include "rtptime.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)rtp_get_system_sec() * 1000; + } +#elif defined(MICRIUM) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + NET_SECURE_OS_TICK clk = 0; + + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + clk = NetSecure_OS_TimeGet(); + #endif + return (word32)clk * 1000; + } +#elif defined(MICROCHIP_TCPIP_V5) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (TickGet() / (TICKS_PER_SECOND / 1000)); + } +#elif defined(MICROCHIP_TCPIP) + #if defined(MICROCHIP_MPLAB_HARMONY) + #include + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (SYS_TMR_TickCountGet() / + (SYS_TMR_TickCounterFrequencyGet() / 1000)); + } + #else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000)); + } + + #endif + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + TIME_STRUCT mqxTime; + + _time_get_elapsed(&mqxTime); + + return (word32) mqxTime.SECONDS * 1000; + } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include "include/task.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (unsigned int)(((float)xTaskGetTickCount()) / + (configTICK_RATE_HZ / 1000)); + } +#elif defined(FREESCALE_KSDK_BM) + #include "lwip/sys.h" /* lwIP */ + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return sys_now(); + } +#elif defined(WOLFSSL_TIRTOS) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) Seconds_get() * 1000; + } +#elif defined(WOLFSSL_UTASKER) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000)); + } +#else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + struct timeval now; + + if (gettimeofday(&now, 0) < 0) + return GETTIME_ERROR; + /* Convert to milliseconds number. */ + return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); + } +#endif +#endif /* HAVE_SESSION_TICKET */ + + +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) && \ + !defined(NO_PSK)) +/* Add input to all handshake hashes. + * + * ssl The SSL/TLS object. + * input The data to hash. + * sz The size of the data to hash. + * returns 0 on success, otherwise failure. + */ +static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) +{ + int ret = BAD_FUNC_ARG; + +#ifndef NO_OLD_TLS +#ifndef NO_SHA + ret = wc_ShaUpdate(&ssl->hsHashes->hashSha, input, sz); + if (ret != 0) + return ret; +#endif +#ifndef NO_MD5 + ret = wc_Md5Update(&ssl->hsHashes->hashMd5, input, sz); + if (ret != 0) + return ret; +#endif +#endif /* !NO_OLD_TLS */ + +#ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz); + if (ret != 0) + return ret; +#endif + + return ret; +} +#endif + +/* Extract the handshake header information. + * + * ssl The SSL/TLS object. + * input The buffer holding the message data. + * inOutIdx On entry, the index into the buffer of the handshake data. + * On exit, the start of the hanshake data. + * type Type of handshake message. + * size The length of the handshake message data. + * totalSz The total size of data in the buffer. + * returns BUFFER_E if there is not enough input data and 0 on success. + */ +static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + byte *type, word32 *size, word32 totalSz) +{ + const byte *ptr = input + *inOutIdx; + (void)ssl; + + *inOutIdx += HANDSHAKE_HEADER_SZ; + if (*inOutIdx > totalSz) + return BUFFER_E; + + *type = ptr[0]; + c24to32(&ptr[1], size); + + return 0; +} + +/* Add record layer header to message. + * + * output The buffer to write the record layer header into. + * length The length of the record data. + * type The type of record message. + * ssl The SSL/TLS object. + */ +static void AddTls13RecordHeader(byte* output, word32 length, byte type, + WOLFSSL* ssl) +{ + RecordLayerHeader* rl; + + rl = (RecordLayerHeader*)output; + rl->type = type; + rl->pvMajor = ssl->version.major; + rl->pvMinor = TLSv1_MINOR; + c16toa((word16)length, rl->length); +} + +/* Add handshake header to message. + * + * output The buffer to write the hanshake header into. + * length The length of the handshake data. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * type The type of handshake message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13HandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) +{ + HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; + (void)ssl; + + /* handshake header */ + hs = (HandShakeHeader*)output; + hs->type = type; + c32to24(length, hs->length); +} + + +/* Add both record layer and handshake header to message. + * + * output The buffer to write the headers into. + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13Headers(byte* output, word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + + AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} + + +#ifndef NO_CERTS +/* Add both record layer and fragement handshake header to message. + * + * output The buffer to write the headers into. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + + AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz, + type, ssl); +} +#endif /* NO_CERTS */ + +/* Write the sequence number into the buffer. + * No DTLS v1.3 support. + * + * ssl The SSL/TLS object. + * verifyOrder Which set of sequence numbers to use. + * out The buffer to write into. + */ +static INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (verifyOrder) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.peer_sequence_number_lo) + ssl->keys.peer_sequence_number_hi++; + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.sequence_number_lo) + ssl->keys.sequence_number_hi++; + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} + +/* Build the nonce for TLS v1.3 encryption and decryption. + * + * ssl The SSL/TLS object. + * nonce The nonce data to use when encrypting or decrypting. + * iv The derived IV. + * order The side on which the message is to be or was sent. + */ +static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte *nonce, const byte* iv, + int order) +{ + int i; + + /* The nonce is the IV with the sequence XORed into the last bytes. */ + WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ); + for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++) + nonce[i] = iv[i]; + for (; i < AEAD_NONCE_SZ; i++) + nonce[i] ^= iv[i]; +} + +/* Encrypt with ChaCha20 and create authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * nonce The nonce to use with ChaCha20. + * tag The authentication tag buffer. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + byte* tag) +{ + int ret = 0; + byte poly[CHACHA20_256_KEY_SIZE]; + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set the nonce for ChaCha and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Create Poly1305 key using ChaCha20 keystream. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + /* Encrypt the plain text. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz); + if (ret != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Add authentication code of encrypted data to end. */ + ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, output, sz, tag, + POLY1305_AUTH_SZ); + + return ret; +} + +/* Encrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * returns 0 on success, otherwise failure. + */ +static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + byte nonce[AEAD_NONCE_SZ]; + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to encrypt"); + WOLFSSL_BUFFER(input, dataSz); +#endif + + BuildTls13Nonce(ssl, nonce, ssl->keys.aead_enc_imp_IV, CUR_ORDER); + + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, dataSz, + nonce, AESGCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, dataSz, + nonce, AESCCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, nonce, + output + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + return ENCRYPT_ERROR; + } + + ForceZero(nonce, AEAD_NONCE_SZ); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Encrypted data"); + WOLFSSL_BUFFER(output, dataSz); + WOLFSSL_MSG("Authentication Tag"); + WOLFSSL_BUFFER(output + dataSz, macSz); +#endif + + return ret; +} + +/* Decrypt with ChaCha20 and check authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to decrypt. + * sz The number of bytes to decrypt. + * nonce The nonce to use with ChaCha20. + * tagIn The authentication tag data from packet. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Decrypt(WOLFSSL *ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + const byte* tagIn) +{ + int ret; + byte tag[POLY1305_AUTH_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set nonce and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Use ChaCha20 keystream to get Poly1305 key for tag. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Generate authentication tag for encrypted data. */ + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, (byte*)input, sz, + tag, sizeof(tag))) != 0) { + return ret; + } + + /* Check tag sent along with packet. */ + if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) { + WOLFSSL_MSG("MAC did not match"); + return VERIFY_MAC_ERROR; + } + + /* If the tag was good decrypt message. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz); + + return ret; +} + +/* Decrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to encrypt and authentication tag. + * sz The length of the encrypted data plus authentication tag. + * returns 0 on success, otherwise failure. + */ +int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + byte nonce[AEAD_NONCE_SZ]; + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to decrypt"); + WOLFSSL_BUFFER(input, dataSz); + WOLFSSL_MSG("Authentication tag"); + WOLFSSL_BUFFER(input + dataSz, macSz); +#endif + + BuildTls13Nonce(ssl, nonce, ssl->keys.aead_dec_imp_IV, PEER_ORDER); + + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, dataSz, + nonce, AESGCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, + nonce, AESCCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, nonce, + input + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + return DECRYPT_ERROR; + } + + ForceZero(nonce, AEAD_NONCE_SZ); + if (ret < 0 && !ssl->options.dtls) { + SendAlert(ssl, alert_fatal, bad_record_mac); + ret = VERIFY_MAC_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Decrypted data"); + WOLFSSL_BUFFER(output, dataSz); +#endif + + return ret; +} + +/* Build SSL Message, encrypted. + * TLS v1.3 encryption is AEAD only. + * + * ssl The SSL/TLS object. + * output The buffer to write record message to. + * outSz Size of the buffer being written into. + * input The record data to encrypt (excluding record header). + * inSz The size of the record data. + * type The recorder header content type. + * hashOutput Whether to hash the unencrypted record data. + * sizeOnly Only want the size of the record message. + * returns the size of the encrypted record message or negative value on error. + */ +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly) +{ + word32 sz = RECORD_HEADER_SZ + inSz; + word32 idx = RECORD_HEADER_SZ; + word32 headerSz = RECORD_HEADER_SZ; + word16 size; + int ret = 0; + int atomicUser = 0; + + if (ssl == NULL) + return BAD_FUNC_ARG; + if (!sizeOnly && (output == NULL || input == NULL)) + return BAD_FUNC_ARG; + /* catch mistaken sizeOnly parameter */ + if (sizeOnly && (output || input)) { + WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); + return BAD_FUNC_ARG; + } + + /* Record layer content type at the end of record data. */ + sz++; + /* Authentication data at the end. */ + sz += ssl->specs.aead_mac_size; + + if (sizeOnly) + return sz; + + if (sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + return BUFFER_E; + } + + /* Record data length. */ + size = (word16)(sz - headerSz); + /* Write/update the record header with the new size. + * Always have the content type as application data for encrypted + * messages in TLS v1.3. + */ + AddTls13RecordHeader(output, size, application_data, ssl); + + /* TLS v1.3 can do in place encryption. */ + if (input != output + idx) + XMEMCPY(output + idx, input, inSz); + idx += inSz; + + if (hashOutput) { + ret = HashOutput(ssl, output, headerSz + inSz, 0); + if (ret != 0) + return ret; + } + + /* The real record content type goes at the end of the data. */ + output[idx++] = type; + +#ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) + atomicUser = 1; +#endif + + if (atomicUser) { /* User Record Layer Callback handling */ +#ifdef ATOMIC_USER + byte* mac = output + idx; + output += headerSz; + + if ((ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, + output, output, size, ssl->MacEncryptCtx)) != 0) { + return ret; + } +#endif + } + else { + output += headerSz; + if ((ret = EncryptTls13(ssl, output, output, size)) != 0) + return ret; + } + + return sz; +} + +#ifndef NO_WOLFSSL_CLIENT +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* Get the size of the message hash. + * + * ssl The SSL/TLS object. + * returns the length of the hash. + */ +static int GetMsgHashSize(WOLFSSL *ssl) +{ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + return SHA256_DIGEST_SIZE; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return SHA384_DIGEST_SIZE; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return SHA512_DIGEST_SIZE; + #endif /* WOLFSSL_SHA512 */ + } + return 0; +} + +/* Derive and write the binders into the ClientHello in space left when + * writing the Pre-Shared Key extension. + * + * ssl The SSL/TLS object. + * output The buffer containing the ClientHello. + * idx The index at the end of the completed ClientHello. + * returns 0 on success and otherwise failure. + */ +static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) +{ + int ret; + TLSX* ext; + PreSharedKey* current; + byte binderKey[MAX_DIGEST_SIZE]; + word16 len; + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return SANITY_MSG_E; + + /* Get the size of the binders to determine where to write binders. */ + idx -= TLSX_PreSharedKey_GetSizeBinders(ext->data, client_hello); + + /* Hash truncated ClientHello - up to binders. */ + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + current = ext->data; + /* Calculate the binder for each identity based on previous handshake data. + */ + while (current != NULL) { + if (current->resumption) { + /* Set the HMAC to use based on the one for the session (set into + * the extension data at the start of this function based on the + * cipher suite in the session information. + */ + ssl->specs.mac_algorithm = current->hmac; + + /* Resumption PSK is master secret. */ + ssl->arrays->psk_keySz = GetMsgHashSize(ssl); + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->arrays->psk_keySz); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKeyResume(ssl, binderKey); + if (ret != 0) + return ret; + } + else { + /* TODO: [TLS13] Support non-ticket PSK. */ + /* Get the pre-shared key. */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char *)current->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKey(ssl, binderKey); + if (ret != 0) + return ret; + } + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Build the HMAC of the handshake message data = binder. */ + ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, + current->binder, ¤t->binderLen); + if (ret != 0) + return ret; + + current = current->next; + } + + /* Data entered into extension, now write to message. */ + len = TLSX_PreSharedKey_WriteBinders(ext->data, output + idx, client_hello); + + /* Hash binders to complete the hash of the ClientHello. */ + return HashOutputRaw(ssl, output + idx, len); +} +#endif + +/* Send a ClientHello message to the server. + * Include the information required to start a handshake with servers using + * protocol versions less than TLS v1.3. + * Only a client will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +int SendTls13ClientHello(WOLFSSL* ssl) +{ + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + if (ssl->options.resuming && + (ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor)) { + ssl->version.major = ssl->session.version.major; + ssl->version.minor = ssl->session.version.minor; + return SendClientHello(ssl); + } +#endif + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello"); + return SUITES_ERROR; + } + + /* Version | Random | Session Id | Cipher Suites | Compression | Ext */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; +#ifdef HAVE_QSH + if (QSH_Init(ssl) != 0) + return MEMORY_E; +#endif + /* Include length of TLS extensions. */ + length += TLSX_GetRequestSize(ssl); + + /* Total message size. */ + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, client_hello, ssl); + + /* Protocol version. */ + output[idx++] = SSLv3_MAJOR; + output[idx++] = TLSv1_2_MINOR; + ssl->chVersion = ssl->version; + + /* Client Random */ + if (ssl->options.connectState == CONNECT_BEGIN) { + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + + /* Store random for possible second ClientHello. */ + XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + } + else + XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); + idx += RAN_LEN; + + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; + + /* Cipher suites */ + c16toa(ssl->suites->suiteSz, output + idx); + idx += OPAQUE16_LEN; + XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); + idx += ssl->suites->suiteSz; + + /* Compression not supported in TLS v1.3. */ + output[idx++] = COMP_LEN; + output[idx++] = NO_COMPRESSION; + + /* Write out extensions for a request. */ + idx += TLSX_WriteRequest(ssl, output + idx); + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + /* Resumption has a specific set of extensions and binder is calculated + * for each identity. + */ + if (ssl->options.resuming) + ret = WritePSKBinders(ssl, output, idx); + else +#endif + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); +} + +/* Parse and handle a HelloRetryRequest message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * HelloRetryRequest. + * On exit, the index of byte after the HelloRetryRequest message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + ProtocolVersion pv; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo); +#endif + + /* Version info and length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + /* Protocol version. */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + + /* Length of extension data. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if (totalExtSz == 0) { + WOLFSSL_MSG("HelloRetryRequest must contain extensions"); + return MISSING_HANDSHAKE_DATA; + } + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + hello_retry_request, NULL))) + return ret; + /* The KeyShare extension parsing fails when not valid. */ + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + ssl->options.tls1_3 = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + + return 0; +} + +/* Handle the ServerHello message from the server. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ServerHello. + * On exit, the index of byte after the ServerHello message. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + ProtocolVersion pv; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + word16 totalExtSz; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* Protocol version length check. */ + if (OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) { + ssl->version = pv; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } + + /* Random, cipher suite and extensions length check. */ + if ((i - begin) + RAN_LEN + OPAQUE16_LEN + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Server random - keep for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); + i += RAN_LEN; + /* TODO: [TLS13] Check last 8 bytes. */ + + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + + /* Get extension length and length check. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, server_hello, NULL); + if (ret != 0) + return ret; + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + +#ifdef HAVE_SECRET_CALLBACK + if (ssl->sessionSecretCb != NULL) { + int secretSz = SECRET_LEN, ret; + ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + &secretSz, ssl->sessionSecretCtx); + if (ret != 0 || secretSz != SECRET_LEN) + return SESSION_SECRET_CB_E; + } +#endif /* HAVE_SECRET_CALLBACK */ + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + +#ifndef NO_PSK + if (ssl->options.resuming) { + PreSharedKey *psk = NULL; + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext != NULL) + psk = (PreSharedKey*)ext->data; + while (psk != NULL && !psk->chosen) + psk = psk->next; + if (psk == NULL) { + ssl->options.resuming = 0; + ssl->arrays->psk_keySz = ssl->specs.hash_size; + XMEMSET(ssl->arrays->psk_key, 0, ssl->arrays->psk_keySz); + } + } +#endif + + ssl->keys.encryptionOn = 1; + + return ret; +} + +/* Parse and handle an EncryptedExtensions message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * EncryptedExtensions. + * On exit, the index of byte after the EncryptedExtensions + * message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("EncryptedExtensions", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo); +#endif + + /* Length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + encrypted_extensions, NULL))) + return ret; + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + return 0; +} + +/* Handle a TLS v1.3 CertificateRequest message. + * This message is always encrypted. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of CertificateRequest. + * On exit, the index of byte after the CertificateRequest message. + * size The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + word16 len; + word32 begin = *inOutIdx; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateRequest", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); + #endif + + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + return BUFFER_ERROR; + + /* Length of the request context. */ + len = input[(*inOutIdx)++]; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (ssl->options.connectState < FINISHED_DONE && len > 0) + return BUFFER_ERROR; + + /* Request context parsed here. */ + /* TODO: [TLS13] Request context for post-handshake auth. + * Store the value and return it in Certificate message. + * Must be unique in the scope of the connection. + */ + *inOutIdx += len; + + /* Signature and hash algorithms. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + PickHashSigAlgo(ssl, input + *inOutIdx, len); + *inOutIdx += len; + + /* Length of certificate authority data. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + /* Certificate authorities. */ + while (len) { + word16 dnSz; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &dnSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + dnSz > size) + return BUFFER_ERROR; + + *inOutIdx += dnSz; + len -= OPAQUE16_LEN + dnSz; + } + + /* TODO: [TLS13] Add extension handling. */ + /* Certificate extensions */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + /* Skip over extensions for now. */ + *inOutIdx += len; + + ssl->options.sendVerify = SEND_CERT; + + /* This message is always encrypted so add encryption padding. */ + *inOutIdx += ssl->keys.padSz; + + return 0; +} + +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* Handle any Pre-Shared Key (PSK) extension. + * Must do this in ClientHello as it requires a hash of the truncated message. + * Don't know size of binders until Pre-Shared Key extension has been parsed. + * + * ssl The SSL/TLS object. + * input The ClientHello message. + * helloSz The size of the ClientHello message (including binders if present). + * usingPSK Indicates handshake is using Pre-Shared Keys. + * returns 0 on success and otherwise failure. + */ +static int DoPreSharedKeys(WOLFSSL *ssl, const byte* input, word32 helloSz, + int* usingPSK) +{ + int ret; + TLSX* ext; + word16 bindersLen; + PreSharedKey* current; + byte binderKey[MAX_DIGEST_SIZE]; + byte binder[MAX_DIGEST_SIZE]; + word32 binderLen; + word16 modes; + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return 0; + + /* Extensions pushed on stack/list and PSK must be last. */ + if (ssl->extensions != ext) + return PSK_KEY_ERROR; + + /* Assume we are going to resume with a pre-shared key. */ + ssl->options.resuming = 1; + + /* Find the pre-shared key extension and calculate hash of truncated + * ClientHello for binders. + */ + bindersLen = TLSX_PreSharedKey_GetSizeBinders(ext->data, client_hello); + + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz - bindersLen); + if (ret != 0) + return ret; + + /* Look through all client's pre-shared keys for a match. */ + current = (PreSharedKey*)ext->data; + while (current != NULL) { + /* TODO: [TLS13] Support non-ticket PSK. */ + /* Decode the identity. */ + ret = DoClientTicket(ssl, current->identity, current->identityLen); + if (ret != WOLFSSL_TICKET_RET_OK) + continue; + + if (current->resumption) { + /* Check the ticket isn't too old or new. */ + int diff = TimeNowInMilliseconds() - ssl->session.ticketSeen; + diff -= current->ticketAge - ssl->session.ticketAdd; + /* TODO: [TLS13] What should the value be? Configurable? */ + if (diff < -1000 || diff > 1000) { + /* Invalid difference, fallback to full handshake. */ + ssl->options.resuming = 0; + break; + } + + /* Use the same cipher suite as before and set up for use. */ + ssl->options.cipherSuite0 = ssl->session.cipherSuite0; + ssl->options.cipherSuite = ssl->session.cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + /* Resumption PSK is resumption master secret. */ + ssl->arrays->psk_keySz = ssl->specs.hash_size; + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->specs.hash_size); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKeyResume(ssl, binderKey); + if (ret != 0) + return ret; + } + else { + /* PSK age is always zero. */ + if (current->ticketAge != ssl->session.ticketAdd) + return PSK_KEY_ERROR; + + /* Get the pre-shared key. */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char*)current->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKey(ssl, binderKey); + if (ret != 0) + return ret; + } + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Derive the binder and compare with the one in the extension. */ + ret = BuildTls13HandshakeHmac(ssl, + ssl->keys.client_write_MAC_secret, binder, &binderLen); + if (ret != 0) + return ret; + if (binderLen != current->binderLen || + XMEMCMP(binder, current->binder, binderLen) != 0) { + return BAD_BINDER; + } + + /* This PSK works, no need to try any more. */ + current->chosen = 1; + ext->resp = 1; + break; + } + + /* Hash the rest of the ClientHello. */ + ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen); + if (ret != 0) + return ret; + + /* Get the PSK key exchange modes the client wants to negotiate. */ + ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (ext == NULL) + return MISSING_HANDSHAKE_DATA; + modes = ext->val; + + ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + /* Use (EC)DHE for forward-security if possible. */ + if (ext != NULL && (modes & (1 << PSK_DHE_KE)) != 0 && + !ssl->options.noPskDheKe) { + /* Only use named group used in last session. */ + ssl->namedGroup = ssl->session.namedGroup; + + /* Try to establish a new secret. */ + ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + return PSK_KEY_ERROR; + else if (ret > 0) + ret = 0; + + /* Send new public key to client. */ + ext->resp = 1; + } + else if ((modes & (1 << PSK_KE)) != 0) { + /* Don't send a key share extension back. */ + if (ext != NULL) + ext->resp = 0; + } + else + return PSK_KEY_ERROR; + + *usingPSK = 1; + + return ret; +} +#endif + +/* Handle a ClientHello handshake message. + * If the protocol version in the message is not TLS v1.3 or higher, use + * DoClientHello() + * Only a server will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ClientHello. + * On exit, the index of byte after the ClientHello message and + * padding. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + int ret; + byte b; + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; + word16 totalExtSz; + int usingPSK = 0; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + ssl->chVersion = pv; /* store */ + i += OPAQUE16_LEN; + + if ((ssl->version.major == SSLv3_MAJOR && + ssl->version.minor < TLSv1_3_MINOR) || ssl->options.dtls) { + return DoClientHello(ssl, input, inOutIdx, helloSz); + } + + /* Client random */ + XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); + i += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("client random"); + WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); +#endif + + + /* Session id - empty in TLS v1.3 */ + b = input[i++]; + if (b != 0) { + WOLFSSL_MSG("Client sent session id - not supported"); + return BUFFER_ERROR; + } + + /* Cipher suites */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &clSuites.suiteSz); + i += OPAQUE16_LEN; + /* suites and compression length check */ + if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + i += clSuites.suiteSz; + clSuites.hashSigAlgoSz = 0; + + /* Compression */ + b = input[i++]; + if ((i - begin) + b > helloSz) + return BUFFER_ERROR; + if (b != COMP_LEN) { + WOLFSSL_MSG("Must be one compression type in list"); + return INVALID_PARAMETER; + } + b = input[i++]; + if (b != NO_COMPRESSION) { + WOLFSSL_MSG("Must be no compression type in list"); + return INVALID_PARAMETER; + } + + /* TLS v1.3 ClientHello messages will have extensions. */ + if ((i - begin) >= helloSz) { + WOLFSSL_MSG("ClientHello must have extensions in TLS v1.3"); + return BUFFER_ERROR; + } + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + +#ifdef HAVE_QSH + QSH_Init(ssl); +#endif + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; + + /* Parse extensions */ + if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, + &clSuites))) { + return ret; + } + +#ifdef HAVE_STUNNEL + if ((ret = SNI_Callback(ssl)) != 0) + return ret; +#endif /*HAVE_STUNNEL*/ + + if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) + ssl->version.minor = pv.minor; + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + /* Process the Pre-Shared Key extension if present. */ + ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); + if (ret != 0) + return ret; +#endif + + if (!usingPSK) { + ret = MatchSuite(ssl, &clSuites); + if (ret < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return ret; + } + +#ifndef NO_PSK + if (ssl->options.resuming) { + ssl->options.resuming = 0; + XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size); + /* May or may not have done any hashing. */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + } +#endif + + ret = HashInput(ssl, input + begin, helloSz); + if (ret != 0) + return ret; + } + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + + return 0; +} + +/* Send the HelloRetryRequest message to indicate the negotiated protocol + * version and security parameters the server is willing to use. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13HelloRetryRequest(WOLFSSL *ssl) +{ + int ret; + byte* output; + word32 length; + word32 len; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + /* Get the length of the extensions that will be written. */ + len = TLSX_GetResponseSize(ssl, hello_retry_request); + /* There must be extensions sent to indicate what client needs to do. */ + if (len == 0) + return MISSING_HANDSHAKE_DATA; + + /* Protocol version + Extensions */ + length = OPAQUE16_LEN + len; + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + ret = CheckAvailableSize(ssl, sendSz); + if (ret != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + /* Add record and hanshake headers. */ + AddTls13Headers(output, length, hello_retry_request, ssl); + + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * output[idx++] = ssl->version.major; + * output[idx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* Add TLS extensions. */ + TLSX_WriteResponse(ssl, output + idx, hello_retry_request); + idx += len; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("HelloRetryRequest", &ssl->timeoutInfo, output, sendSz, + ssl->heap); +#endif + + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + ssl->buffers.outputBuffer.length += sendSz; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + +/* Send TLS v1.3 ServerHello message to client. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13ServerHello(WOLFSSL* ssl) +{ + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + + /* Protocol version, server random, cipher suite and extensions. */ + length = VERSION_SZ + RAN_LEN + SUITE_LEN + + TLSX_GetResponseSize(ssl, server_hello); + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, server_hello, ssl); + + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * output[idx++] = ssl->version.major; + * output[idx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* TODO: [TLS13] Last 8 bytes have special meaning. */ + /* Generate server random. */ + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + /* Store in SSL for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); + idx += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Server random"); + WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); +#endif + + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + + /* Extensions */ + TLSX_WriteResponse(ssl, output + idx, server_hello); + + ssl->buffers.outputBuffer.length += sendSz; + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + +/* Send the rest of the extensions encrypted under the handshake key. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13EncryptedExtensions(WOLFSSL *ssl) +{ + int ret; + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + ssl->keys.encryptionOn = 1; + + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + /* Derive the handshake secret now that we are at first message to be + * encrypted under the keys. + */ + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + + /* Setup encrypt/decrypt keys for following messages. */ + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + + length = TLSX_GetResponseSize(ssl, encrypted_extensions); + sendSz = idx + length; + /* Encryption always on. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + ret = CheckAvailableSize(ssl, sendSz); + if (ret != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, encrypted_extensions, ssl); + + TLSX_WriteResponse(ssl, output + idx, encrypted_extensions); + idx += length; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("EncryptedExtensions", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("EncryptedExtensions", &ssl->timeoutInfo, output, + sendSz, ssl->heap); +#endif + + /* This handshake message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 1, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + +#ifndef NO_CERTS +/* Send the TLS v1.3 CertificateRequest message. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13CertificateRequest(WOLFSSL* ssl) +{ + byte *output; + int ret; + int sendSz; + int reqCtxLen = 0; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + int reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ; + + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) + return 0; /* not needed */ + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + /* Always encrypted and make room for padding. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, reqSz, certificate_request, ssl); + + /* Certificate request context. */ + /* TODO: [TLS13] Request context for post-handshake auth. + * Must be unique in the scope of the connection. + */ + output[i++] = reqCtxLen; + + /* supported hash/sig */ + c16toa(ssl->suites->hashSigAlgoSz, &output[i]); + i += LENGTH_SZ; + + XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; + + /* Certificate authorities not supported yet - empty buffer. */ + c16toa(0, &output[i]); + i += REQ_HEADER_SZ; + + /* Certificate extensions. */ + /* TODO: [TLS13] Add extension handling. */ + c16toa(0, &output[i]); /* auth's */ + i += REQ_HEADER_SZ; + + /* Always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + return SendBuffered(ssl); + return 0; +} +#endif /* NO_CERTS */ +#endif /* NO_WOLFSSL_SERVER */ + +#ifndef NO_CERTS +#if !defined(NO_RSA) || defined(HAVE_ECC) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + output[0] = hashAlgo; + output[1] = rsa_sa_algo; + break; +#endif + /* PSS signatures: 0x080[4-6] */ + /* ED25519: 0x0807 */ + /* ED448: 0x0808 */ + } +} + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + */ +static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + case 0x08: + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= 0x06) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + break; + /* ED25519: 0x0807 */ + /* ED448: 0x0808 */ + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} + +/* Get the hash of the messages so far. + * + * ssl The SSL/TLS object. + * hash The buffer to write the hash to. + * returns the length of the hash. + */ +static INLINE int GetMsgHash(WOLFSSL *ssl, byte* hash) +{ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + return SHA256_DIGEST_SIZE; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + return SHA384_DIGEST_SIZE; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + return SHA512_DIGEST_SIZE; + #endif /* WOLFSSL_SHA512 */ + } + return 0; +} + +/* The length of the certificate verification label - client and server. */ +#define CERT_VFY_LABEL_SZ 34 +/* The server certificate verification label. */ +static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, server CertificateVerify"; +/* The client certificate verification label. */ +static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, client CertificateVerify"; + +/* The number of prefix bytes for signature data. */ +#define SIGNING_DATA_PREFIX_SZ 64 +/* The prefix byte in the signature data. */ +#define SIGNING_DATA_PREFIX_BYTE 0x20 +/* Maximum length of the signature data. */ +#define MAX_SIG_DATA_SZ (SIGNING_DATA_PREFIX_SZ + \ + CERT_VFY_LABEL_SZ + \ + MAX_DIGEST_SIZE) + +/* Create the signature data for TLS v1.3 certificate verification. + * + * ssl The SSL/TLS object. + * sigData The signature data. + * sigDataSz The length of the signature data. + * check Indicates this is a check not create. + */ +static void CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, + int check) +{ + word16 idx; + int side = ssl->options.side; + + /* Signature Data = Prefix | Label | Handshake Hash */ + XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ); + idx = SIGNING_DATA_PREFIX_SZ; + + #ifndef NO_WOLFSSL_SERVER + if ((side == WOLFSSL_SERVER_END && check) || + (side == WOLFSSL_CLIENT_END && !check)) { + XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ); + } + #endif + #ifndef NO_WOLFSSL_CLIENT + if ((side == WOLFSSL_CLIENT_END && check) || + (side == WOLFSSL_SERVER_END && !check)) { + XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ); + } + #endif + idx += CERT_VFY_LABEL_SZ; + + *sigDataSz = idx + GetMsgHash(ssl, &sigData[idx]); +} + +#ifndef NO_RSA +/* Encode the PKCS #1.5 RSA signature. + * + * sig The buffer to place the encoded signature into. + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, + int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int hashOid = 0; + int ret = BAD_FUNC_ARG; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, sigData); + wc_Sha256Free(&digest.sha256); + } + hashSz = SHA256_DIGEST_SIZE; + hashOid = SHA256h; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, sigData); + wc_Sha384Free(&digest.sha384); + } + hashSz = SHA384_DIGEST_SIZE; + hashOid = SHA384h; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, sigData); + wc_Sha512Free(&digest.sha512); + } + hashSz = SHA512_DIGEST_SIZE; + hashOid = SHA512h; + break; +#endif + } + + if (ret != 0) + return ret; + + /* Encode the signature data as per PKCS #1.5 */ + return wc_EncodeSignature(sig, sigData, hashSz, hashOid); +} + +#ifdef HAVE_ECC +/* Encode the ECC signature. + * + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int ret = BAD_FUNC_ARG; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, sigData); + wc_Sha256Free(&digest.sha256); + } + hashSz = SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, sigData); + wc_Sha384Free(&digest.sha384); + } + hashSz = SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, sigData); + wc_Sha512Free(&digest.sha512); + } + hashSz = SHA512_DIGEST_SIZE; + break; +#endif + } + + if (ret != 0) + return ret; + + return hashSz; +} +#endif + + +/* Check that the decrypted signature matches the encoded signature + * based on the digest of the signature data. + * + * ssl The SSL/TLS object. + * hashAlgo The signature algorithm used to generate signature. + * hashAlgo The hash algorithm used to generate signature. + * decSig The decrypted signature. + * decSigSz The size of the decrypted signature. + * returns 0 on success, otherwise failure. + */ +static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, + byte* decSig, word32 decSigSz) +{ + int ret = 0; + byte sigData[MAX_SIG_DATA_SZ]; + word16 sigDataSz; +#ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; +#else + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + word32 sigSz; + + if (sigAlgo == rsa_sa_algo) { +#ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ret = MEMORY_E; + goto end; + } +#endif + + CreateSigData(ssl, sigData, &sigDataSz, 1); + sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, hashAlgo); + /* Check the encoded and decrypted signature data match. */ + if (decSigSz != sigSz || decSig == NULL || + XMEMCMP(decSig, encodedSig, sigSz) != 0) { + ret = VERIFY_CERT_ERROR; + } + } + else { + CreateSigData(ssl, sigData, &sigDataSz, 1); + sigSz = CreateECCEncodedSig(sigData, sigDataSz, hashAlgo); + if (decSigSz != sigSz || decSig == NULL) + ret = VERIFY_CERT_ERROR; + else { + decSig -= 2 * decSigSz; + XMEMCPY(decSig, sigData, decSigSz); + decSig -= 8; + XMEMSET(decSig, 0, 8); + CreateECCEncodedSig(decSig, 8 + decSigSz * 2, hashAlgo); + if (XMEMCMP(decSig, decSig + 8 + decSigSz * 2, decSigSz) != 0) + ret = VERIFY_CERT_ERROR; + } + } + +#ifdef WOLFSSL_SMALL_STACK +end: + if (encodedSig != NULL) + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* !NO_RSA */ +#endif /* !NO_RSA || HAVE_ECC */ + +/* Get the next certificate from the list for writing into the TLS v1.3 + * Certificate message. + * + * data The certificate list. + * length The length of the certificate data in the list. + * idx The index of the next certificate. + * returns the length of the certificate data. 0 indicates no more certificates + * in the list. + */ +static word32 NextCert(byte* data, word32 length, word32* idx) +{ + word32 len; + + /* Is index at end of list. */ + if (*idx == length) + return 0; + + /* Length of the current ASN.1 encoded certificate. */ + c24to32(data + *idx, &len); + /* Include the length field. */ + len += 3; + + /* Move index to next certificate and return the current certificate's + * length. + */ + *idx += len; + return len; +} + +/* Add certificate data and empty extension to output up to the fragment size. + * + * cert The certificate data to write out. + * len The length of the certificate data. + * idx The start of the certificate data to write out. + * fragSz The maximum size of this fragment. + * output The buffer to write to. + * returns the number of bytes written. + */ +static word32 AddCertExt(byte* cert, word32 len, word32 idx, word32 fragSz, + byte* output) +{ + word32 i = 0; + word32 copySz = min(len - idx, fragSz); + + if (idx < len) { + XMEMCPY(output, cert + idx, copySz); + i = copySz; + } + + if (copySz + OPAQUE16_LEN <= fragSz) { + /* Empty extension */ + output[i++] = 0; + output[i++] = 0; + } + + return i; +} + +/* Send the certificate for this end and any CAs that help with validation. + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13Certificate(WOLFSSL* ssl) +{ + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word32 length, maxFragment; + word32 len = 0; + word32 idx = 0; + word32 offset = OPAQUE16_LEN; + byte* p = NULL; + + + /* TODO: [TLS13] Request context for post-handshake auth. + * Taken from request if post-handshake. + */ + + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + certSz = 0; + certChainSz = 0; + headerSz = CERT_HEADER_SZ; + length = CERT_HEADER_SZ; + listSz = 0; + } + else { + if (!ssl->buffers.certificate) { + WOLFSSL_MSG("Send Cert missing certificate buffer"); + return BUFFER_ERROR; + } + /* Certificate Data */ + certSz = ssl->buffers.certificate->length; + /* Cert Req Ctx Len | Cert List Len | Cert Data Len */ + headerSz = OPAQUE8_LEN + CERT_HEADER_SZ + CERT_HEADER_SZ; + /* Length of message data with one certificate and empty extensions. */ + length = headerSz + certSz + OPAQUE16_LEN; + /* Length of list data with one certificate and empty extensions. */ + listSz = CERT_HEADER_SZ + certSz + OPAQUE16_LEN; + + /* Send rest of chain if sending cert (chain has leading size/s). */ + if (certSz > 0 && ssl->buffers.certChainCnt > 0) { + /* The pointer to the current spot in the cert chain buffer. */ + p = ssl->buffers.certChain->buffer; + /* Chain length including extensions. */ + certChainSz = ssl->buffers.certChain->length + + OPAQUE16_LEN * ssl->buffers.certChainCnt; + length += certChainSz; + listSz += certChainSz; + } + else + certChainSz = 0; + } + + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + maxFragment = MAX_RECORD_SIZE; + + #ifdef HAVE_MAX_FRAGMENT + if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment) + maxFragment = ssl->max_fragment; + #endif /* HAVE_MAX_FRAGMENT */ + + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz = 0; + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; + + if (ssl->fragOffset == 0) { + if (headerSz + certSz + OPAQUE16_LEN + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + + fragSz = headerSz + certSz + OPAQUE16_LEN + certChainSz; + } + else { + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + + /* Request context. */ + output[i++] = 0; + length -= 1; + fragSz -= 1; + /* Certificate list length. */ + c32to24(listSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + /* Leaf certificate data length. */ + if (certSz > 0) { + c32to24(certSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + } + } + else + AddTls13RecordHeader(output, fragSz, handshake, ssl); + + /* TODO: [TLS13] Test with fragments and multiple CA certs */ + if (certSz > 0 && ssl->fragOffset < certSz + OPAQUE16_LEN) { + /* Put in the leaf certificate and empty extension. */ + word32 copySz = AddCertExt(ssl->buffers.certificate->buffer, certSz, + ssl->fragOffset, fragSz, output + i); + + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + if (certChainSz > 0 && fragSz > 0) { + /* Put in the CA certificates with empty extensions. */ + while (fragSz > 0) { + word32 l; + + if (offset == len + OPAQUE16_LEN) { + /* Find next CA certificate to write out. */ + offset = 0; + len = NextCert(ssl->buffers.certChain->buffer, + ssl->buffers.certChain->length, &idx); + if (len == 0) + break; + } + + /* Write out certificate and empty extension. */ + l = AddCertExt(p, len, offset, fragSz, output + i); + i += l; + ssl->fragOffset += l; + length -= l; + fragSz -= l; + offset += l; + } + } + + if ((int)i - RECORD_HEADER_SZ < 0) { + WOLFSSL_MSG("Send Cert bad inputSz"); + return BUFFER_E; + } + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, + output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + + return ret; +} + +typedef struct Scv13Args { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + byte* input; + word32 idx; + word32 sigLen; + int sendSz; + word16 length; + + byte* sigData; + word16 sigDataSz; +} Scv13Args; + +static void FreeScv13Args(WOLFSSL* ssl, void* pArgs) +{ + Scv13Args* args = (Scv13Args*)pArgs; + + (void)ssl; + +#ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } +#endif + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->sigData = NULL; + } + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; + } +} + +/* Send the TLS v1.3 CertificateVerify message. + * A hash of all the message so far is used. + * The signed data is: + * 0x20 * 64 | context string | 0x00 | hash of messages + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13CertificateVerify(WOLFSSL* ssl) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Scv13Args* args = (Scv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Scv13Args args[1]; +#endif + + WOLFSSL_ENTER("SendTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_scv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Scv13Args)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + return 0; /* sent blank cert, can't verify */ + } + + args->sendSz = MAX_CERT_VERIFY_SZ; + /* Always encrypted. */ + args->sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scv; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* idx is used to track verify pointer offset to output */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) + goto exit_scv; + + /* Add signature algorithm. */ + EncodeSigAlg(ssl->suites->hashAlgo, ssl->hsType, args->verify); + + /* Create the data to be signed. */ + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); + + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* build encoded signature buffer */ + sig->length = MAX_ENCODED_SIG_SZ; + sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + /* Digest the signature data and encode. Used in verify too. */ + ret = CreateRSAEncodedSig(sig->buffer, args->sigData, + args->sigDataSz, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + sig->length = ret; + ret = 0; + + /* Maximum size of RSA Signature. */ + args->sigLen = args->length; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + sig->length = args->sendSz - args->idx - HASH_SIG_SIZE - + VERIFY_HEADER; + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + args->sigDataSz = ret; + ret = 0; + } + #endif /* HAVE_ECC */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ret = EccSign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + &sig->length, (ecc_key*)ssl->hsKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->EccSignCtx + #else + NULL, 0, NULL + #endif + ); + args->length = sig->length; + } + #endif /* HAVE_ECC */ + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + ret = RsaSign(ssl, sig->buffer, sig->length, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, + (RsaKey*)ssl->hsKey, + ssl->buffers.key->buffer, ssl->buffers.key->length, + #ifdef HAVE_PK_CALLBACKS + ssl->RsaSignCtx + #else + NULL + #endif + ); + args->length = args->sigLen; + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Add signature length. */ + c16toa(args->length, args->verify + HASH_SIG_SIZE); + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigLen, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->verifySig == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + XMEMCPY(args->verifySig, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + args->sigLen); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, args->verifySig, args->sigLen, + sig->buffer, sig->length, (RsaKey*)ssl->hsKey); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + /* Put the record and handshake headers on. */ + AddTls13Headers(args->output, args->length + HASH_SIG_SIZE + VERIFY_HEADER, + certificate_verify, ssl); + + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + args->length + + HASH_SIG_SIZE + VERIFY_HEADER; + + /* This message is always encrypted. */ + args->sendSz = BuildTls13Message(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->output + RECORD_HEADER_SZ, + args->sendSz - RECORD_HEADER_SZ, handshake, + 1, 0); + if (args->sendSz < 0) { + ret = args->sendSz; + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, + args->output, args->sendSz, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += args->sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scv: + + WOLFSSL_LEAVE("SendTls13CertificateVerify", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeScv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + + +/* Parse and handle a TLS v1.3 Certificate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Certificate. + * On exit, the index of byte after the Certificate message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + return ProcessPeerCerts(ssl, input, inOutIdx, totalSz); +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) + +typedef struct Dcv13Args { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + + byte* sigData; + word16 sigDataSz; +} Dcv13Args; + +static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs) +{ + Dcv13Args* args = (Dcv13Args*)pArgs; + + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->sigData = NULL; + } + + (void)ssl; +} + +/* Parse and handle a TLS v1.3 CertificateVerify message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * CertificateVerify. + * On exit, the index of byte after the CertificateVerify message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Dcv13Args* args = (Dcv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dcv13Args args[1]; +#endif + + WOLFSSL_ENTER("DoTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dcv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dcv13Args)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateVerify", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateVerify", + &ssl->timeoutInfo); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* Signature algorithm. */ + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + DecodeSigAlg(input + args->idx, &args->hashAlgo, &args->sigAlgo); + args->idx += OPAQUE16_LEN; + /* TODO: [TLS13] was it in SignatureAlgorithms extension? */ + + /* Signature length. */ + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; + + /* Signature data. */ + if ((args->idx - args->begin) + args->sz > totalSz || + args->sz > ENCRYPT_LEN) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + /* Check for public key of required type. */ + if (args->sigAlgo == ecc_dsa_sa_algo && + !ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + if ((args->sigAlgo == rsa_sa_algo || + args->sigAlgo == rsa_pss_sa_algo) && + (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + + sig->buffer = XMALLOC(args->sz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + sig->length = args->sz; + XMEMCPY(sig->buffer, input + args->idx, args->sz); + + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, args->hashAlgo); + if (ret < 0) + goto exit_dcv; + args->sigDataSz = ret; + ret = 0; + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifndef NO_RSA + if (args->sigAlgo == rsa_sa_algo || + args->sigAlgo == rsa_pss_sa_algo) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, sig->buffer, sig->length, &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx + #else + NULL, 0, NULL + #endif + ); + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + ret = EccVerify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + 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.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo, + args->output, args->sendSz); + if (ret != 0) + goto exit_dcv; + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + ssl->options.havePeerVerify = 1; + + /* Set final index */ + args->idx += args->sz; + *inOutIdx = args->idx; + + /* Encryption is always on: add padding */ + *inOutIdx += ssl->keys.padSz; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + + case TLS_ASYNC_END: + { + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dcv: + + WOLFSSL_LEAVE("DoTls13CertificateVerify", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeDcv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} +#endif /* !NO_RSA || HAVE_ECC */ + +/* Parse and handle a TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size Length of message data. + * totalSz Length of remaining data in the message buffer. + * sniff Indicates whether we are sniffing packets. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz, int sniff) +{ + int ret; + word32 finishedSz = 0; + byte* secret; + byte mac[MAX_DIGEST_SIZE]; + + /* check against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* All the handshake messages have been received to calculate + * client and server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + else + secret = ssl->keys.client_write_MAC_secret; + + ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz); + if (ret != 0) + return ret; + if (size != finishedSz) + return BUFFER_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); + #endif + + if (sniff == NO_SNIFF) { + /* Actually check verify data. */ + if (XMEMCMP(input + *inOutIdx, mac, size) != 0){ + WOLFSSL_MSG("Verify finished error on hashes"); + return VERIFY_FINISHED_ERROR; + } + } + + /* Force input exhaustion at ProcessReply by consuming padSz. */ + *inOutIdx += size + ssl->keys.padSz; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Setup keys for application data messages from client. */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + } + +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + if (!ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } +#endif +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif + + return 0; +} +#endif /* NO_CERTS */ + +/* Send the TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13Finished(WOLFSSL* ssl) +{ + int sendSz; + int finishedSz = ssl->specs.hash_size; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + byte* secret; + + outputSz = MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + + /* make finished hashes */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + secret = ssl->keys.client_write_MAC_secret; + else { + /* All the handshake messages have been done to calculate client and + * server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL); + if (ret != 0) + return ret; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + finishedSz, handshake, 1, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + if (!ssl->options.resuming) { +#ifndef NO_SESSION_CACHE + AddSession(ssl); /* just try */ +#endif + } + else { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + if (ret != 0) + return ret; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Can send application data now. */ + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* Setup keys for application data messages. */ + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + +#ifndef NO_PSK + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); +#endif + } + + return ret; +} + +/* Send the TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13KeyUpdate(WOLFSSL* ssl) +{ + int sendSz; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl); + + /* If: + * 1. I haven't sent a KeyUpdate requesting a response and + * 2. This isn't responding to peer KeyUpdate requiring a response then, + * I want a response. + */ + ssl->keys.updateResponseReq = output[i++] = + !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond; + /* Sent response, no longer need to respond. */ + ssl->keys.keyUpdateRespond = 0; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + OPAQUE8_LEN, handshake, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("KeyUpdate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("KeyUpdate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + if (ret != 0 && ret != WANT_WRITE) + return ret; + + /* Future traffic uses new encryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY)) + != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + return ret; +} + +/* Parse and handle a TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret; + word32 i = *inOutIdx; + + /* check against totalSz */ + if (OPAQUE8_LEN != totalSz) + return BUFFER_E; + + switch (input[i]) { + case update_not_requested: + /* This message in response to any oustanding request. */ + ssl->keys.keyUpdateRespond = 0; + ssl->keys.updateResponseReq = 0; + break; + case update_requested: + /* New key update requiring a response. */ + ssl->keys.keyUpdateRespond = 1; + break; + default: + return INVALID_PARAMETER; + break; + } + + /* Move index to byte after message. */ + *inOutIdx += totalSz; + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + /* Future traffic uses new decryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY)) != 0) + return ret; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + if (ssl->keys.keyUpdateRespond) + return SendTls13KeyUpdate(ssl); + return 0; +} + +#ifndef NO_WOLFSSL_CLIENT +/* Handle a New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size The length of the current handshake message. + * retuns 0 on success, otherwise failure. + */ +static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ +#ifdef HAVE_SESSION_TICKET + word32 begin = *inOutIdx; + word32 lifetime; + word32 ageAdd; + word16 length; + + /* Lifetime hint. */ + if ((*inOutIdx - begin) + SESSION_HINT_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &lifetime); + *inOutIdx += SESSION_HINT_SZ; + if (lifetime > MAX_LIFETIME) + return SERVER_HINT_ERROR; + + /* Age add. */ + if ((*inOutIdx - begin) + SESSION_ADD_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &ageAdd); + *inOutIdx += SESSION_ADD_SZ; + + /* Ticket length. */ + if ((*inOutIdx - begin) + LENGTH_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += LENGTH_SZ; + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + /* Free old dynamic ticket if we already had one. */ + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + /* Reset back to static by default. */ + ssl->session.ticket = NULL; + ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session.staticTicket; + } + /* Use dynamic ticket if required.*/ + if (length > sizeof(ssl->session.staticTicket)) { + ssl->session.ticket = (byte*)XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (ssl->session.ticket == NULL) + return MEMORY_E; + ssl->session.isDynamic = 1; + } + + /* Copy in ticket data (server identity). */ + XMEMCPY(ssl->session.ticket, input + *inOutIdx, length); + *inOutIdx += length; + ssl->timeout = lifetime; + ssl->session.ticketLen = length; + ssl->session.timeout = lifetime; + ssl->session.ticketAdd = ageAdd; + ssl->session.ticketSeen = TimeNowInMilliseconds(); + if (ssl->session_ticket_cb != NULL) { + ssl->session_ticket_cb(ssl, ssl->session.ticket, + ssl->session.ticketLen, + ssl->session_ticket_ctx); + } + ssl->options.haveSessionId = 1; + XMEMCPY(ssl->arrays->sessionID, ssl->session.ticket + length - ID_LEN, + ID_LEN); + ssl->session.cipherSuite0 = ssl->options.cipherSuite0; + ssl->session.cipherSuite = ssl->options.cipherSuite; + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* No extension support - skip over extensions. */ + if ((*inOutIdx - begin) + EXTS_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += EXTS_SZ; + if ((*inOutIdx - begin) + length != size) + return BUFFER_ERROR; + *inOutIdx += length; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ssl->expect_session_ticket = 0; +#else + (void)ssl; + (void)input; + *inOutIdx += size + ssl->keys.padSz; +#endif /* HAVE_SESSION_TICKET */ + + return 0; +} +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + #ifdef HAVE_SESSION_TICKET +/* Send New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * retuns 0 on success, otherwise failure. + */ +int SendTls13NewSessionTicket(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + if (!ssl->options.noTicketTls13) { + ret = CreateTicket(ssl); + if (ret != 0) return ret; + } + + /* Lifetime | Age Add | Ticket | Extensions */ + length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ + + ssl->session.ticketLen + EXTS_SZ; + sendSz = idx + length + MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, session_ticket, ssl); + + /* Lifetime hint */ + c32toa(ssl->ctx->ticketHint, output + idx); + idx += SESSION_HINT_SZ; + /* Age add - obfuscator */ + c32toa(ssl->session.ticketAdd, output + idx); + idx += SESSION_ADD_SZ; + + /* length */ + c16toa(ssl->session.ticketLen, output + idx); + idx += LENGTH_SZ; + /* ticket */ + XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); + idx += ssl->session.ticketLen; + + /* No extension support - empty extensions. */ + c16toa(0, output + idx); + idx += EXTS_SZ; + + ssl->options.haveSessionId = 1; + + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); +} + #endif /* HAVE_SESSION_TICKET */ +#endif /* NO_WOLFSSL_SERVER */ + +/* Make sure no duplicates, no fast forward, or other problems + * + * ssl The SSL/TLS object. + * type Type of handshake message received. + * returns 0 on success, otherwise failure. + */ +static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) +{ + /* verify not a duplicate, mark received, check state */ + switch (type) { + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + if (ssl->msgsReceived.got_client_hello == 2) { + WOLFSSL_MSG("Too many ClientHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_client_hello++; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + if (ssl->msgsReceived.got_session_ticket) { + WOLFSSL_MSG("Duplicate SessionTicket received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + if (ssl->msgsReceived.got_hello_retry_request) { + WOLFSSL_MSG("Duplicate HelloRetryRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_retry_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case encrypted_extensions: + if (ssl->msgsReceived.got_encrypted_extensions) { + WOLFSSL_MSG("Duplicate EncryptedExtensions received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_encrypted_extensions = 1; + + break; +#endif + + case certificate: + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ( ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if ( ssl->msgsReceived.got_client_hello == 0) { + WOLFSSL_MSG("No ClientHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + + case certificate_verify: + if (ssl->msgsReceived.got_certificate_verify) { + WOLFSSL_MSG("Duplicate CertificateVerify received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_verify = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + break; + + case finished: + if (ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("Duplicate Finished received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_finished = 1; + + break; + + case key_update: + if (!ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("No KeyUpdate before Finished"); + return OUT_OF_ORDER_E; + } + break; + + default: + WOLFSSL_MSG("Unknown message type"); + return SANITY_MSG_E; + } + + return 0; +} + +/* Handle a type of handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * size The length of the current handshake message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, + byte type, word32 size, word32 totalSz) +{ + int ret = 0; + (void)totalSz; + word32 inIdx = *inOutIdx; + + WOLFSSL_ENTER("DoTls13HandShakeMsgType"); + + /* make sure can read the message */ + if (*inOutIdx + size > totalSz) + return INCOMPLETE_DATA; + + /* sanity check msg received */ + if ( (ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + return ret; + } + +#ifdef WOLFSSL_CALLBACKS + /* add name later, add on record and handshake header part back on */ + if (ssl->toInfoOn) { + int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add, + size + add, ssl->heap); + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + } +#endif + + if (ssl->options.handShakeState == HANDSHAKE_DONE && + type != session_ticket && type != certificate_request && + type != key_update) { + WOLFSSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && !ssl->options.dtls && + ssl->options.serverState == NULL_STATE && + type != server_hello && type != hello_retry_request) { + WOLFSSL_MSG("First server message not server hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls && + type == server_hello_done && + ssl->options.serverState < SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("Server hello done received before server hello in DTLS"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.clientState == NULL_STATE && type != client_hello) { + WOLFSSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + /* above checks handshake state */ + switch (type) { + +#ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + WOLFSSL_MSG("processing hello rety request"); + ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size); + break; + + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoTls13ServerHello(ssl, input, inOutIdx, size); + break; + +#ifndef NO_CERTS + case certificate_request: + WOLFSSL_MSG("processing certificate request"); + ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size); + break; +#endif + + case session_ticket: + WOLFSSL_MSG("processing new session ticket"); + ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size); + break; + + case encrypted_extensions: + WOLFSSL_MSG("processing encrypted extensions"); + ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_CERTS + case certificate: + WOLFSSL_MSG("processing certificate"); + ret = DoTls13Certificate(ssl, input, inOutIdx, size); + break; +#endif + +#if !defined(NO_RSA) || defined(HAVE_ECC) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* !NO_RSA || HAVE_ECC */ + + case finished: + WOLFSSL_MSG("processing finished"); + ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + break; + + case key_update: + WOLFSSL_MSG("processing finished"); + ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size); + break; + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoTls13ClientHello(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_SERVER */ + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + + if (ret == 0 && type != client_hello && type != session_ticket && + type != key_update && ssl->error != WC_PENDING_E) { + ret = HashInput(ssl, input + inIdx, size); + } + + if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) + SendAlert(ssl, alert_fatal, decode_error); + + if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || + ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || + ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + + if (ssl->options.tls1_3) { + if (type == server_hello && ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + + /* setup decrypt keys for following messages */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + + if (type == finished && ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + } + +#ifndef NO_PSK + if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) + DeriveResumptionSecret(ssl, ssl->session.masterSecret); +#endif + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async, offset index so this msg will be processed again */ + if (ret == WC_PENDING_E) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + } +#endif + + WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret); + return ret; +} + + +/* Handle a handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; + word32 inputLength; + + WOLFSSL_ENTER("DoTls13HandShakeMsg()"); + + if (ssl->arrays == NULL) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) + return PARSE_ERROR; + + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx; + + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ + if (ssl->arrays->pendingMsgSz == 0) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0) + return PARSE_ERROR; + + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + return HANDSHAKE_SIZE_ERROR; + } + + /* size is the size of the certificate message payload */ + if (inputLength - HANDSHAKE_HEADER_SZ < size) { + ssl->arrays->pendingMsgType = type; + ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; + ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, + ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays->pendingMsg == NULL) + return MEMORY_E; + XMEMCPY(ssl->arrays->pendingMsg, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + inputLength); + ssl->arrays->pendingMsgOffset = inputLength; + *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + else { + if (inputLength + ssl->arrays->pendingMsgOffset > + ssl->arrays->pendingMsgSz) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = 0; + ret = DoTls13HandShakeMsgType(ssl, + ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, + ssl->arrays->pendingMsgSz); + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + + WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret); + return ret; +} + +/* The client connecting to the server. + * The protocol version is expecting to be TLS v1.3. + * If the server downgrades, and older versions of the protocol are compiled + * in, the client will fallback to wolfSSL_connect(). + * Please see note at top of README if you get an error from connect. + * + * ssl The SSL/TLS object. + * returns SSL_SUCCESS on successful handshake, SSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_connect_TLSv13(WOLFSSL* ssl) +{ + int neededState; + + WOLFSSL_ENTER("wolfSSL_connect_TLSv13()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl->options.side != WOLFSSL_CLIENT_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN: + /* Always send client hello first. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; + + case CLIENT_HELLO_SENT: + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + /* Get the response/s from the server. */ + while (ssl->options.serverState < neededState) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state. */ + if (neededState == SERVER_FINISHED_COMPLETE && + !ssl->options.resuming) { + neededState = SERVER_HELLODONE_COMPLETE; + } + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + + case HELLO_AGAIN: + if (ssl->options.certOnly) + return SSL_SUCCESS; + + if (!ssl->options.tls1_3) + return wolfSSL_connect(ssl); + + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + ssl->options.serverState = NULL_STATE; + /* Try again with different security parameters. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + + case HELLO_AGAIN_REPLY: + if (ssl->options.serverState == NULL_STATE) { + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + + /* Get the response/s from the server. */ + while (ssl->options.serverState < neededState) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) + neededState = SERVER_HELLODONE_COMPLETE; + } + } + } + + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; + + case FIRST_REPLY_DONE: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13Certificate(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; + + case FIRST_REPLY_FIRST: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13CertificateVerify(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; + + case FIRST_REPLY_SECOND: + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; + + case FINISHED_DONE: +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb != NULL) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return SSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS); + return SSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return SSL_FATAL_ERROR; /* unknown connect state */ + } +} + +/* Create a key share entry from group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * group The named group. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) +{ + int ret = BAD_FUNC_ARG; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + if (ret != 0) + return ret; + + return SSL_SUCCESS; +} + +/* Send no key share entries - use HelloRetryRequest to negotiate shared group. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_NoKeyShares(WOLFSSL* ssl) +{ + int ret = BAD_FUNC_ARG; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + + return SSL_SUCCESS; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_SESSION_TICKET + ctx->noTicketTls13 = 1; +#endif + + return 0; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on + * a client and 0 on success. + */ +int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version) || + ssl->options.side == WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + +#ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = 1; +#endif + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->noPskDheKe = 1; + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on + * success. + */ +int wolfSSL_no_dhe_psk(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ssl->options.noPskDheKe = 1; + + return 0; +} + +/* Update the keys for encryption and decryption. + * If using non-blocking I/O and SSL_ERROR_WANT_WRITE is returned then + * calling wolfSSL_write() will have the message sent when ready. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write, + * SSL_SUCCESS on success and otherwise failure. + */ +int wolfSSL_update_keys(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ret = SendTls13KeyUpdate(ssl); + if (ret == WANT_WRITE) + ret = SSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = SSL_SUCCESS; + return ret; +} + +/* The server accepting a connection from a client. + * The protocol version is expecting to be TLS v1.3. + * If the client downgrades, and older versions of the protocol are compiled + * in, the server will fallback to wolfSSL_accept(). + * Please see note at top of README if you get an error from accept. + * + * ssl The SSL/TLS object. + * returns SSL_SUCCESS on successful handshake, SSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_accept_TLSv13(WOLFSSL* ssl) +{ + word16 havePSK = 0; + word16 haveAnon = 0; + WOLFSSL_ENTER("SSL_accept_TLSv13()"); + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif + (void)havePSK; + +#ifdef HAVE_ANON + haveAnon = ssl->options.haveAnon; +#endif + (void)haveAnon; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + +#ifndef NO_CERTS + /* in case used set_accept_state after init */ + if (!havePSK && !haveAnon && + (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer || + !ssl->buffers.key || + !ssl->buffers.key->buffer)) { + WOLFSSL_MSG("accept error: don't have server cert and key"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } +#endif +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + } +#endif + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + + switch (ssl->options.acceptState) { + + case ACCEPT_BEGIN : + /* get response */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; + + case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case ACCEPT_HELLO_RETRY_REQUEST_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_FIRST_REPLY_DONE : + if ((ssl->error = SendTls13ServerHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; + + case SERVER_HELLO_SENT : + if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_EXTENSIONS_SENT; + WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT"); + FALL_THROUGH; + + case SERVER_EXTENSIONS_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { + ssl->error = SendTls13CertificateRequest(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + } +#endif + ssl->options.acceptState = CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; + + case CERT_REQ_SENT : + ssl->options.acceptState = KEY_EXCHANGE_SENT; +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if ((ssl->error = SendTls13Certificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; + + case CERT_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = CERT_STATUS_SENT; + WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; + + case CERT_VERIFY_SENT : + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; + + case ACCEPT_FINISHED_DONE : +#ifdef HAVE_SESSION_TICKET + /* TODO: [TLS13] Section 4.5.1 Note. */ + if (!ssl->options.resuming && !ssl->options.verifyPeer && + !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TICKET_SENT: + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_SECOND_REPLY_DONE : +#ifdef HAVE_SESSION_TICKET + if (!ssl->options.resuming && ssl->options.verifyPeer && + !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_THIRD_REPLY_DONE: +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return SSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + +#ifdef WOLFSSL_SESSION_EXPORT + if (ssl->dtls_export) { + if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { + WOLFSSL_MSG("Export DTLS session error"); + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + + WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS); + return SSL_SUCCESS; + + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return SSL_FATAL_ERROR; + } +} + + +#undef ERROR_OUT + +#endif /* WOLFCRYPT_ONLY */ + +#endif /* WOLFSSL_TLS13 */ diff --git a/support/wolfssl.pc b/support/wolfssl.pc index 41636af6d7..560a4b9840 100644 --- a/support/wolfssl.pc +++ b/support/wolfssl.pc @@ -5,6 +5,6 @@ includedir=${prefix}/include Name: wolfssl Description: wolfssl C library. -Version: 3.10.0 +Version: 3.11.1 Libs: -L${libdir} -lwolfssl Cflags: -I${includedir} diff --git a/tests/api.c b/tests/api.c index 26eea67942..779e27fbe5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36,6 +36,9 @@ #ifdef HAVE_ECC #include /* wc_ecc_fp_free */ #endif +#ifndef NO_ASN + #include +#endif #include #include @@ -43,9 +46,32 @@ #include #include +#ifndef NO_MD5 + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_SHA256 + #include +#endif +#ifdef WOLFSSL_SHA512 + #include +#endif +#ifdef WOLFSSL_SHA384 + #include +#endif +#ifdef WOLFSSL_RIPEMD + #include +#endif + #ifdef OPENSSL_EXTRA #include #include + #include + #include + #include + #include #ifndef NO_DES3 #include #endif @@ -57,6 +83,16 @@ #endif #include + +typedef struct testVector { + const char* input; + const char* output; + size_t inLen; + size_t outLen; + +} testVector; + + /*----------------------------------------------------------------------------* | Constants *----------------------------------------------------------------------------*/ @@ -70,7 +106,7 @@ static const char* passed = "passed"; static const char* failed = "failed"; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - static const char* bogusFile = + static const char* bogusFile = #ifdef _WIN32 "NUL" #else @@ -79,6 +115,12 @@ static const char* failed = "failed"; ; #endif +enum { + TESTING_RSA = 1, + TESTING_ECC = 2 +}; + + /*----------------------------------------------------------------------------* | Setup *----------------------------------------------------------------------------*/ @@ -195,20 +237,20 @@ static void test_wolfSSL_CTX_use_certificate_file(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCert, + AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCertFile, SSL_FILETYPE_PEM)); /* invalid cert file */ AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile, SSL_FILETYPE_PEM)); /* invalid cert type */ - AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert, 9999)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, 9999)); #ifdef NO_RSA /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert,SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,SSL_FILETYPE_PEM)); #else /* success */ - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -250,21 +292,21 @@ static void test_wolfSSL_CTX_use_PrivateKey_file(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKey, + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKeyFile, SSL_FILETYPE_PEM)); /* invalid key file */ AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile, SSL_FILETYPE_PEM)); /* invalid key type */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, 9999)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, 9999)); /* success */ #ifdef NO_RSA /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #else /* success */ - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -286,11 +328,11 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) SSL_FILETYPE_PEM) != SSL_SUCCESS); assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, SSL_FILETYPE_PEM) != SSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, SSL_FILETYPE_ASN1) != SSL_SUCCESS); /* success */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, SSL_FILETYPE_PEM) + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, SSL_FILETYPE_PEM) == SSL_SUCCESS); /* unload cert */ @@ -331,20 +373,21 @@ static void test_wolfSSL_CTX_load_verify_locations(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCert, 0)); + AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCertFile, 0)); /* invalid ca file */ - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0)); + AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); + AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0)); + #ifndef WOLFSSL_TIRTOS /* invalid path */ /* not working... investigate! */ - /* AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, caCert, bogusFile)); */ + /* AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, bogusFile)); */ #endif /* success */ - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); wolfSSL_CTX_free(ctx); #endif @@ -359,16 +402,16 @@ static void test_wolfSSL_CTX_SetTmpDH_file(void) /* invalid context */ AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(NULL, - dhParam, SSL_FILETYPE_PEM)); + dhParamFile, SSL_FILETYPE_PEM)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, NULL, SSL_FILETYPE_PEM)); AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, bogusFile, SSL_FILETYPE_PEM)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParam, + AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile, SSL_FILETYPE_PEM)); wolfSSL_CTX_free(ctx); @@ -386,7 +429,7 @@ static void test_wolfSSL_CTX_SetTmpDH_buffer(void) AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, dh_key_der_2048, sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, NULL, 0, SSL_FILETYPE_ASN1)); AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dsa_key_der_2048, @@ -414,8 +457,8 @@ static void test_server_wolfSSL_new(void) AssertNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_server_method())); AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); /* invalid context */ AssertNull(ssl = wolfSSL_new(NULL)); @@ -443,7 +486,7 @@ static void test_client_wolfSSL_new(void) AssertNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_client_method())); AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); /* invalid context */ AssertNull(ssl = wolfSSL_new(NULL)); @@ -469,30 +512,30 @@ static void test_wolfSSL_SetTmpDH_file(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #ifndef NO_RSA - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #else - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCert, + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKey, + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, SSL_FILETYPE_PEM)); #endif AssertNotNull(ssl = wolfSSL_new(ctx)); /* invalid ssl */ AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(NULL, - dhParam, SSL_FILETYPE_PEM)); + dhParamFile, SSL_FILETYPE_PEM)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, NULL, SSL_FILETYPE_PEM)); AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, bogusFile, SSL_FILETYPE_PEM)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParam, + AssertIntEQ(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM)); wolfSSL_free(ssl); @@ -517,7 +560,7 @@ static void test_wolfSSL_SetTmpDH_buffer(void) AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, dh_key_der_2048, sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, NULL, 0, SSL_FILETYPE_ASN1)); AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dsa_key_der_2048, @@ -529,13 +572,12 @@ static void test_wolfSSL_SetTmpDH_buffer(void) wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); - printf("SUCCESS4\n"); #endif } /* Test function for wolfSSL_SetMinVersion. Sets the minimum downgrade version - * allowed. + * allowed. * POST: return 1 on success. */ static int test_wolfSSL_SetMinVersion(void) @@ -633,12 +675,17 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #endif ((func_args*)args)->return_code = TEST_FAIL; - method = wolfSSLv23_server_method(); + if (((func_args*)args)->callbacks != NULL && + ((func_args*)args)->callbacks->method != NULL) { + method = ((func_args*)args)->callbacks->method(); + } + else { + method = wolfSSLv23_server_method(); + } ctx = wolfSSL_CTX_new(method); #if defined(USE_WINDOWS_API) - /* Generate random port for testing */ - port = GetRandomPort(); + port = ((func_args*)args)->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ @@ -655,19 +702,19 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0) != SSL_SUCCESS) { /*err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } - if (wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ goto done; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load server key file, " @@ -686,7 +733,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + wolfSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif @@ -776,26 +823,32 @@ static void test_client_nofail(void* args) #endif ((func_args*)args)->return_code = TEST_FAIL; - method = wolfSSLv23_client_method(); + if (((func_args*)args)->callbacks != NULL && + ((func_args*)args)->callbacks->method != NULL) { + method = ((func_args*)args)->callbacks->method(); + } + else { + method = wolfSSLv23_client_method(); + } ctx = wolfSSL_CTX_new(method); #ifdef OPENSSL_EXTRA wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != SSL_SUCCESS) { /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done2; } - if (wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done2; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load client key file, " @@ -885,8 +938,7 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) ((func_args*)args)->return_code = TEST_FAIL; #if defined(USE_WINDOWS_API) - /* Generate random port for testing */ - port = GetRandomPort(); + port = ((func_args*)args)->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ @@ -907,13 +959,13 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #endif - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0)); + AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); @@ -939,7 +991,7 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + wolfSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif @@ -1043,13 +1095,13 @@ static void run_wolfssl_client(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); @@ -1142,6 +1194,8 @@ static void test_wolfSSL_read_write(void) func_args server_args; THREAD_TYPE serverThread; + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif @@ -1149,6 +1203,11 @@ static void test_wolfSSL_read_write(void) StartTCP(); InitTcpReady(&ready); +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + server_args.signal = &ready; client_args.signal = &ready; @@ -1186,7 +1245,14 @@ static void test_wolfSSL_dtls_export(void) InitTcpReady(&ready); +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + /* set using dtls */ + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); server_cbf.method = wolfDTLSv1_2_server_method; @@ -1230,6 +1296,9 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks, func_args server_args; THREAD_TYPE serverThread; + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + StartTCP(); client_args.callbacks = client_callbacks; @@ -1241,6 +1310,12 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks, /* RUN Server side */ InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + server_args.signal = &ready; client_args.signal = &ready; start_thread(run_wolfssl_server, &server_args, &serverThread); @@ -1958,9 +2033,9 @@ static void test_wolfSSL_DisableExtendedMasterSecret(void) *----------------------------------------------------------------------------*/ static void test_wolfSSL_X509_NAME_get_entry(void) { -#ifndef NO_CERTS +#if !defined(NO_CERTS) && !defined(NO_RSA) #if defined(OPENSSL_EXTRA) && (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)) \ - && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) + && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) || defined(WOLFSSL_HAPROXY) printf(testingFmt, "wolfSSL_X509_NAME_get_entry()"); { @@ -1973,7 +2048,7 @@ static void test_wolfSSL_X509_NAME_get_entry(void) int idx; #ifndef NO_FILESYSTEM - x509 = wolfSSL_X509_load_certificate_file(cliCert, SSL_FILETYPE_PEM); + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM); AssertNotNull(x509); name = X509_get_subject_name(x509); @@ -2006,7 +2081,7 @@ static void test_wolfSSL_PKCS12(void) { /* .p12 file is encrypted with DES3 */ #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \ - !defined(NO_ASN) && !defined(NO_PWDBASED) + !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_RSA) byte buffer[5300]; char file[] = "./certs/test-servercert.p12"; FILE *f; @@ -2165,7 +2240,7 @@ static int test_wolfSSL_UseOCSPStapling(void) * check. * PRE: HAVE_CERTIFICATE_STATUS_REQUEST_V2 and HAVE_OCSP defined. */ -static int test_wolfSSL_UseOCSPStaplingV2(void) +static int test_wolfSSL_UseOCSPStaplingV2 (void) { #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && defined(HAVE_OCSP) int ret; @@ -2185,7 +2260,7 @@ static int test_wolfSSL_UseOCSPStaplingV2(void) wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); - if(ret != SSL_SUCCESS){ + if (ret != SSL_SUCCESS){ wolfSSL_Cleanup(); return SSL_FAILURE; } @@ -2197,102 +2272,2720 @@ static int test_wolfSSL_UseOCSPStaplingV2(void) } /*END test_wolfSSL_UseOCSPStaplingV2*/ - /*----------------------------------------------------------------------------* - | Compatibility Tests + | Wolfcrypt *----------------------------------------------------------------------------*/ +/* + * Unit test for the wc_InitMd5() + */ +static int test_wc_InitMd5 (void) +{ +#ifndef NO_MD5 -static void test_wolfSSL_DES(void) + Md5 md5; + int ret, flag; + + printf(testingFmt, "wc_InitMd5()"); + + flag = 0; + + /* Test good arg. */ + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitMd5(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitMd5 */ + +/* + * Unit test for the wc_InitSha() + */ +static int test_wc_InitSha(void) { - #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) - const_DES_cblock myDes; - DES_key_schedule key; - word32 i; +#ifndef NO_SHA + Sha sha; + int ret, flag; - printf(testingFmt, "wolfSSL_DES()"); + flag = 0; - DES_check_key(1); - DES_set_key(&myDes, &key); + printf(testingFmt, "wc_InitSha()"); - /* check, check of odd parity */ - XMEMSET(key, 4, sizeof(DES_key_schedule)); key[0] = 3; /*set even parity*/ - XMEMSET(myDes, 5, sizeof(const_DES_cblock)); - DES_set_key_checked(&myDes, &key); - AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ + /* Test good arg. */ + ret = wc_InitSha(&sha); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } - /* set odd parity for success case */ - key[0] = 4; - DES_set_key_checked(&myDes, &key); - for (i = 0; i < sizeof(DES_key_schedule); i++) { - AssertIntEQ(key[i], myDes[i]); + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } } - /* check weak key */ - XMEMSET(key, 1, sizeof(DES_key_schedule)); - XMEMSET(myDes, 5, sizeof(const_DES_cblock)); - DES_set_key_checked(&myDes, &key); - AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ + printf(resultFmt, flag == 0 ? passed : failed); - /* now do unchecked copy of a weak key over */ - DES_set_key_unchecked(&myDes, &key); - /* compare arrays, should be the same */ - for (i = 0; i < sizeof(DES_key_schedule); i++) { - AssertIntEQ(key[i], myDes[i]); +#endif + return 0; + +} /* END test_wc_InitSha */ + +/* + * Unit test for wc_InitSha256() + */ +static int test_wc_InitSha256 (void) +{ +#ifndef NO_SHA256 + Sha256 sha256; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha256()"); + + /* Test good arg. */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = SSL_FATAL_ERROR; } - printf(resultFmt, passed); - #endif /* defined(OPENSSL_EXTRA) && !defined(NO_DES3) */ -} + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha256(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } -/*----------------------------------------------------------------------------* - | Main - *----------------------------------------------------------------------------*/ + printf(resultFmt, flag == 0 ? passed : failed); -void ApiTest(void) +#endif + return 0; +} /* END test_wc_InitSha256 */ + + +/* + * Testing wc_InitSha512() + */ +static int test_wc_InitSha512 (void) { - printf(" Begin API Tests\n"); - AssertIntEQ(test_wolfSSL_Init(), SSL_SUCCESS); - /* wolfcrypt initialization tests */ - AssertFalse(test_wolfCrypt_Init()); - test_wolfSSL_Method_Allocators(); - test_wolfSSL_CTX_new(wolfSSLv23_server_method()); - test_wolfSSL_CTX_use_certificate_file(); - AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), SSL_SUCCESS); - test_wolfSSL_CTX_use_PrivateKey_file(); - test_wolfSSL_CTX_load_verify_locations(); - test_wolfSSL_CTX_trust_peer_cert(); - test_wolfSSL_CTX_SetTmpDH_file(); - test_wolfSSL_CTX_SetTmpDH_buffer(); - test_server_wolfSSL_new(); - test_client_wolfSSL_new(); - test_wolfSSL_SetTmpDH_file(); - test_wolfSSL_SetTmpDH_buffer(); - test_wolfSSL_read_write(); - test_wolfSSL_dtls_export(); - AssertIntEQ(test_wolfSSL_SetMinVersion(), SSL_SUCCESS); - AssertIntEQ(test_wolfSSL_CTX_SetMinVersion(), SSL_SUCCESS); +#ifdef WOLFSSL_SHA512 + Sha512 sha512; + int ret, flag; - /* TLS extensions tests */ - test_wolfSSL_UseSNI(); - test_wolfSSL_UseMaxFragment(); - test_wolfSSL_UseTruncatedHMAC(); - test_wolfSSL_UseSupportedCurve(); - test_wolfSSL_UseALPN(); - test_wolfSSL_DisableExtendedMasterSecret(); + flag = 0; - /* X509 tests */ - test_wolfSSL_X509_NAME_get_entry(); - test_wolfSSL_PKCS12(); + printf(testingFmt, "wc_InitSha512()"); - /*OCSP Stapling. */ - AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS); - AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), SSL_SUCCESS); + /* Test good arg. */ + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } - /* compatibility tests */ - test_wolfSSL_DES(); + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha512(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } - AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_InitSha512 */ + +/* + * Testing wc_InitSha384() + */ +static int test_wc_InitSha384 (void) +{ +#ifdef WOLFSSL_SHA384 + Sha384 sha384; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha384()"); + + /* Test good arg. */ + ret = wc_InitSha384(&sha384); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha384(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitSha384 */ + +/* + * Testing wc_InitSha224(); + */ +static int test_wc_InitSha224 (void) +{ +#ifdef WOLFSSL_SHA224 + Sha224 sha224; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha224()"); + + /* Test good arg. */ + ret = wc_InitSha224(&sha224); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha224(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitSha224 */ + + +/* + * Testing wc_InitRipeMd() + */ +static int test_wc_InitRipeMd (void) +{ +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitRipeMd()"); + + /* Test good arg. */ + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitRipeMd(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_InitRipeMd */ + +/* + * Testing wc_UpdateMd5() + */ +static int test_wc_Md5Update (void) +{ + +#ifndef NO_MD5 + Md5 md5; + byte hash[MD5_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Md5Update()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag){ + ret = wc_Md5Update(&md5, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" + "\x72"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Md5Update(&md5, (byte*) a.input, (word32) a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, MD5_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /*Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Md5Update(&md5, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = MD5_DIGEST_SIZE; + + ret = wc_Md5Update(&md5, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Md5Update() */ + +/* + * Tesing wc_ShaUpdate() + */ +static int test_wc_ShaUpdate (void) +{ + +#ifndef NO_SHA + Sha sha; + byte hash[SHA_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha(&sha); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_ShaUpdate()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2" + "\x6C\x9C\xD0\xD8\x9D"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, hash); + if (ret !=0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try passing in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_ShaUpdate(&sha, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA_DIGEST_SIZE; + + ret = wc_ShaUpdate(&sha, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_ShaUpdate() */ + + +/* + * Unit test for wc_Sha256Update() + */ +static int test_wc_Sha256Update (void) +{ +#ifndef NO_SHA256 + Sha256 sha256; + byte hash[SHA256_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha256Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xBA\x78\x16\xBF\x8F\x01\xCF\xEA\x41\x41\x40\xDE\x5D\xAE\x22" + "\x23\xB0\x03\x61\xA3\x96\x17\x7A\x9C\xB4\x10\xFF\x61\xF2\x00" + "\x15\xAD"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA256_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try passing in bad values */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha256Update(&sha256, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA256_DIGEST_SIZE; + + ret = wc_Sha256Update(&sha256, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha256Update */ + +/* + * test wc_Sha384Update() + */ +static int test_wc_Sha384Update (void) +{ + +#ifdef WOLFSSL_SHA384 + Sha384 sha384; + byte hash[SHA384_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha384(&sha384); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha384Update()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50" + "\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff" + "\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34" + "\xc8\x25\xa7"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA384_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha384Update(&sha384, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA384_DIGEST_SIZE; + + ret = wc_Sha384Update(&sha384, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha384Update */ + +/* + * Testing wc_RipeMdUpdate() + */ +static int test_wc_RipeMdUpdate (void) +{ + +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + byte hash[RIPEMD_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_RipeMdUpdate()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_RipeMdUpdate(&ripemd, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6" + "\xb0\x87\xf1\x5a\x0b\xfc"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_RipeMdUpdate(&ripemd, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, RIPEMD_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_RipeMdUpdate(&ripemd, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = RIPEMD_DIGEST_SIZE; + + ret = wc_RipeMdUpdate(&ripemd, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_RipeMdUdpate */ + +/* + * wc_Sha512Update() test. + */ +static int test_wc_Sha512Update (void) +{ + +#ifdef WOLFSSL_SHA512 + Sha512 sha512; + byte hash[SHA512_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha512Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha512Update(&sha512, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41" + "\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b" + "\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c" + "\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a" + "\x9a\xc9\x4f\xa5\x4c\xa4\x9f"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha512Update(&sha512, (byte*) a.input, (word32) a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA512_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try passing in bad values */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha512Update(&sha512, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA512_DIGEST_SIZE; + + ret = wc_Sha512Update(&sha512, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha512Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha512Update */ + +/* + * Unit test on wc_Sha224Update + */ +static int test_wc_Sha224Update (void) +{ +#ifdef WOLFSSL_SHA224 + Sha224 sha224; + byte hash[SHA224_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha224(&sha224); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha224Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2" + "\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA224_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha224Update(&sha224, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA224_DIGEST_SIZE; + + ret = wc_Sha224Update(&sha224, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha224Update */ + +/* + * Unit test on wc_Md5Final() in wolfcrypt/src/md5.c + */ +static int test_wc_Md5Final (void) +{ + +#ifndef NO_MD5 + /* Instantiate */ + Md5 md5; + byte* hash_test[3]; + byte hash1[MD5_DIGEST_SIZE]; + byte hash2[2*MD5_DIGEST_SIZE]; + byte hash3[5*MD5_DIGEST_SIZE]; + int times, i, flag, ret; + + flag = 0; + + /* Initialize */ + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test)/sizeof(byte*); + + /* Test good args. */ + printf(testingFmt, "wc_Md5Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Md5Final(&md5, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Md5Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} + +/* + * Unit test on wc_ShaFinal + */ +static int test_wc_ShaFinal (void) +{ +#ifndef NO_SHA + Sha sha; + byte* hash_test[3]; + byte hash1[SHA_DIGEST_SIZE]; + byte hash2[2*SHA_DIGEST_SIZE]; + byte hash3[5*SHA_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /*Initialize*/ + ret = wc_InitSha(&sha); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test)/sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_ShaFinal()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_ShaFinal(&sha, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_ShaFinal(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaFinal(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_ShaFinal */ + +/* + * Unit test function for wc_Sha256Final() + */ +static int test_wc_Sha256Final (void) +{ +#ifndef NO_SHA256 + Sha256 sha256; + byte* hash_test[3]; + byte hash1[SHA256_DIGEST_SIZE]; + byte hash2[2*SHA256_DIGEST_SIZE]; + byte hash3[5*SHA256_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_Sha256Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha256Final(&sha256, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag ) { + ret = wc_Sha256Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha256Final */ + +/* + * Unit test function for wc_Sha512Final() + */ +static int test_wc_Sha512Final (void) +{ +#ifdef WOLFSSL_SHA512 + Sha512 sha512; + byte* hash_test[3]; + byte hash1[SHA512_DIGEST_SIZE]; + byte hash2[2*SHA512_DIGEST_SIZE]; + byte hash3[5*SHA512_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte *); + + /* Good test args. */ + printf(testingFmt, "wc_Sha512Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha512Final(&sha512, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + /* Test bad args. */ + if (!flag) { + ret = wc_Sha512Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + + if (!flag) {} + ret = wc_Sha512Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha512Final */ + +/* + * Unit test functionf or wc_Sha384Final(); + */ +static int test_wc_Sha384Final (void) +{ +#ifdef WOLFSSL_SHA384 + Sha384 sha384; + byte* hash_test[3]; + byte hash1[SHA384_DIGEST_SIZE]; + byte hash2[2*SHA384_DIGEST_SIZE]; + byte hash3[5*SHA384_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha384(&sha384); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_Sha384Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha384Final(&sha384, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Sha384Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha384Final */ + +/* + * Unit test function for wc_RipeMdFinal() + */ +static int test_wc_RipeMdFinal (void) +{ +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + byte* hash_test[3]; + byte hash1[RIPEMD_DIGEST_SIZE]; + byte hash2[2*RIPEMD_DIGEST_SIZE]; + byte hash3[5*RIPEMD_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_RipeMdFinal()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_RipeMdFinal(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_RipeMdFinal */ + +/* + * Unit test for wc_Sha224Final(); + */ +static int test_wc_Sha224Final (void) +{ +#ifdef WOLFSSL_SHA224 + Sha224 sha224; + byte* hash_test[3]; + byte hash1[SHA224_DIGEST_SIZE]; + byte hash2[2*SHA224_DIGEST_SIZE]; + byte hash3[5*SHA224_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha224(&sha224); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_sha224Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha224Final(&sha224, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Sha224Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha224Final */ + + +/*----------------------------------------------------------------------------* + | Compatibility Tests + *----------------------------------------------------------------------------*/ + + +static void test_wolfSSL_DES(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) + const_DES_cblock myDes; + DES_key_schedule key; + word32 i; + + printf(testingFmt, "wolfSSL_DES()"); + + DES_check_key(1); + DES_set_key(&myDes, &key); + + /* check, check of odd parity */ + XMEMSET(key, 4, sizeof(DES_key_schedule)); key[0] = 3; /*set even parity*/ + XMEMSET(myDes, 5, sizeof(const_DES_cblock)); + AssertIntEQ(DES_set_key_checked(&myDes, &key), -1); + AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ + + /* set odd parity for success case */ + key[0] = 4; + AssertIntEQ(DES_set_key_checked(&myDes, &key), 0); + for (i = 0; i < sizeof(DES_key_schedule); i++) { + AssertIntEQ(key[i], myDes[i]); + } + + /* check weak key */ + XMEMSET(key, 1, sizeof(DES_key_schedule)); + XMEMSET(myDes, 5, sizeof(const_DES_cblock)); + AssertIntEQ(DES_set_key_checked(&myDes, &key), -2); + AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ + + /* now do unchecked copy of a weak key over */ + DES_set_key_unchecked(&myDes, &key); + /* compare arrays, should be the same */ + for (i = 0; i < sizeof(DES_key_schedule); i++) { + AssertIntEQ(key[i], myDes[i]); + } + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_DES3) */ +} + + +static void test_wolfSSL_certs(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509* x509; + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + STACK_OF(ASN1_OBJECT)* sk; + int crit; + + printf(testingFmt, "wolfSSL_certs()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + + #ifdef HAVE_PK_CALLBACKS + AssertIntEQ((int)SSL_set_tlsext_debug_arg(ssl, NULL), SSL_SUCCESS); + #endif /* HAVE_PK_CALLBACKS */ + + /* create and use x509 */ + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ(SSL_use_certificate(ssl, x509), SSL_SUCCESS); + + #ifndef HAVE_USER_RSA + /* with loading in a new cert the check on private key should now fail */ + AssertIntNE(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + #endif + + + #if defined(USE_CERT_BUFFERS_2048) + AssertIntEQ(SSL_use_certificate_ASN1(ssl, + (unsigned char*)server_cert_der_2048, + sizeof_server_cert_der_2048), SSL_SUCCESS); + #endif + + #if !defined(NO_SHA) && !defined(NO_SHA256) + /************* Get Digest of Certificate ******************/ + { + byte digest[64]; /* max digest size */ + word32 digestSz; + + XMEMSET(digest, 0, sizeof(digest)); + AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha1(), digest, &digestSz), + SSL_SUCCESS); + AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha256(), digest, &digestSz), + SSL_SUCCESS); + + AssertIntEQ(X509_digest(NULL, wolfSSL_EVP_sha1(), digest, &digestSz), + SSL_FAILURE); + } + #endif /* !NO_SHA && !NO_SHA256*/ + + /* test and checkout X509 extensions */ + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_basic_constraints, + &crit, NULL); + AssertNotNull(sk); + AssertIntEQ(crit, 0); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_key_usage, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, + &crit, NULL); + /* AssertNotNull(sk); no extension set */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_authority_key_identifier, &crit, NULL); + AssertNotNull(sk); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_private_key_usage_period, &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_subject_alt_name, + &crit, NULL); + /* AssertNotNull(sk); no alt names set */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_issuer_alt_name, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_info_access, &crit, + NULL); + /* AssertNotNull(sk); no auth info set */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_sinfo_access, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_name_constraints, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_certificate_policies, &crit, NULL); + #if !defined(WOLFSSL_SEP) && !defined(WOLFSSL_CERT_EXT) + AssertNull(sk); + #else + /* AssertNotNull(sk); no cert policy set */ + #endif + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_mappings, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_constraints, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_inhibit_any_policy, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_tlsfeature, &crit, + NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + /* test invalid cases */ + crit = 0; + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, -1, &crit, NULL); + AssertNull(sk); + AssertIntEQ(crit, -1); + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(NULL, NID_tlsfeature, + NULL, NULL); + AssertNull(sk); + + AssertIntEQ(SSL_get_hit(ssl), 0); + X509_free(x509); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_private_keys(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + EVP_PKEY* pkey = NULL; + + printf(testingFmt, "wolfSSL_private_keys()"); + + OpenSSL_add_all_digests(); + OpenSSL_add_all_algorithms(); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + +#ifdef USE_CERT_BUFFERS_2048 + { + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + + AssertIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, + (unsigned char*)client_key_der_2048, + sizeof_client_key_der_2048), SSL_SUCCESS); +#ifndef HAVE_USER_RSA + /* Should missmatch now that a different private key loaded */ + AssertIntNE(wolfSSL_check_private_key(ssl), SSL_SUCCESS); +#endif + + AssertIntEQ(SSL_use_PrivateKey_ASN1(0, ssl, + (unsigned char*)server_key, + sizeof_server_key_der_2048), SSL_SUCCESS); + /* After loading back in DER format of original key, should match */ + AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + + /* pkey not set yet, expecting to fail */ + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_FAILURE); + + /* set PKEY and test again */ + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_SUCCESS); + } +#endif + + + EVP_PKEY_free(pkey); + SSL_free(ssl); /* frees x509 also since loaded into ssl */ + SSL_CTX_free(ctx); + + /* test existence of no-op macros in wolfssl/openssl/ssl.h */ + CONF_modules_free(); + ENGINE_cleanup(); + CONF_modules_unload(); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_PEM_PrivateKey(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) && \ + defined(USE_CERT_BUFFERS_2048) + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + EVP_PKEY* pkey = NULL; + BIO* bio; + + printf(testingFmt, "wolfSSL_PEM_PrivateKey()"); + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + AssertNotNull(bio); + + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + SSL_SUCCESS); + + BIO_free(bio); + EVP_PKEY_free(pkey); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_tmp_dh(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) + byte buffer[5300]; + char file[] = "./certs/dsaparams.pem"; + FILE *f; + int bytes; + DSA* dsa; + DH* dh; + BIO* bio; + SSL* ssl; + SSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_tmp_dh()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + f = fopen(file, "rb"); + AssertNotNull(f); + bytes = (int)fread(buffer, 1, sizeof(buffer), f); + fclose(f); + + bio = BIO_new_mem_buf((void*)buffer, bytes); + AssertNotNull(bio); + + dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); + AssertNotNull(dsa); + + dh = wolfSSL_DSA_dup_DH(dsa); + AssertNotNull(dh); + + AssertIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), SSL_SUCCESS); + AssertIntEQ((int)SSL_set_tmp_dh(ssl, dh), SSL_SUCCESS); + + BIO_free(bio); + DSA_free(dsa); + DH_free(dh); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + +static void test_wolfSSL_ctrl(void) +{ + #if defined(OPENSSL_EXTRA) + byte buffer[5300]; + BIO* bio; + int bytes; + BUF_MEM* ptr = NULL; + + printf(testingFmt, "wolfSSL_crtl()"); + + bytes = sizeof(buffer); + bio = BIO_new_mem_buf((void*)buffer, bytes); + AssertNotNull(bio); + AssertNotNull(BIO_s_socket()); + + AssertIntEQ((int)wolfSSL_BIO_get_mem_ptr(bio, &ptr), SSL_SUCCESS); + + /* needs tested after stubs filled out @TODO + SSL_ctrl + SSL_CTX_ctrl + */ + + BIO_free(bio); + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) */ +} + + +static void test_wolfSSL_CTX_add_extra_chain_cert(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + char caFile[] = "./certs/client-ca.pem"; + char clientFile[] = "./certs/client-cert.pem"; + SSL_CTX* ctx; + X509* x509 = NULL; + + printf(testingFmt, "wolfSSL_CTX_add_extra_chain_cert()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + + x509 = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + + x509 = wolfSSL_X509_load_certificate_file(clientFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + + AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); + AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); + + SSL_CTX_free(ctx); + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +static void test_wolfSSL_ERR_peek_last_error_line(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && defined(DEBUG_WOLFSSL) && \ + !defined(NO_OLD_TLS) && defined(HAVE_IO_TESTS_DEPENDENCIES) + tcp_ready ready; + func_args client_args; + func_args server_args; +#ifndef SINGLE_THREADED + THREAD_TYPE serverThread; +#endif + callback_functions client_cb; + callback_functions server_cb; + int line = 0; + const char* file = NULL; + + printf(testingFmt, "wolfSSL_ERR_peek_last_error_line()"); + + /* create a failed connection and inspect the error */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + client_cb.method = wolfTLSv1_1_client_method; + server_cb.method = wolfTLSv1_2_server_method; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + +#ifndef SINGLE_THREADED + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args); + join_thread(serverThread); +#endif + + FreeTcpReady(&ready); + + /* check that error code was stored */ + AssertIntNE((int)ERR_peek_last_error_line(NULL, NULL), 0); + ERR_peek_last_error_line(NULL, &line); + AssertIntNE(line, 0); + ERR_peek_last_error_line(&file, NULL); + AssertNotNull(file); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); + + printf("\nTesting error print out\n"); + ERR_print_errors_fp(stdout); + printf("Done testing print out\n\n"); + fflush(stdout); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(DEBUG_WOLFSSL) */ +} + + +static void test_wolfSSL_X509_STORE_set_flags(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + + X509_STORE* store; + X509* x509; + + printf(testingFmt, "wolfSSL_ERR_peek_last_error_line()"); + AssertNotNull((store = wolfSSL_X509_STORE_new())); + AssertNotNull((x509 = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + AssertIntEQ(X509_STORE_add_cert(store, x509), SSL_SUCCESS); + +#ifdef HAVE_CRL + AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), SSL_SUCCESS); +#else + AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), + NOT_COMPILED_IN); +#endif + + wolfSSL_X509_free(x509); + wolfSSL_X509_STORE_free(store); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_X509_LOOKUP_load_file(void) +{ + #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL_X509_STORE* store; + WOLFSSL_X509_LOOKUP* lookup; + + printf(testingFmt, "wolfSSL_X509_LOOKUP_load_file()"); + + AssertNotNull(store = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/client-ca.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/crl/crl2.pem", + X509_FILETYPE_PEM), 1); + + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, cliCertFile, + SSL_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + SSL_FILETYPE_PEM), ASN_NO_SIGNER_E); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + SSL_FILETYPE_PEM), 1); + + wolfSSL_X509_STORE_free(store); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +static void test_wolfSSL_BN(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + BIGNUM* a; + BIGNUM* b; + BIGNUM* c; + BIGNUM* d; + ASN1_INTEGER ai; + unsigned char value[1]; + + printf(testingFmt, "wolfSSL_BN()"); + + AssertNotNull(b = BN_new()); + AssertNotNull(c = BN_new()); + AssertNotNull(d = BN_new()); + + value[0] = 0x03; + + /* at the moment hard setting since no set function */ + ai.data[0] = 0x02; /* tag for ASN_INTEGER */ + ai.data[1] = 0x01; /* length of integer */ + ai.data[2] = value[0]; + + AssertNotNull(a = ASN1_INTEGER_to_BN(&ai, NULL)); + + value[0] = 0x02; + AssertNotNull(BN_bin2bn(value, sizeof(value), b)); + + value[0] = 0x05; + AssertNotNull(BN_bin2bn(value, sizeof(value), c)); + + /* a^b mod c = */ + AssertIntEQ(BN_mod_exp(d, NULL, b, c, NULL), SSL_FAILURE); + AssertIntEQ(BN_mod_exp(d, a, b, c, NULL), SSL_SUCCESS); + + /* check result 3^2 mod 5 */ + value[0] = 0; + AssertIntEQ(BN_bn2bin(d, value), SSL_SUCCESS); + AssertIntEQ((int)(value[0] & 0x04), 4); + + BN_free(a); + BN_free(b); + BN_free(c); + BN_clear_free(d); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ +} + + +static void test_wolfSSL_set_options(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + SSL* ssl; + SSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_set_options()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertTrue(SSL_set_options(ssl, SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1); + AssertTrue(SSL_get_options(ssl) == SSL_OP_NO_TLSv1); + + AssertIntGT((int)SSL_set_options(ssl, (SSL_OP_COOKIE_EXCHANGE | + SSL_OP_NO_SSLv2)), 0); + AssertTrue((SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE) & + SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE); + AssertTrue((SSL_set_options(ssl, SSL_OP_NO_TLSv1_2) & + SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2); + AssertTrue((SSL_set_options(ssl, SSL_OP_NO_COMPRESSION) & + SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION); + + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_PEM_read_bio(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + byte buffer[5300]; + FILE *f; + int bytes; + X509* x509; + BIO* bio = NULL; + + printf(testingFmt, "wolfSSL_PEM_read_bio()"); + + AssertNotNull(f = fopen(cliCertFile, "rb")); + bytes = (int)fread(buffer, 1, sizeof(buffer), f); + fclose(f); + + AssertNull(x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); + AssertNotNull(bio = BIO_new_mem_buf((void*)buffer, bytes)); + AssertNotNull(x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); + AssertIntEQ((int)BIO_set_fd(bio, 0, BIO_NOCLOSE), 1); + + BIO_free(bio); + X509_free(x509); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +static void test_wolfSSL_BIO(void) +{ + #if defined(OPENSSL_EXTRA) + byte buffer[20]; + BIO* bio1; + BIO* bio2; + BIO* bio3; + char* bufPt; + int i; + + printf(testingFmt, "wolfSSL_BIO()"); + + for (i = 0; i < 20; i++) { + buffer[i] = i; + } + + /* Creating and testing type BIO_s_bio */ + AssertNotNull(bio1 = BIO_new(BIO_s_bio())); + AssertNotNull(bio2 = BIO_new(BIO_s_bio())); + AssertNotNull(bio3 = BIO_new(BIO_s_bio())); + + /* read/write before set up */ + AssertIntEQ(BIO_read(bio1, buffer, 2), WOLFSSL_BIO_UNSET); + AssertIntEQ(BIO_write(bio1, buffer, 2), WOLFSSL_BIO_UNSET); + + AssertIntEQ(BIO_set_write_buf_size(bio1, 20), SSL_SUCCESS); + AssertIntEQ(BIO_set_write_buf_size(bio2, 8), SSL_SUCCESS); + AssertIntEQ(BIO_make_bio_pair(bio1, bio2), SSL_SUCCESS); + + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 10), 10); + XMEMCPY(bufPt, buffer, 10); + AssertIntEQ(BIO_write(bio1, buffer + 10, 10), 10); + /* write buffer full */ + AssertIntEQ(BIO_write(bio1, buffer, 10), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_flush(bio1), SSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio1), 0); + + /* write the other direction with pair */ + AssertIntEQ((int)BIO_nwrite(bio2, &bufPt, 10), 8); + XMEMCPY(bufPt, buffer, 8); + AssertIntEQ(BIO_write(bio2, buffer, 10), WOLFSSL_BIO_ERROR); + + /* try read */ + AssertIntEQ((int)BIO_ctrl_pending(bio1), 8); + AssertIntEQ((int)BIO_ctrl_pending(bio2), 20); + + AssertIntEQ(BIO_nread(bio2, &bufPt, (int)BIO_ctrl_pending(bio2)), 20); + for (i = 0; i < 20; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio2, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio1, &bufPt, (int)BIO_ctrl_pending(bio1)), 8); + for (i = 0; i < 8; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio1, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_ctrl_reset_read_request(bio1), 1); + + /* new pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_FAILURE); + BIO_free(bio2); /* free bio2 and automaticly remove from pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 10), WOLFSSL_BIO_ERROR); + + /* test wrap around... */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ(BIO_reset(bio3), 0); + + /* fill write buffer, read only small amount then write again */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 4), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* try writing over read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 5), 4); + XMEMSET(bufPt, 0, 4); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 20); + + /* read and write 0 bytes */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 0), 0); + + /* should read only to end of write buffer then need to read again */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 20), 16); + for (i = 0; i < 16; i++) { + AssertIntEQ(bufPt[i], buffer[4 + i]); + } + + AssertIntEQ(BIO_nread(bio3, NULL, 0), SSL_FAILURE); + AssertIntEQ(BIO_nread0(bio3, &bufPt), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* read index should not have advanced with nread0 */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 5), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* write and fill up buffer checking reset of index state */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + + /* test reset on data in bio1 write buffer */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 3), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 6), 6); + for (i = 0; i < 6; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* test case of writing twice with offset read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 3), 3); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 3); /* try overwriting */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 1), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + + BIO_free(bio1); + BIO_free(bio3); + + /* BIOs with file pointers */ + #if !defined(NO_FILESYSTEM) + { + XFILE f1; + XFILE f2; + BIO* f_bio1; + BIO* f_bio2; + unsigned char cert[300]; + char testFile[] = "tests/bio_write_test.txt"; + char msg[] = "bio_write_test.txt contains the first 300 bytes of certs/server-cert.pem\ncreated by tests/unit.test\n\n"; + + AssertNotNull(f_bio1 = BIO_new(BIO_s_file())); + AssertNotNull(f_bio2 = BIO_new(BIO_s_file())); + + AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); + AssertIntEQ((int)BIO_set_mem_eof_return(NULL, -1), 0); + + f1 = XFOPEN(svrCertFile, "rwb"); + AssertIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), SSL_SUCCESS); + AssertIntEQ(BIO_write_filename(f_bio2, testFile), + SSL_SUCCESS); + + AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); + AssertIntEQ(BIO_write(f_bio2, msg, sizeof(msg)), sizeof(msg)); + AssertIntEQ(BIO_write(f_bio2, cert, sizeof(cert)), sizeof(cert)); + + AssertIntEQ((int)BIO_get_fp(f_bio2, &f2), SSL_SUCCESS); + AssertIntEQ(BIO_reset(f_bio2), 0); + AssertIntEQ(BIO_seek(f_bio2, 4), 0); + + BIO_free(f_bio1); + BIO_free(f_bio2); + } + #endif /* !defined(NO_FILESYSTEM) */ + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_DES_ecb_encrypt(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && defined(WOLFSSL_DES_ECB) + WOLFSSL_DES_cblock input1,input2,output1,output2,back1,back2; + WOLFSSL_DES_key_schedule key; + + printf(testingFmt, "wolfSSL_DES_ecb_encrypt()"); + + XMEMCPY(key,"12345678",sizeof(WOLFSSL_DES_key_schedule)); + XMEMCPY(input1, "Iamhuman",sizeof(WOLFSSL_DES_cblock)); + XMEMCPY(input2, "Whoisit?",sizeof(WOLFSSL_DES_cblock)); + XMEMSET(output1, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(output2, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(back1, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(back2, 0, sizeof(WOLFSSL_DES_cblock)); + + /* Encrypt messages */ + wolfSSL_DES_ecb_encrypt(&input1,&output1,&key,DES_ENCRYPT); + wolfSSL_DES_ecb_encrypt(&input2,&output2,&key,DES_ENCRYPT); + + /* Decrypt messages */ + int ret1 = 0; + int ret2 = 0; + wolfSSL_DES_ecb_encrypt(&output1,&back1,&key,DES_DECRYPT); + ret1 = memcmp((unsigned char *) back1,(unsigned char *) input1,sizeof(WOLFSSL_DES_cblock)); + AssertIntEQ(ret1,0); + wolfSSL_DES_ecb_encrypt(&output2,&back2,&key,DES_DECRYPT); + ret2 = memcmp((unsigned char *) back2,(unsigned char *) input2,sizeof(WOLFSSL_DES_cblock)); + AssertIntEQ(ret2,0); + + printf(resultFmt, passed); + #endif +} +/*----------------------------------------------------------------------------* + | wolfCrypt ASN + *----------------------------------------------------------------------------*/ + +static void test_wc_GetPkcs8TraditionalOffset(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) + int length, derSz; + word32 inOutIdx; + const char* path = "./certs/server-keyPkcs8.der"; + FILE* file; + byte der[2048]; + + printf(testingFmt, "wc_GetPkcs8TraditionalOffset"); + + file = fopen(path, "rb"); + AssertNotNull(file); + derSz = (int)fread(der, 1, sizeof(der), file); + fclose(file); + + /* valid case */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntGT(length, 0); + + /* inOutIdx > sz */ + inOutIdx = 4000; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* null input */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(NULL, &inOutIdx, 0); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* invalid input, fill buffer with 1's */ + XMEMSET(der, 1, sizeof(der)); + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, ASN_PARSE_E); + + printf(resultFmt, passed); +#endif /* NO_ASN */ +} + + +/*----------------------------------------------------------------------------* + | wolfCrypt ECC + *----------------------------------------------------------------------------*/ + +static void test_wc_ecc_get_curve_size_from_name(void) +{ +#ifdef HAVE_ECC + int ret; + + printf(testingFmt, "wc_ecc_get_curve_size_from_name"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + ret = wc_ecc_get_curve_size_from_name("SECP256R1"); + AssertIntEQ(ret, 32); + #endif + + /* invalid case */ + ret = wc_ecc_get_curve_size_from_name("BADCURVE"); + AssertIntEQ(ret, -1); + + /* NULL input */ + ret = wc_ecc_get_curve_size_from_name(NULL); + AssertIntEQ(ret, BAD_FUNC_ARG); + + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} + +static void test_wc_ecc_get_curve_id_from_name(void) +{ +#ifdef HAVE_ECC + int id; + + printf(testingFmt, "wc_ecc_get_curve_id_from_name"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + #endif + + /* invalid case */ + id = wc_ecc_get_curve_id_from_name("BADCURVE"); + AssertIntEQ(id, -1); + + /* NULL input */ + id = wc_ecc_get_curve_id_from_name(NULL); + AssertIntEQ(id, BAD_FUNC_ARG); + + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} + +static void test_wc_ecc_get_curve_id_from_params(void) +{ +#ifdef HAVE_ECC + int id; + + const byte prime[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF + }; + + const byte primeInvalid[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01 + }; + + const byte Af[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC + }; + + const byte Bf[] = + { + 0x5A,0xC6,0x35,0xD8,0xAA,0x3A,0x93,0xE7, + 0xB3,0xEB,0xBD,0x55,0x76,0x98,0x86,0xBC, + 0x65,0x1D,0x06,0xB0,0xCC,0x53,0xB0,0xF6, + 0x3B,0xCE,0x3C,0x3E,0x27,0xD2,0x60,0x4B + }; + + const byte order[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xBC,0xE6,0xFA,0xAD,0xA7,0x17,0x9E,0x84, + 0xF3,0xB9,0xCA,0xC2,0xFC,0x63,0x25,0x51 + }; + + const byte Gx[] = + { + 0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47, + 0xF8,0xBC,0xE6,0xE5,0x63,0xA4,0x40,0xF2, + 0x77,0x03,0x7D,0x81,0x2D,0xEB,0x33,0xA0, + 0xF4,0xA1,0x39,0x45,0xD8,0x98,0xC2,0x96 + }; + + const byte Gy[] = + { + 0x4F,0xE3,0x42,0xE2,0xFE,0x1A,0x7F,0x9B, + 0x8E,0xE7,0xEB,0x4A,0x7C,0x0F,0x9E,0x16, + 0x2B,0xCE,0x33,0x57,0x6B,0x31,0x5E,0xCE, + 0xCB,0xB6,0x40,0x68,0x37,0xBF,0x51,0xF5 + }; + + int cofactor = 1; + int fieldSize = 256; + + printf(testingFmt, "wc_ecc_get_curve_id_from_params"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_params(fieldSize, prime, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_SECP256R1); + #endif + + /* invalid case, fieldSize = 0 */ + id = wc_ecc_get_curve_id_from_params(0, prime, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_CURVE_INVALID); + + /* invalid case, NULL prime */ + id = wc_ecc_get_curve_id_from_params(fieldSize, NULL, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, BAD_FUNC_ARG); + + /* invalid case, invalid prime */ + id = wc_ecc_get_curve_id_from_params(fieldSize, + primeInvalid, sizeof(primeInvalid), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_CURVE_INVALID); + + printf(resultFmt, passed); +#endif +} + + +/*----------------------------------------------------------------------------* + | Certficate Failure Checks + *----------------------------------------------------------------------------*/ +#ifndef NO_CERTS + /* Use the Cert Manager(CM) API to generate the error ASN_SIG_CONFIRM_E */ + static int verify_sig_cm(const char* ca, byte* cert_buf, size_t cert_sz, + int type) + { + int ret; + WOLFSSL_CERT_MANAGER* cm = NULL; + + switch (type) { + case TESTING_RSA: + #ifdef NO_RSA + printf("RSA disabled, skipping test\n"); + return ASN_SIG_CONFIRM_E; + #else + break; + #endif + case TESTING_ECC: + #ifndef HAVE_ECC + printf("ECC disabled, skipping test\n"); + return ASN_SIG_CONFIRM_E; + #else + break; + #endif + default: + printf("Bad function argument\n"); + return BAD_FUNC_ARG; + } + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) { + printf("wolfSSL_CertManagerNew failed\n"); + return -1; + } + + ret = wolfSSL_CertManagerLoadCA(cm, ca, 0); + if (ret != SSL_SUCCESS) { + printf("wolfSSL_CertManagerLoadCA failed\n"); + wolfSSL_CertManagerFree(cm); + return ret; + } + + ret = wolfSSL_CertManagerVerifyBuffer(cm, cert_buf, cert_sz, SSL_FILETYPE_ASN1); + /* Let AssertIntEQ handle return code */ + + wolfSSL_CertManagerFree(cm); + + return ret; + } + + static int test_RsaSigFailure_cm(void) + { + int ret = 0; + const char* ca_cert = "./certs/ca-cert.pem"; + const char* server_cert = "./certs/server-cert.der"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + + ret = load_file(server_cert, &cert_buf, &cert_sz); + if (ret == 0) { + /* corrupt DER - invert last byte, which is signature */ + cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; + + /* test bad cert */ + ret = verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_RSA); + } + + printf("Signature failure test: RSA: Ret %d\n", ret); + + if (cert_buf) + free(cert_buf); + + return ret; + } + + static int test_EccSigFailure_cm(void) + { + int ret = 0; + /* self-signed ECC cert, so use server cert as CA */ + const char* ca_cert = "./certs/server-ecc.pem"; + const char* server_cert = "./certs/server-ecc.der"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + + ret = load_file(server_cert, &cert_buf, &cert_sz); + if (ret == 0) { + /* corrupt DER - invert last byte, which is signature */ + cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; + + /* test bad cert */ + ret = verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_ECC); + } + + printf("Signature failure test: ECC: Ret %d\n", ret); + + if (cert_buf) + free(cert_buf); + + return ret; + } + +#endif /* NO_CERTS */ + + +/*----------------------------------------------------------------------------* + | Main + *----------------------------------------------------------------------------*/ + +void ApiTest(void) +{ + printf(" Begin API Tests\n"); + AssertIntEQ(test_wolfSSL_Init(), SSL_SUCCESS); + /* wolfcrypt initialization tests */ + test_wolfSSL_Method_Allocators(); + test_wolfSSL_CTX_new(wolfSSLv23_server_method()); + test_wolfSSL_CTX_use_certificate_file(); + AssertIntEQ(test_wolfSSL_CTX_use_certificate_buffer(), SSL_SUCCESS); + test_wolfSSL_CTX_use_PrivateKey_file(); + test_wolfSSL_CTX_load_verify_locations(); + test_wolfSSL_CTX_trust_peer_cert(); + test_wolfSSL_CTX_SetTmpDH_file(); + test_wolfSSL_CTX_SetTmpDH_buffer(); + test_server_wolfSSL_new(); + test_client_wolfSSL_new(); + test_wolfSSL_SetTmpDH_file(); + test_wolfSSL_SetTmpDH_buffer(); + test_wolfSSL_read_write(); + test_wolfSSL_dtls_export(); + AssertIntEQ(test_wolfSSL_SetMinVersion(), SSL_SUCCESS); + AssertIntEQ(test_wolfSSL_CTX_SetMinVersion(), SSL_SUCCESS); + + /* TLS extensions tests */ + test_wolfSSL_UseSNI(); + test_wolfSSL_UseMaxFragment(); + test_wolfSSL_UseTruncatedHMAC(); + test_wolfSSL_UseSupportedCurve(); + test_wolfSSL_UseALPN(); + test_wolfSSL_DisableExtendedMasterSecret(); + + /* X509 tests */ + test_wolfSSL_X509_NAME_get_entry(); + test_wolfSSL_PKCS12(); + + /*OCSP Stapling. */ + AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS); + AssertIntEQ(test_wolfSSL_UseOCSPStaplingV2(), SSL_SUCCESS); + + /* compatibility tests */ + test_wolfSSL_DES(); + test_wolfSSL_certs(); + test_wolfSSL_private_keys(); + test_wolfSSL_PEM_PrivateKey(); + test_wolfSSL_tmp_dh(); + test_wolfSSL_ctrl(); + test_wolfSSL_CTX_add_extra_chain_cert(); + test_wolfSSL_ERR_peek_last_error_line(); + test_wolfSSL_X509_STORE_set_flags(); + test_wolfSSL_X509_LOOKUP_load_file(); + test_wolfSSL_BN(); + test_wolfSSL_set_options(); + test_wolfSSL_PEM_read_bio(); + test_wolfSSL_BIO(); + test_wolfSSL_DES_ecb_encrypt(); + AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); + + /* wolfCrypt ASN tests */ + test_wc_GetPkcs8TraditionalOffset(); + + /* wolfCrypt ECC tests */ + test_wc_ecc_get_curve_size_from_name(); + test_wc_ecc_get_curve_id_from_name(); + test_wc_ecc_get_curve_id_from_params(); + +#ifndef NO_CERTS + /* Bad certificate signature tests */ + AssertIntEQ(test_EccSigFailure_cm(), ASN_SIG_CONFIRM_E); + AssertIntEQ(test_RsaSigFailure_cm(), ASN_SIG_CONFIRM_E); +#endif /* NO_CERTS */ + + /*wolfcrypt */ + printf("\n-----------------wolfcrypt unit tests------------------\n"); + AssertFalse(test_wolfCrypt_Init()); + AssertFalse(test_wc_InitMd5()); + AssertFalse(test_wc_Md5Update()); + AssertFalse(test_wc_Md5Final()); + AssertFalse(test_wc_InitSha()); + AssertFalse(test_wc_ShaUpdate()); + AssertFalse(test_wc_ShaFinal()); + AssertFalse(test_wc_InitSha256()); + AssertFalse(test_wc_Sha256Update()); + AssertFalse(test_wc_Sha256Final()); + AssertFalse(test_wc_InitSha512()); + AssertFalse(test_wc_Sha512Update()); + AssertFalse(test_wc_Sha512Final()); + AssertFalse(test_wc_InitSha384()); + AssertFalse(test_wc_Sha384Update()); + AssertFalse(test_wc_Sha384Final()); + AssertFalse(test_wc_InitSha224()); + AssertFalse(test_wc_Sha224Update()); + AssertFalse(test_wc_Sha224Final()); + AssertFalse(test_wc_InitRipeMd()); + AssertFalse(test_wc_RipeMdUpdate()); + AssertFalse(test_wc_RipeMdFinal()); printf(" End API Tests\n"); } diff --git a/tests/hash.c b/tests/hash.c index 9167cda16c..5dd0017bec 100644 --- a/tests/hash.c +++ b/tests/hash.c @@ -255,6 +255,7 @@ int md4_test(void) int md5_test(void) { Md5 md5; + int ret; byte hash[MD5_DIGEST_SIZE]; testVector a, b, c, d, e; @@ -299,11 +300,22 @@ int md5_test(void) test_md5[3] = d; test_md5[4] = e; - wc_InitMd5(&md5); + ret = wc_InitMd5(&md5); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); - wc_Md5Final(&md5, hash); + ret = wc_Md5Update(&md5, (byte*)test_md5[i].input, + (word32)test_md5[i].inLen); + if (ret) { + return ret; + } + + ret = wc_Md5Final(&md5, hash); + if (ret) { + return ret; + } if (XMEMCMP(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0) return -5 - i; @@ -578,6 +590,7 @@ int sha384_test() int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -614,12 +627,22 @@ int ripemd_test(void) test_ripemd[2] = c; test_ripemd[3] = d; - wc_InitRipeMd(&ripemd); + ret = wc_InitRipeMd(&ripemd); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, - (word32)test_ripemd[i].inLen); - wc_RipeMdFinal(&ripemd, hash); + ret = wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, + (word32)test_ripemd[i].inLen); + if (ret) { + return ret; + } + + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret) { + return ret; + } if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) return -10 - i; @@ -673,6 +696,10 @@ int hmac_md5_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -693,6 +720,8 @@ int hmac_md5_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -743,6 +772,10 @@ int hmac_sha_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -763,6 +796,8 @@ int hmac_sha_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -813,6 +848,10 @@ int hmac_sha224_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) if (i == 1) @@ -831,11 +870,10 @@ int hmac_sha224_test(void) if (XMEMCMP(hash, test_hmac[i].output, SHA224_DIGEST_SIZE) != 0) return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif } + wc_HmacFree(&hmac); + return 0; } #endif @@ -890,6 +928,10 @@ int hmac_sha256_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -910,6 +952,8 @@ int hmac_sha256_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -967,6 +1011,10 @@ int hmac_sha384_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -987,6 +1035,8 @@ int hmac_sha384_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif diff --git a/tests/include.am b/tests/include.am index 8368b49ce0..9344544172 100644 --- a/tests/include.am +++ b/tests/include.am @@ -20,6 +20,7 @@ tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h EXTRA_DIST += tests/test.conf \ + tests/test-tls13.conf \ tests/test-qsh.conf \ tests/test-psk-no-id.conf \ tests/test-dtls.conf \ diff --git a/tests/srp.c b/tests/srp.c index 3314a69b66..0ca2a2b704 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -117,8 +117,8 @@ static void test_SrpInit(void) /* invalid params */ AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, 255 )); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, (SrpType)255, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, (SrpSide)255)); /* success */ AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); @@ -240,8 +240,8 @@ static void test_SrpSetPassword(void) static void test_SrpGetPublic(void) { Srp srp; - byte public[64]; - word32 publicSz = 0; + byte pub[64]; + word32 pubSz = 0; AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); @@ -250,23 +250,23 @@ static void test_SrpGetPublic(void) salt, sizeof(salt))); /* invalid call order */ - AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); /* fix call order */ AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz)); /* invalid params */ - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(NULL, public, &publicSz)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, NULL, &publicSz)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, public, NULL)); - AssertIntEQ(BUFFER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(NULL, pub, &pubSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, NULL, &pubSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, pub, NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); /* success */ - publicSz = sizeof(public); + pubSz = sizeof(pub); AssertIntEQ(0, wc_SrpSetPrivate(&srp, a, sizeof(a))); - AssertIntEQ(0, wc_SrpGetPublic(&srp, public, &publicSz)); - AssertIntEQ(publicSz, sizeof(A)); - AssertIntEQ(0, XMEMCMP(public, A, publicSz)); + AssertIntEQ(0, wc_SrpGetPublic(&srp, pub, &pubSz)); + AssertIntEQ(pubSz, sizeof(A)); + AssertIntEQ(0, XMEMCMP(pub, A, pubSz)); wc_SrpTerm(&srp); @@ -277,16 +277,16 @@ static void test_SrpGetPublic(void) salt, sizeof(salt))); /* invalid call order */ - AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); /* fix call order */ AssertIntEQ(0, wc_SrpSetVerifier(&srp, verifier, sizeof(verifier))); /* success */ AssertIntEQ(0, wc_SrpSetPrivate(&srp, b, sizeof(b))); - AssertIntEQ(0, wc_SrpGetPublic(&srp, public, &publicSz)); - AssertIntEQ(publicSz, sizeof(B)); - AssertIntEQ(0, XMEMCMP(public, B, publicSz)); + AssertIntEQ(0, wc_SrpGetPublic(&srp, pub, &pubSz)); + AssertIntEQ(pubSz, sizeof(B)); + AssertIntEQ(0, XMEMCMP(pub, B, pubSz)); wc_SrpTerm(&srp); } diff --git a/tests/suites.c b/tests/suites.c index f23c116ccc..289c5ef46e 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -35,7 +35,7 @@ #define MAX_ARGS 40 #define MAX_COMMAND_SZ 240 -#define MAX_SUITE_SZ 80 +#define MAX_SUITE_SZ 80 #define NOT_BUILT_IN -123 #if defined(NO_OLD_TLS) || !defined(WOLFSSL_ALLOW_SSLV3) #define VERSION_TOO_OLD -124 @@ -54,6 +54,11 @@ static char flagSep[] = " "; static char portFlag[] = "-p"; static char svrPort[] = "0"; #endif +static char forceDefCipherListFlag[] = "-H"; + +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif #ifndef WOLFSSL_ALLOW_SSLV3 @@ -155,7 +160,8 @@ static int IsValidCipherSuite(const char* line, char* suite) static int execute_test_case(int svr_argc, char** svr_argv, int cli_argc, char** cli_argv, int addNoVerify, int addNonBlocking, - int addDisableEMS) + int addDisableEMS, int forceSrvDefCipherList, + int forceCliDefCipherList) { #ifdef WOLFSSL_TIRTOS func_args cliArgs = {0}; @@ -174,20 +180,22 @@ static int execute_test_case(int svr_argc, char** svr_argv, char commandLine[MAX_COMMAND_SZ]; char cipherSuite[MAX_SUITE_SZ+1]; int i; - size_t added = 0; + size_t added; static int tests = 1; + /* Is Valid Cipher and Version Checks */ + /* build command list for the Is checks below */ commandLine[0] = '\0'; - for (i = 0; i < svr_argc; i++) { + added = 0; + for (i = 0; i < svrArgs.argc; i++) { added += XSTRLEN(svr_argv[i]) + 2; if (added >= MAX_COMMAND_SZ) { - printf("server command line too long\n"); + printf("server command line too long\n"); break; } strcat(commandLine, svr_argv[i]); strcat(commandLine, flagSep); } - if (IsValidCipherSuite(commandLine, cipherSuite) == 0) { #ifdef DEBUG_SUITE_TESTS printf("cipher suite %s not supported in build\n", cipherSuite); @@ -203,7 +211,6 @@ static int execute_test_case(int svr_argc, char** svr_argv, return VERSION_TOO_OLD; } #endif - #ifdef NO_OLD_TLS if (IsOldTlsVersion(commandLine) == 1) { #ifdef DEBUG_SUITE_TESTS @@ -213,78 +220,52 @@ static int execute_test_case(int svr_argc, char** svr_argv, } #endif + /* Build Client Command */ if (addNoVerify) { - printf("repeating test with client cert request off\n"); - added += 4; /* -d plus space plus terminator */ - if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS) + printf("repeating test with client cert request off\n"); + if (svrArgs.argc >= MAX_ARGS) printf("server command line too long\n"); - else { - svr_argv[svr_argc++] = noVerifyFlag; - svrArgs.argc = svr_argc; - strcat(commandLine, noVerifyFlag); - strcat(commandLine, flagSep); - } + else + svr_argv[svrArgs.argc++] = noVerifyFlag; } if (addNonBlocking) { - printf("repeating test with non blocking on\n"); - added += 4; /* -N plus terminator */ - if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS) + printf("repeating test with non blocking on\n"); + if (svrArgs.argc >= MAX_ARGS) printf("server command line too long\n"); - else { - svr_argv[svr_argc++] = nonblockFlag; - svrArgs.argc = svr_argc; - strcat(commandLine, nonblockFlag); - strcat(commandLine, flagSep); - } + else + svr_argv[svrArgs.argc++] = nonblockFlag; } #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) - /* add port 0 */ - if (svr_argc + 2 > MAX_ARGS) + /* add port */ + if (svrArgs.argc + 2 > MAX_ARGS) printf("cannot add the magic port number flag to server\n"); - else - { - svr_argv[svr_argc++] = portFlag; - svr_argv[svr_argc++] = svrPort; - svrArgs.argc = svr_argc; + else { + svr_argv[svrArgs.argc++] = portFlag; + svr_argv[svrArgs.argc++] = svrPort; } #endif - printf("trying server command line[%d]: %s\n", tests, commandLine); + if (forceSrvDefCipherList) { + if (svrArgs.argc >= MAX_ARGS) + printf("cannot add the force def cipher list flag to server\n"); + else + svr_argv[svrArgs.argc++] = forceDefCipherListFlag; + } + /* update server flags list */ commandLine[0] = '\0'; added = 0; - for (i = 0; i < cli_argc; i++) { - added += XSTRLEN(cli_argv[i]) + 2; + for (i = 0; i < svrArgs.argc; i++) { + added += XSTRLEN(svr_argv[i]) + 2; if (added >= MAX_COMMAND_SZ) { - printf("client command line too long\n"); + printf("server command line too long\n"); break; } - strcat(commandLine, cli_argv[i]); + strcat(commandLine, svr_argv[i]); strcat(commandLine, flagSep); } - if (addNonBlocking) { - added += 4; /* -N plus space plus terminator */ - if (added >= MAX_COMMAND_SZ) - printf("client command line too long\n"); - else { - cli_argv[cli_argc++] = nonblockFlag; - strcat(commandLine, nonblockFlag); - strcat(commandLine, flagSep); - cliArgs.argc = cli_argc; - } - } - if (addDisableEMS) { - printf("repeating test without extended master secret\n"); - added += 4; /* -n plus terminator */ - if (added >= MAX_COMMAND_SZ) - printf("client command line too long\n"); - else { - cli_argv[cli_argc++] = disableEMSFlag; - strcat(commandLine, disableEMSFlag); - strcat(commandLine, flagSep); - cliArgs.argc = cli_argc; - } - } - printf("trying client command line[%d]: %s\n", tests++, commandLine); + printf("trying server command line[%d]: %s\n", tests, commandLine); + + tests++; /* test count */ InitTcpReady(&ready); @@ -296,31 +277,65 @@ static int execute_test_case(int svr_argc, char** svr_argv, svrArgs.signal = &ready; start_thread(server_test, &svrArgs, &serverThread); wait_tcp_ready(&svrArgs); - #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) - if (ready.port != 0) - { - if (cli_argc + 2 > MAX_ARGS) - printf("cannot add the magic port number flag to client\n"); - else { - char portNumber[8]; - snprintf(portNumber, sizeof(portNumber), "%d", ready.port); - cli_argv[cli_argc++] = portFlag; - cli_argv[cli_argc++] = portNumber; - cliArgs.argc = cli_argc; - } + + + /* Build Client Command */ + if (addNonBlocking) { + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the non block flag to client\n"); + else + cli_argv[cliArgs.argc++] = nonblockFlag; + } + if (addDisableEMS) { + printf("repeating test without extended master secret\n"); + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the disable EMS flag to client\n"); + else + cli_argv[cliArgs.argc++] = disableEMSFlag; + } +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + if (ready.port != 0) { + if (cliArgs.argc + 2 > MAX_ARGS) + printf("cannot add the magic port number flag to client\n"); + else { + char portNumber[8]; + snprintf(portNumber, sizeof(portNumber), "%d", ready.port); + cli_argv[cliArgs.argc++] = portFlag; + cli_argv[cliArgs.argc++] = portNumber; } - #endif + } +#endif + if (forceCliDefCipherList) { + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the force def cipher list flag to client\n"); + else + cli_argv[cliArgs.argc++] = forceDefCipherListFlag; + } + + commandLine[0] = '\0'; + added = 0; + for (i = 0; i < cliArgs.argc; i++) { + added += XSTRLEN(cli_argv[i]) + 2; + if (added >= MAX_COMMAND_SZ) { + printf("client command line too long\n"); + break; + } + strcat(commandLine, cli_argv[i]); + strcat(commandLine, flagSep); + } + printf("trying client command line[%d]: %s\n", tests, commandLine); + /* start client */ client_test(&cliArgs); - /* verify results */ + /* verify results */ if (cliArgs.return_code != 0) { printf("client_test failed\n"); exit(EXIT_FAILURE); } join_thread(serverThread); - if (svrArgs.return_code != 0) { + if (svrArgs.return_code != 0) { printf("server_test failed\n"); exit(EXIT_FAILURE); } @@ -329,7 +344,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, fdCloseSession(Task_self()); #endif FreeTcpReady(&ready); - + return 0; } @@ -361,7 +376,7 @@ static void test_harness(void* vargs) fname = args->argv[1]; } - file = fopen(fname, "r"); + file = fopen(fname, "rb"); if (file == NULL) { fprintf(stderr, "unable to open %s\n", fname); args->return_code = 1; @@ -393,7 +408,7 @@ static void test_harness(void* vargs) args->return_code = 1; return; } - + fclose(file); script[sz] = 0; @@ -442,7 +457,7 @@ static void test_harness(void* vargs) else svrArgs[svrArgsSz++] = strsep(&cursor, "\n"); if (*cursor == 0) /* eof */ - do_it = 1; + do_it = 1; } if (svrArgsSz == MAX_ARGS || cliArgsSz == MAX_ARGS) { @@ -452,24 +467,31 @@ static void test_harness(void* vargs) if (do_it) { ret = execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 0, 0); + cliArgsSz, cliArgs, 0, 0, 0, 0, 0); /* don't repeat if not supported in build */ if (ret == 0) { + /* test with default cipher list on server side */ + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 0, 0, 0, 1, 0); + /* test with default cipher list on client side */ + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 0, 0, 0, 0, 1); + execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 1, 0); + cliArgsSz, cliArgs, 0, 1, 0, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 0, 0); + cliArgsSz, cliArgs, 1, 0, 0, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 1, 0); + cliArgsSz, cliArgs, 1, 1, 0, 0, 0); #ifdef HAVE_EXTENDED_MASTER execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 0, 1); + cliArgsSz, cliArgs, 0, 0, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 1, 1); + cliArgsSz, cliArgs, 0, 1, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 0, 1); + cliArgsSz, cliArgs, 1, 0, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 1, 1); + cliArgsSz, cliArgs, 1, 1, 1, 0, 0); #endif } svrArgsSz = 1; @@ -515,22 +537,43 @@ int SuiteTest(void) memory, sizeof(memory), 0, 1) != SSL_SUCCESS) { printf("unable to load static memory and create ctx"); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +#ifdef WOLFSSL_ASYNC_CRYPT + if (wolfAsync_DevOpen(&devId) < 0) { + printf("Async device open failed"); + args.return_code = EXIT_FAILURE; + goto exit; + } + wolfSSL_CTX_UseAsync(cipherSuiteCtx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + /* default case */ args.argc = 1; printf("starting default cipher suite tests\n"); test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } /* any extra cases will need another argument */ args.argc = 2; +#ifdef WOLFSSL_TLS13 + /* add TLSv13 extra suites */ + strcpy(argv0[1], "tests/test-tls13.conf"); + printf("starting TLSv13 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif #ifdef WOLFSSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); @@ -538,7 +581,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif #ifdef WOLFSSL_SCTP @@ -548,7 +592,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif #ifndef WC_STRICT_SIG @@ -559,7 +604,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif /* HAVE_RSA and HAVE_ECC */ #endif /* !WC_STRICT_SIG */ @@ -570,7 +616,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif @@ -581,15 +628,21 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +exit: printf(" End Cipher Suite Tests\n"); wolfSSL_CTX_free(cipherSuiteCtx); wolfSSL_Cleanup(); +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + return args.return_code; } diff --git a/tests/test-dtls.conf b/tests/test-dtls.conf index fb4260e62c..5bd76c694b 100644 --- a/tests/test-dtls.conf +++ b/tests/test-dtls.conf @@ -1,36 +1,3 @@ -# server DTLSv1 DHE-RSA-CHACHA20-POLY1305 --u --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 DHE-RSA-CHACHA20-POLY1305 --u --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 -u -v 3 @@ -133,26 +100,6 @@ -l ECDHE-ECDSA-CHACHA20-POLY1305-OLD -A ./certs/server-ecc.pem -# server DTLSv1 RC4-SHA --u --v 2 --l RC4-SHA - -# client DTLSv1 RC4-SHA --u --v 2 --l RC4-SHA - -# server DTLSv1.2 RC4-SHA --u --v 3 --l RC4-SHA - -# client DTLSv1.2 RC4-SHA --u --v 3 --l RC4-SHA - # server DTLSv1 IDEA-CBC-SHA -u -v 2 @@ -263,16 +210,6 @@ -v 3 -l AES256-SHA256 -# server DTLSv1 ECDHE-RSA-RC4 --u --v 2 --l ECDHE-RSA-RC4-SHA - -# client DTLSv1 ECDHE-RSA-RC4 --u --v 2 --l ECDHE-RSA-RC4-SHA - # server DTLSv1.1 ECDHE-RSA-DES3 -u -v 2 @@ -283,12 +220,12 @@ -v 2 -l ECDHE-RSA-DES-CBC3-SHA -# server DTLSv1.1 ECDHE-RSA-AES128 +# server DTLSv1.1 ECDHE-RSA-AES128 -u -v 2 -l ECDHE-RSA-AES128-SHA -# client DTLSv1.1 ECDHE-RSA-AES128 +# client DTLSv1.1 ECDHE-RSA-AES128 -u -v 2 -l ECDHE-RSA-AES128-SHA @@ -303,16 +240,6 @@ -v 2 -l ECDHE-RSA-AES256-SHA -# server DTLSv1.2 ECDHE-RSA-RC4 --u --v 3 --l ECDHE-RSA-RC4-SHA - -# client DTLSv1.2 ECDHE-RSA-RC4 --u --v 3 --l ECDHE-RSA-RC4-SHA - # server DTLSv1.2 ECDHE-RSA-DES3 -u -v 3 @@ -323,12 +250,12 @@ -v 3 -l ECDHE-RSA-DES-CBC3-SHA -# server DTLSv1.2 ECDHE-RSA-AES128 +# server DTLSv1.2 ECDHE-RSA-AES128 -u -v 3 -l ECDHE-RSA-AES128-SHA -# client DTLSv1.2 ECDHE-RSA-AES128 +# client DTLSv1.2 ECDHE-RSA-AES128 -u -v 3 -l ECDHE-RSA-AES128-SHA @@ -338,7 +265,7 @@ -v 3 -l ECDHE-RSA-AES128-SHA256 -# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 -u -v 3 -l ECDHE-RSA-AES128-SHA256 @@ -392,19 +319,6 @@ -l ECDHE-ECDSA-NULL-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDHE-EDCSA-RC4 --u --v 2 --l ECDHE-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDHE-ECDSA-RC4 --u --v 2 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.1 ECDHE-ECDSA-DES3 -u -v 2 @@ -418,14 +332,14 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDHE-ECDSA-AES128 +# server DTLSv1.1 ECDHE-ECDSA-AES128 -u -v 2 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDHE-ECDSA-AES128 +# client DTLSv1.1 ECDHE-ECDSA-AES128 -u -v 2 -l ECDHE-ECDSA-AES128-SHA @@ -444,19 +358,6 @@ -l ECDHE-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDHE-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.2 ECDHE-ECDSA-DES3 -u -v 3 @@ -470,14 +371,14 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-ECDSA-AES128 +# server DTLSv1.2 ECDHE-ECDSA-AES128 -u -v 3 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDHE-ECDSA-AES128 +# client DTLSv1.2 ECDHE-ECDSA-AES128 -u -v 3 -l ECDHE-ECDSA-AES128-SHA @@ -509,18 +410,6 @@ -l ECDHE-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDH-RSA-RC4 --u --v 2 --l ECDH-RSA-RC4-SHA --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDH-RSA-RC4 --u --v 2 --l ECDH-RSA-RC4-SHA - # server DTLSv1.1 ECDH-RSA-DES3 -u -v 2 @@ -533,14 +422,14 @@ -v 2 -l ECDH-RSA-DES-CBC3-SHA -# server DTLSv1.1 ECDH-RSA-AES128 +# server DTLSv1.1 ECDH-RSA-AES128 -u -v 2 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDH-RSA-AES128 +# client DTLSv1.1 ECDH-RSA-AES128 -u -v 2 -l ECDH-RSA-AES128-SHA @@ -557,18 +446,6 @@ -v 2 -l ECDH-RSA-AES256-SHA -# server DTLSv1.2 ECDH-RSA-RC4 --u --v 3 --l ECDH-RSA-RC4-SHA --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDH-RSA-RC4 --u --v 3 --l ECDH-RSA-RC4-SHA - # server DTLSv1.2 ECDH-RSA-DES3 -u -v 3 @@ -581,26 +458,26 @@ -v 3 -l ECDH-RSA-DES-CBC3-SHA -# server DTLSv1.2 ECDH-RSA-AES128 +# server DTLSv1.2 ECDH-RSA-AES128 -u -v 3 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128 +# client DTLSv1.2 ECDH-RSA-AES128 -u -v 3 -l ECDH-RSA-AES128-SHA -# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 -u -v 3 -l ECDH-RSA-AES128-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128-SHA256 +# client DTLSv1.2 ECDH-RSA-AES128-SHA256 -u -v 3 -l ECDH-RSA-AES128-SHA256 @@ -617,19 +494,6 @@ -v 3 -l ECDH-RSA-AES256-SHA -# server DTLSv1.1 ECDH-EDCSA-RC4 --u --v 2 --l ECDH-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDH-ECDSA-RC4 --u --v 2 --l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.1 ECDH-ECDSA-DES3 -u -v 2 @@ -643,14 +507,14 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDH-ECDSA-AES128 +# server DTLSv1.1 ECDH-ECDSA-AES128 -u -v 2 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDH-ECDSA-AES128 +# client DTLSv1.1 ECDH-ECDSA-AES128 -u -v 2 -l ECDH-ECDSA-AES128-SHA @@ -669,19 +533,6 @@ -l ECDH-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDH-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDH-ECDSA-RC4 --u --v 3 --l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.2 ECDH-ECDSA-DES3 -u -v 3 @@ -695,14 +546,14 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDH-ECDSA-AES128 +# server DTLSv1.2 ECDH-ECDSA-AES128 -u -v 3 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128 +# client DTLSv1.2 ECDH-ECDSA-AES128 -u -v 3 -l ECDH-ECDSA-AES128-SHA @@ -715,7 +566,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-SHA256 @@ -734,12 +585,12 @@ -l ECDH-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 -u -v 3 -l ECDHE-RSA-AES256-SHA384 -# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 -u -v 3 -l ECDHE-RSA-AES256-SHA384 @@ -757,14 +608,14 @@ -l ECDHE-ECDSA-AES256-SHA384 -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 -u -v 3 -l ECDH-RSA-AES256-SHA384 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES256-SHA384 +# client DTLSv1.2 ECDH-RSA-AES256-SHA384 -u -v 3 -l ECDH-RSA-AES256-SHA384 @@ -776,7 +627,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 -u -v 3 -l ECDH-ECDSA-AES256-SHA384 @@ -926,14 +777,14 @@ -v 3 -l PSK-AES256-CBC-SHA384 -# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 @@ -952,14 +803,14 @@ -l ECDHE-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 @@ -978,12 +829,12 @@ -l ECDH-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 @@ -998,14 +849,14 @@ -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-RSA-AES128-GCM-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-RSA-AES128-GCM-SHA256 diff --git a/tests/test-sig.conf b/tests/test-sig.conf index 4ce46ca83e..aa7f3b2958 100644 --- a/tests/test-sig.conf +++ b/tests/test-sig.conf @@ -174,6 +174,17 @@ -l ECDHE-ECDSA-AES128-GCM-SHA256 -A ./certs/ca-cert.pem +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-privkey.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem + # server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 -l ECDHE-ECDSA-AES256-GCM-SHA384 diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf new file mode 100644 index 0000000000..cf1e9f7f92 --- /dev/null +++ b/tests/test-tls13.conf @@ -0,0 +1,95 @@ +# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 + +# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 + +# client TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 + +# server TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 + +# client TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 + +# server TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 + +# client TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 + +# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 +-A ./certs/server-ecc.pem + diff --git a/tests/test.conf b/tests/test.conf index 37f672ab0b..933d001fd2 100644 --- a/tests/test.conf +++ b/tests/test.conf @@ -1,30 +1,3 @@ -# server TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-EDCSA-CHACHA20-POLY1305 --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1.1 ECDHE-ECDSA-CHACHA20-POLY1305 --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server TLSv1.2 DHE-RSA-CHACHA20-POLY1305 -v 3 -l DHE-RSA-CHACHA20-POLY1305 @@ -341,11 +314,11 @@ -v 1 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1 ECDHE-RSA-AES128 +# server TLSv1 ECDHE-RSA-AES128 -v 1 -l ECDHE-RSA-AES128-SHA -# client TLSv1 ECDHE-RSA-AES128 +# client TLSv1 ECDHE-RSA-AES128 -v 1 -l ECDHE-RSA-AES128-SHA @@ -373,11 +346,11 @@ -v 2 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1.1 ECDHE-RSA-AES128 +# server TLSv1.1 ECDHE-RSA-AES128 -v 2 -l ECDHE-RSA-AES128-SHA -# client TLSv1.1 ECDHE-RSA-AES128 +# client TLSv1.1 ECDHE-RSA-AES128 -v 2 -l ECDHE-RSA-AES128-SHA @@ -405,11 +378,11 @@ -v 3 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1.2 ECDHE-RSA-AES128 +# server TLSv1.2 ECDHE-RSA-AES128 -v 3 -l ECDHE-RSA-AES128-SHA -# client TLSv1.2 ECDHE-RSA-AES128 +# client TLSv1.2 ECDHE-RSA-AES128 -v 3 -l ECDHE-RSA-AES128-SHA @@ -417,7 +390,7 @@ -v 3 -l ECDHE-RSA-AES128-SHA256 -# client TLSv1.2 ECDHE-RSA-AES128-SHA256 +# client TLSv1.2 ECDHE-RSA-AES128-SHA256 -v 3 -l ECDHE-RSA-AES128-SHA256 @@ -484,13 +457,13 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1 ECDHE-ECDSA-AES128 +# server TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDHE-ECDSA-AES128 +# client TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -528,13 +501,13 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.1 ECDHE-ECDSA-AES128 +# server TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDHE-ECDSA-AES128 +# client TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -572,13 +545,13 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.2 ECDHE-ECDSA-AES128 +# server TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-AES128 +# client TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -625,13 +598,13 @@ -v 1 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1 ECDH-RSA-AES128 +# server TLSv1 ECDH-RSA-AES128 -v 1 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDH-RSA-AES128 +# client TLSv1 ECDH-RSA-AES128 -v 1 -l ECDH-RSA-AES128-SHA @@ -665,13 +638,13 @@ -v 2 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1.1 ECDH-RSA-AES128 +# server TLSv1.1 ECDH-RSA-AES128 -v 2 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDH-RSA-AES128 +# client TLSv1.1 ECDH-RSA-AES128 -v 2 -l ECDH-RSA-AES128-SHA @@ -705,23 +678,23 @@ -v 3 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1.2 ECDH-RSA-AES128 +# server TLSv1.2 ECDH-RSA-AES128 -v 3 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128 +# client TLSv1.2 ECDH-RSA-AES128 -v 3 -l ECDH-RSA-AES128-SHA -# server TLSv1.2 ECDH-RSA-AES128-SHA256 +# server TLSv1.2 ECDH-RSA-AES128-SHA256 -v 3 -l ECDH-RSA-AES128-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128-SHA256 +# client TLSv1.2 ECDH-RSA-AES128-SHA256 -v 3 -l ECDH-RSA-AES128-SHA256 @@ -757,13 +730,13 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1 ECDH-ECDSA-AES128 +# server TLSv1 ECDH-ECDSA-AES128 -v 1 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDH-ECDSA-AES128 +# client TLSv1 ECDH-ECDSA-AES128 -v 1 -l ECDH-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -801,13 +774,13 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.1 ECDH-ECDSA-AES128 +# server TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDH-ECDSA-AES128 +# client TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l ECDH-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -845,13 +818,13 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.2 ECDH-ECDSA-AES128 +# server TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128 +# client TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l ECDH-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -862,7 +835,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 +# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 -v 3 -l ECDH-ECDSA-AES128-SHA256 -A ./certs/server-ecc.pem @@ -882,7 +855,7 @@ -v 3 -l ECDHE-RSA-AES256-SHA384 -# client TLSv1.2 ECDHE-RSA-AES256-SHA384 +# client TLSv1.2 ECDHE-RSA-AES256-SHA384 -v 3 -l ECDHE-RSA-AES256-SHA384 @@ -897,13 +870,13 @@ -l ECDHE-ECDSA-AES256-SHA384 -A ./certs/server-ecc.pem -# server TLSv1.2 ECDH-RSA-AES256-SHA384 +# server TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 -l ECDH-RSA-AES256-SHA384 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES256-SHA384 +# client TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 -l ECDH-RSA-AES256-SHA384 @@ -913,7 +886,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 +# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 -v 3 -l ECDH-ECDSA-AES256-SHA384 -A ./certs/server-ecc.pem @@ -1664,11 +1637,11 @@ -v 3 -l DHE-RSA-CAMELLIA256-SHA256 -# server TLSv1.2 RSA-AES128-GCM-SHA256 +# server TLSv1.2 RSA-AES128-GCM-SHA256 -v 3 -l AES128-GCM-SHA256 -# client TLSv1.2 RSA-AES128-GCM-SHA256 +# client TLSv1.2 RSA-AES128-GCM-SHA256 -v 3 -l AES128-GCM-SHA256 @@ -1680,13 +1653,13 @@ -v 3 -l AES256-GCM-SHA384 -# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -A ./certs/server-ecc.pem @@ -1702,13 +1675,13 @@ -l ECDHE-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -A ./certs/server-ecc.pem @@ -1724,11 +1697,11 @@ -l ECDH-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 @@ -1740,13 +1713,13 @@ -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -v 3 -l ECDH-RSA-AES128-GCM-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -v 3 -l ECDH-RSA-AES128-GCM-SHA256 @@ -1760,11 +1733,11 @@ -v 3 -l ECDH-RSA-AES256-GCM-SHA384 -# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 -v 3 -l DHE-RSA-AES128-GCM-SHA256 -# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 -v 3 -l DHE-RSA-AES128-GCM-SHA256 @@ -2196,3 +2169,12 @@ -v 3 -l NTRU-AES128-SHA +# server TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-SHA256 +-j + diff --git a/tests/unit.c b/tests/unit.c index dd98465291..39a76ddf2f 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -45,7 +45,7 @@ int main(int argc, char** argv) int unit_test(int argc, char** argv) { - int ret; + int ret = 0; (void)argc; (void)argv; @@ -68,24 +68,25 @@ int unit_test(int argc, char** argv) if ( (ret = HashTest()) != 0){ printf("hash test failed with %d\n", ret); - return ret; + goto exit; } #ifndef SINGLE_THREADED if ( (ret = SuiteTest()) != 0){ printf("suite test failed with %d\n", ret); - return ret; + goto exit; } #endif SrpTest(); +exit: #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); #endif /* HAVE_WNR */ - return 0; + return ret; } diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 3a2bc64ec1..144efb140a 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -210,7 +210,7 @@ int testsuite_test(int argc, char** argv) #endif /* HAVE_WNR */ printf("\nAll tests passed!\n"); - EXIT_TEST(EXIT_SUCCESS); + return EXIT_SUCCESS; } void simple_test(func_args* args) @@ -405,11 +405,13 @@ int main(int argc, char** argv) server_args.argc = argc; server_args.argv = argv; + wolfSSL_Init(); ChangeToWolfRoot(); wolfcrypt_test(&server_args); if (server_args.return_code != 0) return server_args.return_code; + wolfSSL_Cleanup(); printf("\nAll tests passed!\n"); EXIT_TEST(EXIT_SUCCESS); diff --git a/tirtos/README b/tirtos/README index 6001f56644..dc7fbb1149 100644 --- a/tirtos/README +++ b/tirtos/README @@ -7,6 +7,9 @@ library and the example applications. Also read TI-RTOS Getting Started Guide and TI-RTOS User Guide to learn more about TI-RTOS (http://www.ti.com/tool/ti-rtos). +For more information see: +(https://github.com/wolfSSL/wolfssl-examples/blob/master/tirtos_ccs_examples/README.md) + ## Example Application A simple "TCP echo server with TLS" example application is provided with TI-RTOS diff --git a/tirtos/packages/ti/net/wolfssl/package.bld b/tirtos/packages/ti/net/wolfssl/package.bld index 1d506f13f6..91b7d79c99 100644 --- a/tirtos/packages/ti/net/wolfssl/package.bld +++ b/tirtos/packages/ti/net/wolfssl/package.bld @@ -41,6 +41,7 @@ var wolfSSLObjList = [ "wolfcrypt/src/sha512.c", "wolfcrypt/src/tfm.c", "wolfcrypt/src/wc_port.c", + "wolfcrypt/src/wolfmath.c", "src/internal.c", "src/io.c", diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 0b5ad6ad7e..80018c149d 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -32,6 +32,10 @@ /* Macro to disable benchmark */ #ifndef NO_CRYPT_BENCHMARK +#ifdef XMALLOC_USER + #include /* we're using malloc / free direct here */ +#endif + #ifdef WOLFSSL_STATIC_MEMORY #include static WOLFSSL_HEAP_HINT* HEAP_HINT; @@ -48,6 +52,11 @@ #else #include #endif +#elif defined(FREESCALE_KSDK_BM) + #include "fsl_debug_console.h" + #include "fsl_os_abstraction.h" + #undef printf + #define printf PRINTF #else #include #endif @@ -93,40 +102,44 @@ #include #include +/* only for stack size check */ +#ifdef HAVE_STACK_SIZE + #include + #include +#endif + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif -#if defined(WOLFSSL_ASYNC_CRYPT) || defined(HAVE_ECC) - static int devId = INVALID_DEVID; -#endif #ifdef HAVE_WNR const char* wnrConfigFile = "wnr-example.conf"; #endif #if defined(WOLFSSL_MDK_ARM) - extern FILE * wolfSSL_fopen(const char *fname, const char *mode) ; + extern FILE * wolfSSL_fopen(const char *fname, const char *mode); #define fopen wolfSSL_fopen #endif #if defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM) #define HAVE_GET_CYCLES static INLINE word64 get_intel_cycles(void); - static word64 total_cycles; + static THREAD_LS_T word64 total_cycles; #define INIT_CYCLE_COUNTER #define BEGIN_INTEL_CYCLES total_cycles = get_intel_cycles(); #define END_INTEL_CYCLES total_cycles = get_intel_cycles() - total_cycles; #define SHOW_INTEL_CYCLES printf(" Cycles per byte = %6.2f", \ - (float)total_cycles / (numBlocks*sizeof(plain))); + count == 0 ? 0 : \ + (float)total_cycles / (count*BENCH_SIZE)); #elif defined(LINUX_CYCLE_COUNT) #include #include #include - static word64 begin_cycles; - static word64 total_cycles; - static int cycles = -1; - static struct perf_event_attr atr; + static THREAD_LS_T word64 begin_cycles; + static THREAD_LS_T word64 total_cycles; + static THREAD_LS_T int cycles = -1; + static THREAD_LS_T struct perf_event_attr atr; #define INIT_CYCLE_COUNTER do { \ atr.type = PERF_TYPE_HARDWARE; \ @@ -141,7 +154,7 @@ } while (0); #define SHOW_INTEL_CYCLES printf(" Cycles per byte = %6.2f", \ - (float)total_cycles / (numBlocks*sizeof(plain))); + (float)total_cycles / (count*BENCH_SIZE)); #else #define INIT_CYCLE_COUNTER @@ -158,7 +171,7 @@ #if defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048) \ || !defined(NO_DH) /* include test cert and key buffers for use with NO_FILESYSTEM */ - #include + #include #endif @@ -174,43 +187,36 @@ #include "wolfcrypt/benchmark/benchmark.h" -#ifdef USE_WOLFSSL_MEMORY - #include "wolfssl/wolfcrypt/mem_track.h" -#endif - -void bench_des(void); +void bench_des(int); void bench_idea(void); -void bench_arc4(void); +void bench_arc4(int); void bench_hc128(void); void bench_rabbit(void); void bench_chacha(void); void bench_chacha20_poly1305_aead(void); -void bench_aes(int); -void bench_aesgcm(void); +void bench_aescbc(int); +void bench_aesgcm(int); void bench_aesccm(void); void bench_aesctr(void); void bench_poly1305(void); void bench_camellia(void); -void bench_md5(void); -void bench_sha(void); -void bench_sha224(void); -void bench_sha256(void); -void bench_sha384(void); -void bench_sha512(void); -void bench_ripemd(void); +void bench_md5(int); +void bench_sha(int); +void bench_sha224(int); +void bench_sha256(int); +void bench_sha384(int); +void bench_sha512(int); +int bench_ripemd(void); void bench_cmac(void); void bench_scrypt(void); -void bench_rsa(void); -#ifdef WOLFSSL_ASYNC_CRYPT - void bench_rsa_async(void); -#endif -void bench_rsaKeyGen(void); -void bench_dh(void); +void bench_rsaKeyGen(int); +void bench_rsa(int); +void bench_dh(int); #ifdef HAVE_ECC -void bench_eccKeyGen(void); -void bench_eccKeyAgree(void); +void bench_eccMakeKey(int); +void bench_ecc(int); #ifdef HAVE_ECC_ENCRYPT void bench_eccEncrypt(void); #endif @@ -233,37 +239,215 @@ void bench_ntruKeyGen(void); void bench_rng(void); #endif /* WC_NO_RNG */ -double current_time(int); - +#ifdef WOLFSSL_CURRTIME_REMAP + #define current_time WOLFSSL_CURRTIME_REMAP +#elif !defined(HAVE_STACK_SIZE) + double current_time(int); +#endif -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ + !defined(HAVE_STACK_SIZE) WOLFSSL_API int wolfSSL_Debugging_ON(); + WOLFSSL_API void wolfSSL_Debugging_OFF(void); #endif #if !defined(NO_RSA) || !defined(NO_DH) \ || defined(WOLFSSL_KEYGEN) || defined(HAVE_ECC) \ || defined(HAVE_CURVE25519) || defined(HAVE_ED25519) #define HAVE_LOCAL_RNG - static WC_RNG rng; + static THREAD_LS_T WC_RNG rng; #endif -/* use kB instead of mB for embedded benchmarking */ -#ifdef BENCH_EMBEDDED - static byte plain [1024]; + + +/* Asynchronous helper macros */ +static THREAD_LS_T int devId = INVALID_DEVID; + +#ifdef WOLFSSL_ASYNC_CRYPT + static THREAD_LS_T WOLF_EVENT_QUEUE eventQueue; + static THREAD_LS_T int asyncPending; + + #define BENCH_ASYNC_GET_DEV(obj) (&(obj)->asyncDev) + #define BENCH_ASYNC_GET_NAME(doAsync) (doAsync) ? "HW" : "SW" + #define BENCH_ASYNC_IS_PEND() (asyncPending > 0) + #define BENCH_MAX_PENDING (WOLF_ASYNC_MAX_PENDING) + +#ifndef WC_NO_ASYNC_THREADING + typedef struct ThreadData { + pthread_t thread_id; + } ThreadData; + static ThreadData* g_threadData; + static int g_threadCount; +#endif + + static INLINE int bench_async_begin(void) { + /* init event queue */ + asyncPending = 0; + return wolfEventQueue_Init(&eventQueue); + } + + static INLINE void bench_async_end(void) { + /* free event queue */ + wolfEventQueue_Free(&eventQueue); + } + + static INLINE void bench_async_complete(int* ret, WC_ASYNC_DEV* asyncDev, + int* times) + { + *ret = asyncDev->event.ret; + if (*ret >= 0) { + (*times)++; + asyncDev->event.done = 0; /* reset done flag */ + } + } + + static INLINE int bench_async_check(int* ret, WC_ASYNC_DEV* asyncDev, + int callAgain, int* times, int limit) + { + int allowNext = 0; + + /* if algo doesn't require calling again then use this flow */ + if (!callAgain) { + if (asyncDev->event.done) { + /* operation completed */ + bench_async_complete(ret, asyncDev, times); + } + } + /* if algo does require calling again then use this flow */ + else { + if (asyncDev->event.done) { + allowNext = 1; + } + } + + if (asyncDev->event.pending == 0 && + (*times + asyncPending) < limit) { + allowNext = 1; + } + + return allowNext; + } + + static INLINE int bench_async_handle(int* ret, WC_ASYNC_DEV* asyncDev, + int callAgain, int* times) + { + if (*ret == WC_PENDING_E) { + *ret = wc_AsyncHandle(asyncDev, &eventQueue, + callAgain ? WC_ASYNC_FLAG_CALL_AGAIN : WC_ASYNC_FLAG_NONE); + if (*ret == 0) + asyncPending++; + } + else if (*ret >= 0) { + /* operation completed */ + bench_async_complete(ret, asyncDev, times); + } + + return (*ret >= 0) ? 1 : 0; + } + + static INLINE void bench_async_poll(void) + { + /* poll until there are events done */ + if (asyncPending > 0) { + int ret, asyncDone = 0; + do { + ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, + WOLF_POLL_FLAG_CHECK_HW, &asyncDone); + if (ret != 0) { + printf("Async poll failed %d\n", ret); + return; + } + } while (asyncDone == 0); + asyncPending -= asyncDone; + } + } + #else - static byte plain [1024*1024]; + #define BENCH_MAX_PENDING (1) + #define BENCH_ASYNC_GET_NAME(doAsync) "" + #define BENCH_ASYNC_GET_DEV(obj) NULL + #define BENCH_ASYNC_IS_PEND() (0) + + #define bench_async_begin() + #define bench_async_end() (void)doAsync; + + static INLINE int bench_async_check(int* ret, void* asyncDev, + int callAgain, int* times, int limit) + { + (void)ret; + (void)asyncDev; + (void)callAgain; + (void)times; + (void)limit; + + return 1; + } + + static INLINE int bench_async_handle(int* ret, void* asyncDev, + int callAgain, int* times) + { + (void)asyncDev; + (void)callAgain; + + if (*ret >= 0) { + /* operation completed */ + (*times)++; + return 1; + } + return 0; + } + #define bench_async_poll() +#endif /* WOLFSSL_ASYNC_CRYPT */ + + + +/* maximum runtime for each benchmark */ +#define BENCH_MIN_RUNTIME_SEC 1.0f + + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + #define AES_AUTH_ADD_SZ 13 + #define AES_AUTH_TAG_SZ 16 + #define BENCH_CIPHER_ADD AES_AUTH_TAG_SZ +#endif +#ifndef BENCH_CIPHER_ADD + #define BENCH_CIPHER_ADD 0 #endif /* use kB instead of mB for embedded benchmarking */ #ifdef BENCH_EMBEDDED - static byte cipher[1024]; + enum BenchmarkBounds { + numBlocks = 25, /* how many kB to test (en/de)cryption */ + scryptCnt = 1, + ntimes = 2, + genTimes = BENCH_MAX_PENDING, + agreeTimes = 2 + }; + static const char blockType[] = "kB"; /* used in printf output */ + #define BENCH_SIZE (1024ul) #else - static byte cipher[1024*1024]; + enum BenchmarkBounds { + numBlocks = 5, /* how many megs to test (en/de)cryption */ + scryptCnt = 10, + ntimes = 100, + genTimes = BENCH_MAX_PENDING, /* must be at least BENCH_MAX_PENDING */ + agreeTimes = 100 + }; + static const char blockType[] = "megs"; /* used in printf output */ + #define BENCH_SIZE (1024*1024ul) #endif -static const XGEN_ALIGN byte key[] = +/* globals for cipher tests */ +#ifdef WOLFSSL_ASYNC_CRYPT + static byte* bench_plain = NULL; + static byte* bench_cipher = NULL; +#else + static byte bench_plain[BENCH_SIZE]; + static byte bench_cipher[BENCH_SIZE]; +#endif +static const XGEN_ALIGN byte bench_key_buf[] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, @@ -271,78 +455,246 @@ static const XGEN_ALIGN byte key[] = 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef }; -static const XGEN_ALIGN byte iv[] = +static const XGEN_ALIGN byte bench_iv_buf[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 }; +static byte* bench_key = (byte*)bench_key_buf; +static byte* bench_iv = (byte*)bench_iv_buf; +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef BENCH_EMBEDDED + static byte gBenchMemory[50000]; + #else + static byte gBenchMemory[400000]; + #endif +#endif -/* so embedded projects can pull in tests on their own */ -#if !defined(NO_MAIN_DRIVER) -int main(int argc, char** argv) +/******************************************************************************/ +/* Begin Stats Functions */ +/******************************************************************************/ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + typedef enum bench_stat_type { + BENCH_STAT_ASYM, + BENCH_STAT_SYM, + } bench_stat_type_t; + typedef struct bench_stats { + struct bench_stats* next; + struct bench_stats* prev; + const char* algo; + const char* desc; + double perfsec; + int strength; + int doAsync; + int finishCount; + bench_stat_type_t type; + } bench_stats_t; + static bench_stats_t* bench_stats_head; + static bench_stats_t* bench_stats_tail; + static pthread_mutex_t bench_lock = PTHREAD_MUTEX_INITIALIZER; + + static bench_stats_t* bench_stats_add(bench_stat_type_t type, + const char* algo, int strength, const char* desc, int doAsync, + double perfsec) + { + bench_stats_t* stat; + pthread_mutex_lock(&bench_lock); + + /* locate existing in list */ + for (stat = bench_stats_head; stat != NULL; stat = stat->next) { + /* match based on algo, strength and desc */ + if (stat->algo == algo && stat->strength == strength && stat->desc == desc && stat->doAsync == doAsync) { + break; + } + } + + if (stat == NULL) { + /* allocate new and put on list */ + stat = (bench_stats_t*)XMALLOC(sizeof(bench_stats_t), NULL, DYNAMIC_TYPE_INFO); + if (stat) { + XMEMSET(stat, 0, sizeof(bench_stats_t)); + + /* add to list */ + stat->next = NULL; + if (bench_stats_tail == NULL) { + bench_stats_head = stat; + } + else { + bench_stats_tail->next = stat; + stat->prev = bench_stats_tail; + } + bench_stats_tail = stat; /* add to the end either way */ + } + } + + if (stat) { + int isLast = 0; + stat->type = type; + stat->algo = algo; + stat->strength = strength; + stat->desc = desc; + stat->doAsync = doAsync; + stat->perfsec += perfsec; + stat->finishCount++; + + if (stat->finishCount == g_threadCount) { + isLast = 1; + } + + pthread_mutex_unlock(&bench_lock); + + /* wait until remaining are complete */ + while (stat->finishCount < g_threadCount) { + wc_AsyncThreadYield(); + } + + /* print final stat */ + if (isLast) { + if (stat->type == BENCH_STAT_SYM) { + printf("%-8s%s %8.3f MB/s\n", stat->desc, + BENCH_ASYNC_GET_NAME(stat->doAsync), stat->perfsec); + } + else { + printf("%-5s %4d %-9s %s %.3f ops/sec\n", + stat->algo, stat->strength, stat->desc, + BENCH_ASYNC_GET_NAME(stat->doAsync), stat->perfsec); + } + } + + (void)blockType; + } + else { + pthread_mutex_unlock(&bench_lock); + } + + return stat; + } +#endif /* WOLFSSL_ASYNC_CRYPT && !WC_NO_ASYNC_THREADING */ + +static INLINE void bench_stats_init(void) { - (void)argc; - (void)argv; -#else -int benchmark_test(void *args) -{ - (void)args; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_head = NULL; + bench_stats_tail = NULL; #endif + INIT_CYCLE_COUNTER +} -#ifdef WOLFSSL_STATIC_MEMORY - #ifdef BENCH_EMBEDDED - byte memory[50000]; - #else - byte memory[400000]; - #endif +static INLINE void bench_stats_start(int* count, double* start) +{ + *count = 0; + *start = current_time(1); + BEGIN_INTEL_CYCLES +} - if (wc_LoadStaticMemory(&HEAP_HINT, memory, sizeof(memory), - WOLFMEM_GENERAL, 1) != 0) { - printf("unable to load static memory"); - exit(EXIT_FAILURE); - } +static INLINE int bench_stats_sym_check(double start) +{ + return ((current_time(0) - start) < BENCH_MIN_RUNTIME_SEC); +} + +static void bench_stats_sym_finish(const char* desc, int doAsync, int count, double start) +{ + double total, persec = 0; + + END_INTEL_CYCLES + total = current_time(0) - start; + + if (count > 0) + persec = 1 / total * count; +#ifdef BENCH_EMBEDDED + /* since using kB, convert to MB/s */ + persec = persec / 1024; #endif -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - InitMemoryTracker(); + printf("%-8s%s %5d %s took %5.3f seconds, %8.3f MB/s", + desc, BENCH_ASYNC_GET_NAME(doAsync), count, blockType, total, persec); + SHOW_INTEL_CYCLES + printf("\n"); + (void)doAsync; + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_SYM, NULL, 0, desc, doAsync, persec); #endif +} - wolfCrypt_Init(); - INIT_CYCLE_COUNTER +/* declare here rather than creating a static function to avoid warning of not + * used in the case of something like a leanpsk only build */ +void bench_stats_asym_finish(const char* algo, int strength, + const char* desc, int doAsync, int count, double start); -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) - wolfSSL_Debugging_ON(); +void bench_stats_asym_finish(const char* algo, int strength, + const char* desc, int doAsync, int count, double start) +{ + double total, each = 0, opsSec, milliEach; + + total = current_time(0) - start; + if (count > 0) + each = total / count; /* per second */ + opsSec = count / total; /* ops/per second */ + milliEach = each * 1000; /* milliseconds */ + + printf("%-5s %4d %-9s %s %6d ops took %5.3f sec, avg %5.3f ms," + " %.3f ops/sec\n", algo, strength, desc, BENCH_ASYNC_GET_NAME(doAsync), + count, total, milliEach, opsSec); + (void)doAsync; + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_ASYM, algo, strength, desc, doAsync, opsSec); +#endif +} + +static INLINE void bench_stats_free(void) +{ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_t* stat; + for (stat = bench_stats_head; stat != NULL; ) { + bench_stats_t* next = stat->next; + XFREE(stat, NULL, DYNAMIC_TYPE_INFO); + stat = next; + } + bench_stats_head = NULL; + bench_stats_tail = NULL; #endif +} +/******************************************************************************/ +/* End Stats Functions */ +/******************************************************************************/ - (void)plain; - (void)cipher; - (void)key; - (void)iv; +static void* benchmarks_do(void* args) +{ #ifdef WOLFSSL_ASYNC_CRYPT - if (wolfAsync_DevOpen(&devId) != 0) { - printf("Async device open failed\n"); - exit(-1); +#ifndef WC_NO_ASYNC_THREADING + ThreadData* threadData = (ThreadData*)args; + + if (wolfAsync_DevOpenThread(&devId, &threadData->thread_id) < 0) +#else + if (wolfAsync_DevOpen(&devId) < 0) +#endif + { + printf("Async device open failed\nRunning without async\n"); } #endif /* WOLFSSL_ASYNC_CRYPT */ -#ifdef HAVE_WNR - if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { - printf("Whitewood netRandom config init failed\n"); - exit(-1); - } -#endif /* HAVE_WNR */ + (void)args; #if defined(HAVE_LOCAL_RNG) { - int rngRet = wc_InitRng(&rng); + int rngRet; + +#ifndef HAVE_FIPS + rngRet = wc_InitRng_ex(&rng, HEAP_HINT, INVALID_DEVID); +#else + rngRet = wc_InitRng(&rng); +#endif if (rngRet < 0) { printf("InitRNG failed\n"); - return rngRet; } } #endif @@ -352,11 +704,20 @@ int benchmark_test(void *args) #endif /* WC_NO_RNG */ #ifndef NO_AES #ifdef HAVE_AES_CBC - bench_aes(0); - bench_aes(1); + #ifndef NO_SW_BENCH + bench_aescbc(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aescbc(1); + #endif #endif #ifdef HAVE_AESGCM - bench_aesgcm(); + #ifndef NO_SW_BENCH + bench_aesgcm(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aesgcm(1); + #endif #endif #ifdef WOLFSSL_AES_COUNTER bench_aesctr(); @@ -370,7 +731,12 @@ int benchmark_test(void *args) bench_camellia(); #endif #ifndef NO_RC4 - bench_arc4(); + #ifndef NO_SW_BENCH + bench_arc4(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + bench_arc4(1); + #endif #endif #ifdef HAVE_HC128 bench_hc128(); @@ -385,34 +751,67 @@ int benchmark_test(void *args) bench_chacha20_poly1305_aead(); #endif #ifndef NO_DES3 - bench_des(); + #ifndef NO_SW_BENCH + bench_des(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + bench_des(1); + #endif #endif #ifdef HAVE_IDEA bench_idea(); #endif - printf("\n"); - #ifndef NO_MD5 - bench_md5(); + #ifndef NO_SW_BENCH + bench_md5(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + bench_md5(1); + #endif #endif #ifdef HAVE_POLY1305 bench_poly1305(); #endif #ifndef NO_SHA - bench_sha(); + #ifndef NO_SW_BENCH + bench_sha(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + bench_sha(1); + #endif #endif #ifdef WOLFSSL_SHA224 - bench_sha224(); + #ifndef NO_SW_BENCH + bench_sha224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + bench_sha224(1); + #endif #endif #ifndef NO_SHA256 - bench_sha256(); + #ifndef NO_SW_BENCH + bench_sha256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + bench_sha256(1); + #endif #endif #ifdef WOLFSSL_SHA384 - bench_sha384(); + #ifndef NO_SW_BENCH + bench_sha384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + bench_sha384(1); + #endif #endif #ifdef WOLFSSL_SHA512 - bench_sha512(); + #ifndef NO_SW_BENCH + bench_sha512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_sha512(1); + #endif #endif #ifdef WOLFSSL_RIPEMD bench_ripemd(); @@ -424,26 +823,37 @@ int benchmark_test(void *args) bench_cmac(); #endif - printf("\n"); - #ifdef HAVE_SCRYPT bench_scrypt(); #endif - printf("\n"); - #ifndef NO_RSA - bench_rsa(); - #ifdef WOLFSSL_ASYNC_CRYPT - bench_rsa_async(); - #endif #ifdef WOLFSSL_KEY_GEN - bench_rsaKeyGen(); + #ifndef NO_SW_BENCH + bench_rsaKeyGen(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + /* async supported in simulator only */ + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + bench_rsaKeyGen(1); + #endif + #endif + #endif + #ifndef NO_SW_BENCH + bench_rsa(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + bench_rsa(1); #endif #endif #ifndef NO_DH - bench_dh(); + #ifndef NO_SW_BENCH + bench_dh(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + bench_dh(1); + #endif #endif #ifdef HAVE_NTRU @@ -452,14 +862,24 @@ int benchmark_test(void *args) #endif #ifdef HAVE_ECC - bench_eccKeyGen(); - bench_eccKeyAgree(); + #ifndef NO_SW_BENCH + bench_eccMakeKey(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* async supported in simulator only */ + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + bench_eccMakeKey(1); + #endif + #endif + #ifndef NO_SW_BENCH + bench_ecc(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + bench_ecc(1); + #endif #ifdef HAVE_ECC_ENCRYPT bench_eccEncrypt(); #endif - #if defined(FP_ECC) - wc_ecc_fp_free(); - #endif #endif #ifdef HAVE_CURVE25519 @@ -482,246 +902,357 @@ int benchmark_test(void *args) wolfAsync_DevClose(&devId); #endif -#ifdef HAVE_WNR - if (wc_FreeNetRandom() < 0) { - printf("Failed to free netRandom context\n"); - exit(-1); - } -#endif - -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - ShowMemoryTracker(); -#endif - - EXIT_TEST(0); + return NULL; } -#ifdef BENCH_EMBEDDED -enum BenchmarkBounds { - numBlocks = 25, /* how many kB to test (en/de)cryption */ - scryptCnt = 1, - ntimes = 1, - genTimes = 5, /* public key iterations */ - agreeTimes = 5 -}; -static const char blockType[] = "kB"; /* used in printf output */ -#else -enum BenchmarkBounds { - numBlocks = 50, /* how many megs to test (en/de)cryption */ - scryptCnt = 10, -#ifdef WOLFSSL_ASYNC_CRYPT - ntimes = 1000, - genTimes = 1000, - agreeTimes = 1000 +/* so embedded projects can pull in tests on their own */ +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args) #else - ntimes = 100, - genTimes = 100, - agreeTimes = 100 -#endif -}; -static const char blockType[] = "megs"; /* used in printf output */ +int benchmark_test(void *args) #endif - -#ifndef WC_NO_RNG -void bench_rng(void) { - int ret, i; - double start, total, persec; - int pos, len, remain; -#ifndef HAVE_LOCAL_RNG - WC_RNG rng; -#endif + int ret = 0; -#ifndef HAVE_LOCAL_RNG - ret = wc_InitRng(&rng); - if (ret < 0) { - printf("InitRNG failed\n"); - return; +#ifdef WOLFSSL_STATIC_MEMORY + ret = wc_LoadStaticMemory(&HEAP_HINT, gBenchMemory, sizeof(gBenchMemory), + WOLFMEM_GENERAL, 1); + if (ret != 0) { + printf("unable to load static memory %d\n", ret); + EXIT_TEST(EXIT_FAILURE); } -#endif +#endif /* WOLFSSL_STATIC_MEMORY */ - start = current_time(1); - BEGIN_INTEL_CYCLES + (void)args; - for(i = 0; i < numBlocks; i++) { - /* Split request to handle large RNG request */ - pos = 0; - remain = (int)sizeof(plain); - while (remain > 0) { - len = remain; - if (len > RNG_MAX_BLOCK_LEN) - len = RNG_MAX_BLOCK_LEN; - ret = wc_RNG_GenerateBlock(&rng, &plain[pos], len); - if (ret < 0) { - printf("wc_RNG_GenerateBlock failed %d\n", ret); - break; - } - remain -= len; - pos += len; - } - } + wolfCrypt_Init(); - END_INTEL_CYCLES - total = current_time(0) - start; + bench_stats_init(); - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); #endif - printf("RNG %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifndef HAVE_LOCAL_RNG - wc_FreeRng(&rng); -#endif -} -#endif /* WC_NO_RNG */ + printf("wolfCrypt Benchmark (min %.1f sec each)\n", BENCH_MIN_RUNTIME_SEC); +#ifdef HAVE_WNR + ret = wc_InitNetRandom(wnrConfigFile, NULL, 5000); + if (ret != 0) { + printf("Whitewood netRandom config init failed %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } +#endif /* HAVE_WNR */ -#ifndef NO_AES - -#ifdef HAVE_AES_CBC -void bench_aes(int show) + /* setup bench plain, cipher, key and iv globals */ +#ifdef WOLFSSL_ASYNC_CRYPT + bench_plain = (byte*)XMALLOC(BENCH_SIZE+BENCH_CIPHER_ADD, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_cipher = (byte*)XMALLOC(BENCH_SIZE+BENCH_CIPHER_ADD, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_key = (byte*)XMALLOC(sizeof(bench_key_buf), HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_iv = (byte*)XMALLOC(sizeof(bench_iv_buf), HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + if (bench_plain == NULL || bench_cipher == NULL || bench_key == NULL || bench_iv == NULL) { + printf("Benchmark cipher buffer alloc failed!\n"); + EXIT_TEST(EXIT_FAILURE); + } + XMEMCPY(bench_key, bench_key_buf, sizeof(bench_key_buf)); + XMEMCPY(bench_iv, bench_iv_buf, sizeof(bench_iv_buf)); + XMEMSET(bench_plain, 0, BENCH_SIZE+BENCH_CIPHER_ADD); + XMEMSET(bench_cipher, 0, BENCH_SIZE+BENCH_CIPHER_ADD); +#endif + (void)bench_plain; + (void)bench_cipher; + (void)bench_key; + (void)bench_iv; + + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) { - Aes enc; - double start, total, persec; - int i; - int ret; + int i; + int numCpus = wc_AsyncGetNumberOfCpus(); -#ifdef WOLFSSL_ASYNC_CRYPT - if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { - printf("wc_AesAsyncInit failed, ret = %d\n", ret); - return; - } -#endif + printf("CPUs: %d\n", numCpus); - ret = wc_AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("AesSetKey failed, ret = %d\n", ret); - return; + g_threadData = (ThreadData*)XMALLOC(sizeof(ThreadData) * numCpus, + HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (g_threadData == NULL) { + printf("Thread data alloc failed!\n"); + EXIT_TEST(EXIT_FAILURE); } - start = current_time(1); - BEGIN_INTEL_CYCLES + g_threadCount = numCpus; - for(i = 0; i < numBlocks; i++) - wc_AesCbcEncrypt(&enc, plain, cipher, sizeof(plain)); + /* Create threads */ + for (i = 0; i < numCpus; i++) { + ret = wc_AsyncThreadCreate(&g_threadData[i].thread_id, + benchmarks_do, &g_threadData[i]); + if (ret != 0) { + printf("Error creating benchmark thread %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } + } - END_INTEL_CYCLES - total = current_time(0) - start; + /* Start threads */ + for (i = 0; i < numCpus; i++) { + wc_AsyncThreadJoin(&g_threadData[i].thread_id); + } - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + XFREE(g_threadData, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +} +#else + benchmarks_do(NULL); #endif - if (show) { - printf("AES enc %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - } #ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); - if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { - printf("wc_AesAsyncInit failed, ret = %d\n", ret); - return; + XFREE(bench_plain, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_cipher, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_key, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_iv, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); +#endif + +#ifdef HAVE_WNR + ret = wc_FreeNetRandom(); + if (ret < 0) { + printf("Failed to free netRandom context %d\n", ret); + EXIT_TEST(EXIT_FAILURE); } #endif - ret = wc_AesSetKey(&enc, key, 16, iv, AES_DECRYPTION); - if (ret != 0) { - printf("AesSetKey failed, ret = %d\n", ret); - return; + bench_stats_free(); + + if (wolfCrypt_Cleanup() != 0) { + printf("error with wolfCrypt_Cleanup\n"); } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCbcDecrypt(&enc, plain, cipher, sizeof(plain)); + EXIT_TEST(ret); +} - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifndef WC_NO_RNG +void bench_rng(void) +{ + int ret, i, count; + double start; + int pos, len, remain; + WC_RNG myrng; + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&myrng); #endif + if (ret < 0) { + printf("InitRNG failed %d\n", ret); + return; + } - if (show) { - printf("AES dec %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + /* Split request to handle large RNG request */ + pos = 0; + remain = (int)BENCH_SIZE; + while (remain > 0) { + len = remain; + if (len > RNG_MAX_BLOCK_LEN) + len = RNG_MAX_BLOCK_LEN; + ret = wc_RNG_GenerateBlock(&myrng, &bench_plain[pos], len); + if (ret < 0) + goto exit_rng; + + remain -= len; + pos += len; + } + } + count += i; + } while (bench_stats_sym_check(start)); +exit_rng: + bench_stats_sym_finish("RNG", 0, count, start); + + if (ret < 0) { + printf("wc_RNG_GenerateBlock failed %d\n", ret); } -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); -#endif + + wc_FreeRng(&myrng); } -#endif /* HAVE_AES_CBC */ +#endif /* WC_NO_RNG */ -#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) - static byte additional[13]; - static byte tag[16]; -#endif +#ifndef NO_AES -#ifdef HAVE_AESGCM -void bench_aesgcm(void) +#ifdef HAVE_AES_CBC +void bench_aescbc(int doAsync) { - Aes enc; - double start, total, persec; - int i; + int ret, i, count = 0, times; + Aes enc[BENCH_MAX_PENDING]; + double start; - wc_AesGcmSetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) - wc_AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } - END_INTEL_CYCLES - total = current_time(0) - start; + ret = wc_AesSetKey(&enc[i], bench_key, 16, bench_iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } + } - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - printf("AES-GCM %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_AesCbcEncrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_aes_enc; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_enc: + bench_stats_sym_finish("AES-Enc", doAsync, count, start); -#if 0 - start = current_time(1); - BEGIN_INTEL_CYCLES + if (ret < 0) { + goto exit; + } - for(i = 0; i < numBlocks; i++) - wc_AesGcmDecrypt(&enc, plain, cipher, sizeof(cipher), iv, 12, - tag, 16, additional, 13); +#ifdef HAVE_AES_DECRYPT + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_AesSetKey(&enc[i], bench_key, 16, bench_iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } + } - END_INTEL_CYCLES - total = current_time(0) - start; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_AesCbcDecrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_aes_dec; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_dec: + bench_stats_sym_finish("AES-Dec", doAsync, count, start); - printf("AES-GCM Decrypt %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); +#endif /* HAVE_AES_DECRYPT */ + +exit: + + if (ret < 0) { + printf("bench_aescbc failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } + + bench_async_end(); +} +#endif /* HAVE_AES_CBC */ + +#ifdef HAVE_AESGCM +void bench_aesgcm(int doAsync) +{ + int ret, i, count = 0, times; + Aes enc[BENCH_MAX_PENDING]; + double start; + + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_additional) #endif + { XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); } +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_tag) +#endif + { XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); } + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesGcmSetKey(&enc[i], bench_key, 16); + if (ret != 0) { + printf("AesGcmSetKey failed, ret = %d\n", ret); + goto exit; + } + } + + /* GCM uses same routine in backend for both encrypt and decrypt */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_AesGcmEncrypt(&enc[i], bench_cipher, + bench_plain, BENCH_SIZE, + bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_aes_gcm; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_gcm: + bench_stats_sym_finish("AES-GCM", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_aesgcm failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } + + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); + + bench_async_end(); } #endif /* HAVE_AESGCM */ @@ -730,29 +1261,19 @@ void bench_aesgcm(void) void bench_aesctr(void) { Aes enc; - double start, total, persec; - int i; - - wc_AesSetKeyDirect(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); - start = current_time(1); - BEGIN_INTEL_CYCLES + double start; + int i, count; - for(i = 0; i < numBlocks; i++) - wc_AesCtrEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + wc_AesSetKeyDirect(&enc, bench_key, AES_BLOCK_SIZE, bench_iv, AES_ENCRYPTION); - printf("AES-CTR %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_AesCtrEncrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CTR", 0, count, start); } #endif /* WOLFSSL_AES_COUNTER */ @@ -761,34 +1282,30 @@ void bench_aesctr(void) void bench_aesccm(void) { Aes enc; - double start, total, persec; - int i; - int ret; + double start; + int ret, i, count; + + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); - if ((ret = wc_AesCcmSetKey(&enc, key, 16)) != 0) { + if ((ret = wc_AesCcmSetKey(&enc, bench_key, 16)) != 0) { printf("wc_AesCcmSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_AesCcmEncrypt(&enc, bench_cipher, bench_plain, BENCH_SIZE, + bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CCM", 0, count, start); - printf("AES-CCM %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); } #endif /* HAVE_AESCCM */ #endif /* !NO_AES */ @@ -797,38 +1314,30 @@ void bench_aesccm(void) #ifdef HAVE_POLY1305 void bench_poly1305() { - Poly1305 enc; - byte mac[16]; - double start, total, persec; - int i; - int ret; - + Poly1305 enc; + byte mac[16]; + double start; + int ret, i, count; - ret = wc_Poly1305SetKey(&enc, key, 32); + ret = wc_Poly1305SetKey(&enc, bench_key, 32); if (ret != 0) { printf("Poly1305SetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_Poly1305Update(&enc, plain, sizeof(plain)); - - wc_Poly1305Final(&enc, mac); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("POLY1305 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Poly1305Update(&enc, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Poly1305Update failed: %d\n", ret); + break; + } + } + wc_Poly1305Final(&enc, mac); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("POLY1305", 0, count, start); } #endif /* HAVE_POLY1305 */ @@ -837,178 +1346,197 @@ void bench_poly1305() void bench_camellia(void) { Camellia cam; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_CamelliaSetKey(&cam, key, 16, iv); + ret = wc_CamelliaSetKey(&cam, bench_key, 16, bench_iv); if (ret != 0) { printf("CamelliaSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_CamelliaCbcEncrypt(&cam, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - printf("Camellia %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_CamelliaCbcEncrypt(&cam, bench_plain, bench_cipher, + BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("Camellia", 0, count, start); } #endif #ifndef NO_DES3 -void bench_des(void) +void bench_des(int doAsync) { - Des3 enc; - double start, total, persec; - int i, ret; + int ret, i, count = 0, times; + Des3 enc[BENCH_MAX_PENDING]; + double start; -#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) { - printf("Des3_SetKey failed, ret = %d\n", ret); - return; + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_Des3Init(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("Des3Init failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_Des3_SetKey(&enc[i], bench_key, bench_iv, DES_ENCRYPTION); + if (ret != 0) { + printf("Des3_SetKey failed, ret = %d\n", ret); + goto exit; + } } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_Des3_CbcEncrypt(&enc, plain, cipher, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - END_INTEL_CYCLES - total = current_time(0) - start; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_Des3_CbcEncrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_3des; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_3des: + bench_stats_sym_finish("3DES", doAsync, count, start); - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif +exit: - printf("3DES %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Des3AsyncFree(&enc); -#endif + if (ret < 0) { + printf("bench_des failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Des3Free(&enc[i]); + } + + bench_async_end(); } -#endif +#endif /* !NO_DES3 */ #ifdef HAVE_IDEA void bench_idea(void) { Idea enc; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_IdeaSetKey(&enc, key, IDEA_KEY_SIZE, iv, IDEA_ENCRYPTION); + ret = wc_IdeaSetKey(&enc, bench_key, IDEA_KEY_SIZE, bench_iv, + IDEA_ENCRYPTION); if (ret != 0) { printf("Des3_SetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_IdeaCbcEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("IDEA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_IdeaCbcEncrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("IDEA", 0, count, start); } #endif /* HAVE_IDEA */ #ifndef NO_RC4 -void bench_arc4(void) +void bench_arc4(int doAsync) { - Arc4 enc; - double start, total, persec; - int i; + int ret, i, count = 0, times; + Arc4 enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Arc4AsyncInit(&enc, devId) != 0) - printf("arc4 async init failed\n"); -#endif + bench_async_begin(); - wc_Arc4SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_Arc4Init(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("Arc4Init failed, ret = %d\n", ret); + goto exit; + } - for(i = 0; i < numBlocks; i++) - wc_Arc4Process(&enc, cipher, plain, sizeof(plain)); + ret = wc_Arc4SetKey(&enc[i], bench_key, 16); + if (ret != 0) { + printf("Arc4SetKey failed, ret = %d\n", ret); + goto exit; + } + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - printf("ARC4 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Arc4AsyncFree(&enc); -#endif + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_Arc4Process(&enc[i], bench_cipher, bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_arc4; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_arc4: + bench_stats_sym_finish("ARC4", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_arc4 failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Arc4Free(&enc[i]); + } + + bench_async_end(); } -#endif +#endif /* !NO_RC4 */ #ifdef HAVE_HC128 void bench_hc128(void) { HC128 enc; - double start, total, persec; - int i; - - wc_Hc128_SetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + double start; + int i, count; - for(i = 0; i < numBlocks; i++) - wc_Hc128_Process(&enc, cipher, plain, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + wc_Hc128_SetKey(&enc, bench_key, bench_iv); - printf("HC128 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_Hc128_Process(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("HC128", 0, count, start); } #endif /* HAVE_HC128 */ @@ -1016,29 +1544,20 @@ void bench_hc128(void) #ifndef NO_RABBIT void bench_rabbit(void) { - Rabbit enc; - double start, total, persec; - int i; - - wc_RabbitSetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_RabbitProcess(&enc, cipher, plain, sizeof(plain)); + Rabbit enc; + double start; + int i, count; - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + wc_RabbitSetKey(&enc, bench_key, bench_iv); - printf("RABBIT %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_RabbitProcess(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("RABBIT", 0, count, start); } #endif /* NO_RABBIT */ @@ -1047,347 +1566,534 @@ void bench_rabbit(void) void bench_chacha(void) { ChaCha enc; - double start, total, persec; - int i; - - wc_Chacha_SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES - - for (i = 0; i < numBlocks; i++) { - wc_Chacha_SetIV(&enc, iv, 0); - wc_Chacha_Process(&enc, cipher, plain, sizeof(plain)); - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + double start; + int i, count; - printf("CHACHA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + wc_Chacha_SetKey(&enc, bench_key, 16); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_Chacha_SetIV(&enc, bench_iv, 0); + wc_Chacha_Process(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("CHACHA", 0, count, start); } #endif /* HAVE_CHACHA*/ -#if( defined( HAVE_CHACHA ) && defined( HAVE_POLY1305 ) ) +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) void bench_chacha20_poly1305_aead(void) { - double start, total, persec; - int i; + double start; + int ret, i, count; byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; - XMEMSET( authTag, 0, sizeof( authTag ) ); - - start = current_time(1); - BEGIN_INTEL_CYCLES - - for (i = 0; i < numBlocks; i++) - { - wc_ChaCha20Poly1305_Encrypt(key, iv, NULL, 0, plain, sizeof(plain), - cipher, authTag ); - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("CHA-POLY %d %s took %5.3f seconds, %8.3f MB/s", - numBlocks, blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + XMEMSET(authTag, 0, sizeof(authTag)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_ChaCha20Poly1305_Encrypt(bench_key, bench_iv, NULL, 0, + bench_plain, BENCH_SIZE, bench_cipher, authTag); + if (ret < 0) { + printf("wc_ChaCha20Poly1305_Encrypt error: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("CHA-POLY", 0, count, start); } #endif /* HAVE_CHACHA && HAVE_POLY1305 */ #ifndef NO_MD5 -void bench_md5(void) +void bench_md5(int doAsync) { - Md5 hash; - byte digest[MD5_DIGEST_SIZE]; - double start, total, persec; - int i; + Md5 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, MD5_DIGEST_SIZE, HEAP_HINT); - wc_InitMd5(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) - wc_Md5Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - wc_Md5Final(&hash, digest); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitMd5_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitMd5_ex failed, ret = %d\n", ret); + goto exit; + } + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Md5Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_md5; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Md5Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_md5; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_md5: + bench_stats_sym_finish("MD5", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_md5 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Md5Free(&hash[i]); + } #endif - printf("MD5 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } -#endif /* NO_MD5 */ +#endif /* !NO_MD5 */ #ifndef NO_SHA -void bench_sha(void) +void bench_sha(int doAsync) { - Sha hash; - byte digest[SHA_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha(&hash); - if (ret != 0) { - printf("InitSha failed, ret = %d\n", ret); - return; + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha failed, ret = %d\n", ret); + goto exit; + } } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_ShaUpdate(&hash, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_ShaUpdate(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_ShaFinal(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha: + bench_stats_sym_finish("SHA", doAsync, count, start); + +exit: - wc_ShaFinal(&hash, digest); + if (ret < 0) { + printf("bench_sha failed: %d\n", ret); + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ShaFree(&hash[i]); + } #endif - printf("SHA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif /* NO_SHA */ #ifdef WOLFSSL_SHA224 -void bench_sha224(void) +void bench_sha224(int doAsync) { - Sha224 hash; - byte digest[SHA224_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha224 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA224_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha224(&hash); - if (ret != 0) { - printf("InitSha224 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha224Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha224_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha224Update failed, ret = %d\n", ret); - return; + printf("InitSha224_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha224Final(&hash, digest); - if (ret != 0) { - printf("Sha224Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha224Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha224; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha224Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha224; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha224: + bench_stats_sym_finish("SHA-224", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha224 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha224Free(&hash[i]); + } #endif - printf("SHA-224 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifndef NO_SHA256 -void bench_sha256(void) +void bench_sha256(int doAsync) { - Sha256 hash; - byte digest[SHA256_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha256 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA256_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha256(&hash); - if (ret != 0) { - printf("InitSha256 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha256Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha256_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha256Update failed, ret = %d\n", ret); - return; + printf("InitSha256_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha256Final(&hash, digest); - if (ret != 0) { - printf("Sha256Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha256Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha256; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha256Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha256; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha256: + bench_stats_sym_finish("SHA-256", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha256 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha256Free(&hash[i]); + } #endif - printf("SHA-256 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifdef WOLFSSL_SHA384 -void bench_sha384(void) +void bench_sha384(int doAsync) { - Sha384 hash; - byte digest[SHA384_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha384 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA384_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha384(&hash); - if (ret != 0) { - printf("InitSha384 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha384Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha384_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha384Update failed, ret = %d\n", ret); - return; + printf("InitSha384_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha384Final(&hash, digest); - if (ret != 0) { - printf("Sha384Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha384Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha384; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha384Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha384; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha384: + bench_stats_sym_finish("SHA-384", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha384 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha384Free(&hash[i]); + } #endif - printf("SHA-384 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifdef WOLFSSL_SHA512 -void bench_sha512(void) +void bench_sha512(int doAsync) { - Sha512 hash; - byte digest[SHA512_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha512 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA512_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha512(&hash); - if (ret != 0) { - printf("InitSha512 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha512Update(&hash, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha512_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha512Update failed, ret = %d\n", ret); - return; + printf("InitSha512_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha512Final(&hash, digest); - if (ret != 0) { - printf("Sha512Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha512Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha512; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha512Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha512; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha512: + bench_stats_sym_finish("SHA-512", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha512 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha512Free(&hash[i]); + } #endif - printf("SHA-512 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifdef WOLFSSL_RIPEMD -void bench_ripemd(void) +int bench_ripemd(void) { RipeMd hash; byte digest[RIPEMD_DIGEST_SIZE]; - double start, total, persec; - int i; - - wc_InitRipeMd(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES + double start; + int i, count, ret; - for(i = 0; i < numBlocks; i++) - wc_RipeMdUpdate(&hash, plain, sizeof(plain)); + ret = wc_InitRipeMd(&hash); + if (ret != 0) { + return ret; + } - wc_RipeMdFinal(&hash, digest); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_RipeMdUpdate(&hash, bench_plain, BENCH_SIZE); + if (ret != 0) { + return ret; + } + } + ret = wc_RipeMdFinal(&hash, digest); + if (ret != 0) { + return ret; + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("RIPEMD", 0, count, start); - printf("RIPEMD %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + return 0; } #endif @@ -1397,43 +2103,32 @@ void bench_blake2(void) { Blake2b b2b; byte digest[64]; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) { printf("InitBlake2b failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) { - ret = wc_Blake2bUpdate(&b2b, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Blake2bUpdate(&b2b, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Blake2bUpdate failed, ret = %d\n", ret); + return; + } + } + ret = wc_Blake2bFinal(&b2b, digest, 64); if (ret != 0) { - printf("Blake2bUpdate failed, ret = %d\n", ret); + printf("Blake2bFinal failed, ret = %d\n", ret); return; } - } - - ret = wc_Blake2bFinal(&b2b, digest, 64); - if (ret != 0) { - printf("Blake2bFinal failed, ret = %d\n", ret); - return; - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("BLAKE2b %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("BLAKE2b", 0, count, start); } #endif @@ -1445,43 +2140,33 @@ void bench_cmac(void) Cmac cmac; byte digest[AES_BLOCK_SIZE]; word32 digestSz = sizeof(digest); - double start, total, persec; - int i, ret; - - ret = wc_InitCmac(&cmac, key, 16, WC_CMAC_AES, NULL); - if (ret != 0) { - printf("InitCmac failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + double start; + int ret, i, count; - for(i = 0; i < numBlocks; i++) { - ret = wc_CmacUpdate(&cmac, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + ret = wc_InitCmac(&cmac, bench_key, 16, WC_CMAC_AES, NULL); if (ret != 0) { - printf("CmacUpdate failed, ret = %d\n", ret); + printf("InitCmac failed, ret = %d\n", ret); return; } - } - - ret = wc_CmacFinal(&cmac, digest, &digestSz); - if (ret != 0) { - printf("CmacFinal failed, ret = %d\n", ret); - return; - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - printf("AES-CMAC %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + for (i = 0; i < numBlocks; i++) { + ret = wc_CmacUpdate(&cmac, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("CmacUpdate failed, ret = %d\n", ret); + return; + } + } + /* Note: final force zero's the Cmac struct */ + ret = wc_CmacFinal(&cmac, digest, &digestSz); + if (ret != 0) { + printf("CmacFinal failed, ret = %d\n", ret); + return; + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CMAC", 0, count, start); } #endif /* WOLFSSL_CMAC */ @@ -1491,30 +2176,89 @@ void bench_cmac(void) void bench_scrypt(void) { byte derived[64]; - double start, total, each, milliEach; - int ret, i; - - start = current_time(1); - for (i = 0; i < scryptCnt; i++) { - ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, - (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(derived)); - if (ret != 0) { - printf("scrypt failed, ret = %d\n", ret); - return; + double start; + int ret, i, count; + + bench_stats_start(&count, &start); + do { + for (i = 0; i < scryptCnt; i++) { + ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, + (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(derived)); + if (ret != 0) { + printf("scrypt failed, ret = %d\n", ret); + goto exit; + } } - } - total = current_time(0) - start; - each = total / scryptCnt; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("scrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, scryptCnt); + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("scrypt", 0, "", 0, count, start); } #endif /* HAVE_SCRYPT */ #ifndef NO_RSA +#if defined(WOLFSSL_KEY_GEN) +void bench_rsaKeyGen(int doAsync) +{ + RsaKey genKey[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + int k, keySz; + const int keySizes[2] = {1024, 2048}; + const long rsa_e_val = 65537; + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(genKey, 0, sizeof(genKey)); + + for (k = 0; k < (int)(sizeof(keySizes)/sizeof(int)); k++) { + keySz = keySizes[k]; + + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, genTimes)) { + + wc_FreeRsaKey(&genKey[i]); + ret = wc_InitRsaKey_ex(&genKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret < 0) { + goto exit; + } + + ret = wc_MakeRsaKey(&genKey[i], keySz, rsa_e_val, &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); + exit: + bench_stats_asym_finish("RSA", keySz, "key gen", doAsync, count, start); + + if (ret < 0) { + printf("bench_rsaKeyGen failed: %d\n", ret); + break; + } + } + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeRsaKey(&genKey[i]); + } + + bench_async_end(); +} +#endif /* WOLFSSL_KEY_GEN */ #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #if defined(WOLFSSL_MDK_SHELL) @@ -1528,111 +2272,23 @@ void bench_scrypt(void) #endif #endif -void bench_rsa(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; - int rsaKeySz = 2048; /* used in printf */ - -#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 */ - - if ((ret = wc_InitRsaKey(&rsaKey, HEAP_HINT)) < 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); - if (ret < 0) { - break; - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d public %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - if (ret < 0) { - printf("Rsa Public Encrypt failed! %d\n", ret); - return; - } - -#ifdef WC_RSA_BLINDING - 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 */ - - 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 private %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); +#define RSA_BUF_SIZE 256 /* for up to 2048 bit */ - wc_FreeRsaKey(&rsaKey); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT -void bench_rsa_async(void) +void bench_rsa(int doAsync) { - int i; - int ret; - size_t bytes; - word32 idx = 0; + int ret, i, times, count = 0; + size_t bytes; + word32 idx = 0; const byte* tmp; + const char* messageStr = "Everyone gets Friday off."; + const int len = (int)XSTRLEN((char*)messageStr); + double start = 0.0f; + RsaKey rsaKey[BENCH_MAX_PENDING]; + int rsaKeySz = RSA_BUF_SIZE * 8; /* used in printf */ - 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; + DECLARE_VAR_INIT(message, byte, len, messageStr, HEAP_HINT); + DECLARE_ARRAY(enc, byte, BENCH_MAX_PENDING, RSA_BUF_SIZE, HEAP_HINT); + DECLARE_ARRAY(out, byte, BENCH_MAX_PENDING, RSA_BUF_SIZE, HEAP_HINT); #ifdef USE_CERT_BUFFERS_1024 tmp = rsa_key_der_1024; @@ -1645,181 +2301,114 @@ void bench_rsa_async(void) #error "need a cert buffer size" #endif /* USE_CERT_BUFFERS */ - /* init event queue */ - ret = wolfEventQueue_Init(&eventQueue); - if (ret != 0) { - return; - } + bench_async_begin(); /* 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], HEAP_HINT, 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 */ + XMEMSET(rsaKey, 0, sizeof(rsaKey)); - /* 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); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an async context for each key */ + if ((ret = wc_InitRsaKey_ex(&rsaKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit; } - } /* for ntimes */ - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&rsaKey[i], &rng); + if (ret != 0) + goto exit; + #endif + + /* 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 exit; + } + } - printf("RSA %d public async %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); + /* begin public RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes)) { + ret = wc_RsaPublicEncrypt(message, len, enc[i], + RSA_BUF_SIZE, &rsaKey[i], &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×)) { + goto exit_rsa_pub; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_pub: + bench_stats_asym_finish("RSA", rsaKeySz, "public", doAsync, count, start); if (ret < 0) { - goto done; + goto exit; } - - /* begin private async RSA */ - start = current_time(1); +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&rsaKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif /* 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; - } + idx = RSA_BUF_SIZE; /* fixed at 2048 bit */ - 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; + /* begin private async RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes)) { + ret = wc_RsaPrivateDecrypt(enc[i], idx, out[i], + RSA_BUF_SIZE, &rsaKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×)) { + goto exit; + } } - } - } /* 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: + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("RSA", rsaKeySz, "private", doAsync, count, start); if (ret < 0) { - printf("bench_rsa_async failed: %d\n", ret); + printf("bench_rsa failed: %d\n", ret); } /* cleanup */ - for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + for (i = 0; i < BENCH_MAX_PENDING; i++) { wc_FreeRsaKey(&rsaKey[i]); } - /* free event queue */ - wolfEventQueue_Free(&eventQueue); + FREE_ARRAY(enc, BENCH_MAX_PENDING, HEAP_HINT); + FREE_ARRAY(out, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(message, HEAP_HINT); + + bench_async_end(); } -#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* !NO_RSA */ #ifndef NO_DH - #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #if defined(WOLFSSL_MDK_SHELL) static char *certDHname = "certs/dh2048.der"; @@ -1834,26 +2423,34 @@ void bench_rsa_async(void) #endif #endif -void bench_dh(void) +#define BENCH_DH_KEY_SIZE 256 /* for 2048 bit */ +#define BENCH_DH_PRIV_SIZE (BENCH_DH_KEY_SIZE/8) + +void bench_dh(int doAsync) { - int i ; - size_t bytes; - word32 idx = 0, pubSz, privSz = 0, pubSz2, privSz2, agreeSz; + int ret, i; + int count = 0, times; const byte* tmp = NULL; - - byte pub[256]; /* for 2048 bit */ - byte pub2[256]; /* for 2048 bit */ - byte agree[256]; /* for 2048 bit */ - byte priv[32]; /* for 2048 bit */ - byte priv2[32]; /* for 2048 bit */ - - double start, total, each, milliEach; - DhKey dhKey; + double start = 0.0f; + DhKey dhKey[BENCH_MAX_PENDING]; int dhKeySz = 2048; /* used in printf */ +#ifndef NO_ASN + size_t bytes; + word32 idx; +#endif + word32 pubSz[BENCH_MAX_PENDING]; + word32 privSz[BENCH_MAX_PENDING]; + word32 pubSz2; + word32 privSz2; + word32 agreeSz[BENCH_MAX_PENDING]; - (void)idx; - (void)tmp; + DECLARE_ARRAY(pub, byte, BENCH_MAX_PENDING, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_VAR(pub2, byte, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_ARRAY(agree, byte, BENCH_MAX_PENDING, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_ARRAY(priv, byte, BENCH_MAX_PENDING, BENCH_DH_PRIV_SIZE, HEAP_HINT); + DECLARE_VAR(priv2, byte, BENCH_DH_PRIV_SIZE, HEAP_HINT); + (void)tmp; #if defined(NO_ASN) dhKeySz = 1024; @@ -1869,86 +2466,112 @@ void bench_dh(void) #error "need to define a cert buffer size" #endif /* USE_CERT_BUFFERS */ + bench_async_begin(); - wc_InitDhKey(&dhKey); -#ifdef NO_ASN - bytes = wc_DhSetKey(&dhKey, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); -#else - bytes = wc_DhKeyDecode(tmp, &idx, &dhKey, (word32)bytes); -#endif - if (bytes != 0) { - printf("dhekydecode failed, can't benchmark\n"); - return; - } - - start = current_time(1); - - for (i = 0; i < ntimes; i++) - wc_DhGenerateKeyPair(&dhKey, &rng, priv, &privSz, pub, &pubSz); - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("DH %d key generation %6.3f milliseconds, avg over %d" - " iterations\n", dhKeySz, milliEach, ntimes); + /* clear for done cleanup */ + XMEMSET(dhKey, 0, sizeof(dhKey)); - wc_DhGenerateKeyPair(&dhKey, &rng, priv2, &privSz2, pub2, &pubSz2); - start = current_time(1); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an async context for each key */ + ret = wc_InitDhKey_ex(&dhKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) + goto exit; + + /* setup key */ + #ifdef NO_ASN + ret = wc_DhSetKey(&dhKey[i], dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); + #else + idx = 0; + ret = wc_DhKeyDecode(tmp, &idx, &dhKey[i], (word32)bytes); + #endif + if (ret != 0) { + printf("DhKeyDecode failed %d, can't benchmark\n", ret); + goto exit; + } + } - for (i = 0; i < ntimes; i++) - wc_DhAgree(&dhKey, agree, &agreeSz, priv, privSz, pub2, pubSz2); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, genTimes)) { + privSz[i] = 0; + ret = wc_DhGenerateKeyPair(&dhKey[i], &rng, priv[i], &privSz[i], + pub[i], &pubSz[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×)) { + goto exit_dh_gen; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_dh_gen: + bench_stats_asym_finish("DH", dhKeySz, "key gen", doAsync, count, start); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ + if (ret < 0) { + goto exit; + } - printf("DH %d key agreement %6.3f milliseconds, avg over %d" - " iterations\n", dhKeySz, milliEach, ntimes); + /* Generate key to use as other public */ + ret = wc_DhGenerateKeyPair(&dhKey[0], &rng, priv2, &privSz2, pub2, &pubSz2); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &dhKey[0].asyncDev, WC_ASYNC_FLAG_NONE); - wc_FreeDhKey(&dhKey); -} + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&dhKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; #endif -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) -void bench_rsaKeyGen(void) -{ - RsaKey genKey; - double start, total, each, milliEach; - int i; + /* Key Agree */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - /* 1024 bit */ - start = current_time(1); + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, agreeTimes)) { + ret = wc_DhAgree(&dhKey[i], agree[i], &agreeSz[i], priv[i], privSz[i], + pub2, pubSz2); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("DH", dhKeySz, "key agree", doAsync, count, start); - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, HEAP_HINT); - wc_MakeRsaKey(&genKey, 1024, 65537, &rng); - wc_FreeRsaKey(&genKey); + if (ret < 0) { + printf("bench_dh failed: %d\n", ret); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("RSA 1024 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); - - /* 2048 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, HEAP_HINT); - wc_MakeRsaKey(&genKey, 2048, 65537, &rng); - wc_FreeRsaKey(&genKey); + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeDhKey(&dhKey[i]); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("RSA 2048 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + FREE_ARRAY(pub, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(pub2, HEAP_HINT); + FREE_ARRAY(priv, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(priv2, HEAP_HINT); + FREE_ARRAY(agree, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } -#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_DH */ + #ifdef HAVE_NTRU byte GetEntropy(ENTROPY_CMD cmd, byte* out); @@ -1974,7 +2597,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) void bench_ntru(void) { int i; - double start, total, each, milliEach; + double start; byte public_key[1027]; word16 public_key_len = sizeof(public_key); @@ -1999,7 +2622,6 @@ void bench_ntru(void) 'w', 'o', 'l', 'f', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U' }; - printf("\n"); for (ntruBits = 128; ntruBits < 257; ntruBits += 64) { switch (ntruBits) { case 128: @@ -2054,8 +2676,8 @@ void bench_ntru(void) printf("NTRU error occurred requesting the buffer size needed\n"); return; } - start = current_time(1); + bench_stats_start(&i, &start); for (i = 0; i < ntimes; i++) { ret = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key, sizeof(aes_key), aes_key, &ciphertext_len, ciphertext); @@ -2064,21 +2686,14 @@ void bench_ntru(void) return; } } - ret = ntru_crypto_drbg_uninstantiate(drbg); + bench_stats_asym_finish("NTRU", ntruBits, "encryption", 0, i, start); + ret = ntru_crypto_drbg_uninstantiate(drbg); if (ret != DRBG_OK) { printf("NTRU error occurred uninstantiating the DRBG\n"); return; } - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU %d encryption took %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, ntimes); - - ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, &plaintext_len, NULL); @@ -2088,8 +2703,8 @@ void bench_ntru(void) } plaintext_len = sizeof(plaintext); - start = current_time(1); + bench_stats_start(&i, &start); for (i = 0; i < ntimes; i++) { ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, @@ -2100,20 +2715,14 @@ void bench_ntru(void) return; } } - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU %d decryption took %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, ntimes); + bench_stats_asym_finish("NTRU", ntruBits, "decryption", 0, i, start); } } void bench_ntruKeyGen(void) { - double start, total, each, milliEach; + double start; int i; byte public_key[1027]; @@ -2152,15 +2761,14 @@ void bench_ntruKeyGen(void) /* set key sizes */ ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, NULL, &private_key_len, NULL); - start = current_time(1); - for(i = 0; i < genTimes; i++) { + bench_stats_start(&i, &start); + for (i = 0; i < genTimes; i++) { ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, public_key, &private_key_len, private_key); } - - total = current_time(0) - start; + bench_stats_asym_finish("NTRU", ntruBits, "key gen", 0, i, start); if (ret != NTRU_OK) { printf("keygen failed\n"); @@ -2173,183 +2781,333 @@ void bench_ntruKeyGen(void) printf("NTRU drbg uninstantiate failed\n"); return; } - - each = total / genTimes; - milliEach = each * 1000; - - printf("NTRU %d key generation %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, genTimes); } } #endif #ifdef HAVE_ECC -void bench_eccKeyGen(void) +#define BENCH_ECC_SIZE 32 + +void bench_eccMakeKey(int doAsync) { - ecc_key genKey; - double start, total, each, milliEach; - int i; + int ret, i, times, count; + const int keySize = BENCH_ECC_SIZE; + ecc_key genKey[BENCH_MAX_PENDING]; + double start; - /* 256 bit */ - start = current_time(1); + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(genKey)); + + /* ECC Make Key */ + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, genTimes)) { + + wc_ecc_free(&genKey[i]); + ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, doAsync ? devId : INVALID_DEVID); + if (ret < 0) { + goto exit; + } + + ret = wc_ecc_make_key(&rng, keySize, &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("ECC", keySize * 8, "key gen", doAsync, count, start); - for(i = 0; i < genTimes; i++) { - wc_ecc_init_ex(&genKey, HEAP_HINT, devId); - wc_ecc_make_key(&rng, 32, &genKey); - wc_ecc_free(&genKey); + if (ret < 0) { + printf("bench_eccMakeKey failed: %d\n", ret); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("ECC 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); -} + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ecc_free(&genKey[i]); + } + bench_async_end(); +} -void bench_eccKeyAgree(void) +void bench_ecc(int doAsync) { - ecc_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; - byte shared[32]; -#if !defined(NO_ASN) && !defined(NO_ECC_SIGN) - byte sig[64+16]; /* der encoding too */ + int ret, i, times, count; + const int keySize = BENCH_ECC_SIZE; + ecc_key genKey[BENCH_MAX_PENDING]; +#ifdef HAVE_ECC_DHE + ecc_key genKey2[BENCH_MAX_PENDING]; #endif - byte digest[32]; - word32 x = 0; +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) +#ifdef HAVE_ECC_VERIFY + int verify[BENCH_MAX_PENDING]; +#endif +#endif + word32 x[BENCH_MAX_PENDING]; + double start; - wc_ecc_init_ex(&genKey, HEAP_HINT, devId); - wc_ecc_init_ex(&genKey2, HEAP_HINT, devId); +#ifdef HAVE_ECC_DHE + DECLARE_ARRAY(shared, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + DECLARE_ARRAY(sig, byte, BENCH_MAX_PENDING, ECC_MAX_SIG_SIZE, HEAP_HINT); +#endif + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); - ret = wc_ecc_make_key(&rng, 32, &genKey); - if (ret != 0) { - printf("ecc_make_key failed\n"); - return; - } - ret = wc_ecc_make_key(&rng, 32, &genKey2); - if (ret != 0) { - printf("ecc_make_key failed\n"); - return; - } + bench_async_begin(); - /* 256 bit */ - start = current_time(1); + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(genKey)); +#ifdef HAVE_ECC_DHE + XMEMSET(&genKey2, 0, sizeof(genKey2)); +#endif - for(i = 0; i < agreeTimes; i++) { - x = sizeof(shared); - ret = wc_ecc_shared_secret(&genKey, &genKey2, shared, &x); - if (ret != 0) { - printf("ecc_shared_secret failed\n"); - return; + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an context for each key */ + if ((ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit; + } + ret = wc_ecc_make_key(&rng, keySize, &genKey[i]); + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &genKey[i].asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret < 0) { + goto exit; } - } - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DHE key agreement %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + #ifdef HAVE_ECC_DHE + if ((ret = wc_ecc_init_ex(&genKey2[i], HEAP_HINT, INVALID_DEVID)) < 0) { + goto exit; + } + if ((ret = wc_ecc_make_key(&rng, keySize, &genKey2[i])) > 0) { + goto exit; + } + #endif + } - /* make dummy digest */ - for (i = 0; i < (int)sizeof(digest); i++) - digest[i] = (byte)i; +#ifdef HAVE_ECC_DHE +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&genKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif + + /* ECC Shared Secret */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes)) { + x[i] = keySize; + ret = wc_ecc_shared_secret(&genKey[i], &genKey2[i], shared[i], &x[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×)) { + goto exit_ecdhe; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdhe: + bench_stats_asym_finish("ECDHE", keySize * 8, "agree", doAsync, count, start); + if (ret < 0) { + goto exit; + } +#endif /* HAVE_ECC_DHE */ -#if !defined(NO_ASN) && !defined(NO_ECC_SIGN) - start = current_time(1); +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&genKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif - for(i = 0; i < agreeTimes; i++) { - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, &rng, &genKey); - if (ret != 0) { - printf("ecc_sign_hash failed\n"); - return; + /* Init digest to sign */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + for (count = 0; count < keySize; count++) { + digest[i][count] = (byte)count; } } - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DSA sign time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + /* ECC Sign */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes)) { + if (genKey[i].state == 0) + x[i] = ECC_MAX_SIG_SIZE; + ret = wc_ecc_sign_hash(digest[i], keySize, sig[i], &x[i], + &rng, &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×)) { + goto exit_ecdsa_sign; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdsa_sign: + bench_stats_asym_finish("ECDSA", keySize * 8, "sign", doAsync, count, start); - start = current_time(1); + if (ret < 0) { + goto exit; + } - for(i = 0; i < agreeTimes; i++) { - int verify = 0; - ret = wc_ecc_verify_hash(sig, x, digest, sizeof(digest), &verify, &genKey); - if (ret != 0) { - printf("ecc_verify_hash failed\n"); - return; - } +#ifdef HAVE_ECC_VERIFY +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&genKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif + + /* ECC Verify */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes)) { + if (genKey[i].state == 0) + verify[i] = 0; + ret = wc_ecc_verify_hash(sig[i], x[i], digest[i], + keySize, &verify[i], &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×)) { + goto exit_ecdsa_verify; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdsa_verify: + bench_stats_asym_finish("ECDSA", keySize * 8, "verify", doAsync, count, start); +#endif /* HAVE_ECC_VERIFY */ +#endif /* !NO_ASN && HAVE_ECC_SIGN */ + +exit: + + if (ret < 0) { + printf("bench_ecc failed: %d\n", ret); } -#endif - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DSA verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ecc_free(&genKey[i]); + #ifdef HAVE_ECC_DHE + wc_ecc_free(&genKey2[i]); + #endif + } + +#ifdef HAVE_ECC_DHE + FREE_ARRAY(shared, BENCH_MAX_PENDING, HEAP_HINT); +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + FREE_ARRAY(sig, BENCH_MAX_PENDING, HEAP_HINT); +#endif + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); - wc_ecc_free(&genKey2); - wc_ecc_free(&genKey); + bench_async_end(); } + + #ifdef HAVE_ECC_ENCRYPT void bench_eccEncrypt(void) { ecc_key userA, userB; + const int keySize = BENCH_ECC_SIZE; byte msg[48]; byte out[80]; word32 outSz = sizeof(out); - word32 plainSz = sizeof(plain); - int ret, i; - double start, total, each, milliEach; + word32 bench_plainSz = BENCH_SIZE; + int ret, i, count; + double start; - wc_ecc_init_ex(&userA, HEAP_HINT, devId); + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key A failed: %d\n", ret); + return; + } wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key B failed: %d\n", ret); + wc_ecc_free(&userA); + return; + } - wc_ecc_make_key(&rng, 32, &userA); - wc_ecc_make_key(&rng, 32, &userB); + ret = wc_ecc_make_key(&rng, keySize, &userA); + if (ret != 0) + goto exit; + ret = wc_ecc_make_key(&rng, keySize, &userB); + if (ret != 0) + goto exit; for (i = 0; i < (int)sizeof(msg); i++) msg[i] = i; - start = current_time(1); - - for(i = 0; i < ntimes; i++) { - /* encrypt msg to B */ - ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); - if (ret != 0) { - printf("wc_ecc_encrypt failed! %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < ntimes; i++) { + /* encrypt msg to B */ + ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); + if (ret != 0) { + printf("wc_ecc_encrypt failed! %d\n", ret); + goto exit_enc; + } } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_enc: + bench_stats_asym_finish("ECC", keySize * 8, "encrypt", 0, count, start); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ECC encrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); + bench_stats_start(&count, &start); + do { + for (i = 0; i < ntimes; i++) { + /* decrypt msg from A */ + ret = wc_ecc_decrypt(&userB, &userA, out, outSz, bench_plain, &bench_plainSz, NULL); + if (ret != 0) { + printf("wc_ecc_decrypt failed! %d\n", ret); + goto exit_dec; + } + } + count += i; + } while (bench_stats_sym_check(start)); +exit_dec: + bench_stats_asym_finish("ECC", keySize * 8, "decrypt", 0, count, start); - start = current_time(1); +exit: - for(i = 0; i < ntimes; i++) { - /* decrypt msg from A */ - ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); - if (ret != 0) { - printf("wc_ecc_decrypt failed! %d\n", ret); - return; - } + if (ret != 0) { + printf("bench_eccEncrypt failed! %d\n", ret); } - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ECC decrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); - /* cleanup */ wc_ecc_free(&userB); wc_ecc_free(&userA); @@ -2361,31 +3119,31 @@ void bench_eccEncrypt(void) void bench_curve25519KeyGen(void) { curve25519_key genKey; - double start, total, each, milliEach; - int i; - - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_curve25519_make_key(&rng, 32, &genKey); - wc_curve25519_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("CURVE25519 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + double start; + int ret, i, count; + + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_curve25519_make_key(&rng, 32, &genKey); + wc_curve25519_free(&genKey); + if (ret != 0) { + printf("wc_curve25519_make_key failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("CURVE", 25519, "key gen", 0, count, start); } #ifdef HAVE_CURVE25519_SHARED_SECRET void bench_curve25519KeyAgree(void) { curve25519_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; + double start; + int ret, i, count; byte shared[32]; word32 x = 0; @@ -2399,27 +3157,26 @@ void bench_curve25519KeyAgree(void) } ret = wc_curve25519_make_key(&rng, 32, &genKey2); if (ret != 0) { - printf("curve25519_make_key failed\n"); + printf("curve25519_make_key failed: %d\n", ret); + wc_curve25519_free(&genKey); return; } - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(shared); - ret = wc_curve25519_shared_secret(&genKey, &genKey2, shared, &x); - if (ret != 0) { - printf("curve25519_shared_secret failed\n"); - return; + /* Shared secret */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(shared); + ret = wc_curve25519_shared_secret(&genKey, &genKey2, shared, &x); + if (ret != 0) { + printf("curve25519_shared_secret failed: %d\n", ret); + goto exit; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("CURVE25519 key agreement %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("CURVE", 25519, "key agree", 0, count, start); wc_curve25519_free(&genKey2); wc_curve25519_free(&genKey); @@ -2431,24 +3188,20 @@ void bench_curve25519KeyAgree(void) void bench_ed25519KeyGen(void) { ed25519_key genKey; - double start, total, each, milliEach; - int i; - - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_ed25519_init(&genKey); - wc_ed25519_make_key(&rng, 32, &genKey); - wc_ed25519_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("ED25519 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + double start; + int i, count; + + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + wc_ed25519_init(&genKey); + wc_ed25519_make_key(&rng, 32, &genKey); + wc_ed25519_free(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ED", 25519, "key gen", 0, count, start); } @@ -2457,8 +3210,8 @@ void bench_ed25519KeySign(void) int ret; ed25519_key genKey; #ifdef HAVE_ED25519_SIGN - double start, total, each, milliEach; - int i; + double start; + int i, count; byte sig[ED25519_SIG_SIZE]; byte msg[512]; word32 x = 0; @@ -2477,41 +3230,37 @@ void bench_ed25519KeySign(void) for (i = 0; i < (int)sizeof(msg); i++) msg[i] = (byte)i; - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(sig); - ret = wc_ed25519_sign_msg(msg, sizeof(msg), sig, &x, &genKey); - if (ret != 0) { - printf("ed25519_sign_msg failed\n"); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(sig); + ret = wc_ed25519_sign_msg(msg, sizeof(msg), sig, &x, &genKey); + if (ret != 0) { + printf("ed25519_sign_msg failed\n"); + goto exit_ed_sign; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ED25519 sign time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_sign: + bench_stats_asym_finish("ED", 25519, "sign", 0, count, start); #ifdef HAVE_ED25519_VERIFY - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - int verify = 0; - ret = wc_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, - &genKey); - if (ret != 0 || verify != 1) { - printf("ed25519_verify_msg failed\n"); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + int verify = 0; + ret = wc_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, + &genKey); + if (ret != 0 || verify != 1) { + printf("ed25519_verify_msg failed\n"); + goto exit_ed_verify; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ED25519 verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_verify: + bench_stats_asym_finish("ED", 25519, "verify", 0, count, start); #endif /* HAVE_ED25519_VERIFY */ #endif /* HAVE_ED25519_SIGN */ @@ -2519,8 +3268,8 @@ void bench_ed25519KeySign(void) } #endif /* HAVE_ED25519 */ - -#ifdef _WIN32 +#ifndef HAVE_STACK_SIZE +#if defined(_WIN32) && !defined(INTIME_RTOS) #define WIN32_LEAN_AND_MEAN #include @@ -2567,8 +3316,9 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_CURRTIME) - /* declared above at line 189 */ +#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_USER_CURRTIME) || defined(WOLFSSL_CURRTIME_REMAP) + /* declared above at line 239 */ /* extern double current_time(int reset); */ #elif defined FREERTOS @@ -2598,6 +3348,13 @@ void bench_ed25519KeySign(void) return (double)tv.SECONDS + (double)tv.MILLISECONDS / 1000; } +#elif defined(FREESCALE_KSDK_BM) + + double current_time(int reset) + { + return (double)OSA_TimeGetMsec() / 1000; + } + #elif defined(WOLFSSL_EMBOS) #include "RTOS.h" @@ -2630,6 +3387,7 @@ void bench_ed25519KeySign(void) } #endif /* _WIN32 */ +#endif /* !HAVE_STACK_SIZE */ #if defined(HAVE_GET_CYCLES) @@ -2646,6 +3404,26 @@ static INLINE word64 get_intel_cycles(void) } #endif /* HAVE_GET_CYCLES */ + +#ifndef NO_MAIN_DRIVER + +int main(int argc, char** argv) +{ + int ret = 0; + +#ifdef HAVE_STACK_SIZE + ret = StackSizeCheck(NULL, benchmark_test); +#else + ret = benchmark_test(NULL); +#endif + + (void)argc; + (void)argv; + + return ret; +} +#endif /* !NO_MAIN_DRIVER */ + #else #ifndef NO_MAIN_DRIVER int main() { return 0; } diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 20feeb45d5..4c67bd12d7 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -28,7 +28,11 @@ extern "C" { #endif -int benchmark_test(void* args); +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args); +#else +int benchmark_test(void *args); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c old mode 100644 new mode 100755 index c1f1f74e80..12ded23841 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -30,176 +30,175 @@ #include +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS -int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, - int dir) -{ - return AesSetKey_fips(aes, key, len, iv, dir); -} - - -int wc_AesSetIV(Aes* aes, const byte* iv) -{ - return AesSetIV_fips(aes, iv); -} - - -#ifdef HAVE_AES_CBC -int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcEncrypt_fips(aes, out, in, sz); -} - -#ifdef HAVE_AES_DECRYPT -int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcDecrypt_fips(aes, out, in, sz); -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ - -/* AES-CTR */ -#ifdef WOLFSSL_AES_COUNTER -void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - AesCtrEncrypt(aes, out, in, sz); -} -#endif - -/* AES-DIRECT */ -#if defined(WOLFSSL_AES_DIRECT) -void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesEncryptDirect(aes, out, in); -} - -#ifdef HAVE_AES_DECRYPT -void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesDecryptDirect(aes, out, in); -} -#endif /* HAVE_AES_DECRYPT */ - -int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, - const byte* iv, int dir) -{ - return AesSetKeyDirect(aes, key, len, iv, dir); -} -#endif - - -#ifdef HAVE_AESGCM -int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) -{ - return AesGcmSetKey_fips(aes, key, len); -} - + int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) + { + return AesSetKey_fips(aes, key, len, iv, dir); + } + int wc_AesSetIV(Aes* aes, const byte* iv) + { + return AesSetIV_fips(aes, iv); + } + #ifdef HAVE_AES_CBC + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return AesCbcEncrypt_fips(aes, out, in, sz); + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return AesCbcDecrypt_fips(aes, out, in, sz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ -int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz); -} + /* AES-CTR */ + #ifdef WOLFSSL_AES_COUNTER + void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + AesCtrEncrypt(aes, out, in, sz); + } + #endif -#ifdef HAVE_AES_DECRYPT -int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz); -} -#endif /* HAVE_AES_DECRYPT */ + /* AES-DIRECT */ + #if defined(WOLFSSL_AES_DIRECT) + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + AesEncryptDirect(aes, out, in); + } -int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) -{ - return GmacSetKey(gmac, key, len); -} + #ifdef HAVE_AES_DECRYPT + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + AesDecryptDirect(aes, out, in); + } + #endif /* HAVE_AES_DECRYPT */ + int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) + { + return AesSetKeyDirect(aes, key, len, iv, dir); + } + #endif /* WOLFSSL_AES_DIRECT */ -int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, - const byte* authIn, word32 authInSz, - byte* authTag, word32 authTagSz) -{ - return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, - authTag, authTagSz); -} + /* AES-GCM */ + #ifdef HAVE_AESGCM + int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) + { + return AesGcmSetKey_fips(aes, key, len); + } + int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } -#endif /* HAVE_AESGCM */ -#ifdef HAVE_AESCCM -int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) -{ - AesCcmSetKey(aes, key, keySz); - return 0; -} + #ifdef HAVE_AES_DECRYPT + int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) + { + return GmacSetKey(gmac, key, len); + } + int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) + { + return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, + authTag, authTagSz); + } + #endif /* HAVE_AESGCM */ -int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - /* sanity check on arguments */ - if (aes == NULL || out == NULL || in == NULL || nonce == NULL - || authTag == NULL || nonceSz < 7 || nonceSz > 13) - return BAD_FUNC_ARG; + /* AES-CCM */ + #ifdef HAVE_AESCCM + void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) + { + AesCcmSetKey(aes, key, keySz); + } + int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; - AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); - return 0; -} + AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, + authTagSz, authIn, authInSz); + return 0; + } -#ifdef HAVE_AES_DECRYPT -int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AESCCM */ + #ifdef HAVE_AES_DECRYPT + int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, + authTag, authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AESCCM */ -#ifdef WOLFSSL_ASYNC_CRYPT -int wc_AesAsyncInit(Aes* aes, int i) -{ - return AesAsyncInit(aes, i); -} + int wc_AesInit(Aes* aes, void* h, int i) + { + (void)aes; + (void)h; + (void)i; + /* FIPS doesn't support: + return AesInit(aes, h, i); */ + return 0; + } + void wc_AesFree(Aes* aes) + { + (void)aes; + /* FIPS doesn't support: + AesFree(aes); */ + } -void wc_AesAsyncFree(Aes* aes) -{ - AesAsyncFree(aes); -} -#endif #else /* HAVE_FIPS */ -#ifdef WOLFSSL_TI_CRYPT -#include + +#if defined(WOLFSSL_TI_CRYPT) + #include #else #include #include + #ifdef NO_INLINE #include #else #define WOLFSSL_MISC_INCLUDED #include #endif + #ifdef DEBUG_AESNI #include #endif - #ifdef _MSC_VER /* 4127 warning constant while(1) */ #pragma warning(disable: 4127) #endif + /* Define AES implementation includes and functions */ #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) /* STM32F2/F4 hardware AES support for CBC, CTR modes */ @@ -210,6 +209,7 @@ void wc_AesAsyncFree(Aes* aes) int ret = 0; #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { @@ -225,8 +225,6 @@ void wc_AesAsyncFree(Aes* aes) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -324,13 +322,13 @@ void wc_AesAsyncFree(Aes* aes) #endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM || HAVE_AESCCM */ #ifdef HAVE_AES_DECRYPT - #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) + #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { int ret = 0; #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -345,8 +343,6 @@ void wc_AesAsyncFree(Aes* aes) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -364,7 +360,7 @@ void wc_AesAsyncFree(Aes* aes) #endif /* WOLFSSL_STM32_CUBEMX */ return ret; } - #endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM */ + #endif /* WOLFSSL_AES_DIRECT || HAVE_AESCCM */ #endif /* HAVE_AES_DECRYPT */ #elif defined(HAVE_COLDFIRE_SEC) @@ -382,12 +378,12 @@ void wc_AesAsyncFree(Aes* aes) #else /* if LTC doesn't have GCM, use software with LTC AES ECB mode */ static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) - { + { wc_AesEncryptDirect(aes, outBlock, inBlock); return 0; } static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) - { + { wc_AesDecryptDirect(aes, outBlock, inBlock); return 0; } @@ -419,13 +415,12 @@ void wc_AesAsyncFree(Aes* aes) return ret; } #endif /* HAVE_AES_DECRYPT */ + #elif defined(WOLFSSL_PIC32MZ_CRYPT) /* NOTE: no support for AES-CCM/Direct */ #define DEBUG_WOLFSSL #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" -#elif defined(HAVE_CAVIUM) - /* still leave SW crypto available */ - #define NEED_AES_TABLES + #elif defined(WOLFSSL_NRF51_AES) /* Use built-in AES hardware - AES 128 ECB Encrypt Only */ #include "wolfssl/wolfcrypt/port/nrf51.h" @@ -434,9 +429,176 @@ void wc_AesAsyncFree(Aes* aes) { return nrf51_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); } + #ifdef HAVE_AES_DECRYPT #error nRF51 AES Hardware does not support decrypt #endif /* HAVE_AES_DECRYPT */ + + +#elif defined(WOLFSSL_AESNI) + + #define NEED_AES_TABLES + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #ifndef AESNI_ALIGN + #define AESNI_ALIGN 16 + #endif + + #ifndef _MSC_VER + #define cpuid(reg, func)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (func)); + + #define XASM_LINK(f) asm(f) + #else + + #include + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + + static int Check_CPU_support_AES(void) + { + unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ + cpuid(reg, 1); /* query info 1 */ + + if (reg[2] & 0x2000000) + return 1; + + return 0; + } + + static int checkAESNI = 0; + static int haveAESNI = 0; + + + /* tell C compiler these are asm functions in case any mix up of ABI underscore + prefix between clang/gcc/llvm etc */ + #ifdef HAVE_AES_CBC + void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_encrypt"); + + #ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_AESNI_BY4) + void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by4"); + #elif defined(WOLFSSL_AESNI_BY6) + void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by6"); + #else /* WOLFSSL_AESNI_BYx */ + void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by8"); + #endif /* WOLFSSL_AESNI_BYx */ + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + + void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_encrypt"); + + #ifdef HAVE_AES_DECRYPT + void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_decrypt"); + #endif + + void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_128_Key_Expansion"); + + void AES_192_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_192_Key_Expansion"); + + void AES_256_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_256_Key_Expansion"); + + + static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + Aes* aes) + { + int ret; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + switch (bits) { + case 128: + AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; + return 0; + case 192: + AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; + return 0; + case 256: + AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; + return 0; + default: + ret = BAD_FUNC_ARG; + } + + return ret; + } + + #ifdef HAVE_AES_DECRYPT + static int AES_set_decrypt_key(const unsigned char* userKey, + const int bits, Aes* aes) + { + int nr; + Aes temp_key; + __m128i *Key_Schedule = (__m128i*)aes->key; + __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) + return BAD_FUNC_ARG; + + nr = temp_key.rounds; + aes->rounds = nr; + + Key_Schedule[nr] = Temp_Key_Schedule[0]; + Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); + Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); + Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); + Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); + Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); + Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); + Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); + Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); + Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); + + if (nr>10) { + Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); + Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); + } + + if (nr>12) { + Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); + Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); + } + + Key_Schedule[0] = Temp_Key_Schedule[nr]; + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ + #else /* using wolfCrypt software AES implementation */ @@ -444,6 +606,7 @@ void wc_AesAsyncFree(Aes* aes) #endif + #ifdef NEED_AES_TABLES static const word32 rcon[] = { @@ -720,6 +883,7 @@ static const word32 Te[4][256] = { } }; +#ifdef HAVE_AES_DECRYPT static const word32 Td[4][256] = { { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, @@ -1024,170 +1188,13 @@ static const byte Td4[256] = 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; - -#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) - - -#ifdef WOLFSSL_AESNI - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - - #define cpuid(reg, func)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (func)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - - -static int Check_CPU_support_AES(void) -{ - unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ - cpuid(reg, 1); /* query info 1 */ - - if (reg[2] & 0x2000000) - return 1; - - return 0; -} - -static int checkAESNI = 0; -static int haveAESNI = 0; - - -/* tell C compiler these are asm functions in case any mix up of ABI underscore - prefix between clang/gcc/llvm etc */ -#ifdef HAVE_AES_CBC -void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_encrypt"); - -#ifdef HAVE_AES_DECRYPT - #if defined(WOLFSSL_AESNI_BY4) - void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by4"); - #elif defined(WOLFSSL_AESNI_BY6) - void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by6"); - #else /* WOLFSSL_AESNI_BYx */ - void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by8"); - #endif /* WOLFSSL_AESNI_BYx */ #endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ - -void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, - unsigned long length, const unsigned char* KS, int nr) - XASM_LINK("AES_ECB_encrypt"); - -#ifdef HAVE_AES_DECRYPT -void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, - unsigned long length, const unsigned char* KS, int nr) - XASM_LINK("AES_ECB_decrypt"); -#endif - -void AES_128_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_128_Key_Expansion"); - -void AES_192_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_192_Key_Expansion"); - -void AES_256_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_256_Key_Expansion"); - - -static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - Aes* aes) -{ - if (!userKey || !aes) - return BAD_FUNC_ARG; - - if (bits == 128) { - AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; - return 0; - } - else if (bits == 192) { - AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; - return 0; - } - else if (bits == 256) { - AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; - return 0; - } - return BAD_FUNC_ARG; -} - -#ifdef HAVE_AES_DECRYPT -static int AES_set_decrypt_key(const unsigned char* userKey, const int bits, - Aes* aes) -{ - int nr; - Aes temp_key; - __m128i *Key_Schedule = (__m128i*)aes->key; - __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; - - if (!userKey || !aes) - return BAD_FUNC_ARG; - - if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) - return BAD_FUNC_ARG; - - nr = temp_key.rounds; - aes->rounds = nr; - - Key_Schedule[nr] = Temp_Key_Schedule[0]; - Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); - Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); - Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); - Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); - Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); - Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); - Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); - Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); - Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); - - if(nr>10) { - Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); - Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); - } - - if(nr>12) { - Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); - Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); - } - Key_Schedule[0] = Temp_Key_Schedule[nr]; +#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) - return 0; -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* WOLFSSL_AESNI */ -#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) ||\ - defined(HAVE_AESGCM) +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) #ifndef WC_CACHE_LINE_SZ #if defined(__x86_64__) || defined(_M_X64) || \ @@ -1221,12 +1228,13 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) word32 s0, s1, s2, s3; word32 t0, t1, t2, t3; word32 r = aes->rounds >> 1; - const word32* rk = aes->key; + if (r > 7 || r == 0) { WOLFSSL_MSG("AesEncrypt encountered improper key, set it up"); return; /* stop instead of segfaulting, set up your keys! */ } + #ifdef WOLFSSL_AESNI if (haveAESNI && aes->use_aesni) { #ifdef DEBUG_AESNI @@ -1239,16 +1247,19 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif /* check alignment, decrypt doesn't need alignment */ - if ((wolfssl_word)inBlock % 16) { + if ((wolfssl_word)inBlock % AESNI_ALIGN) { #ifndef NO_WOLFSSL_ALLOC_ALIGN byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; if (tmp == NULL) return; - XMEMCPY(tmp, inBlock, AES_BLOCK_SIZE); - AES_ECB_encrypt(tmp, tmp, AES_BLOCK_SIZE, (byte*)aes->key, + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + + XMEMCPY(tmp_align, inBlock, AES_BLOCK_SIZE); + AES_ECB_encrypt(tmp_align, tmp_align, AES_BLOCK_SIZE, (byte*)aes->key, aes->rounds); - XMEMCPY(outBlock, tmp, AES_BLOCK_SIZE); + XMEMCPY(outBlock, tmp_align, AES_BLOCK_SIZE); XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return; #else @@ -1278,12 +1289,12 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif s0 ^= rk[0]; s1 ^= rk[1]; @@ -1384,12 +1395,12 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk[3]; /* write out */ - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif XMEMCPY(outBlock, &s0, sizeof(s0)); XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); @@ -1399,6 +1410,7 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) } #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */ + #ifdef HAVE_AES_DECRYPT #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) @@ -1417,7 +1429,6 @@ static INLINE word32 PreFetchTd(void) return x; } - /* load Td Table4 into cache by cache line stride */ static INLINE word32 PreFetchTd4(void) { @@ -1430,7 +1441,6 @@ static INLINE word32 PreFetchTd4(void) return x; } - static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { word32 s0, s1, s2, s3; @@ -1464,7 +1474,7 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) printf("Skipping AES-NI\n"); #endif } -#endif +#endif /* WOLFSSL_AESNI */ /* * map byte array block to cipher state @@ -1475,12 +1485,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif s0 ^= rk[0]; s1 ^= rk[1]; @@ -1582,12 +1592,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk[3]; /* write out */ - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif XMEMCPY(outBlock, &s0, sizeof(s0)); XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); @@ -1599,10 +1609,11 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif /* NEED_AES_TABLES */ + /* wc_AesSetKey */ #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) -int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { word32 *rk = aes->key; @@ -1612,6 +1623,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); #ifndef WOLFSSL_STM32_CUBEMX @@ -1648,28 +1660,28 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, extern volatile unsigned char __MBAR[]; - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { if (AESBuffIn == NULL) { - #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, - AES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, - AES_BUFFER_SIZE, TX_NO_WAIT); - s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, - AES_BLOCK_SIZE*2, TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, - AES_BLOCK_SIZE, TX_NO_WAIT); - - if(s1 || s2 || s3 || s4 || s5) - return BAD_FUNC_ARG; - #else - #warning "Allocate non-Cache buffers" - #endif + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, + AES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, + AES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, + AES_BLOCK_SIZE*2, TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, + AES_BLOCK_SIZE, TX_NO_WAIT); + + if (s1 || s2 || s3 || s4 || s5) + return BAD_FUNC_ARG; + #else + #warning "Allocate non-Cache buffers" + #endif wc_InitMutex(&Mutex_AesSEC); } @@ -1680,6 +1692,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (aes == NULL) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); @@ -1697,7 +1710,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); - + #ifdef WOLFSSL_AES_COUNTER aes->left = 0; #endif /* WOLFSSL_AES_COUNTER */ @@ -1711,8 +1724,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return wc_AesSetKey(aes, userKey, keylen, iv, dir); } #elif defined(FREESCALE_MMCAU) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { int ret; byte *rk = (byte*)aes->key; @@ -1728,7 +1741,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, #ifdef WOLFSSL_AES_COUNTER aes->left = 0; #endif /* WOLFSSL_AES_COUNTER */ - + + aes->keylen = keylen; aes->rounds = keylen/4 + 6; ret = wolfSSL_CryptHwMutexLock(); @@ -1747,9 +1761,10 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + #elif defined(WOLFSSL_NRF51_AES) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { int ret; @@ -1759,6 +1774,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (keylen != 16) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; ret = nrf51_aes_set_key(userKey); @@ -1770,6 +1786,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + #else static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) @@ -1777,25 +1794,25 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, word32 temp, *rk = aes->key; unsigned int i = 0; - #ifdef WOLFSSL_AESNI - aes->use_aesni = 0; - #endif /* WOLFSSL_AESNI */ - #ifdef WOLFSSL_AES_COUNTER - aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AESNI + aes->use_aesni = 0; + #endif /* WOLFSSL_AESNI */ + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); - #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(rk, rk, keylen); - #endif + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(rk, rk, keylen); + #endif #ifdef WOLFSSL_PIC32MZ_CRYPT { word32 *akey1 = aes->key_ce; - word32 *areg = aes->iv_ce ; - aes->keylen = keylen ; + word32 *areg = aes->iv_ce; XMEMCPY(akey1, userKey, keylen); if (iv) XMEMCPY(areg, iv, AES_BLOCK_SIZE); @@ -1925,20 +1942,24 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff]; } } +#else + (void)dir; #endif /* HAVE_AES_DECRYPT */ return wc_AesSetIV(aes, iv); } - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { #if defined(AES_MAX_KEY_SIZE) const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); #endif - if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + if (aes == NULL || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { return BAD_FUNC_ARG; + } #if defined(AES_MAX_KEY_SIZE) /* Check key length */ @@ -1946,12 +1967,15 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return BAD_FUNC_ARG; } #endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { - return NitroxAesSetKey(aes, userKey, keylen, iv); + aes->asyncKey = userKey; + aes->asyncIv = iv; } - #endif + #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (checkAESNI == 0) { @@ -1959,6 +1983,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, checkAESNI = 1; } if (haveAESNI) { + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ aes->use_aesni = 1; if (iv) XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); @@ -1975,14 +2002,12 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, } #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) - - /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ - int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, - const byte* iv, int dir) - { - return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); - } - + /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + } #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ #endif /* wc_AesSetKey block */ @@ -2001,21 +2026,6 @@ int wc_AesSetIV(Aes* aes, const byte* iv) return 0; } - -/* set the heap hint for aes struct */ -int wc_InitAes_h(Aes* aes, void* h) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - aes->heap = h; - - return 0; -} - - - - /* AES-DIRECT */ #if defined(WOLFSSL_AES_DIRECT) #if defined(HAVE_COLDFIRE_SEC) @@ -2077,7 +2087,7 @@ int wc_InitAes_h(Aes* aes, void* h) { int ret = 0; CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -2092,8 +2102,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -2125,7 +2133,7 @@ int wc_InitAes_h(Aes* aes, void* h) { int ret = 0; CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -2140,8 +2148,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -2400,7 +2406,7 @@ int wc_InitAes_h(Aes* aes, void* h) #elif defined(HAVE_COLDFIRE_SEC) static int wc_AesCbcCrypt(Aes* aes, byte* po, const byte* pi, word32 sz, - word32 descHeader) + word32 descHeader) { #ifdef DEBUG_WOLFSSL int i; int stat1, stat2; int ret; @@ -2422,9 +2428,9 @@ int wc_InitAes_h(Aes* aes, void* h) secDesc->pointer2 = (byte *)secReg; /* Initial Vector */ switch(aes->rounds) { - case 10: secDesc->length3 = 16 ; break ; - case 12: secDesc->length3 = 24 ; break ; - case 14: secDesc->length3 = 32 ; break ; + case 10: secDesc->length3 = 16; break; + case 12: secDesc->length3 = 24; break; + case 14: secDesc->length3 = 32; break; } XMEMCPY(secKey, aes->key, secDesc->length3); @@ -2503,8 +2509,8 @@ int wc_InitAes_h(Aes* aes, void* h) return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT)); } #endif /* HAVE_AES_DECRYPT */ - -#elif defined(FREESCALE_LTC) + +#elif defined(FREESCALE_LTC) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { uint32_t keySize; @@ -2609,21 +2615,22 @@ int wc_InitAes_h(Aes* aes, void* h) return 0; } #endif /* HAVE_AES_DECRYPT */ + #elif defined(WOLFSSL_PIC32MZ_CRYPT) /* core hardware crypt engine driver */ static void wc_AesCrypt(Aes *aes, byte* out, const byte* in, word32 sz, int dir, int algo, int cryptoalgo) { - securityAssociation *sa_p ; - bufferDescriptor *bd_p ; + securityAssociation *sa_p; + bufferDescriptor *bd_p; volatile securityAssociation sa __attribute__((aligned (8))); volatile bufferDescriptor bd __attribute__((aligned (8))); - volatile int k ; + volatile int k; /* get uncached address */ - sa_p = KVA0_TO_KVA1(&sa) ; - bd_p = KVA0_TO_KVA1(&bd) ; + sa_p = KVA0_TO_KVA1(&sa); + bd_p = KVA0_TO_KVA1(&bd); /* Sync cache and physical memory */ if(PIC32MZ_IF_RAM(in)) { @@ -2632,27 +2639,27 @@ int wc_InitAes_h(Aes* aes, void* h) XMEMSET((void *)KVA0_TO_KVA1(out), 0, sz); /* Set up the Security Association */ XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); - sa_p->SA_CTRL.ALGO = algo ; /* AES */ + sa_p->SA_CTRL.ALGO = algo; /* AES */ sa_p->SA_CTRL.LNC = 1; sa_p->SA_CTRL.LOADIV = 1; sa_p->SA_CTRL.FB = 1; - sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ + sa_p->SA_CTRL.ENCTYPE = dir; /* Encryption/Decryption */ sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM){ switch(aes->keylen) { case 32: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_256 ; - break ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_256; + break; case 24: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_192 ; - break ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_192; + break; case 16: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; - break ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128; + break; } } else - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128; ByteReverseWords( (word32 *)KVA0_TO_KVA1(sa.SA_ENCKEY + 8 - aes->keylen/sizeof(word32)), @@ -2665,27 +2672,27 @@ int wc_InitAes_h(Aes* aes, void* h) bd_p->BD_CTRL.BUFLEN = sz; if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM) { if(sz % 0x10) - bd_p->BD_CTRL.BUFLEN = (sz/0x10 + 1) * 0x10 ; + bd_p->BD_CTRL.BUFLEN = (sz/0x10 + 1) * 0x10; } bd_p->BD_CTRL.LIFM = 1; bd_p->BD_CTRL.SA_FETCH_EN = 1; bd_p->BD_CTRL.LAST_BD = 1; bd_p->BD_CTRL.DESC_EN = 1; - bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; - bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa); + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in); bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); - bd_p->MSGLEN = sz ; + bd_p->MSGLEN = sz; CECON = 1 << 6; while (CECON); /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd); CEINTEN = 0x07; CECON = 0x27; - WAIT_ENGINE ; + WAIT_ENGINE; if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| @@ -2694,14 +2701,14 @@ int wc_InitAes_h(Aes* aes, void* h) if(dir == PIC32_ENCRYPTION) { XMEMCPY((void *)aes->iv_ce, (void*)KVA0_TO_KVA1(out + sz - AES_BLOCK_SIZE), - AES_BLOCK_SIZE) ; + AES_BLOCK_SIZE); } else { ByteReverseWords((word32*)aes->iv_ce, (word32 *)KVA0_TO_KVA1(in + sz - AES_BLOCK_SIZE), AES_BLOCK_SIZE); } } - XMEMCPY((byte *)out, (byte *)KVA0_TO_KVA1(out), sz) ; + XMEMCPY((byte *)out, (byte *)KVA0_TO_KVA1(out), sz); ByteReverseWords((word32*)out, (word32 *)out, sz); } @@ -2709,14 +2716,14 @@ int wc_InitAes_h(Aes* aes, void* h) { wc_AesCrypt(aes, out, in, sz, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC ); - return 0 ; + return 0; } #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { wc_AesCrypt(aes, out, in, sz, PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); - return 0 ; + return 0; } #endif /* HAVE_AES_DECRYPT */ @@ -2725,10 +2732,28 @@ int wc_InitAes_h(Aes* aes, void* h) { word32 blocks = sz / AES_BLOCK_SIZE; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) return NitroxAesCbcEncrypt(aes, out, in, sz); - #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_CBC_ENCRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { @@ -2743,22 +2768,25 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* check alignment, decrypt doesn't need alignment */ - if ((wolfssl_word)in % 16) { + if ((wolfssl_word)in % AESNI_ALIGN) { #ifndef NO_WOLFSSL_ALLOC_ALIGN - byte* tmp = (byte*)XMALLOC(sz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); + byte* tmp = (byte*)XMALLOC(sz + AESNI_ALIGN, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; if (tmp == NULL) return MEMORY_E; - XMEMCPY(tmp, in, sz); - AES_CBC_encrypt(tmp, tmp, (byte*)aes->reg, sz, (byte*)aes->key, + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + XMEMCPY(tmp_align, in, sz); + AES_CBC_encrypt(tmp_align, tmp_align, (byte*)aes->reg, sz, (byte*)aes->key, aes->rounds); /* store iv for next call */ - XMEMCPY(aes->reg, tmp + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, tmp_align + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - XMEMCPY(out, tmp, sz); + XMEMCPY(out, tmp_align, sz); XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return 0; #else + WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); return BAD_ALIGN_E; #endif } @@ -2787,11 +2815,28 @@ int wc_InitAes_h(Aes* aes, void* h) #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = sz / AES_BLOCK_SIZE; + word32 blocks; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) return NitroxAesCbcDecrypt(aes, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_CBC_DECRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif } #endif @@ -2825,6 +2870,7 @@ int wc_InitAes_h(Aes* aes, void* h) } #endif + blocks = sz / AES_BLOCK_SIZE; while (blocks--) { XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); wc_AesDecrypt(aes, (byte*)aes->tmp, out); @@ -2842,6 +2888,33 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* AES-CBC block */ #endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_ECB +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + while (sz>0) { + wc_AesEncryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + } + return 0; +} +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + while (sz>0) { + wc_AesDecryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + } + return 0; +} +#endif + /* AES-CTR */ #ifdef WOLFSSL_AES_COUNTER @@ -2850,7 +2923,7 @@ int wc_InitAes_h(Aes* aes, void* h) void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -2865,8 +2938,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = aes->key; @@ -2987,58 +3058,58 @@ int wc_InitAes_h(Aes* aes, void* h) #elif defined(WOLFSSL_PIC32MZ_CRYPT) void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int i ; - char out_block[AES_BLOCK_SIZE] ; - int odd ; - int even ; - char *tmp ; /* (char *)aes->tmp, for short */ + int i; + char out_block[AES_BLOCK_SIZE]; + int odd; + int even; + char *tmp; /* (char *)aes->tmp, for short */ - tmp = (char *)aes->tmp ; + tmp = (char *)aes->tmp; if(aes->left) { if((aes->left + sz) >= AES_BLOCK_SIZE){ - odd = AES_BLOCK_SIZE - aes->left ; + odd = AES_BLOCK_SIZE - aes->left; } else { - odd = sz ; + odd = sz; } - XMEMCPY(tmp+aes->left, in, odd) ; + XMEMCPY(tmp+aes->left, in, odd); if((odd+aes->left) == AES_BLOCK_SIZE){ wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - XMEMCPY(out, out_block+aes->left, odd) ; - aes->left = 0 ; - XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; + XMEMCPY(out, out_block+aes->left, odd); + aes->left = 0; + XMEMSET(tmp, 0x0, AES_BLOCK_SIZE); /* Increment IV */ for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { if (++((byte *)aes->iv_ce)[i]) - break ; + break; } } - in += odd ; - out+= odd ; - sz -= odd ; + in += odd; + out+= odd; + sz -= odd; } - odd = sz % AES_BLOCK_SIZE ; /* if there is tail fragment */ + odd = sz % AES_BLOCK_SIZE; /* if there is tail fragment */ if(sz / AES_BLOCK_SIZE) { - even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; + even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE; wc_AesCrypt(aes, out, in, even, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - out += even ; - in += even ; + out += even; + in += even; do { /* Increment IV */ for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { if (++((byte *)aes->iv_ce)[i]) - break ; + break; } - even -= AES_BLOCK_SIZE ; - } while((int)even > 0) ; + even -= AES_BLOCK_SIZE; + } while((int)even > 0); } if(odd) { - XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; - XMEMCPY(tmp+aes->left, in, odd) ; + XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left); + XMEMCPY(tmp+aes->left, in, odd); wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - XMEMCPY(out, out_block+aes->left,odd) ; - aes->left += odd ; + XMEMCPY(out, out_block+aes->left,odd); + aes->left += odd; } } @@ -3051,7 +3122,7 @@ int wc_InitAes_h(Aes* aes, void* h) uint32_t keySize; byte *iv, *enc_key; byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; - + /* consume any unused bytes left in aes->tmp */ while (aes->left && sz) { *(out++) = *(in++) ^ *(tmp++); @@ -3126,6 +3197,7 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AESGCM /* @@ -3722,8 +3794,8 @@ static void GMULT(byte* X, byte* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; @@ -3871,8 +3943,8 @@ static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE]) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; @@ -3931,9 +4003,9 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, static void GMULT(word64* X, word64* Y) { word64 Z[2] = {0,0}; - word64 V[2] ; + word64 V[2]; int i, j; - V[0] = X[0] ; V[1] = X[1] ; + V[0] = X[0]; V[1] = X[1]; for (i = 0; i < 2; i++) { @@ -3947,13 +4019,15 @@ static void GMULT(word64* X, word64* Y) if (V[1] & 0x0000000000000001) { V[1] >>= 1; - V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000ULL : 0); + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); V[0] >>= 1; V[0] ^= 0xE100000000000000ULL; } else { V[1] >>= 1; - V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000ULL : 0); + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); V[0] >>= 1; } y <<= 1; @@ -3963,8 +4037,9 @@ static void GMULT(word64* X, word64* Y) X[1] = Z[1]; } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) + +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { word64 x[2] = {0,0}; word32 blocks, partial; @@ -4031,8 +4106,8 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, /* Hash in the lengths in bits of A and C */ { - word64 len[2] ; - len[0] = aSz ; len[1] = cSz; + word64 len[2]; + len[0] = aSz; len[1] = cSz; /* Lengths are in bytes. Convert to bits. */ len[0] *= 8; @@ -4055,7 +4130,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, static void GMULT(word32* X, word32* Y) { word32 Z[4] = {0,0,0,0}; - word32 V[4] ; + word32 V[4]; int i, j; V[0] = X[0]; V[1] = X[1]; V[2] = X[2]; V[3] = X[3]; @@ -4100,8 +4175,8 @@ static void GMULT(word32* X, word32* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { word32 x[4] = {0,0,0,0}; word32 blocks, partial; @@ -4209,6 +4284,11 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, uint32_t keySize; status_t status; + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + key = (byte*)aes->key; status = wc_AesGetKeySize(aes, &keySize); @@ -4229,13 +4309,47 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* c = out; byte counter[AES_BLOCK_SIZE]; byte initialCounter[AES_BLOCK_SIZE]; - byte *ctr ; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; /* Sanity check for XMEMCPY in GHASH function and local xorbuf call */ if (authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM) { + #if defined(HAVE_CAVIUM) + /* Not yet supported, contact wolfSSL if interested in using */ + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_GCM_ENCRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLFSSL_AESNI if (haveAESNI) { AES_GCM_encrypt(in, out, authIn, iv, authTag, @@ -4245,9 +4359,9 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif #ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; + ctr = (char *)aes->iv_ce; #else - ctr = counter ; + ctr = counter; #endif XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); @@ -4293,7 +4407,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, } -#ifdef HAVE_AES_DECRYPT +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, @@ -4324,12 +4438,44 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* p = out; byte counter[AES_BLOCK_SIZE]; byte initialCounter[AES_BLOCK_SIZE]; - byte *ctr ; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; - /* Sanity check for local ConstantCompare call */ - if (authTagSz > AES_BLOCK_SIZE) + /* argument checks */ + if (aes == NULL || out == NULL || in == NULL || sz == 0 || iv == NULL || + authTag == NULL || authTagSz > AES_BLOCK_SIZE) { return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM) { + #if defined(HAVE_CAVIUM) + /* Not yet supported, contact wolfSSL if interested in using */ + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_GCM_DECRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = (byte*)authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { @@ -4341,9 +4487,9 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif #ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; + ctr = (char *)aes->iv_ce; #else - ctr = counter ; + ctr = counter; #endif XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); @@ -4397,7 +4543,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif /* FREESCALE_LTC_AES_GCM */ } -#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) { @@ -4887,28 +5033,36 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, #endif /* HAVE_AES_KEYWRAP */ -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Aes for use with Nitrox device */ -int wc_AesAsyncInit(Aes* aes, int devId) +/* Initialize Aes for use with async hardware */ +int wc_AesInit(Aes* aes, void* heap, int devId) { + int ret = 0; + if (aes == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, devId); -} + aes->heap = heap; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, + aes->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ -/* Free Aes from use with Nitrox device */ -void wc_AesAsyncFree(Aes* aes) + return ret; +} + +/* Free Aes from use with async hardware */ +void wc_AesFree(Aes* aes) { if (aes == NULL) return; - wolfAsync_DevCtxFree(&aes->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES); #endif /* WOLFSSL_ASYNC_CRYPT */ +} int wc_AesGetKeySize(Aes* aes, word32* keySize) diff --git a/wolfcrypt/src/arc4.c b/wolfcrypt/src/arc4.c index 6922089de2..160c36a916 100644 --- a/wolfcrypt/src/arc4.c +++ b/wolfcrypt/src/arc4.c @@ -32,12 +32,14 @@ #include -void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) +int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) { + int ret = 0; word32 i; word32 keyIndex = 0, stateIndex = 0; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { return NitroxArc4SetKey(arc4, key, length); } @@ -59,6 +61,8 @@ void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) if (++keyIndex >= length) keyIndex = 0; } + + return ret; } @@ -76,12 +80,14 @@ static INLINE byte MakeByte(word32* x, word32* y, byte* s) } -void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) +int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) { + int ret = 0; word32 x; word32 y; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { return NitroxArc4Process(arc4, out, in, length); } @@ -95,31 +101,41 @@ void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) arc4->x = (byte)x; arc4->y = (byte)y; -} - -#ifdef WOLFSSL_ASYNC_CRYPT + return ret; +} -/* Initialize Arc4 for use with Nitrox device */ -int wc_Arc4AsyncInit(Arc4* arc4, int devId) +/* Initialize Arc4 for use with async device */ +int wc_Arc4Init(Arc4* arc4, void* heap, int devId) { + int ret = 0; + if (arc4 == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, devId); + arc4->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, + arc4->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } -/* Free Arc4 from use with Nitrox device */ -void wc_Arc4AsyncFree(Arc4* arc4) +/* Free Arc4 from use with async device */ +void wc_Arc4Free(Arc4* arc4) { if (arc4 == NULL) return; - wolfAsync_DevCtxFree(&arc4->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4); #endif /* WOLFSSL_ASYNC_CRYPT */ +} #endif /* NO_RC4 */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c old mode 100755 new mode 100644 index 665199aeb8..bd478ffba7 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -31,6 +31,9 @@ ASN Options: * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC or wishing to save space. * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks. + * ASN_DUMP_OID: Allows dump of OID information for debugging. + * RSA_DECODE_EXTRA: Decodes extra information in RSA public key. + * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName. */ #ifndef NO_ASN @@ -78,6 +81,10 @@ ASN Options: #include #endif +#ifndef NO_RSA + #include +#endif + #ifdef WOLFSSL_DEBUG_ENCODING #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #if MQX_USE_IO_OLD @@ -95,26 +102,24 @@ ASN Options: #pragma warning(disable: 4996) #endif - -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } #ifndef NO_ASN_TIME #if defined(USER_TIME) - /* user time, and gmtime compatible functions, there is a gmtime - implementation here that WINCE uses, so really just need some ticks - since the EPOCH + /* Use our gmtime and time_t/struct tm types. + Only needs seconds since EPOCH using XTIME function. + time_t XTIME(time_t * timer) {} */ #define WOLFSSL_GMTIME #define USE_WOLF_TM #define USE_WOLF_TIME_T #elif defined(TIME_OVERRIDES) - /* user would like to override time() and gmtime() functionality */ + /* Override XTIME() and XGMTIME() functionality. + Requires user to provide these functions: + time_t XTIME(time_t * timer) {} + struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {} + */ #ifndef HAVE_TIME_T_TYPE #define USE_WOLF_TIME_T #endif @@ -234,6 +239,10 @@ ASN Options: struct tm* gmtime(const time_t* timer); #endif +#if defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + /* extern time_t ksdk_time(time_t* timer); */ +#endif /* FREESCALE_KSDK_BM || FREESCALE_FREE_RTOS */ + #if defined(_WIN32_WCE) time_t windows_time(time_t* timer) @@ -363,7 +372,7 @@ time_t pic32_time(time_t* timer) return *timer; } -#endif /* MICROCHIP_TCPIP */ +#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */ #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) @@ -382,14 +391,8 @@ time_t mqx_time(time_t* timer) return *timer; } -#endif /* FREESCALE_MQX */ - -#if defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) - -/* */ -//extern time_t ksdk_time(time_t* timer); +#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */ -#endif /* FREESCALE_KSDK_BM */ #if defined(WOLFSSL_TIRTOS) @@ -484,6 +487,7 @@ CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format, #endif /* MICRIUM */ + #if defined(IDIRECT_DEV_TIME) extern time_t getTimestamp(); @@ -502,43 +506,44 @@ time_t idirect_time(time_t * timer) #endif /* !NO_ASN_TIME */ + WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { int length = 0; - word32 i = *inOutIdx; + word32 idx = *inOutIdx; byte b; *len = 0; /* default length */ - if ( (i+1) > maxIdx) { /* for first read */ + if ((idx + 1) > maxIdx) { /* for first read */ WOLFSSL_MSG("GetLength bad index on input"); return BUFFER_E; } - b = input[i++]; + b = input[idx++]; if (b >= ASN_LONG_LENGTH) { word32 bytes = b & 0x7F; - if ( (i+bytes) > maxIdx) { /* for reading bytes */ + if ((idx + bytes) > maxIdx) { /* for reading bytes */ WOLFSSL_MSG("GetLength bad long length"); return BUFFER_E; } while (bytes--) { - b = input[i++]; + b = input[idx++]; length = (length << 8) | b; } } else length = b; - if ( (i+length) > maxIdx) { /* for user of length */ + if ((idx + length) > maxIdx) { /* for user of length */ WOLFSSL_MSG("GetLength value exceeds buffer length"); return BUFFER_E; } - *inOutIdx = i; + *inOutIdx = idx; if (length > 0) *len = length; @@ -546,39 +551,317 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } -WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, - word32 maxIdx) +/* Get the DER/BER encoding of an ASN.1 header. + * + * input Buffer holding DER/BER encoded data. + * tag ASN.1 tag value expected in header. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the expected tag is not found or length is invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != tag) + return ASN_PARSE_E; - if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) + if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; *len = length; *inOutIdx = idx; - return length; } +WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; + return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + +/* Get the DER/BER encoded ASN.1 NULL element. + * Ensure that the all fields are as expected and move index past the element. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_TAG_NULL_E when the NULL tag is not found. + * ASN_EXPECT_0_E when the length is not zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 2) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_TAG_NULL) + return ASN_TAG_NULL_E; + + if (input[idx++] != 0) + return ASN_EXPECT_0_E; + + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 NULL element. + * + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNNull(byte* output) +{ + output[0] = ASN_TAG_NULL; + output[1] = 0; + + return 2; +} + +/* Get the DER/BER encoding of an ASN.1 BOOLEAN. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1. + * Otherwise, 0 to indicate the value was false and 1 to indicate true. + */ +static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; - if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) + b = input[idx++]; + if (b != ASN_BOOLEAN) return ASN_PARSE_E; - *len = length; + if (input[idx++] != 1) + return ASN_PARSE_E; + + b = input[idx++] != 0; + *inOutIdx = idx; + return b; +} - return length; +#ifdef ASN1_SET_BOOLEAN +/* Set the DER/BER encoding of the ASN.1 NULL element. + * Note: Function not required as yet. + * + * val Boolean value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetBoolean(int val, byte* output) +{ + output[0] = ASN_BOOLEAN; + output[1] = 1; + output[2] = val ? -1 : 0; + + return 3; +} +#endif + +/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the OCTET_STRING tag is not found or length is + * invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetOctetString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx); +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER header. + * Removes the leading zero byte when found. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data (excluding any leading zero). + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found, length is invalid, + * or invalid use of or missing leading zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNInt(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int ret; + + ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx); + if (ret < 0) + return ret; + + if (*len > 0) { + /* remove leading zero, unless there is only one 0x00 byte */ + if ((input[*inOutIdx] == 0x00) && (*len > 1)) { + (*inOutIdx)++; + (*len)--; + + if (*len > 0 && (input[*inOutIdx] & 0x80) == 0) + return ASN_PARSE_E; + } + else if ((input[*inOutIdx] & 0x80) == 0x80) + return ASN_PARSE_E; + } + + return 0; +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than + * 7 bits. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found or length is invalid. + * Otherwise, the 7-bit value. + */ +static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + if (input[idx++] != 1) + return ASN_PARSE_E; + b = input[idx++]; + + *inOutIdx = idx; + return b; +} + +#if !defined(NO_DSA) || defined(HAVE_ECC) || (!defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)))) +/* Set the DER/BER encoding of the ASN.1 INTEGER header. + * + * len Length of data to encode. + * firstByte First byte of data, most significant byte of integer, to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNInt(int len, byte firstByte, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_INTEGER; + if (firstByte & 0x80) + len++; + idx += SetLength(len, output + idx); + if (firstByte & 0x80) + output[idx++] = 0x00; + + return idx; +} +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * maxSz Maximum size of the encoded integer. + * A negative value indicates no check of length requested. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntMP(mp_int* n, int maxSz, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = mp_leading_bit(n); + length = mp_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if (maxSz >= 0 && (idx + length) > maxSz) + return BUFFER_E; + + err = mp_to_unsigned_bin(n, output + idx); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; } +#endif + +#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && defined(WOLFSSL_CERT_GEN) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from + * an RSA key. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntRSA(mp_int* n, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = wc_Rsa_leading_bit(n); + length = wc_Rsa_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if ((idx + length) > MAX_RSA_INT_SZ) + return BUFFER_E; + + err = wc_Rsa_to_unsigned_bin(n, output + idx, length); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + return idx; +} +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ /* Windows header clash for WinCE using GetVersion */ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, @@ -586,10 +869,8 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, { word32 idx = *inOutIdx; - WOLFSSL_ENTER("GetMyVersion"); - - if (idx + MIN_VERSION_SZ > maxIdx) - return ASN_PARSE_E; + if ((idx + MIN_VERSION_SZ) > maxIdx) + return ASN_PARSE_E; if (input[idx++] != ASN_INTEGER) return ASN_PARSE_E; @@ -613,8 +894,9 @@ int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) *number = 0; - if (idx + 2 > maxIdx) /*one for type and one for length */ - return ASN_PARSE_E; + /* check for type and length bytes */ + if ((idx + 2) > maxIdx) + return BUFFER_E; if (input[idx++] != ASN_INTEGER) return ASN_PARSE_E; @@ -636,7 +918,6 @@ int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) } #endif /* !NO_PWDBASED */ -#ifndef NO_ASN_TIME /* May not have one, not an error */ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, word32 maxIdx) @@ -644,8 +925,12 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, word32 idx = *inOutIdx; WOLFSSL_ENTER("GetExplicitVersion"); + + if ((idx + 1) > maxIdx) + return BUFFER_E; + if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { - *inOutIdx = ++idx; /* eat header */ + *inOutIdx = ++idx; /* skip header */ return GetMyVersion(input, inOutIdx, version, maxIdx); } @@ -654,96 +939,146 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, return 0; } -#endif /* !NO_ASN_TIME */ -int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, - word32 maxIdx) +int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) { - word32 i = *inOutIdx; - byte b = input[i++]; + word32 idx = *inOutIdx; + int ret; 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--; + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; if (mp_init(mpi) != MP_OKAY) return MP_INIT_E; - if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { + if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) { mp_clear(mpi); return ASN_GETINT_E; } - *inOutIdx = i + length; +#ifdef HAVE_WOLF_BIGINT + if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + *inOutIdx = idx + length; + 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) +static int CheckBitString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int zeroBits, byte* unusedBits) { - word32 i = *inOutIdx; - byte b = input[i++]; + word32 idx = *inOutIdx; int length; + byte b; - (void)key; + if ((idx + 1) > maxIdx) + return BUFFER_E; - if (b != ASN_INTEGER) - return ASN_PARSE_E; + if (input[idx++] != ASN_BIT_STRING) + return ASN_BITSTR_E; - if (GetLength(input, &i, &length, maxIdx) < 0) + if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; - if (length > 0) { - /* remove leading zero */ - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + /* extra sanity check that length is greater than 0 */ + if (length <= 0) { + WOLFSSL_MSG("Error length was 0 in CheckBitString"); + return BUFFER_E; } -#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); + if (idx + 1 > maxIdx) { + WOLFSSL_MSG("Attempted buffer read larger than input buffer"); + return BUFFER_E; } - 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; - } + b = input[idx]; + if (zeroBits && b != 0x00) + return ASN_EXPECT_0_E; + if (b >= 0x08) + return ASN_PARSE_E; + if (b != 0) { + if ((byte)(input[idx + length - 1] << (8 - b)) != 0) + return ASN_PARSE_E; } + idx++; + length--; /* length has been checked for greater than 0 */ + + *inOutIdx = idx; + if (len != NULL) + *len = length; + if (unusedBits != NULL) + *unusedBits = b; - *inOutIdx = i + length; return 0; } -#endif /* !NO_RSA && !HAVE_USER_RSA */ + +#if (!defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_KEY_GEN) && \ + !defined(HAVE_USER_RSA)))) || \ + (defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN))) +/* Set the DER/BER encoding of the ASN.1 BIT_STRING header. + * + * len Length of data to encode. + * unusedBits The number of unused bits in the last byte of data. + * That is, the number of least significant zero bits before a one. + * The last byte is the most-significant non-zero byte of a number. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString(word32 len, byte unusedBits, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_BIT_STRING; + idx += SetLength(len + 1, output + idx); + output[idx++] = unusedBits; + + return idx; +} + +#ifdef WOLFSSL_CERT_EXT +/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value. + * + * val 16-bit value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString16Bit(word16 val, byte* output) +{ + word32 idx; + int len; + byte lastByte; + byte unusedBits = 0; + + if ((val >> 8) != 0) { + len = 2; + lastByte = (byte)(val >> 8); + } + else { + len = 1; + lastByte = (byte)val; + } + + while (((lastByte >> unusedBits) & 0x01) == 0x00) + unusedBits++; + + idx = SetBitString(len, unusedBits, output); + output[idx++] = (byte)val; + output[idx++] = (byte)(val >> 8); + + return idx; +} +#endif /* WOLFSSL_CERT_EXT */ +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA)) */ + /* hashType */ @@ -1312,52 +1647,100 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) } #endif /* HAVE_OID_DECODING */ -int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, - word32 oidType, word32 maxIdx) +/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_OBJECt_ID_E when the OBJECT_ID tag is not found. + * ASN_PARSE_E when length is invalid. + * Otherwise, 0 to indicate success. + */ +static int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) { - int length; - word32 i = *inOutIdx; -#ifndef NO_VERIFY_OID - word32 actualOidSz = 0; - const byte* actualOid; -#endif /* NO_VERIFY_OID */ + word32 idx = *inOutIdx; byte b; + int length; - (void)oidType; - WOLFSSL_ENTER("GetObjectId()"); - *oid = 0; + if ((idx + 1) > maxIdx) + return BUFFER_E; - b = input[i++]; + b = input[idx++]; if (b != ASN_OBJECT_ID) return ASN_OBJECT_ID_E; - if (GetLength(input, &i, &length, maxIdx) < 0) + if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; -#ifndef NO_VERIFY_OID - actualOid = &input[i]; - if (length > 0) - actualOidSz = (word32)length; -#endif /* NO_VERIFY_OID */ + *len = length; + *inOutIdx = idx; + return 0; +} - while(length--) { - /* odd HC08 compiler behavior here when input[i++] */ - *oid += input[i]; - i++; - } - /* just sum it up for now */ +/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header. + * + * len Length of the OBJECT_ID data. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetObjectId(int len, byte* output) +{ + int idx = 0; - *inOutIdx = i; + output[idx++] = ASN_OBJECT_ID; + idx += SetLength(len, output + idx); -#ifndef NO_VERIFY_OID - { + return idx; +} + +int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx) +{ + int ret = 0, length; + word32 idx = *inOutIdx; +#ifndef NO_VERIFY_OID + word32 actualOidSz = 0; + const byte* actualOid; +#endif /* NO_VERIFY_OID */ + + (void)oidType; + WOLFSSL_ENTER("GetObjectId()"); + *oid = 0; + + ret = GetASNObjectId(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + +#ifndef NO_VERIFY_OID + actualOid = &input[idx]; + if (length > 0) + actualOidSz = (word32)length; +#endif /* NO_VERIFY_OID */ + + while (length--) { + /* odd HC08 compiler behavior here when input[idx++] */ + *oid += (word32)input[idx]; + idx++; + } + /* just sum it up for now */ + + *inOutIdx = idx; + +#ifndef NO_VERIFY_OID + { const byte* checkOid = NULL; word32 checkOidSz; + #ifdef ASN_DUMP_OID + int i; + #endif if (oidType != oidIgnoreType) { checkOid = OidFromId(*oid, oidType, &checkOidSz); - #if 0 + #ifdef ASN_DUMP_OID /* support for dumping OID information */ printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid); for (i=0; itype = RSA_PRIVATE; - 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; + 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; return 0; } #endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ -/* Remove PKCS8 header, move beginning of traditional to beginning of input */ -int ToTraditional(byte* input, word32 sz) +/* Remove PKCS8 header, place inOutIdx at beginning of traditional, + * return traditional length on success, negative on error */ +int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) { - word32 inOutIdx = 0, oid; + word32 idx, oid; int version, length; + int ret; - if (GetSequence(input, &inOutIdx, &length, sz) < 0) + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + if (GetSequence(input, &idx, &length, sz) < 0) return ASN_PARSE_E; - if (GetMyVersion(input, &inOutIdx, &version, sz) < 0) + if (GetMyVersion(input, &idx, &version, sz) < 0) return ASN_PARSE_E; - if (GetAlgoId(input, &inOutIdx, &oid, oidKeyType, sz) < 0) + if (GetAlgoId(input, &idx, &oid, oidKeyType, sz) < 0) return ASN_PARSE_E; - if (input[inOutIdx] == ASN_OBJECT_ID) { - /* pkcs8 ecc uses slightly different format */ - inOutIdx++; /* past id */ - if (GetLength(input, &inOutIdx, &length, sz) < 0) + if (input[idx] == ASN_OBJECT_ID) { + if (SkipObjectId(input, &idx, sz) < 0) return ASN_PARSE_E; - inOutIdx += length; /* over sub id, key input will verify */ } - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + *inOutIdx = idx; + + return length; +} + +/* Remove PKCS8 header, move beginning of traditional to beginning of input */ +int ToTraditional(byte* input, word32 sz) +{ + word32 inOutIdx = 0; + int length; + + if (input == NULL) + return BAD_FUNC_ARG; + + length = ToTraditionalInline(input, &inOutIdx, sz); + if (length < 0) + return length; XMEMMOVE(input, input + inOutIdx, length); @@ -1515,6 +1911,134 @@ int ToTraditional(byte* input, word32 sz) } +/* find beginning of traditional key inside PKCS#8 unencrypted buffer + * return traditional length on success, with inOutIdx at beginning of + * traditional + * return negative on failure/error */ +int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz) +{ + int length; + + if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz)) + return BAD_FUNC_ARG; + + length = ToTraditionalInline(input, inOutIdx, sz); + + return length; +} + + +/* PKCS#8 from RFC 5208 + * This function takes in a DER key and converts it to PKCS#8 format. Used + * in creating PKCS#12 shrouded key bags. + * Reverse of ToTraditional + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes optional + * } + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * out buffer to place result in + * outSz size of out buffer + * key buffer with DER key + * keySz size of key buffer + * algoID algorithm ID i.e. RSAk + * curveOID ECC curve oid if used. Should be NULL for RSA keys. + * oidSz size of curve oid. Is set to 0 if curveOID is NULL. + * + * Returns the size of PKCS#8 placed into out. In error cases returns negative + * values. + */ +int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, + int algoID, const byte* curveOID, word32 oidSz) +{ + word32 keyIdx = 0; + word32 tmpSz = 0; + word32 sz; + + + /* If out is NULL then return the max size needed + * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ + if (out == NULL && outSz != NULL) { + *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; + + if (curveOID != NULL) + *outSz += oidSz + MAX_LENGTH_SZ + 1; + + WOLFSSL_MSG("Checking size of PKCS8"); + + return LENGTH_ONLY_E; + } + + WOLFSSL_ENTER("wc_CreatePKCS8Key()"); + + if (key == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* check the buffer has enough room for largest possible size */ + if (curveOID != NULL) { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) + return BUFFER_E; + } + else { + oidSz = 0; /* with no curveOID oid size must be 0 */ + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) + return BUFFER_E; + } + + /* PrivateKeyInfo ::= SEQUENCE */ + keyIdx += MAX_SEQ_SZ; /* save room for sequence */ + + /* version Version + * no header information just INTEGER */ + sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ + sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ + if (curveOID != NULL && oidSz > 0) { + byte buf[MAX_LENGTH_SZ]; + sz = SetLength(oidSz, buf); + sz += 1; /* plus one for ASN object id */ + } + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); + tmpSz += sz; keyIdx += sz; + + /* privateKey PrivateKey * + * pkcs8 ecc uses slightly different format. Places curve oid in + * buffer */ + if (curveOID != NULL && oidSz > 0) { + sz = SetObjectId(oidSz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, curveOID, oidSz); + keyIdx += oidSz; tmpSz += oidSz; + } + + sz = SetOctetString(keySz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, key, keySz); + tmpSz += keySz; + + /* attributes optional + * No attributes currently added */ + + /* rewind and add sequence */ + sz = SetSequence(tmpSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + + return tmpSz + sz; +} + + /* check that the private key is a pair for the public key in certificate * return 1 (true) on match * return 0 or negative value on failure/error @@ -1630,11 +2154,11 @@ static int CheckAlgo(int first, int second, int* id, int* version) switch (second) { case 1: *id = PBE_SHA1_RC4_128; - *version = PKCS12; + *version = PKCS12v1; return 0; case 3: *id = PBE_SHA1_DES3; - *version = PKCS12; + *version = PKCS12v1; return 0; default: return ALGO_ID_E; @@ -1742,7 +2266,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, ret = wc_PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations, derivedLen, typeH); #endif - else if (version == PKCS12) { + else if (version == PKCS12v1) { int i, idx = 0; byte unicodePasswd[MAX_UNICODE_SZ]; @@ -1788,7 +2312,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, Des dec; byte* desIv = key + 8; - if (version == PKCS5v2 || version == PKCS12) + if (version == PKCS5v2 || version == PKCS12v1) desIv = cbcIv; ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION); @@ -1808,7 +2332,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, Des3 dec; byte* desIv = key + 24; - if (version == PKCS5v2 || version == PKCS12) + if (version == PKCS5v2 || version == PKCS12v1) desIv = cbcIv; ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION); if (ret != 0) { @@ -1853,12 +2377,88 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, } +int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, + int* algoID, void* heap) +{ + word32 tmpIdx = 0; +#ifdef HAVE_ECC + ecc_key ecc; +#endif +#ifndef NO_RSA + RsaKey rsa; +#endif + + if (algoID == NULL) { + return BAD_FUNC_ARG; + } + *algoID = 0; + +#ifndef NO_RSA + if (wc_InitRsaKey(&rsa, heap) == 0) { + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(&rsa); + } + else { + WOLFSSL_MSG("GetKeyOID wc_InitRsaKey failed"); + } +#endif /* NO_RSA */ +#ifdef HAVE_ECC + if (*algoID != RSAk) { + tmpIdx = 0; + if (wc_ecc_init_ex(&ecc, heap, INVALID_DEVID) == 0) { + if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* sanity check on arguments */ + if (curveOID == NULL || oidSz == NULL) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + + /* now find oid */ + if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + } + else { + WOLFSSL_MSG("Not ECC DER key either"); + } + wc_ecc_free(&ecc); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ecc_init_ex failed"); + } + } +#endif /* HAVE_ECC */ + + /* if flag is not set then is neither RSA or ECC key that could be + * found */ + if (*algoID == 0) { + WOLFSSL_MSG("Bad key DER or compile options"); + return BAD_FUNC_ARG; + } + + (void)curveOID; + (void)oidSz; + + return 1; +} + + /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) { word32 inOutIdx = 0, oid; - int first, second, length, version, saltSz, id; + int ret = 0, first, second, length = 0, version, saltSz, id; int iterations = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; @@ -1868,63 +2468,65 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) byte cbcIv[MAX_IV_SIZE]; #endif - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ - if (CheckAlgo(first, second, &id, &version) < 0) - return ASN_INPUT_E; /* Algo ID error */ + if (CheckAlgo(first, second, &id, &version) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_tte); /* Algo ID error */ + } if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (oid != PBKDF2_OID) - return ASN_PARSE_E; + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) - return ASN_PARSE_E; + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_tte; - if (saltSz > MAX_SALT_SIZE) - return ASN_PARSE_E; + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } #ifdef WOLFSSL_SMALL_STACK salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (salt == NULL) - return MEMORY_E; + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_tte); + } #endif XMEMCPY(salt, &input[inOutIdx], saltSz); inOutIdx += saltSz; if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); } #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_tte); } #endif @@ -1932,89 +2534,52 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) /* get encryption algo */ /* JOHN: New type. Need a little more research. */ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); } if (CheckAlgoV2(oid, &id) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; /* PKCS v2 algo id error */ - } - - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */ } - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; if (length > MAX_IV_SIZE) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); } XMEMCPY(cbcIv, &input[inOutIdx], length); inOutIdx += length; } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; - if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id, - input + inOutIdx, length, version, cbcIv) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_INPUT_E; /* decrypt failure */ - } + ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv); +exit_tte: #ifdef WOLFSSL_SMALL_STACK XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - XMEMMOVE(input, input + inOutIdx, length); - return ToTraditional(input, length); + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = ToTraditional(input, length); + } + + return ret; } /* decrypt PKCS */ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) { word32 inOutIdx = 0, oid; - int ret; - int first, second, length, version, saltSz, id; + int ret = 0; + int first, second, length = 0, version, saltSz, id; int iterations = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; @@ -2024,60 +2589,61 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) byte cbcIv[MAX_IV_SIZE]; #endif - if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ - if (CheckAlgo(first, second, &id, &version) < 0) - return ASN_INPUT_E; /* Algo ID error */ + if (CheckAlgo(first, second, &id, &version) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */ + } if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (oid != PBKDF2_OID) - return ASN_PARSE_E; + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) - return ASN_PARSE_E; + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_dc; - if (saltSz > MAX_SALT_SIZE) - return ASN_PARSE_E; + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } #ifdef WOLFSSL_SMALL_STACK salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (salt == NULL) - return MEMORY_E; + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_dc); + } #endif XMEMCPY(salt, &input[inOutIdx], saltSz); inOutIdx += saltSz; if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_dc); } #endif @@ -2085,73 +2651,45 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) /* get encryption algo */ /* JOHN: New type. Need a little more research. */ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } if (CheckAlgoV2(oid, &id) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; /* PKCS v2 algo id error */ + ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */ } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_dc; XMEMCPY(cbcIv, &input[inOutIdx], length); inOutIdx += length; } - if (input[inOutIdx++] != ASN_LONG_LENGTH) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + if (input[inOutIdx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + ERROR_OUT(ASN_PARSE_E, exit_dc); } if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } - if ((ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, - input + inOutIdx, length, version, cbcIv)) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; /* decrypt failure */ - } + ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv); + +exit_dc: #ifdef WOLFSSL_SMALL_STACK XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - XMEMMOVE(input, input + inOutIdx, length); - return length; + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = length; + } + + return ret; } #endif /* NO_PWDBASED */ @@ -2161,11 +2699,14 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { - int length; + int length; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + byte b; +#endif + int ret; - if (input == NULL || inOutIdx == NULL || key == NULL) { + if (input == NULL || inOutIdx == NULL || key == NULL) return BAD_FUNC_ARG; - } if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -2173,8 +2714,10 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, key->type = RSA_PUBLIC; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; + if ((*inOutIdx + 1) > inSz) + return BUFFER_E; + + b = input[*inOutIdx]; if (b != ASN_INTEGER) { /* not from decoded cert, will have algo id, skip past */ if (GetSequence(input, inOutIdx, &length, inSz) < 0) @@ -2183,39 +2726,29 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (SkipObjectId(input, inOutIdx, inSz) < 0) return ASN_PARSE_E; - /* could have NULL tag and 0 terminator, but may not */ - b = input[(*inOutIdx)++]; - - if (b == ASN_TAG_NULL) { - b = input[(*inOutIdx)++]; - if (b != 0) - return ASN_EXPECT_0_E; + /* Option NULL ASN.1 tag */ + if (input[*inOutIdx] == ASN_TAG_NULL) { + ret = GetASNNull(input, inOutIdx, inSz); + if (ret != 0) + return ret; } - else - /* go back, didn't have it */ - (*inOutIdx)--; /* should have bit tag length and seq next */ - b = input[(*inOutIdx)++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - /* could have 0 */ - b = input[(*inOutIdx)++]; - if (b != 0) - (*inOutIdx)--; + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - } /* end if */ - } /* openssl var block */ + } #endif /* OPENSSL_EXTRA */ - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + if (GetInt(&key->n, input, inOutIdx, inSz) < 0) + return ASN_RSA_KEY_E; + if (GetInt(&key->e, input, inOutIdx, inSz) < 0) { + mp_clear(&key->n); + return ASN_RSA_KEY_E; + } return 0; } @@ -2263,7 +2796,9 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) return ASN_PARSE_E; if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E; + GetInt(&key->g, input, inOutIdx, inSz) < 0) { + return ASN_DH_KEY_E; + } return 0; } @@ -2272,47 +2807,37 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz) { - word32 i = 0; - byte b; + word32 idx = 0; + int ret; int length; - if (GetSequence(input, &i, &length, inSz) < 0) - return ASN_PARSE_E; - - b = input[i++]; - if (b != ASN_INTEGER) + if (GetSequence(input, &idx, &length, inSz) <= 0) return ASN_PARSE_E; - if (GetLength(input, &i, &length, inSz) < 0) - return ASN_PARSE_E; - - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*pInOutSz) { - XMEMCPY(p, &input[i], length); + XMEMCPY(p, &input[idx], length); *pInOutSz = length; } - else + else { return BUFFER_E; + } + idx += length; - i += length; - - b = input[i++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, inSz) < 0) - return ASN_PARSE_E; + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*gInOutSz) { - XMEMCPY(g, &input[i], length); + XMEMCPY(g, &input[idx], length); *gInOutSz = length; } - else + else { return BUFFER_E; + } return 0; } @@ -2396,7 +2921,7 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) { word32 seqSz, verSz, rawLen, intTotalLen = 0; word32 sizes[DSA_INTS]; - int i, j, outLen, ret = 0, lbit; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -2415,10 +2940,7 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) for (i = 0; i < DSA_INTS; i++) { mp_int* keyInt = GetDsaInt(key, i); - /* leading zero */ - lbit = mp_leading_bit(keyInt); - rawLen = mp_unsigned_bin_size(keyInt) + lbit; - + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_DSA); if (tmps[i] == NULL) { @@ -2426,30 +2948,12 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err; - - /* leading zero */ - if (lbit) - tmps[i][sizes[i]-1] = 0x00; - - err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ - intTotalLen += sizes[i]; - } - else { - ret = err; - break; - } - } - else { - ret = ASN_INPUT_E; + mpSz = SetASNIntMP(keyInt, -1, tmps[i]); + if (mpSz < 0) { + ret = mpSz; break; } + intTotalLen += (sizes[i] = mpSz); } if (ret != 0) { @@ -2488,6 +2992,7 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) cert->publicKey = 0; cert->pubKeySize = 0; cert->pubKeyStored = 0; + cert->keyOID = 0; cert->version = 0; cert->signature = 0; cert->subjectCN = 0; @@ -2560,6 +3065,10 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) #ifdef OPENSSL_EXTRA XMEMSET(&cert->issuerName, 0, sizeof(DecodedName)); XMEMSET(&cert->subjectName, 0, sizeof(DecodedName)); + cert->extCRLdistSet = 0; + cert->extCRLdistCrit = 0; + cert->extAuthInfoSet = 0; + cert->extAuthInfoCrit = 0; cert->extBasicConstSet = 0; cert->extBasicConstCrit = 0; cert->extSubjAltNameSet = 0; @@ -2598,6 +3107,9 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) XMEMSET(cert->extCertPolicies, 0, MAX_CERTPOL_NB*MAX_CERTPOL_SZ); cert->extCertPoliciesNb = 0; #endif + + cert->ca = NULL; + InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID); } @@ -2658,9 +3170,9 @@ void FreeDecodedCert(DecodedCert* cert) if (cert->subjectName.fullName != NULL) XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509); #endif /* OPENSSL_EXTRA */ + FreeSignatureCtx(&cert->sigCtx); } -#ifndef NO_ASN_TIME static int GetCertHeader(DecodedCert* cert) { int ret = 0, len; @@ -2707,9 +3219,7 @@ static int StoreRsaKey(DecodedCert* cert) return 0; } -#endif -#endif /* !NO_ASN_TIME */ - +#endif /* !NO_RSA */ #ifdef HAVE_ECC @@ -2730,7 +3240,6 @@ static int StoreRsaKey(DecodedCert* cert) #endif /* HAVE_ECC */ -#ifndef NO_ASN_TIME static int GetKey(DecodedCert* cert) { int length; @@ -2749,15 +3258,11 @@ static int GetKey(DecodedCert* cert) #ifndef NO_RSA case RSAk: { - byte b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0) - return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, NULL, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; return StoreRsaKey(cert); } @@ -2830,7 +3335,7 @@ static int GetKey(DecodedCert* cert) #ifdef HAVE_ECC case ECDSAk: { - byte b; + int ret; if (GetObjectId(cert->source, &cert->srcIdx, &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0) @@ -2840,18 +3345,10 @@ static int GetKey(DecodedCert* cert) return ECC_CURVE_OID_E; /* key header */ - b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0) - return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; - - /* actual key, use length - 1 since ate preceding 0 */ - length -= 1; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; cert->publicKey = (byte*) XMALLOC(length, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); @@ -2871,7 +3368,6 @@ static int GetKey(DecodedCert* cert) } } - /* process NAME, either issuer or subject */ static int GetName(DecodedCert* cert, int nameType) { @@ -2900,10 +3396,8 @@ static int GetName(DecodedCert* cert, int nameType) if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (SkipObjectId(cert->source, &cert->srcIdx, cert->maxIdx) < 0) return ASN_PARSE_E; - - cert->srcIdx += length; WOLFSSL_MSG("Got optional prefix"); } @@ -2949,14 +3443,15 @@ static int GetName(DecodedCert* cert, int nameType) WOLFSSL_MSG("Cert name lacks set header, trying sequence"); } - if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) + if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) <= 0) return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; + ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx); + if (ret != 0) + return ret; - if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0) + /* make sure there is room for joint */ + if ((cert->srcIdx + sizeof(joint)) > cert->maxIdx) return ASN_PARSE_E; XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint)); @@ -3351,6 +3846,7 @@ static int GetName(DecodedCert* cert, int nameType) } +#ifndef NO_ASN_TIME #if !defined(NO_TIME_H) && defined(USE_WOLF_VALIDDATE) /* to the second */ @@ -3390,7 +3886,7 @@ static INLINE int DateLessThan(const struct tm* a, const struct tm* b) } -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) int GetTimeString(byte* date, int format, char* buf, int len) { struct tm t; @@ -3432,7 +3928,7 @@ int GetTimeString(byte* date, int format, char* buf, int len) return 1; } -#endif /* MYSQL compatibility */ +#endif /* WOLFSSL_MYSQL_COMPATIBLE */ int ExtractDate(const unsigned char* date, unsigned char format, struct tm* certTime, int* idx) @@ -3483,6 +3979,21 @@ int ValidateDate(const byte* date, byte format, int dateType) #endif ltime = XTIME(0); + +#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW + if (dateType == BEFORE) { + WOLFSSL_MSG("Skewing local time for before date check"); + ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW; + } +#endif + +#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW + if (dateType == AFTER) { + WOLFSSL_MSG("Skewing local time for after date check"); + ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW; + } +#endif + if (!ExtractDate(date, format, &certTime, &i)) { WOLFSSL_MSG("Error extracting the date"); return 0; @@ -3508,12 +4019,17 @@ int ValidateDate(const byte* date, byte format, int dateType) } if (dateType == BEFORE) { - if (DateLessThan(localTime, &certTime)) + if (DateLessThan(localTime, &certTime)) { + WOLFSSL_MSG("Date BEFORE check failed"); return 0; + } } - else - if (DateGreaterThan(localTime, &certTime)) + else { /* dateType == AFTER */ + if (DateGreaterThan(localTime, &certTime)) { + WOLFSSL_MSG("Date AFTER check failed"); return 0; + } + } return 1; } @@ -3536,6 +4052,8 @@ int wc_GetTime(void* timePtr, word32 timeSize) return 0; } +#endif /* !NO_ASN_TIME */ + static int GetDate(DecodedCert* cert, int dateType) { int length; @@ -3544,6 +4062,7 @@ static int GetDate(DecodedCert* cert, int dateType) word32 startIdx = 0; XMEMSET(date, 0, MAX_DATE_SIZE); + if (dateType == BEFORE) cert->beforeDate = &cert->source[cert->srcIdx]; else @@ -3568,17 +4087,18 @@ static int GetDate(DecodedCert* cert, int dateType) else cert->afterDateLen = cert->srcIdx - startIdx; +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(date, b, dateType)) { if (dateType == BEFORE) return ASN_BEFORE_DATE_E; else return ASN_AFTER_DATE_E; } +#endif return 0; } - static int GetValidity(DecodedCert* cert, int verify) { int length; @@ -3638,39 +4158,35 @@ int DecodeToKey(DecodedCert* cert, int verify) return ret; } - static int GetSignature(DecodedCert* cert) { - int length; - byte b = cert->source[cert->srcIdx++]; - - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) - return ASN_PARSE_E; + int length; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, + NULL); + if (ret != 0) + return ret; cert->sigLength = length; - - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; - - cert->sigLength--; cert->signature = &cert->source[cert->srcIdx]; cert->srcIdx += cert->sigLength; return 0; } -#endif /* !NO_ASN_TIME */ -static word32 SetDigest(const byte* digest, word32 digSz, byte* output) +static word32 SetOctetString8Bit(word32 len, byte* output) { output[0] = ASN_OCTET_STRING; - output[1] = (byte)digSz; - XMEMCPY(&output[2], digest, digSz); + output[1] = (byte)len; + return 2; +} - return digSz + 2; +static word32 SetDigest(const byte* digest, word32 digSz, byte* output) +{ + word32 idx = SetOctetString8Bit(digSz, output); + XMEMCPY(&output[idx], digest, digSz); + + return idx + digSz; } @@ -3742,7 +4258,9 @@ WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) static int SetCurve(ecc_key* key, byte* output) { +#ifdef HAVE_OID_ENCODING int ret; +#endif int idx = 0; word32 oidSz = 0; @@ -3760,11 +4278,7 @@ static int SetCurve(ecc_key* key, byte* output) oidSz = key->dp->oidSz; #endif - output[0] = ASN_OBJECT_ID; - idx++; - - ret = SetLength(oidSz, output+idx); - idx += ret; + idx += SetObjectId(oidSz, output); #ifdef HAVE_OID_ENCODING ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz); @@ -3797,7 +4311,7 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) { word32 tagSz, idSz, seqSz, algoSz = 0; const byte* algoName = 0; - byte ID_Length[MAX_LENGTH_SZ]; + byte ID_Length[1 + MAX_LENGTH_SZ]; byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ tagSz = (type == oidHashType || @@ -3811,18 +4325,14 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) return 0; } - idSz = SetLength(algoSz, ID_Length); - seqSz = SetSequence(idSz + algoSz + 1 + tagSz + curveSz, seqArray); - /* +1 for object id, curveID of curveSz follows for ecc */ - seqArray[seqSz++] = ASN_OBJECT_ID; + idSz = SetObjectId(algoSz, ID_Length); + seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray); XMEMCPY(output, seqArray, seqSz); XMEMCPY(output + seqSz, ID_Length, idSz); XMEMCPY(output + seqSz + idSz, algoName, algoSz); - if (tagSz == 2) { - output[seqSz + idSz + algoSz] = ASN_TAG_NULL; - output[seqSz + idSz + algoSz + 1] = 0; - } + if (tagSz == 2) + SetASNNull(&output[seqSz + idSz + algoSz]); return seqSz + idSz + algoSz + tagSz; @@ -3880,280 +4390,352 @@ int wc_GetCTC_HashOID(int type) case SHA512: return SHA512h; #endif - default: - return 0; - }; + default: + return 0; + }; +} + +void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId) +{ + if (sigCtx) { + XMEMSET(sigCtx, 0, sizeof(SignatureCtx)); + sigCtx->devId = devId; + sigCtx->heap = heap; + } +} + +void FreeSignatureCtx(SignatureCtx* sigCtx) +{ + if (sigCtx == NULL) + return; + + if (sigCtx->digest) { + XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + sigCtx->digest = NULL; + } +#ifndef NO_RSA + if (sigCtx->plain) { + XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + sigCtx->plain = NULL; + } +#endif + if (sigCtx->key.ptr) { + switch (sigCtx->keyOID) { + #ifndef NO_RSA + case RSAk: + wc_FreeRsaKey(sigCtx->key.rsa); + XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA); + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + wc_ecc_free(sigCtx->key.ecc); + XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); + break; + #endif /* HAVE_ECC */ + default: + break; + } /* switch (keyOID) */ + sigCtx->key.ptr = NULL; + } + + /* reset state, we are done */ + sigCtx->state = SIG_STATE_BEGIN; } -#ifndef NO_ASN_TIME -/* return true (1) or false (0) for Confirmation */ -static int ConfirmSignature(const byte* buf, word32 bufSz, +/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ +static int ConfirmSignature(SignatureCtx* sigCtx, + const byte* buf, word32 bufSz, const byte* key, word32 keySz, word32 keyOID, - const byte* sig, word32 sigSz, word32 sigOID, - void* heap) + const byte* sig, word32 sigSz, word32 sigOID) { - int typeH = 0, digestSz = 0, ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* digest; -#else - byte digest[WC_MAX_DIGEST_SIZE]; -#endif + int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ -#endif + if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL || + keySz == 0 || sig == NULL || sigSz == 0) { + return BAD_FUNC_ARG; + } (void)key; (void)keySz; (void)sig; (void)sigSz; - (void)heap; - - switch (sigOID) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if (wc_Md5Hash(buf, bufSz, digest) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; - } - break; - #endif - #if defined(WOLFSSL_MD2) - case CTC_MD2wRSA: - if (wc_Md2Hash(buf, bufSz, digest) == 0) { - typeH = MD2h; - digestSz = MD2_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwDSA: - case CTC_SHAwECDSA: - if (wc_ShaHash(buf, bufSz, digest) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if (wc_Sha224Hash(buf, bufSz, digest) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if (wc_Sha256Hash(buf, bufSz, digest) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if (wc_Sha512Hash(buf, bufSz, digest) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if (wc_Sha384Hash(buf, bufSz, digest) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - } - break; - #endif - default: - WOLFSSL_MSG("Verify Signature has unsupported type"); - } - if (typeH == 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return 0; /* not confirmed */ - } + WOLFSSL_ENTER("ConfirmSignature"); - switch (keyOID) { - #ifndef NO_RSA - case RSAk: + switch (sigCtx->state) { + case SIG_STATE_BEGIN: { - word32 idx = 0; - int encodedSigSz, verifySz; - byte* out; -#ifdef WOLFSSL_SMALL_STACK - RsaKey* pubKey; - byte* plain; - byte* encodedSig; -#else - RsaKey pubKey[1]; - byte plain[MAX_ENCODED_SIG_SZ]; - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (pubKey == NULL || plain == NULL || encodedSig == NULL) { - WOLFSSL_MSG("Failed to allocate memory at ConfirmSignature"); + sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sigCtx->digest == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } - if (pubKey) - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (plain) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig) - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sigCtx->state = SIG_STATE_HASH; + } /* SIG_STATE_BEGIN */ + FALL_THROUGH; - break; /* not confirmed */ - } -#endif - if (wc_InitRsaKey(pubKey, heap) != 0) { - WOLFSSL_MSG("InitRsaKey failed"); - } - else if (sigSz > MAX_ENCODED_SIG_SZ) { - WOLFSSL_MSG("Verify Signature is too big"); + case SIG_STATE_HASH: + { + switch (sigOID) { + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = MD5h; + sigCtx->digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #if defined(WOLFSSL_MD2) + case CTC_MD2wRSA: + if ((ret = wc_Md2Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = MD2h; + sigCtx->digestSz = MD2_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwDSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHAh; + sigCtx->digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA224h; + sigCtx->digestSz = SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA256h; + sigCtx->digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA512h; + sigCtx->digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA384h; + sigCtx->digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + default: + ret = HASH_TYPE_E; + WOLFSSL_MSG("Verify Signature has unsupported type"); } - else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) { - WOLFSSL_MSG("ASN Key decode error RSA"); + + if (ret != 0) { + goto exit_cs; } - else { - XMEMCPY(plain, sig, sigSz); - 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); + sigCtx->state = SIG_STATE_KEY; + } /* SIG_STATE_HASH */ + FALL_THROUGH; + + case SIG_STATE_KEY: + { + sigCtx->keyOID = keyOID; + + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 idx = 0; + + sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), + sigCtx->heap, DYNAMIC_TYPE_RSA); + sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); } - } 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); - if (encodedSigSz != verifySz || - XMEMCMP(out, encodedSig, encodedSigSz) != 0) { - WOLFSSL_MSG("Rsa SSL verify match encode error"); + if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap, + sigCtx->devId)) != 0) { + goto exit_cs; } - else - ret = 1; /* match */ - #ifdef WOLFSSL_DEBUG_ENCODING - { - int x; + if (sigSz > MAX_ENCODED_SIG_SZ) { + WOLFSSL_MSG("Verify Signature is too big"); + ERROR_OUT(BUFFER_E, exit_cs); + } - printf("wolfssl encodedSig:\n"); + if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa, + keySz)) != 0) { + WOLFSSL_MSG("ASN Key decode error RSA"); + goto exit_cs; + } - for (x = 0; x < encodedSigSz; x++) { - printf("%02x ", encodedSig[x]); - if ( (x % 16) == 15) - printf("\n"); - } + XMEMCPY(sigCtx->plain, sig, sigSz); + sigCtx->out = NULL; + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + sigCtx->verify = 0; + sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), + sigCtx->heap, DYNAMIC_TYPE_ECC); + if (sigCtx->key.ecc == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } - printf("\n"); - printf("actual digest:\n"); + if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap, + sigCtx->devId)) < 0) { + goto exit_cs; + } + if ((ret = wc_ecc_import_x963(key, keySz, + sigCtx->key.ecc)) < 0) { + WOLFSSL_MSG("ASN Key import error ECC"); + goto exit_cs; + } + break; + } + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Verify Key type unknown"); + ret = ASN_UNKNOWN_OID_E; + break; + } /* switch (keyOID) */ - for (x = 0; x < verifySz; x++) { - printf("%02x ", out[x]); - if ( (x % 16) == 15) - printf("\n"); - } + if (ret != 0) { + goto exit_cs; + } - printf("\n"); - } - #endif /* WOLFSSL_DEBUG_ENCODING */ + sigCtx->state = SIG_STATE_DO; + } /* SIG_STATE_KEY */ + FALL_THROUGH; + case SIG_STATE_DO: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz, + &sigCtx->out, sigCtx->key.rsa); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev; + #endif + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest, + sigCtx->digestSz, &sigCtx->verify, sigCtx->key.ecc); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev; + #endif + break; } + #endif /* HAVE_ECC */ + default: + break; + } /* switch (keyOID) */ + if (ret < 0) { + /* treat all non async RSA errors as ASN_SIG_CONFIRM_E */ + if (ret != WC_PENDING_E) + ret = ASN_SIG_CONFIRM_E; + goto exit_cs; } - wc_FreeRsaKey(pubKey); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - break; - } + sigCtx->state = SIG_STATE_CHECK; + } /* SIG_STATE_DO */ + FALL_THROUGH; - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: + case SIG_STATE_CHECK: { - int verify = 0; -#ifdef WOLFSSL_SMALL_STACK - ecc_key* pubKey; -#else - ecc_key pubKey[1]; -#endif + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + int encodedSigSz, verifySz; + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif -#ifdef WOLFSSL_SMALL_STACK - pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (pubKey == NULL) { - WOLFSSL_MSG("Failed to allocate pubKey"); - break; /* not confirmed */ - } -#endif + verifySz = ret; - if (wc_ecc_init(pubKey) < 0) { - WOLFSSL_MSG("Failed to initialize key"); - break; /* not confirmed */ - } - if (wc_ecc_import_x963(key, keySz, pubKey) < 0) { - WOLFSSL_MSG("ASN Key import error ECC"); - } - else { - if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify, - pubKey) != 0) { - WOLFSSL_MSG("ECC verify hash error"); - } - else if (1 != verify) { - WOLFSSL_MSG("ECC Verify didn't match"); - } else - ret = 1; /* match */ + /* make sure we're right justified */ + encodedSigSz = wc_EncodeSignature(encodedSig, + sigCtx->digest, sigCtx->digestSz, sigCtx->typeH); + if (encodedSigSz == verifySz && + XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) { + ret = 0; + } + else { + WOLFSSL_MSG("RSA SSL verify match encode error"); + ret = ASN_SIG_CONFIRM_E; + } - } - wc_ecc_free(pubKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + break; + } + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ECC Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ECC */ + default: + break; + } /* switch (keyOID) */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif break; - } - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Verify Key type unknown"); - } + } /* SIG_STATE_CHECK */ + } /* switch (sigCtx->state) */ - (void)digestSz; -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +exit_cs: + + WOLFSSL_LEAVE("ConfirmSignature", ret); + + if (ret != WC_PENDING_E) { + FreeSignatureCtx(sigCtx); + } return ret; } @@ -4327,7 +4909,6 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) #endif /* IGNORE_NAME_CONSTRAINTS */ - static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; @@ -4343,7 +4924,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->weOwnAltNames = 1; while (length > 0) { - byte b = input[idx++]; + byte b = input[idx++]; length--; @@ -4384,7 +4965,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } -#ifndef IGNORE_NAME_CONSTRAINTS + #ifndef IGNORE_NAME_CONSTRAINTS else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) { DNS_entry* emailEntry; int strLen; @@ -4420,13 +5001,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } -#endif /* IGNORE_NAME_CONSTRAINTS */ -#ifdef WOLFSSL_SEP + #endif /* IGNORE_NAME_CONSTRAINTS */ + #ifdef WOLFSSL_SEP else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) { int strLen; word32 lenStartIdx = idx; word32 oid = 0; + int ret; if (GetLength(input, &idx, &strLen, sz) < 0) { WOLFSSL_MSG("\tfail: other name length"); @@ -4460,14 +5042,10 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\texpected OID"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; + ret = GetASNObjectId(input, &idx, &strLen, sz); + if (ret != 0) { + WOLFSSL_MSG("\tbad OID"); + return ret; } cert->hwType = (byte*)XMALLOC(strLen, cert->heap, @@ -4481,15 +5059,9 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->hwTypeSz = strLen; idx += strLen; - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\texpected Octet String"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; - } + ret = GetOctetString(input, &idx, &strLen, sz); + if (ret < 0) + return ret; cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_X509_EXT); @@ -4503,7 +5075,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->hwSerialNumSz = strLen; idx += strLen; } -#endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_SEP */ else { int strLen; word32 lenStartIdx = idx; @@ -4521,13 +5093,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return 0; } - static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; + int ret; WOLFSSL_ENTER("DecodeBasicCaConstraint"); + if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: bad SEQUENCE"); return ASN_PARSE_E; @@ -4539,37 +5112,23 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) /* If the basic ca constraint is false, this extension may be named, but * left empty. So, if the length is 0, just return. */ - if (input[idx++] != ASN_BOOLEAN) - { - WOLFSSL_MSG("\tfail: constraint not BOOLEAN"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) < 0) - { - WOLFSSL_MSG("\tfail: length"); - return ASN_PARSE_E; + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN"); + return ret; } - if (input[idx++]) - cert->isCA = 1; + cert->isCA = (byte)ret; /* If there isn't any more data, return. */ if (idx >= (word32)sz) return 0; - /* Anything left should be the optional pathlength */ - if (input[idx++] != ASN_INTEGER) { - WOLFSSL_MSG("\tfail: pathlen not INTEGER"); - return ASN_PARSE_E; - } - - if (input[idx++] != 1) { - WOLFSSL_MSG("\tfail: pathlen too long"); - return ASN_PATHLEN_SIZE_E; - } + ret = GetInteger7Bit(input, &idx, sz); + if (ret < 0) + return ret; - cert->pathLength = input[idx]; + cert->pathLength = (byte)ret; cert->pathLengthSet = 1; return 0; @@ -4626,9 +5185,10 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) /* This isn't a URI, skip it. */ idx += length; } - else + else { /* This isn't a FULLNAME, skip it. */ idx += length; + } } /* Check for reasonFlags */ @@ -4687,6 +5247,7 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert) if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0) return ASN_PARSE_E; + /* Only supporting URIs right now. */ b = input[idx++]; if (GetLength(input, &idx, &length, sz) < 0) @@ -4723,15 +5284,15 @@ static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert) return 0; } - if (GetLength(input, &idx, &length, sz) < 0) { + if (GetLength(input, &idx, &length, sz) <= 0) { WOLFSSL_MSG("\tfail: extension data length"); return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extAuthKeyIdSrc = &input[idx]; - cert->extAuthKeyIdSz = length; - #endif /* OPENSSL_EXTRA */ +#ifdef OPENSSL_EXTRA + cert->extAuthKeyIdSrc = &input[idx]; + cert->extAuthKeyIdSz = length; +#endif /* OPENSSL_EXTRA */ if (length == KEYID_SIZE) { XMEMCPY(cert->extAuthKeyId, input + idx, length); @@ -4755,15 +5316,12 @@ static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert) WOLFSSL_ENTER("DecodeSubjKeyId"); - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + if (sz <= 0) return ASN_PARSE_E; - } - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; #ifdef OPENSSL_EXTRA cert->extSubjKeyIdSrc = &input[idx]; @@ -4789,20 +5347,12 @@ static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length; - WOLFSSL_ENTER("DecodeKeyUsage"); - - if (input[idx++] != ASN_BIT_STRING) { - WOLFSSL_MSG("\tfail: key usage expected bit string"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: key usage bad length"); - return ASN_PARSE_E; - } + int ret; + WOLFSSL_ENTER("DecodeKeyUsage"); - /* pass the unusedBits value */ - idx++; length--; + ret = CheckBitString(input, &idx, &length, sz, 0, NULL); + if (ret != 0) + return ret; cert->extKeyUsage = (word16)(input[idx]); if (length == 2) @@ -4824,10 +5374,10 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageSrc = input + idx; - cert->extExtKeyUsageSz = length; - #endif +#ifdef OPENSSL_EXTRA + cert->extExtKeyUsageSrc = input + idx; + cert->extExtKeyUsageSz = length; +#endif while (idx < (word32)sz) { if (GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz) < 0) @@ -4848,9 +5398,9 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) break; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageCount++; - #endif + #ifdef OPENSSL_EXTRA + cert->extExtKeyUsageCount++; + #endif } return 0; @@ -4953,7 +5503,7 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) return 0; } #endif /* IGNORE_NAME_CONSTRAINTS */ -#endif /* NO_ASN_TIME */ + #if defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP) @@ -5047,7 +5597,13 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; + word32 oldIdx; + int ret; int total_length = 0, policy_length = 0, length = 0; + #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \ + !defined(WOLFSSL_DUP_CERTPOL) + int i; + #endif WOLFSSL_ENTER("DecodeCertPolicy"); @@ -5069,17 +5625,11 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) return ASN_PARSE_E; } - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\tCertPolicy isn't OID"); - return ASN_PARSE_E; - } - policy_length--; - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tGet CertPolicy length failed"); - return ASN_PARSE_E; - } - policy_length--; + oldIdx = idx; + ret = GetASNObjectId(input, &idx, &length, sz); + if (ret != 0) + return ret; + policy_length -= idx - oldIdx; if (length > 0) { /* Verify length won't overrun buffer */ @@ -5105,6 +5655,22 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) WOLFSSL_MSG("\tCouldn't decode CertPolicy"); return ASN_PARSE_E; } + #ifndef WOLFSSL_DUP_CERTPOL + /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST + * NOT appear more than once in a certificate policies + * extension". This is a sanity check for duplicates. + * extCertPolicies should only have OID values, additional + * qualifiers need to be stored in a seperate array. */ + for (i = 0; i < cert->extCertPoliciesNb; i++) { + if (XMEMCMP(cert->extCertPolicies[i], + cert->extCertPolicies[cert->extCertPoliciesNb], + MAX_CERTPOL_SZ) == 0) { + WOLFSSL_MSG("Duplicate policy OIDs not allowed"); + WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted"); + return CERTPOLICIES_E; + } + } + #endif /* !defined(WOLFSSL_DUP_CERTPOL) */ cert->extCertPoliciesNb++; #else WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0); @@ -5123,7 +5689,6 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) } #endif /* WOLFSSL_SEP */ -#ifndef NO_ASN_TIME static int DecodeCertExtensions(DecodedCert* cert) /* * Processing the Certificate Extensions. This does not modify the current @@ -5174,25 +5739,20 @@ static int DecodeCertExtensions(DecodedCert* cert) /* check for critical flag */ critical = 0; if (input[idx] == ASN_BOOLEAN) { - int boolLength = 0; - idx++; - if (GetLength(input, &idx, &boolLength, sz) < 0) { - WOLFSSL_MSG("\tfail: critical boolean length"); - return ASN_PARSE_E; + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: critical boolean"); + return ret; } - if (input[idx++]) - critical = 1; - } - /* process the extension based on the OID */ - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; + critical = (byte)ret; } - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; + /* process the extension based on the OID */ + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: bad OCTET STRING"); + return ret; } switch (oid) { @@ -5206,11 +5766,19 @@ static int DecodeCertExtensions(DecodedCert* cert) break; case CRL_DIST_OID: + #ifdef OPENSSL_EXTRA + cert->extCRLdistSet = 1; + cert->extCRLdistCrit = critical; + #endif if (DecodeCrlDist(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; case AUTH_INFO_OID: + #ifdef OPENSSL_EXTRA + cert->extAuthInfoSet = 1; + cert->extAuthInfoCrit = critical; + #endif if (DecodeAuthInfo(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; @@ -5238,6 +5806,18 @@ static int DecodeCertExtensions(DecodedCert* cert) #ifdef OPENSSL_EXTRA cert->extSubjKeyIdCrit = critical; #endif + #ifndef WOLFSSL_ALLOW_CRIT_SKID + /* This check is added due to RFC 5280 section 4.2.1.2 + * stating that conforming CA's must mark this extension + * as non-critical. When parsing extensions check that + * certificate was made in compliance with this. */ + if (critical) { + WOLFSSL_MSG("Critical Subject Key ID is not allowed"); + WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted"); + return ASN_CRIT_EXT_E; + } + #endif + if (DecodeSubjKeyId(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; @@ -5306,7 +5886,6 @@ static int DecodeCertExtensions(DecodedCert* cert) return criticalFail ? ASN_CRIT_EXT_E : 0; } - int ParseCert(DecodedCert* cert, int type, int verify, void* cm) { int ret; @@ -5340,8 +5919,6 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } -#endif /* !NO_ASN_TIME */ - /* from SSL proper, for locking can't do find here anymore */ #ifdef __cplusplus @@ -5377,130 +5954,143 @@ Signer* GetCAByName(void* signers, byte* hash) #endif /* WOLFCRYPT_ONLY || NO_CERTS */ -#ifndef NO_ASN_TIME int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) { - word32 confirmOID; - int ret; - int badDate = 0; + int ret = 0; + int badDate = 0; int criticalExt = 0; + word32 confirmOID; - if ((ret = DecodeToKey(cert, verify)) < 0) { - if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) - badDate = ret; - else - return ret; + if (cert == NULL) { + return BAD_FUNC_ARG; } - WOLFSSL_MSG("Parsed Past Key"); + if (cert->sigCtx.state == SIG_STATE_BEGIN) { + if ((ret = DecodeToKey(cert, verify)) < 0) { + if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) + badDate = ret; + else + return ret; + } + + WOLFSSL_MSG("Parsed Past Key"); - if (cert->srcIdx < cert->sigIndex) { + if (cert->srcIdx < cert->sigIndex) { #ifndef ALLOW_V1_EXTENSIONS if (cert->version < 2) { - WOLFSSL_MSG(" v1 and v2 certs not allowed extensions"); + WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions"); return ASN_VERSION_E; } #endif - /* save extensions */ - cert->extensions = &cert->source[cert->srcIdx]; - cert->extensionsSz = cert->sigIndex - cert->srcIdx; - cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - - if ((ret = DecodeCertExtensions(cert)) < 0) { - if (ret == ASN_CRIT_EXT_E) - criticalExt = ret; - else - return ret; - } - /* advance past extensions */ - cert->srcIdx = cert->sigIndex; - } + /* save extensions */ + cert->extensions = &cert->source[cert->srcIdx]; + cert->extensionsSz = cert->sigIndex - cert->srcIdx; + cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, - oidSigType, cert->maxIdx)) < 0) - return ret; + if ((ret = DecodeCertExtensions(cert)) < 0) { + if (ret == ASN_CRIT_EXT_E) + criticalExt = ret; + else + return ret; + } - if ((ret = GetSignature(cert)) < 0) - return ret; + /* advance past extensions */ + cert->srcIdx = cert->sigIndex; + } + + if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, + oidSigType, cert->maxIdx)) < 0) + return ret; + + if ((ret = GetSignature(cert)) < 0) + return ret; - if (confirmOID != cert->signatureOID) - return ASN_SIG_OID_E; + if (confirmOID != cert->signatureOID) + return ASN_SIG_OID_E; #ifndef NO_SKID - if (cert->extSubjKeyIdSet == 0 - && cert->publicKey != NULL && cert->pubKeySize > 0) { + if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL && + cert->pubKeySize > 0) { #ifdef NO_SHA ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); #else ret = wc_ShaHash(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); - #endif + #endif /* NO_SHA */ if (ret != 0) return ret; } - #endif + #endif /* !NO_SKID */ - if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { - Signer* ca = NULL; + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + cert->ca = NULL; #ifndef NO_SKID if (cert->extAuthKeyIdSet) - ca = GetCA(cm, cert->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(cm, cert->issuerHash); - #else /* NO_SKID */ - ca = GetCA(cm, cert->issuerHash); - #endif /* NO SKID */ - WOLFSSL_MSG("About to verify certificate signature"); - - if (ca) { - if (cert->isCA) { - if (ca->pathLengthSet) { - if (ca->pathLength == 0) { - WOLFSSL_MSG("CA with path length 0 signing a CA"); - return ASN_PATHLEN_INV_E; - } - if (cert->pathLengthSet && - cert->pathLength >= ca->pathLength) { + cert->ca = GetCA(cm, cert->extAuthKeyId); + if (cert->ca == NULL) + cert->ca = GetCAByName(cm, cert->issuerHash); + #else + cert->ca = GetCA(cm, cert->issuerHash); + #endif /* !NO_SKID */ + + WOLFSSL_MSG("About to verify certificate signature"); + if (cert->ca) { + if (cert->isCA) { + if (cert->ca->pathLengthSet) { + if (cert->ca->pathLength == 0) { + WOLFSSL_MSG("CA with path length 0 signing a CA"); + return ASN_PATHLEN_INV_E; + } + if (cert->pathLengthSet && + cert->pathLength >= cert->ca->pathLength) { - WOLFSSL_MSG("CA signing CA with longer path length"); - return ASN_PATHLEN_INV_E; + WOLFSSL_MSG("CA signing CA with longer path length"); + return ASN_PATHLEN_INV_E; + } } } - } -#ifdef HAVE_OCSP - /* Need the ca's public key hash for OCSP */ - #ifdef NO_SHA - ret = wc_Sha256Hash(ca->publicKey, ca->pubKeySize, - cert->issuerKeyHash); - #else /* NO_SHA */ - ret = wc_ShaHash(ca->publicKey, ca->pubKeySize, - cert->issuerKeyHash); - #endif /* NO_SHA */ - if (ret != 0) - return ret; -#endif /* HAVE_OCSP */ + #ifdef HAVE_OCSP + /* Need the CA's public key hash for OCSP */ + #ifdef NO_SHA + ret = wc_Sha256Hash(cert->ca->publicKey, cert->ca->pubKeySize, + cert->issuerKeyHash); + #else + ret = wc_ShaHash(cert->ca->publicKey, cert->ca->pubKeySize, + cert->issuerKeyHash); + #endif /* NO_SHA */ + if (ret != 0) + return ret; + #endif /* HAVE_OCSP */ + } + } + } + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + if (cert->ca) { if (verify == VERIFY) { /* try to confirm/verify signature */ - if (!ConfirmSignature(cert->source + cert->certBegin, - cert->sigIndex - cert->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - cert->signature, cert->sigLength, cert->signatureOID, - cert->heap)) { - WOLFSSL_MSG("Confirm signature failed"); - return ASN_SIG_CONFIRM_E; + if ((ret = ConfirmSignature(&cert->sigCtx, + cert->source + cert->certBegin, + cert->sigIndex - cert->certBegin, + cert->ca->publicKey, cert->ca->pubKeySize, + cert->ca->keyOID, cert->signature, + cert->sigLength, cert->signatureOID)) != 0) { + if (ret != WC_PENDING_E) { + WOLFSSL_MSG("Confirm signature failed"); + } + return ret; } - #ifndef IGNORE_NAME_CONSTRAINTS + #ifndef IGNORE_NAME_CONSTRAINTS /* check that this cert's name is permitted by the signer's * name constraints */ - if (!ConfirmNameConstraints(ca, cert)) { + if (!ConfirmNameConstraints(cert->ca, cert)) { WOLFSSL_MSG("Confirm name constraint failed"); return ASN_NAME_INVALID_E; } - #endif /* IGNORE_NAME_CONSTRAINTS */ + #endif /* IGNORE_NAME_CONSTRAINTS */ } } else { @@ -5516,9 +6106,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (criticalExt != 0) return criticalExt; - return 0; + return ret; } -#endif /* !NO_ASN_TIME */ /* Create and init an new signer */ Signer* MakeSigner(void* heap) @@ -5630,7 +6219,7 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) if (header) { output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; - output[i++] = ASN_BIT_STRING; + output[i++] = 3; } output[i++] = ASN_INTEGER; output[i++] = 0x01; @@ -5673,7 +6262,7 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, byte* serial, int* serialSz, word32 maxIdx) { int result = 0; - byte b; + int ret; WOLFSSL_ENTER("GetSerialNumber"); @@ -5686,42 +6275,19 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, WOLFSSL_MSG("Bad idx first"); return BUFFER_E; } - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_INTEGER) { - WOLFSSL_MSG("Expecting Integer"); - return ASN_PARSE_E; - } - if (GetLength(input, inOutIdx, serialSz, maxIdx) < 0) { - return ASN_PARSE_E; - } + ret = GetASNInt(input, inOutIdx, serialSz, maxIdx); + if (ret != 0) + return ret; - /* serial size check */ - if (*serialSz < 0 || *serialSz > EXTERNAL_SERIAL_SIZE) { + if (*serialSz > EXTERNAL_SERIAL_SIZE) { WOLFSSL_MSG("Serial size bad"); return ASN_PARSE_E; } - /* serial size check against max index */ - if ((*inOutIdx + *serialSz) > maxIdx) { - WOLFSSL_MSG("Bad idx serial"); - return BUFFER_E; - } - - /* only check padding and return serial if length is greater than 1 */ - if (*serialSz > 0) { - /* skip padding */ - if (input[*inOutIdx] == 0x00) { - *serialSz -= 1; - *inOutIdx += 1; - } - - /* return serial */ - XMEMCPY(serial, &input[*inOutIdx], *serialSz); - *inOutIdx += *serialSz; - } + /* return serial */ + XMEMCPY(serial, &input[*inOutIdx], *serialSz); + *inOutIdx += *serialSz; return result; } @@ -5734,6 +6300,8 @@ const char* BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----"; const char* END_CERT_REQ = "-----END CERTIFICATE REQUEST-----"; const char* BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----"; const char* END_DH_PARAM = "-----END DH PARAMETERS-----"; +const char* BEGIN_DSA_PARAM = "-----BEGIN DSA PARAMETERS-----"; +const char* END_DSA_PARAM = "-----END DSA PARAMETERS-----"; const char* BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; const char* END_X509_CRL = "-----END X509 CRL-----"; const char* BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----"; @@ -5749,7 +6317,7 @@ const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) /* Used for compatibility API */ int wc_DerToPem(const byte* der, word32 derSz, @@ -5853,15 +6421,33 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, /* extra header information for encrypted key */ if (cipher_info != NULL) { + size_t cipherInfoStrLen = XSTRLEN((char*)cipher_info); + if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (23+10+2)) + cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (23+10+2); + XSTRNCAT(header, "Proc-Type: 4,ENCRYPTED\n", 23); XSTRNCAT(header, "DEK-Info: ", 10); - XSTRNCAT(header, (char*)cipher_info, XSTRLEN((char*)cipher_info)); + XSTRNCAT(header, (char*)cipher_info, cipherInfoStrLen); XSTRNCAT(header, "\n\n", 2); } headerLen = (int)XSTRLEN(header); footerLen = (int)XSTRLEN(footer); + /* if null output and 0 size passed in then return size needed */ + if (!output && outSz == 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + outLen = 0; + if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen)) + != LENGTH_ONLY_E) { + return err; + } + return headerLen + footerLen + outLen; + } + if (!der || !output) { #ifdef WOLFSSL_SMALL_STACK XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -5930,15 +6516,12 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, byte e[MAX_RSA_E_SZ]; #endif byte seq[MAX_SEQ_SZ]; - byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + byte bitString[1 + MAX_LENGTH_SZ + 1]; int nSz; int eSz; int seqSz; - int lenSz; + int bitStringSz; int idx; - int rawLen; - int leadingBit; - int err; if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) return BAD_FUNC_ARG; @@ -5951,37 +6534,15 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, #endif #ifdef HAVE_USER_RSA - leadingBit = wc_Rsa_leading_bit(key->n); - rawLen = wc_Rsa_unsigned_bin_size(key->n) + leadingBit; -#else - leadingBit = mp_leading_bit(&key->n); - rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; -#endif - n[0] = ASN_INTEGER; - nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ - - if ( (nSz + rawLen) <= MAX_RSA_INT_SZ) { - if (leadingBit) - n[nSz] = 0; -#ifdef HAVE_USER_RSA - err = wc_Rsa_to_unsigned_bin(key->n, n + nSz, rawLen); + nSz = SetASNIntRSA(key->n, n); #else - err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); -#endif - if (err == MP_OKAY) - nSz += rawLen; - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n); #endif - return MP_TO_E; - } - } - else { + if (nSz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + return nSz; } /* e */ @@ -5996,39 +6557,16 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, #endif #ifdef HAVE_USER_RSA - leadingBit = wc_Rsa_leading_bit(key->e); - rawLen = wc_Rsa_unsigned_bin_size(key->e) + leadingBit; -#else - leadingBit = mp_leading_bit(&key->e); - rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; -#endif - e[0] = ASN_INTEGER; - eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ - - if ( (eSz + rawLen) < MAX_RSA_E_SZ) { - if (leadingBit) - e[eSz] = 0; -#ifdef HAVE_USER_RSA - err = wc_Rsa_to_unsigned_bin(key->e, e + eSz, rawLen); + eSz = SetASNIntRSA(key->e, e); #else - err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); -#endif - if (err == MP_OKAY) - eSz += rawLen; - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e); #endif - return MP_TO_E; - } - } - else { + if (eSz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + return eSz; } seqSz = SetSequence(nSz + eSz, seq); @@ -6058,14 +6596,12 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, byte algo[MAX_ALGO_SZ]; #endif algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0); - lenSz = SetLength(seqSz + nSz + eSz + 1, len); - len[lenSz++] = 0; /* trailing 0 */ + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); - /* write, 1 is for ASN_BIT_STRING */ - idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output); /* check output size */ - if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6079,10 +6615,8 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, XMEMCPY(output + idx, algo, algoSz); idx += algoSz; /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; #ifdef WOLFSSL_SMALL_STACK XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -6107,8 +6641,8 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, return idx; } -#endif /* !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || - defined(WOLFSSL_KEY_GEN)) */ +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) @@ -6155,7 +6689,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) { word32 seqSz, verSz, rawLen, intTotalLen = 0; word32 sizes[RSA_INTS]; - int i, j, outLen, ret = 0, lbit; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -6174,10 +6708,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) for (i = 0; i < RSA_INTS; i++) { mp_int* keyInt = GetRsaInt(key, i); - /* leading zero */ - lbit = mp_leading_bit(keyInt); - rawLen = mp_unsigned_bin_size(keyInt) + lbit; - + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_RSA); if (tmps[i] == NULL) { @@ -6185,30 +6716,12 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err; - - /* leading zero */ - if (lbit) - tmps[i][sizes[i]-1] = 0x00; - - err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ - intTotalLen += sizes[i]; - } - else { - ret = err; - break; - } - } - else { - ret = ASN_INPUT_E; + mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]); + if (mpSz < 0) { + ret = mpSz; break; } + intTotalLen += (sizes[i] = mpSz); } if (ret != 0) { @@ -6247,23 +6760,11 @@ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) return SetRsaPublicKey(output, key, inLen, 1); } -#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ +#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA */ #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - /* Initialize and Set Certificate defaults: version = 3 (0x2) serial = 0 @@ -6421,10 +6922,10 @@ static int SetSerial(const byte* serial, byte* output) /* Write a public ECC key to output */ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) { - byte len[MAX_LENGTH_SZ + TRAILING_ZERO]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; int algoSz; int curveSz; - int lenSz; + int bitStringSz; int idx; word32 pubSz = ECC_BUFSIZE; #ifdef WOLFSSL_SMALL_STACK @@ -6479,11 +6980,9 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) #endif algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz); - lenSz = SetLength(pubSz + TRAILING_ZERO, len); - len[lenSz++] = 0; /* trailing 0 */ + bitStringSz = SetBitString(pubSz, 0, bitString); - /* write, 1 is for ASN_BIT_STRING */ - idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output); + idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output); /* algo */ XMEMCPY(output + idx, algo, algoSz); idx += algoSz; @@ -6491,10 +6990,8 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) XMEMCPY(output + idx, curve, curveSz); idx += curveSz; /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; } else idx = 0; @@ -6897,7 +7394,7 @@ static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, /* sequence, + 1 => byte to put value size */ idx = SetSequence(inSz + oidSz + 1, out); - if (outSz < idx + inSz + oidSz + 1) + if ((idx + inSz + oidSz + 1) > outSz) return BUFFER_E; XMEMCPY(out+idx, oid, oidSz); @@ -6910,9 +7407,9 @@ static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, /* encode Subject Key Identifier, return total bytes written * RFC5280 : non-critical */ -static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) +static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length) { - byte skid_len[MAX_LENGTH_SZ]; + byte skid_len[1 + MAX_LENGTH_SZ]; byte skid_enc_len[MAX_LENGTH_SZ]; int idx = 0, skid_lenSz, skid_enc_lenSz; static const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 }; @@ -6920,20 +7417,19 @@ static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) if (output == NULL || input == NULL) return BAD_FUNC_ARG; - /* length of value */ - skid_lenSz = SetLength(length, skid_len); + /* Octet String header */ + skid_lenSz = SetOctetString(length, skid_len); /* length of encoded value */ - skid_enc_lenSz = SetLength(length + skid_lenSz + 1, skid_enc_len); + skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len); if (outSz < 3) return BUFFER_E; - /* sequence, + 1 => byte to put type size */ - idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz+1, + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz, output); - if (outSz < length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz + 1) + if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz) return BUFFER_E; /* put oid */ @@ -6944,10 +7440,7 @@ static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz); idx += skid_enc_lenSz; - /* put type */ - output[idx++] = ASN_OCTET_STRING; - - /* put value len */ + /* put octet header */ XMEMCPY(output+idx, skid_len, skid_lenSz); idx += skid_lenSz; @@ -6965,27 +7458,26 @@ static int SetAKID(byte* output, word32 outSz, { byte *enc_val; int ret, enc_valSz; - static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04}; + static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 }; static const byte akid_cs[] = { 0x80 }; if (output == NULL || input == NULL) return BAD_FUNC_ARG; - enc_val = (byte *)XMALLOC(length+3+sizeof(akid_cs), heap, - DYNAMIC_TYPE_TMP_BUFFER); + enc_valSz = length + 3 + sizeof(akid_cs); + enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (enc_val == NULL) return MEMORY_E; /* sequence for ContentSpec & value */ - enc_valSz = SetOidValue(enc_val, length+3+sizeof(akid_cs), - akid_cs, sizeof(akid_cs), input, length); - if (enc_valSz == 0) { - XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; - } + ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs), + input, length); + if (ret > 0) { + enc_valSz = ret; - ret = SetOidValue(output, outSz, akid_oid, - sizeof(akid_oid), enc_val, enc_valSz); + ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid), + enc_val, enc_valSz); + } XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; @@ -6996,42 +7488,16 @@ static int SetAKID(byte* output, word32 outSz, static int SetKeyUsage(byte* output, word32 outSz, word16 input) { byte ku[5]; - int unusedBits = 0; + int idx; static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04}; if (output == NULL) return BAD_FUNC_ARG; - /* Key Usage is a BitString */ - ku[0] = ASN_BIT_STRING; - - /* put the Bit String size */ - if (input > 255) { - ku[1] = (byte)3; - - /* compute unused bits */ - while (((((input >> 8) & 0xff) >> unusedBits) & 0x01) == 0) - unusedBits++; - } - else { - ku[1] = (byte)2; - - /* compute unused bits */ - while (((input >> unusedBits) & 0x01) == 0) - unusedBits++; - } - - /* put unused bits value */ - ku[2] = (byte)unusedBits; - - /* compute byte value */ - ku[3] = (byte)(input & 0xff); - if (input > 255) - ku[4] = (byte)((input >> 8) & 0xff); - + idx = SetBitString16Bit(input, ku); return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid), - ku, (int)ku[1]+2); + ku, idx); } /* Encode OID string representation to ITU-T X.690 format */ @@ -7217,7 +7683,7 @@ int SetName(byte* output, word32 outputSz, CertName* name) const char* nameStr = GetOneName(name, i); if (nameStr) { /* bottom up */ - byte firstLen[MAX_LENGTH_SZ]; + byte firstLen[1 + MAX_LENGTH_SZ]; byte secondLen[MAX_LENGTH_SZ]; byte sequence[MAX_SEQ_SZ]; byte set[MAX_SET_SZ]; @@ -7245,16 +7711,15 @@ int SetName(byte* output, word32 outputSz, CertName* name) if (email) { thisLen += EMAIL_JOINT_LEN; thisLen ++; /* id type */ - firstSz = SetLength(EMAIL_JOINT_LEN, firstLen); + firstSz = SetObjectId(EMAIL_JOINT_LEN, firstLen); } else { thisLen++; /* str type */ thisLen++; /* id type */ thisLen += JOINT_LEN; - firstSz = SetLength(JOINT_LEN + 1, firstLen); + firstSz = SetObjectId(JOINT_LEN + 1, firstLen); } thisLen += firstSz; - thisLen++; /* object id */ seqSz = SetSequence(thisLen, sequence); thisLen += seqSz; @@ -7277,8 +7742,6 @@ int SetName(byte* output, word32 outputSz, CertName* name) XMEMCPY(names[i].encoded + idx, sequence, seqSz); idx += seqSz; /* asn object id */ - names[i].encoded[idx++] = ASN_OBJECT_ID; - /* first length */ XMEMCPY(names[i].encoded + idx, firstLen, firstSz); idx += firstSz; if (email) { @@ -7480,6 +7943,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (cert->skidSz > (int)sizeof(der->skid)) return SKID_E; + /* Note: different skid buffers sizes for der (MAX_KID_SZ) and + cert (CTC_MAX_SKID_SIZE). */ der->skidSz = SetSKID(der->skid, sizeof(der->skid), cert->skid, cert->skidSz); if (der->skidSz <= 0) @@ -7651,28 +8116,14 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ -static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, - RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - int sigAlgoType) +static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, + int sigAlgoType, void* heap) { - int encSigSz, digestSz, typeH = 0, ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* digest; -#else - byte digest[WC_MAX_DIGEST_SIZE]; /* max size */ -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* encSig; -#else - byte encSig[MAX_DER_DIGEST_SZ]; -#endif + int digestSz = 0, typeH = 0, ret = 0; - (void)digest; (void)digestSz; - (void)encSig; - (void)encSigSz; (void)typeH; - (void)buffer; (void)sz; (void)sig; @@ -7681,119 +8132,141 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, (void)eccKey; (void)rng; -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ -#endif + switch (certSignCtx->state) { + case CERTSIGN_STATE_BEGIN: + case CERTSIGN_STATE_DIGEST: - switch (sigAlgoType) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; + certSignCtx->state = CERTSIGN_STATE_DIGEST; + certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->digest == NULL) { + ret = MEMORY_E; goto exit_ms; } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + + switch (sigAlgoType) { + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = MD5h; + digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHAh; + digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA224h; + digestSz = SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + default: + WOLFSSL_MSG("MakeSignautre called with unsupported type"); + ret = ALGO_ID_E; } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buffer, sz, digest)) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; + + /* set next state, since WC_PENDING rentry for these are not "call again" */ + certSignCtx->state = CERTSIGN_STATE_ENCODE; + if (ret != 0) { + goto exit_ms; } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buffer, sz, digest)) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; + FALL_THROUGH; + + case CERTSIGN_STATE_ENCODE: + #ifndef NO_RSA + if (rsaKey) { + certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->encSig == NULL) { + ret = MEMORY_E; goto exit_ms; + } + + /* signature */ + certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig, + certSignCtx->digest, digestSz, typeH); } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buffer, sz, digest)) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; + #endif /* !NO_RSA */ + FALL_THROUGH; + + case CERTSIGN_STATE_DO: + certSignCtx->state = CERTSIGN_STATE_DO; + ret = ALGO_ID_E; /* default to error */ + + #ifndef NO_RSA + if (rsaKey) { + /* signature */ + ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz, + sig, sigSz, rsaKey, rng); } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buffer, sz, digest)) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; + #endif /* !NO_RSA */ + + #ifdef HAVE_ECC + if (!rsaKey && eccKey) { + word32 outSz = sigSz; + + ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz, + sig, &outSz, rng, eccKey); + if (ret == 0) + ret = outSz; } + #endif /* HAVE_ECC */ break; - #endif - default: - WOLFSSL_MSG("MakeSignautre called with unsupported type"); - ret = ALGO_ID_E; } - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } +exit_ms: -#ifdef WOLFSSL_SMALL_STACK - encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encSig == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + if (ret == WC_PENDING_E) { + return ret; } -#endif - - ret = ALGO_ID_E; #ifndef NO_RSA if (rsaKey) { - /* signature */ - encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH); - 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); + XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER); } -#endif - -#ifdef HAVE_ECC - if (!rsaKey && eccKey) { - word32 outSz = sigSz; - ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey); +#endif /* !NO_RSA */ - if (ret == 0) - ret = outSz; - } -#endif + XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->digest = NULL; -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* reset state */ + certSignCtx->state = CERTSIGN_STATE_BEGIN; return ret; } @@ -7810,10 +8283,7 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, /* algo */ idx += SetAlgoID(sigAlgoType, buffer + idx, oidSigType, 0); /* bit string */ - buffer[idx++] = ASN_BIT_STRING; - /* length */ - idx += SetLength(sigSz + 1, buffer + idx); - buffer[idx++] = 0; /* trailing 0 */ + idx += SetBitString(sigSz, 0, buffer + idx); /* signature */ XMEMCPY(buffer + idx, sig, sigSz); idx += sigSz; @@ -8122,7 +8592,7 @@ static int WriteCertReqBody(DerCert* der, byte* buffer) /* extensions */ if (der->extensionsSz) { XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, - sizeof(der->extensions))); + (int)sizeof(der->extensions))); idx += der->extensionsSz; } @@ -8170,35 +8640,59 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { - int sigSz; -#ifdef WOLFSSL_SMALL_STACK - byte* sig; -#else - byte sig[MAX_ENCODED_SIG_SZ]; + int sigSz = 0; + void* heap = NULL; + CertSignCtx* certSignCtx = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + CertSignCtx certSignCtx_lcl; + certSignCtx = &certSignCtx_lcl; + XMEMSET(certSignCtx, 0, sizeof(CertSignCtx)); #endif if (requestSz < 0) return requestSz; -#ifdef WOLFSSL_SMALL_STACK - sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sig == NULL) - return MEMORY_E; + /* locate ctx */ + if (rsaKey) { + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &rsaKey->certSignCtx; + #endif + heap = rsaKey->heap; + } + else if (eccKey) { + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &eccKey->certSignCtx; + #endif + heap = eccKey->heap; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + if (certSignCtx == NULL) { + return BAD_FUNC_ARG; + } #endif - sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey, - eccKey, rng, sType); + if (certSignCtx->sig == NULL) { + certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->sig == NULL) + return MEMORY_E; + } + + sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig, + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, rng, sType, heap); + if (sigSz == WC_PENDING_E) + return sigSz; if (sigSz >= 0) { if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) sigSz = BUFFER_E; else - sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType); + sigSz = AddSignature(buffer, requestSz, certSignCtx->sig, sigSz, sType); } -#ifdef WOLFSSL_SMALL_STACK - XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->sig = NULL; return sigSz; } @@ -8436,22 +8930,31 @@ int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) #endif /* decode certificate and get SKID that will be AKID of current cert */ - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } /* Subject Key Id not found !! */ if (decoded->extSubjKeyIdSet == 0) { FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ASN_NO_SKID; } /* SKID invalid size */ if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return MEMORY_E; } @@ -8460,6 +8963,10 @@ int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) cert->akidSz = KEYID_SIZE; FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; } @@ -8500,6 +9007,7 @@ int wc_SetAuthKeyId(Cert *cert, const char* file) /* Set KeyUsage from human readable string */ int wc_SetKeyUsage(Cert *cert, const char *value) { + int ret = 0; char *token, *str, *ptr; word32 len; @@ -8541,14 +9049,16 @@ int wc_SetKeyUsage(Cert *cert, const char *value) cert->keyUsage |= KEYUSE_ENCIPHER_ONLY; else if (!XSTRNCASECMP(token, "decipherOnly", len)) cert->keyUsage |= KEYUSE_DECIPHER_ONLY; - else - return KEYUSAGE_E; + else { + ret = KEYUSAGE_E; + break; + } token = XSTRTOK(NULL, ",", &ptr); } XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; + return ret; } #endif /* WOLFSSL_CERT_EXT */ @@ -8575,7 +9085,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8671,7 +9181,7 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8727,7 +9237,7 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8906,8 +9416,8 @@ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz) int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) { word32 idx = 0; - word32 rSz; /* encoding size */ - word32 sSz; + int rSz; /* encoding size */ + int sSz; word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ /* If the leading bit on the INTEGER is a 1, add a leading zero */ @@ -8915,33 +9425,24 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) int sLeadingZero = mp_leading_bit(s); int rLen = mp_unsigned_bin_size(r); /* big int size */ int sLen = mp_unsigned_bin_size(s); - int err; if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */ - return BAD_FUNC_ARG; + return BUFFER_E; - idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out); + idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out); /* store r */ - out[idx++] = ASN_INTEGER; - rSz = SetLength(rLen + rLeadingZero, &out[idx]); + rSz = SetASNIntMP(r, -1, &out[idx]); + if (rSz < 0) + return rSz; idx += rSz; - if (rLeadingZero) - out[idx++] = 0; - err = mp_to_unsigned_bin(r, &out[idx]); - if (err != MP_OKAY) return err; - idx += rLen; /* store s */ - out[idx++] = ASN_INTEGER; - sSz = SetLength(sLen + sLeadingZero, &out[idx]); + sSz = SetASNIntMP(s, -1, &out[idx]); + if (sSz < 0) + return sSz; idx += sSz; - if (sLeadingZero) - out[idx++] = 0; - err = mp_to_unsigned_bin(s, &out[idx]); - if (err != MP_OKAY) return err; - idx += sLen; *outLen = idx; @@ -8955,17 +9456,21 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) word32 idx = 0; int len = 0; - if (GetSequence(sig, &idx, &len, sigLen) < 0) + if (GetSequence(sig, &idx, &len, sigLen) < 0) { return ASN_ECC_KEY_E; + } - if ((word32)len > (sigLen - idx)) + if ((word32)len > (sigLen - idx)) { return ASN_ECC_KEY_E; + } - if (GetInt(r, sig, &idx, sigLen) < 0) + if (GetInt(r, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; + } - if (GetInt(s, sig, &idx, sigLen) < 0) + if (GetInt(s, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; + } return 0; } @@ -8974,9 +9479,9 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) { - word32 oidSum = 0; + word32 oidSum; int version, length; - int privSz, pubSz; + int privSz, pubSz = 0; byte b; int ret = 0; int curve_id = ECC_CURVE_DEF; @@ -8987,6 +9492,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, byte priv[ECC_MAXSIZE+1]; byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */ #endif + byte* pubData = NULL; if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -9027,32 +9533,26 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, XMEMCPY(priv, &input[*inOutIdx], privSz); *inOutIdx += length; + if ((*inOutIdx + 1) > inSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + /* prefix 0, may have */ b = input[*inOutIdx]; if (b == ECC_PREFIX_0) { *inOutIdx += 1; - if (GetLength(input, inOutIdx, &length, inSz) < 0) + if (GetLength(input, inOutIdx, &length, inSz) <= 0) ret = ASN_PARSE_E; else { - /* object id */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_OBJECT_ID) { - ret = ASN_OBJECT_ID_E; - } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { - ret = ASN_PARSE_E; - } - else { - while(length--) { - oidSum += input[*inOutIdx]; - *inOutIdx += 1; - } - if ((ret = CheckCurve(oidSum)) < 0) { + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret == 0) { + if ((ret = CheckCurve(oidSum)) < 0) ret = ECC_CURVE_OID_E; - } else { curve_id = ret; ret = 0; @@ -9061,7 +9561,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, } } - if (ret == 0) { + if (ret == 0 && (*inOutIdx + 1) < inSz) { /* prefix 1 */ b = input[*inOutIdx]; *inOutIdx += 1; @@ -9069,46 +9569,30 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, if (b != ECC_PREFIX_1) { ret = ASN_ECC_KEY_E; } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { + else if (GetLength(input, inOutIdx, &length, inSz) <= 0) { ret = ASN_PARSE_E; } else { /* key header */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_BIT_STRING) { - ret = ASN_BITSTR_E; - } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { - ret = ASN_PARSE_E; - } - else if (length <= 0) { - /* pubkey needs some size */ - ret = ASN_INPUT_E; - } - else { - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != 0x00) { - ret = ASN_EXPECT_0_E; - } - else { - /* pub key */ - pubSz = length - 1; /* null prefix */ - if (pubSz < 2*(ECC_MAXSIZE+1)) { - XMEMCPY(pub, &input[*inOutIdx], pubSz); - *inOutIdx += length; - ret = wc_ecc_import_private_key_ex(priv, privSz, pub, - pubSz, key, curve_id); - } else - ret = BUFFER_E; + ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL); + if (ret == 0) { + /* pub key */ + pubSz = length; + if (pubSz < 2*(ECC_MAXSIZE+1)) { + XMEMCPY(pub, &input[*inOutIdx], pubSz); + *inOutIdx += length; } + else + ret = BUFFER_E; } } } + if (ret == 0) { + ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key, + curve_id); + } + #ifdef WOLFSSL_SMALL_STACK XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -9117,11 +9601,15 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, return ret; } + int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) { int length; - int ret = 0; + int ret; +#ifdef ECC_CHECK_PUBLIC_KEY_OID + word32 oidSum; +#endif if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -9129,68 +9617,50 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; -#if defined(OPENSSL_EXTRA) || defined(ECC_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; - if (b != ASN_INTEGER) { - /* not from decoded cert, will have algo id, skip past */ - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - *inOutIdx += length; /* skip past */ - - /* ecc params information */ - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - *inOutIdx += length; /* skip past */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; - /* key header */ - b = input[*inOutIdx]; - *inOutIdx += 1; + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; - if (b != ASN_BIT_STRING) - ret = ASN_BITSTR_E; - else if (GetLength(input, inOutIdx, &length, inSz) < 0) - ret = ASN_PARSE_E; - else { - b = input[*inOutIdx]; - *inOutIdx += 1; + /* ecc params information */ +#ifdef ECC_CHECK_PUBLIC_KEY_OID + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret != 0) + return ret; + if (CheckCurve(oidSum) < 0) + return ECC_CURVE_OID_E; +#else + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; +#endif - if (b != 0x00) - ret = ASN_EXPECT_0_E; - } - } - } /* openssl var block */ -#endif /* OPENSSL_EXTRA */ + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; - if (wc_ecc_import_x963(input+*inOutIdx, inSz - *inOutIdx, key) != 0) + /* This is the raw point data compressed or uncompressed. */ + if (wc_ecc_import_x963(input + *inOutIdx, inSz - *inOutIdx, key) != 0) return ASN_ECC_KEY_E; - return ret; + return 0; } #ifdef WOLFSSL_KEY_GEN -/* Write a Private ecc key to DER format, length on success else < 0 */ -int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +/* build DER formatted ECC key, include optional public key if requested, + * return length on success, negative on error */ +static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, + int pubIn) { byte curve[MAX_ALGO_SZ+2]; byte ver[MAX_VERSION_SZ]; byte seq[MAX_SEQ_SZ]; - byte *prv, *pub; + byte *prv = NULL, *pub = NULL; int ret, totalSz, curveSz, verSz; int privHdrSz = ASN_ECC_HEADER_SZ; int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ; @@ -9218,8 +9688,7 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) if (prv == NULL) { return MEMORY_E; } - prv[prvidx++] = ASN_OCTET_STRING; - prv[prvidx++] = (byte)key->dp->size; + prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]); ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz); if (ret < 0) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -9227,35 +9696,37 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) } prvidx += privSz; - /* public */ - ret = wc_ecc_export_x963(key, NULL, &pubSz); - if (ret != LENGTH_ONLY_E) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + /* pubIn */ + if (pubIn) { + ret = wc_ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } - pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, - key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } + pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } - pub[pubidx++] = ECC_PREFIX_1; - if (pubSz > 128) /* leading zero + extra size byte */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); - else /* leading zero */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); - pub[pubidx++] = ASN_BIT_STRING; - pubidx += SetLength(pubSz + 1, pub+pubidx); - pub[pubidx++] = (byte)0; /* leading zero */ - ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); - if (ret != 0) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + pub[pubidx++] = ECC_PREFIX_1; + if (pubSz > 128) /* leading zero + extra size byte */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); + else /* leading zero */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); + + /* SetBitString adds leading zero */ + pubidx += SetBitString(pubSz, 0, pub + pubidx); + ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); + if (ret != 0) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pubidx += pubSz; } - pubidx += pubSz; /* make headers */ verSz = SetMyVersion(1, ver, FALSE); @@ -9264,7 +9735,9 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) totalSz = prvidx + pubidx + curveidx + verSz + seqSz; if (totalSz > (int)inLen) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pubIn) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return BAD_FUNC_ARG; } @@ -9286,14 +9759,32 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) XMEMCPY(output + idx, curve, curveidx); idx += curveidx; - /* public */ - XMEMCPY(output + idx, pub, pubidx); - /* idx += pubidx; not used after write, if more data remove comment */ - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + /* pubIn */ + if (pubIn) { + XMEMCPY(output + idx, pub, pubidx); + /* idx += pubidx; not used after write, if more data remove comment */ + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return totalSz; } + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 1); +} + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 0); +} + #endif /* WOLFSSL_KEY_GEN */ #endif /* HAVE_ECC */ @@ -9363,6 +9854,7 @@ static int DecodeSingleResponse(byte* source, word32 idx = *ioIndex, prevIndex, oid; int length, wrapperSz; CertStatus* cs = resp->status; + int ret; WOLFSSL_ENTER("DecodeSingleResponse"); @@ -9386,17 +9878,15 @@ static int DecodeSingleResponse(byte* source, if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0) return ASN_PARSE_E; /* Save reference to the hash of CN */ - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; resp->issuerHash = source + idx; idx += length; /* Save reference to the hash of the issuer public key */ - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; resp->issuerKeyHash = source + idx; idx += length; @@ -9425,11 +9915,17 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->thisDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->thisDate, &cs->thisDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; +#endif /* The following items are optional. Only check for them if there is more * unprocessed data in the singleResponse wrapper. */ @@ -9440,11 +9936,17 @@ static int DecodeSingleResponse(byte* source, idx++; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->nextDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->nextDate, &cs->nextDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) return ASN_AFTER_DATE_E; +#endif } if (((int)(idx - prevIndex) < wrapperSz) && (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))) @@ -9467,15 +9969,21 @@ static int DecodeOcspRespExtensions(byte* source, int length; int ext_bound; /* boundary index for the sequence of extensions */ word32 oid; + int ret; WOLFSSL_ENTER("DecodeOcspRespExtensions"); + if ((idx + 1) > sz) + return BUFFER_E; + if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) return ASN_PARSE_E; - if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E; + if (GetLength(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; - if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E; + if (GetSequence(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; ext_bound = idx + length; @@ -9494,31 +10002,20 @@ static int DecodeOcspRespExtensions(byte* source, /* check for critical flag */ if (source[idx] == ASN_BOOLEAN) { WOLFSSL_MSG("\tfound optional critical flag, moving past"); - idx += (ASN_BOOL_SIZE + 1); - } - - /* process the extension based on the OID */ - if (source[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; + ret = GetBoolean(source, &idx, sz); + if (ret < 0) + return ret; } - if (GetLength(source, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; if (oid == OCSP_NONCE_OID) { /* get data inside extra OCTET_STRING */ - if (source[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(source, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; resp->nonce = source + idx; resp->nonceSz = length; @@ -9592,6 +10089,8 @@ static int DecodeResponseData(byte* source, } +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS + static int DecodeCerts(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { @@ -9618,15 +10117,20 @@ static int DecodeCerts(byte* source, return 0; } +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + + static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, - OcspResponse* resp, word32 size, void* cm, void* heap) + OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify) { - int length; + int length; word32 idx = *ioIndex; word32 end_index; - int ret = -1; + int ret; + int sigLength; WOLFSSL_ENTER("DecodeBasicOcspResponse"); + (void)heap; if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; @@ -9642,21 +10146,19 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0) return ASN_PARSE_E; - /* Obtain pointer to the start of the signature, and save the size */ - if (source[idx++] == ASN_BIT_STRING) - { - int sigLength = 0; - if (GetLength(source, &idx, &sigLength, size) < 0) - return ASN_PARSE_E; - resp->sigSz = sigLength; - resp->sig = source + idx; - idx += sigLength; - } + ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL); + if (ret != 0) + return ret; + + resp->sigSz = sigLength; + resp->sig = source + idx; + idx += sigLength; /* * Check the length of the BasicOcspResponse against the current index to * see if there are certificates, they are optional. */ +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS if (idx < end_index) { DecodedCert cert; @@ -9665,27 +10167,49 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, return ASN_PARSE_E; InitDecodedCert(&cert, resp->cert, resp->certSz, heap); - ret = ParseCertRelative(&cert, CERT_TYPE, VERIFY, cm); - if (ret < 0) + /* Don't verify if we don't have access to Cert Manager. */ + ret = ParseCertRelative(&cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY, + cm); + if (ret < 0) { + WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); + FreeDecodedCert(&cert); return ret; + } - ret = ConfirmSignature(resp->response, resp->responseSz, - cert.publicKey, cert.pubKeySize, cert.keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL); + /* ConfirmSignature is blocking here */ + ret = ConfirmSignature(&cert.sigCtx, + resp->response, resp->responseSz, + cert.publicKey, cert.pubKeySize, cert.keyOID, + resp->sig, resp->sigSz, resp->sigOID); FreeDecodedCert(&cert); - if (ret == 0) - { + if (ret != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } } - else { - Signer* ca = GetCA(cm, resp->issuerKeyHash); + else +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + { + Signer* ca = NULL; + int sigValid = -1; + + #ifndef NO_SKID + ca = GetCA(cm, resp->issuerKeyHash); + #else + ca = GetCA(cm, resp->issuerHash); + #endif + + if (ca) { + SignatureCtx sigCtx; + InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); - if (!ca || !ConfirmSignature(resp->response, resp->responseSz, - ca->publicKey, ca->pubKeySize, ca->keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL)) { + /* ConfirmSignature is blocking here */ + sigValid = ConfirmSignature(&sigCtx, resp->response, + resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID, + resp->sig, resp->sigSz, resp->sigOID); + } + if (ca == NULL || sigValid != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } @@ -9711,8 +10235,9 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, } -int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) +int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) { + int ret; int length = 0; word32 idx = 0; byte* source = resp->source; @@ -9749,14 +10274,13 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) return ASN_PARSE_E; if (oid != OCSP_BASIC_OID) return ASN_PARSE_E; - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; - if (DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap) < 0) - return ASN_PARSE_E; + ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify); + if (ret < 0) + return ret; return 0; } @@ -9766,8 +10290,8 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) { static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; - byte seqArray[6][MAX_SEQ_SZ]; - word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId); + byte seqArray[5][MAX_SEQ_SZ]; + word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId); WOLFSSL_ENTER("SetOcspReqExtensions"); @@ -9777,20 +10301,15 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) totalSz += req->nonceSz; totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]); totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]); - seqArray[2][0] = ASN_OBJECT_ID; - totalSz += seqSz[2] = 1 + SetLength(sizeof(NonceObjId), &seqArray[2][1]); + totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]); totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]); totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); - totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]); if (totalSz > size) return 0; totalSz = 0; - XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); - totalSz += seqSz[5]; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; @@ -9841,8 +10360,14 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) snSz = SetSerialNumber(req->serial, req->serialSz, snArray); extSz = 0; - if (req->nonceSz) - extSz = EncodeOcspRequestExtensions(req, extArray, OCSP_NONCE_EXT_SZ); + if (req->nonceSz) { + /* TLS Extensions use this function too - put extensions after + * ASN.1: Context Specific [2]. + */ + extSz = EncodeOcspRequestExtensions(req, extArray + 2, + OCSP_NONCE_EXT_SZ); + extSz += SetExplicit(2, extSz, extArray); + } totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { @@ -9851,6 +10376,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) if (i == 2) totalSz += extSz; } + if (output == NULL) + return totalSz; if (totalSz > size) return BUFFER_E; @@ -9884,6 +10411,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, void* heap) { + int ret; + WOLFSSL_ENTER("InitOcspRequest"); if (req == NULL) @@ -9915,17 +10444,17 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); req->urlSz = cert->extAuthInfoSz; } - } if (useNonce) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, req->heap) != 0) { -#else - if (wc_InitRng(&rng) != 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) { WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); } else { if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) @@ -9974,7 +10503,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) /* Nonces are not critical. The responder may not necessarily add * the nonce to the response. */ - if (req->nonceSz && resp->nonceSz != 0) { + if (resp->nonceSz != 0) { cmp = req->nonceSz - resp->nonceSz; if (cmp != 0) { @@ -10160,40 +10689,51 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl, int maxIdx) { int length; - byte b; + int ret; WOLFSSL_ENTER("GetCRL_Signature"); - b = source[*idx]; - *idx += 1; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(source, idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - + ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL); + if (ret != 0) + return ret; dcrl->sigLength = length; - b = source[*idx]; - *idx += 1; - if (b != 0x00) - return ASN_EXPECT_0_E; - - dcrl->sigLength--; dcrl->signature = (byte*)&source[*idx]; - *idx += dcrl->sigLength; return 0; } +int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, + word32 tbsSz, const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, void* heap) +{ + /* try to confirm/verify signature */ +#ifndef IGNORE_KEY_EXTENSIONS + if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { + WOLFSSL_MSG("CA cannot sign CRLs"); + return ASN_CRL_NO_SIGNER_E; + } +#endif /* IGNORE_KEY_EXTENSIONS */ + + InitSignatureCtx(sigCtx, heap, INVALID_DEVID); + if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, + ca->pubKeySize, ca->keyOID, signature, sigSz, + signatureOID) != 0) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + + return 0; +} /* prase crl buffer into decoded state, 0 on success */ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) { - int version, len, doNextDate = 1; - word32 oid, idx = 0, dateIdx; - Signer* ca = NULL; + int version, len, doNextDate = 1; + word32 oid, idx = 0, dateIdx; + Signer* ca = NULL; + SignatureCtx sigCtx; WOLFSSL_MSG("ParseCRL"); @@ -10242,10 +10782,13 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) #endif } - if (doNextDate && !XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, - AFTER)) { - WOLFSSL_MSG("CRL after date is no longer valid"); - return ASN_AFTER_DATE_E; + if (doNextDate) { +#ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL after date is no longer valid"); + return ASN_AFTER_DATE_E; + } +#endif } if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) { @@ -10271,46 +10814,34 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) /* openssl doesn't add skid by default for CRLs cause firefox chokes we're not assuming it's available yet */ - #if !defined(NO_SKID) && defined(CRL_SKID_READY) - if (dcrl->extAuthKeyIdSet) - ca = GetCA(cm, dcrl->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(cm, dcrl->issuerHash); - #else /* NO_SKID */ - ca = GetCA(cm, dcrl->issuerHash); - #endif /* NO_SKID */ +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (dcrl->extAuthKeyIdSet) + ca = GetCA(cm, dcrl->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(cm, dcrl->issuerHash); +#else + ca = GetCA(cm, dcrl->issuerHash); +#endif /* !NO_SKID && CRL_SKID_READY */ WOLFSSL_MSG("About to verify CRL signature"); - if (ca) { - WOLFSSL_MSG("Found CRL issuer CA"); - /* try to confirm/verify signature */ - #ifndef IGNORE_KEY_EXTENSIONS - if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { - WOLFSSL_MSG("CA cannot sign CRLs"); - return ASN_CRL_NO_SIGNER_E; - } - #endif /* IGNORE_KEY_EXTENSIONS */ - if (!ConfirmSignature(buff + dcrl->certBegin, - dcrl->sigIndex - dcrl->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) { - WOLFSSL_MSG("CRL Confirm signature failed"); - return ASN_CRL_CONFIRM_E; - } - } - else { + if (ca == NULL) { WOLFSSL_MSG("Did NOT find CRL issuer CA"); return ASN_CRL_NO_SIGNER_E; } - return 0; + WOLFSSL_MSG("Found CRL issuer CA"); + return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin, + dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength, + dcrl->signatureOID, ca, dcrl->heap); } #endif /* HAVE_CRL */ + +#undef ERROR_OUT + #endif /* !NO_ASN */ #ifdef WOLFSSL_SEP - #endif /* WOLFSSL_SEP */ diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 4ed71b44ab..f30b685af1 100644 --- a/wolfcrypt/src/blake2b.c +++ b/wolfcrypt/src/blake2b.c @@ -126,6 +126,7 @@ int blake2b_init( blake2b_state *S, const byte outlen ) if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD P->digest_length = outlen; P->key_length = 0; P->fanout = 1; @@ -137,6 +138,12 @@ int blake2b_init( blake2b_state *S, const byte outlen ) XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); XMEMSET( P->salt, 0, sizeof( P->salt ) ); XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->fanout = 1; + P->depth = 1; +#endif return blake2b_init_param( S, P ); } @@ -150,6 +157,7 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD P->digest_length = outlen; P->key_length = keylen; P->fanout = 1; @@ -161,6 +169,13 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); XMEMSET( P->salt, 0, sizeof( P->salt ) ); XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; +#endif if( blake2b_init_param( S, P ) < 0 ) return -1; diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index 6c7c88dc92..79b13fc43a 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -40,17 +40,6 @@ #include -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - static void ShiftAndXorRb(byte* out, byte* in) { int i, j, xorRb; diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index f144b1130a..43cb45d068 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -347,7 +347,8 @@ int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen) #endif /* defined(WOLFSSL_BASE64_ENCODE) */ -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) static const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c old mode 100644 new mode 100755 index 4fc5101547..739fb62d66 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -26,91 +26,78 @@ #include + #ifndef NO_DES3 #include +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + return Des_SetKey(des, key, iv, dir); + } + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + return Des3_SetKey_fips(des, key, iv, dir); + } + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcEncrypt(des, out, in, sz); + } + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcDecrypt(des, out, in, sz); + } + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_CbcEncrypt_fips(des, out, in, sz); + } + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_CbcDecrypt_fips(des, out, in, sz); + } -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - return Des_SetKey(des, key, iv, dir); -} - - -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - return Des3_SetKey_fips(des, key, iv, dir); -} - - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcEncrypt(des, out, in, sz); -} - - -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcDecrypt(des, out, in, sz); -} - - -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcEncrypt_fips(des, out, in, sz); -} - - -int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcDecrypt_fips(des, out, in, sz); -} - - -#ifdef WOLFSSL_DES_ECB - -/* One block, compatibility only */ -int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_EcbEncrypt(des, out, in, sz); -} - -#endif /* WOLFSSL_DES_ECB */ - - -void wc_Des_SetIV(Des* des, const byte* iv) -{ - Des_SetIV(des, iv); -} - - -int wc_Des3_SetIV(Des3* des, const byte* iv) -{ - return Des3_SetIV_fips(des, iv); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Des3 for use with Nitrox device */ -int wc_Des3AsyncInit(Des3* des3, int devId) -{ - return Des3AsyncInit(des3, devId); -} - - -/* Free Des3 from use with Nitrox device */ -void wc_Des3AsyncFree(Des3* des3) -{ - Des3AsyncFree(des3); -} + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_EcbEncrypt(des, out, in, sz); + } + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_EcbEncrypt(des, out, in, sz); + } + #endif /* WOLFSSL_DES_ECB */ + void wc_Des_SetIV(Des* des, const byte* iv) + { + Des_SetIV(des, iv); + } + int wc_Des3_SetIV(Des3* des, const byte* iv) + { + return Des3_SetIV_fips(des, iv); + } -#endif /* WOLFSSL_ASYNC_CRYPT */ + int wc_Des3Init(Des3* des3, void* heap, int devId) + { + (void)des3; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return Des3Init(des3, heap, devId); */ + return 0; + } + void wc_Des3Free(Des3* des3) + { + (void)des3; + /* FIPS doesn't support: + Des3Free(des3); */ + } #else /* build without fips */ + #if defined(WOLFSSL_TI_CRYPT) #include #else @@ -126,6 +113,7 @@ void wc_Des3AsyncFree(Des3* des3) #endif +/* Hardware Acceleration */ #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) /* @@ -442,227 +430,224 @@ void wc_Des3AsyncFree(Des3* des3) #elif defined(HAVE_COLDFIRE_SEC) -#include + #include -#include "sec.h" -#include "mcf5475_sec.h" -#include "mcf5475_siu.h" + #include "sec.h" + #include "mcf5475_sec.h" + #include "mcf5475_siu.h" -#if defined (HAVE_THREADX) -#include "memory_pools.h" -extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ -#endif + #if defined (HAVE_THREADX) + #include "memory_pools.h" + extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ + #endif -#define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) -static unsigned char *desBuffIn = NULL ; -static unsigned char *desBuffOut = NULL ; -static byte *secIV ; -static byte *secKey ; -static volatile SECdescriptorType *secDesc ; + #define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) + static unsigned char *desBuffIn = NULL; + static unsigned char *desBuffOut = NULL; + static byte *secIV; + static byte *secKey; + static volatile SECdescriptorType *secDesc; -static wolfSSL_Mutex Mutex_DesSEC ; + static wolfSSL_Mutex Mutex_DesSEC; -#define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 -#define SEC_DESC_DES_CBC_DECRYPT 0x20400010 -#define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 -#define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 + #define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 + #define SEC_DESC_DES_CBC_DECRYPT 0x20400010 + #define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 + #define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 -#define DES_IVLEN 8 -#define DES_KEYLEN 8 -#define DES3_IVLEN 8 -#define DES3_KEYLEN 24 + #define DES_IVLEN 8 + #define DES_KEYLEN 8 + #define DES3_IVLEN 8 + #define DES3_KEYLEN 24 -extern volatile unsigned char __MBAR[]; + extern volatile unsigned char __MBAR[]; -static void wc_Des_Cbc(byte* out, const byte* in, word32 sz, - byte *key, byte *iv, word32 desc) -{ - #ifdef DEBUG_WOLFSSL - int ret ; int stat1,stat2 ; - #endif - int size ; - volatile int v ; - - wc_LockMutex(&Mutex_DesSEC) ; - - secDesc->length1 = 0x0; - secDesc->pointer1 = NULL; - if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ - secDesc->length2 = DES_IVLEN ; - secDesc->length3 = DES_KEYLEN ; - } else { - secDesc->length2 = DES3_IVLEN ; - secDesc->length3 = DES3_KEYLEN ; - } - secDesc->pointer2 = secIV ; - secDesc->pointer3 = secKey; - secDesc->pointer4 = desBuffIn ; - secDesc->pointer5 = desBuffOut ; - secDesc->length6 = 0; - secDesc->pointer6 = NULL; - secDesc->length7 = 0x0; - secDesc->pointer7 = NULL; - secDesc->nextDescriptorPtr = NULL ; - - while(sz) { - XMEMCPY(secIV, iv, secDesc->length2) ; - if((sz%DES_BUFFER_SIZE) == sz) { - size = sz ; - sz = 0 ; + static void wc_Des_Cbc(byte* out, const byte* in, word32 sz, + byte *key, byte *iv, word32 desc) + { + #ifdef DEBUG_WOLFSSL + int ret; int stat1,stat2; + #endif + int size; + volatile int v; + + wc_LockMutex(&Mutex_DesSEC) ; + + secDesc->length1 = 0x0; + secDesc->pointer1 = NULL; + if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ + secDesc->length2 = DES_IVLEN; + secDesc->length3 = DES_KEYLEN; } else { - size = DES_BUFFER_SIZE ; - sz -= DES_BUFFER_SIZE ; + secDesc->length2 = DES3_IVLEN; + secDesc->length3 = DES3_KEYLEN; } + secDesc->pointer2 = secIV; + secDesc->pointer3 = secKey; + secDesc->pointer4 = desBuffIn; + secDesc->pointer5 = desBuffOut; + secDesc->length6 = 0; + secDesc->pointer6 = NULL; + secDesc->length7 = 0x0; + secDesc->pointer7 = NULL; + secDesc->nextDescriptorPtr = NULL; + + while(sz) { + XMEMCPY(secIV, iv, secDesc->length2); + if((sz%DES_BUFFER_SIZE) == sz) { + size = sz; + sz = 0; + } else { + size = DES_BUFFER_SIZE; + sz -= DES_BUFFER_SIZE; + } - XMEMCPY(desBuffIn, in, size) ; - XMEMCPY(secKey, key, secDesc->length3) ; - - secDesc->header = desc ; - secDesc->length4 = size; - secDesc->length5 = size; - /* Point SEC to the location of the descriptor */ - MCF_SEC_FR0 = (uint32)secDesc; - /* Initialize SEC and wait for encryption to complete */ - MCF_SEC_CCCR0 = 0x0000001a; - /* poll SISR to determine when channel is complete */ - v=0 ; - while((secDesc->header>> 24) != 0xff) { - if(v++ > 1000)break ; - } - -#ifdef DEBUG_WOLFSSL - ret = MCF_SEC_SISRH; - stat1 = MCF_SEC_DSR ; - stat2 = MCF_SEC_DISR ; - if(ret & 0xe0000000) { - /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2) ; */ - } -#endif - - XMEMCPY(out, desBuffOut, size) ; + XMEMCPY(desBuffIn, in, size); + XMEMCPY(secKey, key, secDesc->length3); + + secDesc->header = desc; + secDesc->length4 = size; + secDesc->length5 = size; + /* Point SEC to the location of the descriptor */ + MCF_SEC_FR0 = (uint32)secDesc; + /* Initialize SEC and wait for encryption to complete */ + MCF_SEC_CCCR0 = 0x0000001a; + /* poll SISR to determine when channel is complete */ + v=0; + while((secDesc->header>> 24) != 0xff) { + if(v++ > 1000)break; + } - if((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { - XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2) ; - } else { - XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2) ; - } + #ifdef DEBUG_WOLFSSL + ret = MCF_SEC_SISRH; + stat1 = MCF_SEC_DSR; + stat2 = MCF_SEC_DISR; + if(ret & 0xe0000000) { + /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2); */ + } + #endif - in += size ; - out += size ; + XMEMCPY(out, desBuffOut, size); - } - wc_UnLockMutex(&Mutex_DesSEC) ; + if ((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { + XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2); + } else { + XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2); + } -} + in += size; + out += size; + } + wc_UnLockMutex(&Mutex_DesSEC) ; -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT) ; - return 0; -} + } -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT) ; - return 0; -} -int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT) ; - return 0; -} + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT); + return 0; + } + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT); + return 0; + } -int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT) ; - return 0; -} + int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT); + return 0; + } -static void setParity(byte *buf, int len) -{ - int i, j ; - byte v ; - int bits ; - for(i=0; i> 1 ; - buf[i] = v << 1 ; - bits = 0 ; - for(j=0; j<7; j++) - { - bits += (v&0x1) ; - v = v >> 1 ; - } - buf[i] |= (1 - (bits&0x1)) ; + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT); + return 0; } -} + static void setParity(byte *buf, int len) + { + int i, j; + byte v; + int bits; + + for (i=0; i> 1; + buf[i] = v << 1; + bits = 0; + for (j=0; j<7; j++) { + bits += (v&0x1); + v = v >> 1; + } + buf[i] |= (1 - (bits&0x1)); + } + } -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - if(desBuffIn == NULL) { + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + if(desBuffIn == NULL) { #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); - /* Don't know des or des3 to be used. Allocate larger buffers */ - s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + /* Don't know des or des3 to be used. Allocate larger buffers */ + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); #else - #warning "Allocate non-Cache buffers" + #warning "Allocate non-Cache buffers" #endif - wc_InitMutex(&Mutex_DesSEC) ; - } + InitMutex(&Mutex_DesSEC); + } - XMEMCPY(des->key, key, DES_KEYLEN); - setParity((byte *)des->key, DES_KEYLEN) ; + XMEMCPY(des->key, key, DES_KEYLEN); + setParity((byte *)des->key, DES_KEYLEN); - if (iv) { - XMEMCPY(des->reg, iv, DES_IVLEN); - } else { - XMEMSET(des->reg, 0x0, DES_IVLEN) ; + if (iv) { + XMEMCPY(des->reg, iv, DES_IVLEN); + } else { + XMEMSET(des->reg, 0x0, DES_IVLEN); + } + return 0; } - return 0; -} -int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) -{ + int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) + { - if(desBuffIn == NULL) { + if(desBuffIn == NULL) { #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); - s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); #else - #warning "Allocate non-Cache buffers" + #warning "Allocate non-Cache buffers" #endif - wc_InitMutex(&Mutex_DesSEC) ; - } + InitMutex(&Mutex_DesSEC); + } - XMEMCPY(des3->key[0], key, DES3_KEYLEN); - setParity((byte *)des3->key[0], DES3_KEYLEN) ; + XMEMCPY(des3->key[0], key, DES3_KEYLEN); + setParity((byte *)des3->key[0], DES3_KEYLEN); - if (iv) { - XMEMCPY(des3->reg, iv, DES3_IVLEN); - } else { - XMEMSET(des3->reg, 0x0, DES3_IVLEN) ; - } - return 0; + if (iv) { + XMEMCPY(des3->reg, iv, DES3_IVLEN); + } else { + XMEMSET(des3->reg, 0x0, DES3_IVLEN); + } + return 0; -} + } #elif (defined FREESCALE_LTC_DES) #include "fsl_ltc.h" @@ -749,7 +734,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) return -1; } -#elif defined FREESCALE_MMCAU +#elif defined(FREESCALE_MMCAU) /* * Freescale mmCAU hardware DES/3DES support through the CAU/mmCAU library. * Documentation located in ColdFire/ColdFire+ CAU and Kinetis mmCAU @@ -757,8 +742,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) */ #include "fsl_mmcau.h" - const unsigned char parityLookup[128] = - { + const unsigned char parityLookup[128] = { 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, @@ -820,7 +804,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) byte temp_block[DES_BLOCK_SIZE]; iv = (byte*)des->reg; - + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -893,7 +877,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) byte temp_block[DES_BLOCK_SIZE]; iv = (byte*)des->reg; - + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -965,13 +949,10 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" -void wc_Des_SetIV(Des* des, const byte* iv); -int wc_Des3_SetIV(Des3* des, const byte* iv); - int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { - word32 *dkey = des->key ; - word32 *dreg = des->reg ; + word32 *dkey = des->key; + word32 *dreg = des->reg; XMEMCPY((byte *)dkey, (byte *)key, 8); ByteReverseWords(dkey, dkey, 8); @@ -984,12 +965,12 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { word32 *dkey1 = des->key[0]; - word32 *dreg = des->reg ; + word32 *dreg = des->reg; XMEMCPY(dkey1, key, 24); ByteReverseWords(dkey1, dkey1, 24); XMEMCPY(dreg, iv, 8); - ByteReverseWords(dreg, dreg, 8) ; + ByteReverseWords(dreg, dreg, 8); return 0; } @@ -997,21 +978,21 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); void DesCrypt(word32 *key, word32 *iv, byte* out, const byte* in, word32 sz, int dir, int algo, int cryptoalgo) { - securityAssociation *sa_p ; - bufferDescriptor *bd_p ; - const byte *in_p, *in_l ; - byte *out_p, *out_l ; + securityAssociation *sa_p; + bufferDescriptor *bd_p; + const byte *in_p, *in_l; + byte *out_p, *out_l; volatile securityAssociation sa __attribute__((aligned (8))); volatile bufferDescriptor bd __attribute__((aligned (8))); - volatile int k ; + volatile int k; /* get uncached address */ in_l = in; - out_l = out ; - sa_p = KVA0_TO_KVA1(&sa) ; - bd_p = KVA0_TO_KVA1(&bd) ; - in_p = KVA0_TO_KVA1(in_l) ; + out_l = out; + sa_p = KVA0_TO_KVA1(&sa); + bd_p = KVA0_TO_KVA1(&bd); + in_p = KVA0_TO_KVA1(in_l); out_p= KVA0_TO_KVA1(out_l); if(PIC32MZ_IF_RAM(in_p)) @@ -1020,13 +1001,13 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); /* Set up the Security Association */ XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); - sa_p->SA_CTRL.ALGO = algo ; + sa_p->SA_CTRL.ALGO = algo; sa_p->SA_CTRL.LNC = 1; sa_p->SA_CTRL.LOADIV = 1; sa_p->SA_CTRL.FB = 1; - sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ + sa_p->SA_CTRL.ENCTYPE = dir; /* Encryption/Decryption */ sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; - sa_p->SA_CTRL.KEYSIZE = 1 ; /* KEY is 192 bits */ + sa_p->SA_CTRL.KEYSIZE = 1; /* KEY is 192 bits */ XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCKEY[algo==PIC32_ALGO_TDES ? 2 : 6]), (byte *)key, algo==PIC32_ALGO_TDES ? 24 : 8); XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCIV[2]), (byte *)iv, 8); @@ -1039,30 +1020,30 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); bd_p->BD_CTRL.LAST_BD = 1; bd_p->BD_CTRL.DESC_EN = 1; - bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; /* (unsigned int)sa_p; */ - bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; /* (unsigned int)in_p; */ + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa); /* (unsigned int)sa_p; */ + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in); /* (unsigned int)in_p; */ bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); /* (unsigned int)out_p; */ bd_p->NXTPTR = (unsigned int)KVA_TO_PA(&bd); - bd_p->MSGLEN = sz ; + bd_p->MSGLEN = sz; /* Fire in the hole! */ CECON = 1 << 6; while (CECON); /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; /* (unsigned int)bd_p ; */ + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd); /* (unsigned int)bd_p; */ CEINTEN = 0x07; CECON = 0x27; - WAIT_ENGINE ; + WAIT_ENGINE; if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| (cryptoalgo == PIC32_CRYPTOALGO_RCBC)) { /* set iv for the next call */ if(dir == PIC32_ENCRYPTION) { - XMEMCPY((void *)iv, (void*)&(out_p[sz-DES_IVLEN]), DES_IVLEN) ; - } else { + XMEMCPY((void *)iv, (void*)&(out_p[sz-DES_IVLEN]), DES_IVLEN); + } else { ByteReverseWords((word32*)iv, (word32 *)&(in_p[sz-DES_IVLEN]), DES_IVLEN); } @@ -1099,536 +1080,575 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); return 0; } -#else /* Begin wolfCrypt software implementation */ - -/* permuted choice table (key) */ -static const byte pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const byte totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const byte pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - -static const word32 Spbox[8][64] = { -{ -0x01010400,0x00000000,0x00010000,0x01010404, -0x01010004,0x00010404,0x00000004,0x00010000, -0x00000400,0x01010400,0x01010404,0x00000400, -0x01000404,0x01010004,0x01000000,0x00000004, -0x00000404,0x01000400,0x01000400,0x00010400, -0x00010400,0x01010000,0x01010000,0x01000404, -0x00010004,0x01000004,0x01000004,0x00010004, -0x00000000,0x00000404,0x00010404,0x01000000, -0x00010000,0x01010404,0x00000004,0x01010000, -0x01010400,0x01000000,0x01000000,0x00000400, -0x01010004,0x00010000,0x00010400,0x01000004, -0x00000400,0x00000004,0x01000404,0x00010404, -0x01010404,0x00010004,0x01010000,0x01000404, -0x01000004,0x00000404,0x00010404,0x01010400, -0x00000404,0x01000400,0x01000400,0x00000000, -0x00010004,0x00010400,0x00000000,0x01010004}, -{ -0x80108020,0x80008000,0x00008000,0x00108020, -0x00100000,0x00000020,0x80100020,0x80008020, -0x80000020,0x80108020,0x80108000,0x80000000, -0x80008000,0x00100000,0x00000020,0x80100020, -0x00108000,0x00100020,0x80008020,0x00000000, -0x80000000,0x00008000,0x00108020,0x80100000, -0x00100020,0x80000020,0x00000000,0x00108000, -0x00008020,0x80108000,0x80100000,0x00008020, -0x00000000,0x00108020,0x80100020,0x00100000, -0x80008020,0x80100000,0x80108000,0x00008000, -0x80100000,0x80008000,0x00000020,0x80108020, -0x00108020,0x00000020,0x00008000,0x80000000, -0x00008020,0x80108000,0x00100000,0x80000020, -0x00100020,0x80008020,0x80000020,0x00100020, -0x00108000,0x00000000,0x80008000,0x00008020, -0x80000000,0x80100020,0x80108020,0x00108000}, -{ -0x00000208,0x08020200,0x00000000,0x08020008, -0x08000200,0x00000000,0x00020208,0x08000200, -0x00020008,0x08000008,0x08000008,0x00020000, -0x08020208,0x00020008,0x08020000,0x00000208, -0x08000000,0x00000008,0x08020200,0x00000200, -0x00020200,0x08020000,0x08020008,0x00020208, -0x08000208,0x00020200,0x00020000,0x08000208, -0x00000008,0x08020208,0x00000200,0x08000000, -0x08020200,0x08000000,0x00020008,0x00000208, -0x00020000,0x08020200,0x08000200,0x00000000, -0x00000200,0x00020008,0x08020208,0x08000200, -0x08000008,0x00000200,0x00000000,0x08020008, -0x08000208,0x00020000,0x08000000,0x08020208, -0x00000008,0x00020208,0x00020200,0x08000008, -0x08020000,0x08000208,0x00000208,0x08020000, -0x00020208,0x00000008,0x08020008,0x00020200}, -{ -0x00802001,0x00002081,0x00002081,0x00000080, -0x00802080,0x00800081,0x00800001,0x00002001, -0x00000000,0x00802000,0x00802000,0x00802081, -0x00000081,0x00000000,0x00800080,0x00800001, -0x00000001,0x00002000,0x00800000,0x00802001, -0x00000080,0x00800000,0x00002001,0x00002080, -0x00800081,0x00000001,0x00002080,0x00800080, -0x00002000,0x00802080,0x00802081,0x00000081, -0x00800080,0x00800001,0x00802000,0x00802081, -0x00000081,0x00000000,0x00000000,0x00802000, -0x00002080,0x00800080,0x00800081,0x00000001, -0x00802001,0x00002081,0x00002081,0x00000080, -0x00802081,0x00000081,0x00000001,0x00002000, -0x00800001,0x00002001,0x00802080,0x00800081, -0x00002001,0x00002080,0x00800000,0x00802001, -0x00000080,0x00800000,0x00002000,0x00802080}, -{ -0x00000100,0x02080100,0x02080000,0x42000100, -0x00080000,0x00000100,0x40000000,0x02080000, -0x40080100,0x00080000,0x02000100,0x40080100, -0x42000100,0x42080000,0x00080100,0x40000000, -0x02000000,0x40080000,0x40080000,0x00000000, -0x40000100,0x42080100,0x42080100,0x02000100, -0x42080000,0x40000100,0x00000000,0x42000000, -0x02080100,0x02000000,0x42000000,0x00080100, -0x00080000,0x42000100,0x00000100,0x02000000, -0x40000000,0x02080000,0x42000100,0x40080100, -0x02000100,0x40000000,0x42080000,0x02080100, -0x40080100,0x00000100,0x02000000,0x42080000, -0x42080100,0x00080100,0x42000000,0x42080100, -0x02080000,0x00000000,0x40080000,0x42000000, -0x00080100,0x02000100,0x40000100,0x00080000, -0x00000000,0x40080000,0x02080100,0x40000100}, -{ -0x20000010,0x20400000,0x00004000,0x20404010, -0x20400000,0x00000010,0x20404010,0x00400000, -0x20004000,0x00404010,0x00400000,0x20000010, -0x00400010,0x20004000,0x20000000,0x00004010, -0x00000000,0x00400010,0x20004010,0x00004000, -0x00404000,0x20004010,0x00000010,0x20400010, -0x20400010,0x00000000,0x00404010,0x20404000, -0x00004010,0x00404000,0x20404000,0x20000000, -0x20004000,0x00000010,0x20400010,0x00404000, -0x20404010,0x00400000,0x00004010,0x20000010, -0x00400000,0x20004000,0x20000000,0x00004010, -0x20000010,0x20404010,0x00404000,0x20400000, -0x00404010,0x20404000,0x00000000,0x20400010, -0x00000010,0x00004000,0x20400000,0x00404010, -0x00004000,0x00400010,0x20004010,0x00000000, -0x20404000,0x20000000,0x00400010,0x20004010}, -{ -0x00200000,0x04200002,0x04000802,0x00000000, -0x00000800,0x04000802,0x00200802,0x04200800, -0x04200802,0x00200000,0x00000000,0x04000002, -0x00000002,0x04000000,0x04200002,0x00000802, -0x04000800,0x00200802,0x00200002,0x04000800, -0x04000002,0x04200000,0x04200800,0x00200002, -0x04200000,0x00000800,0x00000802,0x04200802, -0x00200800,0x00000002,0x04000000,0x00200800, -0x04000000,0x00200800,0x00200000,0x04000802, -0x04000802,0x04200002,0x04200002,0x00000002, -0x00200002,0x04000000,0x04000800,0x00200000, -0x04200800,0x00000802,0x00200802,0x04200800, -0x00000802,0x04000002,0x04200802,0x04200000, -0x00200800,0x00000000,0x00000002,0x04200802, -0x00000000,0x00200802,0x04200000,0x00000800, -0x04000002,0x04000800,0x00000800,0x00200002}, -{ -0x10001040,0x00001000,0x00040000,0x10041040, -0x10000000,0x10001040,0x00000040,0x10000000, -0x00040040,0x10040000,0x10041040,0x00041000, -0x10041000,0x00041040,0x00001000,0x00000040, -0x10040000,0x10000040,0x10001000,0x00001040, -0x00041000,0x00040040,0x10040040,0x10041000, -0x00001040,0x00000000,0x00000000,0x10040040, -0x10000040,0x10001000,0x00041040,0x00040000, -0x00041040,0x00040000,0x10041000,0x00001000, -0x00000040,0x10040040,0x00001000,0x00041040, -0x10001000,0x00000040,0x10000040,0x10040000, -0x10040040,0x10000000,0x00040000,0x10001040, -0x00000000,0x10041040,0x00040040,0x10000040, -0x10040000,0x10001000,0x10001040,0x00000000, -0x10041040,0x00041000,0x00041000,0x00001040, -0x00001040,0x00040040,0x10000000,0x10041000} -}; - - -static INLINE void IPERM(word32* left, word32* right) -{ - word32 work; - - *right = rotlFixed(*right, 4U); - work = (*left ^ *right) & 0xf0f0f0f0; - *left ^= work; +#else + #define NEED_SOFT_DES - *right = rotrFixed(*right^work, 20U); - work = (*left ^ *right) & 0xffff0000; - *left ^= work; +#endif - *right = rotrFixed(*right^work, 18U); - work = (*left ^ *right) & 0x33333333; - *left ^= work; - *right = rotrFixed(*right^work, 6U); - work = (*left ^ *right) & 0x00ff00ff; - *left ^= work; +#ifdef NEED_SOFT_DES + + /* permuted choice table (key) */ + static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + }; + + /* number left rotations of pc1 */ + static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 + }; + + /* permuted choice key (table) */ + static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + }; + + /* End of DES-defined tables */ + + /* bit 0 is left-most in byte */ + static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 + }; + + static const word32 Spbox[8][64] = { + { 0x01010400,0x00000000,0x00010000,0x01010404, + 0x01010004,0x00010404,0x00000004,0x00010000, + 0x00000400,0x01010400,0x01010404,0x00000400, + 0x01000404,0x01010004,0x01000000,0x00000004, + 0x00000404,0x01000400,0x01000400,0x00010400, + 0x00010400,0x01010000,0x01010000,0x01000404, + 0x00010004,0x01000004,0x01000004,0x00010004, + 0x00000000,0x00000404,0x00010404,0x01000000, + 0x00010000,0x01010404,0x00000004,0x01010000, + 0x01010400,0x01000000,0x01000000,0x00000400, + 0x01010004,0x00010000,0x00010400,0x01000004, + 0x00000400,0x00000004,0x01000404,0x00010404, + 0x01010404,0x00010004,0x01010000,0x01000404, + 0x01000004,0x00000404,0x00010404,0x01010400, + 0x00000404,0x01000400,0x01000400,0x00000000, + 0x00010004,0x00010400,0x00000000,0x01010004}, + { 0x80108020,0x80008000,0x00008000,0x00108020, + 0x00100000,0x00000020,0x80100020,0x80008020, + 0x80000020,0x80108020,0x80108000,0x80000000, + 0x80008000,0x00100000,0x00000020,0x80100020, + 0x00108000,0x00100020,0x80008020,0x00000000, + 0x80000000,0x00008000,0x00108020,0x80100000, + 0x00100020,0x80000020,0x00000000,0x00108000, + 0x00008020,0x80108000,0x80100000,0x00008020, + 0x00000000,0x00108020,0x80100020,0x00100000, + 0x80008020,0x80100000,0x80108000,0x00008000, + 0x80100000,0x80008000,0x00000020,0x80108020, + 0x00108020,0x00000020,0x00008000,0x80000000, + 0x00008020,0x80108000,0x00100000,0x80000020, + 0x00100020,0x80008020,0x80000020,0x00100020, + 0x00108000,0x00000000,0x80008000,0x00008020, + 0x80000000,0x80100020,0x80108020,0x00108000}, + { 0x00000208,0x08020200,0x00000000,0x08020008, + 0x08000200,0x00000000,0x00020208,0x08000200, + 0x00020008,0x08000008,0x08000008,0x00020000, + 0x08020208,0x00020008,0x08020000,0x00000208, + 0x08000000,0x00000008,0x08020200,0x00000200, + 0x00020200,0x08020000,0x08020008,0x00020208, + 0x08000208,0x00020200,0x00020000,0x08000208, + 0x00000008,0x08020208,0x00000200,0x08000000, + 0x08020200,0x08000000,0x00020008,0x00000208, + 0x00020000,0x08020200,0x08000200,0x00000000, + 0x00000200,0x00020008,0x08020208,0x08000200, + 0x08000008,0x00000200,0x00000000,0x08020008, + 0x08000208,0x00020000,0x08000000,0x08020208, + 0x00000008,0x00020208,0x00020200,0x08000008, + 0x08020000,0x08000208,0x00000208,0x08020000, + 0x00020208,0x00000008,0x08020008,0x00020200}, + { 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802080,0x00800081,0x00800001,0x00002001, + 0x00000000,0x00802000,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00800080,0x00800001, + 0x00000001,0x00002000,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002001,0x00002080, + 0x00800081,0x00000001,0x00002080,0x00800080, + 0x00002000,0x00802080,0x00802081,0x00000081, + 0x00800080,0x00800001,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00000000,0x00802000, + 0x00002080,0x00800080,0x00800081,0x00000001, + 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802081,0x00000081,0x00000001,0x00002000, + 0x00800001,0x00002001,0x00802080,0x00800081, + 0x00002001,0x00002080,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002000,0x00802080}, + { 0x00000100,0x02080100,0x02080000,0x42000100, + 0x00080000,0x00000100,0x40000000,0x02080000, + 0x40080100,0x00080000,0x02000100,0x40080100, + 0x42000100,0x42080000,0x00080100,0x40000000, + 0x02000000,0x40080000,0x40080000,0x00000000, + 0x40000100,0x42080100,0x42080100,0x02000100, + 0x42080000,0x40000100,0x00000000,0x42000000, + 0x02080100,0x02000000,0x42000000,0x00080100, + 0x00080000,0x42000100,0x00000100,0x02000000, + 0x40000000,0x02080000,0x42000100,0x40080100, + 0x02000100,0x40000000,0x42080000,0x02080100, + 0x40080100,0x00000100,0x02000000,0x42080000, + 0x42080100,0x00080100,0x42000000,0x42080100, + 0x02080000,0x00000000,0x40080000,0x42000000, + 0x00080100,0x02000100,0x40000100,0x00080000, + 0x00000000,0x40080000,0x02080100,0x40000100}, + { 0x20000010,0x20400000,0x00004000,0x20404010, + 0x20400000,0x00000010,0x20404010,0x00400000, + 0x20004000,0x00404010,0x00400000,0x20000010, + 0x00400010,0x20004000,0x20000000,0x00004010, + 0x00000000,0x00400010,0x20004010,0x00004000, + 0x00404000,0x20004010,0x00000010,0x20400010, + 0x20400010,0x00000000,0x00404010,0x20404000, + 0x00004010,0x00404000,0x20404000,0x20000000, + 0x20004000,0x00000010,0x20400010,0x00404000, + 0x20404010,0x00400000,0x00004010,0x20000010, + 0x00400000,0x20004000,0x20000000,0x00004010, + 0x20000010,0x20404010,0x00404000,0x20400000, + 0x00404010,0x20404000,0x00000000,0x20400010, + 0x00000010,0x00004000,0x20400000,0x00404010, + 0x00004000,0x00400010,0x20004010,0x00000000, + 0x20404000,0x20000000,0x00400010,0x20004010}, + { 0x00200000,0x04200002,0x04000802,0x00000000, + 0x00000800,0x04000802,0x00200802,0x04200800, + 0x04200802,0x00200000,0x00000000,0x04000002, + 0x00000002,0x04000000,0x04200002,0x00000802, + 0x04000800,0x00200802,0x00200002,0x04000800, + 0x04000002,0x04200000,0x04200800,0x00200002, + 0x04200000,0x00000800,0x00000802,0x04200802, + 0x00200800,0x00000002,0x04000000,0x00200800, + 0x04000000,0x00200800,0x00200000,0x04000802, + 0x04000802,0x04200002,0x04200002,0x00000002, + 0x00200002,0x04000000,0x04000800,0x00200000, + 0x04200800,0x00000802,0x00200802,0x04200800, + 0x00000802,0x04000002,0x04200802,0x04200000, + 0x00200800,0x00000000,0x00000002,0x04200802, + 0x00000000,0x00200802,0x04200000,0x00000800, + 0x04000002,0x04000800,0x00000800,0x00200002}, + { 0x10001040,0x00001000,0x00040000,0x10041040, + 0x10000000,0x10001040,0x00000040,0x10000000, + 0x00040040,0x10040000,0x10041040,0x00041000, + 0x10041000,0x00041040,0x00001000,0x00000040, + 0x10040000,0x10000040,0x10001000,0x00001040, + 0x00041000,0x00040040,0x10040040,0x10041000, + 0x00001040,0x00000000,0x00000000,0x10040040, + 0x10000040,0x10001000,0x00041040,0x00040000, + 0x00041040,0x00040000,0x10041000,0x00001000, + 0x00000040,0x10040040,0x00001000,0x00041040, + 0x10001000,0x00000040,0x10000040,0x10040000, + 0x10040040,0x10000000,0x00040000,0x10001040, + 0x00000000,0x10041040,0x00040040,0x10000040, + 0x10040000,0x10001000,0x10001040,0x00000000, + 0x10041040,0x00041000,0x00041000,0x00001040, + 0x00001040,0x00040040,0x10000000,0x10041000} + }; + + static INLINE void IPERM(word32* left, word32* right) + { + word32 work; - *right = rotlFixed(*right^work, 9U); - work = (*left ^ *right) & 0xaaaaaaaa; - *left = rotlFixed(*left^work, 1U); - *right ^= work; -} + *right = rotlFixed(*right, 4U); + work = (*left ^ *right) & 0xf0f0f0f0; + *left ^= work; + *right = rotrFixed(*right^work, 20U); + work = (*left ^ *right) & 0xffff0000; + *left ^= work; -static INLINE void FPERM(word32* left, word32* right) -{ - word32 work; + *right = rotrFixed(*right^work, 18U); + work = (*left ^ *right) & 0x33333333; + *left ^= work; - *right = rotrFixed(*right, 1U); - work = (*left ^ *right) & 0xaaaaaaaa; - *right ^= work; + *right = rotrFixed(*right^work, 6U); + work = (*left ^ *right) & 0x00ff00ff; + *left ^= work; - *left = rotrFixed(*left^work, 9U); - work = (*left ^ *right) & 0x00ff00ff; - *right ^= work; + *right = rotlFixed(*right^work, 9U); + work = (*left ^ *right) & 0xaaaaaaaa; + *left = rotlFixed(*left^work, 1U); + *right ^= work; + } - *left = rotlFixed(*left^work, 6U); - work = (*left ^ *right) & 0x33333333; - *right ^= work; + static INLINE void FPERM(word32* left, word32* right) + { + word32 work; - *left = rotlFixed(*left^work, 18U); - work = (*left ^ *right) & 0xffff0000; - *right ^= work; + *right = rotrFixed(*right, 1U); + work = (*left ^ *right) & 0xaaaaaaaa; + *right ^= work; - *left = rotlFixed(*left^work, 20U); - work = (*left ^ *right) & 0xf0f0f0f0; - *right ^= work; + *left = rotrFixed(*left^work, 9U); + work = (*left ^ *right) & 0x00ff00ff; + *right ^= work; - *left = rotrFixed(*left^work, 4U); -} + *left = rotlFixed(*left^work, 6U); + work = (*left ^ *right) & 0x33333333; + *right ^= work; + *left = rotlFixed(*left^work, 18U); + work = (*left ^ *right) & 0xffff0000; + *right ^= work; -static int DesSetKey(const byte* key, int dir, word32* out) -{ -#ifdef WOLFSSL_SMALL_STACK - byte* buffer = (byte*)XMALLOC(56+56+8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *left = rotlFixed(*left^work, 20U); + work = (*left ^ *right) & 0xf0f0f0f0; + *right ^= work; - if (buffer == NULL) - return MEMORY_E; -#else - byte buffer[56+56+8]; -#endif + *left = rotrFixed(*left^work, 4U); + } + static int DesSetKey(const byte* key, int dir, word32* out) { - byte* const pc1m = buffer; /* place to modify pc1 into */ - byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ - byte* const ks = pcr + 56; - register int i, j, l; - int m; - - for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ - l = pc1[j] - 1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } + #define DES_KEY_BUFFER_SIZE (56+56+8) + #ifdef WOLFSSL_SMALL_STACK + byte* buffer = (byte*)XMALLOC(DES_KEY_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - for (i = 0; i < 16; i++) { /* key chunk for each iteration */ - XMEMSET(ks, 0, 8); /* Clear key schedule */ - - for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ - pcr[j] = - pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; + if (buffer == NULL) + return MEMORY_E; + #else + byte buffer[DES_KEY_BUFFER_SIZE]; + #endif - /* rotate left and right halves independently */ - for (j = 0; j < 48; j++) { /* select bits individually */ - if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ - l= j % 6; /* mask it in if it's there */ - ks[j/6] |= bytebit[l] >> 2; - } + { + byte* const pc1m = buffer; /* place to modify pc1 into */ + byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ + byte* const ks = pcr + 56; + register int i, j, l; + int m; + + for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ + l = pc1[j] - 1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ } - /* Now convert to odd/even interleaved form for use in F */ - out[2*i] = ((word32) ks[0] << 24) - | ((word32) ks[2] << 16) - | ((word32) ks[4] << 8) - | ((word32) ks[6]); - - out[2*i + 1] = ((word32) ks[1] << 24) - | ((word32) ks[3] << 16) - | ((word32) ks[5] << 8) - | ((word32) ks[7]); - } - - /* reverse key schedule order */ - if (dir == DES_DECRYPTION) { - for (i = 0; i < 16; i += 2) { - word32 swap = out[i]; - out[i] = out[DES_KS_SIZE - 2 - i]; - out[DES_KS_SIZE - 2 - i] = swap; + for (i = 0; i < 16; i++) { /* key chunk for each iteration */ + XMEMSET(ks, 0, 8); /* Clear key schedule */ - swap = out[i + 1]; - out[i + 1] = out[DES_KS_SIZE - 1 - i]; - out[DES_KS_SIZE - 1 - i] = swap; - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - } + for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ + pcr[j] = + pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; - return 0; -} + /* rotate left and right halves independently */ + for (j = 0; j < 48; j++) { /* select bits individually */ + if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ + l= j % 6; /* mask it in if it's there */ + ks[j/6] |= bytebit[l] >> 2; + } + } + /* Now convert to odd/even interleaved form for use in F */ + out[2*i] = ((word32) ks[0] << 24) + | ((word32) ks[2] << 16) + | ((word32) ks[4] << 8) + | ((word32) ks[6]); -static INLINE int Reverse(int dir) -{ - return !dir; -} + out[2*i + 1] = ((word32) ks[1] << 24) + | ((word32) ks[3] << 16) + | ((word32) ks[5] << 8) + | ((word32) ks[7]); + } + /* reverse key schedule order */ + if (dir == DES_DECRYPTION) { + for (i = 0; i < 16; i += 2) { + word32 swap = out[i]; + out[i] = out[DES_KS_SIZE - 2 - i]; + out[DES_KS_SIZE - 2 - i] = swap; -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - wc_Des_SetIV(des, iv); + swap = out[i + 1]; + out[i + 1] = out[DES_KS_SIZE - 1 - i]; + out[DES_KS_SIZE - 1 - i] = swap; + } + } - return DesSetKey(key, dir, des->key); -} + #ifdef WOLFSSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + return 0; + } -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - int ret; + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + wc_Des_SetIV(des, iv); -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3SetKey(des, key, iv); + return DesSetKey(key, dir, des->key); } -#endif - ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); - if (ret != 0) - return ret; + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int ret; - ret = DesSetKey(key + 8, Reverse(dir), des->key[1]); - if (ret != 0) - return ret; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + /* key_raw holds orignal key copy */ + des->key_raw = key; + des->iv_raw = iv; - ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); - if (ret != 0) - return ret; + /* continue on to set normal key for smaller DES operations */ + } + #endif /* WOLFSSL_ASYNC_CRYPT */ - return wc_Des3_SetIV(des, iv); -} + ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); + if (ret != 0) + return ret; + ret = DesSetKey(key + 8, !dir, des->key[1]); + if (ret != 0) + return ret; -static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) -{ - word32 l = *lIn, r = *rIn, i; + ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); + if (ret != 0) + return ret; - for (i=0; i<8; i++) - { - word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; - l ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = r ^ kptr[4*i+1]; - l ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; - - work = rotrFixed(l, 4U) ^ kptr[4*i+2]; - r ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = l ^ kptr[4*i+3]; - r ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; + return wc_Des3_SetIV(des, iv); } - *lIn = l; *rIn = r; -} - + static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) + { + word32 l = *lIn, r = *rIn, i; -static void DesProcessBlock(Des* des, const byte* in, byte* out) -{ - word32 l, r; + for (i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } - XMEMCPY(&l, in, sizeof(l)); - XMEMCPY(&r, in + sizeof(l), sizeof(r)); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - IPERM(&l,&r); + *lIn = l; *rIn = r; + } - DesRawProcessBlock(&l, &r, des->key); + static void DesProcessBlock(Des* des, const byte* in, byte* out) + { + word32 l, r; - FPERM(&l,&r); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - XMEMCPY(out, &r, sizeof(r)); - XMEMCPY(out + sizeof(r), &l, sizeof(l)); -} + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); + DesRawProcessBlock(&l, &r, des->key); -static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) -{ - word32 l, r; + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); + } - XMEMCPY(&l, in, sizeof(l)); - XMEMCPY(&r, in + sizeof(l), sizeof(r)); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - IPERM(&l,&r); + static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) + { + word32 l, r; - DesRawProcessBlock(&l, &r, des->key[0]); - DesRawProcessBlock(&r, &l, des->key[1]); - DesRawProcessBlock(&l, &r, des->key[2]); + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); - FPERM(&l,&r); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - XMEMCPY(out, &r, sizeof(r)); - XMEMCPY(out + sizeof(r), &l, sizeof(l)); -} + DesRawProcessBlock(&l, &r, des->key[0]); + DesRawProcessBlock(&r, &l, des->key[1]); + DesRawProcessBlock(&l, &r, des->key[2]); + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); + } -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); - DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); - XMEMCPY(out, des->reg, DES_BLOCK_SIZE); + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } - return 0; -} + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; - - while (blocks--) { - XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); - DesProcessBlock(des, (byte*)des->tmp, out); - xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } - return 0; -} + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcEncrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DES3_CBC_ENCRYPT; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks; + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3CbcEncrypt(des, out, in, sz); + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } -#endif - - blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); - Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); - XMEMCPY(out, des->reg, DES_BLOCK_SIZE); - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks; + + #if defined(WOLFSSL_ASYNC_CRYPT) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcDecrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DES3_CBC_DECRYPT; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ -int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks; + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3CbcDecrypt(des, out, in, sz); + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } -#endif - blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); - Des3ProcessBlock(des, (byte*)des->tmp, out); - xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } -#ifdef WOLFSSL_DES_ECB + while (blocks--) { + DesProcessBlock(des, in, out); -/* One block, compatibility only */ -int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } - while (blocks--) { - DesProcessBlock(des, in, out); + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + /* printf("wc_Des3_EcbEncrypt(%016x, %016x, %d)\n", + *(unsigned long *)in, *(unsigned long *)out, sz) ; */ - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; - } - return 0; -} + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + Des3ProcessBlock(des, in, out); -#endif /* WOLFSSL_DES_ECB */ + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + #endif /* WOLFSSL_DES_ECB */ -#endif /* End wolfCrypt software implementation */ +#endif /* NEED_SOFT_DES */ void wc_Des_SetIV(Des* des, const byte* iv) @@ -1639,7 +1659,6 @@ void wc_Des_SetIV(Des* des, const byte* iv) XMEMSET(des->reg, 0, DES_BLOCK_SIZE); } - int wc_Des3_SetIV(Des3* des, const byte* iv) { if (des && iv) @@ -1651,28 +1670,35 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) } -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Des3 for use with Nitrox device */ -int wc_Des3AsyncInit(Des3* des3, int devId) +/* Initialize Des3 for use with async device */ +int wc_Des3Init(Des3* des3, void* heap, int devId) { + int ret = 0; if (des3 == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, devId); -} + des3->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, + des3->heap, devId); +#else + (void)devId; +#endif + return ret; +} -/* Free Des3 from use with Nitrox device */ -void wc_Des3AsyncFree(Des3* des3) +/* Free Des3 from use with async device */ +void wc_Des3Free(Des3* des3) { if (des3 == NULL) return; - wolfAsync_DevCtxFree(&des3->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES); #endif /* WOLFSSL_ASYNC_CRYPT */ +} #endif /* WOLFSSL_TI_CRYPT */ #endif /* HAVE_FIPS */ diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c old mode 100644 new mode 100755 index b300e5e0d3..f6e2caf21d --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -30,6 +30,15 @@ #include #include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + #if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST) #include @@ -39,48 +48,502 @@ /* user's own math lib */ #endif +#ifdef HAVE_FFDHE_2048 +static const byte dh_ffdhe2048_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe2048_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe2048_Get(void) +{ + static const DhParams ffdhe2048 = { + dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p), + dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g) + }; + return &ffdhe2048; +} +#endif -#if !defined(WOLFSSL_HAVE_MIN) && !defined(WOLFSSL_DH_CONST) -#define WOLFSSL_HAVE_MIN +#ifdef HAVE_FFDHE_3072 +static const byte dh_ffdhe3072_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe3072_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe3072_Get(void) +{ + static const DhParams ffdhe3072 = { + dh_ffdhe3072_p, sizeof(dh_ffdhe3072_p), + dh_ffdhe3072_g, sizeof(dh_ffdhe3072_g) + }; + return &ffdhe3072; +} +#endif - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } +#ifdef HAVE_FFDHE_4096 +static const byte dh_ffdhe4096_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe4096_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe4096_Get(void) +{ + static const DhParams ffdhe4096 = { + dh_ffdhe4096_p, sizeof(dh_ffdhe4096_p), + dh_ffdhe4096_g, sizeof(dh_ffdhe4096_g) + }; + return &ffdhe4096; +} +#endif -#endif /* WOLFSSL_HAVE_MIN */ +#ifdef HAVE_FFDHE_6144 +static const byte dh_ffdhe6144_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe6144_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe6144_Get(void) +{ + static const DhParams ffdhe6144 = { + dh_ffdhe6144_p, sizeof(dh_ffdhe6144_p), + dh_ffdhe6144_g, sizeof(dh_ffdhe6144_g) + }; + return &ffdhe6144; +} +#endif +#ifdef HAVE_FFDHE_8192 +static const byte dh_ffdhe8192_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe8192_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe8192_Get(void) +{ + static const DhParams ffdhe8192 = { + dh_ffdhe8192_p, sizeof(dh_ffdhe8192_p), + dh_ffdhe8192_g, sizeof(dh_ffdhe8192_g) + }; + return &ffdhe8192; +} +#endif -void wc_InitDhKey(DhKey* key) +int wc_InitDhKey_ex(DhKey* key, void* heap, int devId) { - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = NULL; - key->g.dp = NULL; + int ret = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + key->heap = heap; /* for XMALLOC/XFREE in future */ + + if (mp_init_multi(&key->p, &key->g, NULL, NULL, NULL, NULL) != MP_OKAY) + return MEMORY_E; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH, + key->heap, devId); +#else + (void)devId; #endif + + return ret; +} + +int wc_InitDhKey(DhKey* key) +{ + return wc_InitDhKey_ex(key, NULL, INVALID_DEVID); } void wc_FreeDhKey(DhKey* key) { - (void)key; - mp_clear(&key->p); - mp_clear(&key->g); + if (key) { + mp_clear(&key->p); + mp_clear(&key->g); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH); + #endif + } } /* if defined to not use floating point values do not compile in */ #ifndef WOLFSSL_DH_CONST -static word32 DiscreteLogWorkFactor(word32 n) -{ - /* assuming discrete log takes about the same time as factoring */ - if (n<5) - return 0; - else - return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * - XPOW(XLOG((double)n), 2.0/3.0) - 5); -} + static word32 DiscreteLogWorkFactor(word32 n) + { + /* assuming discrete log takes about the same time as factoring */ + if (n < 5) + return 0; + else + return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * + XPOW(XLOG((double)n), 2.0/3.0) - 5); + } #endif /* WOLFSSL_DH_CONST*/ @@ -100,9 +563,9 @@ static word32 DiscreteLogWorkFactor(word32 n) #endif -static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) +static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) { - int ret; + int ret = 0; word32 sz = mp_unsigned_bin_size(&key->p); /* Table of predetermined values from the operation @@ -120,33 +583,31 @@ static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) case 896: sz = 49; break; case 1024: sz = 52; break; default: - #ifndef WOLFSSL_DH_CONST - /* if using floating points and size of p is not in table */ - sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / - WOLFSSL_BIT_SIZE + 1); - break; - #else - return BAD_FUNC_ARG; - #endif + #ifndef WOLFSSL_DH_CONST + /* if using floating points and size of p is not in table */ + sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / + WOLFSSL_BIT_SIZE + 1); + break; + #else + return BAD_FUNC_ARG; + #endif } ret = wc_RNG_GenerateBlock(rng, priv, sz); - if (ret != 0) - return ret; - - priv[0] |= 0x0C; - *privSz = sz; + if (ret == 0) { + priv[0] |= 0x0C; + *privSz = sz; + } - return 0; + return ret; } -static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, - byte* pub, word32* pubSz) +static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, + byte* pub, word32* pubSz) { int ret = 0; - mp_int x; mp_int y; @@ -171,24 +632,163 @@ static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, return ret; } +static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + + ret = GeneratePrivateDh(key, rng, priv, privSz); -int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz, - byte* pub, word32* pubSz) + return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz); +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) { - int ret = GeneratePrivate(key, rng, priv, privSz); + int ret; - return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz); +#if defined(HAVE_INTEL_QA) + mp_int x; + + ret = mp_init(&x); + if (ret != MP_OKAY) + return ret; + + ret = GeneratePrivateDh(key, rng, priv, privSz); + if (ret == 0) + ret = mp_read_unsigned_bin(&x, priv, *privSz); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&x, &x.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->g, &key->g.raw); + if (ret == MP_OKAY) + ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw, + &x.raw, pub, pubSz); + mp_clear(&x); + +#else + + #if defined(HAVE_CAVIUM) + /* TODO: Not implemented - use software for now */ + + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DH_GEN; + testDev->dhGen.key = key; + testDev->dhGen.rng = rng; + testDev->dhGen.priv = priv; + testDev->dhGen.privSz = privSz; + testDev->dhGen.pub = pub; + testDev->dhGen.pubSz = pubSz; + return WC_PENDING_E; + } + #endif + + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + +#endif /* HAVE_INTEL_QA */ + + return ret; } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */ -int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, - word32 privSz, const byte* otherPub, word32 pubSz) + +/* Check DH Public Key for invalid numbers + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) { int ret = 0; - mp_int x; + mp_int x; + mp_int y; + + if (key == NULL || pub == NULL) { + return BAD_FUNC_ARG; + } + + if (mp_init_multi(&x, &y, NULL, NULL, NULL, NULL) != MP_OKAY) { + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&x, pub, pubSz) != MP_OKAY) { + ret = MP_READ_E; + } + + /* pub should not be 0 or 1 */ + if (ret == 0 && mp_cmp_d(&x, 2) == MP_LT) { + ret = MP_CMP_E; + } + + /* pub shouldn't be greater than or equal to p - 1 */ + if (ret == 0 && mp_copy(&key->p, &y) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0 && mp_sub_d(&y, 2, &y) != MP_OKAY) { + ret = MP_SUB_E; + } + if (ret == 0 && mp_cmp(&x, &y) == MP_GT) { + ret = MP_CMP_E; + } + + mp_clear(&y); + mp_clear(&x); + + return ret; +} + + +int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhGenerateKeyPair_Async(key, rng, priv, privSz, pub, pubSz); + } + else +#endif + { + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + } + + return ret; +} + + +static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + mp_int x; mp_int y; mp_int z; + if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); + return DH_CHECK_PUB_E; + } + if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) return MP_INIT_E; @@ -209,7 +809,65 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, mp_clear(&z); mp_clear(&y); - mp_clear(&x); + mp_forcezero(&x); + + return ret; +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret; + +#ifdef HAVE_CAVIUM + /* TODO: Not implemented - use software for now */ + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + +#elif defined(HAVE_INTEL_QA) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = IntelQaDhAgree(&key->asyncDev, &key->p.raw, + agree, agreeSz, priv, privSz, otherPub, pubSz); +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DH_AGREE; + testDev->dhAgree.key = key; + testDev->dhAgree.agree = agree; + testDev->dhAgree.agreeSz = agreeSz; + testDev->dhAgree.priv = priv; + testDev->dhAgree.privSz = privSz; + testDev->dhAgree.otherPub = otherPub; + testDev->dhAgree.pubSz = pubSz; + return WC_PENDING_E; + } + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); +#endif + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ + +int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, + word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + + if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL || + otherPub == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } + else +#endif + { + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } return ret; } @@ -219,8 +877,9 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz) { - if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) + if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) { return BAD_FUNC_ARG; + } /* may have leading 0 */ if (p[0] == 0) { @@ -251,6 +910,4 @@ int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, return 0; } - #endif /* NO_DH */ - diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index d9ba8ac036..8719b4a56d 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -35,6 +35,13 @@ #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + enum { DSA_HALF_SIZE = 20, /* r and s size */ @@ -42,50 +49,49 @@ enum { }; -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } -#endif /* WOLFSSL_HAVE_MIN */ - - -void wc_InitDsaKey(DsaKey* key) +int wc_InitDsaKey(DsaKey* key) { + if (key == NULL) + return BAD_FUNC_ARG; + key->type = -1; /* haven't decided yet */ key->heap = NULL; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = 0; /* public alloc parts */ - key->q.dp = 0; - key->g.dp = 0; - key->y.dp = 0; - - key->x.dp = 0; /* private alloc parts */ -#endif + return mp_init_multi( + /* public alloc parts */ + &key->p, + &key->q, + &key->g, + &key->y, + + /* private alloc parts */ + &key->x, + NULL + ); } int wc_InitDsaKey_h(DsaKey* key, void* h) { - wc_InitDsaKey(key); - key->heap = h; + int ret = wc_InitDsaKey(key); + if (ret == 0) + key->heap = h; - return 0; + return ret; } void wc_FreeDsaKey(DsaKey* key) { - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH + if (key == NULL) + return; + if (key->type == DSA_PRIVATE) - mp_clear(&key->x); + mp_forcezero(&key->x); + +#ifndef USE_FAST_MATH + mp_clear(&key->x); mp_clear(&key->y); mp_clear(&key->g); mp_clear(&key->q); @@ -151,7 +157,7 @@ int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) } dsa->type = DSA_PRIVATE; - + return MP_OKAY; } @@ -315,7 +321,13 @@ int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) } /* find a value g for which g^tmp2 != 1 */ - mp_set(&dsa->g, 1); + if (mp_set(&dsa->g, 1) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return MP_INIT_E; + } do { err = mp_add_d(&dsa->g, 1, &dsa->g); @@ -359,7 +371,7 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) byte* tmp = out; /* initial output pointer */ sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q)); - + if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) return MP_INIT_E; @@ -373,12 +385,12 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) ret = MP_READ_E; - + /* k is a random numnber and it should be less than q * if k greater than repeat */ } while (mp_cmp(&k, &key->q) != MP_LT); - + if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT) ret = MP_CMP_E; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c old mode 100644 new mode 100755 index ecdc408a21..3fb8287c4f --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -35,14 +35,21 @@ Possible ECC enable options: * HAVE_ECC_SIGN: ECC sign default: on * HAVE_ECC_VERIFY: ECC verify default: on * HAVE_ECC_DHE: ECC build shared secret default: on + * HAVE_ECC_CDH: ECC cofactor DH shared secret default: off * HAVE_ECC_KEY_IMPORT: ECC Key import default: on * HAVE_ECC_KEY_EXPORT: ECC Key export default: on * ECC_SHAMIR: Enables Shamir calc method default: on * HAVE_COMP_KEY: Enables compressed key default: off * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import default: off + * WOLFSSL_VALIDATE_ECC_KEYGEN: Validate ECC key gen default: off * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off * Includes the curve "a" variable in calculation - * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off + * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off + * ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance + default: off + * FP_ECC: ECC Fixed Point Cache default: off + * USE_ECC_B_PARAM: Enable ECC curve B param default: off + (on for HAVE_COMP_KEY) */ /* @@ -118,6 +125,22 @@ ECC Curve Sizes: #endif +/* internal ECC states */ +enum { + ECC_STATE_NONE = 0, + + ECC_STATE_SHARED_SEC_GEN, + ECC_STATE_SHARED_SEC_RES, + + ECC_STATE_SIGN_DO, + ECC_STATE_SIGN_ENCODE, + + ECC_STATE_VERIFY_DECODE, + ECC_STATE_VERIFY_DO, + ECC_STATE_VERIFY_RES, +}; + + /* map ptmul -> mulmod */ @@ -912,6 +935,7 @@ const ecc_set_type ecc_sets[] = { NULL, 0, 0, 0 } }; +#define ECC_SET_COUNT (sizeof(ecc_sets)/sizeof(ecc_set_type)) #ifdef HAVE_OID_ENCODING /* encoded OID cache */ @@ -919,20 +943,16 @@ const ecc_set_type ecc_sets[] = { word32 oidSz; byte oid[ECC_MAX_OID_LEN]; } oid_cache_t; - static oid_cache_t ecc_oid_cache[sizeof(ecc_sets)/sizeof(ecc_set_type)]; + static oid_cache_t ecc_oid_cache[ECC_SET_COUNT]; #endif + #ifdef HAVE_COMP_KEY static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); #endif #ifndef WOLFSSL_ATECC508A -int ecc_map(ecc_point*, mp_int*, mp_digit); -int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, - mp_int* a, mp_int* modulus, mp_digit mp); -int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, - mp_int* modulus, mp_digit mp); static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, mp_int* order); #ifdef ECC_SHAMIR static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, @@ -942,10 +962,276 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, int mp_jacobi(mp_int* a, mp_int* n, int* c); int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); + +/* Curve Specs */ +typedef struct ecc_curve_spec { + const ecc_set_type* dp; + + mp_int* prime; + mp_int* Af; + #ifdef USE_ECC_B_PARAM + mp_int* Bf; + #endif + mp_int* order; + mp_int* Gx; + mp_int* Gy; + +#ifdef ECC_CACHE_CURVE + mp_int prime_lcl; + mp_int Af_lcl; + #ifdef USE_ECC_B_PARAM + mp_int Bf_lcl; + #endif + mp_int order_lcl; + mp_int Gx_lcl; + mp_int Gy_lcl; +#else + mp_int* spec_ints; + word32 spec_count; + word32 spec_use; +#endif + + byte load_mask; +} ecc_curve_spec; + +enum ecc_curve_load_mask { + ECC_CURVE_FIELD_NONE = 0x00, + ECC_CURVE_FIELD_PRIME = 0x01, + ECC_CURVE_FIELD_AF = 0x02, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_BF = 0x04, +#endif + ECC_CURVE_FIELD_ORDER = 0x08, + ECC_CURVE_FIELD_GX = 0x10, + ECC_CURVE_FIELD_GY = 0x20, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_ALL = 0x3F, + ECC_CURVE_FIELD_COUNT = 6, +#else + ECC_CURVE_FIELD_ALL = 0x3B, + ECC_CURVE_FIELD_COUNT = 5, +#endif +}; + +#ifdef ECC_CACHE_CURVE + /* cache (mp_int) of the curve parameters */ + static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT]; + #ifndef SINGLE_THREADED + static wolfSSL_Mutex ecc_curve_cache_mutex; + #endif + + #define DECLARE_CURVE_SPECS(intcount) ecc_curve_spec* curve = NULL; +#else + #define DECLARE_CURVE_SPECS(intcount) \ + mp_int spec_ints[(intcount)]; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_ints = spec_ints; \ + curve->spec_count = intcount; +#endif /* ECC_CACHE_CURVE */ + +static void _wc_ecc_curve_free(ecc_curve_spec* curve) +{ + if (curve == NULL) { + return; + } + + if (curve->load_mask & ECC_CURVE_FIELD_PRIME) + mp_clear(curve->prime); + if (curve->load_mask & ECC_CURVE_FIELD_AF) + mp_clear(curve->Af); +#ifdef USE_ECC_B_PARAM + if (curve->load_mask & ECC_CURVE_FIELD_BF) + mp_clear(curve->Bf); +#endif + if (curve->load_mask & ECC_CURVE_FIELD_ORDER) + mp_clear(curve->order); + if (curve->load_mask & ECC_CURVE_FIELD_GX) + mp_clear(curve->Gx); + if (curve->load_mask & ECC_CURVE_FIELD_GY) + mp_clear(curve->Gy); + + curve->load_mask = 0; +} + +static void wc_ecc_curve_free(ecc_curve_spec* curve) +{ + /* don't free cached curves */ +#ifndef ECC_CACHE_CURVE + _wc_ecc_curve_free(curve); +#endif + (void)curve; +} + +static int wc_ecc_curve_load_item(const char* src, mp_int** dst, + ecc_curve_spec* curve, byte mask) +{ + int err; + +#ifndef ECC_CACHE_CURVE + /* get mp_int from temp */ + if (curve->spec_use >= curve->spec_count) { + WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count"); + return ECC_BAD_ARG_E; + } + *dst = &curve->spec_ints[curve->spec_use++]; +#endif + + err = mp_init(*dst); + if (err == MP_OKAY) { + curve->load_mask |= mask; + + err = mp_read_radix(*dst, src, 16); + + #ifdef HAVE_WOLF_BIGINT + if (err == MP_OKAY) + err = wc_mp_to_bigint(*dst, &(*dst)->raw); + #endif + } + return err; +} + +static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, + byte load_mask) +{ + int ret = 0, x; + ecc_curve_spec* curve; + byte load_items = 0; /* mask of items to load */ + + if (dp == NULL || pCurve == NULL) + return BAD_FUNC_ARG; + +#ifdef ECC_CACHE_CURVE + x = wc_ecc_get_curve_idx(dp->id); + if (x == ECC_CURVE_INVALID) + return ECC_BAD_ARG_E; + + /* make sure cache has been allocated */ + if (ecc_curve_spec_cache[x] == NULL) { + ecc_curve_spec_cache[x] = (ecc_curve_spec*)XMALLOC( + sizeof(ecc_curve_spec), NULL, DYNAMIC_TYPE_ECC); + if (ecc_curve_spec_cache[x] == NULL) + return MEMORY_E; + XMEMSET(ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec)); + } + + /* set curve pointer to cache */ + *pCurve = ecc_curve_spec_cache[x]; + +#endif /* ECC_CACHE_CURVE */ + curve = *pCurve; + + /* make sure the curve is initialized */ + if (curve->dp != dp) { + curve->load_mask = 0; + + #ifdef ECC_CACHE_CURVE + curve->prime = &curve->prime_lcl; + curve->Af = &curve->Af_lcl; + #ifdef USE_ECC_B_PARAM + curve->Bf = &curve->Bf_lcl; + #endif + curve->order = &curve->order_lcl; + curve->Gx = &curve->Gx_lcl; + curve->Gy = &curve->Gy_lcl; + #endif + } + curve->dp = dp; /* set dp info */ + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + ret = wc_LockMutex(&ecc_curve_cache_mutex); + if (ret != 0) { + return MEMORY_E; + } +#endif + + /* determine items to load */ + load_items = (~curve->load_mask & load_mask); + curve->load_mask |= load_items; + + /* load items */ + x = 0; + if (load_items & ECC_CURVE_FIELD_PRIME) + x += wc_ecc_curve_load_item(dp->prime, &curve->prime, curve, + ECC_CURVE_FIELD_PRIME); + if (load_items & ECC_CURVE_FIELD_AF) + x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve, + ECC_CURVE_FIELD_AF); +#ifdef USE_ECC_B_PARAM + if (load_items & ECC_CURVE_FIELD_BF) + x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve, + ECC_CURVE_FIELD_BF); +#endif + if (load_items & ECC_CURVE_FIELD_ORDER) + x += wc_ecc_curve_load_item(dp->order, &curve->order, curve, + ECC_CURVE_FIELD_ORDER); + if (load_items & ECC_CURVE_FIELD_GX) + x += wc_ecc_curve_load_item(dp->Gx, &curve->Gx, curve, + ECC_CURVE_FIELD_GX); + if (load_items & ECC_CURVE_FIELD_GY) + x += wc_ecc_curve_load_item(dp->Gy, &curve->Gy, curve, + ECC_CURVE_FIELD_GY); + + /* check for error */ + if (x != 0) { + wc_ecc_curve_free(curve); + ret = MP_READ_E; + } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_UnLockMutex(&ecc_curve_cache_mutex); +#endif + + return ret; +} + +#ifdef ECC_CACHE_CURVE +int wc_ecc_curve_cache_init(void) +{ + int ret = 0; +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + ret = wc_InitMutex(&ecc_curve_cache_mutex); +#endif + return ret; +} + +void wc_ecc_curve_cache_free(void) +{ + int x; + + /* free all ECC curve caches */ + for (x = 0; x < (int)ECC_SET_COUNT; x++) { + if (ecc_curve_spec_cache[x]) { + _wc_ecc_curve_free(ecc_curve_spec_cache[x]); + XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC); + ecc_curve_spec_cache[x] = NULL; + } + } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_FreeMutex(&ecc_curve_cache_mutex); +#endif +} +#endif /* ECC_CACHE_CURVE */ + #endif /* WOLFSSL_ATECC508A */ -static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) +/* Retrieve the curve name for the ECC curve id. + * + * curve_id The id of the curve. + * returns the name stored from the curve if available, otherwise NULL. + */ +const char* wc_ecc_get_name(int curve_id) +{ + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return NULL; + return ecc_sets[curve_idx].name; +} + +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) { if (keysize <= 0 && curve_id <= 0) { return BAD_FUNC_ARG; @@ -970,7 +1256,8 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) } } if (ecc_sets[x].size == 0) { - return ECC_BAD_ARG_E; + WOLFSSL_MSG("ECC Curve not found"); + return ECC_CURVE_OID_E; } key->idx = x; @@ -982,24 +1269,6 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) #ifndef WOLFSSL_ATECC508A -/* helper for either lib */ -static int get_digit_count(mp_int* a) -{ - if (a == NULL) - return 0; - - return a->used; -} - -/* helper for either lib */ -static mp_digit get_digit(mp_int* a, int n) -{ - if (a == NULL) - return 0; - - return (n >= a->used || n < 0) ? 0 : a->dp[n]; -} - /** Add two ECC points P The point to add @@ -1042,10 +1311,8 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if ( (mp_cmp(P->x, Q->x) == MP_EQ) && (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) { - #ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); - #endif return ecc_projective_dbl_point(P, R, a, modulus, mp); } } @@ -1271,11 +1538,10 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, #endif done: -#ifndef USE_FAST_MATH + /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -1333,10 +1599,8 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, z = &rz; if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { - #ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); - #endif return err; } #else @@ -1543,11 +1807,9 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, err = mp_copy(z, R->z); #endif -#ifndef USE_FAST_MATH /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -1574,10 +1836,12 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) /* special case for point at infinity */ if (mp_cmp_d(P->z, 0) == MP_EQ) { - mp_set(P->x, 0); - mp_set(P->y, 0); - mp_set(P->z, 1); - return MP_OKAY; + err = mp_set(P->x, 0); + if (err == MP_OKAY) + err = mp_set(P->y, 0); + if (err == MP_OKAY) + err = mp_set(P->z, 1); + return err; } if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { @@ -1600,6 +1864,10 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) err = mp_copy(P->y, y); if (err == MP_OKAY) err = mp_copy(P->z, z); + + if (err != MP_OKAY) { + goto done; + } #else /* Use destination directly */ x = P->x; @@ -1607,10 +1875,6 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) z = P->z; #endif - if (err != MP_OKAY) { - goto done; - } - /* first map z back to normal */ err = mp_montgomery_reduce(z, modulus, mp); @@ -1639,32 +1903,29 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) err = mp_montgomery_reduce(y, modulus, mp); if (err == MP_OKAY) - mp_set(z, 1); + err = mp_set(z, 1); #ifdef ALT_ECC_SIZE /* return result */ - mp_copy(x, P->x); - mp_copy(y, P->y); - mp_copy(z, P->z); -#endif + if (err == MP_OKAY) + err = mp_copy(x, P->x); + if (err == MP_OKAY) + err = mp_copy(y, P->y); + if (err == MP_OKAY) + err = mp_copy(z, P->z); done: - /* clean up */ -#ifndef USE_FAST_MATH +#endif + + /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } #if !defined(FREESCALE_LTC_ECC) -#ifndef ECC_TIMING_RESISTANT - -/* size of sliding window, don't change this! */ -#define WINSIZE 4 - /** Perform a point multiplication k The scalar to multiply by @@ -1678,22 +1939,33 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) */ #ifdef FP_ECC static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, + void* heap) #else int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, + void* heap) #endif { - ecc_point *tG, *M[8]; - int i, j, err; +#ifndef ECC_TIMING_RESISTANT + /* size of sliding window, don't change this! */ + #define WINSIZE 4 + #define M_POINTS 8 + int first = 1, bitbuf = 0, bitcpy = 0, j; +#else + #define M_POINTS 3 +#endif + + ecc_point *tG, *M[M_POINTS]; + int i, err; mp_int mu; mp_digit mp; mp_digit buf; - int first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0, - digidx = 0; + int bitcnt = 0, mode = 0, digidx = 0; - if (k == NULL || G == NULL || R == NULL || modulus == NULL) + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; + } /* init variables */ tG = NULL; @@ -1703,6 +1975,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { return err; } + if ((err = mp_init(&mu)) != MP_OKAY) { return err; } @@ -1712,16 +1985,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } /* alloc ram for window temps */ - for (i = 0; i < 8; i++) { + for (i = 0; i < M_POINTS; i++) { M[i] = wc_ecc_new_point_h(heap); if (M[i] == NULL) { - for (j = 0; j < i; j++) { - wc_ecc_del_point_h(M[j], heap); - } - #ifndef USE_FAST_MATH mp_clear(&mu); - #endif - return MEMORY_E; + err = MEMORY_E; goto exit; } } @@ -1747,10 +2015,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } } -#ifndef USE_FAST_MATH /* done with mu */ mp_clear(&mu); -#endif + +#ifndef ECC_TIMING_RESISTANT /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ @@ -1764,7 +2032,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* now find (8+k)G for k=1..7 */ if (err == MP_OKAY) for (j = 9; j < 16; j++) { - err = ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus, mp); + err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a, + modulus, mp); if (err != MP_OKAY) break; } @@ -1812,13 +2081,13 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* if this is the first window we do a simple copy */ if (first == 1) { /* R = kG [k = first window] */ - err = mp_copy(M[bitbuf-8]->x, R->x); + err = mp_copy(M[bitbuf-M_POINTS]->x, R->x); if (err != MP_OKAY) break; - err = mp_copy(M[bitbuf-8]->y, R->y); + err = mp_copy(M[bitbuf-M_POINTS]->y, R->y); if (err != MP_OKAY) break; - err = mp_copy(M[bitbuf-8]->z, R->z); + err = mp_copy(M[bitbuf-M_POINTS]->z, R->z); first = 0; } else { /* normal window */ @@ -1831,7 +2100,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (err != MP_OKAY) break; /* out of first for(;;) */ /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ - err = ecc_projective_add_point(R, M[bitbuf-8], R, a, + err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a, modulus, mp); } if (err != MP_OKAY) break; @@ -1877,127 +2146,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } } - /* map R back from projective space */ - if (err == MP_OKAY && map) - err = ecc_map(R, modulus, mp); - - wc_ecc_del_point_h(tG, heap); - for (i = 0; i < 8; i++) { - wc_ecc_del_point_h(M[i], heap); - } - return err; -} - -#ifndef FP_ECC -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, int map) -{ - return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); -} -#endif /* !FP_ECC */ -#undef WINSIZE + #undef WINSIZE #else /* ECC_TIMING_RESISTANT */ - -#ifndef WC_NO_CACHE_RESISTANT -#if defined(TFM_TIMING_RESISTANT) && defined(USE_FAST_MATH) && \ - !defined(__cplusplus) - /* let's use the one we already have */ - extern const wolfssl_word wc_off_on_addr[2]; -#else - static const wolfssl_word wc_off_on_addr[2] = - { - #if defined(WC_64BIT_CPU) - W64LIT(0x0000000000000000), - W64LIT(0xffffffffffffffff) - #elif defined(WC_16BIT_CPU) - 0x0000U, - 0xffffU - #else - /* 32 bit */ - 0x00000000U, - 0xffffffffU - #endif - }; -#endif /* TFM_TIMING_RESISTANT && USE_FAST_MATH */ -#endif /* WC_NO_CACHE_RESISTANT */ - -/** - Perform a point multiplication (timing resistant) - k The scalar to multiply by - G The base point - R [out] Destination for kG - a ECC curve parameter a - modulus The modulus of the field the ECC curve is in - map Boolean whether to map back to affine or not - (1==map, 0 == leave in projective) - return MP_OKAY on success -*/ -#ifdef FP_ECC -static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) -#else -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) -#endif -{ - ecc_point *tG, *M[3]; - int i, j, err; - mp_int mu; - mp_digit mp; - mp_digit buf; - int bitcnt = 0, mode = 0, digidx = 0; - - if (k == NULL || G == NULL || R == NULL || modulus == NULL) - return ECC_BAD_ARG_E; - - /* init variables */ - tG = NULL; - XMEMSET(M, 0, sizeof(M)); - - /* init montgomery reduction */ - if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { - return err; - } - if ((err = mp_init(&mu)) != MP_OKAY) { - return err; - } - if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { - mp_clear(&mu); - return err; - } - - /* alloc ram for window temps */ - for (i = 0; i < 3; i++) { - M[i] = wc_ecc_new_point_h(heap); - if (M[i] == NULL) { - for (j = 0; j < i; j++) { - wc_ecc_del_point_h(M[j], heap); - } - mp_clear(&mu); - return MEMORY_E; - } - } - - /* make a copy of G in case R==G */ - tG = wc_ecc_new_point_h(heap); - if (tG == NULL) - err = MEMORY_E; - - /* tG = G and convert to montgomery */ - if (err == MP_OKAY) - err = mp_mulmod(G->x, &mu, modulus, tG->x); - if (err == MP_OKAY) - err = mp_mulmod(G->y, &mu, modulus, tG->y); - if (err == MP_OKAY) - err = mp_mulmod(G->z, &mu, modulus, tG->z); - -#ifndef USE_FAST_MATH - /* done with mu */ - mp_clear(&mu); -#endif - /* calc the M tab */ /* M[0] == G */ if (err == MP_OKAY) @@ -2114,27 +2266,38 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (err == MP_OKAY) err = mp_copy(M[0]->z, R->z); +#endif /* ECC_TIMING_RESISTANT */ + /* map R back from projective space */ if (err == MP_OKAY && map) - err = ecc_map(R, modulus, mp); + err = ecc_map(R, modulus, mp); + +exit: /* done */ wc_ecc_del_point_h(tG, heap); - for (i = 0; i < 3; i++) { + for (i = 0; i < M_POINTS; i++) { wc_ecc_del_point_h(M[i], heap); } + return err; } - -#ifndef FP_ECC +/** ECC Fixed Point mulmod global + k The multiplicand + G Base point to multiply + R [out] Destination of product + a ECC curve parameter a + modulus The modulus for the curve + map [boolean] If non-zero maps the point back to affine co-ordinates, + otherwise it's left in jacobian-montgomery form + return MP_OKAY if successful +*/ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, int map) + mp_int* modulus, int map) { return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } -#endif /* ! FP_ECC */ -#endif /* ECC_TIMING_RESISTANT */ #endif /* !FREESCALE_LTC_ECC */ @@ -2164,12 +2327,6 @@ ecc_point* wc_ecc_new_point_h(void* heap) } XMEMSET(p, 0, sizeof(ecc_point)); -#ifndef USE_FAST_MATH - p->x->dp = NULL; - p->y->dp = NULL; - p->z->dp = NULL; -#endif - #ifndef ALT_ECC_SIZE if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) { XFREE(p, heap, DYNAMIC_TYPE_ECC); @@ -2294,9 +2451,206 @@ int wc_ecc_is_valid_idx(int n) return 0; } -#ifdef HAVE_ECC_DHE -/** - Create an ECC shared secret between two keys +int wc_ecc_get_curve_idx(int curve_id) +{ + int curve_idx; + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (curve_id == ecc_sets[curve_idx].id) + break; + } + if (ecc_sets[curve_idx].size == 0) { + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +int wc_ecc_get_curve_id(int curve_idx) +{ + if (wc_ecc_is_valid_idx(curve_idx)) { + return ecc_sets[curve_idx].id; + } + return ECC_CURVE_INVALID; +} + +/* Returns the curve size that corresponds to a given ecc_curve_id identifier + * + * id curve id, from ecc_curve_id enum in ecc.h + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_id(int curve_id) +{ + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return ECC_BAD_ARG_E; + return ecc_sets[curve_idx].size; +} + +/* Returns the curve index that corresponds to a given curve name in + * ecc_sets[] of ecc.c + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve index in ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_idx_from_name(const char* curveName) +{ + int curve_idx; + word32 len; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + len = (word32)XSTRLEN(curveName); + + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (XSTRNCASECMP(ecc_sets[curve_idx].name, curveName, len) == 0) { + break; + } + } + if (ecc_sets[curve_idx].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +/* Returns the curve size that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].size; +} + +/* Returns the curve id that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].id; +} + +/* Compares a curve parameter (hex, from ecc_sets[]) to given input + * parameter (byte array) for equality. + * + * Returns MP_EQ on success, negative on error */ +static int wc_ecc_cmp_param(const char* curveParam, + const byte* param, word32 paramSz) +{ + int err = MP_OKAY; + mp_int a, b; + + if (param == NULL || curveParam == NULL) + return BAD_FUNC_ARG; + + if ((err = mp_init_multi(&a, &b, NULL, NULL, NULL, NULL)) != MP_OKAY) + return err; + + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&a, param, paramSz); + + if (err == MP_OKAY) + err = mp_read_radix(&b, curveParam, 16); + + if (err == MP_OKAY) { + if (mp_cmp(&a, &b) != MP_EQ) { + err = -1; + } else { + err = MP_EQ; + } + } + +#ifndef USE_FAST_MATH + mp_clear(&a); + mp_clear(&b); +#endif + + return err; +} + +/* Returns the curve id in ecc_sets[] that corresponds to a given set of + * curve parameters. + * + * fieldSize the field size in bits + * prime prime of the finite field + * primeSz size of prime in octets + * Af first coefficient a of the curve + * AfSz size of Af in octets + * Bf second coefficient b of the curve + * BfSz size of Bf in octets + * order curve order + * orderSz size of curve in octets + * Gx affine x coordinate of base point + * GxSz size of Gx in octets + * Gy affine y coordinate of base point + * GySz size of Gy in octets + * cofactor curve cofactor + * + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor) +{ + int idx; + int curveSz; + + if (prime == NULL || Af == NULL || Bf == NULL || order == NULL || + Gx == NULL || Gy == NULL) + return BAD_FUNC_ARG; + + curveSz = (fieldSize + 1) / 8; /* round up */ + + for (idx = 0; ecc_sets[idx].size != 0; idx++) { + if (curveSz == ecc_sets[idx].size) { + if ((wc_ecc_cmp_param(ecc_sets[idx].prime, prime, + primeSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, order, + orderSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz) == MP_EQ) && + (cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; +} + + +#ifdef HAVE_ECC_DHE +/** + Create an ECC shared secret between two keys private_key The private ECC key (heap hint based off of private key) public_key The public key out [out] Destination of the shared secret @@ -2307,13 +2661,7 @@ int wc_ecc_is_valid_idx(int n) int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { - int err = 0; -#ifndef WOLFSSL_ATECC508A - word32 x = 0; - ecc_point* result; - mp_int prime; - mp_int a; -#endif /* !WOLFSSL_ATECC508A */ + int err; if (private_key == NULL || public_key == NULL || out == NULL || outlen == NULL) { @@ -2331,83 +2679,166 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return ECC_BAD_ARG_E; } - /* Verify curve name matches */ - if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0) { + /* Verify curve id matches */ + if (private_key->dp->id != public_key->dp->id) { 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 - #ifdef WOLFSSL_ATECC508A err = atcatls_ecdh(private_key->slot, public_key->pubkey, out); if (err != ATCA_SUCCESS) { err = BAD_COND_E; } *outlen = private_key->dp->size; - #else + err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen); +#endif /* WOLFSSL_ATECC508A */ - /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { - return MEMORY_E; - } + return err; +} - if ((err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { - wc_ecc_del_point_h(result, private_key->heap); - return err; - } - /* read in the specs for this curve */ - err = mp_read_radix(&prime, private_key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, private_key->dp->Af, 16); +#ifndef WOLFSSL_ATECC508A - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&private_key->k, &public_key->pubkey, result, &a, - &prime, 1, private_key->heap); +static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen, ecc_curve_spec* curve) +{ + int err; + ecc_point* result = NULL; + word32 x = 0; + mp_int* k = &private_key->k; +#ifdef HAVE_ECC_CDH + mp_int k_lcl; + + /* if cofactor flag has been set */ + if (private_key->flags & WC_ECC_FLAG_COFACTOR) { + mp_digit cofactor = (mp_digit)private_key->dp->cofactor; + /* only perform cofactor calc if not equal to 1 */ + if (cofactor != 1) { + k = &k_lcl; + if (mp_init(k) != MP_OKAY) + return MEMORY_E; + /* multiply cofactor times private key "k" */ + err = mp_mul_d(&private_key->k, cofactor, k); + if (err != MP_OKAY) { + mp_clear(k); + return err; + } + } + } +#endif - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&prime); - if (*outlen < x) - err = BUFFER_E; - } + /* make new point */ + result = wc_ecc_new_point_h(private_key->heap); + if (result == NULL) { +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif + return MEMORY_E; + } - if (err == MP_OKAY) { - XMEMSET(out, 0, x); - err = mp_to_unsigned_bin(result->x,out + (x - - mp_unsigned_bin_size(result->x))); - *outlen = x; - } + err = wc_ecc_mulmod_ex(k, point, result, + curve->Af, curve->prime, 1, private_key->heap); + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(curve->prime); + if (*outlen < x) { + err = BUFFER_E; + } + } -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&prime); + if (err == MP_OKAY) { + XMEMSET(out, 0, x); + err = mp_to_unsigned_bin(result->x,out + + (x - mp_unsigned_bin_size(result->x))); + } + *outlen = x; + + wc_ecc_del_point_h(result, private_key->heap); +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); #endif - wc_ecc_del_point_h(result, private_key->heap); -#endif /* WOLFSSL_ATECC508A */ + return err; +} - return err; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, + ecc_point* point, byte* out, word32 *outlen, + ecc_curve_spec* curve) +{ + int err; + +#ifdef HAVE_CAVIUM + /* TODO: Not implemented - use software for now */ + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); + +#elif defined(HAVE_INTEL_QA) + /* sync public key x/y */ + err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&private_key->k, &private_key->k.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(point->x, &point->x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(point->y, &point->y->raw); + if (err == MP_OKAY) + err = IntelQaEcdh(&private_key->asyncDev, + &private_key->k.raw, &point->x->raw, &point->y->raw, + out, outlen, + &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, + private_key->dp->cofactor); +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &private_key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_SHARED_SEC; + testDev->eccSharedSec.private_key = private_key; + testDev->eccSharedSec.public_point = point; + testDev->eccSharedSec.out = out; + testDev->eccSharedSec.outLen = outlen; + return WC_PENDING_E; + } + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); +#endif + + return err; } +#endif /* WOLFSSL_ASYNC_CRYPT */ -#ifndef WOLFSSL_ATECC508A +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) +{ + int err; + DECLARE_CURVE_SPECS(2) + + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + + /* load curve info */ + err = wc_ecc_curve_load(private_key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + if (err != MP_OKAY) + return err; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + err = wc_ecc_shared_secret_gen_async(private_key, point, + out, outlen, curve); + } + else +#endif + { + err = wc_ecc_shared_secret_gen_sync(private_key, point, + out, outlen, curve); + } + + wc_ecc_curve_free(curve); + + return err; +} /** Create an ECC shared secret between private key and public point @@ -2418,14 +2849,10 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, outlen [in/out] The max size and resulting size of the shared secret return MP_OKAY if successful */ -int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, - byte* out, word32 *outlen) +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) { - word32 x = 0; - ecc_point* result; - mp_int prime; - mp_int a; - int err; + int err; if (private_key == NULL || point == NULL || out == NULL || outlen == NULL) { @@ -2441,50 +2868,47 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, if (wc_ecc_is_valid_idx(private_key->idx) == 0) return ECC_BAD_ARG_E; - /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { - return MEMORY_E; - } - - if ((err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { - wc_ecc_del_point_h(result, private_key->heap); - return err; - } - - /* read in the specs for this curve */ - err = mp_read_radix(&prime, private_key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, private_key->dp->Af, 16); + switch(private_key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SHARED_SEC_GEN: + private_key->state = ECC_STATE_SHARED_SEC_GEN; - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&private_key->k, point, result, &a, &prime, 1, - private_key->heap); + err = wc_ecc_shared_secret_gen(private_key, point, out, outlen); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_SHARED_SEC_RES: + private_key->state = ECC_STATE_SHARED_SEC_RES; + err = 0; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #if defined(HAVE_CAVIUM) || defined(HAVE_INTEL_QA) + err = private_key->asyncDev.event.ret; + #endif + } + #endif + break; - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&prime); - if (*outlen < x) - err = BUFFER_E; - } + default: + err = BAD_STATE_E; + } /* switch */ - if (err == MP_OKAY) { - XMEMSET(out, 0, x); - err = mp_to_unsigned_bin(result->x,out + - (x - mp_unsigned_bin_size(result->x))); - *outlen = x; + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + private_key->state++; + return err; } -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&prime); -#endif - wc_ecc_del_point_h(result, private_key->heap); + private_key->state = ECC_STATE_NONE; return err; } #endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_DHE */ + #ifndef WOLFSSL_ATECC508A /* return 1 if point is at infinity, 0 if not, < 0 on error */ int wc_ecc_point_is_at_infinity(ecc_point* p) @@ -2498,39 +2922,85 @@ int wc_ecc_point_is_at_infinity(ecc_point* p) return 0; } -#endif /* WOLFSSL_ATECC508A */ +/* generate random and ensure its greater than 0 and less than order */ +static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) +{ + int err; +#ifdef WOLFSSL_SMALL_STACK + byte* buf; +#else + byte buf[ECC_MAXSIZE_GEN]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + return MEMORY_E; +#endif + + /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ + /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ + size += 8; + + /* make up random string */ + err = wc_RNG_GenerateBlock(rng, buf, size); + /* load random buffer data into k */ + if (err == 0) + err = mp_read_unsigned_bin(k, (byte*)buf, size); + + /* quick sanity check to make sure we're not dealing with a 0 key */ + if (err == MP_OKAY) { + if (mp_iszero(k) == MP_YES) + err = MP_ZERO_E; + } + + /* the key should be smaller than the order of base point */ + if (err == MP_OKAY) { + if (mp_cmp(k, order) != MP_LT) { + err = mp_mod(k, order, k); + } + } + + ForceZero(buf, ECC_MAXSIZE); +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* !WOLFSSL_ATECC508A */ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) { int err; #ifndef WOLFSSL_ATECC508A ecc_point* base = NULL; - mp_int prime; - mp_int a; - mp_int order; -#ifdef WOLFSSL_SMALL_STACK - byte* buf; -#else - byte buf[ECC_MAXSIZE_GEN]; + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) #endif -#endif /* !WOLFSSL_ATECC508A */ if (key == NULL || rng == NULL) { return BAD_FUNC_ARG; } + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; + key->idx = 0; + key->dp = NULL; + err = wc_ecc_set_curve(key, keysize, curve_id); if (err != 0) { return err; } -#ifdef WOLFSSL_ASYNC_CRYPT +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { #ifdef HAVE_CAVIUM /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + /* TODO: Not implemented */ #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; + WC_ASYNC_TEST* testDev = &key->asyncDev.test; if (testDev->type == ASYNC_TEST_NONE) { testDev->type = ASYNC_TEST_ECC_MAKE; testDev->eccMake.rng = rng; @@ -2541,7 +3011,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) } #endif } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_ATECC508A key->type = ECC_PRIVATEKEY; @@ -2552,99 +3022,53 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) #else -#ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) - return MEMORY_E; -#endif - - /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ - /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ - keysize = key->dp->size + 8; - - /* make up random string */ - err = wc_RNG_GenerateBlock(rng, buf, keysize); - if (err != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return err; - } - /* setup the key variables */ - err = mp_init_multi(&key->k, &prime, &order, &a, NULL, NULL); - if (err != MP_OKAY) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err = mp_init(&key->k); + if (err == MP_OKAY) { + #ifndef ALT_ECC_SIZE + err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL, NULL); + #else + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); #endif - return err; } -#ifndef ALT_ECC_SIZE - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL, NULL); -#else - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; - key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; - key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; - alt_fp_init(key->pubkey.x); - alt_fp_init(key->pubkey.y); - alt_fp_init(key->pubkey.z); -#endif - if (err == MP_OKAY) { base = wc_ecc_new_point_h(key->heap); if (base == NULL) err = MEMORY_E; } - /* read in the specs for this curve */ + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&prime, key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&order, key->dp->order, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); /* read in the x/y for this key */ if (err == MP_OKAY) - err = mp_read_radix(base->x, key->dp->Gx, 16); + err = mp_copy(curve->Gx, base->x); if (err == MP_OKAY) - err = mp_read_radix(base->y, key->dp->Gy, 16); + err = mp_copy(curve->Gy, base->y); if (err == MP_OKAY) - mp_set(base->z, 1); + err = mp_set(base->z, 1); - /* load random buffer data into k */ + /* generate k */ if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize); - - /* quick sanity check to make sure we're not dealing with a 0 key */ - if (err == MP_OKAY) { - if (mp_iszero(&key->k) == MP_YES) - err = MP_ZERO_E; - } - - /* the key should be smaller than the order of base point */ - if (err == MP_OKAY) { - if (mp_cmp(&key->k, &order) != MP_LT) - err = mp_mod(&key->k, &order, &key->k); - } - - /* the key should be smaller than the order of base point */ - if (err == MP_OKAY) { - if (mp_cmp(&key->k, &order) != MP_LT) - err = mp_mod(&key->k, &order, &key->k); - } + err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order); /* make the public key */ if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, &a, &prime, 1, - key->heap); + err = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, + curve->Af, curve->prime, 1, key->heap); #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN /* validate the public key, order * pubkey = point at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &a, &prime, &order); + err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order); #endif /* WOLFSSL_VALIDATE_KEYGEN */ if (err == MP_OKAY) @@ -2652,24 +3076,19 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) /* cleanup these on failure case only */ if (err != MP_OKAY) { + /* clean up */ + #ifndef ALT_ECC_SIZE mp_clear(key->pubkey.x); mp_clear(key->pubkey.y); mp_clear(key->pubkey.z); + #endif mp_forcezero(&key->k); } /* cleanup allocations */ wc_ecc_del_point_h(base, key->heap); -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&prime); - mp_clear(&order); -#endif + wc_ecc_curve_free(curve); - ForceZero(buf, ECC_MAXSIZE); -#ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif #endif /* WOLFSSL_ATECC508A */ return err; @@ -2745,6 +3164,65 @@ 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); } +static INLINE int wc_ecc_alloc_rs(ecc_key* key, mp_int** r, mp_int** s) +{ + int err = 0; + +#ifndef WOLFSSL_ASYNC_CRYPT + (void)key; +#endif + + if (*r == NULL) { + #ifdef WOLFSSL_ASYNC_CRYPT + *r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*r == NULL) { + return MEMORY_E; + } + key->r = *r; + #endif + } + if (*s == NULL) { + #ifdef WOLFSSL_ASYNC_CRYPT + *s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*s == NULL) { + XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT); + return MEMORY_E; + } + key->s = *s; + #endif + } + + /* initialize mp_int */ + if (*r) + XMEMSET(*r, 0, sizeof(mp_int)); + if (*s) + XMEMSET(*s, 0, sizeof(mp_int)); + + return err; +} + +static INLINE void wc_ecc_free_rs(ecc_key* key, mp_int** r, mp_int** s) +{ + if (*r) { + mp_clear(*r); + + #ifdef WOLFSSL_ASYNC_CRYPT + XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT); + key->r = NULL; + #endif + *r = NULL; + } + if (*s) { + mp_clear(*s); + + #ifdef WOLFSSL_ASYNC_CRYPT + XFREE(*s, key->heap, DYNAMIC_TYPE_BIGINT); + key->s = NULL; + #endif + *s = NULL; + } + (void)key; +} /* Setup dynamic pointers if using normal math for proper freeing */ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) @@ -2755,14 +3233,12 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) return BAD_FUNC_ARG; } - (void)devId; - #ifdef ECC_DUMP_OID wc_ecc_dump_oids(); #endif - key->dp = NULL; - key->idx = 0; + XMEMSET(key, 0, sizeof(ecc_key)); + key->state = ECC_STATE_NONE; #ifdef WOLFSSL_ATECC508A key->slot = atmel_ecc_alloc(); @@ -2770,28 +3246,21 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) return ECC_BAD_ARG_E; } #else - -#ifndef USE_FAST_MATH - key->pubkey.x->dp = NULL; - key->pubkey.y->dp = NULL; - key->pubkey.z->dp = NULL; - - key->k.dp = NULL; -#endif - #ifdef ALT_ECC_SIZE - 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]; key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; alt_fp_init(key->pubkey.x); alt_fp_init(key->pubkey.y); alt_fp_init(key->pubkey.z); -#endif - + ret = mp_init(&key->k); +#else + ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); +#endif /* ALT_ECC_SIZE */ + if (ret != MP_OKAY) { + return MEMORY_E; + } #endif /* WOLFSSL_ATECC508A */ #ifdef WOLFSSL_HEAP_TEST @@ -2800,12 +3269,12 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) key->heap = heap; #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - /* handle as async */ - ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, - devId); - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, + key->heap, devId); +#else + (void)devId; #endif return ret; @@ -2816,6 +3285,14 @@ int wc_ecc_init(ecc_key* key) return wc_ecc_init_ex(key, NULL, INVALID_DEVID); } +int wc_ecc_set_flags(ecc_key* key, word32 flags) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->flags |= flags; + return 0; +} #ifdef HAVE_ECC_SIGN @@ -2832,119 +3309,128 @@ int wc_ecc_init(ecc_key* key) int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, WC_RNG* rng, ecc_key* key) { - mp_int r; - mp_int s; - int err; + int err; + mp_int *r = NULL, *s = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + mp_int r_lcl, s_lcl; + r = &r_lcl; + s = &s_lcl; +#endif - if (in == NULL || out == NULL || outlen == NULL || - key == NULL || rng == NULL) { + if (in == NULL || out == NULL || outlen == NULL || key == NULL || + rng == NULL) { return ECC_BAD_ARG_E; } + switch(key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SIGN_DO: + key->state = ECC_STATE_SIGN_DO; + + err = wc_ecc_alloc_rs(key, &r, &s); + if (err != 0) + break; + + if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ + break; + } + + #ifdef WOLFSSL_ATECC508A + /* Check args */ + if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) { + 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 + /* Sign: Result is 32-bytes of R then 32-bytes of S */ + err = atcatls_sign(key->slot, in, out); + if (err != ATCA_SUCCESS) { + return BAD_COND_E; + } - /* is this a private key? */ - if (key->type != ECC_PRIVATEKEY) - return ECC_BAD_ARG_E; + /* Load R and S */ + err = mp_read_unsigned_bin(r, &out[0], ATECC_KEY_SIZE); + if (err != MP_OKAY) { + return err; + } + err = mp_read_unsigned_bin(s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE); + if (err != MP_OKAY) { + return err; + } - /* is the IDX valid ? */ - if (wc_ecc_is_valid_idx(key->idx) != 1) - return ECC_BAD_ARG_E; + /* Check for zeros */ + if (mp_iszero(r) || mp_iszero(s)) { + return MP_ZERO_E; + } - if ((err = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL)) != MP_OKAY) { - return err; - } + #else -#ifdef WOLFSSL_ATECC508A - /* Check args */ - if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) { - err = ECC_BAD_ARG_E; - goto exit_sign; - } + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + if (err < 0) { + break; + } - /* Sign: Result is 32-bytes of R then 32-bytes of S */ - err = atcatls_sign(key->slot, in, out); - if (err != ATCA_SUCCESS) { - err = BAD_COND_E; - goto exit_sign; - } + #endif /* WOLFSSL_ATECC508A */ + FALL_THROUGH; - /* Load R and S */ - err = mp_read_unsigned_bin(&r, &out[0], ATECC_KEY_SIZE); - if (err != MP_OKAY) { - goto exit_sign; - } - err = mp_read_unsigned_bin(&s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE); - if (err != MP_OKAY) { - goto exit_sign; - } + case ECC_STATE_SIGN_ENCODE: + key->state = ECC_STATE_SIGN_ENCODE; - /* Check for zeros */ - if (mp_iszero(&r) || mp_iszero(&s)) { - err = MP_ZERO_E; - goto exit_sign; - } + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* restore r/s */ + r = key->r; + s = key->s; -#else + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + /* only do this if not simulator, since it overwrites result */ + #ifndef WOLFSSL_ASYNC_CRYPT_TEST + wc_bigint_to_mp(&r->raw, r); + wc_bigint_to_mp(&s->raw, s); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ - err = wc_ecc_sign_hash_ex(in, inlen, rng, key, &r, &s); - if (err != MP_OKAY) { - goto exit_sign; - } + /* encoded with DSA header */ + err = StoreECC_DSA_Sig(out, outlen, r, s); - err = StoreECC_DSA_Sig(out, outlen, &r, &s); + /* always free r/s */ + mp_clear(r); + mp_clear(s); + break; -#endif /* WOLFSSL_ATECC508A */ + default: + err = BAD_STATE_E; + } -exit_sign: + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; + } -#ifndef USE_FAST_MATH - mp_clear(&r); - mp_clear(&s); -#endif + /* cleanup */ + wc_ecc_free_rs(key, &r, &s); + key->state = ECC_STATE_NONE; return err; } #endif /* !NO_ASN */ #ifndef WOLFSSL_ATECC508A - /** Sign a message digest in The message digest to sign inlen The length of the digest - out [out] The destination for the signature - outlen [in/out] The max size and resulting size of the signature key A private ECC key r [out] The destination for r component of the signature - s [out] The destination for s component of the signature + s [out] The destination for s component of the signature return MP_OKAY if successful */ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, ecc_key* key, mp_int *r, mp_int *s) { - mp_int e; - mp_int p; - int err; + int err; + mp_int e; + DECLARE_CURVE_SPECS(1) if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) return ECC_BAD_ARG_E; @@ -2959,20 +3445,40 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return ECC_BAD_ARG_E; } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_SIGN; + testDev->eccSign.in = in; + testDev->eccSign.inSz = inlen; + testDev->eccSign.rng = rng; + testDev->eccSign.key = key; + testDev->eccSign.r = r; + testDev->eccSign.s = s; + return WC_PENDING_E; + } + } +#endif + /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ - if ((err = mp_init_multi(&p, &e, NULL, NULL, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init(&e)) != MP_OKAY) { return err; } - err = mp_read_radix(&p, key->dp->order, 16); + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + + /* load digest into e */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - word32 orderBits = mp_count_bits(&p); + word32 orderBits = mp_count_bits(curve->order); /* truncate down to byte size, may be all that's needed */ - if ( (WOLFSSL_BIT_SIZE * inlen) > orderBits) - inlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE; + if ((WOLFSSL_BIT_SIZE * inlen) > orderBits) + inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; err = mp_read_unsigned_bin(&e, (byte*)in, inlen); /* may still need bit truncation too */ @@ -2984,7 +3490,48 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err == MP_OKAY) { int loop_check = 0; ecc_key pubkey; - if (wc_ecc_init(&pubkey) == MP_OKAY) { + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + mp_int k; + + err = mp_init(&k); + /* make sure r and s are allocated */ + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, key->dp->size); + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->s->raw, key->dp->size); + /* load e and k */ + if (err == MP_OKAY) + err = wc_mp_to_bigint(&e, &e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->k, &key->k.raw); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, &k, curve->order); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&k, &k.raw); + if (err == MP_OKAY) + err = IntelQaEcdsaSign(&key->asyncDev, &e.raw, &key->k.raw, + &k.raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, + &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, + &curve->Gy->raw); + + mp_clear(&e); + mp_clear(&k); + wc_ecc_curve_free(curve); + + return err; + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* don't use async for key, since we don't support async return here */ + if (wc_ecc_init_ex(&pubkey, key->heap, INVALID_DEVID) == MP_OKAY) { for (;;) { if (++loop_check > 64) { err = RNG_FAILURE_E; @@ -2995,31 +3542,36 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err != MP_OKAY) break; /* find r = x1 mod n */ - err = mp_mod(pubkey.pubkey.x, &p, r); + err = mp_mod(pubkey.pubkey.x, curve->order, r); if (err != MP_OKAY) break; if (mp_iszero(r) == MP_YES) { + #ifndef ALT_ECC_SIZE mp_clear(pubkey.pubkey.x); mp_clear(pubkey.pubkey.y); mp_clear(pubkey.pubkey.z); - mp_clear(&pubkey.k); + #endif + mp_forcezero(&pubkey.k); } else { /* find s = (e + xr)/k */ - err = mp_invmod(&pubkey.k, &p, &pubkey.k); + err = mp_invmod(&pubkey.k, curve->order, &pubkey.k); if (err != MP_OKAY) break; - err = mp_mulmod(&key->k, r, &p, s); /* s = xr */ + /* s = xr */ + err = mp_mulmod(&key->k, r, curve->order, s); if (err != MP_OKAY) break; - err = mp_add(&e, s, s); /* s = e + xr */ + /* s = e + xr */ + err = mp_add(&e, s, s); if (err != MP_OKAY) break; - err = mp_mod(s, &p, s); /* s = e + xr */ + /* s = e + xr */ + err = mp_mod(s, curve->order, s); if (err != MP_OKAY) break; - err = mp_mulmod(s, &pubkey.k, &p, s); /* s = (e + xr)/k */ - if (err != MP_OKAY) break; + /* s = (e + xr)/k */ + err = mp_mulmod(s, &pubkey.k, curve->order, s); if (mp_iszero(s) == MP_NO) break; @@ -3029,14 +3581,12 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } } -#ifndef USE_FAST_MATH - mp_clear(&p); mp_clear(&e); -#endif + wc_ecc_curve_free(curve); return err; } -#endif /* !WOLFSSL_ATECC508A */ +#endif /* WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_SIGN */ /** @@ -3045,14 +3595,13 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, */ void wc_ecc_free(ecc_key* key) { - if (key == NULL) { - return; - } - -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - wolfAsync_DevCtxFree(&key->asyncDev); + if (key == NULL) { + return; } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC); + wc_ecc_free_rs(key, &key->r, &key->s); #endif #ifdef WOLFSSL_ATECC508A @@ -3060,15 +3609,14 @@ void wc_ecc_free(ecc_key* key) key->slot = -1; #else - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - mp_forcezero(&key->k); -#endif /* !WOLFSSL_ATECC508A */ -} + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + mp_forcezero(&key->k); +#endif /* WOLFSSL_ATECC508A */ +} -#ifndef WOLFSSL_ATECC508A #ifdef ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @@ -3178,10 +3726,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z); - #ifndef USE_FAST_MATH /* done with mu */ mp_clear(&mu); - #endif } } @@ -3295,7 +3841,6 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, } #endif /* ECC_SHAMIR */ -#endif /* !WOLFSSL_ATECC508A */ #ifdef HAVE_ECC_VERIFY @@ -3316,157 +3861,176 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, siglen The length of the signature (octets) hash The hash (message digest) that was signed hashlen The length of the hash (octets) - stat Result of signature, 1==valid, 0==invalid + res Result of signature, 1==valid, 0==invalid key The corresponding public ECC key return MP_OKAY if successful (even if the signature is not valid) */ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) + word32 hashlen, int* res, ecc_key* key) { - mp_int r; - mp_int s; - int err; -#ifdef WOLFSSL_ATECC508A - byte sigRS[ATECC_KEY_SIZE*2]; + int err; + mp_int *r = NULL, *s = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + mp_int r_lcl, s_lcl; + r = &r_lcl; + s = &s_lcl; #endif - if (sig == NULL || hash == NULL || stat == NULL || key == NULL) { + if (sig == NULL || hash == NULL || res == NULL || key == NULL) { return ECC_BAD_ARG_E; } - /* default to invalid signature */ - *stat = 0; + switch(key->state) { + case ECC_STATE_NONE: + case ECC_STATE_VERIFY_DECODE: + key->state = ECC_STATE_VERIFY_DECODE; -#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 + /* default to invalid signature */ + *res = 0; - /* 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 - * gets cleaned up at the end. */ - XMEMSET(&r, 0, sizeof(r)); - XMEMSET(&s, 0, sizeof(s)); + /* 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 + * gets cleaned up at the end. */ + err = wc_ecc_alloc_rs(key, &r, &s); + if (err != 0) + break; - err = DecodeECC_DSA_Sig(sig, siglen, &r, &s); - if (err != 0) { - goto exit_verify; - } + /* decode DSA header */ + err = DecodeECC_DSA_Sig(sig, siglen, r, s); + if (err < 0) { + break; + } + FALL_THROUGH; -#ifdef WOLFSSL_ATECC508A - /* Extract R and S */ - err = mp_to_unsigned_bin(&r, &sigRS[0]); - if (err != MP_OKAY) { - goto exit_verify; - } - err = mp_to_unsigned_bin(&s, &sigRS[ATECC_KEY_SIZE]); - if (err != MP_OKAY) { - goto exit_verify; - } + case ECC_STATE_VERIFY_DO: + key->state = ECC_STATE_VERIFY_DO; - err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)stat); - if (err != ATCA_SUCCESS) { - err = BAD_COND_E; - } + err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); + if (err < 0) { + break; + } + FALL_THROUGH; -#else + case ECC_STATE_VERIFY_RES: + key->state = ECC_STATE_VERIFY_RES; + err = 0; - err = wc_ecc_verify_hash_ex(&r, &s, hash, hashlen, stat, key); + #ifdef WOLFSSL_ASYNC_CRYPT + /* restore r/s */ + r = key->r; + s = key->s; + #endif -#endif /* WOLFSSL_ATECC508A */ + /* done with R/S */ + mp_clear(r); + mp_clear(s); + break; -exit_verify: + default: + err = BAD_STATE_E; + } -#ifndef USE_FAST_MATH - mp_clear(&r); - mp_clear(&s); -#endif + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; + } + + /* cleanup */ + wc_ecc_free_rs(key, &r, &s); + key->state = ECC_STATE_NONE; return err; } #endif /* !NO_ASN */ -#ifndef WOLFSSL_ATECC508A - /** Verify an ECC signature r The signature R component to verify s The signature S component to verify hash The hash (message digest) that was signed hashlen The length of the hash (octets) - stat Result of signature, 1==valid, 0==invalid + res Result of signature, 1==valid, 0==invalid key The corresponding public ECC key return MP_OKAY if successful (even if the signature is not valid) */ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) + word32 hashlen, int* res, ecc_key* key) { + int err; +#ifndef WOLFSSL_ATECC508A + int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; mp_int v; mp_int w; mp_int u1; mp_int u2; mp_int e; - mp_int order; - mp_int modulus; - mp_int a; - int err; + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) +#else + byte sigRS[ATECC_KEY_SIZE*2]; +#endif - if (r == NULL || s == NULL || hash == NULL || stat == NULL || key == NULL) + if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) return ECC_BAD_ARG_E; /* default to invalid signature */ - *stat = 0; + *res = 0; /* is the IDX valid ? */ if (wc_ecc_is_valid_idx(key->idx) != 1) { return ECC_BAD_ARG_E; } - /* allocate ints */ - if ((err = mp_init_multi(&v, &w, &u1, &u2, &order, &e)) != MP_OKAY) { - return MEMORY_E; - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_VERIFY; + testDev->eccVerify.r = r; + testDev->eccVerify.s = s; + testDev->eccVerify.hash = hash; + testDev->eccVerify.hashlen = hashlen; + testDev->eccVerify.stat = res; + testDev->eccVerify.key = key; + return WC_PENDING_E; + } + } +#endif - if ((err = mp_init_multi(&modulus, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { - err = MEMORY_E; goto done; +#ifdef WOLFSSL_ATECC508A + /* Extract R and S */ + err = mp_to_unsigned_bin(r, &sigRS[0]); + if (err != MP_OKAY) { + return err; + } + err = mp_to_unsigned_bin(s, &sigRS[ATECC_KEY_SIZE]); + if (err != MP_OKAY) { + return err; + } + + err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)res); + if (err != ATCA_SUCCESS) { + return BAD_COND_E; } - /* allocate points */ - mG = wc_ecc_new_point_h(key->heap); - mQ = wc_ecc_new_point_h(key->heap); - if (mQ == NULL || mG == NULL) - err = MEMORY_E; +#else + + err = mp_init(&e); + if (err != MP_OKAY) + return MEMORY_E; /* read in the specs for this curve */ - if (err == MP_OKAY) - err = mp_read_radix(&order, key->dp->order, 16); - if (err == MP_OKAY) - err = mp_read_radix(&modulus, key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); /* check for zero */ if (err == MP_OKAY) { if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || - mp_cmp(r, &order) != MP_LT || mp_cmp(s, &order) != MP_LT) { + mp_cmp(r, curve->order) != MP_LT || + mp_cmp(s, curve->order) != MP_LT) { err = MP_ZERO_E; } } @@ -3474,11 +4038,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* read hash */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - unsigned int orderBits = mp_count_bits(&order); + unsigned int orderBits = mp_count_bits(curve->order); /* truncate down to byte size, may be all that's needed */ if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) - hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE; + hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; err = mp_read_unsigned_bin(&e, hash, hashlen); /* may still need bit truncation too */ @@ -3486,26 +4050,67 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); } + /* check for async hardware acceleration */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + err = wc_mp_to_bigint(&e, &e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw); + if (err == MP_OKAY) + err = IntelQaEcdsaVerify(&key->asyncDev, &e.raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw, + &curve->Bf->raw, &curve->prime->raw, &curve->order->raw, + &curve->Gx->raw, &curve->Gy->raw, res); + + mp_clear(&e); + + wc_ecc_curve_free(curve); + + return err; + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* allocate ints */ + if (err == MP_OKAY) { + if ((err = mp_init_multi(&v, &w, &u1, &u2, NULL, NULL)) != MP_OKAY) { + err = MEMORY_E; + } + did_init = 1; + } + + /* allocate points */ + if (err == MP_OKAY) { + mG = wc_ecc_new_point_h(key->heap); + mQ = wc_ecc_new_point_h(key->heap); + if (mQ == NULL || mG == NULL) + err = MEMORY_E; + } + /* w = s^-1 mod n */ if (err == MP_OKAY) - err = mp_invmod(s, &order, &w); + err = mp_invmod(s, curve->order, &w); /* u1 = ew */ if (err == MP_OKAY) - err = mp_mulmod(&e, &w, &order, &u1); + err = mp_mulmod(&e, &w, curve->order, &u1); /* u2 = rw */ if (err == MP_OKAY) - err = mp_mulmod(r, &w, &order, &u2); + err = mp_mulmod(r, &w, curve->order, &u2); /* find mG and mQ */ if (err == MP_OKAY) - err = mp_read_radix(mG->x, key->dp->Gx, 16); - + err = mp_copy(curve->Gx, mG->x); if (err == MP_OKAY) - err = mp_read_radix(mG->y, key->dp->Gy, 16); + err = mp_copy(curve->Gy, mG->y); if (err == MP_OKAY) - mp_set(mG->z, 1); + err = mp_set(mG->z, 1); if (err == MP_OKAY) err = mp_copy(key->pubkey.x, mQ->x); @@ -3517,11 +4122,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #ifdef FREESCALE_LTC_ECC /* use PKHA to compute u1*mG + u2*mQ */ if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u1, mG, mG, &a, &modulus, 0, NULL); + err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u2, mQ, mQ, &a, &modulus, 0, NULL); + err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_point_add(mG, mQ, mG, &modulus); + err = wc_ecc_point_add(mG, mQ, mG, curve->prime); #else /* FREESCALE_LTC_ECC */ #ifndef ECC_SHAMIR { @@ -3529,57 +4134,58 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* compute u1*mG + u2*mQ = mG */ if (err == MP_OKAY) - err = wc_ecc_mulmod(&u1, mG, mG, &a, &modulus, 0); + err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_mulmod(&u2, mQ, mQ, &a, &modulus, 0); + err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); /* find the montgomery mp */ if (err == MP_OKAY) - err = mp_montgomery_setup(&modulus, &mp); + err = mp_montgomery_setup(curve->prime, &mp); /* add them */ if (err == MP_OKAY) - err = ecc_projective_add_point(mQ, mG, mG, &a, &modulus, mp); + err = ecc_projective_add_point(mQ, mG, mG, curve->Af, + curve->prime, mp); /* reduce */ if (err == MP_OKAY) - err = ecc_map(mG, &modulus, mp); + err = ecc_map(mG, curve->prime, mp); } #else /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ if (err == MP_OKAY) - err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &a, &modulus, key->heap); + err = ecc_mul2add(mG, &u1, mQ, &u2, mG, curve->Af, curve->prime, + key->heap); #endif /* ECC_SHAMIR */ #endif /* FREESCALE_LTC_ECC */ /* v = X_x1 mod n */ if (err == MP_OKAY) - err = mp_mod(mG->x, &order, &v); + err = mp_mod(mG->x, curve->order, &v); /* does v == r */ if (err == MP_OKAY) { if (mp_cmp(&v, r) == MP_EQ) - *stat = 1; + *res = 1; } -done: /* cleanup */ wc_ecc_del_point_h(mG, key->heap); wc_ecc_del_point_h(mQ, key->heap); -#ifndef USE_FAST_MATH - mp_clear(&v); - mp_clear(&w); - mp_clear(&u1); - mp_clear(&u2); - mp_clear(&order); mp_clear(&e); - mp_clear(&modulus); - mp_clear(&a); -#endif + if (did_init) { + mp_clear(&v); + mp_clear(&w); + mp_clear(&u1); + mp_clear(&u2); + } + + wc_ecc_curve_free(curve); + +#endif /* WOLFSSL_ATECC508A */ return err; } -#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_KEY_IMPORT @@ -3633,62 +4239,58 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ - mp_int t1, t2, prime, a, b; int did_init = 0; + mp_int t1, t2; + DECLARE_CURVE_SPECS(3) - if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; else did_init = 1; - /* read in the specs for this curve */ - if (err == MP_OKAY) - err = mp_read_radix(&prime, ecc_sets[curve_idx].prime, 16); + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&a, ecc_sets[curve_idx].Af, 16); - if (err == MP_OKAY) - err = mp_read_radix(&b, ecc_sets[curve_idx].Bf, 16); + err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(point->x, &t1); if (err == MP_OKAY) - err = mp_mulmod(&t1, point->x, &prime, &t1); + err = mp_mulmod(&t1, point->x, curve->prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) - err = mp_mulmod(&a, point->x, &prime, &t2); + err = mp_mulmod(curve->Af, point->x, curve->prime, &t2); if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); /* compute x^3 + a*x + b */ if (err == MP_OKAY) - err = mp_add(&t1, &b, &t1); + err = mp_add(&t1, curve->Bf, &t1); /* compute sqrt(x^3 + a*x + b) */ if (err == MP_OKAY) - err = mp_sqrtmod_prime(&t1, &prime, &t2); + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); /* adjust y */ if (err == MP_OKAY) { if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) || (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) { - err = mp_mod(&t2, &prime, point->y); + err = mp_mod(&t2, curve->prime, point->y); } else { - err = mp_submod(&prime, &t2, &prime, point->y); + err = mp_submod(curve->prime, &t2, curve->prime, point->y); } } if (did_init) { - #ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&b); - mp_clear(&prime); mp_clear(&t2); mp_clear(&t1); - #endif } + + wc_ecc_curve_free(curve); } #endif @@ -3696,7 +4298,7 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, err = mp_read_unsigned_bin(point->y, (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1); if (err == MP_OKAY) - mp_set(point->z, 1); + err = mp_set(point->z, 1); if (err != MP_OKAY) { mp_clear(point->x); @@ -3790,15 +4392,16 @@ int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, /* export public ECC key in ANSI X9.63 format */ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) { - word32 numlen; int ret = MP_OKAY; + word32 numlen; #ifndef WOLFSSL_ATECC508A #ifdef WOLFSSL_SMALL_STACK byte* buf; #else byte buf[ECC_BUFSIZE]; #endif -#endif + word32 pubxlen, pubylen; +#endif /* WOLFSSL_ATECC508A */ /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { @@ -3815,6 +4418,7 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) } numlen = key->dp->size; + /* verify room in out buffer */ if (*outLen < (1 + 2*numlen)) { *outLen = 1 + 2*numlen; return BUFFER_E; @@ -3826,6 +4430,14 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) #else + /* verify public key length is less than key size */ + pubxlen = mp_unsigned_bin_size(key->pubkey.x); + pubylen = mp_unsigned_bin_size(key->pubkey.y); + if ((pubxlen > numlen) || (pubylen > numlen)) { + WOLFSSL_MSG("Public key x/y invalid!"); + return BUFFER_E; + } + /* store byte 0x04 */ out[0] = 0x04; @@ -3835,23 +4447,21 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) return MEMORY_E; #endif - /* pad and store x */ - XMEMSET(buf, 0, ECC_BUFSIZE); - ret = mp_to_unsigned_bin(key->pubkey.x, - buf + (numlen - mp_unsigned_bin_size(key->pubkey.x))); - if (ret != MP_OKAY) - goto done; - XMEMCPY(out+1, buf, numlen); + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - pubxlen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); - /* pad and store y */ - XMEMSET(buf, 0, ECC_BUFSIZE); - ret = mp_to_unsigned_bin(key->pubkey.y, - buf + (numlen - mp_unsigned_bin_size(key->pubkey.y))); - if (ret != MP_OKAY) - goto done; - XMEMCPY(out+1+numlen, buf, numlen); + /* pad and store y */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - pubylen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1+numlen, buf, numlen); - *outLen = 1 + 2*numlen; + *outLen = 1 + 2*numlen; done: #ifdef WOLFSSL_SMALL_STACK @@ -3873,9 +4483,9 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, #ifdef HAVE_COMP_KEY else return wc_ecc_export_x963_compressed(key, out, outLen); -#endif - +#else return NOT_COMPILED_IN; +#endif } #endif /* HAVE_ECC_KEY_EXPORT */ @@ -3883,20 +4493,15 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, #ifndef WOLFSSL_ATECC508A /* is ecc point on curve described by dp ? */ -static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) +int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) { - mp_int a, b, t1, t2; int err; + mp_int t1, t2; - if ((err = mp_init_multi(&a, &b, &t1, &t2, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { return err; } - /* read in the specs for this curve */ - err = mp_read_radix(&a, dp->Af, 16); - if (err == MP_OKAY) - err = mp_read_radix(&b, dp->Bf, 16); - /* compute y^2 */ if (err == MP_OKAY) err = mp_sqr(ecp->y, &t1); @@ -3917,8 +4522,9 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) #ifdef WOLFSSL_CUSTOM_CURVES if (err == MP_OKAY) { /* Use a and prime to determine if a == 3 */ - mp_set(&t2, 0); - err = mp_submod(prime, &a, prime, &t2); + err = mp_set(&t2, 0); + if (err == MP_OKAY) + err = mp_submod(prime, a, prime, &t2); } if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) { /* compute y^2 - x^3 + a*x */ @@ -3954,19 +4560,15 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) /* compare to b */ if (err == MP_OKAY) { - if (mp_cmp(&t1, &b) != MP_EQ) { + if (mp_cmp(&t1, b) != MP_EQ) { err = MP_VAL; } else { err = MP_OKAY; } } -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&b); mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -3975,9 +4577,10 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) /* validate privkey * generator == pubkey, 0 on success */ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { - int err = MP_OKAY; + int err = MP_OKAY; ecc_point* base = NULL; ecc_point* res = NULL; + DECLARE_CURVE_SPECS(2) if (key == NULL) return BAD_FUNC_ARG; @@ -3986,12 +4589,17 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) if (base == NULL) return MEMORY_E; + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); + /* set up base generator */ - err = mp_read_radix(base->x, key->dp->Gx, 16); if (err == MP_OKAY) - err = mp_read_radix(base->y, key->dp->Gy, 16); + err = mp_copy(curve->Gx, base->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, base->y); if (err == MP_OKAY) - mp_set(base->z, 1); + err = mp_set(base->z, 1); if (err == MP_OKAY) { res = wc_ecc_new_point_h(key->heap); @@ -4011,23 +4619,22 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) } } + wc_ecc_curve_free(curve); wc_ecc_del_point_h(res, key->heap); wc_ecc_del_point_h(base, key->heap); return err; } - #ifdef WOLFSSL_VALIDATE_ECC_IMPORT /* check privkey generator helper, creates prime needed */ static int ecc_check_privkey_gen_helper(ecc_key* key) { - int err = MP_OKAY; + int err; #ifndef WOLFSSL_ATECC508A - mp_int prime; - mp_int a; -#endif /* !WOLFSSL_ATECC508A */ + DECLARE_CURVE_SPECS(2) +#endif if (key == NULL) return BAD_FUNC_ARG; @@ -4038,22 +4645,15 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) #else - err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; - - err = mp_read_radix(&prime, key->dp->prime, 16); + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); - if (err == MP_OKAY) - err = ecc_check_privkey_gen(key, &a, &prime); + wc_ecc_curve_free(curve); -#ifndef USE_FAST_MATH - mp_clear(&prime); - mp_clear(&a); -#endif #endif /* WOLFSSL_ATECC508A */ return err; @@ -4076,8 +4676,7 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, if (inf == NULL) err = MEMORY_E; else { - err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, a, prime, 1, - key->heap); + err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, a, prime, 1, key->heap); if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf)) err = ECC_INF_E; } @@ -4093,12 +4692,18 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, /* perform sanity checks on ecc key validity, 0 on success */ int wc_ecc_check_key(ecc_key* key) { - int err = MP_OKAY; + int err; #ifndef WOLFSSL_ATECC508A - mp_int prime; /* used by multiple calls so let's cache */ - mp_int a; - mp_int order; /* other callers have, so let's gen here */ -#endif /* !WOLFSSL_ATECC508A */ + mp_int* b; +#ifdef USE_ECC_B_PARAM + DECLARE_CURVE_SPECS(4) +#else + mp_int b_lcl; + DECLARE_CURVE_SPECS(3) + b = &b_lcl; + XMEMSET(b, 0, sizeof(mp_int)); +#endif +#endif /* WOLFSSL_ATECC508A */ if (key == NULL) return BAD_FUNC_ARG; @@ -4113,35 +4718,50 @@ int wc_ecc_check_key(ecc_key* key) if (wc_ecc_point_is_at_infinity(&key->pubkey)) return ECC_INF_E; - err = mp_init_multi(&prime, &a, &order, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | + ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER +#ifdef USE_ECC_B_PARAM + | ECC_CURVE_FIELD_BF +#endif + )); - /* read in the specs for this curve */ - if (err == MP_OKAY) - err = mp_read_radix(&prime, key->dp->prime, 16); +#ifndef USE_ECC_B_PARAM + /* load curve b parameter */ if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = mp_init(b); if (err == MP_OKAY) - err = mp_read_radix(&order, key->dp->order, 16); + err = mp_read_radix(b, key->dp->Bf, 16); +#else + b = curve->Bf; +#endif + + /* Qx must be in the range [0, p-1] */ + if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + + /* Qy must be in the range [0, p-1] */ + if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; /* make sure point is actually on curve */ if (err == MP_OKAY) - err = ecc_is_point(key->dp, &key->pubkey, &prime); + err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime); /* pubkey * order must be at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &a, &prime, &order); + err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order); /* private * base generator must equal pubkey */ if (err == MP_OKAY && key->type == ECC_PRIVATEKEY) - err = ecc_check_privkey_gen(key, &a, &prime); + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); -#ifndef USE_FAST_MATH - mp_clear(&order); - mp_clear(&a); - mp_clear(&prime); + wc_ecc_curve_free(curve); + +#ifndef USE_ECC_B_PARAM + mp_clear(b); #endif + #endif /* WOLFSSL_ATECC508A */ return err; @@ -4156,6 +4776,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #ifndef WOLFSSL_ATECC508A int compressed = 0; #endif /* !WOLFSSL_ATECC508A */ + void* heap; if (in == NULL || key == NULL) return BAD_FUNC_ARG; @@ -4165,6 +4786,10 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, return ECC_BAD_ARG_E; } + heap = key->heap; /* save heap */ + XMEMSET(key, 0, sizeof(ecc_key)); + key->heap = heap; /* restore heap */ + #ifdef WOLFSSL_ATECC508A /* TODO: Implement equiv call to ATECC508A */ err = BAD_COND_E; @@ -4181,8 +4806,8 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, alt_fp_init(key->pubkey.z); err = mp_init(&key->k); #else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); + err = mp_init_multi(&key->k, + key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL); #endif if (err != MP_OKAY) return MEMORY_E; @@ -4202,9 +4827,11 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, if (err == MP_OKAY) { int keysize; + #ifdef HAVE_COMP_KEY /* adjust inLen if compressed */ if (compressed) inLen = (inLen-1)*2 + 1; /* used uncompressed len */ + #endif /* determine key size */ keysize = ((inLen-1)>>1); @@ -4218,63 +4845,61 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ - mp_int t1, t2, prime, a, b; + mp_int t1, t2; int did_init = 0; - if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) + DECLARE_CURVE_SPECS(3) + + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; else did_init = 1; - /* read in the specs for this curve */ - if (err == MP_OKAY) - err = mp_read_radix(&prime, key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&b, key->dp->Bf, 16); + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(key->pubkey.x, &t1); if (err == MP_OKAY) - err = mp_mulmod(&t1, key->pubkey.x, &prime, &t1); + err = mp_mulmod(&t1, key->pubkey.x, curve->prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) - err = mp_mulmod(&a, key->pubkey.x, &prime, &t2); + err = mp_mulmod(curve->Af, key->pubkey.x, curve->prime, &t2); if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); /* compute x^3 + a*x + b */ if (err == MP_OKAY) - err = mp_add(&t1, &b, &t1); + err = mp_add(&t1, curve->Bf, &t1); /* compute sqrt(x^3 + a*x + b) */ if (err == MP_OKAY) - err = mp_sqrtmod_prime(&t1, &prime, &t2); + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); /* adjust y */ if (err == MP_OKAY) { if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) || (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) { - err = mp_mod(&t2, &prime, &t2); + err = mp_mod(&t2, curve->prime, &t2); } else { - err = mp_submod(&prime, &t2, &prime, &t2); + err = mp_submod(curve->prime, &t2, curve->prime, &t2); } - mp_copy(&t2, key->pubkey.y); + if (err == MP_OKAY) + err = mp_copy(&t2, key->pubkey.y); } if (did_init) { - #ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&b); - mp_clear(&prime); mp_clear(&t2); mp_clear(&t1); - #endif } + + wc_ecc_curve_free(curve); } #endif /* HAVE_COMP_KEY */ @@ -4282,7 +4907,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1); if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); + err = mp_set(key->pubkey.z, 1); #ifdef WOLFSSL_VALIDATE_ECC_IMPORT if (err == MP_OKAY) @@ -4339,13 +4964,131 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) mp_unsigned_bin_size(&key->k))); #endif /* WOLFSSL_ATECC508A */ } + + +/* export ecc key to component form, d is optional if only exporting public + * return MP_OKAY on success */ +static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen) +{ + int err; + byte exportPriv = 0; + word32 numLen; + + if (key == NULL || qx == NULL || qxLen == NULL || qy == NULL || + qyLen == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + numLen = key->dp->size; + + if (d != NULL) { + if (dLen == NULL || key->type != ECC_PRIVATEKEY) + return BAD_FUNC_ARG; + exportPriv = 1; + } + + /* check public buffer sizes */ + if ((*qxLen < numLen) || (*qyLen < numLen)) { + *qxLen = numLen; + *qyLen = numLen; + return BUFFER_E; + } + + *qxLen = numLen; + *qyLen = numLen; + + XMEMSET(qx, 0, *qxLen); + XMEMSET(qy, 0, *qyLen); + + /* private d component */ + if (exportPriv == 1) { + + /* check private buffer size */ + if (*dLen < numLen) { + *dLen = numLen; + return BUFFER_E; + } + + *dLen = numLen; + XMEMSET(d, 0, *dLen); + + /* private key, d */ + err = mp_to_unsigned_bin(&key->k, d + + (numLen - mp_unsigned_bin_size(&key->k))); + if (err != MP_OKAY) + return err; + } + + /* public x component */ + err = mp_to_unsigned_bin(key->pubkey.x, qx + + (numLen - mp_unsigned_bin_size(key->pubkey.x))); + if (err != MP_OKAY) + return err; + + /* public y component */ + err = mp_to_unsigned_bin(key->pubkey.y, qy + + (numLen - mp_unsigned_bin_size(key->pubkey.y))); + if (err != MP_OKAY) + return err; + + return 0; +} + + +/* export public key to raw elements including public (Qx,Qy) + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen) +{ + return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, NULL, NULL); +} + + +/* export ecc key to raw elements including public (Qx,Qy) and private (d) + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen) +{ + /* sanitize d and dLen, other args are checked later */ + if (d == NULL || dLen == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, d, dLen); +} + #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_IMPORT -int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, const byte* pub, - word32 pubSz, ecc_key* key, int curve_id) +/* import private key, public part optional if (pub) passed as NULL */ +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, + int curve_id) { - int ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + int ret; + + /* public optional, NULL if only importing private */ + if (pub != NULL) { + + ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + + } else { + + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; + + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; + key->idx = 0; + key->dp = NULL; + + /* set key size */ + ret = wc_ecc_set_curve(key, privSz, curve_id); + } + if (ret != 0) return ret; @@ -4413,10 +5156,62 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) err = MP_ZERO_E; } -#ifndef USE_FAST_MATH mp_clear(&rtmp); mp_clear(&stmp); -#endif + + return err; +} + + +/** + Convert ECC signature to R,S + sig DER-encoded ECDSA signature + sigLen length of signature in octets + r R component of signature + rLen [in/out] output "r" buffer size, output "r" size + s S component of signature + sLen [in/out] output "s" buffer size, output "s" size + return MP_OKAY on success, negative on error +*/ +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen) +{ + int err; + word32 x = 0; + mp_int rtmp; + mp_int stmp; + + if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL) + return ECC_BAD_ARG_E; + + err = DecodeECC_DSA_Sig(sig, sigLen, &rtmp, &stmp); + + /* extract r */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(&rtmp); + if (*rLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *rLen = x; + err = mp_to_unsigned_bin(&rtmp, r); + } + } + + /* extract s */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(&stmp); + if (*sLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *sLen = x; + err = mp_to_unsigned_bin(&stmp, s); + } + } + + mp_clear(&rtmp); + mp_clear(&stmp); return err; } @@ -4427,11 +5222,17 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id) { int err = MP_OKAY; + void* heap; - if (key == NULL || qx == NULL || qy == NULL || d == NULL) { + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL) { return BAD_FUNC_ARG; } + heap = key->heap; /* save heap */ + XMEMSET(key, 0, sizeof(ecc_key)); + key->heap = heap; /* restore heap */ + /* set curve type and index */ err = wc_ecc_set_curve(key, 0, curve_id); if (err != 0) { @@ -4454,8 +5255,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, alt_fp_init(key->pubkey.z); err = mp_init(&key->k); #else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); + err = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); #endif if (err != MP_OKAY) return MEMORY_E; @@ -4469,12 +5270,16 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, err = mp_read_radix(key->pubkey.y, qy, 16); if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); + err = mp_set(key->pubkey.z, 1); /* import private key */ if (err == MP_OKAY) { - key->type = ECC_PRIVATEKEY; - err = mp_read_radix(&key->k, d, 16); + if (d != NULL) { + key->type = ECC_PRIVATEKEY; + err = mp_read_radix(&key->k, d, 16); + } else { + key->type = ECC_PUBLICKEY; + } } #ifdef WOLFSSL_VALIDATE_ECC_IMPORT @@ -4498,7 +5303,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, key The destination ecc_key structure qx x component of the public key, as ASCII hex string qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only dp Custom ecc_set_type return MP_OKAY on success */ @@ -4514,7 +5320,8 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, key The destination ecc_key structure qx x component of the public key, as ASCII hex string qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only curveName ECC curve name, from ecc_sets[] return MP_OKAY on success */ @@ -4523,8 +5330,8 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, { int err, x; - if (key == NULL || qx == NULL || qy == NULL || d == NULL || - curveName == NULL) { + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) { return BAD_FUNC_ARG; } @@ -5239,7 +6046,8 @@ static int add_entry(int idx, ecc_point *g) static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, mp_int* mu) { - unsigned x, y, err, bitlen, lut_gap; + int err; + unsigned x, y, bitlen, lut_gap; mp_int tmp; if (mp_init(&tmp) != MP_OKAY) @@ -5304,8 +6112,6 @@ static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, if (err != MP_OKAY) break; for (y = 0; y < (1UL<z); } -#ifndef USE_FAST_MATH mp_clear(&tmp); -#endif if (err == MP_OKAY) return MP_OKAY; @@ -5385,8 +6189,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, #else unsigned char kb[KB_SIZE]; #endif - int x; - unsigned y, z = 0, err, bitlen, bitpos, lut_gap, first; + int x, err; + unsigned y, z = 0, bitlen, bitpos, lut_gap, first; mp_int tk, order; if (mp_init_multi(&tk, &order, NULL, NULL, NULL, NULL) != MP_OKAY) @@ -5413,10 +6217,14 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, goto done; } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } /* get bitlen and round up to next multiple of FP_LUT */ @@ -5506,10 +6314,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&order); mp_clear(&tk); -#endif #ifdef WOLFSSL_SMALL_STACK XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -5534,8 +6340,8 @@ static int accel_fp_mul2add(int idx1, int idx2, #else unsigned char kb[2][KB_SIZE]; #endif - int x; - unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; + int x, err; + unsigned y, z, bitlen, bitpos, lut_gap, first, zA, zB; mp_int tka, tkb, order; if (mp_init_multi(&tka, &tkb, &order, NULL, NULL, NULL) != MP_OKAY) @@ -5562,10 +6368,14 @@ static int accel_fp_mul2add(int idx1, int idx2, goto done; } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } /* if it's smaller than modulus we fine */ @@ -5589,10 +6399,14 @@ static int accel_fp_mul2add(int idx1, int idx2, goto done; } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } /* get bitlen and round up to next multiple of FP_LUT */ @@ -5722,15 +6536,17 @@ static int accel_fp_mul2add(int idx1, int idx2, done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&tkb); mp_clear(&tka); mp_clear(&order); -#endif +#ifdef WOLFSSL_SMALL_STACK if (kb[0]) +#endif ForceZero(kb[0], KB_SIZE); +#ifdef WOLFSSL_SMALL_STACK if (kb[1]) +#endif ForceZero(kb[1], KB_SIZE); #ifdef WOLFSSL_SMALL_STACK @@ -5865,15 +6681,12 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, #ifndef HAVE_THREAD_LS wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ -#ifndef USE_FAST_MATH mp_clear(&mu); -#endif return err; } #endif /* ECC_SHAMIR */ -#if !defined(FREESCALE_LTC_TFM) /** ECC Fixed Point mulmod global k The multiplicand G Base point to multiply @@ -5884,22 +6697,6 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, int map) -{ - return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); -} -#endif /* !FREESCALE_LTC_TFM */ - -/** ECC Fixed Point mulmod global - k The multiplicand - G Base point to multiply - R [out] Destination of product - modulus The modulus for the curve - map [boolean] If non-zero maps the point back to affine co-ordinates, - otherwise it's left in jacobian-montgomery form - return MP_OKAY if successful -*/ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap) { @@ -5972,9 +6769,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, #ifndef HAVE_THREAD_LS wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ -#ifndef USE_FAST_MATH mp_clear(&mu); -#endif return err; } @@ -6347,8 +7142,15 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = 0; + #endif + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); if (ret == 0) { switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : @@ -6377,6 +7179,9 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) break; ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; @@ -6391,16 +7196,17 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecHMAC_SHA256: { Hmac hmac; - ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, out, msgSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); - if (ret != 0) - break; - ret = wc_HmacFinal(&hmac, out+msgSz); + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, out, msgSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, out+msgSz); + wc_HmacFree(&hmac); + } } break; @@ -6499,8 +7305,15 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = 0; + #endif + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); if (ret == 0) { switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : @@ -6522,25 +7335,28 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, switch (ctx->macAlgo) { case ecHMAC_SHA256: - { - byte verify[SHA256_DIGEST_SIZE]; - Hmac hmac; + { + byte verify[SHA256_DIGEST_SIZE]; + Hmac hmac; + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); - if (ret != 0) - break; - ret = wc_HmacFinal(&hmac, verify); - if (ret != 0) - break; - if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) - ret = -1; + if (ret == 0) + ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, verify); + if (ret == 0) { + if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) + ret = -1; + } + + wc_HmacFree(&hmac); } break; + } default: ret = BAD_FUNC_ARG; @@ -6559,6 +7375,9 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) break; ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; #endif @@ -6586,15 +7405,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #ifdef HAVE_COMP_KEY #ifndef WOLFSSL_ATECC508A -/* computes the jacobi c = (a | n) (or Legendre if n is prime) - * HAC pp. 73 Algorithm 2.149 - * HAC is wrong here, as the special case of (0 | 1) is not - * handled correctly. - */ -int mp_jacobi(mp_int* a, mp_int* n, int* c) +int do_mp_jacobi(mp_int* a, mp_int* n, int* c); + +int do_mp_jacobi(mp_int* a, mp_int* n, int* c) { - mp_int a1, p1; - int k, s, r, res; + int k, s, res; + int r = 0; /* initialize to help static analysis out */ mp_digit residue; /* if a < 0 return MP_VAL */ @@ -6627,18 +7443,9 @@ int mp_jacobi(mp_int* a, mp_int* n, int* c) /* default */ s = 0; - /* step 3. write a = a1 * 2**k */ - if ((res = mp_init_multi(&a1, &p1, NULL, NULL, NULL, NULL)) != MP_OKAY) { - return res; - } - - if ((res = mp_copy(a, &a1)) != MP_OKAY) { - goto done; - } - /* divide out larger power of two */ - k = mp_cnt_lsb(&a1); - res = mp_div_2d(&a1, k, &a1, NULL); + k = mp_cnt_lsb(a); + res = mp_div_2d(a, k, a, NULL); if (res == MP_OKAY) { /* step 4. if e is even set s=1 */ @@ -6655,33 +7462,60 @@ int mp_jacobi(mp_int* a, mp_int* n, int* c) } } - /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ - if ( ((n->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { + /* step 5. if p == 3 (mod 4) *and* a == 3 (mod 4) then s = -s */ + if ( ((n->dp[0] & 3) == 3) && ((a->dp[0] & 3) == 3)) { s = -s; } } if (res == MP_OKAY) { - /* if a1 == 1 we're done */ - if (mp_cmp_d (&a1, 1) == MP_EQ) { + /* if a == 1 we're done */ + if (mp_cmp_d(a, 1) == MP_EQ) { *c = s; } else { - /* n1 = n mod a1 */ - res = mp_mod (n, &a1, &p1); + /* n1 = n mod a */ + res = mp_mod (n, a, n); if (res == MP_OKAY) - res = mp_jacobi (&p1, &a1, &r); + res = do_mp_jacobi(n, a, &r); if (res == MP_OKAY) *c = s * r; } } + return res; +} + + +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + * HAC is wrong here, as the special case of (0 | 1) is not + * handled correctly. + */ +int mp_jacobi(mp_int* a, mp_int* n, int* c) +{ + mp_int a1, n1; + int res; + + /* step 3. write a = a1 * 2**k */ + if ((res = mp_init_multi(&a1, &n1, NULL, NULL, NULL, NULL)) != MP_OKAY) { + return res; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto done; + } + + if ((res = mp_copy(n, &n1)) != MP_OKAY) { + goto done; + } + + res = do_mp_jacobi(&a1, &n1, c); + done: /* cleanup */ -#ifndef USE_FAST_MATH - mp_clear(&p1); + mp_clear(&n1); mp_clear(&a1); -#endif return res; } @@ -6704,8 +7538,7 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) return MP_OKAY; } if (mp_cmp_d(n, 1) == MP_EQ) { - mp_set(ret, 1); - return MP_OKAY; + return mp_set(ret, 1); } /* prime must be odd */ @@ -6856,12 +7689,11 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) /* M = i */ if (res == MP_OKAY) - mp_set(&M, i); + res = mp_set(&M, i); } } } -#ifndef USE_FAST_MATH /* done */ mp_clear(&t1); mp_clear(&C); @@ -6872,7 +7704,6 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) mp_clear(&T); mp_clear(&R); mp_clear(&two); -#endif return res; } @@ -6982,16 +7813,6 @@ int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp) #ifdef HAVE_X963_KDF -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - static INLINE void IncrementX963KdfCounter(byte* inOutCtr) { int i; @@ -7104,51 +7925,4 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, } #endif /* HAVE_X963_KDF */ - -#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/ed25519.c b/wolfcrypt/src/ed25519.c index 310b6cfd61..258631b007 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -207,11 +207,11 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, siglen is the length of sig byte array msg the array of bytes containing the message msglen length of msg array - stat will be 1 on successful verify and 0 on unsuccessful - return 0 and stat of 1 on success + res will be 1 on successful verify and 0 on unsuccessful + return 0 and res of 1 on success */ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, - word32 msglen, int* stat, ed25519_key* key) + word32 msglen, int* res, ed25519_key* key) { byte rcheck[ED25519_KEY_SIZE]; byte h[SHA512_DIGEST_SIZE]; @@ -223,11 +223,11 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, Sha512 sha; /* sanity check on arguments */ - if (sig == NULL || msg == NULL || stat == NULL || key == NULL) + if (sig == NULL || msg == NULL || res == NULL || key == NULL) return BAD_FUNC_ARG; /* set verification failed by default */ - *stat = 0; + *res = 0; /* check on basics needed to verify signature */ if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) @@ -279,7 +279,7 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, return SIG_VERIFY_E; /* set the verification status */ - *stat = 1; + *res = 1; return ret; } diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 2de4e7c0ad..b5b578d5a1 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -204,7 +204,7 @@ const char* wc_GetErrorString(int error) return "ASN NTRU key decode error, invalid input"; case ASN_CRIT_EXT_E: - return "X.509 Critical extension ignored"; + return "X.509 Critical extension ignored or invalid"; case ECC_BAD_ARG_E : return "ECC input argument wrong type, invalid input"; @@ -338,6 +338,9 @@ const char* wc_GetErrorString(int error) case ECC_INF_E: return " ECC point at infinity error"; + case ECC_OUT_OF_RANGE_E: + return " ECC Qx or Qy out of range error"; + case ECC_PRIV_KEY_E: return " ECC private key is not valid error"; @@ -407,6 +410,21 @@ const char* wc_GetErrorString(int error) case BAD_KEYWRAP_IV_E: return "Decrypted AES key wrap IV does not match expected"; + case WC_CLEANUP_E: + return "wolfcrypt cleanup failed"; + + case ECC_CDH_KAT_FIPS_E: + return "wolfcrypt FIPS ECC CDH Known Answer Test Failure"; + + case DH_CHECK_PUB_E: + return "DH Check Public Key failure"; + + case BAD_PATH_ERROR: + return "Bad path for opendir error"; + + case ASYNC_OP_E: + return "Async operation error"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c new file mode 100644 index 0000000000..3dcac0c02c --- /dev/null +++ b/wolfcrypt/src/evp.c @@ -0,0 +1,539 @@ +/* evp.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 + */ + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); + +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv) +{ + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv) +{ + (void) impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv) +{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 0); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit"); + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 0); +} + +WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void) +{ + WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ctx){ + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); + wolfSSL_EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +} + +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return 0; + return ctx->flags & WOLFSSL_EVP_CIPH_MODE; +} + +WOLFSSL_API int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc){ + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return 0; +} + + +WOLFSSL_API int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv, + int enc) +{ + (void)impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc){ + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return 0; +} + +WOLFSSL_API int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) + return 0; + else{ + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } +} + +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) + return 0; + else{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } +} + + +WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex"); + return wolfSSL_EVP_DigestInit(ctx, type); +} + +#ifdef DEBUG_WOLFSSL_EVP +#define PRINT_BUF(b, sz) { int i; for(i=0; i<(sz); i++){printf("%02x(%c),", (b)[i], (b)[i]); if((i+1)%8==0)printf("\n");}} +#else +#define PRINT_BUF(b, sz) +#endif + +static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz) +{ + int fill; + + if (sz > 0) { + if ((sz+ctx->bufUsed) > ctx->block_size) { + fill = ctx->block_size - ctx->bufUsed; + } else { + fill = sz; + } + XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill); + ctx->bufUsed += fill; + return fill; + } else return 0; +} + +static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, int inl) +{ + int ret = 0; + + switch (ctx->cipherType) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + if (ctx->enc) + wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + else + wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: + if (ctx->enc) + ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); + else + ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_CBC_TYPE: + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); + break; + #if defined(WOLFSSL_DES_ECB) + case DES_ECB_TYPE: + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_ECB_TYPE: + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); + break; + #endif /* WOLFSSL_DES_ECB */ + #endif /* !NO_DES3 */ + default: + return 0; + } + + if (ret != 0) + return 0; /* failure */ + + (void)in; + (void)inl; + (void)out; + + return 1; /* success */ +} + +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int blocks; + int fill; + + if (ctx == NULL) return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate"); + *outl = 0; + if (ctx->bufUsed > 0) { /* concatinate them if there is anything */ + fill = fillBuff(ctx, in, inl); + inl -= fill; + in += fill; + } + if((ctx->enc == 0)&& (ctx->lastUsed == 1)){ + PRINT_BUF(ctx->lastBlock, ctx->block_size); + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl+= ctx->block_size; + out += ctx->block_size; + } + if ((ctx->bufUsed == ctx->block_size) || (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING)){ + /* the buff is full, flash out */ + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) + return 0; + PRINT_BUF(out, ctx->block_size); + if(ctx->enc == 0){ + ctx->lastUsed = 1; + XMEMCPY(ctx->lastBlock, out, ctx->block_size); + } else { + *outl+= ctx->block_size; + out += ctx->block_size; + } + ctx->bufUsed = 0; + } + + blocks = inl / ctx->block_size; + if (blocks > 0) { + /* process blocks */ + if (evpCipherBlock(ctx, out, in, blocks*ctx->block_size) == 0) + return 0; + PRINT_BUF(ctx->buf, ctx->block_size); + PRINT_BUF(out, ctx->block_size); + inl -= ctx->block_size * blocks; + in += ctx->block_size * blocks; + if(ctx->enc == 0){ + ctx->lastUsed = 1; + XMEMCPY(ctx->lastBlock, &out[ctx->block_size * (blocks-1)], ctx->block_size); + *outl+= ctx->block_size * (blocks-1); + } else { + *outl+= ctx->block_size * blocks; + } + } + if (inl > 0) { + /* put fraction into buff */ + fillBuff(ctx, in, inl); + /* no increase of outl */ + } + + (void)out; /* silence warning in case not read */ + + return 1; +} + +static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int i; + for (i = ctx->bufUsed; i < ctx->block_size; i++) + ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed); +} + +static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff) +{ + int i; + int n; + n = buff[ctx->block_size-1]; + + if (n > ctx->block_size) return FALSE; + for (i = 0; i < n; i++){ + if (buff[ctx->block_size-i-1] != n) + return FALSE; + } + return ctx->block_size - n; +} + +WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl ; + if (ctx == NULL || out == NULL) return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); + if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) { + *outl = 0; + return 1; + } + if (ctx->enc) { + if (ctx->bufUsed > 0) { + padBlock(ctx); + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) + return 0; + PRINT_BUF(out, ctx->block_size); + *outl = ctx->block_size; + } + } else { + if (ctx->lastUsed){ + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) { + XMEMCPY(out, ctx->lastBlock, fl); + *outl = fl; + } else return 0; + } + } + return 1; +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + switch (ctx->cipherType) { + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: +#endif +#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: +#endif +#if !defined(NO_AES) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: +#endif +#ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_ECB_TYPE: + case DES_EDE3_CBC_TYPE: + case DES_EDE3_ECB_TYPE: +#endif + return ctx->block_size; + default: + return 0; + } +} + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; /* dummy for #ifdef */ + #ifndef NO_DES3 + else if (XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0) + return DES_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_CBC_TYPE; + #if !defined(NO_DES3) + else if (XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0) + return DES_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_ECB_TYPE; + #endif /* NO_DES3 && HAVE_AES_ECB */ + #endif + + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + else if (XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + return AES_128_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + return AES_192_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + return AES_256_CBC_TYPE; + #endif /* !NO_AES && HAVE_AES_CBC */ + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + else if (XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0) + return AES_128_CTR_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0) + return AES_192_CTR_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0) + return AES_256_CTR_TYPE; + #endif /* !NO_AES && HAVE_AES_CBC */ + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + else if (XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0) + return AES_128_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0) + return AES_192_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0) + return AES_256_ECB_TYPE; + #endif /* !NO_AES && HAVE_AES_CBC */ + else return 0; +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return BAD_FUNC_ARG; + switch (cipherType(cipher)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return AES_BLOCK_SIZE; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return AES_BLOCK_SIZE; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return AES_BLOCK_SIZE; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 8; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 8; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + switch (cipherType(cipher)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE ; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return WOLFSSL_EVP_CIPH_CTR_MODE ; + #endif + #if !defined(NO_AES) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE ; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_EDE3_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE ; + case DES_ECB_TYPE: + case DES_EDE3_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE ; + #endif + default: + return 0; + } +} + +WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags = flags; + } +} + +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + if (padding) { + ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING; + } + else { + ctx->flags |= WOLFSSL_EVP_CIPH_NO_PADDING; + } + return 1; +} + +WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) +{ + (void)digest; + /* nothing to do */ + return 0; +} diff --git a/wolfcrypt/src/fe_low_mem.c b/wolfcrypt/src/fe_low_mem.c index 9caffa81f0..aa6a449961 100644 --- a/wolfcrypt/src/fe_low_mem.c +++ b/wolfcrypt/src/fe_low_mem.c @@ -183,7 +183,7 @@ static void raw_add(byte *x, const byte *p) for (i = 0; i < F25519_SIZE; i++) { c += ((word16)x[i]) + ((word16)p[i]); - x[i] = c; + x[i] = (byte)c; c >>= 8; } } @@ -197,11 +197,11 @@ static void raw_try_sub(byte *x, const byte *p) for (i = 0; i < F25519_SIZE; i++) { c = ((word16)x[i]) - ((word16)p[i]) - c; - minusp[i] = c; + minusp[i] = (byte)c; c = (c >> 8) & 1; } - fprime_select(x, minusp, x, c); + fprime_select(x, minusp, x, (byte)c); } @@ -271,7 +271,7 @@ void fprime_mul(byte *r, const byte *a, const byte *b, for (j = 0; j < F25519_SIZE; j++) { c |= ((word16)r[j]) << 1; - r[j] = c; + r[j] = (byte)c; c >>= 8; } raw_try_sub(r, modulus); @@ -310,7 +310,7 @@ void fe_normalize(byte *x) for (i = 0; i < F25519_SIZE; i++) { c += x[i]; - x[i] = c; + x[i] = (byte)c; c >>= 8; } @@ -322,12 +322,12 @@ void fe_normalize(byte *x) for (i = 0; i + 1 < F25519_SIZE; i++) { c += x[i]; - minusp[i] = c; + minusp[i] = (byte)c; c >>= 8; } c += ((word16)x[i]) - 128; - minusp[31] = c; + minusp[31] = (byte)c; /* Load x-p if no underflow */ fe_select(x, minusp, x, (c >> 15) & 1); @@ -355,7 +355,7 @@ void fe_add(fe r, const fe a, const fe b) for (i = 0; i < F25519_SIZE; i++) { c >>= 8; c += ((word16)a[i]) + ((word16)b[i]); - r[i] = c; + r[i] = (byte)c; } /* Reduce with 2^255 = 19 mod p */ @@ -364,7 +364,7 @@ void fe_add(fe r, const fe a, const fe b) for (i = 0; i < F25519_SIZE; i++) { c += r[i]; - r[i] = c; + r[i] = (byte)c; c >>= 8; } } diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c old mode 100644 new mode 100755 index 9dfeab093a..285f6c0cf3 --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -41,6 +41,9 @@ #include #endif +#ifdef HAVE___UINT128_T +#include "fe_x25519_128.i" +#else /* fe means field element. Here the field is \Z/(2^255-19). @@ -942,7 +945,7 @@ replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ -void fe_cswap(fe f,fe g,unsigned int b) +void fe_cswap(fe f, fe g, int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; @@ -1353,7 +1356,7 @@ replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ -void fe_cmov(fe f,const fe g,unsigned int b) +void fe_cmov(fe f, const fe g, int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; @@ -1407,6 +1410,7 @@ void fe_cmov(fe f,const fe g,unsigned int b) f[8] = f8 ^ x8; f[9] = f9 ^ x9; } +#endif #endif /* HAVE ED25519 or CURVE25519 */ #endif /* not defined CURVED25519_SMALL */ diff --git a/wolfcrypt/src/fe_x25519_128.i b/wolfcrypt/src/fe_x25519_128.i new file mode 100644 index 0000000000..d7297a260f --- /dev/null +++ b/wolfcrypt/src/fe_x25519_128.i @@ -0,0 +1,612 @@ +/* fp_mont_small.i + * + * Copyright (C) 2006-2017 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 + */ + +/* Convert a number represented as an array of bytes to an array of words with + * 51-bits of data in each word. + * + * in An array of bytes. + * out An array of words. + */ +void fe_frombytes(fe out, const unsigned char *in) +{ + out[0] = (((int64_t)((in[ 0] ) )) ) + | (((int64_t)((in[ 1] ) )) << 8) + | (((int64_t)((in[ 2] ) )) << 16) + | (((int64_t)((in[ 3] ) )) << 24) + | (((int64_t)((in[ 4] ) )) << 32) + | (((int64_t)((in[ 5] ) )) << 40) + | (((int64_t)((in[ 6] ) & 0x07)) << 48); + out[1] = (((int64_t)((in[ 6] >> 3) & 0x1f)) ) + | (((int64_t)((in[ 7] ) )) << 5) + | (((int64_t)((in[ 8] ) )) << 13) + | (((int64_t)((in[ 9] ) )) << 21) + | (((int64_t)((in[10] ) )) << 29) + | (((int64_t)((in[11] ) )) << 37) + | (((int64_t)((in[12] ) & 0x3f)) << 45); + out[2] = (((int64_t)((in[12] >> 6) & 0x03)) ) + | (((int64_t)((in[13] ) )) << 2) + | (((int64_t)((in[14] ) )) << 10) + | (((int64_t)((in[15] ) )) << 18) + | (((int64_t)((in[16] ) )) << 26) + | (((int64_t)((in[17] ) )) << 34) + | (((int64_t)((in[18] ) )) << 42) + | (((int64_t)((in[19] ) & 0x01)) << 50); + out[3] = (((int64_t)((in[19] >> 1) & 0x7f)) ) + | (((int64_t)((in[20] ) )) << 7) + | (((int64_t)((in[21] ) )) << 15) + | (((int64_t)((in[22] ) )) << 23) + | (((int64_t)((in[23] ) )) << 31) + | (((int64_t)((in[24] ) )) << 39) + | (((int64_t)((in[25] ) & 0x0f)) << 47); + out[4] = (((int64_t)((in[25] >> 4) & 0x0f)) ) + | (((int64_t)((in[26] ) )) << 4) + | (((int64_t)((in[27] ) )) << 12) + | (((int64_t)((in[28] ) )) << 20) + | (((int64_t)((in[29] ) )) << 28) + | (((int64_t)((in[30] ) )) << 36) + | (((int64_t)((in[31] ) & 0x7f)) << 44); +} + +/* Convert a number represented as an array of words to an array of bytes. + * The array of words is normalized to an array of 51-bit data words and if + * greater than the mod, modulo reduced by the prime 2^255 - 1. + * + * n An array of words. + * out An array of bytes. + */ +void fe_tobytes(unsigned char *out, const fe n) +{ + fe in; + int64_t c; + + in[0] = n[0]; + in[1] = n[1]; + in[2] = n[2]; + in[3] = n[3]; + in[4] = n[4]; + + /* Normalize to 51-bits of data per word. */ + in[0] += (in[4] >> 51) * 19; in[4] &= 0x7ffffffffffff; + + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[0] += (in[4] >> 51) * 19; + in[4] &= 0x7ffffffffffff; + + c = (in[0] + 19) >> 51; + c = (in[1] + c) >> 51; + c = (in[2] + c) >> 51; + c = (in[3] + c) >> 51; + c = (in[4] + c) >> 51; + in[0] += c * 19; + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[4] &= 0x7ffffffffffff; + + out[ 0] = (((byte)((in[0] ) )) ); + out[ 1] = (((byte)((in[0] >> 8) )) ); + out[ 2] = (((byte)((in[0] >> 16) )) ); + out[ 3] = (((byte)((in[0] >> 24) )) ); + out[ 4] = (((byte)((in[0] >> 32) )) ); + out[ 5] = (((byte)((in[0] >> 40) )) ); + out[ 6] = (((byte)((in[0] >> 48) & 0x07)) ) + | (((byte)((in[1] ) & 0x1f)) << 3); + out[ 7] = (((byte)((in[1] >> 5) )) ); + out[ 8] = (((byte)((in[1] >> 13) )) ); + out[ 9] = (((byte)((in[1] >> 21) )) ); + out[10] = (((byte)((in[1] >> 29) )) ); + out[11] = (((byte)((in[1] >> 37) )) ); + out[12] = (((byte)((in[1] >> 45) & 0x3f)) ) + | (((byte)((in[2] ) & 0x03)) << 6); + out[13] = (((byte)((in[2] >> 2) )) ); + out[14] = (((byte)((in[2] >> 10) )) ); + out[15] = (((byte)((in[2] >> 18) )) ); + out[16] = (((byte)((in[2] >> 26) )) ); + out[17] = (((byte)((in[2] >> 34) )) ); + out[18] = (((byte)((in[2] >> 42) )) ); + out[19] = (((byte)((in[2] >> 50) & 0x01)) ) + | (((byte)((in[3] ) & 0x7f)) << 1); + out[20] = (((byte)((in[3] >> 7) )) ); + out[21] = (((byte)((in[3] >> 15) )) ); + out[22] = (((byte)((in[3] >> 23) )) ); + out[23] = (((byte)((in[3] >> 31) )) ); + out[24] = (((byte)((in[3] >> 39) )) ); + out[25] = (((byte)((in[3] >> 47) & 0x0f)) ) + | (((byte)((in[4] ) & 0x0f)) << 4); + out[26] = (((byte)((in[4] >> 4) )) ); + out[27] = (((byte)((in[4] >> 12) )) ); + out[28] = (((byte)((in[4] >> 20) )) ); + out[29] = (((byte)((in[4] >> 28) )) ); + out[30] = (((byte)((in[4] >> 36) )) ); + out[31] = (((byte)((in[4] >> 44) & 0x7f)) ); +} + +/* Set the field element to 1. + * + * n The field element number. + */ +void fe_1(fe n) +{ + n[0] = 0x0000000000001; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Set the field element to 0. + * + * n The field element number. + */ +void fe_0(fe n) +{ + n[0] = 0x0000000000000; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Copy field element a into field element r. + * + * r Field element to copy into. + * a Field element to copy. + */ +void fe_copy(fe r, const fe a) +{ + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; + r[4] = a[4]; +} + +/* Constant time, conditional swap of field elements a and b. + * + * a A field element. + * b A field element. + * c If 1 then swap and if 0 then don't swap. + */ +void fe_cswap(fe a, fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + + b[0] ^= t0; + b[1] ^= t1; + b[2] ^= t2; + b[3] ^= t3; + b[4] ^= t4; +} + +/* Subtract b from a into r. (r = a - b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sub(fe r, const fe a, const fe b) +{ + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; + r[3] = a[3] - b[3]; + r[4] = a[4] - b[4]; +} + +/* Add b to a into r. (r = a + b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_add(fe r, const fe a, const fe b) +{ + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; + r[2] = a[2] + b[2]; + r[3] = a[3] + b[3]; + r[4] = a[4] + b[4]; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul(fe r, const fe a, const fe b) +{ + __int128_t t0 = ((__int128_t)a[0]) * b[0]; + __int128_t t1 = ((__int128_t)a[0]) * b[1] + + ((__int128_t)a[1]) * b[0]; + __int128_t t2 = ((__int128_t)a[0]) * b[2] + + ((__int128_t)a[1]) * b[1] + + ((__int128_t)a[2]) * b[0]; + __int128_t t3 = ((__int128_t)a[0]) * b[3] + + ((__int128_t)a[1]) * b[2] + + ((__int128_t)a[2]) * b[1] + + ((__int128_t)a[3]) * b[0]; + __int128_t t4 = ((__int128_t)a[0]) * b[4] + + ((__int128_t)a[1]) * b[3] + + ((__int128_t)a[2]) * b[2] + + ((__int128_t)a[3]) * b[1] + + ((__int128_t)a[4]) * b[0]; + __int128_t t5 = ((__int128_t)a[1]) * b[4] + + ((__int128_t)a[2]) * b[3] + + ((__int128_t)a[3]) * b[2] + + ((__int128_t)a[4]) * b[1]; + __int128_t t6 = ((__int128_t)a[2]) * b[4] + + ((__int128_t)a[3]) * b[3] + + ((__int128_t)a[4]) * b[2]; + __int128_t t7 = ((__int128_t)a[3]) * b[4] + + ((__int128_t)a[4]) * b[3]; + __int128_t t8 = ((__int128_t)a[4]) * b[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * 19; + t1 += t6 * 19; + t2 += t7 * 19; + t3 += t8 * 19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq(fe r, const fe a) +{ + __int128_t t0 = ((__int128_t)a[0]) * a[0]; + __int128_t t1 = ((__int128_t)a[0]) * a[1] * 2; + __int128_t t2 = ((__int128_t)a[0]) * a[2] * 2 + + ((__int128_t)a[1]) * a[1]; + __int128_t t3 = ((__int128_t)a[0]) * a[3] * 2 + + ((__int128_t)a[1]) * a[2] * 2; + __int128_t t4 = ((__int128_t)a[0]) * a[4] * 2 + + ((__int128_t)a[1]) * a[3] * 2 + + ((__int128_t)a[2]) * a[2]; + __int128_t t5 = ((__int128_t)a[1]) * a[4] * 2 + + ((__int128_t)a[2]) * a[3] * 2; + __int128_t t6 = ((__int128_t)a[2]) * a[4] * 2 + + ((__int128_t)a[3]) * a[3]; + __int128_t t7 = ((__int128_t)a[3]) * a[4] * 2; + __int128_t t8 = ((__int128_t)a[4]) * a[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * 19; + t1 += t6 * 19; + t2 += t7 * 19; + t3 += t8 * 19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Multiply a by 121666 and put result in r. (r = 121666 * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul121666(fe r, fe a) +{ + __int128_t t0 = ((__int128_t)a[0]) * (int64_t)121666; + __int128_t t1 = ((__int128_t)a[1]) * (int64_t)121666; + __int128_t t2 = ((__int128_t)a[2]) * (int64_t)121666; + __int128_t t3 = ((__int128_t)a[3]) * (int64_t)121666; + __int128_t t4 = ((__int128_t)a[4]) * (int64_t)121666; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +void fe_invert(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); for (i = 1; i < 1; ++i) fe_sq(t2, t2); fe_mul(t1, t1, t2); + fe_sq(t2, t1); for (i = 1; i < 5; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 20; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 100; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul( r, t1, t0); +} + +/* Scalar multiply the field element a by n using Montgomery Ladder and places + * result in r. + * + * r A field element as an array of bytes. + * n The scalar as an array of bytes. + * a A field element as an array of bytes. + */ +int curve25519(byte* r, byte* n, byte* a) +{ + fe x1, x2, z2, x3, z3; + fe t0, t1; + int pos; + unsigned int swap; + unsigned int b; + + fe_frombytes(x1, a); + fe_1(x2); + fe_0(z2); + fe_copy(x3, x1); + fe_1(z3); + + swap = 0; + for (pos = 254;pos >= 0;--pos) { + b = n[pos / 8] >> (pos & 7); + b &= 1; + swap ^= b; + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + swap = b; + + fe_sub(t0, x3, z3); + fe_sub(t1, x2, z2); + fe_add(x2, x2, z2); + fe_add(z2, x3, z3); + fe_mul(z3, t0, x2); + fe_mul(z2, z2, t1); + fe_sq(t0, t1); + fe_sq(t1, x2); + fe_add(x3, z3, z2); + fe_sub(z2, z3, z2); + fe_mul(x2, t1, t0); + fe_sub(t1, t1, t0); + fe_sq(z2, z2); + fe_mul121666(z3, t1); + fe_sq(x3, x3); + fe_add(t0, t0, z3); + fe_mul(z3, x1, z2); + fe_mul(z2, t1, t0); + } + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + + fe_invert(z2, z2); + fe_mul(x2, x2, z2); + fe_tobytes(r, x2); + + return 0; +} + +/* The field element value 0 as an array of bytes. */ +static const unsigned char zero[32] = {0}; + +/* Constant time check as to whether a is a not 0. + * + * a A field element. + */ +int fe_isnonzero(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return ConstantCompare(s, zero, 32); +} + +/* Checks whether a is negative. + * + * a A field element. + */ +int fe_isnegative(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return s[0] & 1; +} + +/* Negates field element a and stores the result in r. + * + * r A field element. + * a A field element. + */ +void fe_neg(fe r, const fe a) +{ + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; + r[4] = -a[4]; +} + +/* Constant time, conditional move of b into a. + * a is not changed if the condition is 0. + * + * a A field element. + * b A field element. + * c If 1 then copy and if 0 then don't copy. + */ +void fe_cmov(fe a, const fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; +} + +void fe_pow22523(fe r, const fe a) +{ + fe t0, t1, t2; + int i; + + /* a ^ (2^255 - 23) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); for (i = 1; i < 1; ++i) fe_sq(t0, t0); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 20; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 100; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t0, t0); for (i = 1; i < 2; ++i) fe_sq(t0, t0); fe_mul( r, t0, a); + + return; +} + +/* Double the square of a and put result in r. (r = 2 * a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq2(fe r, const fe a) +{ + __int128_t t0 = 2 * (((__int128_t)a[0]) * a[0]); + __int128_t t1 = 2 * (((__int128_t)a[0]) * a[1] * 2); + __int128_t t2 = 2 * (((__int128_t)a[0]) * a[2] * 2 + + ((__int128_t)a[1]) * a[1]); + __int128_t t3 = 2 * (((__int128_t)a[0]) * a[3] * 2 + + ((__int128_t)a[1]) * a[2] * 2); + __int128_t t4 = 2 * (((__int128_t)a[0]) * a[4] * 2 + + ((__int128_t)a[1]) * a[3] * 2 + + ((__int128_t)a[2]) * a[2]); + __int128_t t5 = 2 * (((__int128_t)a[1]) * a[4] * 2 + + ((__int128_t)a[2]) * a[3] * 2); + __int128_t t6 = 2 * (((__int128_t)a[2]) * a[4] * 2 + + ((__int128_t)a[3]) * a[3]); + __int128_t t7 = 2 * (((__int128_t)a[3]) * a[4] * 2); + __int128_t t8 = 2 * (((__int128_t)a[4]) * a[4]); + + /* Modulo reduce double long word. */ + t0 += t5 * 19; + t1 += t6 * 19; + t2 += t7 * 19; + t3 += t8 * 19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Load 3 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16)); + + return result; +} + +/* Load 4 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24)); + + return result; +} + diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 99eaeb2dca..bf9b2eee4b 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -274,38 +274,38 @@ void sc_reduce(byte* s) carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; + s[0] = (byte)(s0 >> 0); + s[1] = (byte)(s0 >> 8); + s[2] = (byte)((s0 >> 16) | (s1 << 5)); + s[3] = (byte)(s1 >> 3); + s[4] = (byte)(s1 >> 11); + s[5] = (byte)((s1 >> 19) | (s2 << 2)); + s[6] = (byte)(s2 >> 6); + s[7] = (byte)((s2 >> 14) | (s3 << 7)); + s[8] = (byte)(s3 >> 1); + s[9] = (byte)(s3 >> 9); + s[10] = (byte)((s3 >> 17) | (s4 << 4)); + s[11] = (byte)(s4 >> 4); + s[12] = (byte)(s4 >> 12); + s[13] = (byte)((s4 >> 20) | (s5 << 1)); + s[14] = (byte)(s5 >> 7); + s[15] = (byte)((s5 >> 15) | (s6 << 6)); + s[16] = (byte)(s6 >> 2); + s[17] = (byte)(s6 >> 10); + s[18] = (byte)((s6 >> 18) | (s7 << 3)); + s[19] = (byte)(s7 >> 5); + s[20] = (byte)(s7 >> 13); + s[21] = (byte)(s8 >> 0); + s[22] = (byte)(s8 >> 8); + s[23] = (byte)((s8 >> 16) | (s9 << 5)); + s[24] = (byte)(s9 >> 3); + s[25] = (byte)(s9 >> 11); + s[26] = (byte)((s9 >> 19) | (s10 << 2)); + s[27] = (byte)(s10 >> 6); + s[28] = (byte)((s10 >> 14) | (s11 << 7)); + s[29] = (byte)(s11 >> 1); + s[30] = (byte)(s11 >> 9); + s[31] = (byte)(s11 >> 17); /* hush warnings after setting values to 0 */ (void)s12; @@ -640,38 +640,38 @@ void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c) carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; + s[0] = (byte)(s0 >> 0); + s[1] = (byte)(s0 >> 8); + s[2] = (byte)((s0 >> 16) | (s1 << 5)); + s[3] = (byte)(s1 >> 3); + s[4] = (byte)(s1 >> 11); + s[5] = (byte)((s1 >> 19) | (s2 << 2)); + s[6] = (byte)(s2 >> 6); + s[7] = (byte)((s2 >> 14) | (s3 << 7)); + s[8] = (byte)(s3 >> 1); + s[9] = (byte)(s3 >> 9); + s[10] = (byte)((s3 >> 17) | (s4 << 4)); + s[11] = (byte)(s4 >> 4); + s[12] = (byte)(s4 >> 12); + s[13] = (byte)((s4 >> 20) | (s5 << 1)); + s[14] = (byte)(s5 >> 7); + s[15] = (byte)((s5 >> 15) | (s6 << 6)); + s[16] = (byte)(s6 >> 2); + s[17] = (byte)(s6 >> 10); + s[18] = (byte)((s6 >> 18) | (s7 << 3)); + s[19] = (byte)(s7 >> 5); + s[20] = (byte)(s7 >> 13); + s[21] = (byte)(s8 >> 0); + s[22] = (byte)(s8 >> 8); + s[23] = (byte)((s8 >> 16) | (s9 << 5)); + s[24] = (byte)(s9 >> 3); + s[25] = (byte)(s9 >> 11); + s[26] = (byte)((s9 >> 19) | (s10 << 2)); + s[27] = (byte)(s10 >> 6); + s[28] = (byte)((s10 >> 14) | (s11 << 7)); + s[29] = (byte)(s11 >> 1); + s[30] = (byte)(s11 >> 9); + s[31] = (byte)(s11 >> 17); /* hush warnings after setting values to 0 */ (void)s12; @@ -754,7 +754,7 @@ static unsigned char negative(signed char b) unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ - return x; + return (unsigned char)x; } @@ -765,7 +765,1354 @@ static void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b) fe_cmov(t->xy2d,u->xy2d,b); } - +#ifdef HAVE___UINT128_T +static const ge_precomp base[32][8] = { +{ + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x4e7fc933c71d7, 0x2cf41feb6b244, 0x7581c0a7d1a76, 0x7172d534d32f0, 0x590c063fa87d2 }, + { 0x1a56042b4d5a8, 0x189cc159ed153, 0x5b8deaa3cae04, 0x2aaf04f11b5d8, 0x6bb595a669c92 }, + { 0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58 }, + { 0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a }, + { 0x3fbe9c476ff09, 0x0af6b982e4b42, 0x0ad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553 }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x4eeeb77157131, 0x1201915f10741, 0x1669cda6c9c56, 0x45ec032db346d, 0x51e57bb6a2cc3 }, + { 0x006b67b7d8ca4, 0x084fa44e72933, 0x1154ee55d6f8a, 0x4425d842e7390, 0x38b64c41ae417 }, + { 0x4326702ea4b71, 0x06834376030b5, 0x0ef0512f9c380, 0x0f1a9f2512584, 0x10b8e91a9f0d6 }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x0915e76061bce }, + { 0x75dedf39234d9, 0x01c36ab1f3c54, 0x0f08fee58f5da, 0x0e19613a0d637, 0x3a9024a1320e0 }, + { 0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4 }, + }, +}, +{ + { + { 0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee }, + { 0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31 }, + { 0x444172106e4c7, 0x01251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864 }, + }, + { + { 0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x03bf9baf55080 }, + { 0x3c4277dbe5fde, 0x5a335afd44c92, 0x0c1164099753e, 0x70487006fe423, 0x25e61cabed66f }, + { 0x3e128cc586604, 0x5968b2e8fc7e2, 0x049a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e }, + }, + { + { 0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b }, + { 0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3 }, + { 0x746166985f7d4, 0x09939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5 }, + }, + { + { 0x70b2f4e71ecb8, 0x728148efc643c, 0x0753e03995b76, 0x5bf5fb2ab6767, 0x05fc3bc4535d7 }, + { 0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0x0b9cf062eb09e, 0x2fd9c71e5f758 }, + { 0x0b3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651 }, + }, + { + { 0x095cb14246590, 0x002d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907 }, + { 0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f }, + { 0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x02521cf67a635 }, + }, + { + { 0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x001753d9f7cd6 }, + { 0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382 }, + { 0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e }, + }, + { + { 0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c }, + { 0x0fbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x037e9023930ff, 0x749b76f96fb12 }, + { 0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0x0a8b0d4045af7, 0x0fcec10f01e02 }, + }, + { + { 0x2d29dc4244e45, 0x6927b1bc147be, 0x0308534ac0839, 0x4853664033f41, 0x413779166feab }, + { 0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0x0f981220e2d44, 0x4901aa7183c51 }, + { 0x1b7548c1af8f0, 0x7848c53368116, 0x01b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1 }, + }, +}, +{ + { + { 0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0x0a871e070c6a9 }, + { 0x07d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb }, + { 0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d }, + }, + { + { 0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x01850832f0ef1, 0x7d47c6a2cfb89 }, + { 0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912 }, + { 0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e }, + }, + { + { 0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0x0dccfe885b6b4, 0x278febad4eaea }, + { 0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db }, + { 0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6 }, + }, + { + { 0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x0165b5a48efca }, + { 0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5 }, + { 0x0a474a0846a76, 0x099a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec }, + }, + { + { 0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301 }, + { 0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7 }, + { 0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb }, + }, + { + { 0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0x0adc8d1a97b28, 0x06a1a6c288675 }, + { 0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6 }, + { 0x0d1d47c1764b6, 0x01c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274 }, + }, + { + { 0x4278b85eaec2e, 0x0ef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059 }, + { 0x777fd3a2dcc7f, 0x594a9fb124932, 0x01f8e80ca15f0, 0x714d13cec3269, 0x0403ed1d0ca67 }, + { 0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303 }, + }, + { + { 0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f }, + { 0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a }, + { 0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x0690c11b03bcd, 0x740dca6d58f0e }, + }, +}, +{ + { + { 0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0 }, + { 0x0ee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea }, + { 0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b }, + }, + { + { 0x53de66aa91948, 0x045f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2 }, + { 0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905 }, + { 0x6134b925112e1, 0x6bb942bb406ed, 0x070c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032 }, + }, + { + { 0x1fec6f0e7f04c, 0x3cebc692c477d, 0x077986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab }, + { 0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb }, + { 0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43 }, + }, + { + { 0x4431ca596cf14, 0x015da7c801405, 0x03c9b6f8f10b5, 0x0346922934017, 0x201f33139e457 }, + { 0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd }, + { 0x27f6b08039d51, 0x4802f8000dfaa, 0x09692a062c525, 0x1baea91075817, 0x397cba8862460 }, + }, + { + { 0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c }, + { 0x13093f05959b2, 0x1bd352f2ec618, 0x075789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6 }, + { 0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971 }, + }, + { + { 0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a }, + { 0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf }, + { 0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x088fe4eb8c225, 0x612436341f08b }, + }, + { + { 0x349e31a2d2638, 0x0137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90 }, + { 0x541db874e898d, 0x62d80fb841b33, 0x03e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef }, + { 0x02f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x036746419c8db, 0x45fe70f505243 }, + }, + { + { 0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2 }, + { 0x075a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39 }, + { 0x74a4401a308fd, 0x06ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3 }, + }, +}, +{ + { + { 0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8 }, + { 0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd }, + { 0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe }, + }, + { + { 0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd }, + { 0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0 }, + { 0x3b0cf4a465030, 0x022b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82 }, + }, + { + { 0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6 }, + { 0x004468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0x0bc3d08194a31 }, + { 0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19 }, + }, + { + { 0x0c172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x0770c9e824e1a }, + { 0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de }, + { 0x1d99a45b5b5fd, 0x523674f2499ec, 0x0f8fa26182613, 0x58f7398048c98, 0x39f264fd41500 }, + }, + { + { 0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0x0a761e4844a16, 0x65c621272c35f }, + { 0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889 }, + { 0x389f8ce3193dd, 0x2d424b8177ce5, 0x073fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce }, + }, + { + { 0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c }, + { 0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762 }, + { 0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0x0d5fde948eed6, 0x508214fa574bd }, + }, + { + { 0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb }, + { 0x269153ed6fe4b, 0x72a23aef89840, 0x052be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba }, + { 0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f }, + }, + { + { 0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9 }, + { 0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb }, + { 0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb }, + }, +}, +{ + { + { 0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x0844bdee2adf3, 0x4cbad279663ab }, + { 0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345 }, + { 0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007 }, + }, + { + { 0x45dc5f3c29094, 0x3455220b579af, 0x070c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d }, + { 0x71e6a266b2801, 0x09aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75 }, + { 0x297d86a7b3768, 0x4835a2f4c6332, 0x070305f434160, 0x183dd014e56ae, 0x7ccdd084387a0 }, + }, + { + { 0x484186760cc93, 0x7435665533361, 0x02f686336b801, 0x5225446f64331, 0x3593ca848190c }, + { 0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c }, + { 0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6 }, + }, + { + { 0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3 }, + { 0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3 }, + { 0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc }, + }, + { + { 0x615520fbf6363, 0x0b9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1 }, + { 0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f }, + { 0x0c938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647 }, + }, + { + { 0x08bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f }, + { 0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6 }, + { 0x6b517a751b13b, 0x0cfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e }, + }, + { + { 0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0x0fe9877824cde }, + { 0x3d2e0c30d0cd9, 0x3f597686671bb, 0x0aa587eb63999, 0x0e3c7b592c619, 0x6b2916c05448c }, + { 0x334d10aba913b, 0x045cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00 }, + }, + { + { 0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0x0ea89850aafe1, 0x416b151ab706a }, + { 0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0x0d61b8f78b2ab }, + { 0x0d7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e }, + }, +}, +{ + { + { 0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545 }, + { 0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc }, + { 0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115 }, + }, + { + { 0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x00731fbc78f89 }, + { 0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x021142e9c2b1c }, + { 0x0c71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15 }, + }, + { + { 0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9 }, + { 0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47 }, + { 0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4 }, + }, + { + { 0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e }, + { 0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189 }, + { 0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x022183510be8d }, + }, + { + { 0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404 }, + { 0x766385ead2d14, 0x0194f8b06095e, 0x08478f6823b62, 0x6018689d37308, 0x6a071ce17b806 }, + { 0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed }, + }, + { + { 0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424 }, + { 0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08 }, + { 0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924 }, + }, + { + { 0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7 }, + { 0x28e665ca59cc7, 0x165c715940dd9, 0x0785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84 }, + { 0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57 }, + }, + { + { 0x6706efc7c3484, 0x6987839ec366d, 0x0731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6 }, + { 0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64 }, + { 0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21 }, + }, +}, +{ + { + { 0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da }, + { 0x1214fe194961a, 0x0e1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917 }, + { 0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a }, + }, + { + { 0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66 }, + { 0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc }, + { 0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f }, + }, + { + { 0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52 }, + { 0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0x0d8cc1c48bc16 }, + { 0x402d36eb419a9, 0x7cef68c14a052, 0x0f1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16 }, + }, + { + { 0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53 }, + { 0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948 }, + { 0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4 }, + }, + { + { 0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c }, + { 0x094e7d7dced2a, 0x068fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99 }, + { 0x26c422e3622f4, 0x0f3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952 }, + }, + { + { 0x00c2af5f85c6b, 0x0609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0x0d1d2af9ffeb5 }, + { 0x0ed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x004475ea1a1bb, 0x0fee3e871e188 }, + { 0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531 }, + }, + { + { 0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161 }, + { 0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302 }, + { 0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f }, + }, + { + { 0x780f1680c3a94, 0x2a35d3cfcd453, 0x005e5cdc7ddf8, 0x6ee888078ac24, 0x054aa4b316b38 }, + { 0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1 }, + { 0x0468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da }, + }, +}, +{ + { + { 0x265e777d1f515, 0x0f1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc }, + { 0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d }, + { 0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0x0ad725db29ecb }, + }, + { + { 0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399 }, + { 0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03 }, + { 0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0x0bccbb72a2a86 }, + }, + { + { 0x55e4c50fe1296, 0x05fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3 }, + { 0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b }, + { 0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4 }, + }, + { + { 0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423 }, + { 0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d }, + { 0x0ba651c5b2b47, 0x5862363701027, 0x0c4d6c219c6db, 0x0f03dff8658de, 0x745d2ffa9c0cf }, + }, + { + { 0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x06e15be54c1dc }, + { 0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf }, + { 0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0x0fbbee20aa4ed, 0x58ded861278ec }, + }, + { + { 0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x08ba696b531d5 }, + { 0x73793f266c55c, 0x0b988a9c93b02, 0x09b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f }, + { 0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf }, + }, + { + { 0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x07433be3cb393 }, + { 0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0x0c2b85f39caca, 0x35d30a99b4d59 }, + { 0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d }, + }, + { + { 0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x0543618a01600 }, + { 0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa }, + { 0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079 }, + }, +}, +{ + { + { 0x454e91c529ccb, 0x24c98c6bf72cf, 0x0486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66 }, + { 0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6 }, + { 0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0x0c2a1c4bcda28 }, + }, + { + { 0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d }, + { 0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64 }, + { 0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x0404a5ca0afba }, + }, + { + { 0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e }, + { 0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9 }, + { 0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0x00b77ea5f78aa, 0x76579a29e822d }, + }, + { + { 0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x02c514bb2a277 }, + { 0x68e7e49c02a17, 0x45795346fe8b6, 0x089306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b }, + { 0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x02c989c8b6bd4, 0x1160920961548 }, + }, + { + { 0x05616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x0213ee10dfcea, 0x2f637d7491e6e }, + { 0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698 }, + { 0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2 }, + }, + { + { 0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5 }, + { 0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9 }, + { 0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0x0dea56e50e364, 0x556d1c8312ad7 }, + }, + { + { 0x06756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x097abe38cc8c7 }, + { 0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824 }, + { 0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8 }, + }, + { + { 0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009 }, + { 0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78 }, + { 0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635 }, + }, +}, +{ + { + { 0x0aaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7 }, + { 0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23 }, + { 0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895 }, + }, + { + { 0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x0408cc9469953, 0x50af7aed84afa }, + { 0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313 }, + { 0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x0033c0102c085, 0x1921a316baebd }, + }, + { + { 0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c }, + { 0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a }, + { 0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950 }, + }, + { + { 0x6eebe6084034b, 0x6cf01f70a8d7b, 0x0b41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647 }, + { 0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a }, + { 0x2b6e7a128b071, 0x5b27511755dcf, 0x08584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b }, + }, + { + { 0x048dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b }, + { 0x043c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0 }, + { 0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x079bfa9b08792 }, + }, + { + { 0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706 }, + { 0x03a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0x0ca769e789685, 0x038c77f684817 }, + { 0x65ee65b167bec, 0x052da19b850a9, 0x0408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf }, + }, + { + { 0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5 }, + { 0x080908a182fcf, 0x0532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f }, + { 0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x050eca52651e4 }, + }, + { + { 0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a }, + { 0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f }, + { 0x55c0dfdf05d96, 0x405569dcf475e, 0x05c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0 }, + }, +}, +{ + { + { 0x2aff530976b86, 0x0d85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340 }, + { 0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x09f56900584fd, 0x544d49292fc86 }, + { 0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316 }, + }, + { + { 0x3f635d32a7627, 0x0cbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06 }, + { 0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a }, + { 0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0x00f94051ee040 }, + }, + { + { 0x793bb07af9753, 0x1e7b6ecd4fafd, 0x02c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40 }, + { 0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x086d9b618b637, 0x07d79c7e8beab }, + { 0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64 }, + }, + { + { 0x06f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12 }, + { 0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee }, + { 0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x0621e2c7d3304 }, + }, + { + { 0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002 }, + { 0x060cc8259838d, 0x038d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x0007d6097bd3a }, + { 0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb }, + }, + { + { 0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55 }, + { 0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x02459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8 }, + { 0x094265066e80d, 0x0a60f918d61a5, 0x0444bf7f30fde, 0x1c40da9ed3c06, 0x079c170bd843b }, + }, + { + { 0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8 }, + { 0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f }, + { 0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5 }, + }, + { + { 0x147ab2bbea455, 0x1f240f2253126, 0x0c3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd }, + { 0x02b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929 }, + { 0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9 }, + }, +}, +{ + { + { 0x0639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x07a195152e095 }, + { 0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32 }, + { 0x68f02389e5fc8, 0x059f1bc877506, 0x504990e410cec, 0x09bd7d0feaee2, 0x3e8fe83d032f0 }, + }, + { + { 0x04c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258 }, + { 0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x003ef0e2d70b0, 0x75ba3b797fac4 }, + { 0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x0904d07b87779 }, + }, + { + { 0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72 }, + { 0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd }, + { 0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40 }, + }, + { + { 0x0d36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x03aa31507e1e5 }, + { 0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741 }, + { 0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4 }, + }, + { + { 0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x02b4d5e242940 }, + { 0x31e1988bb79bb, 0x7b82f46b3bcab, 0x0f7a8ce827b41, 0x5e15816177130, 0x326055cf5b276 }, + { 0x155cb28d18df2, 0x0c30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3 }, + }, + { + { 0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2 }, + { 0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0x0bf79176fd18a, 0x2cb67174ff60a }, + { 0x6cdf9390be1d0, 0x08e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f }, + }, + { + { 0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x01ed95554468f, 0x68698245d352e }, + { 0x2f2e0b3b2a224, 0x0c56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5 }, + { 0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0x0e7a25d714087, 0x46cf4c473daf0 }, + }, + { + { 0x46ea7f1498140, 0x70725690a8427, 0x0a73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc }, + { 0x525ed9ec4e5f9, 0x022d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5 }, + { 0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce }, + }, +}, +{ + { + { 0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f }, + { 0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0x0dfcefaa53320, 0x7369e6a92493a }, + { 0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4 }, + }, + { + { 0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0x0e0e9d86d24d3, 0x31e83b4161d08 }, + { 0x0bd1e249dd197, 0x00bcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a }, + { 0x0c7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550 }, + }, + { + { 0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x099dec18e71a4, 0x1a56fbaa62ba0 }, + { 0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0x0ea712017d489, 0x669a656457089 }, + { 0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58 }, + }, + { + { 0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b }, + { 0x25d465ab3e1b9, 0x0f8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b }, + { 0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd }, + }, + { + { 0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30 }, + { 0x47ff83362127d, 0x08e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0x0e645912219f7 }, + { 0x72f31d8394627, 0x07bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a }, + }, + { + { 0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950 }, + { 0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5 }, + { 0x06edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x05bff02328a11 }, + }, + { + { 0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a }, + { 0x2137023cae00b, 0x15a3599eb26c6, 0x0687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4 }, + { 0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b }, + }, + { + { 0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c }, + { 0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96 }, + { 0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb }, + }, +}, +{ + { + { 0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x058d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2 }, + { 0x42b256768d593, 0x2e88459427b4f, 0x02b3876630701, 0x34878d405eae5, 0x29cdd1adc088a }, + { 0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049 }, + }, + { + { 0x59a5fd67ff163, 0x3a998ead0352b, 0x083c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072 }, + { 0x0fd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0x0a4a26e2e2182, 0x5be8cc57092a7 }, + { 0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791 }, + }, + { + { 0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018 }, + { 0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030 }, + { 0x0172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x0728b6bfe6e91, 0x08420edd5fcdf }, + }, + { + { 0x0c34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x04d654f321db8 }, + { 0x720ab8362fa4a, 0x29c4347cdd9bf, 0x0e798ad5f8463, 0x4fef18bcb0bfe, 0x0d9a53efbc176 }, + { 0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991 }, + }, + { + { 0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e }, + { 0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31 }, + { 0x0274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc }, + }, + { + { 0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595 }, + { 0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0x0f3690d04eb8e, 0x73fcdd14b71c0 }, + { 0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0x0eb26573b10af, 0x389e740c9a9ce }, + }, + { + { 0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263 }, + { 0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6 }, + { 0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484 }, + }, + { + { 0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0x0f65320ef019b }, + { 0x21f74c3d2f773, 0x024b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1 }, + { 0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330 }, + }, +}, +{ + { + { 0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x010f93bc5fe67, 0x7ee498165acb2 }, + { 0x69624089c0a2e, 0x0075fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8 }, + { 0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0x0edf493c85b60 }, + }, + { + { 0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x04c00c54d1dfa }, + { 0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4 }, + { 0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617 }, + }, + { + { 0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a }, + { 0x664cc7493bbf4, 0x33d94761874e3, 0x0179e1796f613, 0x1890535e2867d, 0x0f9b8132182ec }, + { 0x059c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175 }, + }, + { + { 0x65d50c85066b0, 0x6167453361f7c, 0x06ba3818bb312, 0x6aff29baa7522, 0x08fea02ce8d48 }, + { 0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0x00b89b8576469 }, + { 0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d }, + }, + { + { 0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d }, + { 0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c }, + { 0x0cf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4 }, + }, + { + { 0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3 }, + { 0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813 }, + { 0x6a4d400a2509b, 0x041791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6 }, + }, + { + { 0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a }, + { 0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879 }, + { 0x0a0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e }, + }, + { + { 0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce }, + { 0x193434934d643, 0x0d4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9 }, + { 0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9 }, + }, +}, +{ + { + { 0x304bfacad8ea2, 0x502917d108b07, 0x043176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b }, + { 0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d }, + { 0x014d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd }, + }, + { + { 0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247 }, + { 0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b }, + { 0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2 }, + }, + { + { 0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4 }, + { 0x6cfab8de73e68, 0x3e6efced4bd21, 0x0056609500dbe, 0x71b7824ad85df, 0x577629c4a7f41 }, + { 0x0024509c6a888, 0x2696ab12e6644, 0x0cca27f4b80d8, 0x0c7c1f11b119e, 0x701f25bb0caec }, + }, + { + { 0x0f6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955 }, + { 0x0b0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40 }, + { 0x709439b805a35, 0x6ec48557f8187, 0x08a4d1ba13a2c, 0x076348a0bf9ae, 0x0e9b9cbb144ef }, + }, + { + { 0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3 }, + { 0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337 }, + { 0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593 }, + }, + { + { 0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed }, + { 0x39d2876f62700, 0x001cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552 }, + { 0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6 }, + }, + { + { 0x0e28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690 }, + { 0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x08fc3a4c677d5 }, + { 0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x068f1199f11fb, 0x4f2fad0116b90 }, + }, + { + { 0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e }, + { 0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef }, + { 0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289 }, + }, +}, +{ + { + { 0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4 }, + { 0x147499718289c, 0x0a48a67e4c7ab, 0x30fbc544bafe3, 0x0c701315fe58a, 0x20b878d577b75 }, + { 0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c }, + }, + { + { 0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154 }, + { 0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c }, + { 0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0x00ba739e2ae39 }, + }, + { + { 0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d }, + { 0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x03283a3e67ad7 }, + { 0x41dc7be0cb939, 0x1b16c66100904, 0x0a24c20cbc66d, 0x4a2e9efe48681, 0x05e1296846271 }, + }, + { + { 0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c }, + { 0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698 }, + { 0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x006b52076b3ff }, + }, + { + { 0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7 }, + { 0x0cfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x0912bef9ce9b8, 0x4d57e3443bc76 }, + { 0x0d4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602 }, + }, + { + { 0x3f3245bb2d80a, 0x0e5f720f36efd, 0x3b9cccf60c06d, 0x084e323f37926, 0x465812c8276c2 }, + { 0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3 }, + { 0x3beb22a1062d9, 0x6a7063b82c9a8, 0x0a5a35dc197ed, 0x3c80c06a53def, 0x05b32c2b1cb16 }, + }, + { + { 0x4a42c7ad58195, 0x5c8667e799eff, 0x02e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730 }, + { 0x05eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471 }, + { 0x0c524e14dd482, 0x283457496c656, 0x0ad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733 }, + }, + { + { 0x48b440c86c50d, 0x139929cca3b86, 0x0f8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c }, + { 0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98 }, + { 0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x006a573a83075, 0x3f8612966c870 }, + }, +}, +{ + { + { 0x0fcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1 }, + { 0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x09ebfb1432d98, 0x504aa77679736 }, + { 0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x034c2e0ad1a27, 0x4041943d9dba3 }, + }, + { + { 0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0x00ce58ea7bd01, 0x12d931429800d }, + { 0x0eeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843 }, + { 0x67799d337594f, 0x01647548f6018, 0x57fce5578f145, 0x009220c142a71, 0x1b4f92314359a }, + }, + { + { 0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2 }, + { 0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132 }, + { 0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x020c526a758f3 }, + }, + { + { 0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c }, + { 0x034f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x02aacc4615313 }, + { 0x0f7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8 }, + }, + { + { 0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3 }, + { 0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075 }, + { 0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592 }, + }, + { + { 0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614 }, + { 0x4a74cb50f9e56, 0x531d1c2640192, 0x0c03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a }, + { 0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25 }, + }, + { + { 0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d }, + { 0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce }, + { 0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1 }, + }, + { + { 0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2 }, + { 0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172 }, + { 0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d }, + }, +}, +{ + { + { 0x08d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d }, + { 0x0071b276d01c9, 0x0b0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db }, + { 0x00f1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x06e1cd13b19ea }, + }, + { + { 0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837 }, + { 0x0ad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16 }, + { 0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x03f3466bc182c, 0x30d0fded2e513 }, + }, + { + { 0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58 }, + { 0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0x0a9214202c099 }, + { 0x019c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5 }, + }, + { + { 0x08eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28 }, + { 0x031bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1 }, + { 0x5460af1cad202, 0x0b4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca }, + }, + { + { 0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4 }, + { 0x090f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d }, + { 0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf }, + }, + { + { 0x04a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018 }, + { 0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x08f338d0c85ee }, + { 0x3a821991a73bd, 0x03be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078 }, + }, + { + { 0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0x0db3e7e00cbfb }, + { 0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x05ce3a41191e6, 0x65ea753f10177 }, + { 0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0x0ed87df022109, 0x02a4ec1921e1a }, + }, + { + { 0x06162f1cf795f, 0x324ddcafe5eb9, 0x018d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067 }, + { 0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780 }, + { 0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82 }, + }, +}, +{ + { + { 0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x04af87a96e3a3, 0x57968290bb3a0 }, + { 0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a }, + { 0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa }, + }, + { + { 0x02a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x044fb81d82d50 }, + { 0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x097e37046fc77, 0x7ef72016758cc }, + { 0x718c5a907e3d9, 0x3b9c98c6b383b, 0x006ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d }, + }, + { + { 0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d }, + { 0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0x0a4e0373d784d }, + { 0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x071a7d0ace183 }, + }, + { + { 0x4355220e14431, 0x0e1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775 }, + { 0x72daac887ba0b, 0x0b7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7 }, + { 0x0d7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca }, + }, + { + { 0x1d4eba3d944be, 0x0100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x02ab9680ee8d3 }, + { 0x1000c2f41c6c5, 0x0219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a }, + { 0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b }, + }, + { + { 0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x09f20459f5168, 0x16fb869c03dd3 }, + { 0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0x0ae333f685277 }, + { 0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x03aa408fbf684, 0x3f81e38b8f70d }, + }, + { + { 0x37f355f17c824, 0x07ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0x0ad3e2d34cded }, + { 0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50 }, + { 0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1 }, + }, + { + { 0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d }, + { 0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4 }, + { 0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392 }, + }, +}, +{ + { + { 0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x0302f0cb36a3c, 0x0edc5f5eb426d }, + { 0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca }, + { 0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb }, + }, + { + { 0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122 }, + { 0x02abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x09d8eddeaa591, 0x2177bfa36dcb7 }, + { 0x01bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab }, + }, + { + { 0x17e44985bfb83, 0x54e32c626cc22, 0x096412ff38118, 0x6b241d61a246a, 0x75685abe5ba43 }, + { 0x3f6aa5344a32e, 0x69683680f11bb, 0x04c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3 }, + { 0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e }, + }, + { + { 0x716bce22e83fe, 0x33d0130b83eb8, 0x0952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a }, + { 0x0dbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3 }, + { 0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3 }, + }, + { + { 0x0443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a }, + { 0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638 }, + { 0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c }, + }, + { + { 0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x055dc39b6dea1 }, + { 0x7937ff7f927c2, 0x0c2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2 }, + { 0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2 }, + }, + { + { 0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3 }, + { 0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e }, + { 0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a }, + }, + { + { 0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x0473d308a7639 }, + { 0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e }, + { 0x6792603589e05, 0x248db9892595d, 0x006a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043 }, + }, +}, +{ + { + { 0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x096cc0f9baefa, 0x3f6bd725da4ea }, + { 0x0b9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x09edb93896d16, 0x36597d25ea5c0 }, + { 0x58d7b106058ac, 0x3cdf8d20bee69, 0x00a4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d }, + }, + { + { 0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x03bedc661bf5c }, + { 0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743 }, + { 0x0cb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0x0e7ce2b0cdf06 }, + }, + { + { 0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece }, + { 0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46 }, + { 0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d }, + }, + { + { 0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a }, + { 0x06ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0x0d1f8dbcf8eed }, + { 0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x00011b44a31bf }, + }, + { + { 0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x01308d46ebfcd, 0x63d988a2d2851 }, + { 0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835 }, + { 0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x0337c0b34d9c2, 0x33fad52b2368a }, + }, + { + { 0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0x0f151ff5b7376, 0x3cc355ccb90a7 }, + { 0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d }, + { 0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7 }, + }, + { + { 0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x05aa9b2c79399, 0x431f2c7f665f8 }, + { 0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91 }, + { 0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253 }, + }, + { + { 0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde }, + { 0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65 }, + { 0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3 }, + }, +}, +{ + { + { 0x19cd61ff38640, 0x060c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9 }, + { 0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x00311d00a9ff4, 0x2cdfdfecd5d05 }, + { 0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4 }, + }, + { + { 0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x07eb1f28bbe70, 0x03c935afc4b03 }, + { 0x65517fd181bae, 0x3e5772c76816d, 0x019189640898a, 0x1ed2a84de7499, 0x578edd74f63c1 }, + { 0x276c6492b0c3d, 0x09bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c }, + }, + { + { 0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x07aaca43cae1f, 0x62f05d7526374, 0x0e1bf66c6adba }, + { 0x0d27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc }, + { 0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88 }, + }, + { + { 0x3094ba1d6e334, 0x6e126a7e3300b, 0x089c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784 }, + { 0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db }, + { 0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9 }, + }, + { + { 0x073a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f }, + { 0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84 }, + { 0x12f5c6f136c7c, 0x0fedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f }, + }, + { + { 0x153d8f5e08181, 0x08533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f }, + { 0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3 }, + { 0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212 }, + }, + { + { 0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6 }, + { 0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38 }, + { 0x44ead1be8f7d6, 0x5759d4f31f466, 0x0378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6 }, + }, + { + { 0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x03a134ced89df, 0x7dcf843ce405f }, + { 0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f }, + { 0x0d6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271 }, + }, +}, +{ + { + { 0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7 }, + { 0x02014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x059a668f5a82e, 0x46115aba1d4dc }, + { 0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674 }, + }, + { + { 0x628d3a0a643b9, 0x01cd8640c93d2, 0x0b7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c }, + { 0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1 }, + { 0x63f06eda6e133, 0x233342758070f, 0x098e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e }, + }, + { + { 0x129126699b2e3, 0x0ee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8 }, + { 0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f }, + { 0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0x0bcd601a4e930, 0x0eafb03790e52 }, + }, + { + { 0x0805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435 }, + { 0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c }, + { 0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946 }, + }, + { + { 0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x01bd28338402c, 0x14f29a5383922 }, + { 0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754 }, + { 0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0 }, + }, + { + { 0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734 }, + { 0x3fc074571217f, 0x3a0d29b2b6aeb, 0x06478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e }, + { 0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x02522333bc2af, 0x0e34398f4a064 }, + }, + { + { 0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379 }, + { 0x522d93ecebde8, 0x024f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362 }, + { 0x0123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d }, + }, + { + { 0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58 }, + { 0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0x0eb28bf671928 }, + { 0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2 }, + }, +}, +{ + { + { 0x6f4bd567ae7a9, 0x65ac89317b783, 0x07d3b20fd8932, 0x000f208326916, 0x2ef9c5a5ba384 }, + { 0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c }, + { 0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f }, + }, + { + { 0x0918b1d61dc94, 0x0d350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0x0a738027f639d }, + { 0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7 }, + { 0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a }, + }, + { + { 0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3 }, + { 0x5318832b0ba78, 0x6f24b9ff17cec, 0x0a47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae }, + { 0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd }, + }, + { + { 0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d }, + { 0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f }, + { 0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b }, + }, + { + { 0x190b1829825d5, 0x0e7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2 }, + { 0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x04321adf49d75 }, + { 0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70 }, + }, + { + { 0x64624cfccb1ed, 0x257ab8072b6c1, 0x0120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d }, + { 0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d }, + { 0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621 }, + }, + { + { 0x18e3cc676e542, 0x26079d995a990, 0x04a7c217908b2, 0x1dc7603e6655a, 0x0dedfa10b2444 }, + { 0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615 }, + { 0x367d5b82b522a, 0x0d3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9 }, + }, + { + { 0x72836afb62874, 0x0af3c2094b240, 0x0c285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663 }, + { 0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d }, + { 0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05 }, + }, +}, +{ + { + { 0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320 }, + { 0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b }, + { 0x5fdcb41446a8e, 0x5286926ff2a71, 0x0f231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0 }, + }, + { + { 0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067 }, + { 0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed }, + { 0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d }, + }, + { + { 0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb }, + { 0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0x0a3b6063214f2, 0x5065f158c9fd2 }, + { 0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f }, + }, + { + { 0x5dfa56de66fde, 0x0058809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1 }, + { 0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x07e9d42d4a28a, 0x38dc083705acd }, + { 0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2 }, + }, + { + { 0x1fd11ed0c84a7, 0x021b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64 }, + { 0x36b15b807cba6, 0x3f78a9e1afed7, 0x0a59c2c608f1f, 0x52bdd8ecb81b7, 0x0b24f48847ed4 }, + { 0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481 }, + }, + { + { 0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x0119a3042fb37 }, + { 0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6 }, + { 0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20 }, + }, + { + { 0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x038b7ea483590 }, + { 0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x09674c6b99108 }, + { 0x6f82199316ff8, 0x05d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e }, + }, + { + { 0x4fb0e63066222, 0x130f59747e660, 0x041868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838 }, + { 0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x08f5114789a8d }, + { 0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d }, + }, +}, +{ + { + { 0x68549af3f666e, 0x09e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3 }, + { 0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x07fea2aba5132, 0x1926e1dc6401e }, + { 0x74e8aea17cea0, 0x0c743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5 }, + }, + { + { 0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0x0f2bf89f49f7e, 0x73fced18ee9a0 }, + { 0x055947d599832, 0x346fe2aa41990, 0x0164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c }, + { 0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864 }, + }, + { + { 0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0x0b76bb1b3fa7e }, + { 0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x0482c3aed35f9, 0x4e1af5271d31b }, + { 0x0c1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a }, + }, + { + { 0x0abf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6 }, + { 0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2 }, + { 0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61 }, + }, + { + { 0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30 }, + { 0x3d16733e248f3, 0x0e2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191 }, + { 0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd }, + }, + { + { 0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e }, + { 0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f }, + { 0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba }, + }, + { + { 0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x094707842cf44, 0x7dd73f960725d }, + { 0x42ddf2845ab2c, 0x6214ffd3276bb, 0x00b8d181a5246, 0x268a6d579eb20, 0x093ff26e58647 }, + { 0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x05209b3929d5a, 0x2f59bcbc86b47 }, + }, + { + { 0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082 }, + { 0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a }, + { 0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768 }, + }, +}, +{ + { + { 0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9 }, + { 0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce }, + { 0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e }, + }, + { + { 0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a }, + { 0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252 }, + { 0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459 }, + }, + { + { 0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340 }, + { 0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f }, + { 0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0x0f8893f02210c, 0x15596b3ae5710 }, + }, + { + { 0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x09c1495be913f, 0x3aa4e241afb6d }, + { 0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0x0d2237687b5f4 }, + { 0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a }, + }, + { + { 0x7a4732787ccdf, 0x11e427c7f0640, 0x03659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600 }, + { 0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6 }, + { 0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66 }, + }, + { + { 0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd }, + { 0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f }, + { 0x232cda2b4e554, 0x0422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x02c70bf52b68e }, + }, + { + { 0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43 }, + { 0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef }, + { 0x0f04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2 }, + }, + { + { 0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196 }, + { 0x7565a5cc7324f, 0x01ca0d5244a11, 0x116b067418713, 0x0a57d8c55edae, 0x6c6809c103803 }, + { 0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x05911b9f6ef7c }, + }, +}, +{ + { + { 0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2 }, + { 0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270 }, + { 0x770ba3b73bd08, 0x11475f7e186d4, 0x0251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817 }, + }, + { + { 0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3 }, + { 0x452036b1782fc, 0x02d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c }, + { 0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda }, + }, + { + { 0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b }, + { 0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db }, + { 0x2aa650dfa5ce7, 0x54916a8f19415, 0x00dc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091 }, + }, + { + { 0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a }, + { 0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x0040f3d945441 }, + { 0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254 }, + }, + { + { 0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7 }, + { 0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78 }, + { 0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c }, + }, + { + { 0x6d317e820107c, 0x090815d2ca3ca, 0x03ff1eb1499a1, 0x23960f050e319, 0x5373669c91611 }, + { 0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78 }, + { 0x014ab9a0e5257, 0x09939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87 }, + }, + { + { 0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x02f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6 }, + { 0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743 }, + { 0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1 }, + }, + { + { 0x0bc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5 }, + { 0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d }, + { 0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287 }, + }, +}, +{ + { + { 0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x087ed7e3bc55f, 0x7deb10149c726 }, + { 0x048478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a }, + { 0x2af6a8766ee7a, 0x08aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x08e68e9ff62ce }, + }, + { + { 0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71 }, + { 0x5500a4bc130ad, 0x127a17a938695, 0x02a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3 }, + { 0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2 }, + }, + { + { 0x172cdd596bdbd, 0x0731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a }, + { 0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3 }, + { 0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa }, + }, + { + { 0x55261e293eac6, 0x06426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x0760bb8d195ad }, + { 0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2 }, + { 0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac }, + }, + { + { 0x469656571f2d3, 0x0aa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x01b9c7b62e6dd }, + { 0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d }, + { 0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x08af5b784e4ba }, + }, + { + { 0x314d289cc2c4b, 0x23450e2f1bc4e, 0x0cd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98 }, + { 0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1 }, + { 0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2 }, + }, + { + { 0x14ce442ce221f, 0x18980a72516cc, 0x072f80db86677, 0x703331fda526e, 0x24b31d47691c8 }, + { 0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b }, + { 0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x04a7857b309a7, 0x545b585d14dda }, + }, + { + { 0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x038858667fead, 0x4d22dc3e64c8d }, + { 0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0x0f62f9c332ba5 }, + { 0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371 }, + }, +}, +{ + { + { 0x02b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0x0a037db9f2a62, 0x4005419b1d2bc }, + { 0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0x0fa3614f3b1ca }, + { 0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a }, + }, + { + { 0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0x0eae41ce355cc, 0x6c535d13ff776 }, + { 0x49448fac8f53e, 0x34f74c6e8356a, 0x0ad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86 }, + { 0x534e93e8a35af, 0x08b10fd02c997, 0x26ac2acb81e05, 0x09d8c98ce3b79, 0x25e17fe4d50ac }, + }, + { + { 0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698 }, + { 0x09bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb }, + { 0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7 }, + }, + { + { 0x091e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd }, + { 0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x01ab12d5807e3 }, + { 0x5189041e32d96, 0x05b062b090231, 0x0c91766e7b78f, 0x0aa0f55a138ec, 0x4a3961e2c918a }, + }, + { + { 0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x08fc1dad38b79, 0x68aceead9bd41 }, + { 0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db }, + { 0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f }, + }, + { + { 0x2cbebfd022790, 0x0b8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515 }, + { 0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0x0d49fc5e044be, 0x709fa43edcb29 }, + { 0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81 }, + }, + { + { 0x2afaa5e10b0b9, 0x61de08355254d, 0x0eb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd }, + { 0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0x0b7d5d8a6c314 }, + { 0x448327b95d543, 0x0146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de }, + }, + { + { 0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x053713fe3b7e6, 0x19735fd7f6bc2 }, + { 0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc }, + { 0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0x0fef911191df8 }, + }, +}, +}; +#else /* base[i][j] = (j+1)*256^i*B */ static const ge_precomp base[32][8] = { { @@ -2113,6 +3460,7 @@ static const ge_precomp base[32][8] = { }, }, } ; +#endif static void ge_select(ge_precomp *t,int pos,signed char b) @@ -2221,7 +3569,50 @@ static void slide(signed char *r,const unsigned char *a) } } - +#ifdef HAVE___UINT128_T +static const ge_precomp Bi[8] = { + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x6678aa6a8632f, 0x5ea3788d8b365, 0x21bd6d6994279, 0x7ace75919e4e3, 0x34b9ed338add7 }, + { 0x6217e039d8064, 0x6dea408337e6d, 0x57ac112628206, 0x647cb65e30473, 0x49c05a51fadc9 }, + { 0x4e8bf9045af1b, 0x514e33a45e0d6, 0x7533c5b8bfe0f, 0x583557b7e14c9, 0x73c172021b008 }, + }, + { + { 0x700848a802ade, 0x1e04605c4e5f7, 0x5c0d01b9767fb, 0x7d7889f42388b, 0x4275aae2546d8 }, + { 0x75b0249864348, 0x52ee11070262b, 0x237ae54fb5acd, 0x3bfd1d03aaab5, 0x18ab598029d5c }, + { 0x32cc5fd6089e9, 0x426505c949b05, 0x46a18880c7ad2, 0x4a4221888ccda, 0x3dc65522b53df }, + }, + { + { 0x0c222a2007f6d, 0x356b79bdb77ee, 0x41ee81efe12ce, 0x120a9bd07097d, 0x234fd7eec346f }, + { 0x7013b327fbf93, 0x1336eeded6a0d, 0x2b565a2bbf3af, 0x253ce89591955, 0x0267882d17602 }, + { 0x0a119732ea378, 0x63bf1ba8e2a6c, 0x69f94cc90df9a, 0x431d1779bfc48, 0x497ba6fdaa097 }, + }, + { + { 0x6cc0313cfeaa0, 0x1a313848da499, 0x7cb534219230a, 0x39596dedefd60, 0x61e22917f12de }, + { 0x3cd86468ccf0b, 0x48553221ac081, 0x6c9464b4e0a6e, 0x75fba84180403, 0x43b5cd4218d05 }, + { 0x2762f9bd0b516, 0x1c6e7fbddcbb3, 0x75909c3ace2bd, 0x42101972d3ec9, 0x511d61210ae4d }, + }, +}; +#else static const ge_precomp Bi[8] = { { { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, @@ -2264,6 +3655,7 @@ static const ge_precomp Bi[8] = { { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, }, } ; +#endif /* @@ -2272,7 +3664,7 @@ where a = a[0]+256*a[1]+...+256^31 a[31]. and b = b[0]+256*b[1]+...+256^31 b[31]. B is the Ed25519 base point (x,4/5) with x positive. */ -int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, +int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { signed char aslide[256]; @@ -2327,17 +3719,30 @@ int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, return 0; } - +#ifdef HAVE___UINT128_T +static const fe d = { + 0x34dca135978a3, 0x1a8283b156ebd, 0x5e7a26001c029, 0x739c663a03cbb, + 0x52036cee2b6ff +}; +#else static const fe d = { -10913610,13857413,-15372611,6949391,114729, -8787816,-6275908,-3247719,-18696448,-12055116 } ; +#endif +#ifdef HAVE___UINT128_T +static const fe sqrtm1 = { + 0x61b274a0ea0b0, 0x0d5a5fc8f189d, 0x7ef5e9cbd0c60, 0x78595a6804c9e, + 0x2b8324804fc1d +}; +#else static const fe sqrtm1 = { -32595792,-7943725,9377950,3500415,12389472, -272473,-25146209,-2005654,326686,11406482 } ; +#endif int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) @@ -2516,10 +3921,17 @@ void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) r = p */ +#ifdef HAVE___UINT128_T +static const fe d2 = { + 0x69b9426b2f159, 0x35050762add7a, 0x3cf44c0038052, 0x6738cc7407977, + 0x2406d9dc56dff +}; +#else static const fe d2 = { -21827239,-5839606,-30745221,13898782,229458, 15978800,-12551817,-6495438,29715968,9444199 } ; +#endif extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 87d4d0fe18..58a9c22514 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -166,7 +166,7 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, if (hash_len < dig_size) { return BUFFER_E; } - + /* Suppress possible unused arg if all hashing is disabled */ (void)data; (void)data_len; @@ -236,41 +236,32 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_InitMd5(&hash->md5); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_InitSha(&hash->sha); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_InitSha224(&hash->sha224); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_InitSha256(&hash->sha256); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_InitSha384(&hash->sha384); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_InitSha512(&hash->sha512); - if (ret != 0) - return ret; #endif break; @@ -280,10 +271,10 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, @@ -298,41 +289,34 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Update(&hash->md5, data, dataSz); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaUpdate(&hash->sha, data, dataSz); if (ret != 0) -#endif return ret; +#endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Update(&hash->sha224, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Update(&hash->sha256, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Update(&hash->sha384, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Update(&hash->sha512, data, dataSz); - if (ret != 0) - return ret; #endif break; @@ -342,10 +326,10 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) @@ -359,41 +343,32 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Final(&hash->md5, out); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaFinal(&hash->sha, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Final(&hash->sha224, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Final(&hash->sha256, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Final(&hash->sha384, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Final(&hash->sha512, out); - if (ret != 0) - return ret; #endif break; @@ -403,92 +378,80 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } #if !defined(WOLFSSL_TI_HASH) #if !defined(NO_MD5) -void wc_Md5GetHash(Md5* md5, byte* hash) -{ - Md5 save = *md5 ; - wc_Md5Final(md5, hash) ; - *md5 = save ; -} + int wc_Md5Hash(const byte* data, word32 len, byte* hash) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + Md5* md5; + #else + Md5 md5[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; + #endif + + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_Md5Update(md5, data, len); + if (ret == 0) { + ret = wc_Md5Final(md5, hash); + } + } -WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { - *m1 = *m2 ; -} + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif -#endif + return ret; + } +#endif /* !NO_MD5 */ #if !defined(NO_SHA) -int wc_ShaGetHash(Sha* sha, byte* hash) -{ - int ret ; - Sha save = *sha ; - ret = wc_ShaFinal(sha, hash) ; - *sha = save ; - return ret ; -} - -void wc_ShaRestorePos(Sha* s1, Sha* s2) { - *s1 = *s2 ; -} - -int wc_ShaHash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha* sha; -#else - Sha sha[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha(sha)) != 0) { - WOLFSSL_MSG("wc_InitSha failed"); - } - else { - wc_ShaUpdate(sha, data, len); - wc_ShaFinal(sha, hash); + int wc_ShaHash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha* sha; + #else + Sha sha[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("wc_InitSha failed"); + } + else { + wc_ShaUpdate(sha, data, len); + wc_ShaFinal(sha, hash); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; - -} - -#endif /* !defined(NO_SHA) */ +#endif /* !NO_SHA */ #if defined(WOLFSSL_SHA224) -int wc_Sha224GetHash(Sha224* sha224, byte* hash) -{ - int ret; - Sha224 save; - - if (sha224 == NULL || hash == NULL) - return BAD_FUNC_ARG; - - save= *sha224; - ret = wc_Sha224Final(sha224, hash); - *sha224 = save; - - return ret; -} - int wc_Sha224Hash(const byte* data, word32 len, byte* hash) { int ret = 0; @@ -520,154 +483,109 @@ int wc_Sha224Hash(const byte* data, word32 len, byte* hash) return ret; } - -#endif /* defined(WOLFSSL_SHA224) */ +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -int wc_Sha256GetHash(Sha256* sha256, byte* hash) -{ - int ret ; - Sha256 save = *sha256 ; - ret = wc_Sha256Final(sha256, hash) ; - *sha256 = save ; - return ret ; -} - -void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - *s1 = *s2 ; -} - -int wc_Sha256Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256; -#else - Sha256 sha256[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha256(sha256)) != 0) { - WOLFSSL_MSG("InitSha256 failed"); - } - else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { - WOLFSSL_MSG("Sha256Update failed"); - } - else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { - WOLFSSL_MSG("Sha256Final failed"); + int wc_Sha256Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha256* sha256; + #else + Sha256 sha256[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha256(sha256)) != 0) { + WOLFSSL_MSG("InitSha256 failed"); + } + else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { + WOLFSSL_MSG("Sha256Update failed"); + } + else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { + WOLFSSL_MSG("Sha256Final failed"); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#endif /* !defined(NO_SHA256) */ +#endif /* !NO_SHA256 */ #endif /* !defined(WOLFSSL_TI_HASH) */ -#if defined(WOLFSSL_SHA512) -int wc_Sha512GetHash(Sha512* sha512, byte* hash) -{ - int ret; - Sha512 save; - - if (sha512 == NULL || hash == NULL) - return BAD_FUNC_ARG; - - save= *sha512; - ret = wc_Sha512Final(sha512, hash); - *sha512 = save; - - return ret; -} - -int wc_Sha512Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha512* sha512; -#else - Sha512 sha512[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL) - return MEMORY_E; -#endif - if ((ret = wc_InitSha512(sha512)) != 0) { - WOLFSSL_MSG("InitSha512 failed"); - } - else if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { - WOLFSSL_MSG("Sha512Update failed"); - } - else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { - WOLFSSL_MSG("Sha512Final failed"); +#if defined(WOLFSSL_SHA512) + int wc_Sha512Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha512* sha512; + #else + Sha512 sha512[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha512(sha512)) != 0) { + WOLFSSL_MSG("InitSha512 failed"); + } + else if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { + WOLFSSL_MSG("Sha512Update failed"); + } + else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { + WOLFSSL_MSG("Sha512Final failed"); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#if defined(WOLFSSL_SHA384) -int wc_Sha384GetHash(Sha384* sha384, byte* hash) -{ - int ret; - Sha384 save; - - if (sha384 == NULL || hash == NULL) - return BAD_FUNC_ARG; - - save= *sha384; - ret = wc_Sha384Final(sha384, hash); - *sha384 = save; - - return ret; -} - -int wc_Sha384Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha384* sha384; -#else - Sha384 sha384[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL) - return MEMORY_E; -#endif + #if defined(WOLFSSL_SHA384) + int wc_Sha384Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha384* sha384; + #else + Sha384 sha384[1]; + #endif - if ((ret = wc_InitSha384(sha384)) != 0) { - WOLFSSL_MSG("InitSha384 failed"); - } - else if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { - WOLFSSL_MSG("Sha384Update failed"); - } - else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { - WOLFSSL_MSG("Sha384Final failed"); - } + #ifdef WOLFSSL_SMALL_STACK + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL) + return MEMORY_E; + #endif -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if ((ret = wc_InitSha384(sha384)) != 0) { + WOLFSSL_MSG("InitSha384 failed"); + } + else if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { + WOLFSSL_MSG("Sha384Update failed"); + } + else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { + WOLFSSL_MSG("Sha384Final failed"); + } - return ret; -} + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif -#endif /* defined(WOLFSSL_SHA384) */ -#endif /* defined(WOLFSSL_SHA512) */ + return ret; + } + #endif /* WOLFSSL_SHA384 */ +#endif /* WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c old mode 100644 new mode 100755 index a699b65429..0dc7453614 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -30,83 +30,87 @@ #include -#ifdef HAVE_FIPS -/* does init */ -int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) -{ - return HmacSetKey_fips(hmac, type, key, keySz); -} - - -int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) -{ - return HmacUpdate_fips(hmac, in, sz); -} - - -int wc_HmacFinal(Hmac* hmac, byte* out) -{ - return HmacFinal_fips(hmac, out); -} +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif -#ifdef WOLFSSL_ASYNC_CRYPT - int wc_HmacAsyncInit(Hmac* hmac, int i) +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + /* does init */ + int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) { - return HmacAsyncInit(hmac, i); + return HmacSetKey_fips(hmac, type, key, keySz); } - - - void wc_HmacAsyncFree(Hmac* hmac) + int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) { - HmacAsyncFree(hmac); + return HmacUpdate_fips(hmac, in, sz); + } + int wc_HmacFinal(Hmac* hmac, byte* out) + { + return HmacFinal_fips(hmac, out); + } + int wolfSSL_GetHmacMaxSize(void) + { + return CyaSSL_GetHmacMaxSize(); } -#endif - -int wolfSSL_GetHmacMaxSize(void) -{ - return CyaSSL_GetHmacMaxSize(); -} -#ifdef HAVE_HKDF + int wc_HmacInit(Hmac* hmac, void* heap, int devId) + { + (void)hmac; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return HmacInit(hmac, heap, devId); */ + return 0; + } + void wc_HmacFree(Hmac* hmac) + { + (void)hmac; + /* FIPS doesn't support: + HmacFree(hmac); */ + } -int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + #ifdef HAVE_HKDF + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, byte* out, word32 outSz) -{ - return HKDF(type, inKey, inKeySz, salt, saltSz, info, infoSz, out, outSz); -} - + { + return HKDF(type, inKey, inKeySz, salt, saltSz, + info, infoSz, out, outSz); + } + #endif /* HAVE_HKDF */ -#endif /* HAVE_HKDF */ #else /* else build without fips */ -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw -#define wc_InitSha wc_InitSha_sw -#define wc_ShaUpdate wc_ShaUpdate_sw -#define wc_ShaFinal wc_ShaFinal_sw +#include -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw -#endif +#ifdef WOLFSSL_PIC32MZ_HASH + #define wc_InitMd5 wc_InitMd5_sw + #define wc_Md5Update wc_Md5Update_sw + #define wc_Md5Final wc_Md5Final_sw -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif + #define wc_InitSha wc_InitSha_sw + #define wc_ShaUpdate wc_ShaUpdate_sw + #define wc_ShaFinal wc_ShaFinal_sw + + #define wc_InitSha256 wc_InitSha256_sw + #define wc_Sha256Update wc_Sha256Update_sw + #define wc_Sha256Final wc_Sha256Final_sw +#endif /* WOLFSSL_PIC32MZ_HASH */ -#include int wc_HmacSizeByType(int type) { + int ret; + if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 || type == SHA512 || type == BLAKE2B_ID || type == SHA224)) { @@ -116,121 +120,151 @@ int wc_HmacSizeByType(int type) switch (type) { #ifndef NO_MD5 case MD5: - return MD5_DIGEST_SIZE; - #endif + ret = MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ #ifndef NO_SHA case SHA: - return SHA_DIGEST_SIZE; - #endif + ret = SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ - #ifdef WOLF_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: - return SHA224_DIGEST_SIZE; - #endif + ret = SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ #ifndef NO_SHA256 case SHA256: - return SHA256_DIGEST_SIZE; - #endif + ret = SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA384 case SHA384: - return SHA384_DIGEST_SIZE; - #endif - - #ifdef WOLFSSL_SHA512 + ret = SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - return SHA512_DIGEST_SIZE; - #endif + ret = SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - return BLAKE2B_OUTBYTES; - #endif + ret = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + break; } + + return ret; } -static int InitHmac(Hmac* hmac, int type) +static int _InitHmac(Hmac* hmac, int type, void* heap) { int ret = 0; - hmac->innerHashKeyed = 0; - hmac->macType = (byte)type; - - if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 - || type == SHA512 || type == BLAKE2B_ID - || type == SHA224)) - return BAD_FUNC_ARG; - switch (type) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - wc_InitMd5(&hmac->hash.md5); - break; - #endif + ret = wc_InitMd5(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: ret = wc_InitSha(&hmac->hash.sha); - break; - #endif + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: ret = wc_InitSha224(&hmac->hash.sha224); - break; - #endif + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: ret = wc_InitSha256(&hmac->hash.sha256); - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: ret = wc_InitSha384(&hmac->hash.sha384); - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: ret = wc_InitSha512(&hmac->hash.sha512); - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + break; } + /* default to NULL heap hint or test value */ +#ifdef WOLFSSL_HEAP_TEST + hmac->heap = (void)WOLFSSL_HEAP_TEST; +#else + hmac->heap = heap; +#endif /* WOLFSSL_HEAP_TEST */ + return ret; } int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) { - byte* ip = (byte*) hmac->ipad; - byte* op = (byte*) hmac->opad; + byte* ip; + byte* op; word32 i, hmac_block_size = 0; - int ret; + int ret = 0; + void* heap = NULL; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (hmac == NULL || (key == NULL && length != 0) || + !(type == MD5 || type == SHA || type == SHA256 || type == SHA384 + || type == SHA512 || type == BLAKE2B_ID + || type == SHA224)) { + return BAD_FUNC_ARG; + } + + hmac->innerHashKeyed = 0; + hmac->macType = (byte)type; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacSetKey(hmac, type, key, length); + #if defined(HAVE_CAVIUM) || defined(HAVE_INTEL_QA) + if (length > HMAC_BLOCK_SIZE) { + return WC_KEY_SIZE_E; + } + + if (key != NULL) { + XMEMCPY(hmac->keyRaw, key, length); + } + hmac->keyLen = (word16)length; + + return 0; /* nothing to do here */ + #endif /* HAVE_CAVIUM || HAVE_INTEL_QA */ } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ - ret = InitHmac(hmac, type); + ret = _InitHmac(hmac, type, heap); if (ret != 0) return ret; @@ -239,160 +273,172 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) return HMAC_MIN_KEYLEN_E; #endif + ip = (byte*)hmac->ipad; + op = (byte*)hmac->opad; + switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - { hmac_block_size = MD5_BLOCK_SIZE; if (length <= MD5_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - wc_Md5Update(&hmac->hash.md5, key, length); - wc_Md5Final(&hmac->hash.md5, ip); + ret = wc_Md5Update(&hmac->hash.md5, key, length); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, ip); + if (ret != 0) + break; length = MD5_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - { hmac_block_size = SHA_BLOCK_SIZE; if (length <= SHA_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - wc_ShaUpdate(&hmac->hash.sha, key, length); - wc_ShaFinal(&hmac->hash.sha, ip); + ret = wc_ShaUpdate(&hmac->hash.sha, key, length); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, ip); + if (ret != 0) + break; + length = SHA_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: { hmac_block_size = SHA224_BLOCK_SIZE; if (length <= SHA224_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha224Update(&hmac->hash.sha224, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha224Final(&hmac->hash.sha224, ip); if (ret != 0) - return ret; + break; length = SHA224_DIGEST_SIZE; } } break; - #endif + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: - { hmac_block_size = SHA256_BLOCK_SIZE; if (length <= SHA256_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha256Update(&hmac->hash.sha256, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha256Final(&hmac->hash.sha256, ip); if (ret != 0) - return ret; + break; length = SHA256_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: - { hmac_block_size = SHA384_BLOCK_SIZE; if (length <= SHA384_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha384Update(&hmac->hash.sha384, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha384Final(&hmac->hash.sha384, ip); if (ret != 0) - return ret; + break; length = SHA384_DIGEST_SIZE; } - } - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - { hmac_block_size = SHA512_BLOCK_SIZE; if (length <= SHA512_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha512Update(&hmac->hash.sha512, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha512Final(&hmac->hash.sha512, ip); if (ret != 0) - return ret; + break; length = SHA512_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - { hmac_block_size = BLAKE2B_BLOCKBYTES; if (length <= BLAKE2B_BLOCKBYTES) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); if (ret != 0) - return ret; - + break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); if (ret != 0) - return ret; + break; length = BLAKE2B_256; } - } - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: return BAD_FUNC_ARG; } - if (length < hmac_block_size) - XMEMSET(ip + length, 0, hmac_block_size - length); - for(i = 0; i < hmac_block_size; i++) { - op[i] = ip[i] ^ OPAD; - ip[i] ^= IPAD; + if (ret == 0) { + if (length < hmac_block_size) + XMEMSET(ip + length, 0, hmac_block_size - length); + + for(i = 0; i < hmac_block_size; i++) { + op[i] = ip[i] ^ OPAD; + ip[i] ^= IPAD; + } } - return 0; + + return ret; } @@ -401,68 +447,60 @@ static int HmacKeyInnerHash(Hmac* hmac) int ret = 0; switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - wc_Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); - break; - #endif + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad, + MD5_BLOCK_SIZE); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE); - break; - #endif + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad, + SHA_BLOCK_SIZE); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->ipad, SHA224_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad, + SHA224_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->ipad, SHA256_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad, + SHA256_BLOCK_SIZE); + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->ipad, SHA384_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif - - #ifdef WOLFSSL_SHA512 + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad, + SHA384_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->ipad, SHA512_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad, + SHA512_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->ipad, + BLAKE2B_BLOCKBYTES); + break; + #endif /* HAVE_BLAKE2 */ default: - break; + break; } - hmac->innerHashKeyed = 1; + if (ret == 0) + hmac->innerHashKeyed = 1; return ret; } @@ -470,13 +508,18 @@ static int HmacKeyInnerHash(Hmac* hmac) int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { - int ret; + int ret = 0; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_CAVIUM) return NitroxHmacUpdate(hmac, msg, length); + #elif defined(HAVE_INTEL_QA) + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + hmac->keyRaw, hmac->keyLen, NULL, msg, length); + #endif } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ if (!hmac->innerHashKeyed) { ret = HmacKeyInnerHash(hmac); @@ -485,63 +528,52 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) } switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - wc_Md5Update(&hmac->hash.md5, msg, length); - break; - #endif + ret = wc_Md5Update(&hmac->hash.md5, msg, length); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - wc_ShaUpdate(&hmac->hash.sha, msg, length); - break; - #endif + ret = wc_ShaUpdate(&hmac->hash.sha, msg, length); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: ret = wc_Sha224Update(&hmac->hash.sha224, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: ret = wc_Sha256Update(&hmac->hash.sha256, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: ret = wc_Sha384Update(&hmac->hash.sha384, msg, length); - if (ret != 0) - return ret; - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: ret = wc_Sha512Update(&hmac->hash.sha512, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - break; + break; } - return 0; + return ret; } @@ -549,11 +581,20 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) { int ret; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacFinal(hmac, hash); + int hashLen = wc_HmacSizeByType(hmac->macType); + if (hashLen <= 0) + return hashLen; + + #if defined(HAVE_CAVIUM) + return NitroxHmacFinal(hmac, hmac->macType, hash, hashLen); + #elif defined(HAVE_INTEL_QA) + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + hmac->keyRaw, hmac->keyLen, hash, NULL, hashLen); + #endif } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ if (!hmac->innerHashKeyed) { ret = HmacKeyInnerHash(hmac); @@ -562,216 +603,184 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) } switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - { - wc_Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash); - - wc_Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE); - wc_Md5Update(&hmac->hash.md5, - (byte*) hmac->innerHash, MD5_DIGEST_SIZE); - - wc_Md5Final(&hmac->hash.md5, hash); - } - break; - #endif + ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad, + MD5_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash, + MD5_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, hash); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - { - wc_ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); - - wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE); - wc_ShaUpdate(&hmac->hash.sha, - (byte*) hmac->innerHash, SHA_DIGEST_SIZE); - - wc_ShaFinal(&hmac->hash.sha, hash); - } - break; - #endif + ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad, + SHA_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash, + SHA_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, hash); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: { - ret = wc_Sha224Final(&hmac->hash.sha224, (byte*) hmac->innerHash); + ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->opad, SHA224_BLOCK_SIZE); + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad, + SHA224_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->innerHash, SHA224_DIGEST_SIZE); + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash, + SHA224_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha224Final(&hmac->hash.sha224, hash); if (ret != 0) - return ret; + break; } break; - #endif + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: - { - ret = wc_Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); + ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->opad, SHA256_BLOCK_SIZE); + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad, + SHA256_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash, + SHA256_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha256Final(&hmac->hash.sha256, hash); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: - { - ret = wc_Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash); + ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->opad, SHA384_BLOCK_SIZE); + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad, + SHA384_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->innerHash, SHA384_DIGEST_SIZE); + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash, + SHA384_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha384Final(&hmac->hash.sha384, hash); - if (ret != 0) - return ret; - } - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - { - ret = wc_Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash); + ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->opad, SHA512_BLOCK_SIZE); + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad, + SHA512_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->innerHash, SHA512_DIGEST_SIZE); + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash, + SHA512_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha512Final(&hmac->hash.sha512, hash); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - { - ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, - BLAKE2B_256); + ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->opad, BLAKE2B_BLOCKBYTES); + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->opad, + BLAKE2B_BLOCKBYTES); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->innerHash, BLAKE2B_256); + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); if (ret != 0) - return ret; - + break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - break; + ret = BAD_FUNC_ARG; + break; } - hmac->innerHashKeyed = 0; + if (ret == 0) { + hmac->innerHashKeyed = 0; + } - return 0; + return ret; } -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Hmac for use with Nitrox device */ -int wc_HmacAsyncInit(Hmac* hmac, int devId) +/* Initialize Hmac for use with async device */ +int wc_HmacInit(Hmac* hmac, void* heap, int devId) { int ret = 0; if (hmac == NULL) - return -1; - - ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, devId); - if (ret != 0) { - return ret; - } + return BAD_FUNC_ARG; -#ifdef HAVE_CAVIUM - hmac->keyLen = 0; - hmac->dataLen = 0; - hmac->type = 0; - hmac->data = NULL; /* buffered input data */ + XMEMSET(hmac, 0, sizeof(Hmac)); + hmac->heap = heap; - hmac->innerHashKeyed = 0; -#endif /* HAVE_CAVIUM */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + hmac->keyLen = 0; + #ifdef HAVE_CAVIUM + hmac->dataLen = 0; + hmac->data = NULL; /* buffered input data */ + #endif /* HAVE_CAVIUM */ - /* default to NULL heap hint or test value */ -#ifdef WOLFSSL_HEAP_TEST - hmac->heap = (void)WOLFSSL_HEAP_TEST; + ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, + hmac->heap, devId); #else - hmac->heap = NULL; -#endif /* WOLFSSL_HEAP_TEST */ + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ - return 0; + return ret; } - -/* Free Hmac from use with Nitrox device */ -void wc_HmacAsyncFree(Hmac* hmac) +/* Free Hmac from use with async device */ +void wc_HmacFree(Hmac* hmac) { if (hmac == NULL) return; - wolfAsync_DevCtxFree(&hmac->asyncDev); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC); #ifdef HAVE_CAVIUM - XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_ASYNC_TMP); + XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_HMAC); hmac->data = NULL; -#endif -} - +#endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_ASYNC_CRYPT */ - +} int wolfSSL_GetHmacMaxSize(void) { @@ -779,76 +788,73 @@ int wolfSSL_GetHmacMaxSize(void) } #ifdef HAVE_HKDF - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) + /* HMAC-KDF-Extract. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * salt The optional salt value. + * saltSz The size of the salt. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * out The pseudorandom key with the length that of the hash. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out) { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -/* 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, - const byte* info, word32 infoSz, - byte* out, word32 outSz) -{ - Hmac myHmac; -#ifdef WOLFSSL_SMALL_STACK - byte* tmp; - byte* prk; -#else - byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ - byte prk[MAX_DIGEST_SIZE]; -#endif - const byte* localSalt; /* either points to user input or tmp */ - int hashSz = wc_HmacSizeByType(type); - word32 outIdx = 0; - byte n = 0x1; - int ret; - - if (hashSz < 0) - return BAD_FUNC_ARG; + byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper */ + Hmac myHmac; + int ret; + const byte* localSalt; /* either points to user input or tmp */ + int hashSz; + + ret = wc_HmacSizeByType(type); + if (ret < 0) + return ret; -#ifdef WOLFSSL_SMALL_STACK - tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) - return MEMORY_E; + hashSz = ret; + localSalt = salt; + if (localSalt == NULL) { + XMEMSET(tmp, 0, hashSz); + localSalt = tmp; + saltSz = hashSz; + } - prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - if (prk == NULL) { - XFREE(tmp, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif + ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); + if (ret == 0) + ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); + if (ret == 0) + ret = wc_HmacFinal(&myHmac, out); - localSalt = salt; - if (localSalt == NULL) { - XMEMSET(tmp, 0, hashSz); - localSalt = tmp; - saltSz = hashSz; + return ret; } - do { - ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); - if (ret != 0) - break; - ret = wc_HmacFinal(&myHmac, prk); - } while (0); + /* HMAC-KDF-Expand. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input key. + * inKeySz The size of the input key. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, byte* out, word32 outSz) + { + byte tmp[MAX_DIGEST_SIZE]; + Hmac myHmac; + int ret = 0; + word32 outIdx = 0; + word32 hashSz = wc_HmacSizeByType(type); + byte n = 0x1; - if (ret == 0) { while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; - ret = wc_HmacSetKey(&myHmac, type, prk, hashSz); + ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); @@ -864,21 +870,47 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, if (ret != 0) break; - left = min(left, (word32)hashSz); + left = min(left, hashSz); XMEMCPY(out+outIdx, tmp, left); outIdx += hashSz; n++; } + + return ret; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(prk, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* HMAC-KDF. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * salt The optional salt value. + * saltSz The size of the salt. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz) + { + byte prk[MAX_DIGEST_SIZE]; + int hashSz = wc_HmacSizeByType(type); + int ret; - return ret; -} + if (hashSz < 0) + return BAD_FUNC_ARG; + + ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk); + if (ret != 0) + return ret; + + return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz); + } #endif /* HAVE_HKDF */ diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 714d5d4343..3b895934b3 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -1,7 +1,9 @@ # vim:ft=automake # All paths should be given relative to the root +EXTRA_DIST += src/bio.c EXTRA_DIST += wolfcrypt/src/misc.c +EXTRA_DIST += wolfcrypt/src/evp.c EXTRA_DIST += wolfcrypt/src/asm.c EXTRA_DIST += wolfcrypt/src/aes_asm.asm @@ -37,7 +39,8 @@ EXTRA_DIST += \ wolfcrypt/src/fp_sqr_comba_7.i \ wolfcrypt/src/fp_sqr_comba_8.i \ wolfcrypt/src/fp_sqr_comba_9.i \ - wolfcrypt/src/fp_sqr_comba_small_set.i + wolfcrypt/src/fp_sqr_comba_small_set.i \ + wolfcrypt/src/fe_x25519_128.i EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/ti/ti-des3.c \ @@ -56,3 +59,10 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c EXTRA_DIST += wolfcrypt/src/port/cavium/README.md endif + +if BUILD_INTEL_QA +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist_mem.c + +EXTRA_DIST += wolfcrypt/src/port/intel/README.md +endif diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 7e0c598205..c91d8331a4 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -47,6 +47,9 @@ #include +#if defined(FREESCALE_LTC_TFM) + #include +#endif #ifdef WOLFSSL_DEBUG_MATH #include #endif @@ -142,29 +145,21 @@ int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, /* init a new mp_int */ int mp_init (mp_int * a) { - int i; - /* Safeguard against passing in a null pointer */ if (a == NULL) return MP_VAL; - /* allocate memory required and clear it */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC, 0, - DYNAMIC_TYPE_BIGINT); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the digits to zero */ - for (i = 0; i < MP_PREC; i++) { - a->dp[i] = 0; - } + /* defer allocation until mp_grow */ + a->dp = NULL; /* set the used to zero, allocated digits to the default precision * and sign to positive */ a->used = 0; - a->alloc = MP_PREC; + a->alloc = 0; a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif return MP_OKAY; } @@ -186,15 +181,28 @@ void mp_clear (mp_int * a) } /* free ram */ - XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + mp_free(a); /* reset members to make debugging easier */ - a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } } +void mp_free (mp_int * a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + a->dp = NULL; + } + +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#endif +} + void mp_forcezero(mp_int * a) { if (a == NULL) @@ -206,10 +214,9 @@ void mp_forcezero(mp_int * a) ForceZero(a->dp, a->used * sizeof(mp_digit)); /* free ram */ - XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + mp_free(a); /* reset members to make debugging easier */ - a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } @@ -272,6 +279,22 @@ int mp_leading_bit (mp_int * a) return bit; } +int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b) +{ + int res = 0; + while (mp_iszero(t) == MP_NO) { +#ifndef MP_8BIT + b[x++] = (unsigned char) (t->dp[0] & 255); +#else + b[x++] = (unsigned char) (t->dp[0] | ((t->dp[1] & 0x01) << 7)); +#endif + if ((res = mp_div_2d (t, 8, t, NULL)) != MP_OKAY) { + return res; + } + res = x; + } + return res; +} /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) @@ -283,21 +306,15 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) return res; } - x = 0; - while (mp_iszero (&t) == MP_NO) { -#ifndef MP_8BIT - b[x++] = (unsigned char) (t.dp[0] & 255); -#else - b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); -#endif - if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { - mp_clear (&t); - return res; - } + x = mp_to_unsigned_bin_at_pos(0, &t, b); + if (x < 0) { + mp_clear(&t); + return x; } + bn_reverse (b, x); mp_clear (&t); - return MP_OKAY; + return res; } @@ -328,7 +345,7 @@ int mp_copy (mp_int * a, mp_int * b) } /* grow dest */ - if (b->alloc < a->used) { + if (b->alloc < a->used || b->alloc == 0) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } @@ -352,7 +369,7 @@ int mp_copy (mp_int * a, mp_int * b) } /* clear high digits */ - for (; n < b->used; n++) { + for (; n < b->used && b->dp; n++) { *tmpb++ = 0; } } @@ -371,7 +388,7 @@ int mp_grow (mp_int * a, int size) mp_digit *tmp; /* if the alloc size is smaller alloc more ram */ - if (a->alloc < size) { + if (a->alloc < size || size == 0) { /* ensure there are always at least MP_PREC digits extra on top */ size += (MP_PREC * 2) - (size % MP_PREC); @@ -381,8 +398,8 @@ int mp_grow (mp_int * a, int size) * in case the operation failed we don't want * to overwrite the dp member of a. */ - tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, 0, - DYNAMIC_TYPE_BIGINT); + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, NULL, + DYNAMIC_TYPE_BIGINT); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; @@ -467,6 +484,9 @@ void mp_zero (mp_int * a) a->sign = MP_ZPOS; a->used = 0; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif tmp = a->dp; for (n = 0; n < a->alloc; n++) { @@ -540,6 +560,7 @@ void mp_rshb (mp_int *c, int x) /* set the carry to the carry bits of the current word found above */ r = rr; } + mp_clamp(c); } @@ -781,7 +802,11 @@ int mp_lshd (mp_int * a, int b) * embedded in the normal function but that wasted a lot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { int dr; @@ -892,7 +917,11 @@ int mp_abs (mp_int * a, mp_int * b) /* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod(mp_int * a, mp_int * b, mp_int * c) +#else int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif { /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { @@ -950,7 +979,9 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } - mp_set (&D, 1); + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } top: /* 4. while u is even do */ @@ -1104,8 +1135,12 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } - mp_set (&A, 1); - mp_set (&D, 1); + if ((res = mp_set (&A, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } top: /* 4. while u is even do */ @@ -1288,8 +1323,12 @@ int mp_cmp (mp_int * a, mp_int * b) /* compare a digit */ int mp_cmp_d(mp_int * a, mp_digit b) { + /* special case for zero*/ + if (a->used == 0 && b == 0) + return MP_EQ; + /* compare based on sign */ - if (a->sign == MP_NEG) { + if ((b && a->used == 0) || a->sign == MP_NEG) { return MP_LT; } @@ -1310,11 +1349,16 @@ int mp_cmp_d(mp_int * a, mp_digit b) /* set to a digit */ -void mp_set (mp_int * a, mp_digit b) +int mp_set (mp_int * a, mp_digit b) { + int res; mp_zero (a); - a->dp[0] = (mp_digit)(b & MP_MASK); - a->used = (a->dp[0] != 0) ? 1 : 0; + res = mp_grow (a, 1); + if (res == MP_OKAY) { + a->dp[0] = (mp_digit)(b & MP_MASK); + a->used = (a->dp[0] != 0) ? 1 : 0; + } + return res; } /* chek if a bit is set */ @@ -1327,7 +1371,11 @@ int mp_is_bit_set (mp_int *a, mp_digit b) } /* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod(mp_int * a, mp_int * b, mp_int * c) +#else int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif { mp_int t; int res; @@ -1382,8 +1430,9 @@ int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) return res; } - - mp_set(&tq, 1); + if ((res = mp_set(&tq, 1)) != MP_OKAY) { + return res; + } n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || @@ -1509,31 +1558,31 @@ int mp_add (mp_int * a, mp_int * b, mp_int * c) int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; - int olduse, res, min, max; + int olduse, res, min_ab, max_ab; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits */ if (a->used > b->used) { - min = b->used; - max = a->used; + min_ab = b->used; + max_ab = a->used; x = a; } else { - min = a->used; - max = b->used; + min_ab = a->used; + max_ab = b->used; x = b; } /* init result */ - if (c->alloc < max + 1) { - if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + if (c->alloc < max_ab + 1) { + if ((res = mp_grow (c, max_ab + 1)) != MP_OKAY) { return res; } } /* get old used digit count and set new one */ olduse = c->used; - c->used = max + 1; + c->used = max_ab + 1; { mp_digit u, *tmpa, *tmpb, *tmpc; @@ -1552,7 +1601,7 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* zero the carry */ u = 0; - for (i = 0; i < min; i++) { + for (i = 0; i < min_ab; i++) { /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ *tmpc = *tmpa++ + *tmpb++ + u; @@ -1566,8 +1615,8 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* now copy higher words if any, that is in A+B * if A or B has more digits add those in */ - if (min != max) { - for (; i < max; i++) { + if (min_ab != max_ab) { + for (; i < max_ab; i++) { /* T[i] = X[i] + U */ *tmpc = x->dp[i] + u; @@ -1596,20 +1645,25 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { - int olduse, res, min, max; + int olduse, res, min_b, max_a; /* find sizes */ - min = b->used; - max = a->used; + min_b = b->used; + max_a = a->used; /* init result */ - if (c->alloc < max) { - if ((res = mp_grow (c, max)) != MP_OKAY) { + if (c->alloc < max_a) { + if ((res = mp_grow (c, max_a)) != MP_OKAY) { return res; } } + + /* sanity check on destination */ + if (c->dp == NULL) + return MP_VAL; + olduse = c->used; - c->used = max; + c->used = max_a; { mp_digit u, *tmpa, *tmpb, *tmpc; @@ -1622,7 +1676,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* set carry to zero */ u = 0; - for (i = 0; i < min; i++) { + for (i = 0; i < min_b; i++) { /* T[i] = A[i] - B[i] - U */ *tmpc = *tmpa++ - *tmpb++ - u; @@ -1638,7 +1692,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) } /* now copy higher words if any, e.g. if A has more digits than B */ - for (; i < max; i++) { + for (; i < max_a; i++) { /* T[i] = A[i] - U */ *tmpc = *tmpa++ - u; @@ -1941,7 +1995,9 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, goto LBL_RES; } } else { - mp_set(&res, 1); + if ((err = mp_set(&res, 1)) != MP_OKAY) { + goto LBL_RES; + } if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto LBL_RES; } @@ -2169,7 +2225,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } #ifdef WOLFSSL_SMALL_STACK - W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -2296,7 +2352,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) mp_clamp (x); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif /* if A >= m then A = A - m */ @@ -2647,7 +2703,11 @@ int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) /* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +#else int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif { int res; mp_int t; @@ -2732,7 +2792,11 @@ int mp_sqr (mp_int * a, mp_int * b) /* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int *a, mp_int *b, mp_int *c) +#else int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; @@ -2893,7 +2957,7 @@ int mp_init_size (mp_int * a, int size) size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, 0, + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, NULL, DYNAMIC_TYPE_BIGINT); if (a->dp == NULL) { return MP_MEM; @@ -2903,6 +2967,9 @@ int mp_init_size (mp_int * a, int size) a->used = 0; a->alloc = size; a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif /* zero the digits */ for (x = 0; x < size; x++) { @@ -2946,7 +3013,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3019,7 +3086,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) mp_clamp (b); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; @@ -3065,7 +3132,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3123,7 +3190,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_clamp (c); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; @@ -3283,7 +3350,9 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) return res; } } else { - mp_set(a, 1); + if ((res = mp_set(a, 1)) != MP_OKAY) { + return res; + } bits = 1; } @@ -3422,7 +3491,9 @@ int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_MU; } - mp_set (&res, 1); + if ((err = mp_set (&res, 1)) != MP_OKAY) { + goto LBL_MU; + } /* set initial mode and bit cnt */ mode = 0; @@ -3609,7 +3680,8 @@ int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) /* If x < 0, add b**(k+1) to it */ if (mp_cmp_d (x, 0) == MP_LT) { - mp_set (&q, 1); + if ((res = mp_set (&q, 1)) != MP_OKAY) + goto CLEANUP; if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) goto CLEANUP; if ((res = mp_add (x, &q, x)) != MP_OKAY) @@ -3722,7 +3794,7 @@ int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) pa = a->used; pb = b->used; - for (ix = 0; ix < pa; ix++) { + for (ix = 0; ix < pa && a->dp; ix++) { /* clear the carry */ u = 0; @@ -3787,7 +3859,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3795,7 +3867,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* number of output digits to produce */ pa = a->used + b->used; _W = 0; - for (ix = digs; ix < pa; ix++) { + for (ix = digs; ix < pa && a->dp; ix++) { int tx, ty, iy; mp_digit *tmpx, *tmpy; @@ -3845,32 +3917,40 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_clamp (c); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; } -/* set a 32-bit const */ +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif int mp_set_int (mp_int * a, unsigned long b) { - int x, res; + int x, res; + + /* use direct mp_set if b is less than mp_digit max */ + if (b < MP_DIGIT_MAX) { + return mp_set (a, (mp_digit)b); + } mp_zero (a); - /* set four bits at a time */ - for (x = 0; x < 8; x++) { - /* shift the number up four bits */ - if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + /* shift the number up chunk bits */ + if ((res = mp_mul_2d (a, MP_SET_CHUNK_BITS, a)) != MP_OKAY) { return res; } - /* OR in the top four bits of the source */ - a->dp[0] |= (b >> 28) & 15; + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); - /* shift the source up to the next four bits */ - b <<= 4; + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; /* ensure that digits are not clamped off */ a->used += 1; @@ -4083,7 +4163,7 @@ static const int lnz[16] = { int mp_cnt_lsb(mp_int *a) { int x; - mp_digit q, qq; + mp_digit q = 0, qq; /* easy out */ if (mp_iszero(a) == MP_YES) { @@ -4092,7 +4172,8 @@ int mp_cnt_lsb(mp_int *a) /* scan lower digits until non-zero */ for (x = 0; x < a->used && a->dp[x] == 0; x++) {} - q = a->dp[x]; + if (a->dp) + q = a->dp[x]; x *= DIGIT_BIT; /* now scan this digit until a 1 is found */ @@ -4172,12 +4253,18 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) /* no easy answer [c'est la vie]. Just division */ if (c != NULL) { if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { - return res; + return res; } q.used = a->used; q.sign = a->sign; } + else { + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + } + w = 0; for (ix = a->used - 1; ix >= 0; ix--) { @@ -4200,8 +4287,8 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); - mp_clear(&q); } + mp_clear(&q); return res; } @@ -4476,7 +4563,9 @@ int mp_prime_is_prime (mp_int * a, int t, int *result) for (ix = 0; ix < t; ix++) { /* set the prime */ - mp_set (&b, ltm_prime_tab[ix]); + if ((err = mp_set (&b, ltm_prime_tab[ix])) != MP_OKAY) { + goto LBL_B; + } if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { goto LBL_B; diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index 9a4fac5f43..1a7b6ff390 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -38,14 +38,35 @@ WOLFSSL_API int wolfSSL_Debugging_ON(void); WOLFSSL_API void wolfSSL_Debugging_OFF(void); #ifdef __cplusplus - } + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */ + +/* accessing any node from the queue should be wrapped in a lock of + * debug_mutex */ +static void* wc_error_heap; +struct wc_error_queue { + void* heap; /* the heap hint used with nodes creation */ + struct wc_error_queue* next; + struct wc_error_queue* prev; + char error[WOLFSSL_MAX_ERROR_SZ]; + char file[WOLFSSL_MAX_ERROR_SZ]; + int value; + int line; +}; +volatile struct wc_error_queue* wc_errors; +static struct wc_error_queue* wc_last_node; +/* pointer to last node in queue to make insertion O(1) */ #endif -#ifdef DEBUG_WOLFSSL + +#if defined(DEBUG_WOLFSSL) /* Set these to default values initially. */ -static wolfSSL_Logging_cb log_function = 0; +static wolfSSL_Logging_cb log_function = NULL; static int loggingEnabled = 0; #endif /* DEBUG_WOLFSSL */ @@ -140,7 +161,7 @@ void WOLFSSL_MSG(const char* msg) } -void WOLFSSL_BUFFER(byte* buffer, word32 length) +void WOLFSSL_BUFFER(const byte* buffer, word32 length) { #define LINE_LEN 16 @@ -196,15 +217,319 @@ void WOLFSSL_LEAVE(const char* msg, int ret) wolfssl_log(LEAVE_LOG , buffer); } } +#endif /* DEBUG_WOLFSSL */ - +/* + * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is + * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function + * name where WOLFSSL_ERROR is called at. + */ +#if (defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY) + #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) +void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line, + const char* file, void* usrCtx) + #else void WOLFSSL_ERROR(int error) + #endif { - if (loggingEnabled) { + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_NGINX) + if (loggingEnabled && error != WC_PENDING_E) + #endif + { char buffer[80]; - sprintf(buffer, "wolfSSL error occurred, error = %d", error); + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + (void)usrCtx; /* a user ctx for future flexibility */ + (void)func; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + sprintf(buffer, "wolfSSL error occurred, error = %d", error); + } + else { + if (error < 0) error = error - (2*error); /*get absolute value*/ + sprintf(buffer, "wolfSSL error occurred, error = %d line:%d file:%s", + error, line, file); + if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) { + WOLFSSL_MSG("Error creating logging node"); + /* with void function there is no return here, continue on + * to unlock mutex and log what buffer was created. */ + } + + wc_UnLockMutex(&debug_mutex); + } + #else + sprintf(buffer, "wolfSSL error occurred, error = %d", error); + #endif + #ifdef DEBUG_WOLFSSL wolfssl_log(ERROR_LOG , buffer); + #endif } } -#endif /* DEBUG_WOLFSSL */ +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +/* Internal function that is called by wolfCrypt_Init() */ +int wc_LoggingInit(void) +{ + if (wc_InitMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex"); + return BAD_MUTEX_E; + } + wc_errors = NULL; + wc_last_node = NULL; + + return 0; +} + + +/* internal function that is called by wolfCrypt_Cleanup */ +int wc_LoggingCleanup(void) +{ + /* clear logging entries */ + wc_ClearErrorNodes(); + + /* free mutex */ + if (wc_FreeMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Mutex free"); + return BAD_MUTEX_E; + } + return 0; +} + + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +/* peek at an error node + * + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + * file : pointer to internal file string + * reason : pointer to internal error reason + * line : line number that error happened at + * + * Returns a negative value in error case, on success returns the nodes error + * value which is positve (absolute value) + */ +int wc_PeekErrorNode(int idx, const char **file, const char **reason, + int *line) +{ + struct wc_error_queue* err; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + if (idx < 0) { + err = wc_last_node; + if (err == NULL) { + WOLFSSL_MSG("No Errors in queue"); + wc_UnLockMutex(&debug_mutex); + return BAD_STATE_E; + } + } + else { + int i; + + err = (struct wc_error_queue*)wc_errors; + for (i = 0; i < idx; i++) { + if (err == NULL) { + WOLFSSL_MSG("Error node not found. Bad index?"); + wc_UnLockMutex(&debug_mutex); + return BAD_FUNC_ARG; + } + err = err->next; + } + } + + if (file != NULL) { + *file = err->file; + } + + if (reason != NULL) { + *reason = err->error; + } + + if (line != NULL) { + *line = err->line; + } + + wc_UnLockMutex(&debug_mutex); + + return err->value; +} + + +/* create new error node and add it to the queue + * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal + * function. debug_mutex should be locked before a call to this function. */ +int wc_AddErrorNode(int error, int line, char* buf, char* file) +{ + + struct wc_error_queue* err; + + err = (struct wc_error_queue*)XMALLOC( + sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG); + if (err == NULL) { + WOLFSSL_MSG("Unable to create error node for log"); + return MEMORY_E; + } + else { + int sz; + + XMEMSET(err, 0, sizeof(struct wc_error_queue)); + err->heap = wc_error_heap; + sz = (int)XSTRLEN(buf); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->error, buf, sz); + } + + sz = (int)XSTRLEN(file); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->file, file, sz); + } + + err->value = error; + err->line = line; + + /* make sure is terminated */ + err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + err->file[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + + + /* since is queue place new node at last of the list */ + if (wc_last_node == NULL) { + /* case of first node added to queue */ + if (wc_errors != NULL) { + /* check for unexpected case before over writing wc_errors */ + WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n"); + } + else { + wc_errors = err; + wc_last_node = err; + } + } + else { + wc_last_node->next = err; + err->prev = wc_last_node; + wc_last_node = err; + } + } + + return 0; +} + +/* Removes the error node at the specified index. + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + */ +void wc_RemoveErrorNode(int idx) +{ + struct wc_error_queue* current; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + if (idx == -1) + current = wc_last_node; + else { + current = (struct wc_error_queue*)wc_errors; + for (; current != NULL && idx > 0; idx--) + current = current->next; + } + if (current != NULL) { + if (current->prev != NULL) + current->prev->next = current->next; + if (wc_last_node == current) + wc_last_node = current->prev; + if (wc_errors == current) + wc_errors = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + } + + wc_UnLockMutex(&debug_mutex); +} + +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */ + +/* Clears out the list of error nodes. + */ +void wc_ClearErrorNodes(void) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + /* free all nodes from error queue */ + { + struct wc_error_queue* current; + struct wc_error_queue* next; + + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + } + + wc_errors = NULL; + wc_last_node = NULL; + wc_UnLockMutex(&debug_mutex); +} + +int wc_SetLoggingHeap(void* h) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + wc_error_heap = h; + wc_UnLockMutex(&debug_mutex); + return 0; +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* empties out the error queue into the file */ +void wc_ERR_print_errors_fp(FILE* fp) +{ + WOLFSSL_ENTER("wc_ERR_print_errors_fp"); + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + } + else { + /* free all nodes from error queue and print them to file */ + { + struct wc_error_queue* current; + struct wc_error_queue* next; + + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + fprintf(fp, "%s\n", current->error); + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + + /* set global pointers to match having been freed */ + wc_errors = NULL; + wc_last_node = NULL; + } + + wc_UnLockMutex(&debug_mutex); + } +} +#endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */ + +#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */ + diff --git a/wolfcrypt/src/md4.c b/wolfcrypt/src/md4.c index 3b3ae9555b..bac4240657 100644 --- a/wolfcrypt/src/md4.c +++ b/wolfcrypt/src/md4.c @@ -37,17 +37,6 @@ #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - void wc_InitMd4(Md4* md4) { md4->digest[0] = 0x67452301L; diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c old mode 100644 new mode 100755 index fdde46ff76..aab3117973 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -31,13 +31,8 @@ #if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ -#else -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw -#endif +#else #include #include @@ -49,22 +44,21 @@ #include #endif -#ifdef FREESCALE_MMCAU_SHA - #include "fsl_mmcau.h" - #define XTRANSFORM(S,B) Transform((S), (B)) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif - +/* Hardware Acceleration */ #if defined(STM32F2_HASH) || defined(STM32F4_HASH) /* * STM32F2/F4 hardware MD5 support through the standard peripheral * library. (See note in README). */ - void wc_InitMd5(Md5* md5) + #define HAVE_MD5_CUST_API + + int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { + (void)heap; + (void)devId; + /* STM32 struct notes: * md5->buffer = first 4 bytes used to hold partial block if needed * md5->buffLen = num bytes currently stored in md5->buffer @@ -85,9 +79,11 @@ /* reset HASH processor */ HASH->CR |= HASH_CR_INIT; + + return 0; } - void wc_Md5Update(Md5* md5, const byte* data, word32 len) + int wc_Md5Update(Md5* md5, const byte* data, word32 len) { word32 i = 0; word32 fill = 0; @@ -110,7 +106,7 @@ /* append partial to existing stored block */ XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); md5->buffLen += len; - return; + return 0; } } @@ -131,9 +127,11 @@ /* keep track of total data length thus far */ md5->loLen += (len - md5->buffLen); + + return 0; } - void wc_Md5Final(Md5* md5, byte* hash) + int wc_Md5Final(Md5* md5, byte* hash) { __IO uint16_t nbvalidbitsdata = 0; @@ -165,23 +163,148 @@ XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - wc_InitMd5(md5); /* reset state */ + return wc_InitMd5(md5); /* reset state */ } -#else /* Begin wolfCrypt software implementation */ +#elif defined(FREESCALE_MMCAU_SHA) + #include "cau_api.h" + #define XTRANSFORM(S,B) Transform((S), (B)) + + static int Transform(Md5* md5, byte* data) + { + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + MMCAU_MD5_HashN(data, 1, (uint32_t*)md5->digest); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_PIC32MZ_HASH) + #define wc_InitMd5 wc_InitMd5_sw + #define wc_Md5Update wc_Md5Update_sw + #define wc_Md5Final wc_Md5Final_sw + + #define NEED_SOFT_MD5 + +#else + #define NEED_SOFT_MD5 + +#endif /* End Hardware Acceleration */ + + +#ifdef NEED_SOFT_MD5 + + #define XTRANSFORM(S,B) Transform((S)) + + #define F1(x, y, z) (z ^ (x & (y ^ z))) + #define F2(x, y, z) F1(z, x, y) + #define F3(x, y, z) (x ^ y ^ z) + #define F4(x, y, z) (y ^ (x | ~z)) -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN + #define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x - static INLINE word32 min(word32 a, word32 b) + static int Transform(Md5* md5) { - return a > b ? b : a; + /* Copy context->state[] to working vars */ + word32 a = md5->digest[0]; + word32 b = md5->digest[1]; + word32 c = md5->digest[2]; + word32 d = md5->digest[3]; + + MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); + + /* Add the working vars back into digest state[] */ + md5->digest[0] += a; + md5->digest[1] += b; + md5->digest[2] += c; + md5->digest[3] += d; + + return 0; } +#endif /* NEED_SOFT_MD5 */ -#endif /* WOLFSSL_HAVE_MIN */ -void wc_InitMd5(Md5* md5) +#ifndef HAVE_MD5_CUST_API +static INLINE void AddMd5Length(Md5* md5, word32 len) { + word32 tmp = md5->loLen; + if ((md5->loLen += len) < tmp) { + md5->hiLen++; /* carry low to high */ + } +} + +static int _InitMd5(Md5* md5) +{ + int ret = 0; + md5->digest[0] = 0x67452301L; md5->digest[1] = 0xefcdab89L; md5->digest[2] = 0x98badcfeL; @@ -190,128 +313,55 @@ void wc_InitMd5(Md5* md5) md5->buffLen = 0; md5->loLen = 0; md5->hiLen = 0; -} -#ifdef FREESCALE_MMCAU_SHA -static int Transform(Md5* md5, byte* data) -{ - int ret = wolfSSL_CryptHwMutexLock(); - if(ret == 0) { - MMCAU_MD5_HashN(data, 1, (uint32_t*)(md5->digest)); - wolfSSL_CryptHwMutexUnLock(); - } return ret; } -#endif /* FREESCALE_MMCAU_SHA */ - -#ifndef FREESCALE_MMCAU_SHA -static void Transform(Md5* md5) +int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -#define MD5STEP(f, w, x, y, z, data, s) \ - w = rotlFixed(w + f(x, y, z) + data, s) + x - - /* Copy context->state[] to working vars */ - word32 a = md5->digest[0]; - word32 b = md5->digest[1]; - word32 c = md5->digest[2]; - word32 d = md5->digest[3]; - - MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); - - /* Add the working vars back into digest state[] */ - md5->digest[0] += a; - md5->digest[1] += b; - md5->digest[2] += c; - md5->digest[3] += d; -} + int ret = 0; -#endif /* End Software implementation */ + if (md5 == NULL) + return BAD_FUNC_ARG; + md5->heap = heap; -static INLINE void AddLength(Md5* md5, word32 len) -{ - word32 tmp = md5->loLen; - if ( (md5->loLen += len) < tmp) - md5->hiLen++; /* carry low to high */ -} + ret = _InitMd5(md5); + if (ret != 0) + return ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5, + md5->heap, devId); +#else + (void)devId; +#endif + return ret; +} -void wc_Md5Update(Md5* md5, const byte* data, word32 len) +int wc_Md5Update(Md5* md5, const byte* data, word32 len) { + int ret = 0; + byte* local; + + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + /* do block size increments */ - byte* local = (byte*)md5->buffer; + local = (byte*)md5->buffer; + + /* check that internal buffLen is valid */ + if (md5->buffLen >= MD5_BLOCK_SIZE) + return BUFFER_E; while (len) { word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); @@ -322,23 +372,36 @@ void wc_Md5Update(Md5* md5, const byte* data, word32 len) len -= add; if (md5->buffLen == MD5_BLOCK_SIZE) { - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif XTRANSFORM(md5, local); - AddLength(md5, MD5_BLOCK_SIZE); + AddMd5Length(md5, MD5_BLOCK_SIZE); md5->buffLen = 0; } } + return ret; } - -void wc_Md5Final(Md5* md5, byte* hash) +int wc_Md5Final(Md5* md5, byte* hash) { - byte* local = (byte*)md5->buffer; + byte* local; - AddLength(md5, md5->buffLen); /* before adding pads */ + if (md5 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, hash, NULL, MD5_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + local = (byte*)md5->buffer; + + AddMd5Length(md5, md5->buffLen); /* before adding pads */ local[md5->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ @@ -346,9 +409,9 @@ void wc_Md5Final(Md5* md5, byte* hash) XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif XTRANSFORM(md5, local); md5->buffLen = 0; } @@ -360,50 +423,72 @@ void wc_Md5Final(Md5* md5, byte* hash) md5->loLen = md5->loLen << 3; /* store lengths */ - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif +#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); +#endif /* ! length ordering dependent on digest endian type ! */ XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); XTRANSFORM(md5, local); - #ifdef BIG_ENDIAN_ORDER - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - #endif +#ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); +#endif XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - wc_InitMd5(md5); /* reset state */ + return _InitMd5(md5); /* reset state */ } +#endif /* !HAVE_MD5_CUST_API */ -#endif /* End wolfCrypt software implementation */ - -int wc_Md5Hash(const byte* data, word32 len, byte* hash) +int wc_InitMd5(Md5* md5) { -#ifdef WOLFSSL_SMALL_STACK - Md5* md5; -#else - Md5 md5[1]; -#endif + if (md5 == NULL) { + return BAD_FUNC_ARG; + } + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); +} -#ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); +void wc_Md5Free(Md5* md5) +{ if (md5 == NULL) - return MEMORY_E; -#endif + return; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +int wc_Md5GetHash(Md5* md5, byte* hash) +{ + int ret; + Md5 tmpMd5; + + if (md5 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Md5Copy(md5, &tmpMd5); + if (ret == 0) { + ret = wc_Md5Final(&tmpMd5, hash); + } + + return ret; +} + +int wc_Md5Copy(Md5* src, Md5* dst) +{ + int ret = 0; - wc_InitMd5(md5); - wc_Md5Update(md5, data, len); - wc_Md5Final(md5, hash); + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XMEMCPY(dst, src, sizeof(Md5)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); #endif - return 0; + return ret; } #endif /* WOLFSSL_TI_HASH */ - #endif /* NO_MD5 */ diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 470b09cf9d..927b0c4ad6 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -74,6 +74,16 @@ int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf, return res; } +int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, + wolfSSL_Free_cb* ff, + wolfSSL_Realloc_cb* rf) +{ + if (mf) *mf = malloc_function; + if (ff) *ff = free_function; + if (rf) *rf = realloc_function; + return 0; +} + #ifndef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line) @@ -389,10 +399,19 @@ int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) /* creating only IO buffers from memory passed in, max TLS is 16k */ if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { - ava = sz % (memSz + padSz + WOLFMEM_IO_SZ); + if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { + return 0; /* not enough room for even one bucket */ + } + + ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); } else { int i, k; + + if (ava < (bucketSz[0] + padSz + memSz)) { + return 0; /* not enough room for even one bucket */ + } + while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { /* start at largest and move to smaller buckets */ for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { @@ -530,7 +549,9 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } /* case of using fixed IO buffers */ - if (mem->flag & WOLFMEM_IO_POOL_FIXED) { + if (mem->flag & WOLFMEM_IO_POOL_FIXED && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { if (type == DYNAMIC_TYPE_OUT_BUFFER) { pt = hint->outBuf; } @@ -538,25 +559,26 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) pt = hint->inBuf; } } - - /* check if using IO pool flag */ - if (mem->flag & WOLFMEM_IO_POOL && pt == NULL && + else { + /* check if using IO pool flag */ + if (mem->flag & WOLFMEM_IO_POOL && (type == DYNAMIC_TYPE_OUT_BUFFER || type == DYNAMIC_TYPE_IN_BUFFER)) { - if (mem->io != NULL) { - pt = mem->io; - mem->io = pt->next; + if (mem->io != NULL) { + pt = mem->io; + mem->io = pt->next; + } } - } - /* general static memory */ - if (pt == NULL) { - for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { - if ((word32)size < mem->sizeList[i]) { - if (mem->ava[i] != NULL) { - pt = mem->ava[i]; - mem->ava[i] = pt->next; - break; + /* general static memory */ + if (pt == NULL) { + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((word32)size < mem->sizeList[i]) { + if (mem->ava[i] != NULL) { + pt = mem->ava[i]; + mem->ava[i] = pt->next; + break; + } } } } @@ -663,7 +685,7 @@ void wolfSSL_Free(void *ptr, void* heap, int type) /* fixed IO pools are free'd at the end of SSL lifetime using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */ } - else if (mem->flag & WOLFMEM_IO_POOL && + else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ && (type == DYNAMIC_TYPE_OUT_BUFFER || type == DYNAMIC_TYPE_IN_BUFFER)) { pt->next = mem->io; diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index cbd63c9599..08ba55e862 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -31,7 +31,7 @@ #include -/* inlining these functions is a huge speed increase and a small size decrease, +/* inlining these functions is a huge speed increase and a small size decrease, because the functions are smaller than function call setup/cleanup, e.g., md5 benchmark is twice as fast with inline. If you don't want it, then define NO_INLINE and compile this file into wolfssl, otherwise it's used as @@ -50,6 +50,12 @@ #else + +#if defined(__ICCARM__) + #include +#endif + + #ifdef INTEL_INTRINSICS #include /* get intrinsic definitions */ @@ -73,7 +79,7 @@ STATIC INLINE word32 rotlFixed(word32 x, word32 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); - } + } STATIC INLINE word32 rotrFixed(word32 x, word32 y) @@ -122,7 +128,7 @@ STATIC INLINE void ByteReverseWords(word32* out, const word32* in, STATIC INLINE word64 rotlFixed64(word64 x, word64 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); -} +} STATIC INLINE word64 rotrFixed64(word64 x, word64 y) @@ -133,8 +139,8 @@ STATIC INLINE word64 rotrFixed64(word64 x, word64 y) STATIC INLINE word64 ByteReverseWord64(word64 value) { -#ifdef WOLFCRYPT_SLOW_WORD64 - return (word64)(ByteReverseWord32((word32)value)) << 32 | +#if defined(WOLFCRYPT_SLOW_WORD64) + return (word64)(ByteReverseWord32((word32)value)) << 32 | ByteReverseWord32((word32)(value>>32)); #else value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | @@ -210,8 +216,31 @@ STATIC INLINE int ConstantCompare(const byte* a, const byte* b, int length) return compareSum; } -#undef STATIC +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ + #define min min + #endif + STATIC INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#endif /* !WOLFSSL_HAVE_MIN */ + +#ifndef WOLFSSL_HAVE_MAX + #define WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + STATIC INLINE word32 max(word32 a, word32 b) + { + return a > b ? a : b; + } +#endif /* !WOLFSSL_HAVE_MAX */ + + +#undef STATIC #endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */ diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 9e7453f11c..b96d2a6367 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -200,7 +200,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, freeSafe(safe, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(input, &localIdx, &size, maxIdx)) < 0) { + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { freeSafe(safe, pkcs12->heap); return ret; } @@ -218,7 +218,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, freeSafe(safe, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(input, &localIdx, &size, maxIdx)) < 0) { + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { freeSafe(safe, pkcs12->heap); return ret; } @@ -367,7 +367,7 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, return ASN_PARSE_E; } - if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); return ret; } @@ -398,7 +398,7 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, return ASN_PARSE_E; } - if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); return ret; @@ -527,15 +527,19 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, } /* now that key has been created use it to get HMAC hash on data */ - if ((ret = wc_HmacSetKey(&hmac, typeH, key, kLen)) != 0) { + if ((ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID)) != 0) { return ret; } - if ((ret = wc_HmacUpdate(&hmac, data, dataSz)) != 0) { + ret = wc_HmacSetKey(&hmac, typeH, key, kLen); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, data, dataSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + wc_HmacFree(&hmac); + + if (ret != 0) return ret; - } - if ((ret = wc_HmacFinal(&hmac, digest)) != 0) { - return ret; - } + #ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; @@ -709,6 +713,10 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } } + if (pkcs12->safe == NULL) { + WOLFSSL_MSG("No PKCS12 safes to parse"); + return BAD_FUNC_ARG; + } /* Decode content infos */ ci = pkcs12->safe->CI; @@ -800,7 +808,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, freeCertList(certList, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { freeBuffers(*pkey, buf, pkcs12->heap); freeCertList(certList, pkcs12->heap); return ret; @@ -851,7 +859,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, freeCertList(certList, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { freeBuffers(*pkey, buf, pkcs12->heap); freeCertList(certList, pkcs12->heap); return ASN_PARSE_E; @@ -987,7 +995,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, return ASN_PARSE_E; } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) - < 0) { + <= 0) { freeBuffers(*pkey, buf, pkcs12->heap); freeCertList(certList, pkcs12->heap); return ret; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index d5eb9d0224..428e55b0f0 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -31,6 +31,13 @@ #include #include #include +#include +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif #ifdef NO_INLINE #include #else @@ -38,16 +45,6 @@ #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - /* direction for processing, encoding or decoding */ typedef enum { @@ -55,6 +52,9 @@ typedef enum { WC_PKCS7_DECODE } pkcs7Direction; +#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) + /* placed ASN.1 contentType OID into *output, return idx on success, * 0 upon failure */ @@ -96,7 +96,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output) typeSz = sizeof(signedData); typeName = signedData; break; - + case ENVELOPED_DATA: typeSz = sizeof(envelopedData); typeName = envelopedData; @@ -350,9 +350,10 @@ typedef struct EncodedAttrib { typedef struct ESD { - Sha sha; - byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ - byte contentAttribsDigest[SHA_DIGEST_SIZE]; + wc_HashAlg hash; + enum wc_HashType hashType; + byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; byte encContentDigest[512]; byte outerSeq[MAX_SEQ_SZ]; @@ -438,6 +439,435 @@ static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 idx; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* privKey; +#else + RsaKey stack_privKey; + RsaKey* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey(privKey, pkcs7->heap); + + if (ret == 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + } + + wc_FreeRsaKey(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 outSz, idx; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* privKey; +#else + ecc_key stack_privKey; + ecc_key* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_init_ex(privKey, pkcs7->heap, INVALID_DEVID); + + if (ret == 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + outSz = sizeof(esd->encContentDigest); + ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, + &outSz, pkcs7->rng, privKey); + if (ret == 0) + ret = (int)outSz; + } + + wc_ecc_free(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* builds up SignedData signed attributes, including default ones. + * + * pkcs7 - pointer to initialized PKCS7 structure + * esd - pointer to initialized ESD structure, used for output + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, + byte* contentTypeOid, word32 contentTypeOidSz, + byte* contentType, word32 contentTypeSz, + byte* messageDigestOid, word32 messageDigestOidSz) +{ + int hashSz; + + PKCS7Attrib cannedAttribs[2]; + word32 cannedAttribsCount; + + if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || + contentType == NULL || messageDigestOid == NULL) + return BAD_FUNC_ARG; + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + + cannedAttribs[0].oid = contentTypeOid; + cannedAttribs[0].oidSz = contentTypeOidSz; + cannedAttribs[0].value = contentType; + cannedAttribs[0].valueSz = contentTypeSz; + cannedAttribs[1].oid = messageDigestOid; + cannedAttribs[1].oidSz = messageDigestOidSz; + cannedAttribs[1].value = esd->contentDigest; + cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ + + esd->signedAttribsCount += cannedAttribsCount; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, + cannedAttribs, cannedAttribsCount); + + esd->signedAttribsCount += pkcs7->signedAttribsSz; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + + return 0; +} + + +/* gets correct encryption algo ID for SignedData, either RSAk or + * CTC_wECDSA, from pkcs7->publicKeyOID. + * + * pkcs7 - pointer to PKCS7 structure + * digEncAlgoId - [OUT] output int to store correct algo ID in + * digEncAlgoType - [OUT] output for algo ID type + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, + int* digEncAlgoType) +{ + int algoId = 0; + int algoType = 0; + + if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->publicKeyOID == RSAk) { + + algoId = pkcs7->encryptOID; + algoType = oidKeyType; + + } else if (pkcs7->publicKeyOID == ECDSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + case SHAh: + algoId = CTC_SHAwECDSA; + break; + + case SHA224h: + algoId = CTC_SHA224wECDSA; + break; + + case SHA256h: + algoId = CTC_SHA256wECDSA; + break; + + case SHA384h: + algoId = CTC_SHA384wECDSA; + break; + + case SHA512h: + algoId = CTC_SHA512wECDSA; + break; + } + } + + if (algoId == 0) { + WOLFSSL_MSG("Invalid signature algorithm type"); + return BAD_FUNC_ARG; + } + + *digEncAlgoId = algoId; + *digEncAlgoType = algoType; + + return 0; +} + + +/* build SignedData DigestInfo for use with PKCS#7/RSA + * + * pkcs7 - pointer to initialized PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttrbsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * digestInfo - [OUT] output array for DigestInfo + * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, + word32 flatSignedAttribsSz, ESD* esd, + byte* digestInfo, word32* digestInfoSz) +{ + int ret, hashSz, digIdx = 0; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte attribSet[MAX_SET_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; + word32 attribSetSz; + + if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || + digestInfoSz == NULL) { + return BAD_FUNC_ARG; + } + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + if (pkcs7->signedAttribsSz != 0) { + + if (flatSignedAttribs == NULL) + return BAD_FUNC_ARG; + + attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + attribSet, attribSetSz); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + flatSignedAttribs, flatSignedAttribsSz); + if (ret < 0) + return ret; + + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentAttribsDigest); + if (ret < 0) + return ret; + + } else { + /* when no attrs, digest is contentDigest without tag and length */ + XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); + } + + /* set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { + return BUFFER_E; + } + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); + digIdx += hashSz; + + *digestInfoSz = digIdx; + + return 0; +} + + +/* build SignedData signature over DigestInfo or content digest + * + * pkcs7 - pointer to initizlied PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttribsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * + * returns length of signature on success, negative on error */ +static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, + byte* flatSignedAttribs, + word32 flatSignedAttribsSz, + ESD* esd) +{ + int ret; +#ifdef HAVE_ECC + int hashSz; +#endif + word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(digestInfoSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + return MEMORY_E; + } +#endif + + ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd, digestInfo, + &digestInfoSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* sign digestInfo */ + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + /* CMS with ECDSA does not sign DigestInfo structure + * like PKCS#7 with RSA does */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } + + ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, + hashSz, esd); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) { + esd->encContentDigestSz = (word32)ret; + } + + return ret; +} + + +/* sets the wc_HashType in ESD struct based on pkcs7->hashOID + * + * pkcs7 - pointer to initialized PKCS7 struct + * type - [OUT] pointer to wc_HashType for output + * + * returns hash digest size on success, negative on error */ +static int wc_PKCS7_SetHashType(PKCS7* pkcs7, enum wc_HashType* type) +{ + if (pkcs7 == NULL || type == NULL) + return BAD_FUNC_ARG; + + switch (pkcs7->hashOID) { + +#ifndef NO_SHA + case SHAh: + *type = WC_HASH_TYPE_SHA; + break; +#endif +#ifdef WOLFSSL_SHA224 + case SHA224h: + *type = WC_HASH_TYPE_SHA224; + break; +#endif +#ifndef NO_SHA256 + case SHA256h: + *type = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + *type = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + *type = WC_HASH_TYPE_SHA512; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return wc_HashGetDigestSize(*type); +} + + /* build PKCS#7 signedData content type */ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -448,6 +878,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; + byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + byte contentType[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01 }; + byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + #ifdef WOLFSSL_SMALL_STACK ESD* esd = NULL; #else @@ -458,6 +898,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) word32 signerInfoSz = 0; word32 totalSz = 0; int idx = 0, ret = 0; + int digEncAlgoId, digEncAlgoType, hashSz; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; word32 innerOidSz = sizeof(innerOid); @@ -477,7 +918,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif XMEMSET(esd, 0, sizeof(ESD)); - ret = wc_InitSha(&esd->sha); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &esd->hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + ret = wc_HashInit(&esd->hash, esd->hashType); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -487,10 +937,24 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7->contentSz != 0) { - wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz); + ret = wc_HashUpdate(&esd->hash, esd->hashType, + pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } esd->contentDigest[0] = ASN_OCTET_STRING; - esd->contentDigest[1] = SHA_DIGEST_SIZE; - wc_ShaFinal(&esd->sha, &esd->contentDigest[2]); + esd->contentDigest[1] = hashSz; + ret = wc_HashFinal(&esd->hash, esd->hashType, + &esd->contentDigest[2]); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } } esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); @@ -512,295 +976,566 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, oidHashType, 0); signerInfoSz += esd->signerDigAlgoIdSz; - esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId, - oidKeyType, 0); + + /* set signatureAlgorithm */ + ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, + &digEncAlgoType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, + digEncAlgoType, 0); signerInfoSz += esd->digEncAlgoIdSz; if (pkcs7->signedAttribsSz != 0) { - byte contentTypeOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, - 0x09, 0x03 }; - byte contentType[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01 }; - byte messageDigestOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x04 }; - - PKCS7Attrib cannedAttribs[2] ; - - word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); - cannedAttribs[0].oid = contentTypeOid ; - cannedAttribs[0].oidSz = sizeof(contentTypeOid) ; - cannedAttribs[0].value = contentType ; - cannedAttribs[0].valueSz = sizeof(contentType) ; - cannedAttribs[1].oid = messageDigestOid ; - cannedAttribs[1].oidSz = sizeof(messageDigestOid) ; - cannedAttribs[1].value = esd->contentDigest ; - cannedAttribs[1].valueSz = sizeof(esd->contentDigest) ; - - esd->signedAttribsCount += cannedAttribsCount; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, - cannedAttribs, cannedAttribsCount); - - esd->signedAttribsCount += pkcs7->signedAttribsSz; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, - pkcs7->signedAttribs, pkcs7->signedAttribsSz); + + /* build up signed attributes */ + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, + contentTypeOid, sizeof(contentTypeOid), + contentType, sizeof(contentType), + messageDigestOid, sizeof(messageDigestOid)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS); flatSignedAttribsSz = esd->signedAttribsSz; if (flatSignedAttribs == NULL) { #ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + + FlattenAttributes(flatSignedAttribs, + esd->signedAttribs, esd->signedAttribsCount); + esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, + esd->signedAttribSet); + } + + /* Calculate the final hash and encrypt it. */ + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; + + esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, + esd->signerDigest); + signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; + + esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); + signerInfoSz += esd->signerInfoSeqSz; + esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); + signerInfoSz += esd->signerInfoSetSz; + + esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, + esd->certsSet); + + esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, + oidHashType, 0); + esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet); + + + esd->versionSz = SetMyVersion(1, esd->version, 0); + + totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + + esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz + + esd->innerOctetsSz + esd->innerContSeqSz + + innerOidSz + pkcs7->contentSz + + signerInfoSz; + esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq); + totalSz += esd->innerSeqSz; + esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent); + totalSz += esd->outerContentSz + outerOidSz; + esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq); + totalSz += esd->outerSeqSz; + + if (outputSz < totalSz) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + idx = 0; + XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); + idx += esd->outerSeqSz; + XMEMCPY(output + idx, outerOid, outerOidSz); + idx += outerOidSz; + XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); + idx += esd->outerContentSz; + XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); + idx += esd->innerSeqSz; + XMEMCPY(output + idx, esd->version, esd->versionSz); + idx += esd->versionSz; + XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz); + idx += esd->digAlgoIdSetSz; + XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz); + idx += esd->singleDigAlgoIdSz; + XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); + idx += esd->contentInfoSeqSz; + XMEMCPY(output + idx, innerOid, innerOidSz); + idx += innerOidSz; + XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); + idx += esd->innerContSeqSz; + XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); + idx += esd->innerOctetsSz; + XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); + idx += pkcs7->contentSz; + XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz); + idx += esd->certsSetSz; + XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz); + idx += pkcs7->singleCertSz; + XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz); + idx += esd->signerInfoSetSz; + XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); + idx += esd->signerInfoSeqSz; + XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz); + idx += esd->signerVersionSz; + XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); + idx += esd->issuerSnSeqSz; + XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz); + idx += esd->issuerNameSz; + XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz); + idx += pkcs7->issuerSz; + XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz); + idx += esd->issuerSnSz; + XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); + idx += esd->signerDigAlgoIdSz; + + /* SignerInfo:Attributes */ + if (flatSignedAttribsSz > 0) { + XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); + idx += esd->signedAttribSetSz; + XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); + idx += flatSignedAttribsSz; + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + } + + XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); + idx += esd->digEncAlgoIdSz; + XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz); + idx += esd->signerDigestSz; + XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz); + idx += esd->encContentDigestSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + + +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0; + word32 scratch = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey stack_key; + RsaKey* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_InitRsaKey(key, pkcs7->heap); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); + + wc_FreeRsaKey(key); + + if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0; + int res = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + ecc_key* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + ecc_key stack_key; + ecc_key* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_ecc_init_ex(key, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_ecc_import_x963(pkcs7->publicKey, pkcs7->publicKeySz, key) < 0) { + WOLFSSL_MSG("ASN ECDSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + + wc_ecc_free(key); + + if (ret == 0 && res != 1) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* build SignedData digest, both in PKCS#7 DigestInfo format and + * as plain digest for CMS. + * + * pkcs7 - pointer to initialized PKCS7 struct + * signedAttrib - signed attributes + * signedAttribSz - size of signedAttrib, octets + * pkcs7Digest - [OUT] PKCS#7 DigestInfo + * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest + * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest + * plainDigestSz - [OUT] size of digest at plainDigest + * + * returns 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, + word32 signedAttribSz, byte* pkcs7Digest, + word32* pkcs7DigestSz, byte** plainDigest, + word32* plainDigestSz) +{ + int ret = 0, digIdx = 0, hashSz; + word32 attribSetSz; + byte attribSet[MAX_SET_SZ]; + byte digest[WC_MAX_DIGEST_SIZE]; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; #endif - return MEMORY_E; - } - FlattenAttributes(flatSignedAttribs, - esd->signedAttribs, esd->signedAttribsCount); - esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, - esd->signedAttribSet); + + wc_HashAlg hash; + enum wc_HashType hashType; + + if (pkcs7 == NULL || pkcs7Digest == NULL || + pkcs7DigestSz == NULL || plainDigest == NULL) { + return BAD_FUNC_ARG; } - /* Calculate the final hash and encrypt it. */ - { - int result; - word32 scratch = 0; #ifdef WOLFSSL_SMALL_STACK - byte* digestInfo; - RsaKey* privKey; -#else - RsaKey stack_privKey; - RsaKey* privKey = &stack_privKey; - byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; + digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) + return MEMORY_E; #endif - byte digestInfoSeq[MAX_SEQ_SZ]; - byte digestStr[MAX_OCTET_STR_SZ]; - word32 digestInfoSeqSz, digestStrSz; - int digIdx = 0; - if (pkcs7->signedAttribsSz != 0) { - byte attribSet[MAX_SET_SZ]; - word32 attribSetSz; + XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); + XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ); - attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + hashSz = wc_PKCS7_SetHashType(pkcs7, &hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } - ret = wc_InitSha(&esd->sha); - if (ret < 0) { - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + /* calculate digest */ + ret = wc_HashInit(&hash, hashType); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ret; - } - wc_ShaUpdate(&esd->sha, attribSet, attribSetSz); - wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz); - wc_ShaFinal(&esd->sha, esd->contentAttribsDigest); - } else { - /* when no attrs, digest is contentDigest without tag and length */ - XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, - SHA_DIGEST_SIZE); - } + return ret; + } - digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); - digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz + - digestStrSz + SHA_DIGEST_SIZE, - digestInfoSeq); + if (signedAttribSz > 0) { + if (signedAttrib == NULL) { #ifdef WOLFSSL_SMALL_STACK - digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digestInfo == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif + return BAD_FUNC_ARG; + } - XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); - digIdx += digestInfoSeqSz; - XMEMCPY(digestInfo + digIdx, - esd->signerDigAlgoId, esd->signerDigAlgoIdSz); - digIdx += esd->signerDigAlgoIdSz; - XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); - digIdx += digestStrSz; - XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, - SHA_DIGEST_SIZE); - digIdx += SHA_DIGEST_SIZE; - + attribSetSz = SetSet(signedAttribSz, attribSet); + ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; +#endif + return ret; } + + ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; + } - result = wc_InitRsaKey(privKey, pkcs7->heap); - if (result == 0) - result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey, - pkcs7->privateKeySz); - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return PUBLIC_KEY_E; + return ret; } - result = wc_RsaSSL_Sign(digestInfo, digIdx, - esd->encContentDigest, - sizeof(esd->encContentDigest), - privKey, pkcs7->rng); + } else { - wc_FreeRsaKey(privKey); + if (pkcs7->content == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; + } - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return result; + return ret; } - esd->encContentDigestSz = (word32)result; } - signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; - esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, - esd->signerDigest); - signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; + /* Set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); - esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); - signerInfoSz += esd->signerInfoSeqSz; - esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); - signerInfoSz += esd->signerInfoSetSz; + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); - esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, - esd->certsSet); + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, digest, hashSz); + digIdx += hashSz; - esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, - oidHashType, 0); - esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet); + XMEMCPY(pkcs7Digest, digestInfo, digIdx); + *pkcs7DigestSz = digIdx; + /* set plain digest pointer */ + *plainDigest = pkcs7Digest + digIdx - hashSz; + *plainDigestSz = hashSz; - esd->versionSz = SetMyVersion(1, esd->version, 0); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; +} - totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + - esd->contentInfoSeqSz + esd->certsSetSz + pkcs7->singleCertSz + - esd->innerOctetsSz + esd->innerContSeqSz + - innerOidSz + pkcs7->contentSz + - signerInfoSz; - esd->innerSeqSz = SetSequence(totalSz, esd->innerSeq); - totalSz += esd->innerSeqSz; - esd->outerContentSz = SetExplicit(0, totalSz, esd->outerContent); - totalSz += esd->outerContentSz + outerOidSz; - esd->outerSeqSz = SetSequence(totalSz, esd->outerSeq); - totalSz += esd->outerSeqSz; - if (outputSz < totalSz) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); +/* verifies SignedData signature, over either PKCS#7 DigestInfo or + * content digest. + * + * pkcs7 - pointer to initialized PKCS7 struct + * sig - signature to verify + * sigSz - size of sig + * signedAttrib - signed attributes, or null if empty + * signedAttribSz - size of signedAttributes + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, + word32 sigSz, byte* signedAttrib, + word32 signedAttribSz) +{ + int ret = 0; + word32 plainDigestSz = 0, pkcs7DigestSz; + byte* plainDigest = NULL; /* offset into pkcs7Digest */ #ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + byte* pkcs7Digest; +#else + byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ]; #endif - return BUFFER_E; - } - idx = 0; - XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); - idx += esd->outerSeqSz; - XMEMCPY(output + idx, outerOid, outerOidSz); - idx += outerOidSz; - XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); - idx += esd->outerContentSz; - XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); - idx += esd->innerSeqSz; - XMEMCPY(output + idx, esd->version, esd->versionSz); - idx += esd->versionSz; - XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz); - idx += esd->digAlgoIdSetSz; - XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz); - idx += esd->singleDigAlgoIdSz; - XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); - idx += esd->contentInfoSeqSz; - XMEMCPY(output + idx, innerOid, innerOidSz); - idx += innerOidSz; - XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); - idx += esd->innerContSeqSz; - XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); - idx += esd->innerOctetsSz; - XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); - idx += pkcs7->contentSz; - XMEMCPY(output + idx, esd->certsSet, esd->certsSetSz); - idx += esd->certsSetSz; - XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz); - idx += pkcs7->singleCertSz; - XMEMCPY(output + idx, esd->signerInfoSet, esd->signerInfoSetSz); - idx += esd->signerInfoSetSz; - XMEMCPY(output + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); - idx += esd->signerInfoSeqSz; - XMEMCPY(output + idx, esd->signerVersion, esd->signerVersionSz); - idx += esd->signerVersionSz; - XMEMCPY(output + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); - idx += esd->issuerSnSeqSz; - XMEMCPY(output + idx, esd->issuerName, esd->issuerNameSz); - idx += esd->issuerNameSz; - XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz); - idx += pkcs7->issuerSz; - XMEMCPY(output + idx, esd->issuerSn, esd->issuerSnSz); - idx += esd->issuerSnSz; - XMEMCPY(output + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); - idx += esd->signerDigAlgoIdSz; + if (pkcs7 == NULL) + return BAD_FUNC_ARG; - /* SignerInfo:Attributes */ - if (pkcs7->signedAttribsSz != 0) { - XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); - idx += esd->signedAttribSetSz; - XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); - idx += flatSignedAttribsSz; - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); +#ifdef WOLFSSL_SMALL_STACK + pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs7Digest == NULL) + return MEMORY_E; +#endif + + /* build hash to verify against */ + pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, + signedAttribSz, pkcs7Digest, + &pkcs7DigestSz, &plainDigest, + &plainDigestSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } - XMEMCPY(output + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); - idx += esd->digEncAlgoIdSz; - XMEMCPY(output + idx, esd->signerDigest, esd->signerDigestSz); - idx += esd->signerDigestSz; - XMEMCPY(output + idx, esd->encContentDigest, esd->encContentDigestSz); - idx += esd->encContentDigestSz; + switch (pkcs7->publicKeyOID) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, + pkcs7DigestSz); + if (ret < 0) { + WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + } + break; #endif - return idx; +#ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } /* Finds the certificates in the message and saves it. */ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) { - word32 idx, contentType; + word32 idx, contentType, hashOID; int length, version, ret; byte* content = NULL; byte* sig = NULL; byte* cert = NULL; - int contentSz = 0, sigSz = 0, certSz = 0; + byte* signedAttrib = NULL; + int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) return BAD_FUNC_ARG; @@ -863,7 +1598,7 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) <= 0) return ASN_PARSE_E; if (pkiMsg[idx++] != ASN_OCTET_STRING) @@ -943,11 +1678,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) idx += length; /* Get the sequence of digestAlgorithm */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) { return ASN_PARSE_E; - - /* Skip it */ - idx += length; + } + pkcs7->hashOID = (int)hashOID; /* Get the IMPLICIT[0] SET OF signedAttributes */ if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { @@ -956,6 +1690,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + /* save pointer and length */ + signedAttrib = &pkiMsg[idx]; + signedAttribSz = length; + idx += length; } @@ -983,72 +1721,18 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) pkcs7->content = content; pkcs7->contentSz = contentSz; - { - word32 scratch = 0; - int plainSz = 0; - #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE) - -#ifdef WOLFSSL_SMALL_STACK - byte* digest; - RsaKey* key; - - digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (digest == NULL) - return MEMORY_E; - - key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#else - byte digest[MAX_PKCS7_DIGEST_SZ]; - RsaKey stack_key; - RsaKey* key = &stack_key; -#endif - - XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - - ret = wc_InitRsaKey(key, pkcs7->heap); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, - pkcs7->publicKeySz) < 0) { - WOLFSSL_MSG("ASN RSA key decode error"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - plainSz = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, - key); - wc_FreeRsaKey(key); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (plainSz < 0) - return plainSz; - } + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz); + if (ret < 0) + return ret; } return 0; } +#ifdef HAVE_ECC + /* KARI == KeyAgreeRecipientInfo (key agreement) */ typedef struct WC_PKCS7_KARI { DecodedCert* decoded; /* decoded recip cert */ @@ -1137,7 +1821,7 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) DYNAMIC_TYPE_PKCS7); if (kari->decoded == NULL) { WOLFSSL_MSG("Failed to allocate DecodedCert"); - XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return NULL; } @@ -1145,8 +1829,8 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) DYNAMIC_TYPE_PKCS7); if (kari->recipKey == NULL) { WOLFSSL_MSG("Failed to allocate recipient ecc_key"); - XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); - XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return NULL; } @@ -1154,9 +1838,9 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) DYNAMIC_TYPE_PKCS7); if (kari->senderKey == NULL) { WOLFSSL_MSG("Failed to allocate sender ecc_key"); - XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); - XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); - XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return NULL; } @@ -1292,7 +1976,7 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, /* create ephemeral ECC key, places ecc_key in kari->senderKey, * DER encoded in kari->senderKeyExport. return 0 on success, * negative on error */ -static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, RNG* rng) +static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) { int ret; @@ -1308,7 +1992,7 @@ static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, RNG* rng) kari->senderKeyExportSz = kari->decoded->pubKeySize; - ret = wc_ecc_init(kari->senderKey); + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -1336,6 +2020,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) int keyInfoSz = 0; int suppPubInfoSeqSz = 0; int entityUInfoOctetSz = 0; + int entityUInfoExplicitSz = 0; int kekOctetSz = 0; int sharedInfoSz = 0; @@ -1345,6 +2030,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) byte keyInfo[MAX_ALGO_SZ]; byte suppPubInfoSeq[MAX_SEQ_SZ]; byte entityUInfoOctet[MAX_OCTET_STR_SZ]; + byte entityUInfoExplicitSeq[MAX_SEQ_SZ]; byte kekOctet[MAX_OCTET_STR_SZ]; if (kari == NULL) @@ -1367,6 +2053,11 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) if (kari->ukmSz > 0) { entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); + + entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + + kari->ukmSz, + entityUInfoExplicitSeq); + sharedInfoSz += entityUInfoExplicitSz; } /* keyInfo */ @@ -1389,6 +2080,9 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz); idx += keyInfoSz; if (kari->ukmSz > 0) { + XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq, + entityUInfoExplicitSz); + idx += entityUInfoExplicitSz; XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz); idx += entityUInfoOctetSz; XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz); @@ -1415,7 +2109,8 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, int keyWrapOID, int keyEncOID) { int ret; - int kSz, kdfType; + int kSz; + enum wc_HashType kdfType; byte* secret; word32 secretSz; @@ -1474,7 +2169,7 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, kdfType = WC_HASH_TYPE_SHA; break; #endif - #ifndef WOLF_SHA224 + #ifndef WOLFSSL_SHA224 case dhSinglePass_stdDH_sha224kdf_scheme: kdfType = WC_HASH_TYPE_SHA224; break; @@ -1763,6 +2458,8 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, return idx; } +#endif /* HAVE_ECC */ + /* create ASN.1 formatted RecipientInfo structure, returns sequence size */ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, @@ -2116,32 +2813,32 @@ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, static int wc_PKCS7_GenerateIV(WC_RNG* rng, byte* iv, word32 ivSz) { int ret; - WC_RNG* random = NULL; + WC_RNG* rnd = NULL; if (iv == NULL || ivSz == 0) return BAD_FUNC_ARG; /* input RNG is optional, init local one if input rng is NULL */ if (rng == NULL) { - random = XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (random == NULL) + rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (rnd == NULL) return MEMORY_E; - ret = wc_InitRng(random); + ret = wc_InitRng(rnd); if (ret != 0) { - XFREE(random, NULL, DYNAMIC_TYPE_RNG); + XFREE(rnd, NULL, DYNAMIC_TYPE_RNG); return ret; } } else { - random = rng; + rnd = rng; } - ret = wc_RNG_GenerateBlock(random, iv, ivSz); + ret = wc_RNG_GenerateBlock(rnd, iv, ivSz); if (rng == NULL) { - wc_FreeRng(random); - XFREE(random, NULL, DYNAMIC_TYPE_RNG); + wc_FreeRng(rnd); + XFREE(rnd, NULL, DYNAMIC_TYPE_RNG); } return ret; @@ -2258,7 +2955,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* generate random content encryption key */ - ret = wc_InitRng(&rng); + ret = wc_InitRng_ex(&rng, pkcs7->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -2293,6 +2990,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) MAX_RECIP_SZ, pkcs7->heap); break; +#ifdef HAVE_ECC case ECDSAk: recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert, pkcs7->singleCertSz, @@ -2302,6 +3000,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentKeyPlain, contentKeyEnc, &contentKeyEncSz, recip, MAX_RECIP_SZ); break; +#endif default: WOLFSSL_MSG("Unsupported RecipientInfo public key type"); @@ -2318,7 +3017,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("Failed to create RecipientInfo"); wc_FreeRng(&rng); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return recipSz; } @@ -2329,7 +3028,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) wc_FreeRng(&rng); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -2338,7 +3037,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); if (contentTypeSz == 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return BAD_FUNC_ARG; } @@ -2367,7 +3066,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (encryptedContent == NULL) { XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return MEMORY_E; } @@ -2434,7 +3133,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return BUFFER_E; } @@ -2474,7 +3173,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return idx; @@ -2645,6 +3344,8 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } +#ifdef HAVE_ECC + /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx) @@ -2744,14 +3445,18 @@ static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, return 0; } - kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); - if (kari->ukm == NULL) - return MEMORY_E; + kari->ukm = NULL; + if (length > 0) { + kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->ukm == NULL) + return MEMORY_E; + + XMEMCPY(kari->ukm, pkiMsg + (*idx), length); + kari->ukmOwner = 1; + } - XMEMCPY(kari->ukm, pkiMsg + (*idx), length); (*idx) += length; kari->ukmSz = length; - kari->ukmOwner = 1; return 0; } @@ -2850,6 +3555,8 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, return 0; } +#endif /* HAVE_ECC */ + /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, * < 0 on error */ @@ -2857,6 +3564,7 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { +#ifdef HAVE_ECC int ret, keySz; int encryptedKeySz; int direction = 0; @@ -2990,6 +3698,17 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, #endif return 0; +#else + (void)pkcs7; + (void)pkiMsg; + (void)pkiMsgSz; + (void)idx; + (void)decryptedKey; + (void)decryptedKeySz; + (void)recipFound; + + return NOT_COMPILED_IN; +#endif /* HAVE_ECC */ } @@ -3138,7 +3857,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, /* walk through RecipientInfo set, find correct recipient */ if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - + #ifdef WOLFSSL_SMALL_STACK decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, DYNAMIC_TYPE_PKCS7); @@ -3172,7 +3891,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, #endif return ASN_PARSE_E; } - + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7); @@ -3210,14 +3929,14 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, #endif return ASN_PARSE_E; } - + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7); #endif return ASN_PARSE_E; } - + if (length != expBlockSz) { WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); #ifdef WOLFSSL_SMALL_STACK @@ -3237,7 +3956,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, return ASN_PARSE_E; } - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) { + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7); #endif @@ -3387,8 +4106,11 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* encrypt content */ ret = wc_PKCS7_GenerateIV(NULL, tmpIv, blockSz); - if (ret != 0) + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; + } ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz, @@ -3468,7 +4190,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("PKCS#7 output buffer too small"); if (pkcs7->unprotectedAttribsSz != 0) { XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); } XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -3571,9 +4293,9 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, /* save attribute value bytes and size */ if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) { - return ASN_PARSE_E; XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS); XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + return ASN_PARSE_E; } if ((pkiMsgSz - idx) < (word32)length) { @@ -3691,7 +4413,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) return ASN_PARSE_E; encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, diff --git a/wolfcrypt/src/poly1305.c b/wolfcrypt/src/poly1305.c index 637106b63b..4badc05b70 100644 --- a/wolfcrypt/src/poly1305.c +++ b/wolfcrypt/src/poly1305.c @@ -592,26 +592,28 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, return BAD_FUNC_ARG; } - if (additional == NULL && addSz > 0) { - return BAD_FUNC_ARG; - } + /* additional allowed to be 0 */ + if (addSz > 0) { + if (additional == NULL) + return BAD_FUNC_ARG; - /* additional data plus padding */ - if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { - return ret; - } - paddingLen = -addSz & (WC_POLY1305_PAD_SZ - 1); - if (paddingLen) { - if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + /* additional data plus padding */ + if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { return ret; } + paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen) { + if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + return ret; + } + } } /* input plus padding */ if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { return ret; } - paddingLen = -sz & (WC_POLY1305_PAD_SZ - 1); + paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1); if (paddingLen) { if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { return ret; diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index e59bd2571b..0dc43e4e40 100644 --- a/wolfcrypt/src/port/arm/armv8-aes.c +++ b/wolfcrypt/src/port/arm/armv8-aes.c @@ -301,16 +301,22 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* set the heap hint for aes struct */ -int wc_InitAes_h(Aes* aes, void* h) +int wc_AesInit(Aes* aes, void* heap, int devId) { if (aes == NULL) return BAD_FUNC_ARG; - aes->heap = h; + aes->heap = heap; + (void)devId; return 0; } +void wc_AesFree(Aes* aes) +{ + (void)aes; +} + #ifdef __aarch64__ /* AES CCM/GCM use encrypt direct but not decrypt */ @@ -2532,6 +2538,11 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, return BAD_FUNC_ARG; } + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + switch (aes->rounds) { case 10: return Aes128GcmEncrypt(aes, out, in, sz, iv, ivSz, @@ -4547,26 +4558,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AESCCM */ -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Aes for use with Nitrox device */ -int wc_AesAsyncInit(Aes* aes, int devId) -{ - WOLFSSL_STUB("wc_AesAsyncInit"); - (void)aes; - (void)devId; - return 0; -} - - -/* Free Aes from use with Nitrox device */ -void wc_AesAsyncFree(Aes* aes) -{ - WOLFSSL_STUB("wc_AesAsyncFree"); - (void)aes; -} -#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_AESGCM /* common GCM functions 32 and 64 bit */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) @@ -4653,5 +4645,31 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) #endif /* HAVE_AES_DECRYPT */ #endif /* WOLFSSL_AES_DIRECT */ +int wc_AesGetKeySize(Aes* aes, word32* keySize) +{ + int ret = 0; + + if (aes == NULL || keySize == NULL) { + return BAD_FUNC_ARG; + } + + switch (aes->rounds) { + case 10: + *keySize = 16; + break; + case 12: + *keySize = 24; + break; + case 14: + *keySize = 32; + break; + default: + *keySize = 0; + ret = BAD_FUNC_ARG; + } + + return ret; +} + #endif /* NO_AES */ diff --git a/wolfcrypt/src/port/arm/armv8-sha256.c b/wolfcrypt/src/port/arm/armv8-sha256.c index fdf2634bf7..48d7230efc 100644 --- a/wolfcrypt/src/port/arm/armv8-sha256.c +++ b/wolfcrypt/src/port/arm/armv8-sha256.c @@ -38,27 +38,6 @@ #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - -#if !defined (ALIGN32) - #if defined (__GNUC__) - #define ALIGN32 __attribute__ ( (aligned (32))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN32 __declspec (align (32)) - #else - #define ALIGN32 - #endif -#endif static const ALIGN32 word32 K[64] = { 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, @@ -76,7 +55,8 @@ static const ALIGN32 word32 K[64] = { 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L }; -int wc_InitSha256(Sha256* sha256) + +int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) { int ret = 0; @@ -97,9 +77,21 @@ int wc_InitSha256(Sha256* sha256) sha256->loLen = 0; sha256->hiLen = 0; + (void)heap; + (void)devId; + return ret; } +int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(Sha256* sha256) +{ + (void)sha256; +} static INLINE void AddLength(Sha256* sha256, word32 len) { @@ -1308,7 +1300,35 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) return wc_InitSha256(sha256); /* reset state */ } + #endif /* __aarch64__ */ -#endif /* NO_SHA256 and WOLFSSL_ARMASM */ +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ + int ret; + Sha256 tmpSha256; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); + } + return ret; +} + +int wc_Sha256Copy(Sha256* src, Sha256* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha256)); + + return ret; +} + +#endif /* NO_SHA256 and WOLFSSL_ARMASM */ diff --git a/wolfcrypt/src/port/cavium/README.md b/wolfcrypt/src/port/cavium/README.md index 982a938b98..b98d866dd9 100644 --- a/wolfcrypt/src/port/cavium/README.md +++ b/wolfcrypt/src/port/cavium/README.md @@ -1,32 +1,3 @@ -# Cavium Nitrox V Support +# Cavium Nitrox III/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` +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/wolfcrypt/src/port/cavium/cavium_nitrox.c b/wolfcrypt/src/port/cavium/cavium_nitrox.c deleted file mode 100644 index 1acc496442..0000000000 --- a/wolfcrypt/src/port/cavium/cavium_nitrox.c +++ /dev/null @@ -1,778 +0,0 @@ -/* 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/port/intel/README.md b/wolfcrypt/src/port/intel/README.md new file mode 100644 index 0000000000..4b5d971bab --- /dev/null +++ b/wolfcrypt/src/port/intel/README.md @@ -0,0 +1,3 @@ +# Intel QuickAssist Adapter Asynchronous Support + +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index ac4d579b23..4c5853d7ba 100644 --- a/wolfcrypt/src/port/nxp/ksdk_port.c +++ b/wolfcrypt/src/port/nxp/ksdk_port.c @@ -23,7 +23,6 @@ #include #endif -/* in case user set USE_FAST_MATH there */ #include #ifdef NO_INLINE #include @@ -33,8 +32,7 @@ #endif /* If FREESCALE_LTC_TFM or FREESCALE_LTC_ECC */ -#if (defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM)) ||\ - defined(FREESCALE_LTC_ECC) +#if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) #include #include @@ -42,12 +40,12 @@ #include #include -#define ERROR_OUT(err) { ret = (err); goto done; } +#define ERROR_OUT(res) { ret = (res); goto done; } int ksdk_port_init(void) { -#if defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM) +#if defined(FREESCALE_LTC_TFM) LTC_Init(LTC0); #endif @@ -56,8 +54,7 @@ int ksdk_port_init(void) /* LTC TFM */ -#if defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM) -#include +#if defined(FREESCALE_LTC_TFM) /* Reverse array in memory (in place) */ static void ltc_reverse_array(uint8_t *src, size_t src_len) @@ -73,39 +70,52 @@ static void ltc_reverse_array(uint8_t *src, size_t src_len) } } -/* same as fp_to_unsigned_bin() with fp_reverse() skipped */ -static void fp_to_unsigned_lsb_bin(fp_int *a, unsigned char *b) +/* same as mp_to_unsigned_bin() with mp_reverse() skipped */ +static int mp_to_unsigned_lsb_bin(mp_int *a, unsigned char *b) { - fp_int t; + int res; + mp_int t; - fp_init_copy(&t, a); + res = mp_init_copy(&t, a); + if (res == MP_OKAY) { + res = mp_to_unsigned_bin_at_pos(0, &t, b); + if (res >= 0) + res = 0; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif + } - (void)fp_to_unsigned_bin_at_pos(0, &t, b); + return res; } -static void ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) +static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) { + int res; uint16_t sz; sz = mp_unsigned_bin_size(A); - fp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ + res = mp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ *psz = sz; + + return res; } /* these function are used by wolfSSL upper layers (like RSA) */ /* c = a * b */ -void fp_mul(fp_int *A, fp_int *B, fp_int *C) +int mp_mul(mp_int *A, mp_int *B, mp_int *C) { + int res = MP_OKAY; int szA, szB; - szA = fp_unsigned_bin_size(A); - szB = fp_unsigned_bin_size(B); + szA = mp_unsigned_bin_size(A); + szB = mp_unsigned_bin_size(B); /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call software mul */ if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) { int neg; - neg = (A->sign == B->sign) ? FP_ZPOS : FP_NEG; + neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG; /* unsigned multiply */ uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -115,16 +125,19 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB; - ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); - XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); + res = ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); + if (res == MP_OKAY) { + XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); - LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, - kLTC_PKHA_TimingEqualized); + LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); - ltc_reverse_array(ptrB, sizeB); - mp_read_unsigned_bin(C, ptrB, sizeB); + ltc_reverse_array(ptrB, sizeB); + res = mp_read_unsigned_bin(C, ptrB, sizeB); + } } /* fix sign */ @@ -138,52 +151,53 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return; } else { - wolfcrypt_fp_mul(A, B, C); + res = wolfcrypt_mp_mul(A, B, C); } + return res; } /* c = a mod b, 0 <= c < b */ -int fp_mod(fp_int *a, fp_int *b, fp_int *c) +int mp_mod(mp_int *a, mp_int *b, mp_int *c) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; int neg; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); /* get sign for the result */ - neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; /* get remainder of unsigned a divided by unsigned b */ if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - - if (kStatus_Success == - LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { - ltc_reverse_array(ptrC, sizeC); - mp_read_unsigned_bin(c, ptrC, sizeC); - } - else { - res = FP_VAL; + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + if (kStatus_Success == + LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(c, ptrC, sizeC); + } + else { + res = MP_VAL; + } } } else { - res = FP_MEM; + res = MP_MEM; } /* fix sign */ @@ -198,26 +212,25 @@ int fp_mod(fp_int *a, fp_int *b, fp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return res; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_mod(a, b, c); + res = wolfcrypt_mp_mod(a, b, c); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* c = 1/a (mod b) for odd b only */ -int fp_invmod(fp_int *a, fp_int *b, fp_int *c) +int mp_invmod(mp_int *a, mp_int *b, mp_int *c) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { #endif - int res = FP_OKAY; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -225,21 +238,23 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - - if (kStatus_Success == - LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { - ltc_reverse_array(ptrC, sizeC); - mp_read_unsigned_bin(c, ptrC, sizeC); - } - else { - res = FP_VAL; + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + if (kStatus_Success == + LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(c, ptrC, sizeC); + } + else { + res = MP_VAL; + } } } else { - res = FP_MEM; + res = MP_MEM; } c->sign = a->sign; @@ -252,85 +267,91 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return res; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_invmod(a, b, c); + res = wolfcrypt_mp_invmod(a, b, c); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* d = a * b (mod c) */ -int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB, szC; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); - szC = fp_unsigned_bin_size(c); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); + szC = mp_unsigned_bin_size(c); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; - fp_int t; + mp_int t; uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrD = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - /* if A or B is negative, substracta abs(A) or abs(B) from modulus to get positive integer representation of the + /* if A or B is negative, subtract abs(A) or abs(B) from modulus to get positive integer representation of the * same number */ - fp_init(&t); + res = mp_init(&t); if (a->sign) { - fp_add(a, c, &t); - fp_copy(&t, a); + if (res == MP_OKAY) + res = mp_add(a, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, a); } if (b->sign) { - fp_add(b, c, &t); - fp_copy(&t, b); + if (res == MP_OKAY) + res = mp_add(b, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, b); } - if (ptrA && ptrB && ptrC && ptrD) { + if (res == MP_OKAY && ptrA && ptrB && ptrC && ptrD) { uint16_t sizeA, sizeB, sizeC, sizeD; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); /* (A*B)mod C = ((A mod C) * (B mod C)) mod C */ - if (LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrC, sizeC, ptrA, &sizeA, kLTC_PKHA_IntegerArith)) { - res = FP_VAL; + res = MP_VAL; } } - if ((FP_OKAY == res) && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) + if (res == MP_OKAY && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrB, sizeB, ptrC, sizeC, ptrB, &sizeB, kLTC_PKHA_IntegerArith)) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { if (kStatus_Success != LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, sizeC, ptrD, &sizeD, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized)) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { ltc_reverse_array(ptrD, sizeD); - mp_read_unsigned_bin(d, ptrD, sizeD); + res = mp_read_unsigned_bin(d, ptrD, sizeD); } } else { - res = FP_MEM; + res = MP_MEM; } if (ptrA) { @@ -345,41 +366,45 @@ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) if (ptrD) { XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT); } - return res; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_mulmod(a, b, c, d); + res = wolfcrypt_mp_mulmod(a, b, c, d); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* Y = G^X mod P */ -int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) +int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB, szC; - fp_int tmp; - int err; + mp_int tmp; /* if G cannot fit into LTC_PKHA, reduce it */ - szA = fp_unsigned_bin_size(G); + szA = mp_unsigned_bin_size(G); if (szA > LTC_MAX_INT_BYTES) { - fp_init(&tmp); - if ((err = fp_mod(G, P, &tmp)) != FP_OKAY) { - return err; + res = mp_init(&tmp); + if (res != MP_OKAY) + return res; + if ((res = mp_mod(G, P, &tmp)) != MP_OKAY) { + return res; } G = &tmp; - szA = fp_unsigned_bin_size(G); + szA = mp_unsigned_bin_size(G); } - szB = fp_unsigned_bin_size(X); - szC = fp_unsigned_bin_size(P); + szB = mp_unsigned_bin_size(X); + szC = mp_unsigned_bin_size(P); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; - fp_int t; + mp_int t; uint16_t sizeG, sizeX, sizeP; uint8_t *ptrG = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -387,16 +412,20 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) uint8_t *ptrP = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); /* if G is negative, add modulus to convert to positive number for LTC */ - fp_init(&t); + res = mp_init(&t); if (G->sign) { - fp_add(G, P, &t); - fp_copy(&t, G); + if (res == MP_OKAY) + res = mp_add(G, P, &t); + if (res == MP_OKAY) + res = mp_copy(&t, G); } - if (ptrG && ptrX && ptrP) { - ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); - ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); - ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); + if (res == MP_OKAY && ptrG && ptrX && ptrP) { + res = ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); /* if number if greater that modulo, we must first reduce due to LTC requirement on modular exponentiaton */ /* it needs number less than modulus. */ @@ -405,29 +434,29 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) and then the modular exponentiation. */ /* if G >= P then */ - if (LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { res = (int)LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrG, &sizeG, kLTC_PKHA_IntegerArith); if (res != kStatus_Success) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { res = (int)LTC_PKHA_ModExp(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrX, sizeX, ptrP, &sizeP, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); if (res != kStatus_Success) { - res = FP_VAL; + res = MP_VAL; } else { ltc_reverse_array(ptrP, sizeP); - mp_read_unsigned_bin(Y, ptrP, sizeP); + res = mp_read_unsigned_bin(Y, ptrP, sizeP); } } } else { - res = FP_MEM; + res = MP_MEM; } if (ptrG) { @@ -439,16 +468,24 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) if (ptrP) { XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT); } - return res; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return _wolfcrypt_fp_exptmod(G, X, P, Y); + res = wolfcrypt_mp_exptmod(G, X, P, Y); } + +#ifndef USE_FAST_MATH + if (szA > LTC_MAX_INT_BYTES) + mp_clear(&tmp); +#endif #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } -#endif /* USE_FAST_MATH && FREESCALE_LTC_TFM */ +#endif /* FREESCALE_LTC_TFM */ /* ECC */ @@ -457,11 +494,12 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) /* convert from mp_int to LTC integer, as array of bytes of size sz. * if mp_int has less bytes than sz, add zero bytes at most significant byte positions. * This is when for example modulus is 32 bytes (P-256 curve) - * and mp_int has only 31 bytes, we add leading zeroes + * and mp_int has only 31 bytes, we add leading zeros * so that result array has 32 bytes, same as modulus (sz). */ -static void ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) +static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) { + int res; int szbin; int offset; @@ -480,10 +518,14 @@ static void ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) XMEMSET(dst, 0, offset); /* convert mp_int to array of bytes */ - mp_to_unsigned_bin(a, dst + offset); + res = mp_to_unsigned_bin(a, dst + offset); + + if (res == MP_OKAY) { + /* reverse array for LTC direct use */ + ltc_reverse_array(dst, sz); + } - /* reverse array for LTC direct use */ - ltc_reverse_array(dst, sz); + return res; } /* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA driver functions */ @@ -636,8 +678,10 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, int szkbin; bool point_of_infinity; status_t status; + int res; (void)a; + (void)heap; uint8_t Gxbin[LTC_MAX_ECC_BITS / 8]; uint8_t Gybin[LTC_MAX_ECC_BITS / 8]; @@ -655,9 +699,14 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, szModulus = mp_unsigned_bin_size(modulus); szkbin = mp_unsigned_bin_size(k); - ltc_get_from_mp_int(kbin, k, szkbin); - ltc_get_from_mp_int(Gxbin, G->x, szModulus); - ltc_get_from_mp_int(Gybin, G->y, szModulus); + res = ltc_get_from_mp_int(kbin, k, szkbin); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gxbin, G->x, szModulus); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gybin, G->y, szModulus); + + if (res != MP_OKAY) + return res; size = szModulus; /* find LTC friendly parameters for the selected curve */ @@ -671,25 +720,28 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn, aCurveParam, bCurveParam, size, kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith, &B, &point_of_infinity); if (status != kStatus_Success) { - return FP_VAL; + return MP_VAL; } ltc_reverse_array(Gxbin, size); ltc_reverse_array(Gybin, size); - mp_read_unsigned_bin(R->x, Gxbin, size); - mp_read_unsigned_bin(R->y, Gybin, size); - /* if k is negative, we compute the multiplication with abs(-k) - * with result (x, y) and modify the result to (x, -y) - */ - R->y->sign = k->sign; - mp_set(R->z, 1); + res = mp_read_unsigned_bin(R->x, Gxbin, size); + if (res == MP_OKAY) { + res = mp_read_unsigned_bin(R->y, Gybin, size); + /* if k is negative, we compute the multiplication with abs(-k) + * with result (x, y) and modify the result to (x, -y) + */ + R->y->sign = k->sign; + } + if (res == MP_OKAY) + res = mp_set(R->z, 1); - return MP_OKAY; + return res; } int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) { - int err; + int res; ltc_pkha_ecc_point_t A, B; int size; status_t status; @@ -704,15 +756,22 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) const uint8_t *r2modn; size = mp_unsigned_bin_size(m); + /* find LTC friendly parameters for the selected curve */ - if (0 != ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size)) { - err = ECC_BAD_ARG_E; + if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size) != 0) { + res = ECC_BAD_ARG_E; } else { - ltc_get_from_mp_int(Gxbin, mG->x, size); - ltc_get_from_mp_int(Gybin, mG->y, size); - ltc_get_from_mp_int(Qxbin, mQ->x, size); - ltc_get_from_mp_int(Qybin, mQ->y, size); + res = ltc_get_from_mp_int(Gxbin, mG->x, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gybin, mG->y, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Qxbin, mQ->x, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Qybin, mQ->y, size); + + if (res != MP_OKAY) + return res; A.X = Gxbin; A.Y = Gybin; @@ -723,18 +782,19 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn, aCurveParam, bCurveParam, size, kLTC_PKHA_IntegerArith, &A); if (status != kStatus_Success) { - err = FP_VAL; + res = MP_VAL; } else { ltc_reverse_array(Gxbin, size); ltc_reverse_array(Gybin, size); - mp_read_unsigned_bin(mR->x, Gxbin, size); - mp_read_unsigned_bin(mR->y, Gybin, size); - mp_set(mR->z, 1); - err = MP_OKAY; + res = mp_read_unsigned_bin(mR->x, Gxbin, size); + if (res == MP_OKAY) + res = mp_read_unsigned_bin(mR->y, Gybin, size); + if (res == MP_OKAY) + res = mp_set(mR->z, 1); } } - return err; + return res; } #if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) @@ -852,7 +912,7 @@ status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA, * * X mod 2 get from LSB bit0 */ - if ((status == kStatus_Success) && + if ((status == kStatus_Success) && ((bool)sign != (bool)(res[0] & 0x01u))) { status = LTC_PKHA_ModSub1(LTC_BASE, modbin, sizeof(modbin), res, @@ -1036,7 +1096,7 @@ int wc_curve25519(ECPoint *q, byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_ ltcPoint.X = &pIn.point[0]; ltcPoint.Y = &pIn.pointY[0]; - /* if input point P is on Curve25519 Montgomery curve, transform + /* if input point P is on Curve25519 Montgomery curve, transform it to Weierstrass equivalent */ if (type == kLTC_Curve25519) { LTC_PKHA_Curve25519ToWeierstrass(<cPoint, <cPoint); @@ -1197,7 +1257,7 @@ status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, Mx = (1 + Ey) * ModularArithmetic.invert(1 - Ey, prime) % prime My = (1 + Ey) * ModularArithmetic.invert((1 - Ey)*Ex, prime) % prime */ - /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) + + /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) + (A * ModularArithmetic.invert(3*B, prime))) % prime Gy = (My * ModularArithmetic.invert(B, prime)) % prime */ @@ -1497,7 +1557,7 @@ status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, uint8_t tempB[32] = {0}; status_t status; - /* Assume only b can be larger than modulus. It is called durind + /* Assume only b can be larger than modulus. It is called durind * wc_ed25519_sign_msg() where hram (=a) and nonce(=c) * have been reduced by LTC_PKHA_sc_reduce() * Thus reducing b only. @@ -1622,4 +1682,4 @@ status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, #undef ERROR_OUT -#endif /* (USE_FAST_MATH && FREESCALE_LTC_TFM) || FREESCALE_LTC_ECC */ +#endif /* FREESCALE_LTC_TFM || FREESCALE_LTC_ECC */ diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 5b982c41de..cd8d2eed92 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -490,6 +490,9 @@ WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + return BAD_FUNC_ARG; + } return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; } diff --git a/wolfcrypt/src/port/ti/ti-ccm.c b/wolfcrypt/src/port/ti/ti-ccm.c index abf4d602dc..f4a4c65950 100644 --- a/wolfcrypt/src/port/ti/ti-ccm.c +++ b/wolfcrypt/src/port/ti/ti-ccm.c @@ -32,52 +32,63 @@ #include #include +#ifndef TI_DUMMY_BUILD #include "driverlib/sysctl.h" #include "driverlib/rom_map.h" #include "driverlib/rom.h" #ifndef SINGLE_THREADED #include - static wolfSSL_Mutex TI_CCM_Mutex ; + static wolfSSL_Mutex TI_CCM_Mutex; #endif +#endif /* TI_DUMMY_BUILD */ #define TIMEOUT 500000 -#define WAIT(stat) { volatile int i ; for(i=0; i #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -59,67 +59,68 @@ #define SHAMD5_ALGO_MD5 1 #define SHAMD5_ALGO_SHA1 2 #define SHAMD5_ALGO_SHA256 3 -bool wolfSSL_TI_CCMInit(void) { return true ; } +#define SHAMD5_ALGO_SHA224 4 #endif static int hashInit(wolfssl_TI_Hash *hash) { - if(!wolfSSL_TI_CCMInit())return 1 ; - hash->used = 0 ; - hash->msg = 0 ; - hash->len = 0 ; - return 0 ; + if (!wolfSSL_TI_CCMInit())return 1; + hash->used = 0; + hash->msg = 0; + hash->len = 0; + return 0; } static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) { - void *p ; + void *p; - if((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; + if ((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; - if(hash->len < hash->used+len) { - if(hash->msg == NULL) { + if (hash->len < hash->used+len) { + if (hash->msg == NULL) { p = XMALLOC(hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { p = XREALLOC(hash->msg, hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - if(p == 0)return 1 ; - hash->msg = p ; - hash->len = hash->used+len ; - } - XMEMCPY(hash->msg+hash->used, data, len) ; - hash->used += len ; - return 0 ; + if (p == 0)return 1; + hash->msg = p; + hash->len = hash->used+len; + } + XMEMCPY(hash->msg+hash->used, data, len); + hash->used += len; + return 0; } static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - uint32_t h[16] ; +{ + uint32_t h[16]; #ifndef TI_DUMMY_BUILD - wolfSSL_TI_lockCCM() ; + wolfSSL_TI_lockCCM(); ROM_SHAMD5Reset(SHAMD5_BASE); ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); - ROM_SHAMD5DataProcess(SHAMD5_BASE, + ROM_SHAMD5DataProcess(SHAMD5_BASE, (uint32_t *)hash->msg, hash->used, h); - wolfSSL_TI_unlockCCM() ; + wolfSSL_TI_unlockCCM(); #else - (void) hash ; - (void) algo ; + (void) hash; + (void) algo; #endif - XMEMCPY(result, h, hsize) ; + XMEMCPY(result, h, hsize); - return 0 ; + return 0; } -static void hashRestorePos(wolfssl_TI_Hash *h1, wolfssl_TI_Hash *h2) { - h1->used = h2->used ; +static int hashCopy(wolfssl_TI_Hash *src, wolfssl_TI_Hash *dst) { + XMEMCPY(dst, src, sizeof(wolfssl_TI_Hash)); + return 0; } static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - hashGetHash(hash, result, algo, hsize) ; +{ + hashGetHash(hash, result, algo, hsize); XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hashInit(hash) ; - return 0 ; + hashInit(hash); + return 0; } static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word32 hsize) @@ -153,166 +154,183 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 } static int hashFree(wolfssl_TI_Hash *hash) -{ +{ XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hashInit(hash) ; - return 0 ; + hashInit(hash); + return 0; } #if !defined(NO_MD5) -WOLFSSL_API void wc_InitMd5(Md5* md5) +WOLFSSL_API int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { if (md5 == NULL) - return ; - hashInit((wolfssl_TI_Hash *)md5) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)md5); +} +WOLFSSL_API int wc_InitMd5(Md5* md5) +{ + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); } -WOLFSSL_API void wc_Md5Update(Md5* md5, const byte* data, word32 len) +WOLFSSL_API int wc_Md5Update(Md5* md5, const byte* data, word32 len) { - hashUpdate((wolfssl_TI_Hash *)md5, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)md5, data, len); } -WOLFSSL_API void wc_Md5Final(Md5* md5, byte* hash) +WOLFSSL_API int wc_Md5Final(Md5* md5, byte* hash) { - hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } -WOLFSSL_API void wc_Md5GetHash(Md5* md5, byte* hash) +WOLFSSL_API int wc_Md5GetHash(Md5* md5, byte* hash) { - hashGetHash((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + return hashGetHash((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } -WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { - hashRestorePos((wolfssl_TI_Hash *)m1, (wolfssl_TI_Hash *)m2) ; +WOLFSSL_API int wc_Md5Copy(Md5* src, Md5* dst) { + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } WOLFSSL_API void wc_Md5Free(Md5* md5) { - hashFree((wolfssl_TI_Hash *)md5) ; + hashFree((wolfssl_TI_Hash *)md5); } -#endif /* NO_MD5 */ +#endif /* !NO_MD5 */ #if !defined(NO_SHA) -WOLFSSL_API int wc_InitSha(Sha* sha) +WOLFSSL_API int wc_InitSha_ex(Md5* sha, void* heap, int devId) { if (sha == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha); +} +WOLFSSL_API int wc_InitSha(Sha* sha) +{ + return wc_InitSha_ex(sha, NULL, INVALID_DEVID); } WOLFSSL_API int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha, data, len); } WOLFSSL_API int wc_ShaFinal(Sha* sha, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } WOLFSSL_API int wc_ShaGetHash(Sha* sha, byte* hash) { - return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; + return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } -WOLFSSL_API void wc_ShaRestorePos(Sha* s1, Sha* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; +WOLFSSL_API int wc_ShaCopy(Sha* src, Sha* dst) { + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } WOLFSSL_API void wc_ShaFree(Sha* sha) { - hashFree((wolfssl_TI_Hash *)sha) ; + hashFree((wolfssl_TI_Hash *)sha); } -#endif /* NO_SHA */ +#endif /* !NO_SHA */ -#if defined(HAVE_SHA224) -WOLFSSL_API int wc_InitSha224(Sha224* sha224) +#if defined(WOLFSSL_SHA224) +WOLFSSL_API int wc_InitSha224_ex(Sha224* sha224, void* heap, int devId) { if (sha224 == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha224) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha224); +} +WOLFSSL_API int wc_InitSha224(Sha224* sha224) +{ + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); } WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha224, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha224, data, len); } WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API int wc_Sha224GetHash(Sha224* sha224, byte* hash) { - return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; -} - -WOLFSSL_API void wc_Sha224RestorePos(Sha224* s1, Sha224* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; + return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API void wc_Sha224Free(Sha224* sha224) { - hashFree((wolfssl_TI_Hash *)sha224) ; + hashFree((wolfssl_TI_Hash *)sha224); } -#endif /* HAVE_SHA224 */ +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -WOLFSSL_API int wc_InitSha256(Sha256* sha256) +WOLFSSL_API int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) { if (sha256 == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha256) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha256); +} + +WOLFSSL_API int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); } WOLFSSL_API int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha256, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha256, data, len); } WOLFSSL_API int wc_Sha256Final(Sha256* sha256, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API int wc_Sha256GetHash(Sha256* sha256, byte* hash) { - return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; -} - -WOLFSSL_API void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; + return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API int wc_Sha256Hash(const byte* data, word32 len, byte*hash) { - return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; + return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API void wc_Sha256Free(Sha256* sha256) { - hashFree((wolfssl_TI_Hash *)sha256) ; + hashFree((wolfssl_TI_Hash *)sha256); } -#endif +#endif /* !NO_SHA256 */ #endif diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 7f545ee929..c51e7d1f51 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -59,16 +59,6 @@ #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - #ifndef NO_SHA /* PBKDF1 needs at least SHA available */ @@ -100,10 +90,22 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, switch (hashType) { #ifndef NO_MD5 case MD5: - wc_InitMd5(&md5); - wc_Md5Update(&md5, passwd, pLen); - wc_Md5Update(&md5, salt, sLen); - wc_Md5Final(&md5, buffer); + ret = wc_InitMd5(&md5); + if (ret != 0) { + return ret; + } + ret = wc_Md5Update(&md5, passwd, pLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Update(&md5, salt, sLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Final(&md5, buffer); + if (ret != 0) { + return ret; + } break; #endif /* NO_MD5 */ case SHA: @@ -124,8 +126,14 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, } #ifndef NO_MD5 else { - wc_Md5Update(&md5, buffer, hLen); - wc_Md5Final(&md5, buffer); + ret = wc_Md5Update(&md5, buffer, hLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Final(&md5, buffer); + if (ret != 0) { + return ret; + } } #endif } @@ -192,10 +200,11 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, return MEMORY_E; #endif - ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); - + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); if (ret == 0) { - while (kLen) { + ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); + + while (ret == 0 && kLen) { int currentLen; ret = wc_HmacUpdate(&hmac, salt, sLen); @@ -240,6 +249,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, kLen -= currentLen; i++; } + wc_HmacFree(&hmac); } #ifdef WOLFSSL_SMALL_STACK @@ -310,13 +320,28 @@ int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, case MD5: { Md5 md5; - wc_InitMd5(&md5); - wc_Md5Update(&md5, buffer, totalLen); - wc_Md5Final(&md5, Ai); + ret = wc_InitMd5(&md5); + if (ret != 0) { + break; + } + ret = wc_Md5Update(&md5, buffer, totalLen); + if (ret != 0) { + break; + } + ret = wc_Md5Final(&md5, Ai); + if (ret != 0) { + break; + } for (i = 1; i < iterations; i++) { - wc_Md5Update(&md5, Ai, u); - wc_Md5Final(&md5, Ai); + ret = wc_Md5Update(&md5, Ai, u); + if (ret != 0) { + break; + } + ret = wc_Md5Final(&md5, Ai); + if (ret != 0) { + break; + } } } break; @@ -328,12 +353,24 @@ int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, ret = wc_InitSha(&sha); if (ret != 0) break; - wc_ShaUpdate(&sha, buffer, totalLen); - wc_ShaFinal(&sha, Ai); + ret = wc_ShaUpdate(&sha, buffer, totalLen); + if (ret != 0) { + break; + } + ret = wc_ShaFinal(&sha, Ai); + if (ret != 0) { + break; + } for (i = 1; i < iterations; i++) { - wc_ShaUpdate(&sha, Ai, u); - wc_ShaFinal(&sha, Ai); + ret = wc_ShaUpdate(&sha, Ai, u); + if (ret != 0) { + break; + } + ret = wc_ShaFinal(&sha, Ai); + if (ret != 0) { + break; + } } } break; @@ -619,7 +656,7 @@ static void scryptSalsa(word32* out, word32* in) out[i] = in[i] + x[i]; #else for (i = 0; i < 16; i++) - out[i] = ByteReverseWord32(in[i] + x[i]); + out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]); #endif } @@ -769,15 +806,15 @@ int wc_scrypt(byte* output, const byte* passwd, int passLen, bSz = 128 * blockSize; blocksSz = bSz * parallel; - blocks = XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (blocks == NULL) goto end; /* Temporary for scryptROMix. */ - v = XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (v == NULL) goto end; /* Temporary for scryptBlockMix. */ - y = XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (y == NULL) goto end; diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c old mode 100755 new mode 100644 index 550d965031..1940bff1c2 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -33,13 +33,6 @@ #include -#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) -/* To maintain compatibility the default return value from CUSTOM_RAND_GENERATE is byte */ -#define CUSTOM_RAND_TYPE byte -#endif - -#define RNG_HEALTH_TEST_CHECK_SIZE (SHA256_DIGEST_SIZE * 4) - #ifdef HAVE_FIPS int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) @@ -47,31 +40,37 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) return GenerateSeed(os, seed, sz); } -int wc_InitRng(WC_RNG* rng) +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + (void)heap; + (void)devId; + return InitRng_fips(rng); +} + +int wc_InitRng(WC_RNG* rng) { return InitRng_fips(rng); } -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) { return RNG_GenerateBlock_fips(rng, b, sz); } -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) { return RNG_GenerateByte(rng, b); } -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG int wc_FreeRng(WC_RNG* rng) { return FreeRng_fips(rng); } - int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, @@ -80,113 +79,77 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) return RNG_HealthTest_fips(reseed, entropyA, entropyASz, entropyB, entropyBSz, output, outputSz); } -#endif /* HAVE_HASHDRBG || NO_RC4 */ -#else /* else build without fips */ -#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ -#include +#endif /* HAVE_HASHDRBG */ -/* Allow custom RNG system */ -#ifdef CUSTOM_RAND_GENERATE_BLOCK - -int wc_InitRng_ex(WC_RNG* rng, void* heap) -{ - (void)rng; - (void)heap; - return 0; -} - -int wc_InitRng(WC_RNG* rng) -{ - return wc_InitRng_ex(rng, NULL); -} - -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - (void)rng; - XMEMSET(output, 0, sz); - return CUSTOM_RAND_GENERATE_BLOCK(output, sz); -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} +#else /* else build without fips */ +#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - return 0; -} +#include +#include +#ifdef NO_INLINE + #include #else - -/* Use HASHDRGB with SHA256 */ -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - - #include - - #ifdef NO_INLINE - #include - #else - #define WOLFSSL_MISC_INCLUDED - #include - #endif -#endif /* HAVE_HASHDRBG || NO_RC4 */ + #define WOLFSSL_MISC_INCLUDED + #include +#endif #if defined(WOLFSSL_SGX) -#include + #include #elif defined(USE_WINDOWS_API) #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif #include #include +#elif defined(HAVE_WNR) + #include + #include + wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ + int wnr_timeout = 0; /* entropy timeout, mililseconds */ + int wnr_mutex_init = 0; /* flag for mutex init */ + wnr_context* wnr_ctx; /* global netRandom context */ +#elif defined(FREESCALE_KSDK_2_0_TRNG) + #include "fsl_trng.h" +#elif defined(FREESCALE_KSDK_2_0_RNGA) + #include "fsl_rnga.h" + +#elif defined(NO_DEV_RANDOM) +#elif defined(CUSTOM_RAND_GENERATE) +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) +#elif defined(WOLFSSL_GENSEED_FORTEST) +#elif defined(WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_IAR_ARM) +#elif defined(WOLFSSL_ROWLEY_ARM) +#elif defined(WOLFSSL_EMBOS) #else - #ifdef HAVE_WNR - #include - #include - wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ - int wnr_timeout = 0; /* entropy timeout, mililseconds */ - int wnr_mutex_init = 0; /* flag for mutex init */ - wnr_context* wnr_ctx; /* global netRandom context */ - #elif !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ - !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ - !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ - !defined(WOLFSSL_EMBOS) - #include - #ifndef EBSNET - #include - #endif - #elif defined(FREESCALE_KSDK_2_0_TRNG) - #include "fsl_trng.h" - #elif defined(FREESCALE_KSDK_2_0_RNGA) - #include "fsl_rnga.h" - #else - /* include headers that may be needed to get good seed */ + /* include headers that may be needed to get good seed */ + #include + #ifndef EBSNET + #include #endif -#endif /* USE_WINDOWS_API */ +#endif -#ifdef HAVE_INTEL_RDGEN - static int wc_InitRng_IntelRD(void) ; - #if defined(HAVE_HASHDRBG) || defined(NO_RC4) - static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) ; - #else - static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) ; + +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) + static void wc_InitRng_IntelRD(void); + #ifdef HAVE_INTEL_RDSEED + static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz); #endif - static word32 cpuid_check = 0 ; - static word32 cpuid_flags = 0 ; + #ifdef HAVE_INTEL_RDRAND + static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif + static word32 cpuid_check = 0; + static word32 cpuid_flags = 0; #define CPUID_RDRAND 0x4 #define CPUID_RDSEED 0x8 - #define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) - #define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) + #define IS_INTEL_RDRAND (cpuid_flags & CPUID_RDRAND) + #define IS_INTEL_RDSEED (cpuid_flags & CPUID_RDSEED) #endif - -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - /* Start NIST DRBG code */ +#ifdef HAVE_HASHDRBG #define OUTPUT_BLOCK_LEN (SHA256_DIGEST_SIZE) #define MAX_REQUEST_LEN (0x10000) @@ -209,12 +172,13 @@ int wc_FreeRng(WC_RNG* rng) #define DRBG_FAILED 2 #define DRBG_CONT_FAILED 3 +#define RNG_HEALTH_TEST_CHECK_SIZE (SHA256_DIGEST_SIZE * 4) + /* Verify max gen block len */ #if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length #endif - enum { drbgInitC = 0, drbgReseed = 1, @@ -229,6 +193,10 @@ typedef struct DRBG { word32 lastBlock; byte V[DRBG_SEED_LEN]; byte C[DRBG_SEED_LEN]; +#ifdef WOLFSSL_ASYNC_CRYPT + void* heap; + int devId; +#endif byte matchCount; } DRBG; @@ -241,60 +209,73 @@ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, const byte* inA, word32 inASz, const byte* inB, word32 inBSz) { + int ret = DRBG_FAILURE; byte ctr; int i; int len; word32 bits = (outSz * 8); /* reverse byte order */ Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; + DECLARE_VAR(digest, byte, SHA256_DIGEST_SIZE, drbg->heap); (void)drbg; - #ifdef LITTLE_ENDIAN_ORDER - bits = ByteReverseWord32(bits); - #endif +#ifdef WOLFSSL_ASYNC_CRYPT + if (digest == NULL) + return DRBG_FAILURE; +#endif + +#ifdef LITTLE_ENDIAN_ORDER + bits = ByteReverseWord32(bits); +#endif len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); - for (i = 0, ctr = 1; i < len; i++, ctr++) - { - if (wc_InitSha256(&sha) != 0) - return DRBG_FAILURE; - - if (wc_Sha256Update(&sha, &ctr, sizeof(ctr)) != 0) - return DRBG_FAILURE; - - if (wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)) != 0) - return DRBG_FAILURE; - - /* churning V is the only string that doesn't have the type added */ - if (type != drbgInitV) - if (wc_Sha256Update(&sha, &type, sizeof(type)) != 0) - return DRBG_FAILURE; - - if (wc_Sha256Update(&sha, inA, inASz) != 0) - return DRBG_FAILURE; - - if (inB != NULL && inBSz > 0) - if (wc_Sha256Update(&sha, inB, inBSz) != 0) - return DRBG_FAILURE; + for (i = 0, ctr = 1; i < len; i++, ctr++) { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&sha); + #endif + if (ret != 0) + break; - if (wc_Sha256Final(&sha, digest) != 0) - return DRBG_FAILURE; + if (ret == 0) + ret = wc_Sha256Update(&sha, &ctr, sizeof(ctr)); + if (ret == 0) + ret = wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)); - if (outSz > OUTPUT_BLOCK_LEN) { - XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); - outSz -= OUTPUT_BLOCK_LEN; - out += OUTPUT_BLOCK_LEN; + if (ret == 0) { + /* churning V is the only string that doesn't have the type added */ + if (type != drbgInitV) + ret = wc_Sha256Update(&sha, &type, sizeof(type)); } - else { - XMEMCPY(out, digest, outSz); + if (ret == 0) + ret = wc_Sha256Update(&sha, inA, inASz); + if (ret == 0) { + if (inB != NULL && inBSz > 0) + ret = wc_Sha256Update(&sha, inB, inBSz); + } + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + + wc_Sha256Free(&sha); + if (ret == 0) { + if (outSz > OUTPUT_BLOCK_LEN) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); + outSz -= OUTPUT_BLOCK_LEN; + out += OUTPUT_BLOCK_LEN; + } + else { + XMEMCPY(out, digest, outSz); + } } } - ForceZero(digest, sizeof(digest)); - return DRBG_SUCCESS; -} + ForceZero(digest, SHA256_DIGEST_SIZE); + + FREE_VAR(digest, drbg->heap); + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Reseed(DRBG* drbg, const byte* entropy, word32 entropySz) @@ -331,16 +312,16 @@ static INLINE void array_add_one(byte* data, word32 dataSz) } } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) { + int ret = DRBG_FAILURE; byte data[DRBG_SEED_LEN]; int i; int len; word32 checkBlock; Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; + DECLARE_VAR(digest, byte, SHA256_DIGEST_SIZE, drbg->heap); /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ @@ -351,48 +332,55 @@ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) XMEMCPY(data, V, sizeof(data)); for (i = 0; i < len; i++) { - if (wc_InitSha256(&sha) != 0 || - wc_Sha256Update(&sha, data, sizeof(data)) != 0 || - wc_Sha256Final(&sha, digest) != 0) { - - return DRBG_FAILURE; - } + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&sha); + #endif + if (ret == 0) + ret = wc_Sha256Update(&sha, data, sizeof(data)); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + wc_Sha256Free(&sha); - XMEMCPY(&checkBlock, digest, sizeof(word32)); - if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { - if (drbg->matchCount == 1) { - return DRBG_CONT_FAILURE; + if (ret == 0) { + XMEMCPY(&checkBlock, digest, sizeof(word32)); + if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { + if (drbg->matchCount == 1) { + return DRBG_CONT_FAILURE; + } + else { + if (i == len) { + len++; + } + drbg->matchCount = 1; + } } else { - if (i == len) { - len++; - } - drbg->matchCount = 1; + drbg->matchCount = 0; + drbg->lastBlock = checkBlock; } - } - else { - drbg->matchCount = 0; - drbg->lastBlock = checkBlock; - } - if (out != NULL) { - if (outSz >= OUTPUT_BLOCK_LEN) { - XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); - outSz -= OUTPUT_BLOCK_LEN; - out += OUTPUT_BLOCK_LEN; - array_add_one(data, DRBG_SEED_LEN); - } - else if (out != NULL && outSz != 0) { - XMEMCPY(out, digest, outSz); - outSz = 0; + if (out != NULL && outSz != 0) { + if (outSz >= OUTPUT_BLOCK_LEN) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); + outSz -= OUTPUT_BLOCK_LEN; + out += OUTPUT_BLOCK_LEN; + array_add_one(data, DRBG_SEED_LEN); + } + else { + XMEMCPY(out, digest, outSz); + outSz = 0; + } } } } ForceZero(data, sizeof(data)); - return DRBG_SUCCESS; -} + FREE_VAR(digest, drbg->heap); + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) { @@ -416,13 +404,12 @@ static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) } } - /* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) { int ret = DRBG_NEED_RESEED; Sha256 sha; - byte digest[SHA256_DIGEST_SIZE]; + DECLARE_VAR(digest, byte, SHA256_DIGEST_SIZE, drbg->heap); if (drbg->reseedCtr != RESEED_INTERVAL) { byte type = drbgGenerateH; @@ -430,19 +417,26 @@ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) ret = Hash_gen(drbg, out, outSz, drbg->V); if (ret == DRBG_SUCCESS) { - if (wc_InitSha256(&sha) != 0 || - wc_Sha256Update(&sha, &type, sizeof(type)) != 0 || - wc_Sha256Update(&sha, drbg->V, sizeof(drbg->V)) != 0 || - wc_Sha256Final(&sha, digest) != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_InitSha256_ex(&sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&sha); + #endif + if (ret == 0) + ret = wc_Sha256Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha256Update(&sha, drbg->V, sizeof(drbg->V)); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); - ret = DRBG_FAILURE; - } - else { - array_add(drbg->V, sizeof(drbg->V), digest, sizeof(digest)); + wc_Sha256Free(&sha); + + if (ret == 0) { + array_add(drbg->V, sizeof(drbg->V), digest, SHA256_DIGEST_SIZE); array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C)); - #ifdef LITTLE_ENDIAN_ORDER - reseedCtr = ByteReverseWord32(reseedCtr); - #endif + #ifdef LITTLE_ENDIAN_ORDER + reseedCtr = ByteReverseWord32(reseedCtr); + #endif array_add(drbg->V, sizeof(drbg->V), (byte*)&reseedCtr, sizeof(reseedCtr)); ret = DRBG_SUCCESS; @@ -450,19 +444,28 @@ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) drbg->reseedCtr++; } } - ForceZero(digest, sizeof(digest)); + ForceZero(digest, SHA256_DIGEST_SIZE); - return ret; -} + FREE_VAR(digest, drbg->heap); + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, - const byte* nonce, word32 nonceSz) + const byte* nonce, word32 nonceSz, + void* heap, int devId) { int ret = DRBG_FAILURE; XMEMSET(drbg, 0, sizeof(DRBG)); +#ifdef WOLFSSL_ASYNC_CRYPT + drbg->heap = heap; + drbg->devId = devId; +#else + (void)heap; + (void)devId; +#endif if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz, nonce, nonceSz) == DRBG_SUCCESS && @@ -478,7 +481,6 @@ static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, return ret; } - /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Uninstantiate(DRBG* drbg) { @@ -493,72 +495,105 @@ static int Hash_DRBG_Uninstantiate(DRBG* drbg) return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } - +#endif /* HAVE_HASHDRBG */ /* End NIST DRBG Code */ -/* Get seed and key cipher */ -int wc_InitRng_ex(WC_RNG* rng, void* heap) +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) { - int ret = BAD_FUNC_ARG; + int ret = RNG_FAILURE_E; + + if (rng == NULL) + return BAD_FUNC_ARG; - if (rng != NULL) { #ifdef WOLFSSL_HEAP_TEST - rng->heap = (void*)WOLFSSL_HEAP_TEST; - (void)heap; + rng->heap = (void*)WOLFSSL_HEAP_TEST; + (void)heap; #else - rng->heap = heap; + rng->heap = heap; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + rng->devId = devId; +#else + (void)devId; #endif - if (wc_RNG_HealthTestLocal(0) == 0) { - byte entropy[ENTROPY_NONCE_SZ]; - - rng->drbg = - (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, - DYNAMIC_TYPE_RNG); - if (rng->drbg == NULL) { - ret = MEMORY_E; - } - /* This doesn't use a separate nonce. The entropy input will be - * the default size plus the size of the nonce making the seed - * size. */ - else if (wc_GenerateSeed(&rng->seed, - entropy, ENTROPY_NONCE_SZ) == 0 && - Hash_DRBG_Instantiate(rng->drbg, - entropy, ENTROPY_NONCE_SZ, NULL, 0) == DRBG_SUCCESS) { - ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); - } - else - ret = DRBG_FAILURE; +#ifdef HAVE_HASHDRBG + /* init the DBRG to known values */ + rng->drbg = NULL; + rng->status = DRBG_NOT_INIT; +#endif - ForceZero(entropy, ENTROPY_NONCE_SZ); - } - else - ret = DRBG_CONT_FAILURE; +#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* init the intel RD seed and/or rand */ + wc_InitRng_IntelRD(); +#endif - if (ret == DRBG_SUCCESS) { - rng->status = DRBG_OK; - ret = 0; - } - else if (ret == DRBG_CONT_FAILURE) { - rng->status = DRBG_CONT_FAILED; - ret = DRBG_CONT_FIPS_E; - } - else if (ret == DRBG_FAILURE) { - rng->status = DRBG_FAILED; - ret = RNG_FAILURE_E; + /* configure async RNG source if available */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, + rng->heap, rng->devId); + if (ret != 0) + return ret; +#endif + + +#ifdef HAVE_INTEL_RDRAND + /* if CPU supports RDRAND, use it directly and by-pass DRBG init */ + if (IS_INTEL_RDRAND) + return 0; +#endif + +#ifdef HAVE_HASHDRBG + if (wc_RNG_HealthTestLocal(0) == 0) { + DECLARE_VAR(entropy, byte, ENTROPY_NONCE_SZ, rng->heap); + + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, + DYNAMIC_TYPE_RNG); + if (rng->drbg == NULL) { + ret = MEMORY_E; } - else { - rng->status = DRBG_FAILED; + /* This doesn't use a separate nonce. The entropy input will be + * the default size plus the size of the nonce making the seed + * size. */ + else if (wc_GenerateSeed(&rng->seed, entropy, ENTROPY_NONCE_SZ) == 0 && + Hash_DRBG_Instantiate(rng->drbg, entropy, ENTROPY_NONCE_SZ, + NULL, 0, rng->heap, devId) == DRBG_SUCCESS) { + ret = Hash_DRBG_Generate(rng->drbg, NULL, 0); } + else + ret = DRBG_FAILURE; + + ForceZero(entropy, ENTROPY_NONCE_SZ); + FREE_VAR(entropy, rng->heap); + } + else + ret = DRBG_CONT_FAILURE; + + if (ret == DRBG_SUCCESS) { + rng->status = DRBG_OK; + ret = 0; + } + else if (ret == DRBG_CONT_FAILURE) { + rng->status = DRBG_CONT_FAILED; + ret = DRBG_CONT_FIPS_E; } + else if (ret == DRBG_FAILURE) { + rng->status = DRBG_FAILED; + ret = RNG_FAILURE_E; + } + else { + rng->status = DRBG_FAILED; + } +#endif /* HAVE_HASHDRBG */ return ret; } int wc_InitRng(WC_RNG* rng) { - return wc_InitRng_ex(rng, NULL); + return wc_InitRng_ex(rng, NULL, INVALID_DEVID); } @@ -567,14 +602,33 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) { int ret; - if (rng == NULL || output == NULL || sz > RNG_MAX_BLOCK_LEN) + if (rng == NULL || output == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_INTEL_RDRAND + if (IS_INTEL_RDRAND) + return wc_GenerateRand_IntelRD(NULL, output, sz); +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { + return NitroxRngGenerateBlock(rng, output, sz); + } +#endif + +#ifdef CUSTOM_RAND_GENERATE_BLOCK + XMEMSET(output, 0, sz); + return CUSTOM_RAND_GENERATE_BLOCK(output, sz); +#endif + +#ifdef HAVE_HASHDRBG + if (sz > RNG_MAX_BLOCK_LEN) return BAD_FUNC_ARG; if (rng->status != DRBG_OK) return RNG_FAILURE_E; ret = Hash_DRBG_Generate(rng->drbg, output, sz); - if (ret == DRBG_NEED_RESEED) { if (wc_RNG_HealthTestLocal(1) == 0) { byte entropy[ENTROPY_SZ]; @@ -607,6 +661,12 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = RNG_FAILURE_E; rng->status = DRBG_FAILED; } +#else + + /* if we get here then there is an RNG configuration error */ + ret = RNG_FAILURE_E; + +#endif /* HAVE_HASHDRBG */ return ret; } @@ -620,26 +680,31 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) int wc_FreeRng(WC_RNG* rng) { - int ret = BAD_FUNC_ARG; + int ret = 0; - if (rng != NULL) { - if (rng->drbg != NULL) { - if (Hash_DRBG_Uninstantiate(rng->drbg) == DRBG_SUCCESS) - ret = 0; - else - ret = RNG_FAILURE_E; + if (rng == NULL) + return BAD_FUNC_ARG; - XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); - rng->drbg = NULL; - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG); +#endif + +#ifdef HAVE_HASHDRBG + if (rng->drbg != NULL) { + if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS) + ret = RNG_FAILURE_E; - rng->status = DRBG_NOT_INIT; + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg = NULL; } + rng->status = DRBG_NOT_INIT; +#endif /* HAVE_HASHDRBG */ + return ret; } - +#ifdef HAVE_HASHDRBG int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, byte* output, word32 outputSz) @@ -671,7 +736,8 @@ int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, drbg = &drbg_var; #endif - if (Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, NULL, 0) != 0) { + if (Hash_DRBG_Instantiate(drbg, entropyA, entropyASz, NULL, 0, NULL, + INVALID_DEVID) != 0) { goto exit_rng_ht; } @@ -801,96 +867,7 @@ static int wc_RNG_HealthTestLocal(int reseed) return ret; } - -#else /* HAVE_HASHDRBG || NO_RC4 */ - -/* Get seed and key cipher */ -int wc_InitRng(WC_RNG* rng) -{ - int ret; -#ifdef WOLFSSL_SMALL_STACK - byte* key; - byte* junk; -#else - byte key[32]; - byte junk[256]; -#endif - -#ifdef HAVE_INTEL_RDGEN - wc_InitRng_IntelRD(); - if(IS_INTEL_RDRAND) return 0; -#endif - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, INVALID_DEVID); - if (ret != 0) return ret; -#endif - -#ifdef WOLFSSL_SMALL_STACK - key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - return MEMORY_E; - - junk = (byte*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (junk == NULL) { - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - ret = wc_GenerateSeed(&rng->seed, key, 32); - - if (ret == 0) { - wc_Arc4SetKey(&rng->cipher, key, sizeof(key)); - - ret = wc_RNG_GenerateBlock(rng, junk, 256); /*rid initial state*/ - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(junk, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -/* place a generated block in output */ -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ -#ifdef HAVE_INTEL_RDGEN - if(IS_INTEL_RDRAND) - return wc_GenerateRand_IntelRD(NULL, output, sz) ; -#endif -#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); - - return 0; -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} - - -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - wolfAsync_DevCtxFree(&rng->asyncDev); -#endif - - return 0; -} - -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ #ifdef HAVE_WNR @@ -991,7 +968,7 @@ int wc_FreeNetRandom(void) #endif /* HAVE_WNR */ -#if defined(HAVE_INTEL_RDGEN) +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) #ifndef _MSC_VER #define cpuid(reg, leaf, sub)\ @@ -1015,36 +992,40 @@ int wc_FreeNetRandom(void) #define EDX 3 static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; + int got_intel_cpu = 0; unsigned int reg[5]; - reg[4] = '\0' ; + reg[4] = '\0'; cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { + if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) + { got_intel_cpu = 1; } if (got_intel_cpu) { cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; + return ((reg[num] >> bit) & 0x1); } - return 0 ; + return 0; } -static int wc_InitRng_IntelRD() -{ - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ;} - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ;} - cpuid_check = 1 ; +static void wc_InitRng_IntelRD(void) { + if (cpuid_check==0) { + if (cpuid_flag(1, 0, ECX, 30)) { cpuid_flags |= CPUID_RDRAND; } + if (cpuid_flag(7, 0, EBX, 18)) { cpuid_flags |= CPUID_RDSEED; } + cpuid_check = 1; } - return 1 ; } -#define INTELRD_RETRY 32 +#ifdef WOLFSSL_ASYNC_CRYPT + /* need more retries if multiple cores */ + #define INTELRD_RETRY (32 * 8) +#else + #define INTELRD_RETRY 32 +#endif -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_INTEL_RDSEED /* return 0 on success */ static INLINE int IntelRDseed64(word64* seed) @@ -1052,97 +1033,110 @@ static INLINE int IntelRDseed64(word64* seed) unsigned char ok; __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); - if(ok){ - return 0 ; - } else - return 1; + return (ok) ? 0 : -1; } /* return 0 on success */ static INLINE int IntelRDseed64_r(word64* rnd) { int i; - for(i=0; i 0; sz-=8, output+=8) { - if(IS_INTEL_RDSEED)ret = IntelRDseed64_r((word64*)output); - else return 1 ; - if(ret) - return 1 ; - } - if(sz == 0)return 0 ; - - if(IS_INTEL_RDSEED)ret = IntelRDseed64_r(&rndTmp) ; - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; + int ret; + word64 rndTmp; + + (void)os; + + if (!IS_INTEL_RDSEED) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDseed64_r((word64*)output); + if (ret != 0) + return ret; + } + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDseed64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); + return 0; } -#else /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_INTEL_RDSEED */ + +#ifdef HAVE_INTEL_RDRAND /* return 0 on success */ -static INLINE int IntelRDrand32(unsigned int *rnd) +static INLINE int IntelRDrand64(word64 *rnd) { - int rdrand; unsigned char ok ; - __asm__ volatile("rdrand %0; setc %1":"=r"(rdrand), "=qm"(ok)); - if(ok){ - *rnd = rdrand; - return 0 ; - } else - return 1; + unsigned char ok; + + __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok)); + + return (ok) ? 0 : -1; } /* return 0 on success */ -static INLINE int IntelRDrand32_r(unsigned int *rnd) +static INLINE int IntelRDrand64_r(word64 *rnd) { - int i ; - for(i=0; i 0; sz-=4, output+=4) { - if(IS_INTEL_RDRAND)ret = IntelRDrand32_r((word32 *)output); - else return 1 ; - if(ret) - return 1 ; - } - if(sz == 0)return 0 ; - - if(IS_INTEL_RDRAND)ret = IntelRDrand32_r(&rndTmp); - else return 1 ; - if(ret) - return 1 ; - XMEMCPY(output, &rndTmp, sz) ; + int ret; + word64 rndTmp; + + (void)os; + + if (!IS_INTEL_RDRAND) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDrand64_r((word64 *)output); + if (ret != 0) + return ret; + } + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDrand64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); + return 0; } -#endif /* defined(HAVE_HASHDRBG) || defined(NO_RC4) */ -#endif /* HAVE_INTEL_RDGEN */ +#endif /* HAVE_INTEL_RDRAND */ +#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */ -/* wc_GenerateSeed Implementations */ +/* Begin wc_GenerateSeed Implementations */ #if defined(CUSTOM_RAND_GENERATE_SEED) /* Implement your own random generation function @@ -1169,6 +1163,37 @@ static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz); } +#elif defined(CUSTOM_RAND_GENERATE) + + /* Implement your own random generation function + * word32 rand_gen(void); + * #define CUSTOM_RAND_GENERATE rand_gen */ + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i = 0; + + (void)os; + + while (i < sz) + { + /* If not aligned or there is odd/remainder */ + if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz || + ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0 + ) { + /* Single byte at a time */ + output[i++] = (byte)CUSTOM_RAND_GENERATE(); + } + else { + /* Use native 8, 16, 32 or 64 copy instruction */ + *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE(); + i += sizeof(CUSTOM_RAND_TYPE); + } + } + + return 0; + } + #elif defined(WOLFSSL_SGX) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) @@ -1234,49 +1259,50 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #elif defined(MICROCHIP_PIC32) -#ifdef MICROCHIP_MPLAB_HARMONY - #define PIC32_SEED_COUNT _CP0_GET_COUNT -#else - #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) - #include + #ifdef MICROCHIP_MPLAB_HARMONY + #define PIC32_SEED_COUNT _CP0_GET_COUNT + #else + #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) + #include + #endif + #define PIC32_SEED_COUNT ReadCoreTimer #endif - #define PIC32_SEED_COUNT ReadCoreTimer -#endif + #ifdef WOLFSSL_MIC32MZ_RNG #include "xc.h" int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int i ; - byte rnd[8] ; - word32 *rnd32 = (word32 *)rnd ; - word32 size = sz ; - byte* op = output ; + int i; + byte rnd[8]; + word32 *rnd32 = (word32 *)rnd; + word32 size = sz; + byte* op = output; /* This part has to be replaced with better random seed */ RNGNUMGEN1 = ReadCoreTimer(); RNGPOLY1 = ReadCoreTimer(); RNGPOLY2 = ReadCoreTimer(); RNGNUMGEN2 = ReadCoreTimer(); -#ifdef DEBUG_WOLFSSL - printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2) ; -#endif + #ifdef DEBUG_WOLFSSL + printf("GenerateSeed::Seed=%08x, %08x\n", RNGNUMGEN1, RNGNUMGEN2); + #endif RNGCONbits.PLEN = 0x40; RNGCONbits.PRNGEN = 1; for(i=0; i<5; i++) { /* wait for RNGNUMGEN ready */ - volatile int x ; - x = RNGNUMGEN1 ; - x = RNGNUMGEN2 ; + volatile int x; + x = RNGNUMGEN1; + x = RNGNUMGEN2; } do { rnd32[0] = RNGNUMGEN1; rnd32[1] = RNGNUMGEN2; for(i=0; i<8; i++, op++) { - *op = rnd[i] ; - size -- ; - if(size==0)break ; + *op = rnd[i]; + size --; + if(size==0)break; } - } while(size) ; + } while(size); return 0; } #else /* WOLFSSL_MIC32MZ_RNG */ @@ -1391,7 +1417,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return RAN_BLOCK_E; } } - + #elif defined(FREESCALE_KSDK_2_0_RNGA) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) @@ -1418,46 +1444,15 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #else - #warning "write a real random seed!!!!, just for testing now" - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - return 0; - } + #define USE_TEST_GENSEED #endif /* FREESCALE_K70_RNGA */ -#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) \ - || defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) \ - || defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2)\ - || defined(WOLFSSL_GENSEED_FORTEST) - -#ifndef _MSC_VER -#warning "write a real random seed!!!!, just for testing now" -#else -#pragma message("Warning: write a real random seed!!!!, just for testing now") -#endif - -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - word32 i; - for (i = 0; i < sz; i++ ) - output[i] = i; - - (void)os; - - return 0; -} - #elif defined(STM32F2_RNG) || defined(STM32F4_RNG) /* * wc_Generate a RNG seed using the hardware random number generator * on the STM32F2/F4. */ -#ifdef WOLFSSL_STM32_CUBEMX + #ifdef WOLFSSL_STM32_CUBEMX int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { RNG_HandleTypeDef hrng; @@ -1478,7 +1473,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#else + #else int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { int i; @@ -1500,22 +1495,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#endif /* WOLFSSL_STM32_CUBEMX */ - -#elif defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || defined(MBED) \ - || defined(WOLFSSL_EMBOS) - - #warning "write a real random seed!!!!, just for testing now" - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - int i; - - for (i = 0; i < sz; i++ ) - output[i] = i; - - return 0; - } + #endif /* WOLFSSL_STM32_CUBEMX */ #elif defined(WOLFSSL_TIRTOS) @@ -1625,40 +1605,9 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return 0; } -#elif defined(CUSTOM_RAND_GENERATE) - - /* Implement your own random generation function - * word32 rand_gen(void); - * #define CUSTOM_RAND_GENERATE rand_gen */ - - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - word32 i = 0; - - (void)os; - - while (i < sz) - { - /* If not aligned or there is odd/remainder */ - if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz || - ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0 - ) { - /* Single byte at a time */ - output[i++] = (byte)CUSTOM_RAND_GENERATE(); - } - else { - /* Use native 8, 16, 32 or 64 copy instruction */ - *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE(); - i += sizeof(CUSTOM_RAND_TYPE); - } - } - - return 0; - } - #elif defined(WOLFSSL_ATMEL) #include - + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { int ret = 0; @@ -1673,93 +1622,145 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return ret; } -#elif defined(NO_DEV_RANDOM) +#elif defined(INTIME_RTOS) + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; -#error "you need to write an os specific wc_GenerateSeed() here" + (void)os; -/* -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - return 0; -} -*/ + if (output == NULL) { + return BUFFER_E; + } + /* Note: Investigate better solution */ + /* no return to check */ + arc4random_buf(output, sz); + + return ret; + } #elif defined(IDIRECT_DEV_RANDOM) -extern int getRandom( int sz, unsigned char *output ); + extern int getRandom( int sz, unsigned char *output ); -int GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int num_bytes_returned = 0; + int GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int num_bytes_returned = 0; - num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); + num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); - return 0; -} + return 0; + } +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) + /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ -#else /* !USE_WINDOWS_API && !HAVE_RPT_SYS && !MICRIUM && !NO_DEV_RANDOM */ +#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \ + defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) || \ + defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || \ + defined(MBED) || defined(WOLFSSL_EMBOS) || \ + defined(WOLFSSL_GENSEED_FORTEST) -/* may block */ -int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) -{ - int ret = 0; + /* these platforms do not have a default random seed and + you'll need to implement your own wc_GenerateSeed or define via + CUSTOM_RAND_GENERATE_BLOCK */ + #define USE_TEST_GENSEED -#if defined(HAVE_INTEL_RDGEN) && (defined(HAVE_HASHDRBG) || defined(NO_RC4)) - wc_InitRng_IntelRD() ; /* set cpuid_flags if not yet */ - if(IS_INTEL_RDSEED) { - ret = wc_GenerateSeed_IntelRD(NULL, output, sz); - if (ret == 0) { - /* success, we're done */ - return ret; - } -#ifdef FORCE_FAILURE_RDSEED - /* don't fallback to /dev/urandom */ - return ret; -#else - /* fallback to /dev/urandom attempt */ - ret = 0; -#endif - } +#elif defined(NO_DEV_RANDOM) -#endif + #error "you need to write an os specific wc_GenerateSeed() here" - os->fd = open("/dev/urandom",O_RDONLY); - if (os->fd == -1) { - /* may still have /dev/random */ - os->fd = open("/dev/random",O_RDONLY); - if (os->fd == -1) - return OPEN_RAN_E; + /* + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + return 0; } + */ - while (sz) { - int len = (int)read(os->fd, output, sz); - if (len == -1) { - ret = READ_RAN_E; - break; +#else + + /* may block */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + #ifdef HAVE_INTEL_RDSEED + if (IS_INTEL_RDSEED) { + ret = wc_GenerateSeed_IntelRD(NULL, output, sz); + if (ret == 0) { + /* success, we're done */ + return ret; + } + #ifdef FORCE_FAILURE_RDSEED + /* don't fallback to /dev/urandom */ + return ret; + #else + /* fallback to /dev/urandom attempt */ + ret = 0; + #endif } - sz -= len; - output += len; + #endif /* HAVE_INTEL_RDSEED */ - if (sz) { -#ifdef BLOCKING - sleep(0); /* context switch */ -#else - ret = RAN_BLOCK_E; - break; -#endif + os->fd = open("/dev/urandom",O_RDONLY); + if (os->fd == -1) { + /* may still have /dev/random */ + os->fd = open("/dev/random",O_RDONLY); + if (os->fd == -1) + return OPEN_RAN_E; + } + + while (sz) { + int len = (int)read(os->fd, output, sz); + if (len == -1) { + ret = READ_RAN_E; + break; + } + + sz -= len; + output += len; + + if (sz) { + #ifdef BLOCKING + sleep(0); /* context switch */ + #else + ret = RAN_BLOCK_E; + break; + #endif + } } + close(os->fd); + + return ret; } - close(os->fd); - return ret; -} +#endif + +#ifdef USE_TEST_GENSEED + #ifndef _MSC_VER + #warning "write a real random seed!!!!, just for testing now" + #else + #pragma message("Warning: write a real random seed!!!!, just for testing now") + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + for (i = 0; i < sz; i++ ) + output[i] = i; + + (void)os; + + return 0; + } +#endif + +/* End wc_GenerateSeed */ -#endif /* USE_WINDOWS_API */ -#endif /* CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ #endif /* HAVE_FIPS */ - diff --git a/wolfcrypt/src/ripemd.c b/wolfcrypt/src/ripemd.c index 9da179e4ef..0958ea4773 100644 --- a/wolfcrypt/src/ripemd.c +++ b/wolfcrypt/src/ripemd.c @@ -37,19 +37,14 @@ #include #endif +#include -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; +int wc_InitRipeMd(RipeMd* ripemd) +{ + if (ripemd == NULL) { + return BAD_FUNC_ARG; } -#endif /* WOLFSSL_HAVE_MIN */ - -void wc_InitRipeMd(RipeMd* ripemd) -{ ripemd->digest[0] = 0x67452301L; ripemd->digest[1] = 0xEFCDAB89L; ripemd->digest[2] = 0x98BADCFEL; @@ -59,6 +54,8 @@ void wc_InitRipeMd(RipeMd* ripemd) ripemd->buffLen = 0; ripemd->loLen = 0; ripemd->hiLen = 0; + + return 0; } @@ -282,10 +279,16 @@ static INLINE void AddLength(RipeMd* ripemd, word32 len) } -void wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) +int wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) { /* do block size increments */ - byte* local = (byte*)ripemd->buffer; + byte* local; + + if (ripemd == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + local = (byte*)ripemd->buffer; while (len) { word32 add = min(len, RIPEMD_BLOCK_SIZE - ripemd->buffLen); @@ -305,12 +308,19 @@ void wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) ripemd->buffLen = 0; } } + return 0; } -void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) +int wc_RipeMdFinal(RipeMd* ripemd, byte* hash) { - byte* local = (byte*)ripemd->buffer; + byte* local; + + if (ripemd == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)ripemd->buffer; AddLength(ripemd, ripemd->buffLen); /* before adding pads */ @@ -349,7 +359,7 @@ void wc_RipeMdFinal(RipeMd* ripemd, byte* hash) #endif XMEMCPY(hash, ripemd->digest, RIPEMD_DIGEST_SIZE); - wc_InitRipeMd(ripemd); /* reset state */ + return wc_InitRipeMd(ripemd); /* reset state */ } diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c old mode 100644 new mode 100755 index df475d800f..7f9da78b73 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -148,11 +148,6 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, #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_STATE_NONE = 0, @@ -167,18 +162,18 @@ enum { static void wc_RsaCleanup(RsaKey* key) { - if (key && key->tmp) { + if (key && key->data) { /* make sure any allocated memory is free'd */ - if (key->tmpIsAlloc) { + if (key->dataIsAlloc) { if (key->type == RSA_PRIVATE_DECRYPT || key->type == RSA_PRIVATE_ENCRYPT) { - ForceZero(key->tmp, key->tmpLen); + ForceZero(key->data, key->dataLen); } - XFREE(key->tmp, key->heap, DYNAMIC_TYPE_RSA); - key->tmpIsAlloc = 0; + XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 0; } - key->tmp = NULL; - key->tmpLen = 0; + key->data = NULL; + key->dataLen = 0; } } @@ -190,46 +185,41 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) 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; - key->tmpIsAlloc = 0; + key->data = NULL; + key->dataLen = 0; + key->dataIsAlloc = 0; #ifdef WC_RSA_BLINDING key->rng = NULL; #endif #ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { + #ifdef WOLFSSL_CERT_GEN + XMEMSET(&key->certSignCtx, 0, sizeof(CertSignCtx)); + #endif + + #ifdef WC_ASYNC_ENABLE_RSA /* handle as async */ ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA, - devId); - if (ret == 0) { - ret = InitAsyncRsaKey(key); - } - } - else -#endif - { - /* For normal math defer the memory allocations */ - #ifndef USE_FAST_MATH - key->n.dp = key->e.dp = 0; /* public alloc parts */ - key->d.dp = key->p.dp = 0; /* private alloc parts */ - key->q.dp = key->dP.dp = 0; - key->u.dp = key->dQ.dp = 0; - #else - mp_init(&key->n); - mp_init(&key->e); - mp_init(&key->d); - mp_init(&key->p); - mp_init(&key->q); - mp_init(&key->dP); - mp_init(&key->dQ); - mp_init(&key->u); - #endif /* USE_FAST_MATH */ + key->heap, devId); + if (ret != 0) + return ret; + #endif /* WC_ASYNC_ENABLE_RSA */ +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) + return ret; + + ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u); + if (ret != MP_OKAY) { + mp_clear(&key->n); + mp_clear(&key->e); + return ret; } return ret; @@ -250,31 +240,35 @@ int wc_FreeRsaKey(RsaKey* key) wc_RsaCleanup(key); -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - ret = FreeAsyncRsaKey(key); - wolfAsync_DevCtxFree(&key->asyncDev); - } - else +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA); #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); - } + + 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); + } + /* private part */ + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->dP); + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); + + /* public part */ + mp_clear(&key->e); + mp_clear(&key->n); return ret; } -#ifndef WC_NO_RSA_OAEP +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS) /* Uses MGF1 standard as a mask generation function hType: hash type used seed: seed to use for generating mask @@ -585,6 +579,50 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, } #endif /* !WC_NO_RSA_OAEP */ +#ifdef WC_RSA_PSS +static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf, + void* heap) +{ + int ret; + int hLen, i; + byte* s; + byte* m; + byte* h; + byte salt[WC_MAX_DIGEST_SIZE]; + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + s = m = pkcsBlock; + XMEMSET(m, 0, 8); + m += 8; + XMEMCPY(m, input, inputLen); + m += inputLen; + if ((ret = wc_RNG_GenerateBlock(rng, salt, hLen)) != 0) + return ret; + XMEMCPY(m, salt, hLen); + m += hLen; + + h = pkcsBlock + pkcsBlockLen - 1 - hLen; + if ((ret = wc_Hash(hType, s, (word32)(m - s), h, hLen)) != 0) + return ret; + pkcsBlock[pkcsBlockLen - 1] = 0xbc; + + ret = RsaMGF(mgf, h, hLen, pkcsBlock, pkcsBlockLen - hLen - 1, heap); + if (ret != 0) + return ret; + pkcsBlock[0] &= 0x7f; + + m = pkcsBlock + pkcsBlockLen - 1 - hLen - hLen - 1; + *(m++) ^= 0x01; + for (i = 0; i < hLen; i++) + m[i] ^= salt[i]; + + return 0; +} +#endif static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, word32 pkcsBlockLen, byte padValue, WC_RNG* rng) @@ -646,18 +684,27 @@ static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, switch (padType) { case WC_RSA_PKCSV15_PAD: - //WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/ ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, - padValue, rng); + padValue, rng); break; #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - //WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, - padValue, rng, hType, mgf, optLabel, labelLen, heap); + padValue, rng, hType, mgf, optLabel, labelLen, heap); + break; + #endif + + #ifdef WC_RSA_PSS + case WC_RSA_PSS_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PSS padding"); + ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, + rng, hType, mgf, heap); break; #endif + default: WOLFSSL_MSG("Unknown RSA Pad Type"); ret = RSA_PAD_E; @@ -707,7 +754,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, /* find seedMask value */ if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) { - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -761,6 +808,53 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, } #endif /* WC_NO_RSA_OAEP */ +#ifdef WC_RSA_PSS +static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + void* heap) +{ + int ret; + byte* tmp; + int hLen, i; + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + if (pkcsBlock[pkcsBlockLen - 1] != 0xbc) + return BAD_PADDING_E; + + tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + if ((ret = RsaMGF(mgf, pkcsBlock + pkcsBlockLen - 1 - hLen, hLen, + tmp, pkcsBlockLen - 1 - hLen, heap)) != 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + tmp[0] &= 0x7f; + for (i = 0; i < (int)(pkcsBlockLen - 1 - hLen - hLen - 1); i++) { + if (tmp[i] != pkcsBlock[i]) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_PADDING_E; + } + } + if (tmp[i] != (pkcsBlock[i] ^ 0x01)) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_PADDING_E; + } + for (i++; i < (int)(pkcsBlockLen - 1 - hLen); i++) + pkcsBlock[i] ^= tmp[i]; + + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + + *output = pkcsBlock + i; + return hLen; +} +#endif /* UnPad plaintext, set start to *output, return length of plaintext, * < 0 on error */ @@ -792,7 +886,7 @@ static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, while (i maxOutputLen) || invalid; if (invalid) { - WOLFSSL_MSG("RsaUnPad error, bad formatting"); + WOLFSSL_MSG("RsaUnPad error, invalid formatting"); return RSA_PAD_E; } @@ -816,21 +910,28 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, { int ret; - switch (padType) - { + switch (padType) { case WC_RSA_PKCSV15_PAD: - WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 un-padding");*/ ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); break; #ifndef WC_NO_RSA_OAEP case WC_RSA_OAEP_PAD: - WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + WOLFSSL_MSG("wolfSSL Using RSA OAEP un-padding"); ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, optLabel, labelLen, heap); break; #endif + #ifdef WC_RSA_PSS + case WC_RSA_PSS_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding"); + ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, + heap); + break; + #endif + default: WOLFSSL_MSG("Unknown RSA UnPad Type"); ret = RSA_PAD_E; @@ -846,72 +947,6 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, return ret; } - -#ifdef WC_RSA_BLINDING - -/* helper for either lib */ -static int get_digit_count(mp_int* a) -{ - if (a == NULL) - return 0; - - return a->used; -} - - -static int get_rand_digit(WC_RNG* rng, mp_digit* d) -{ - return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); -} - - -static int mp_rand(mp_int* a, int digits, WC_RNG* rng) -{ - int ret; - mp_digit d; - - if (rng == NULL) - return MISSING_RNG_E; - - if (a == NULL) - return BAD_FUNC_ARG; - - mp_zero(a); - if (digits <= 0) { - return MP_OKAY; - } - - /* first place a random non-zero digit */ - do { - ret = get_rand_digit(rng, &d); - if (ret != 0) { - return ret; - } - } while (d == 0); - - if ((ret = mp_add_d(a, d, a)) != MP_OKAY) { - return ret; - } - - while (--digits > 0) { - if ((ret = mp_lshd(a, 1)) != MP_OKAY) { - return ret; - } - if ((ret = get_rand_digit(rng, &d)) != 0) { - return ret; - } - if ((ret = mp_add_d(a, d, a)) != MP_OKAY) { - return ret; - } - } - - return ret; -} - - -#endif /* WC_RSA_BLINGING */ - - static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { @@ -947,7 +982,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, /* blind */ ret = mp_rand(&rnd, get_digit_count(&key->n), rng); if (ret != MP_OKAY) - ERROR_OUT(ret); + goto done; /* rndi = 1/rnd mod n */ if (mp_invmod(&rnd, &key->n, &rndi) != MP_OKAY) @@ -973,7 +1008,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, */ #define RET_ERR(ret, r, e) \ ((ret) | (COND_N((ret) == 0, COND_N((r) != MP_OKAY, (e))))) - + { /* tmpa/b scope */ mp_int tmpa, tmpb; int r; @@ -1063,20 +1098,19 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, mp_clear(&rnd); } #endif - if (ret == MP_EXPTMOD_E) { - WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); - } return ret; } -#ifdef WOLFSSL_ASYNC_CRYPT +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { int ret = 0; + (void)rng; + #ifdef WOLFSSL_ASYNC_CRYPT_TEST - AsyncCryptTestDev* testDev = &key->asyncDev.dev; + WC_ASYNC_TEST* testDev = &key->asyncDev.test; if (testDev->type == ASYNC_TEST_NONE) { testDev->type = ASYNC_TEST_RSA_FUNC; testDev->rsaFunc.in = in; @@ -1094,11 +1128,22 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, 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); + ret = NitroxRsaExptMod(in, inLen, + key->d.raw.buf, key->d.raw.len, + key->n.raw.buf, key->n.raw.len, + out, outLen, key); #elif defined(HAVE_INTEL_QA) - /* TODO: Add support for Intel Quick Assist */ - ret = -1; + #ifdef RSA_LOW_MEM + ret = IntelQaRsaPrivate(&key->asyncDev, in, inLen, + &key->d.raw, &key->n.raw, + out, outLen); + #else + ret = IntelQaRsaCrtPrivate(&key->asyncDev, in, inLen, + &key->p.raw, &key->q.raw, + &key->dP.raw, &key->dQ.raw, + &key->u.raw, + out, outLen); + #endif #else /* WOLFSSL_ASYNC_CRYPT_TEST */ ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif @@ -1107,11 +1152,14 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, 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); + ret = NitroxRsaExptMod(in, inLen, + key->e.raw.buf, key->e.raw.len, + key->n.raw.buf, key->n.raw.len, + out, outLen, key); #elif defined(HAVE_INTEL_QA) - /* TODO: Add support for Intel Quick Assist */ - ret = -1; + ret = IntelQaRsaPublic(&key->asyncDev, in, inLen, + &key->e.raw, &key->n.raw, + out, outLen); #else /* WOLFSSL_ASYNC_CRYPT_TEST */ ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); #endif @@ -1123,7 +1171,7 @@ static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, return ret; } -#endif /* WOLFSSL_ASYNC_CRYPT */ +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) @@ -1135,8 +1183,9 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, return BAD_FUNC_ARG; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + key->n.raw.len > 0) { ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng); } else @@ -1145,10 +1194,17 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, 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"); + /* handle error */ + if (ret < 0 && ret != WC_PENDING_E) { + 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"); + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); } + return ret; } @@ -1164,7 +1220,8 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, 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 + pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD or + WC_RSA_PSS_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 @@ -1175,10 +1232,10 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, enum wc_HashType hash, int mgf, byte* label, word32 labelSz, WC_RNG* rng) { - int ret = BAD_FUNC_ARG, sz; + int ret, sz; if (in == NULL || inLen == 0 || out == NULL || key == NULL) { - return ret; + return BAD_FUNC_ARG; } sz = wc_RsaEncryptSize(key); @@ -1197,46 +1254,58 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, 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_PAD; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && key->n.raw.buf) { + /* Async operations that include padding */ + if (rsa_type == RSA_PUBLIC_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_2) { key->state = RSA_STATE_ENCRYPT_RES; - key->tmpLen = key->n.used; + key->dataLen = key->n.raw.len; return NitroxRsaPublicEncrypt(in, inLen, out, outLen, key); } - else if (rsa_type == RSA_PRIVATE_ENCRYPT && pad_value == RSA_BLOCK_TYPE_1) { + else if (rsa_type == RSA_PRIVATE_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_1) { key->state = RSA_STATE_ENCRYPT_RES; - key->tmpLen = key->n.used; + key->dataLen = key->n.raw.len; 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); + 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 */ + + key->state = RSA_STATE_ENCRYPT_EXPTMOD; + + 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); + key->dataLen = outLen; + ret = wc_RsaFunction(out, sz, out, &key->dataLen, rsa_type, key, rng); + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_ENCRYPT_RES; + } if (ret < 0) { break; } - /* fall through */ + + FALL_THROUGH; + case RSA_STATE_ENCRYPT_RES: - key->state = RSA_STATE_NONE; - ret = key->tmpLen; + ret = key->dataLen; break; default: ret = BAD_STATE_E; + break; } /* if async pending then return and skip done cleanup below */ @@ -1245,6 +1314,7 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, } key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); return ret; } @@ -1259,7 +1329,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, 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 + pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD + WC_RSA_PSS_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 @@ -1270,68 +1341,75 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, enum wc_HashType hash, int mgf, byte* label, word32 labelSz, WC_RNG* rng) { - int ret = BAD_FUNC_ARG; + int ret = RSA_WRONG_TYPE_E; if (in == NULL || inLen == 0 || out == NULL || key == NULL) { - return ret; + return BAD_FUNC_ARG; } switch (key->state) { case RSA_STATE_NONE: case RSA_STATE_DECRYPT_EXPTMOD: - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + key->state = RSA_STATE_DECRYPT_EXPTMOD; + key->dataLen = inLen; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + /* Async operations that include padding */ if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - key->tmpLen = 0; - if (rsa_type == RSA_PRIVATE_DECRYPT && pad_value == RSA_BLOCK_TYPE_2) { + 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; + key->data = NULL; + if (outPtr) + *outPtr = in; + return NitroxRsaPrivateDecrypt(in, inLen, out, &key->dataLen, key); } - else if (rsa_type == RSA_PUBLIC_DECRYPT && pad_value == RSA_BLOCK_TYPE_1) { + 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); + key->data = NULL; + return NitroxRsaSSL_Verify(in, inLen, out, &key->dataLen, 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 (key->data != NULL) { + ret = BAD_STATE_E; + break; } /* 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); - key->tmpIsAlloc = 1; - if (key->tmp == NULL) { - ERROR_OUT(MEMORY_E); + key->data = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 1; + if (key->data == NULL) { + ret = MEMORY_E; + break; } - XMEMCPY(key->tmp, in, inLen); + XMEMCPY(key->data, in, inLen); } else { - key->tmp = out; + key->data = out; + } + ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, rsa_type, + key, rng); + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_DECRYPT_UNPAD; } - ret = wc_RsaFunction(key->tmp, inLen, key->tmp, &key->tmpLen, - rsa_type, key, rng); if (ret < 0) { break; } - /* fall through */ + + 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); + ret = wc_RsaUnPad_ex(key->data, key->dataLen, &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) { @@ -1347,18 +1425,29 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, if (ret < 0) { break; } - /* fall through */ + + key->state = RSA_STATE_DECRYPT_RES; + + FALL_THROUGH; } case RSA_STATE_DECRYPT_RES: - key->state = RSA_STATE_NONE; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - ret = key->tmpLen; + /* return event ret */ + ret = key->asyncDev.event.ret; + if (ret == 0) { + /* convert result */ + byte* dataLen = (byte*)&key->dataLen; + ret = (dataLen[0] << 8) | (dataLen[1]); + } } #endif break; + default: ret = BAD_STATE_E; + break; } /* if async pending then return and skip done cleanup below */ @@ -1366,8 +1455,6 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, return ret; } -done: - key->state = RSA_STATE_NONE; wc_RsaCleanup(key); @@ -1478,6 +1565,19 @@ int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, rng); } +#ifdef WC_RSA_PSS +int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, rng); +} +#endif int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng) @@ -1490,11 +1590,6 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, int wc_RsaEncryptSize(RsaKey* key) { -#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); } @@ -1544,10 +1639,30 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (e < 3 || (e & 1) == 0) return BAD_FUNC_ARG; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + /* TODO: Not implemented */ + #else + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_RSA_MAKE; + testDev->rsaMake.rng = rng; + testDev->rsaMake.key = key; + testDev->rsaMake.size = size; + testDev->rsaMake.e = e; + return WC_PENDING_E; + } + #endif + } +#endif + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) return err; - err = mp_set_int(&tmp3, (mp_digit)e); + err = mp_set_int(&tmp3, e); /* make p */ if (err == MP_OKAY) { @@ -1652,116 +1767,6 @@ int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) #endif /* WC_RSA_BLINDING */ -#ifdef WOLFSSL_ASYNC_CRYPT -int wc_RsaAsyncHandle(RsaKey* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) -{ - int ret; - - if (key == NULL || queue == NULL || event == NULL) { - return BAD_FUNC_ARG; - } - - /* 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 async RSA key */ -static int FreeAsyncRsaKey(RsaKey* key) -{ - 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 - } - } - -#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 */ - #undef ERROR_OUT #endif /* HAVE_FIPS */ diff --git a/wolfcrypt/src/sha.c b/wolfcrypt/src/sha.c old mode 100644 new mode 100755 index 499d723993..1affcce6e0 --- a/wolfcrypt/src/sha.c +++ b/wolfcrypt/src/sha.c @@ -26,48 +26,70 @@ #include - #if !defined(NO_SHA) #include -#include #include -#ifdef NO_INLINE - #include -#else - #define WOLFSSL_MISC_INCLUDED - #include -#endif - - /* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS - int wc_InitSha(Sha* sha) - { - return InitSha_fips(sha); - } - - int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) - { - return ShaUpdate_fips(sha, data, len); - } - - int wc_ShaFinal(Sha* sha, byte* out) - { - return ShaFinal_fips(sha,out); + int wc_InitSha(Sha* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha_fips(sha); + } + int wc_InitSha_ex(Sha* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha_fips(sha); + } + + int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return ShaUpdate_fips(sha, data, len); + } + + int wc_ShaFinal(Sha* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return ShaFinal_fips(sha,out); + } + void wc_ShaFree(Sha* sha) + { + (void)sha; + /* Not supported in FIPS */ } #else /* else build without fips */ -/****************************************/ -/* SHA Hardware Variations */ -/****************************************/ #if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ -#elif defined(WOLFSSL_PIC32MZ_HASH) +#else + +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* Hardware Acceleration */ +#if defined(WOLFSSL_PIC32MZ_HASH) #define USE_SHA_SOFTWARE_IMPL #define wc_InitSha wc_InitSha_sw #define wc_ShaUpdate wc_ShaUpdate_sw @@ -80,7 +102,7 @@ * library. (See note in README). */ - int wc_InitSha(Sha* sha) + static int InitSha(Sha* sha) { /* STM32 struct notes: * sha->buffer = first 4 bytes used to hold partial block if needed @@ -193,7 +215,7 @@ #elif defined(FREESCALE_LTC_SHA) #include "fsl_ltc.h" - int wc_InitSha(Sha* sha) + static int InitSha(Sha* sha) { LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0); return 0; @@ -219,7 +241,7 @@ #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */ #define XSHATRANSFORM ShaTransform - int wc_InitSha(Sha* sha) + static int InitSha(Sha* sha) { int ret = 0; ret = wolfSSL_CryptHwMutexLock(); @@ -251,7 +273,7 @@ /* Software implementation */ #define USE_SHA_SOFTWARE_IMPL - int wc_InitSha(Sha* sha) + static int InitSha(Sha* sha) { int ret = 0; @@ -268,7 +290,7 @@ return ret; } -#endif +#endif /* End Hardware Acceleration */ /* Software implementation */ @@ -378,13 +400,6 @@ #endif /* !USE_CUSTOM_SHA_TRANSFORM */ -#ifndef WOLFSSL_HAVE_MIN - #define WOLFSSL_HAVE_MIN - static INLINE word32 min(word32 a, word32 b) { - return a > b ? b : a; - } -#endif /* WOLFSSL_HAVE_MIN */ - static INLINE void AddLength(Sha* sha, word32 len) { word32 tmp = sha->loLen; @@ -392,11 +407,51 @@ static INLINE void AddLength(Sha* sha, word32 len) sha->hiLen++; /* carry low to high */ } +int wc_InitSha_ex(Sha* sha, void* heap, int devId) +{ + int ret = 0; + + if (sha == NULL) + return BAD_FUNC_ARG; + + sha->heap = heap; + + ret = InitSha(sha); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA, + sha->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} -int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) +int wc_ShaUpdate (Sha* sha, const byte* data, word32 len) { + byte* local; + + if (sha == NULL ||(data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + /* do block size increments */ - byte* local = (byte*)sha->buffer; + local = (byte*)sha->buffer; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha(&sha->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* check that internal buffLen is valid */ + if (sha->buffLen >= SHA_BLOCK_SIZE) + return BUFFER_E; while (len) { word32 add = min(len, SHA_BLOCK_SIZE - sha->buffLen); @@ -421,7 +476,21 @@ int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) int wc_ShaFinal(Sha* sha, byte* hash) { - byte* local = (byte*)sha->buffer; + byte* local; + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)sha->buffer; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha(&sha->asyncDev, hash, NULL, SHA_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ AddLength(sha, sha->buffLen); /* before adding pads */ @@ -466,10 +535,61 @@ int wc_ShaFinal(Sha* sha, byte* hash) #endif XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); - return wc_InitSha(sha); /* reset state */ + return InitSha(sha); /* reset state */ } #endif /* USE_SHA_SOFTWARE_IMPL */ + +int wc_InitSha(Sha* sha) +{ + return wc_InitSha_ex(sha, NULL, INVALID_DEVID); +} + +void wc_ShaFree(Sha* sha) +{ + if (sha == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* !WOLFSSL_TI_HASH */ #endif /* HAVE_FIPS */ + +#ifndef WOLFSSL_TI_HASH +int wc_ShaGetHash(Sha* sha, byte* hash) +{ + int ret; + Sha tmpSha; + + if (sha == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_ShaCopy(sha, &tmpSha); + if (ret == 0) { + ret = wc_ShaFinal(&tmpSha, hash); + } + return ret; +} + +int wc_ShaCopy(Sha* src, Sha* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} +#endif /* !WOLFSSL_TI_HASH */ + #endif /* !NO_SHA */ diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c old mode 100644 new mode 100755 index e0d986546f..9783c7cab8 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -27,591 +27,674 @@ #endif #include -#include #if !defined(NO_SHA256) -#ifdef HAVE_FIPS - -int wc_InitSha256(Sha256* sha) -{ - return InitSha256_fips(sha); -} - -int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) -{ - return Sha256Update_fips(sha, data, len); -} +#include +#include +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS -int wc_Sha256Final(Sha256* sha, byte* out) -{ - return Sha256Final_fips(sha, out); -} + int wc_InitSha256(Sha256* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); + } + int wc_InitSha256_ex(Sha256* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); + } + int wc_Sha256Update(Sha256* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha256Update_fips(sha, data, len); + } + int wc_Sha256Final(Sha256* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha256Final_fips(sha, out); + } + void wc_Sha256Free(Sha256* sha) + { + (void)sha; + /* Not supported in FIPS */ + } #else /* else build without fips */ -#if !defined(NO_SHA256) && defined(WOLFSSL_TI_HASH) + +#if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ #else -#if !defined (ALIGN32) - #if defined (__GNUC__) - #define ALIGN32 __attribute__ ( (aligned (32))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN32 __declspec (align (32)) - #else - #define ALIGN32 - #endif -#endif +#include -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include #endif -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif #if defined(USE_INTEL_SPEEDUP) -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 - -#if defined(DEBUG_XMM) -#include "stdio.h" -#endif - -#endif + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif /* USE_INTEL_SPEEDUP */ #if defined(HAVE_INTEL_AVX2) -#define HAVE_INTEL_RORX + #define HAVE_INTEL_RORX #endif - -/***** -Intel AVX1/AVX2 Macro Control Structure -#define HAVE_INTEL_AVX1 -#define HAVE_INTEL_AVX2 +static int InitSha256(Sha256* sha256) +{ + int ret = 0; + + if (sha256 == NULL) + return BAD_FUNC_ARG; -#define HAVE_INTEL_RORX + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; -int InitSha256(Sha256* sha256) { - Save/Recover XMM, YMM - ... + return ret; } -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - Transform() ; Function prototype -#else - Transform() { } - int Sha256Final() { - Save/Recover XMM, YMM - ... - } -#endif -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - #if defined(HAVE_INTEL_RORX - #define RND with rorx instuction +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + + /* in case intel instructions aren't available, plus we need the K[] global */ + #define NEED_SOFT_SHA256 + + /***** + Intel AVX1/AVX2 Macro Control Structure + + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + + #define HAVE_INTEL_RORX + + + int InitSha256(Sha256* sha256) { + Save/Recover XMM, YMM + ... + } + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform(); Function prototype #else - #define RND + Transform() { } + int Sha256Final() { + Save/Recover XMM, YMM + ... + } #endif -#endif -#if defined(HAVE_INTEL_AVX1) - - #define XMM Instructions/inline asm - - int Transform() { - Stitched Message Sched/Round - } - -#elif defined(HAVE_INTEL_AVX2) - - #define YMM Instructions/inline asm - - int Transform() { - More granural Stitched Message Sched/Round - } - -*/ + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + #if defined(HAVE_INTEL_RORX + #define RND with rorx instuction + #else + #define RND + #endif + #endif + #if defined(HAVE_INTEL_AVX1) -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + #define XMM Instructions/inline asm -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ + int Transform() { + Stitched Message Sched/Round + } -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); + #elif defined(HAVE_INTEL_AVX2) - #define XASM_LINK(f) asm(f) -#else + #define YMM Instructions/inline asm - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -#define CPUID_AVX1 0x1 -#define CPUID_AVX2 0x2 -#define CPUID_RDRAND 0x4 -#define CPUID_RDSEED 0x8 -#define CPUID_BMI2 0x10 /* MULX, RORX */ - -#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) -#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) -#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) -#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) -#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) - -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} + int Transform() { + More granural Stitched Message Sched/Round + } + + */ + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ -static int set_cpuid_flags(void) { - if(cpuid_check==0) { - if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} - if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } - if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } - cpuid_check = 1 ; - return 0 ; + #ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) + #else + #include + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + #define EAX 0 + #define EBX 1 + #define ECX 2 + #define EDX 3 + + #define CPUID_AVX1 0x1 + #define CPUID_AVX2 0x2 + #define CPUID_RDRAND 0x4 + #define CPUID_RDSEED 0x8 + #define CPUID_BMI2 0x10 /* MULX, RORX */ + + #define IS_INTEL_AVX1 (cpuid_flags & CPUID_AVX1) + #define IS_INTEL_AVX2 (cpuid_flags & CPUID_AVX2) + #define IS_INTEL_BMI2 (cpuid_flags & CPUID_BMI2) + #define IS_INTEL_RDRAND (cpuid_flags & CPUID_RDRAND) + #define IS_INTEL_RDSEED (cpuid_flags & CPUID_RDSEED) + + static word32 cpuid_check = 0; + static word32 cpuid_flags = 0; + + static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { + int got_intel_cpu=0; + unsigned int reg[5]; + + reg[4] = '\0'; + cpuid(reg, 0, 0); + if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return ((reg[num] >> bit) & 0x1); + } + return 0; } - return 1 ; -} + static int set_cpuid_flags(void) { + if (cpuid_check==0) { + if (cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1; } + if (cpuid_flag(7, 0, EBX, 5)) { cpuid_flags |= CPUID_AVX2; } + if (cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2; } + if (cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND; } + if (cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED; } + cpuid_check = 1; + return 0; + } + return 1; + } -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */ -static int Transform(Sha256* sha256); + /* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */ + static int Transform(Sha256* sha256); + #if defined(HAVE_INTEL_AVX1) + static int Transform_AVX1(Sha256 *sha256); + #endif + #if defined(HAVE_INTEL_AVX2) + static int Transform_AVX2(Sha256 *sha256); + static int Transform_AVX1_RORX(Sha256 *sha256); + #endif + static int (*Transform_p)(Sha256* sha256) /* = _Transform */; + #define XTRANSFORM(sha256, B) (*Transform_p)(sha256) + + static void set_Transform(void) { + if (set_cpuid_flags()) return; + + #if defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX2 && IS_INTEL_BMI2) { + Transform_p = Transform_AVX1_RORX; return; + Transform_p = Transform_AVX2; + /* for avoiding warning,"not used" */ + } + #endif + #if defined(HAVE_INTEL_AVX1) + Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform); return; + #endif + Transform_p = Transform; return; + } -#if defined(HAVE_INTEL_AVX1) -static int Transform_AVX1(Sha256 *sha256) ; -#endif -#if defined(HAVE_INTEL_AVX2) -static int Transform_AVX2(Sha256 *sha256) ; -static int Transform_AVX1_RORX(Sha256 *sha256) ; -#endif + /* Dummy for saving MM_REGs on behalf of Transform */ + #if defined(HAVE_INTEL_AVX2) && !defined(HAVE_INTEL_AVX1) + #define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") + #elif defined(HAVE_INTEL_AVX1) + #define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ + "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ + "xmm11","xmm12","xmm13","xmm14","xmm15") + #endif -static int (*Transform_p)(Sha256* sha256) /* = _Transform */; + int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) + { + int ret = 0; + if (sha256 == NULL) + return BAD_FUNC_ARG; -#define XTRANSFORM(sha256, B) (*Transform_p)(sha256) + sha256->heap = heap; -static void set_Transform(void) { - if(set_cpuid_flags())return ; + ret = InitSha256(sha256); + if (ret != 0) + return ret; -#if defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ - Transform_p = Transform_AVX1_RORX; return ; - Transform_p = Transform_AVX2 ; - /* for avoiding warning,"not used" */ - } -#endif -#if defined(HAVE_INTEL_AVX1) - Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : Transform) ; return ; -#endif - Transform_p = Transform ; return ; -} + /* choose best Transform function under this runtime environment */ + set_Transform(); -#else - #if defined(FREESCALE_MMCAU_SHA) - #define XTRANSFORM(sha256, B) Transform(sha256, B) - #else - #define XTRANSFORM(sha256, B) Transform(sha256) - #endif -#endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + ret = wolfAsync_DevCtxInit(&sha256->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ -/* Dummy for saving MM_REGs on behalf of Transform */ -#if defined(HAVE_INTEL_AVX2)&& !defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15") -#elif defined(HAVE_INTEL_AVX1) -#define SAVE_XMM_YMM __asm__ volatile("or %%r8d, %%r8d":::\ - "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10",\ - "xmm11","xmm12","xmm13","xmm14","xmm15") -#else -#define SAVE_XMM_YMM -#endif + return ret; + } -#ifdef WOLFSSL_PIC32MZ_HASH -#define InitSha256 InitSha256_sw -#define Sha256Update Sha256Update_sw -#define Sha256Final Sha256Final_sw -#endif +#elif defined(FREESCALE_LTC_SHA) + int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) + { + (void)heap; + (void)devId; -#include -#include + LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0); -#ifdef NO_INLINE - #include -#else - #define WOLFSSL_MISC_INCLUDED - #include -#endif + return 0; + } -#ifdef FREESCALE_MMCAU_SHA +#elif defined(FREESCALE_MMCAU_SHA) #include "fsl_mmcau.h" -#endif + #define XTRANSFORM(sha256, B) Transform(sha256, B) -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) + int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) { - return a > b ? b : a; - } + int ret = 0; -#endif /* WOLFSSL_HAVE_MIN */ + (void)heap; + (void)devId; -#ifdef FREESCALE_LTC_SHA -int wc_InitSha256(Sha256* sha256) -{ - LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0); - return 0; -} -#else -int wc_InitSha256(Sha256* sha256) -{ - int ret = 0; - #ifdef FREESCALE_MMCAU_SHA ret = wolfSSL_CryptHwMutexLock(); - if(ret != 0) { + if (ret != 0) { return ret; } MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest); wolfSSL_CryptHwMutexUnLock(); - #else - sha256->digest[0] = 0x6A09E667L; - sha256->digest[1] = 0xBB67AE85L; - sha256->digest[2] = 0x3C6EF372L; - sha256->digest[3] = 0xA54FF53AL; - sha256->digest[4] = 0x510E527FL; - sha256->digest[5] = 0x9B05688CL; - sha256->digest[6] = 0x1F83D9ABL; - sha256->digest[7] = 0x5BE0CD19L; - #endif - sha256->buffLen = 0; - sha256->loLen = 0; - sha256->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; /* choose best Transform function under this runtime environment */ -#endif + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; - return ret; -} -#endif /* FREESCALE_LTC_SHA */ - -#if !defined(FREESCALE_LTC_SHA) -#if !defined(FREESCALE_MMCAU_SHA) -static const ALIGN32 word32 K[64] = { - 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, - 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, - 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, - 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, - 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, - 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, - 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, - 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, - 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, - 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, - 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, - 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, - 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L -}; + return ret; + } -#endif + static int Transform(Sha256* sha256, byte* buf) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + MMCAU_SHA256_HashN(buf, 1, sha256->digest); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } -#if defined(FREESCALE_MMCAU_SHA) +#elif defined(WOLFSSL_PIC32MZ_HASH) + #define NEED_SOFT_SHA256 -static int Transform(Sha256* sha256, byte* buf) -{ - int ret = wolfSSL_CryptHwMutexLock(); - if(ret == 0) { - MMCAU_SHA256_HashN(buf, 1, (uint32_t*)sha256->digest); - wolfSSL_CryptHwMutexUnLock(); - } - return ret; -} + #define wc_InitSha256 wc_InitSha256_sw + #define wc_Sha256Update wc_Sha256Update_sw + #define wc_Sha256Final wc_Sha256Final_sw -#endif /* FREESCALE_MMCAU_SHA */ + int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) + { + if (sha256 == NULL) + return BAD_FUNC_ARG; -#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) -#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) -#define R(x, n) (((x)&0xFFFFFFFFU)>>(n)) + sha256->heap = heap; -#define S(x, n) rotrFixed(x, n) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + return InitSha256(sha256); + } -#define RND(a,b,c,d,e,f,g,h,i) \ - t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ - t1 = Sigma0((a)) + Maj((a), (b), (c)); \ - (d) += t0; \ - (h) = t0 + t1; +#else + #define NEED_SOFT_SHA256 -#if !defined(FREESCALE_MMCAU_SHA) -static int Transform(Sha256* sha256) -{ - word32 S[8], t0, t1; - int i; + #define XTRANSFORM(sha256, B) Transform(sha256) -#ifdef WOLFSSL_SMALL_STACK - word32* W; + int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) + { + int ret = 0; + if (sha256 == NULL) + return BAD_FUNC_ARG; - W = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W == NULL) - return MEMORY_E; -#else - word32 W[64]; -#endif + sha256->heap = heap; - /* Copy context->state[] to working vars */ - for (i = 0; i < 8; i++) - S[i] = sha256->digest[i]; - - for (i = 0; i < 16; i++) - W[i] = sha256->buffer[i]; - - for (i = 16; i < 64; i++) - W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; - - for (i = 0; i < 64; i += 8) { - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); - } + ret = InitSha256(sha256); + if (ret != 0) + return ret; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + ret = wolfAsync_DevCtxInit(&sha256->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ - /* Add the working vars back into digest state[] */ - for (i = 0; i < 8; i++) { - sha256->digest[i] += S[i]; + return ret; } +#endif /* End Hardware Acceleration */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifndef SAVE_XMM_YMM + #define SAVE_XMM_YMM #endif - return 0; -} - -#endif /* #if !defined(FREESCALE_MMCAU_SHA) */ +#ifdef NEED_SOFT_SHA256 + + static const ALIGN32 word32 K[64] = { + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, + 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, + 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, + 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, + 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, + 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, + 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, + 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, + 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, + 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L + }; + + #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + #define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) + #define R(x, n) (((x) & 0xFFFFFFFFU) >> (n)) + + #define S(x, n) rotrFixed(x, n) + #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) + #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) + #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) + #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + + #define RND(a,b,c,d,e,f,g,h,i) \ + t0 = (h) + Sigma1((e)) + Ch((e), (f), (g)) + K[(i)] + W[(i)]; \ + t1 = Sigma0((a)) + Maj((a), (b), (c)); \ + (d) += t0; \ + (h) = t0 + t1; + + static int Transform(Sha256* sha256) + { + word32 S[8], t0, t1; + int i; -static INLINE void AddLength(Sha256* sha256, word32 len) -{ - word32 tmp = sha256->loLen; - if ( (sha256->loLen += len) < tmp) - sha256->hiLen++; /* carry low to high */ -} -#endif /* FREESCALE_LTC_SHA */ + #ifdef WOLFSSL_SMALL_STACK + word32* W; -#ifdef FREESCALE_LTC_SHA -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - LTC_HASH_Update(&sha256->ctx, data, len); - return 0; -} -#else -static INLINE int Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ + W = (word32*)XMALLOC(sizeof(word32) * SHA256_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; + #else + word32 W[SHA256_BLOCK_SIZE]; + #endif - /* do block size increments */ - byte* local = (byte*)sha256->buffer; + /* Copy context->state[] to working vars */ + for (i = 0; i < 8; i++) + S[i] = sha256->digest[i]; + + for (i = 0; i < 16; i++) + W[i] = sha256->buffer[i]; + + for (i = 16; i < SHA256_BLOCK_SIZE; i++) + W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; + + for (i = 0; i < SHA256_BLOCK_SIZE; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } - SAVE_XMM_YMM ; /* for Intel AVX */ + /* Add the working vars back into digest state[] */ + for (i = 0; i < 8; i++) { + sha256->digest[i] += S[i]; + } - while (len) { - word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); - XMEMCPY(&local[sha256->buffLen], data, add); + #ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - sha256->buffLen += add; - data += add; - len -= add; + return 0; + } +#endif +/* End wc_ software implementation */ - if (sha256->buffLen == SHA256_BLOCK_SIZE) { - int ret; - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords(sha256->buffer, sha256->buffer, - SHA256_BLOCK_SIZE); - #endif - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; +#ifdef XTRANSFORM - AddLength(sha256, SHA256_BLOCK_SIZE); - sha256->buffLen = 0; - } + static INLINE void AddLength(Sha256* sha256, word32 len) + { + word32 tmp = sha256->loLen; + if ( (sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ } - return 0; -} + static INLINE int Sha256Update(Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + byte* local; -int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) -{ - return Sha256Update(sha256, data, len); -} + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } -#endif /* FREESCALE_LTC_SHA */ + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha256(&sha256->asyncDev, NULL, data, len); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ -#ifdef FREESCALE_LTC_SHA -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - uint32_t hashlen = SHA256_DIGEST_SIZE; - LTC_HASH_Finish(&sha256->ctx, hash, &hashlen); - return wc_InitSha256(sha256); /* reset state */ -} -#else -static INLINE int Sha256Final(Sha256* sha256) -{ - byte* local = (byte*)sha256->buffer; - int ret; - - SAVE_XMM_YMM ; /* for Intel AVX */ + /* do block size increments */ + local = (byte*)sha256->buffer; - AddLength(sha256, sha256->buffLen); /* before adding pads */ + /* check that internal buffLen is valid */ + if (sha256->buffLen >= SHA256_BLOCK_SIZE) + return BUFFER_E; - local[sha256->buffLen++] = 0x80; /* add 1 */ + SAVE_XMM_YMM; /* for Intel AVX */ - /* pad with zeros */ - if (sha256->buffLen > SHA256_PAD_SIZE) { - XMEMSET(&local[sha256->buffLen], 0, SHA256_BLOCK_SIZE - sha256->buffLen); - sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + while (len) { + word32 add = min(len, SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == SHA256_BLOCK_SIZE) { #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + if (!IS_INTEL_AVX1 && !IS_INTEL_AVX2) #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + { + ByteReverseWords(sha256->buffer, sha256->buffer, + SHA256_BLOCK_SIZE); + } #endif + ret = XTRANSFORM(sha256, local); + if (ret != 0) { + break; + } + + AddLength(sha256, SHA256_BLOCK_SIZE); + sha256->buffLen = 0; + } + } - ret = XTRANSFORM(sha256, local); - if (ret != 0) - return ret; + return ret; + } - sha256->buffLen = 0; + int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) + { + return Sha256Update(sha256, data, len); } - XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); - /* put lengths in bits */ - sha256->hiLen = (sha256->loLen >> (8*sizeof(sha256->loLen) - 3)) + - (sha256->hiLen << 3); - sha256->loLen = sha256->loLen << 3; + static INLINE int Sha256Final(Sha256* sha256) + { + + int ret; + byte* local = (byte*)sha256->buffer; + + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + + SAVE_XMM_YMM; /* for Intel AVX */ + + AddLength(sha256, sha256->buffLen); /* before adding pads */ + local[sha256->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha256->buffLen > SHA256_PAD_SIZE) { + XMEMSET(&local[sha256->buffLen], 0, + SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += SHA256_BLOCK_SIZE - sha256->buffLen; + + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + SHA256_BLOCK_SIZE); + } + #endif + + ret = XTRANSFORM(sha256, local); + if (ret != 0) + return ret; + + sha256->buffLen = 0; + } + XMEMSET(&local[sha256->buffLen], 0, SHA256_PAD_SIZE - sha256->buffLen); + + /* put lengths in bits */ + sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) + + (sha256->hiLen << 3); + sha256->loLen = sha256->loLen << 3; - /* store lengths */ + /* store lengths */ #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + if (!IS_INTEL_AVX1 && !IS_INTEL_AVX2) #endif - ByteReverseWords(sha256->buffer, sha256->buffer, SHA256_BLOCK_SIZE); + { + ByteReverseWords(sha256->buffer, sha256->buffer, + SHA256_BLOCK_SIZE); + } #endif - /* ! length ordering dependent on digest endian type ! */ - XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); - XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, - sizeof(word32)); + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + sizeof(word32)); - #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || \ + defined(HAVE_INTEL_AVX2) /* Kinetis requires only these bytes reversed */ #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) + if (IS_INTEL_AVX1 || IS_INTEL_AVX2) #endif - ByteReverseWords(&sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - &sha256->buffer[SHA256_PAD_SIZE/sizeof(word32)], - 2 * sizeof(word32)); + { + ByteReverseWords( + &sha256->buffer[SHA256_PAD_SIZE / sizeof(word32)], + &sha256->buffer[SHA256_PAD_SIZE / sizeof(word32)], + 2 * sizeof(word32)); + } #endif - return XTRANSFORM(sha256, local); -} + return XTRANSFORM(sha256, local); + } -int wc_Sha256Final(Sha256* sha256, byte* hash) -{ - int ret; + int wc_Sha256Final(Sha256* sha256, byte* hash) + { + int ret; - ret = Sha256Final(sha256); - if (ret != 0) - return ret; + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha256(&sha256->asyncDev, hash, NULL, + SHA256_DIGEST_SIZE); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Final(sha256); + if (ret != 0) + return ret; #if defined(LITTLE_ENDIAN_ORDER) ByteReverseWords(sha256->digest, sha256->digest, SHA256_DIGEST_SIZE); #endif - XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); + XMEMCPY(hash, sha256->digest, SHA256_DIGEST_SIZE); - return wc_InitSha256(sha256); /* reset state */ -} -#endif /* FREESCALE_LTC_SHA */ + return InitSha256(sha256); /* reset state */ + } +#endif /* XTRANSFORM */ #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) #define _DigestToReg(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs) ;\ - d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs) ;\ - d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs) ;\ - d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs) ;\ - d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs) ;\ - d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs) ;\ - d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs) ;\ - d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs) ;\ +{ word32 d;\ + d = sha256->digest[0]; __asm__ volatile("movl %0, %"#S_0::"r"(d):SSE_REGs);\ + d = sha256->digest[1]; __asm__ volatile("movl %0, %"#S_1::"r"(d):SSE_REGs);\ + d = sha256->digest[2]; __asm__ volatile("movl %0, %"#S_2::"r"(d):SSE_REGs);\ + d = sha256->digest[3]; __asm__ volatile("movl %0, %"#S_3::"r"(d):SSE_REGs);\ + d = sha256->digest[4]; __asm__ volatile("movl %0, %"#S_4::"r"(d):SSE_REGs);\ + d = sha256->digest[5]; __asm__ volatile("movl %0, %"#S_5::"r"(d):SSE_REGs);\ + d = sha256->digest[6]; __asm__ volatile("movl %0, %"#S_6::"r"(d):SSE_REGs);\ + d = sha256->digest[7]; __asm__ volatile("movl %0, %"#S_7::"r"(d):SSE_REGs);\ } #define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ; \ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ; sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ; sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ; sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ; sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ; sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ; sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ; sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ; sha256->digest[7] += d;\ +{ word32 d; \ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs); sha256->digest[0] += d;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs); sha256->digest[1] += d;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs); sha256->digest[2] += d;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs); sha256->digest[3] += d;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs); sha256->digest[4] += d;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs); sha256->digest[5] += d;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs); sha256->digest[6] += d;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs); sha256->digest[7] += d;\ } @@ -622,11 +705,9 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - - -#define S_0 %r15d +#define S_0 %r15d #define S_1 %r10d -#define S_2 %r11d +#define S_2 %r11d #define S_3 %r12d #define S_4 %r13d #define S_5 %r14d @@ -662,7 +743,7 @@ __asm__ volatile("rorx $13, %"#a", %%edi\n\t":::"%edi",SSE_REGs);/* edi = a>>13 __asm__ volatile("rorx $22, %"#a", %%edx\n\t":::"%edx",SSE_REGs); /* edx = a>>22 */\ __asm__ volatile("xorl %%r8d, %%edi\n\t":::"%edi","%r8",SSE_REGs);/* edi = (a>>2) ^ (a>>13) */\ __asm__ volatile("xorl %%edi, %%edx\n\t":::"%edi","%edx",SSE_REGs); /* edx = Sigma0(a) */\ - + #define RND_STEP_RORX_6(a,b,c,d,e,f,g,h,i)\ __asm__ volatile("movl %"#b", %%edi\n\t":::"%edi",SSE_REGs); /* edi = b */\ __asm__ volatile("orl %"#a", %%edi\n\t":::"%edi",SSE_REGs); /* edi = a | b */\ @@ -678,9 +759,8 @@ __asm__ volatile("orl %%edi, %%r8d\n\t":::"%edi","%r8",SSE_REGs); /* r8d = Maj __asm__ volatile("addl "#h", "#d"\n\t"); /* d += h + w_k + Sigma1(e) + Ch(e,f,g) */\ __asm__ volatile("addl %"#h", %%r8d\n\t":::"%r8",SSE_REGs); \ __asm__ volatile("addl %%edx, %%r8d\n\t":::"%edx","%r8",SSE_REGs); \ -__asm__ volatile("movl %r8d, "#h"\n\t"); - -#endif +__asm__ volatile("movl %r8d, "#h"\n\t"); +#endif /* HAVE_INTEL_RORX */ #define RND_STEP_1(a,b,c,d,e,f,g,h,i)\ __asm__ volatile("movl %"#e", %%edx\n\t":::"%edx",SSE_REGs);\ @@ -742,7 +822,7 @@ __asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ RND_STEP_5(a,b,c,d,e,f,g,h,i); \ RND_STEP_6(a,b,c,d,e,f,g,h,i); \ RND_STEP_7(a,b,c,d,e,f,g,h,i); \ - RND_STEP_8(a,b,c,d,e,f,g,h,i); + RND_STEP_8(a,b,c,d,e,f,g,h,i); #define RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i); #define RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_X(S_7,S_0,S_1,S_2,S_3,S_4,S_5,S_6,_i); @@ -809,15 +889,15 @@ __asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ #define RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,_i) RND_7_8(S_1,S_2,S_3,S_4,S_5,S_6,S_7,S_0,_i); #define FOR(cnt, init, max, inc, loop) \ - __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) + __asm__ volatile("movl $"#init", %0\n\t"#loop":"::"m"(cnt):) #define END(cnt, init, max, inc, loop) \ - __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::) ; + __asm__ volatile("addl $"#inc", %0\n\tcmpl $"#max", %0\n\tjle "#loop"\n\t":"=m"(cnt)::); #endif /* defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) */ #if defined(HAVE_INTEL_AVX1) /* inline Assember for Intel AVX1 instructions */ -#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) +#define VPALIGNR(op1,op2,op3,op4) __asm__ volatile("vpalignr $"#op4", %"#op3", %"#op2", %"#op1:::XMM_REGs) #define VPADDD(op1,op2,op3) __asm__ volatile("vpaddd %"#op3", %"#op2", %"#op1:::XMM_REGs) #define VPSRLD(op1,op2,op3) __asm__ volatile("vpsrld $"#op3", %"#op2", %"#op1:::XMM_REGs) #define VPSRLQ(op1,op2,op3) __asm__ volatile("vpsrlq $"#op3", %"#op2", %"#op1:::XMM_REGs) @@ -830,171 +910,171 @@ __asm__ volatile("movl %%r8d, %"#h"\n\t":::"%r8", SSE_REGs); \ #define MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, SHUF_00BA, SHUF_DC00,\ a,b,c,d,e,f,g,h,_i)\ RND_STEP_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ + VPALIGNR (XTMP0, X3, X2, 4);\ RND_STEP_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ + VPADDD (XTMP0, XTMP0, X0);\ RND_STEP_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + VPALIGNR (XTMP1, X1, X0, 4); /* XTMP1 = W[-15] */\ RND_STEP_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ + VPSRLD (XTMP2, XTMP1, 7);\ RND_STEP_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + VPSLLD (XTMP3, XTMP1, 25); /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ RND_STEP_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + VPOR (XTMP3, XTMP3, XTMP2); /* XTMP1 = W[-15] MY_ROR 7 */\ RND_STEP_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ + VPSRLD (XTMP2, XTMP1,18);\ RND_STEP_8(a,b,c,d,e,f,g,h,_i);\ \ RND_STEP_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + VPSRLD (XTMP4, XTMP1, 3); /* XTMP4 = W[-15] >> 3 */\ RND_STEP_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + VPSLLD (XTMP1, XTMP1, 14); /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ RND_STEP_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ + VPXOR (XTMP3, XTMP3, XTMP1);\ RND_STEP_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ + VPXOR (XTMP3, XTMP3, XTMP2); /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ RND_STEP_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + VPXOR (XTMP1, XTMP3, XTMP4); /* XTMP1 = s0 */\ RND_STEP_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + VPSHUFD(XTMP2, X3, 0b11111010); /* XTMP2 = W[-2] {BBAA}*/\ RND_STEP_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + VPADDD (XTMP0, XTMP0, XTMP1); /* XTMP0 = W[-16] + W[-7] + s0 */\ RND_STEP_8(h,a,b,c,d,e,f,g,_i+1);\ \ RND_STEP_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + VPSRLD (XTMP4, XTMP2, 10); /* XTMP4 = W[-2] >> 10 {BBAA} */\ RND_STEP_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ RND_STEP_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + VPSRLQ (XTMP2, XTMP2, 17); /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ RND_STEP_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ + VPXOR (XTMP2, XTMP2, XTMP3);\ RND_STEP_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + VPXOR (XTMP4, XTMP4, XTMP2); /* XTMP4 = s1 {xBxA} */\ RND_STEP_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA); /* XTMP4 = s1 {00BA} */\ RND_STEP_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + VPADDD (XTMP0, XTMP0, XTMP4); /* XTMP0 = {..., ..., W[1], W[0]} */\ RND_STEP_8(g,h,a,b,c,d,e,f,_i+2);\ \ RND_STEP_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + VPSHUFD (XTMP2, XTMP0, 0b01010000); /* XTMP2 = W[-2] {DDCC} */\ RND_STEP_2(f,g,h,a,b,c,d,e,_i+3);\ VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ RND_STEP_3(f,g,h,a,b,c,d,e,_i+3);\ VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ RND_STEP_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + VPSRLQ (XTMP2, XTMP2, 17); /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ RND_STEP_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ + VPXOR (XTMP2, XTMP2, XTMP3);\ RND_STEP_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + VPXOR (XTMP5, XTMP5, XTMP2); /* XTMP5 = s1 {xDxC} */\ RND_STEP_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00); /* XTMP5 = s1 {DC00} */\ RND_STEP_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ + VPADDD (X0, XTMP5, XTMP0); /* X0 = {W[3], W[2], W[1], W[0]} */\ #if defined(HAVE_INTEL_RORX) #define MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, \ XFER, SHUF_00BA, SHUF_DC00,a,b,c,d,e,f,g,h,_i)\ RND_STEP_RORX_1(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP0, X3, X2, 4) ;\ + VPALIGNR (XTMP0, X3, X2, 4);\ RND_STEP_RORX_2(a,b,c,d,e,f,g,h,_i);\ - VPADDD (XTMP0, XTMP0, X0) ;\ + VPADDD (XTMP0, XTMP0, X0);\ RND_STEP_RORX_3(a,b,c,d,e,f,g,h,_i);\ - VPALIGNR (XTMP1, X1, X0, 4) ; /* XTMP1 = W[-15] */\ + VPALIGNR (XTMP1, X1, X0, 4); /* XTMP1 = W[-15] */\ RND_STEP_RORX_4(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1, 7) ;\ + VPSRLD (XTMP2, XTMP1, 7);\ RND_STEP_RORX_5(a,b,c,d,e,f,g,h,_i);\ - VPSLLD (XTMP3, XTMP1, 25) ; /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ + VPSLLD (XTMP3, XTMP1, 25); /* VPSLLD (XTMP3, XTMP1, (32-7)) */\ RND_STEP_RORX_6(a,b,c,d,e,f,g,h,_i);\ - VPOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 */\ + VPOR (XTMP3, XTMP3, XTMP2); /* XTMP1 = W[-15] MY_ROR 7 */\ RND_STEP_RORX_7(a,b,c,d,e,f,g,h,_i);\ - VPSRLD (XTMP2, XTMP1,18) ;\ + VPSRLD (XTMP2, XTMP1,18);\ RND_STEP_RORX_8(a,b,c,d,e,f,g,h,_i);\ \ RND_STEP_RORX_1(h,a,b,c,d,e,f,g,_i+1);\ - VPSRLD (XTMP4, XTMP1, 3) ; /* XTMP4 = W[-15] >> 3 */\ + VPSRLD (XTMP4, XTMP1, 3); /* XTMP4 = W[-15] >> 3 */\ RND_STEP_RORX_2(h,a,b,c,d,e,f,g,_i+1);\ - VPSLLD (XTMP1, XTMP1, 14) ; /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ + VPSLLD (XTMP1, XTMP1, 14); /* VPSLLD (XTMP1, XTMP1, (32-18)) */\ RND_STEP_RORX_3(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP1) ;\ + VPXOR (XTMP3, XTMP3, XTMP1);\ RND_STEP_RORX_4(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP3, XTMP3, XTMP2) ; /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ + VPXOR (XTMP3, XTMP3, XTMP2); /* XTMP1 = W[-15] MY_ROR 7 ^ W[-15] MY_ROR 18 */\ RND_STEP_RORX_5(h,a,b,c,d,e,f,g,_i+1);\ - VPXOR (XTMP1, XTMP3, XTMP4) ; /* XTMP1 = s0 */\ + VPXOR (XTMP1, XTMP3, XTMP4); /* XTMP1 = s0 */\ RND_STEP_RORX_6(h,a,b,c,d,e,f,g,_i+1);\ - VPSHUFD(XTMP2, X3, 0b11111010) ; /* XTMP2 = W[-2] {BBAA}*/\ + VPSHUFD(XTMP2, X3, 0b11111010); /* XTMP2 = W[-2] {BBAA}*/\ RND_STEP_RORX_7(h,a,b,c,d,e,f,g,_i+1);\ - VPADDD (XTMP0, XTMP0, XTMP1) ; /* XTMP0 = W[-16] + W[-7] + s0 */\ + VPADDD (XTMP0, XTMP0, XTMP1); /* XTMP0 = W[-16] + W[-7] + s0 */\ RND_STEP_RORX_8(h,a,b,c,d,e,f,g,_i+1);\ \ RND_STEP_RORX_1(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLD (XTMP4, XTMP2, 10) ; /* XTMP4 = W[-2] >> 10 {BBAA} */\ + VPSRLD (XTMP4, XTMP2, 10); /* XTMP4 = W[-2] >> 10 {BBAA} */\ RND_STEP_RORX_2(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP3, XTMP2, 19) ; /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ + VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xBxA} */\ RND_STEP_RORX_3(g,h,a,b,c,d,e,f,_i+2);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ + VPSRLQ (XTMP2, XTMP2, 17); /* XTMP2 = W[-2] MY_ROR 17 {xBxA} */\ RND_STEP_RORX_4(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ + VPXOR (XTMP2, XTMP2, XTMP3);\ RND_STEP_RORX_5(g,h,a,b,c,d,e,f,_i+2);\ - VPXOR (XTMP4, XTMP4, XTMP2) ; /* XTMP4 = s1 {xBxA} */\ + VPXOR (XTMP4, XTMP4, XTMP2); /* XTMP4 = s1 {xBxA} */\ RND_STEP_RORX_6(g,h,a,b,c,d,e,f,_i+2);\ - VPSHUFB (XTMP4, XTMP4, SHUF_00BA) ; /* XTMP4 = s1 {00BA} */\ + VPSHUFB (XTMP4, XTMP4, SHUF_00BA); /* XTMP4 = s1 {00BA} */\ RND_STEP_RORX_7(g,h,a,b,c,d,e,f,_i+2);\ - VPADDD (XTMP0, XTMP0, XTMP4) ; /* XTMP0 = {..., ..., W[1], W[0]} */\ + VPADDD (XTMP0, XTMP0, XTMP4); /* XTMP0 = {..., ..., W[1], W[0]} */\ RND_STEP_RORX_8(g,h,a,b,c,d,e,f,_i+2);\ \ RND_STEP_RORX_1(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFD (XTMP2, XTMP0, 0b01010000) ; /* XTMP2 = W[-2] {DDCC} */\ + VPSHUFD (XTMP2, XTMP0, 0b01010000); /* XTMP2 = W[-2] {DDCC} */\ RND_STEP_RORX_2(f,g,h,a,b,c,d,e,_i+3);\ VPSRLD (XTMP5, XTMP2, 10); /* XTMP5 = W[-2] >> 10 {DDCC} */\ RND_STEP_RORX_3(f,g,h,a,b,c,d,e,_i+3);\ VPSRLQ (XTMP3, XTMP2, 19); /* XTMP3 = W[-2] MY_ROR 19 {xDxC} */\ RND_STEP_RORX_4(f,g,h,a,b,c,d,e,_i+3);\ - VPSRLQ (XTMP2, XTMP2, 17) ; /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ + VPSRLQ (XTMP2, XTMP2, 17); /* XTMP2 = W[-2] MY_ROR 17 {xDxC} */\ RND_STEP_RORX_5(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP2, XTMP2, XTMP3) ;\ + VPXOR (XTMP2, XTMP2, XTMP3);\ RND_STEP_RORX_6(f,g,h,a,b,c,d,e,_i+3);\ - VPXOR (XTMP5, XTMP5, XTMP2) ; /* XTMP5 = s1 {xDxC} */\ + VPXOR (XTMP5, XTMP5, XTMP2); /* XTMP5 = s1 {xDxC} */\ RND_STEP_RORX_7(f,g,h,a,b,c,d,e,_i+3);\ - VPSHUFB (XTMP5, XTMP5, SHUF_DC00) ; /* XTMP5 = s1 {DC00} */\ + VPSHUFB (XTMP5, XTMP5, SHUF_DC00); /* XTMP5 = s1 {DC00} */\ RND_STEP_RORX_8(f,g,h,a,b,c,d,e,_i+3);\ - VPADDD (X0, XTMP5, XTMP0) ; /* X0 = {W[3], W[2], W[1], W[0]} */\ + VPADDD (X0, XTMP5, XTMP0); /* X0 = {W[3], W[2], W[1], W[0]} */\ -#endif +#endif /* HAVE_INTEL_RORX */ #define W_K_from_buff\ __asm__ volatile("vmovdqu %0, %%xmm4\n\t"\ "vpshufb %%xmm13, %%xmm4, %%xmm4\n\t"\ - :: "m"(sha256->buffer[0]):"%xmm4") ;\ + :: "m"(sha256->buffer[0]):"%xmm4");\ __asm__ volatile("vmovdqu %0, %%xmm5\n\t"\ "vpshufb %%xmm13, %%xmm5, %%xmm5\n\t"\ - ::"m"(sha256->buffer[4]):"%xmm5") ;\ + ::"m"(sha256->buffer[4]):"%xmm5");\ __asm__ volatile("vmovdqu %0, %%xmm6\n\t"\ "vpshufb %%xmm13, %%xmm6, %%xmm6\n\t"\ - ::"m"(sha256->buffer[8]):"%xmm6") ;\ + ::"m"(sha256->buffer[8]):"%xmm6");\ __asm__ volatile("vmovdqu %0, %%xmm7\n\t"\ "vpshufb %%xmm13, %%xmm7, %%xmm7\n\t"\ - ::"m"(sha256->buffer[12]):"%xmm7") ;\ + ::"m"(sha256->buffer[12]):"%xmm7");\ #define _SET_W_K_XFER(reg, i)\ - __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs) ;\ - __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs) ; + __asm__ volatile("vpaddd %0, %"#reg", %%xmm9"::"m"(K[i]):XMM_REGs);\ + __asm__ volatile("vmovdqa %%xmm9, %0":"=m"(W_K[i])::XMM_REGs); #define SET_W_K_XFER(reg, i) _SET_W_K_XFER(reg, i) -static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF } ; /* shuffle xBxA -> 00BA */ -static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 } ; /* shuffle xDxC -> DC00 */ -static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b } ; +static const ALIGN32 word64 mSHUF_00BA[] = { 0x0b0a090803020100, 0xFFFFFFFFFFFFFFFF }; /* shuffle xBxA -> 00BA */ +static const ALIGN32 word64 mSHUF_DC00[] = { 0xFFFFFFFFFFFFFFFF, 0x0b0a090803020100 }; /* shuffle xDxC -> DC00 */ +static const ALIGN32 word64 mBYTE_FLIP_MASK[] = { 0x0405060700010203, 0x0c0d0e0f08090a0b }; #define _Init_Masks(mask1, mask2, mask3)\ -__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0])) ;\ -__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; +__asm__ volatile("vmovdqu %0, %"#mask1 ::"m"(mBYTE_FLIP_MASK[0]));\ +__asm__ volatile("vmovdqu %0, %"#mask2 ::"m"(mSHUF_00BA[0]));\ +__asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])); #define Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00)\ _Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) @@ -1022,93 +1102,77 @@ __asm__ volatile("vmovdqu %0, %"#mask3 ::"m"(mSHUF_DC00[0])) ; static int Transform_AVX1(Sha256* sha256) { + ALIGN32 word32 W_K[64]; /* temp for W+K */ - word32 W_K[64] ; /* temp for W+K */ + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00); + W_K_from_buff; /* X0, X1, X2, X3 = W[0..15]; */ - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7); - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ + SET_W_K_XFER(X0, 0); - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - SET_W_K_XFER(X0, 0) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0); + SET_W_K_XFER(X1, 4); MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, - SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; - - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4); + SET_W_K_XFER(X2, 8); + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8); + SET_W_K_XFER(X3, 12); + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12); + SET_W_K_XFER(X0, 16); + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16); + SET_W_K_XFER(X1, 20); + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20); + SET_W_K_XFER(X2, 24); + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24); + SET_W_K_XFER(X3, 28); + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28); + SET_W_K_XFER(X0, 32); + MessageSched(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32); + SET_W_K_XFER(X1, 36); + MessageSched(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36); + SET_W_K_XFER(X2, 40); + MessageSched(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40); + SET_W_K_XFER(X3, 44); + MessageSched(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, XFER, + SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44); + + SET_W_K_XFER(X0, 48); + SET_W_K_XFER(X1, 52); + SET_W_K_XFER(X2, 56); + SET_W_K_XFER(X3, 60); + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48); + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49); + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50); + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51); + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52); + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53); + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54); + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55); + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56); + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57); + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58); + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59); + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60); + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61); + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62); + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63); + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7); return 0; } @@ -1116,144 +1180,126 @@ static int Transform_AVX1(Sha256* sha256) #if defined(HAVE_INTEL_RORX) static int Transform_AVX1_RORX(Sha256* sha256) { + ALIGN32 word32 W_K[64]; /* temp for W+K */ + + Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00); + W_K_from_buff; /* X0, X1, X2, X3 = W[0..15]; */ + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7); + SET_W_K_XFER(X0, 0); + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0); + SET_W_K_XFER(X1, 4); + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4); + SET_W_K_XFER(X2, 8); + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8); + SET_W_K_XFER(X3, 12); + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12); + SET_W_K_XFER(X0, 16); + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16); + SET_W_K_XFER(X1, 20); + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20); + SET_W_K_XFER(X2, 24); + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24); + SET_W_K_XFER(X3, 28); + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28); + SET_W_K_XFER(X0, 32); + MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32); + SET_W_K_XFER(X1, 36); + MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36); + SET_W_K_XFER(X2, 40); + MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40); + SET_W_K_XFER(X3, 44); + MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, + XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44); - word32 W_K[64] ; /* temp for W+K */ + SET_W_K_XFER(X0, 48); + SET_W_K_XFER(X1, 52); + SET_W_K_XFER(X2, 56); + SET_W_K_XFER(X3, 60); - #if defined(DEBUG_XMM) - int i, j ; - word32 xmm[29][4*15] ; - #endif + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48); + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49); + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50); + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51); - Init_Masks(BYTE_FLIP_MASK, SHUF_00BA, SHUF_DC00) ; - W_K_from_buff ; /* X0, X1, X2, X3 = W[0..15] ; */ - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - SET_W_K_XFER(X0, 0) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - SET_W_K_XFER(X1, 4) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,4) ; - SET_W_K_XFER(X2, 8) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - SET_W_K_XFER(X3, 12) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,12) ; - SET_W_K_XFER(X0, 16) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - SET_W_K_XFER(X1, 20) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,20) ; - SET_W_K_XFER(X2, 24) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - SET_W_K_XFER(X3, 28) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,28) ; - SET_W_K_XFER(X0, 32) ; - MessageSched_RORX(X0, X1, X2, X3, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - SET_W_K_XFER(X1, 36) ; - MessageSched_RORX(X1, X2, X3, X0, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,36) ; - SET_W_K_XFER(X2, 40) ; - MessageSched_RORX(X2, X3, X0, X1, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - SET_W_K_XFER(X3, 44) ; - MessageSched_RORX(X3, X0, X1, X2, XTMP0, XTMP1, XTMP2, XTMP3, XTMP4, XTMP5, - XFER, SHUF_00BA, SHUF_DC00, S_4,S_5,S_6,S_7,S_0,S_1,S_2,S_3,44) ; - - SET_W_K_XFER(X0, 48) ; - SET_W_K_XFER(X1, 52) ; - SET_W_K_XFER(X2, 56) ; - SET_W_K_XFER(X3, 60) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - #if defined(DEBUG_XMM) - for(i=0; i<29; i++) { - for(j=0; j<4*14; j+=4) - printf("xmm%d[%d]=%08x,%08x,%08x,%08x\n", j/4, i, - xmm[i][j],xmm[i][j+1],xmm[i][j+2],xmm[i][j+3]) ; - printf("\n") ; - } - - for(i=0; i<64; i++)printf("W_K[%d]%08x\n", i, W_K[i]) ; - #endif + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52); + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53); + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54); + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55); + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56); + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57); + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58); + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59); + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60); + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61); + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62); + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63); + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7); return 0; } #endif /* HAVE_INTEL_RORX */ - #endif /* HAVE_INTEL_AVX1 */ #if defined(HAVE_INTEL_AVX2) -#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs) ; -#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs) ; +#define _MOVE_to_REG(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" ":: "m"(mem):YMM_REGs); +#define _MOVE_to_MEM(mem, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" : "=m"(mem)::YMM_REGs); #define _BYTE_SWAP(ymm, map) __asm__ volatile("vpshufb %0, %%"#ymm", %%"#ymm"\n\t"\ - :: "m"(map):YMM_REGs) ; + :: "m"(map):YMM_REGs); #define _MOVE_128(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"#map", %%"\ - #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; + #ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs); #define _MOVE_BYTE(ymm0, ymm1, map) __asm__ volatile("vpshufb %0, %%"#ymm1", %%"\ - #ymm0"\n\t":: "m"(map):YMM_REGs) ; + #ymm0"\n\t":: "m"(map):YMM_REGs); #define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrld $"#bits", %%"\ #src", %%"#dest"\n\tvpslld $32-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ - #temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; + #temp",%%"#dest", %%"#dest" ":::YMM_REGs); #define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrld $"#bits", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; + #src", %%"#dest" ":::YMM_REGs); #define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; + #src2", %%"#dest" ":::YMM_REGs); #define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; + #src2", %%"#dest" ":::YMM_REGs); #define _ADD(dest, src1, src2) __asm__ volatile("vpaddd %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; + #src2", %%"#dest" ":::YMM_REGs); #define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddd %0, %%"#src1", %%"\ - #dest" "::"m"(mem):YMM_REGs) ; + #dest" "::"m"(mem):YMM_REGs); #define _BLEND(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; + #src1", %%"#src2", %%"#dest" ":::YMM_REGs); -#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; +#define _EXTRACT_XMM_0(xmm, mem) __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); +#define _EXTRACT_XMM_1(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); +#define _EXTRACT_XMM_2(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); +#define _EXTRACT_XMM_3(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); #define _EXTRACT_XMM_4(ymm, xmm, mem)\ - __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ;\ - __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; -#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs) ; + __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs);\ + __asm__ volatile("vpextrd $0, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); +#define _EXTRACT_XMM_5(xmm, mem) __asm__ volatile("vpextrd $1, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); +#define _EXTRACT_XMM_6(xmm, mem) __asm__ volatile("vpextrd $2, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); +#define _EXTRACT_XMM_7(xmm, mem) __asm__ volatile("vpextrd $3, %%"#xmm", %0 ":"=r"(mem)::YMM_REGs); -#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs) ; -#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) +#define _SWAP_YMM_HL(ymm) __asm__ volatile("vperm2i128 $0x1, %%"#ymm", %%"#ymm", %%"#ymm" ":::YMM_REGs); +#define SWAP_YMM_HL(ymm) _SWAP_YMM_HL(ymm) #define MOVE_to_REG(ymm, mem) _MOVE_to_REG(ymm, mem) #define MOVE_to_MEM(mem, ymm) _MOVE_to_MEM(mem, ymm) #define BYTE_SWAP(ymm, map) _BYTE_SWAP(ymm, map) -#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) +#define MOVE_128(ymm0, ymm1, ymm2, map) _MOVE_128(ymm0, ymm1, ymm2, map) #define MOVE_BYTE(ymm0, ymm1, map) _MOVE_BYTE(ymm0, ymm1, map) #define XOR(dest, src1, src2) _XOR(dest, src1, src2) #define OR(dest, src1, src2) _OR(dest, src1, src2) @@ -1261,31 +1307,31 @@ static int Transform_AVX1_RORX(Sha256* sha256) #define ADD_MEM(dest, src1, mem) _ADD_MEM(dest, src1, mem) #define BLEND(map, dest, src1, src2) _BLEND(map, dest, src1, src2) -#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); +#define S_TMP(dest, src, bits, temp) _S_TEMP(dest, src, bits, temp); #define AVX2_S(dest, src, bits) S_TMP(dest, src, bits, S_TEMP) #define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) #define GAMMA0(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest) ; -#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); -#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 3); \ - XOR(dest, G_TEMP, dest) ; + XOR(dest, G_TEMP, dest); AVX2_R(G_TEMP, src, 3); XOR(dest, G_TEMP, dest); +#define GAMMA0_1(dest, src) AVX2_S(dest, src, 7); AVX2_S(G_TEMP, src, 18); +#define GAMMA0_2(dest, src) XOR(dest, G_TEMP, dest); AVX2_R(G_TEMP, src, 3); \ + XOR(dest, G_TEMP, dest); #define GAMMA1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); \ - XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest) ; -#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); -#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest) ; AVX2_R(G_TEMP, src, 10); \ - XOR(dest, G_TEMP, dest) ; + XOR(dest, G_TEMP, dest); AVX2_R(G_TEMP, src, 10); XOR(dest, G_TEMP, dest); +#define GAMMA1_1(dest, src) AVX2_S(dest, src, 17); AVX2_S(G_TEMP, src, 19); +#define GAMMA1_2(dest, src) XOR(dest, G_TEMP, dest); AVX2_R(G_TEMP, src, 10); \ + XOR(dest, G_TEMP, dest); -#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]) ; \ - BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ; \ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]) ; BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2) ; -#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]) ; \ - BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2) ; +#define FEEDBACK1_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP1toW_I_2[0]); \ + BLEND(0x0c, W_I_2, YMM_TEMP0, W_I_2); +#define FEEDBACK2_to_W_I_2 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08); \ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAP2toW_I_2[0]); BLEND(0x30, W_I_2, YMM_TEMP0, W_I_2); +#define FEEDBACK3_to_W_I_2 MOVE_BYTE(YMM_TEMP0, W_I, mMAP3toW_I_2[0]); \ + BLEND(0xc0, W_I_2, YMM_TEMP0, W_I_2); -#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08) ;\ - MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]) ; BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7) ; +#define FEEDBACK_to_W_I_7 MOVE_128(YMM_TEMP0, W_I, W_I, 0x08);\ + MOVE_BYTE(YMM_TEMP0, YMM_TEMP0, mMAPtoW_I_7[0]); BLEND(0x80, W_I_7, YMM_TEMP0, W_I_7); #undef voitle @@ -1307,69 +1353,69 @@ static int Transform_AVX1_RORX(Sha256* sha256) #define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs);\ + __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs);\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs);\ + __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs);\ + __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs);\ #define MOVE_7_to_15(w_i_15, w_i_7)\ - __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs);\ #define MOVE_I_to_7(w_i_7, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs);\ + __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs);\ + __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs);\ #define MOVE_I_to_2(w_i_2, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs);\ + __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs);\ #define ROTATE_W(w_i_16, w_i_15, w_i_7, w_i_2, w_i)\ - MOVE_15_to_16(w_i_16, w_i_15, w_i_7) ; \ - MOVE_7_to_15(w_i_15, w_i_7) ; \ - MOVE_I_to_7(w_i_7, w_i) ; \ - MOVE_I_to_2(w_i_2, w_i) ;\ + MOVE_15_to_16(w_i_16, w_i_15, w_i_7); \ + MOVE_7_to_15(w_i_15, w_i_7); \ + MOVE_I_to_7(w_i_7, w_i); \ + MOVE_I_to_2(w_i_2, w_i);\ #define _RegToDigest(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs) ;\ + { word32 d;\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d)::SSE_REGs);\ sha256->digest[0] += d;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d)::SSE_REGs);\ sha256->digest[1] += d;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d)::SSE_REGs);\ sha256->digest[2] += d;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d)::SSE_REGs);\ sha256->digest[3] += d;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d)::SSE_REGs);\ sha256->digest[4] += d;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d)::SSE_REGs);\ sha256->digest[5] += d;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d)::SSE_REGs);\ sha256->digest[6] += d;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs) ;\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d)::SSE_REGs);\ sha256->digest[7] += d;\ } #define _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ - { word32 d[8] ;\ - __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs) ;\ - __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs) ;\ + { word32 d[8];\ + __asm__ volatile("movl %"#S_0", %0":"=r"(d[0])::SSE_REGs);\ + __asm__ volatile("movl %"#S_1", %0":"=r"(d[1])::SSE_REGs);\ + __asm__ volatile("movl %"#S_2", %0":"=r"(d[2])::SSE_REGs);\ + __asm__ volatile("movl %"#S_3", %0":"=r"(d[3])::SSE_REGs);\ + __asm__ volatile("movl %"#S_4", %0":"=r"(d[4])::SSE_REGs);\ + __asm__ volatile("movl %"#S_5", %0":"=r"(d[5])::SSE_REGs);\ + __asm__ volatile("movl %"#S_6", %0":"=r"(d[6])::SSE_REGs);\ + __asm__ volatile("movl %"#S_7", %0":"=r"(d[7])::SSE_REGs);\ printf("S[0..7]=%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);\ - __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs) ;\ - __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs) ;\ + __asm__ volatile("movl %0, %"#S_0::"r"(d[0]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_1::"r"(d[1]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_2::"r"(d[2]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_3::"r"(d[3]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_4::"r"(d[4]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_5::"r"(d[5]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_6::"r"(d[6]):SSE_REGs);\ + __asm__ volatile("movl %0, %"#S_7::"r"(d[7]):SSE_REGs);\ } @@ -1382,383 +1428,382 @@ static int Transform_AVX1_RORX(Sha256* sha256) #define DumS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 )\ _DumpS(S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7 ) - + /* Byte swap Masks to ensure that rest of the words are filled with zero's. */ - static const unsigned long mBYTE_FLIP_MASK_16[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_15[] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_7 [] = - { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b } ; - static const unsigned long mBYTE_FLIP_MASK_2 [] = - { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 } ; - - static const unsigned long mMAPtoW_I_7[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 } ; - static const unsigned long mMAP1toW_I_2[] = - { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 } ; - static const unsigned long mMAP2toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 } ; - static const unsigned long mMAP3toW_I_2[] = - { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 } ; - + static const unsigned long mBYTE_FLIP_MASK_16[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b }; + static const unsigned long mBYTE_FLIP_MASK_15[] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x0c0d0e0f08090a0b }; + static const unsigned long mBYTE_FLIP_MASK_7 [] = + { 0x0405060700010203, 0x0c0d0e0f08090a0b, 0x0405060700010203, 0x8080808008090a0b }; + static const unsigned long mBYTE_FLIP_MASK_2 [] = + { 0x0405060700010203, 0x8080808080808080, 0x8080808080808080, 0x8080808080808080 }; + + static const unsigned long mMAPtoW_I_7[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0302010080808080 }; + static const unsigned long mMAP1toW_I_2[] = + { 0x8080808080808080, 0x0706050403020100, 0x8080808080808080, 0x8080808080808080 }; + static const unsigned long mMAP2toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x0f0e0d0c0b0a0908, 0x8080808080808080 }; + static const unsigned long mMAP3toW_I_2[] = + { 0x8080808080808080, 0x8080808080808080, 0x8080808080808080, 0x0706050403020100 }; + static int Transform_AVX2(Sha256* sha256) { +#ifdef WOLFSSL_SMALL_STACK + word32* W_K; + W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W_K == NULL) + return MEMORY_E; +#else + word32 W_K[64]; +#endif - #ifdef WOLFSSL_SMALL_STACK - word32* W_K; - W_K = (word32*) XMALLOC(sizeof(word32) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (W_K == NULL) - return MEMORY_E; - #else - word32 W_K[64] ; - #endif - - MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]) ; - MOVE_to_REG(W_I, sha256->buffer[8]) ; BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]) ; - MOVE_to_REG(W_I_7, sha256->buffer[16-7]) ; BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]) ; - MOVE_to_REG(W_I_2, sha256->buffer[16-2]) ; BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]) ; - - DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; - - ADD_MEM(W_K_TEMP, W_I_16, K[0]) ; - MOVE_to_MEM(W_K[0], W_K_TEMP) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3) ; - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7) ; - - ADD_MEM(YMM_TEMP0, W_I, K[8]) ; - MOVE_to_MEM(W_K[8], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - - MOVE_to_REG(YMM_TEMP0, K[16]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[16], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - - MOVE_to_REG(YMM_TEMP0, K[24]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[24], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - GAMMA1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - - MOVE_to_REG(YMM_TEMP0, K[32]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[32], YMM_TEMP0) ; - - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - - MOVE_to_REG(YMM_TEMP0, K[40]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[40], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - - MOVE_to_REG(YMM_TEMP0, K[48]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[48], YMM_TEMP0) ; - - /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ - RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_1(W_I_TEMP, W_I_15) ; - RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - GAMMA0_2(W_I_TEMP, W_I_15) ; - RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48) ; - ADD(W_I_TEMP, W_I_16, W_I_TEMP) ;/* for saving W_I before adding incomplete W_I_7 */ - RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - ADD(W_I, W_I_7, W_I_TEMP); - RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - ADD(W_I, W_I, YMM_TEMP0) ;/* now W[16..17] are completed */ - RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK1_to_W_I_2 ; - RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50) ; - FEEDBACK_to_W_I_7 ; - RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - ADD(W_I_TEMP, W_I_7, W_I_TEMP); - RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ;/* now W[16..19] are completed */ - RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - FEEDBACK2_to_W_I_2 ; - RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..21] are completed */ - RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53) ; - FEEDBACK3_to_W_I_2 ; - RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_1(YMM_TEMP0, W_I_2) ; - RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - GAMMA1_2(YMM_TEMP0, W_I_2) ; - RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54) ; - ADD(W_I, W_I_TEMP, YMM_TEMP0) ; /* now W[16..23] are completed */ - RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - - MOVE_to_REG(YMM_TEMP0, K[56]) ; - RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I) ; - RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55) ; - ADD(YMM_TEMP0, YMM_TEMP0, W_I) ; - MOVE_to_MEM(W_K[56], YMM_TEMP0) ; - - RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56) ; - RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57) ; - RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58) ; - RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59) ; - - RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60) ; - RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61) ; - RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62) ; - RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63) ; - - RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7) ; + MOVE_to_REG(W_I_16, sha256->buffer[0]); BYTE_SWAP(W_I_16, mBYTE_FLIP_MASK_16[0]); + MOVE_to_REG(W_I_15, sha256->buffer[1]); BYTE_SWAP(W_I_15, mBYTE_FLIP_MASK_15[0]); + MOVE_to_REG(W_I, sha256->buffer[8]); BYTE_SWAP(W_I, mBYTE_FLIP_MASK_16[0]); + MOVE_to_REG(W_I_7, sha256->buffer[16-7]); BYTE_SWAP(W_I_7, mBYTE_FLIP_MASK_7[0]); + MOVE_to_REG(W_I_2, sha256->buffer[16-2]); BYTE_SWAP(W_I_2, mBYTE_FLIP_MASK_2[0]); + + DigestToReg(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7); + + ADD_MEM(W_K_TEMP, W_I_16, K[0]); + MOVE_to_MEM(W_K[0], W_K_TEMP); + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,0); + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,1); + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,2); + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,3); + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,4); + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,5); + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,6); + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,7); + + ADD_MEM(YMM_TEMP0, W_I, K[8]); + MOVE_to_MEM(W_K[8], YMM_TEMP0); + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8); + GAMMA0_1(W_I_TEMP, W_I_15); + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8); + GAMMA0_2(W_I_TEMP, W_I_15); + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,8); + ADD(W_I_TEMP, W_I_16, W_I_TEMP);/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9); + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,9); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10); + ADD(W_I, W_I, YMM_TEMP0);/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10); + FEEDBACK1_to_W_I_2; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,10); + FEEDBACK_to_W_I_7; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11); + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,11); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12); + ADD(W_I, W_I_TEMP, YMM_TEMP0);/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12); + FEEDBACK2_to_W_I_2; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,12); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,13); + FEEDBACK3_to_W_I_2; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14); + GAMMA1(YMM_TEMP0, W_I_2); + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14); + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,14); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15); + + MOVE_to_REG(YMM_TEMP0, K[16]); + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15); + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I); + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,15); + ADD(YMM_TEMP0, YMM_TEMP0, W_I); + MOVE_to_MEM(W_K[16], YMM_TEMP0); + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16); + GAMMA0_1(W_I_TEMP, W_I_15); + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16); + GAMMA0_2(W_I_TEMP, W_I_15); + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,16); + ADD(W_I_TEMP, W_I_16, W_I_TEMP);/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17); + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,17); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18); + ADD(W_I, W_I, YMM_TEMP0);/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18); + FEEDBACK1_to_W_I_2; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,18); + FEEDBACK_to_W_I_7; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19); + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19); + GAMMA1(YMM_TEMP0, W_I_2); + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,19); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20); + ADD(W_I, W_I_TEMP, YMM_TEMP0);/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20); + FEEDBACK2_to_W_I_2; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,20); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,21); + FEEDBACK3_to_W_I_2; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,22); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23); + + MOVE_to_REG(YMM_TEMP0, K[24]); + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23); + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I); + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,23); + ADD(YMM_TEMP0, YMM_TEMP0, W_I); + MOVE_to_MEM(W_K[24], YMM_TEMP0); + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24); + GAMMA0_1(W_I_TEMP, W_I_15); + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24); + GAMMA0_2(W_I_TEMP, W_I_15); + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,24); + ADD(W_I_TEMP, W_I_16, W_I_TEMP);/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25); + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,25); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26); + ADD(W_I, W_I, YMM_TEMP0);/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26); + FEEDBACK1_to_W_I_2; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,26); + FEEDBACK_to_W_I_7; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27); + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,27); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28); + ADD(W_I, W_I_TEMP, YMM_TEMP0);/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28); + FEEDBACK2_to_W_I_2; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,28); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,29); + FEEDBACK3_to_W_I_2; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30); + GAMMA1(YMM_TEMP0, W_I_2); + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30); + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,30); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31); + + MOVE_to_REG(YMM_TEMP0, K[32]); + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31); + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I); + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,31); + ADD(YMM_TEMP0, YMM_TEMP0, W_I); + MOVE_to_MEM(W_K[32], YMM_TEMP0); + + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32); + GAMMA0_1(W_I_TEMP, W_I_15); + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32); + GAMMA0_2(W_I_TEMP, W_I_15); + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,32); + ADD(W_I_TEMP, W_I_16, W_I_TEMP);/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33); + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,33); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34); + ADD(W_I, W_I, YMM_TEMP0);/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34); + FEEDBACK1_to_W_I_2; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,34); + FEEDBACK_to_W_I_7; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35); + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,35); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36); + ADD(W_I, W_I_TEMP, YMM_TEMP0);/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36); + FEEDBACK2_to_W_I_2; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,36); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,37); + FEEDBACK3_to_W_I_2; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,38); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39); + + MOVE_to_REG(YMM_TEMP0, K[40]); + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39); + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I); + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,39); + ADD(YMM_TEMP0, YMM_TEMP0, W_I); + MOVE_to_MEM(W_K[40], YMM_TEMP0); + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40); + GAMMA0_1(W_I_TEMP, W_I_15); + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40); + GAMMA0_2(W_I_TEMP, W_I_15); + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,40); + ADD(W_I_TEMP, W_I_16, W_I_TEMP);/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41); + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,41); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42); + ADD(W_I, W_I, YMM_TEMP0);/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42); + FEEDBACK1_to_W_I_2; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,42); + FEEDBACK_to_W_I_7; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43); + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,43); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44); + ADD(W_I, W_I_TEMP, YMM_TEMP0);/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44); + FEEDBACK2_to_W_I_2; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,44); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,45); + FEEDBACK3_to_W_I_2; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,46); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47); + + MOVE_to_REG(YMM_TEMP0, K[48]); + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47); + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I); + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,47); + ADD(YMM_TEMP0, YMM_TEMP0, W_I); + MOVE_to_MEM(W_K[48], YMM_TEMP0); + + /* W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15] + W[i-16]) */ + RND_0_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48); + GAMMA0_1(W_I_TEMP, W_I_15); + RND_0_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48); + GAMMA0_2(W_I_TEMP, W_I_15); + RND_0_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,48); + ADD(W_I_TEMP, W_I_16, W_I_TEMP);/* for saving W_I before adding incomplete W_I_7 */ + RND_7_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49); + ADD(W_I, W_I_7, W_I_TEMP); + RND_7_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_7_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,49); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_6_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50); + ADD(W_I, W_I, YMM_TEMP0);/* now W[16..17] are completed */ + RND_6_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50); + FEEDBACK1_to_W_I_2; + RND_6_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,50); + FEEDBACK_to_W_I_7; + RND_5_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51); + ADD(W_I_TEMP, W_I_7, W_I_TEMP); + RND_5_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_5_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,51); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_4_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52); + ADD(W_I, W_I_TEMP, YMM_TEMP0);/* now W[16..19] are completed */ + RND_4_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52); + FEEDBACK2_to_W_I_2; + RND_4_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,52); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_3_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_3_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..21] are completed */ + RND_3_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,53); + FEEDBACK3_to_W_I_2; + RND_2_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54); + GAMMA1_1(YMM_TEMP0, W_I_2); + RND_2_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54); + GAMMA1_2(YMM_TEMP0, W_I_2); + RND_2_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,54); + ADD(W_I, W_I_TEMP, YMM_TEMP0); /* now W[16..23] are completed */ + RND_1_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55); + + MOVE_to_REG(YMM_TEMP0, K[56]); + RND_1_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55); + ROTATE_W(W_I_16, W_I_15, W_I_7, W_I_2, W_I); + RND_1_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,55); + ADD(YMM_TEMP0, YMM_TEMP0, W_I); + MOVE_to_MEM(W_K[56], YMM_TEMP0); + + RND_0(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,56); + RND_7(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,57); + RND_6(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,58); + RND_5(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,59); + + RND_4(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,60); + RND_3(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,61); + RND_2(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,62); + RND_1(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7,63); + + RegToDigest(S_0,S_1,S_2,S_3,S_4,S_5,S_6,S_7); #ifdef WOLFSSL_SMALL_STACK XFREE(W_K, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -1769,53 +1814,210 @@ static int Transform_AVX2(Sha256* sha256) #endif /* HAVE_INTEL_AVX2 */ + #ifdef WOLFSSL_SHA224 -int wc_InitSha224(Sha224* sha224) -{ - sha224->digest[0] = 0xc1059ed8; - sha224->digest[1] = 0x367cd507; - sha224->digest[2] = 0x3070dd17; - sha224->digest[3] = 0xf70e5939; - sha224->digest[4] = 0xffc00b31; - sha224->digest[5] = 0x68581511; - sha224->digest[6] = 0x64f98fa7; - sha224->digest[7] = 0xbefa4fa4; - - sha224->buffLen = 0; - sha224->loLen = 0; - sha224->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; -#endif + static int InitSha224(Sha224* sha224) + { - return 0; -} + int ret = 0; -int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) -{ - return Sha256Update((Sha256 *)sha224, data, len); -} + if (sha224 == NULL) { + return BAD_FUNC_ARG; + } + sha224->digest[0] = 0xc1059ed8; + sha224->digest[1] = 0x367cd507; + sha224->digest[2] = 0x3070dd17; + sha224->digest[3] = 0xf70e5939; + sha224->digest[4] = 0xffc00b31; + sha224->digest[5] = 0x68581511; + sha224->digest[6] = 0x64f98fa7; + sha224->digest[7] = 0xbefa4fa4; + + sha224->buffLen = 0; + sha224->loLen = 0; + sha224->hiLen = 0; + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + /* choose best Transform function under this runtime environment */ + set_Transform(); + #endif + + return ret; + } + + int wc_InitSha224_ex(Sha224* sha224, void* heap, int devId) + { + int ret = 0; + + if (sha224 == NULL) + return BAD_FUNC_ARG; + + sha224->heap = heap; + + ret = InitSha224(sha224); + if (ret != 0) + return ret; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + ret = wolfAsync_DevCtxInit(&sha224->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA224, sha224->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } + + int wc_InitSha224(Sha224* sha224) + { + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); + } + + int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) + { + int ret; + + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha224(&sha224->asyncDev, NULL, data, len); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Update((Sha256 *)sha224, data, len); -int wc_Sha224Final(Sha224* sha224, byte* hash) -{ - int ret = Sha256Final((Sha256 *)sha224); - if (ret != 0) return ret; + } + + int wc_Sha224Final(Sha224* sha224, byte* hash) + { + int ret; + + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha224(&sha224->asyncDev, hash, NULL, + SHA224_DIGEST_SIZE); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Final((Sha256*)sha224); + if (ret != 0) + return ret; #if defined(LITTLE_ENDIAN_ORDER) ByteReverseWords(sha224->digest, sha224->digest, SHA224_DIGEST_SIZE); #endif - XMEMCPY(hash, sha224->digest, SHA224_DIGEST_SIZE); + XMEMCPY(hash, sha224->digest, SHA224_DIGEST_SIZE); + + return InitSha224(sha224); /* reset state */ + } - return wc_InitSha224(sha224); /* reset state */ + void wc_Sha224Free(Sha224* sha224) + { + if (sha224 == NULL) + return; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224); + #endif /* WOLFSSL_ASYNC_CRYPT */ + } + +#endif /* WOLFSSL_SHA224 */ + + +int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(Sha256* sha256) +{ + if (sha256 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256); +#endif /* WOLFSSL_ASYNC_CRYPT */ } + +#endif /* !WOLFSSL_TI_HASH */ +#endif /* HAVE_FIPS */ + + +#ifndef WOLFSSL_TI_HASH +#ifdef WOLFSSL_SHA224 + int wc_Sha224GetHash(Sha224* sha224, byte* hash) + { + int ret; + Sha224 tmpSha224; + + if (sha224 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha224Copy(sha224, &tmpSha224); + if (ret == 0) { + ret = wc_Sha224Final(&tmpSha224, hash); + } + return ret; + } + int wc_Sha224Copy(Sha224* src, Sha224* dst) + { + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha224)); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); + #endif + + return ret; + } #endif /* WOLFSSL_SHA224 */ -#endif /* HAVE_FIPS */ +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ + int ret; + Sha256 tmpSha256; -#endif /* WOLFSSL_TI_HAHS */ + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; -#endif /* NO_SHA256 */ + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); + } + return ret; +} +int wc_Sha256Copy(Sha256* src, Sha256* dst) +{ + int ret = 0; + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha256)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} +#endif /* !WOLFSSL_TI_HASH */ + +#endif /* NO_SHA256 */ diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c old mode 100644 new mode 100755 index 9e8b1f7d8c..cb1fe3aed3 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -25,53 +25,95 @@ #endif #include -#include #ifdef WOLFSSL_SHA512 +#include -#ifdef HAVE_FIPS -int wc_InitSha512(Sha512* sha) -{ - return InitSha512_fips(sha); -} - - -int wc_Sha512Update(Sha512* sha, const byte* data, word32 len) -{ - return Sha512Update_fips(sha, data, len); -} - - -int wc_Sha512Final(Sha512* sha, byte* out) -{ - return Sha512Final_fips(sha, out); -} - - -#if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM) - -int wc_InitSha384(Sha384* sha) -{ - return InitSha384_fips(sha); -} +#include +#include +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + int wc_InitSha512(Sha512* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } -int wc_Sha384Update(Sha384* sha, const byte* data, word32 len) -{ - return Sha384Update_fips(sha, data, len); -} + return InitSha512_fips(sha); + } + int wc_InitSha512_ex(Sha512* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha512_fips(sha); + } + int wc_Sha512Update(Sha512* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha512Update_fips(sha, data, len); + } + int wc_Sha512Final(Sha512* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } -int wc_Sha384Final(Sha384* sha, byte* out) -{ - return Sha384Final_fips(sha, out); -} + return Sha512Final_fips(sha, out); + } + void wc_Sha512Free(Sha512* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + #if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM) + int wc_InitSha384(Sha384* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha384_fips(sha); + } + int wc_InitSha384_ex(Sha384* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha384_fips(sha); + } + int wc_Sha384Update(Sha384* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha384Update_fips(sha, data, len); + } + int wc_Sha384Final(Sha384* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha384Final_fips(sha, out); + } + void wc_Sha384Free(Sha384* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + #endif /* WOLFSSL_SHA384 || HAVE_AESGCM */ -#endif /* WOLFSSL_SHA384 */ #else /* else build without using fips */ + #include -#include #ifdef NO_INLINE #include @@ -81,325 +123,335 @@ int wc_Sha384Final(Sha384* sha, byte* out) #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - #if defined(USE_INTEL_SPEEDUP) - #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 #endif #if defined(HAVE_INTEL_AVX1) -/* #define DEBUG_XMM */ + /* #define DEBUG_XMM */ #endif #if defined(HAVE_INTEL_AVX2) -#define HAVE_INTEL_RORX -/* #define DEBUG_YMM */ + #define HAVE_INTEL_RORX + /* #define DEBUG_YMM */ #endif -/***** -Intel AVX1/AVX2 Macro Control Structure -#if defined(HAVE_INteL_SPEEDUP) - #define HAVE_INTEL_AVX1 - #define HAVE_INTEL_AVX2 +#if defined(HAVE_INTEL_RORX) + #define ROTR(func, bits, x) \ + word64 func(word64 x) { word64 ret ;\ + __asm__ ("rorx $"#bits", %1, %0\n\t":"=r"(ret):"r"(x):) ;\ + return ret ;\ + } + + static INLINE ROTR(rotrFixed64_28, 28, x); + static INLINE ROTR(rotrFixed64_34, 34, x); + static INLINE ROTR(rotrFixed64_39, 39, x); + static INLINE ROTR(rotrFixed64_14, 14, x); + static INLINE ROTR(rotrFixed64_18, 18, x); + static INLINE ROTR(rotrFixed64_41, 41, x); + + #define S0_RORX(x) (rotrFixed64_28(x)^rotrFixed64_34(x)^rotrFixed64_39(x)) + #define S1_RORX(x) (rotrFixed64_14(x)^rotrFixed64_18(x)^rotrFixed64_41(x)) +#endif /* HAVE_INTEL_RORX */ + +#if defined(HAVE_BYTEREVERSE64) && \ + !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) + #define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size) + #define ByteReverseWords64_1(buf, size) \ + { unsigned int i ;\ + for(i=0; i< size/sizeof(word64); i++){\ + __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\ + }\ + } #endif -int InitSha512(Sha512* sha512) { - Save/Recover XMM, YMM - ... +static int InitSha512(Sha512* sha512) +{ + if (sha512 == NULL) + return BAD_FUNC_ARG; - Check Intel AVX cpuid flags + sha512->digest[0] = W64LIT(0x6a09e667f3bcc908); + sha512->digest[1] = W64LIT(0xbb67ae8584caa73b); + sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b); + sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1); + sha512->digest[4] = W64LIT(0x510e527fade682d1); + sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f); + sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b); + sha512->digest[7] = W64LIT(0x5be0cd19137e2179); + + sha512->buffLen = 0; + sha512->loLen = 0; + sha512->hiLen = 0; + + return 0; } -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - Transform_AVX1() ; # Function prototype - Transform_AVX2() ; # -#endif - _Transform() { # Native Transform Function body - - } - - int Sha512Update() { - Save/Recover XMM, YMM - ... - } - - int Sha512Final() { - Save/Recover XMM, YMM - ... - } +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + /***** + Intel AVX1/AVX2 Macro Control Structure -#if defined(HAVE_INTEL_AVX1) - - XMM Instructions/INLINE asm Definitions + #if defined(HAVE_INteL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + #endif -#endif + int InitSha512(Sha512* sha512) { + Save/Recover XMM, YMM + ... -#if defined(HAVE_INTEL_AVX2) + Check Intel AVX cpuid flags + } - YMM Instructions/INLINE asm Definitions + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_AVX1(); # Function prototype + Transform_AVX2(); # + #endif -#endif + _Transform() { # Native Transform Function body -#if defnied(HAVE_INTEL_AVX1) - - int Transform_AVX1() { - Stitched Message Sched/Round - } + } -#endif + int Sha512Update() { + Save/Recover XMM, YMM + ... + } -#if defnied(HAVE_INTEL_AVX2) - - int Transform_AVX2() { - Stitched Message Sched/Round - } -#endif + int Sha512Final() { + Save/Recover XMM, YMM + ... + } -*/ + #if defined(HAVE_INTEL_AVX1) -#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + XMM Instructions/INLINE asm Definitions + #endif -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ + #if defined(HAVE_INTEL_AVX2) -#ifndef _MSC_VER - #define cpuid(reg, leaf, sub)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (leaf), "c"(sub)); + YMM Instructions/INLINE asm Definitions - #define XASM_LINK(f) asm(f) -#else + #endif - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - -#define EAX 0 -#define EBX 1 -#define ECX 2 -#define EDX 3 - -#define CPUID_AVX1 0x1 -#define CPUID_AVX2 0x2 -#define CPUID_RDRAND 0x4 -#define CPUID_RDSEED 0x8 -#define CPUID_BMI2 0x10 /* MULX, RORX */ - -#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) -#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) -#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) -#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) -#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) - -static word32 cpuid_check = 0 ; -static word32 cpuid_flags = 0 ; - -static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { - int got_intel_cpu=0; - unsigned int reg[5]; - - reg[4] = '\0' ; - cpuid(reg, 0, 0); - if(XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && - XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && - XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { - got_intel_cpu = 1; - } - if (got_intel_cpu) { - cpuid(reg, leaf, sub); - return((reg[num]>>bit)&0x1) ; - } - return 0 ; -} + #if defnied(HAVE_INTEL_AVX1) + int Transform_AVX1() { + Stitched Message Sched/Round + } -static int set_cpuid_flags() { - if(cpuid_check ==0) { - if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} - if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } - if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } - if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } - if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } - cpuid_check = 1 ; - return 0 ; - } - return 1 ; -} + #endif + #if defnied(HAVE_INTEL_AVX2) -/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha512 */ + int Transform_AVX2() { + Stitched Message Sched/Round + } + #endif -#if defined(HAVE_INTEL_AVX1) -static int Transform_AVX1(Sha512 *sha512) ; -#endif + */ -#if defined(HAVE_INTEL_AVX2) -static int Transform_AVX2(Sha512 *sha512) ; -#if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) -static int Transform_AVX1_RORX(Sha512 *sha512) ; -#endif + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ -#endif + #ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) + #else + + #include + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + #define EAX 0 + #define EBX 1 + #define ECX 2 + #define EDX 3 + + #define CPUID_AVX1 0x1 + #define CPUID_AVX2 0x2 + #define CPUID_RDRAND 0x4 + #define CPUID_RDSEED 0x8 + #define CPUID_BMI2 0x10 /* MULX, RORX */ + + #define IS_INTEL_AVX1 (cpuid_flags & CPUID_AVX1) + #define IS_INTEL_AVX2 (cpuid_flags & CPUID_AVX2) + #define IS_INTEL_BMI2 (cpuid_flags & CPUID_BMI2) + #define IS_INTEL_RDRAND (cpuid_flags & CPUID_RDRAND) + #define IS_INTEL_RDSEED (cpuid_flags & CPUID_RDSEED) + + static word32 cpuid_check = 0; + static word32 cpuid_flags = 0; + + static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { + int got_intel_cpu = 0; + unsigned int reg[5]; + + reg[4] = '\0'; + cpuid(reg, 0, 0); + if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + if (got_intel_cpu) { + cpuid(reg, leaf, sub); + return ((reg[num] >> bit) & 0x1); + } + return 0; + } -static int _Transform(Sha512 *sha512) ; - -static int (*Transform_p)(Sha512* sha512) = _Transform ; -#define Transform(sha512) (*Transform_p)(sha512) + static int set_cpuid_flags() { + if(cpuid_check ==0) { + if(cpuid_flag(1, 0, ECX, 28)){ cpuid_flags |= CPUID_AVX1 ;} + if(cpuid_flag(7, 0, EBX, 5)){ cpuid_flags |= CPUID_AVX2 ; } + if(cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } + if(cpuid_flag(1, 0, ECX, 30)){ cpuid_flags |= CPUID_RDRAND ; } + if(cpuid_flag(7, 0, EBX, 18)){ cpuid_flags |= CPUID_RDSEED ; } + cpuid_check = 1 ; + return 0 ; + } + return 1 ; + } -static void set_Transform(void) { - if(set_cpuid_flags()) return ; -#if defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX2 && IS_INTEL_BMI2){ - Transform_p = Transform_AVX1_RORX; return ; - Transform_p = Transform_AVX2 ; - /* for avoiding warning,"not used" */ - } -#endif -#if defined(HAVE_INTEL_AVX1) - Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : _Transform) ; return ; -#endif - Transform_p = _Transform ; return ; -} + #if defined(HAVE_INTEL_AVX1) + static int Transform_AVX1(Sha512 *sha512); + #endif + #if defined(HAVE_INTEL_AVX2) + static int Transform_AVX2(Sha512 *sha512); + #if defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_RORX) + static int Transform_AVX1_RORX(Sha512 *sha512); + #endif + #endif + static int _Transform(Sha512 *sha512); + static int (*Transform_p)(Sha512* sha512) = _Transform; + #define Transform(sha512) (*Transform_p)(sha512) + + /* Dummy for saving MM_REGs on behalf of Transform */ + /* #if defined(HAVE_INTEL_AVX2) + #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ + "%ymm0","%ymm1","%ymm2","%ymm3","%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11",\ + "%ymm12","%ymm13","%ymm14","%ymm15") + */ + #if defined(HAVE_INTEL_AVX1) + #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ + "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13","xmm14","xmm15") + #endif -#else - #define Transform(sha512) _Transform(sha512) -#endif -/* Dummy for saving MM_REGs on behalf of Transform */ -/* #if defined(HAVE_INTEL_AVX2) - #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ - "%ymm0","%ymm1","%ymm2","%ymm3","%ymm4","%ymm5","%ymm6","%ymm7","%ymm8","%ymm9","%ymm10","%ymm11",\ - "%ymm12","%ymm13","%ymm14","%ymm15") -*/ -#if defined(HAVE_INTEL_AVX1) - #define SAVE_XMM_YMM __asm__ volatile("orq %%r8, %%r8":::\ - "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7","xmm8","xmm9","xmm10","xmm11","xmm12","xmm13","xmm14","xmm15") -#else -#define SAVE_XMM_YMM -#endif + int wc_InitSha512_ex(Sha512* sha512, void* heap, int devId) + { + int ret = InitSha512(sha512); -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + (void)heap; + (void)devId; + + if (set_cpuid_flags()) + return ret; + + #if defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX2 && IS_INTEL_BMI2) { + Transform_p = Transform_AVX1_RORX; return ret; + Transform_p = Transform_AVX2; + /* for avoiding warning,"not used" */ + } + #endif + #if defined(HAVE_INTEL_AVX1) + Transform_p = ((IS_INTEL_AVX1) ? Transform_AVX1 : _Transform); return ret; + #endif + Transform_p = _Transform; -#include + return ret; + } -#endif /* defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) */ +#else + #define Transform(sha512) _Transform(sha512) + int wc_InitSha512_ex(Sha512* sha512, void* heap, int devId) + { + int ret = 0; -#if defined(HAVE_INTEL_RORX) -#define ROTR(func, bits, x) \ -word64 func(word64 x) { word64 ret ;\ - __asm__ ("rorx $"#bits", %1, %0\n\t":"=r"(ret):"r"(x):) ;\ - return ret ;\ -} + if (sha512 == NULL) + return BAD_FUNC_ARG; -static INLINE ROTR(rotrFixed64_28, 28, x) -static INLINE ROTR(rotrFixed64_34, 34, x) -static INLINE ROTR(rotrFixed64_39, 39, x) -static INLINE ROTR(rotrFixed64_14, 14, x) -static INLINE ROTR(rotrFixed64_18, 18, x) -static INLINE ROTR(rotrFixed64_41, 41, x) + sha512->heap = heap; -#define S0_RORX(x) (rotrFixed64_28(x)^rotrFixed64_34(x)^rotrFixed64_39(x)) -#define S1_RORX(x) (rotrFixed64_14(x)^rotrFixed64_18(x)^rotrFixed64_41(x)) -#endif + ret = InitSha512(sha512); + if (ret != 0) + return ret; -#if defined(HAVE_BYTEREVERSE64) && !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) -#define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size) -#define ByteReverseWords64_1(buf, size)\ - { unsigned int i ;\ - for(i=0; i< size/sizeof(word64); i++){\ - __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\ - }\ -} -#endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + ret = wolfAsync_DevCtxInit(&sha512->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA512, sha512->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + return ret; + } -int wc_InitSha512(Sha512* sha512) -{ - sha512->digest[0] = W64LIT(0x6a09e667f3bcc908); - sha512->digest[1] = W64LIT(0xbb67ae8584caa73b); - sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b); - sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1); - sha512->digest[4] = W64LIT(0x510e527fade682d1); - sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f); - sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b); - sha512->digest[7] = W64LIT(0x5be0cd19137e2179); +#endif /* Hardware Acceleration */ - sha512->buffLen = 0; - sha512->loLen = 0; - sha512->hiLen = 0; - -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; /* choose best Transform function under this runtime environment */ +#ifndef SAVE_XMM_YMM + #define SAVE_XMM_YMM #endif - - return 0 ; -} - static const word64 K512[80] = { - W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), - W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), - W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), - W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), - W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), - W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), - W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), - W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), - W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), - W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), - W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), - W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), - W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), - W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), - W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), - W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), - W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), - W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), - W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), - W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), - W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), - W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), - W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), - W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), - W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), - W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), - W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), - W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), - W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), - W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), - W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), - W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), - W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), - W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), - W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), - W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), - W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), - W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), - W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), - W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) }; @@ -452,7 +504,7 @@ static int _Transform(Sha512* sha512) /* over twice as small, but 50% slower */ /* 80 operations, not unrolled */ for (j = 0; j < 80; j += 16) { - int m; + int m; for (m = 0; m < 16; m++) { /* braces needed here for macros {} */ R(m); } @@ -499,9 +551,19 @@ static INLINE void AddLength(Sha512* sha512, word32 len) static INLINE int Sha512Update(Sha512* sha512, const byte* data, word32 len) { + int ret = 0; /* do block size increments */ byte* local = (byte*)sha512->buffer; - SAVE_XMM_YMM ; /* for Intel AVX */ + + if (sha512 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + /* check that internal buffLen is valid */ + if (sha512->buffLen >= SHA512_BLOCK_SIZE) + return BUFFER_E; + + SAVE_XMM_YMM; /* for Intel AVX */ while (len) { word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen); @@ -512,27 +574,39 @@ static INLINE int Sha512Update(Sha512* sha512, const byte* data, word32 len) len -= add; if (sha512->buffLen == SHA512_BLOCK_SIZE) { - int ret; - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif - ByteReverseWords64(sha512->buffer, sha512->buffer, - SHA512_BLOCK_SIZE); - #endif + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif + ByteReverseWords64(sha512->buffer, sha512->buffer, + SHA512_BLOCK_SIZE); + #endif ret = Transform(sha512); if (ret != 0) - return ret; + break; AddLength(sha512, SHA512_BLOCK_SIZE); sha512->buffLen = 0; } } - return 0; + + return ret; } int wc_Sha512Update(Sha512* sha512, const byte* data, word32 len) { + if (sha512 == NULL ||(data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha512(&sha512->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + return Sha512Update(sha512, data, len); } @@ -542,6 +616,10 @@ static INLINE int Sha512Final(Sha512* sha512) byte* local = (byte*)sha512->buffer; int ret; + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + SAVE_XMM_YMM ; /* for Intel AVX */ AddLength(sha512, sha512->buffLen); /* before adding pads */ @@ -549,14 +627,15 @@ static INLINE int Sha512Final(Sha512* sha512) /* pad with zeros */ if (sha512->buffLen > SHA512_PAD_SIZE) { - XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen); + XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE - sha512->buffLen); sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen; - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif +#if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1 && !IS_INTEL_AVX2) + #endif ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE); - #endif + +#endif /* LITTLE_ENDIAN_ORDER */ ret = Transform(sha512); if (ret != 0) return ret; @@ -564,29 +643,29 @@ static INLINE int Sha512Final(Sha512* sha512) sha512->buffLen = 0; } XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen); - + /* put lengths in bits */ - sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + - (sha512->hiLen << 3); + sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) + + (sha512->hiLen << 3); sha512->loLen = sha512->loLen << 3; /* store lengths */ - #if defined(LITTLE_ENDIAN_ORDER) - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(!IS_INTEL_AVX1 && !IS_INTEL_AVX2) - #endif +#if defined(LITTLE_ENDIAN_ORDER) +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1 && !IS_INTEL_AVX2) +#endif ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE); - #endif +#endif /* ! length ordering dependent on digest endian type ! */ sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; - #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) - if(IS_INTEL_AVX1 || IS_INTEL_AVX2) +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX1 || IS_INTEL_AVX2) ByteReverseWords64(&(sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2]), &(sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2]), SHA512_BLOCK_SIZE - SHA512_PAD_SIZE); - #endif +#endif ret = Transform(sha512); if (ret != 0) return ret; @@ -600,88 +679,117 @@ static INLINE int Sha512Final(Sha512* sha512) int wc_Sha512Final(Sha512* sha512, byte* hash) { - int ret = Sha512Final(sha512); + int ret; + + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha512(&sha512->asyncDev, hash, NULL, + SHA512_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final(sha512); if (ret != 0) return ret; XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE); - return wc_InitSha512(sha512); /* reset state */ + return InitSha512(sha512); /* reset state */ +} + + +int wc_InitSha512(Sha512* sha512) +{ + return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID); +} + +void wc_Sha512Free(Sha512* sha512) +{ + if (sha512 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512); +#endif /* WOLFSSL_ASYNC_CRYPT */ } #if defined(HAVE_INTEL_AVX1) -#define Rx_1(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i] ; +#define Rx_1(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i]; #define Rx_2(i) d(i)+=h(i); #define Rx_3(i) h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); #if defined(HAVE_INTEL_RORX) -#define Rx_RORX_1(i) h(i)+=S1_RORX(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i] ; -#define Rx_RORX_2(i) d(i)+=h(i); -#define Rx_RORX_3(i) h(i)+=S0_RORX(a(i))+Maj(a(i),b(i),c(i)); -#endif -#endif + #define Rx_RORX_1(i) h(i)+=S1_RORX(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + W_X[i]; + #define Rx_RORX_2(i) d(i)+=h(i); + #define Rx_RORX_3(i) h(i)+=S0_RORX(a(i))+Maj(a(i),b(i),c(i)); +#endif /* HAVE_INTEL_RORX */ + +#endif /* HAVE_INTEL_AVX1 */ -#if defined(HAVE_INTEL_AVX2) -#define Ry_1(i, w) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + w ; +#if defined(HAVE_INTEL_AVX2) +#define Ry_1(i, w) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j] + w; #define Ry_2(i, w) d(i)+=h(i); #define Ry_3(i, w) h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)); -#endif +#endif /* HAVE_INTEL_AVX2 */ -#if defined(HAVE_INTEL_AVX1) /* INLINE Assember for Intel AVX1 instructions */ +/* INLINE Assember for Intel AVX1 instructions */ +#if defined(HAVE_INTEL_AVX1) #if defined(DEBUG_XMM) + #define SAVE_REG(i) __asm__ volatile("vmovdqu %%xmm"#i", %0 \n\t":"=m"(reg[i][0])::XMM_REGs); + #define RECV_REG(i) __asm__ volatile("vmovdqu %0, %%xmm"#i" \n\t"::"m"(reg[i][0]):XMM_REGs); + + #define _DUMP_REG(REG, name)\ + { word64 buf[16];word64 reg[16][2];int k;\ + SAVE_REG(0); SAVE_REG(1); SAVE_REG(2); SAVE_REG(3); SAVE_REG(4); \ + SAVE_REG(5); SAVE_REG(6); SAVE_REG(7);SAVE_REG(8); SAVE_REG(9); SAVE_REG(10);\ + SAVE_REG(11); SAVE_REG(12); SAVE_REG(13); SAVE_REG(14); SAVE_REG(15); \ + __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::XMM_REGs);\ + printf(" "#name":\t"); for(k=0; k<2; k++) printf("%016lx.", (word64)(buf[k])); printf("\n"); \ + RECV_REG(0); RECV_REG(1); RECV_REG(2); RECV_REG(3); RECV_REG(4);\ + RECV_REG(5); RECV_REG(6); RECV_REG(7); RECV_REG(8); RECV_REG(9);\ + RECV_REG(10); RECV_REG(11); RECV_REG(12); RECV_REG(13); RECV_REG(14); RECV_REG(15);\ + } -#define SAVE_REG(i) __asm__ volatile("vmovdqu %%xmm"#i", %0 \n\t":"=m"(reg[i][0])::XMM_REGs); -#define RECV_REG(i) __asm__ volatile("vmovdqu %0, %%xmm"#i" \n\t"::"m"(reg[i][0]):XMM_REGs); - -#define _DUMP_REG(REG, name)\ - { word64 buf[16] ;word64 reg[16][2];int k ;\ - SAVE_REG(0); SAVE_REG(1); SAVE_REG(2); SAVE_REG(3); SAVE_REG(4); \ - SAVE_REG(5); SAVE_REG(6); SAVE_REG(7);SAVE_REG(8); SAVE_REG(9); SAVE_REG(10);\ - SAVE_REG(11); SAVE_REG(12); SAVE_REG(13); SAVE_REG(14); SAVE_REG(15); \ - __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::XMM_REGs);\ - printf(" "#name":\t") ; for(k=0; k<2; k++) printf("%016lx.", (word64)(buf[k])); printf("\n") ; \ - RECV_REG(0); RECV_REG(1); RECV_REG(2); RECV_REG(3); RECV_REG(4);\ - RECV_REG(5); RECV_REG(6); RECV_REG(7); RECV_REG(8); RECV_REG(9);\ - RECV_REG(10); RECV_REG(11); RECV_REG(12); RECV_REG(13); RECV_REG(14); RECV_REG(15);\ - } - -#define DUMP_REG(REG) _DUMP_REG(REG, #REG) -#define PRINTF(fmt, ...) - + #define DUMP_REG(REG) _DUMP_REG(REG, #REG) + #define PRINTF(fmt, ...) #else - -#define DUMP_REG(REG) -#define PRINTF(fmt, ...) - -#endif + #define DUMP_REG(REG) + #define PRINTF(fmt, ...) +#endif /* DEBUG_XMM */ #define _MOVE_to_REG(xymm, mem) __asm__ volatile("vmovdqu %0, %%"#xymm" "\ - :: "m"(mem):XMM_REGs) ; + :: "m"(mem):XMM_REGs); #define _MOVE_to_MEM(mem,i, xymm) __asm__ volatile("vmovdqu %%"#xymm", %0" :\ - "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::XMM_REGs) ; + "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::XMM_REGs); #define _MOVE(dest, src) __asm__ volatile("vmovdqu %%"#src", %%"\ - #dest" ":::XMM_REGs) ; + #dest" ":::XMM_REGs); #define _S_TEMP(dest, src, bits, temp) __asm__ volatile("vpsrlq $"#bits", %%"\ #src", %%"#dest"\n\tvpsllq $64-"#bits", %%"#src", %%"#temp"\n\tvpor %%"\ - #temp",%%"#dest", %%"#dest" ":::XMM_REGs) ; + #temp",%%"#dest", %%"#dest" ":::XMM_REGs); #define _AVX1_R(dest, src, bits) __asm__ volatile("vpsrlq $"#bits", %%"\ - #src", %%"#dest" ":::XMM_REGs) ; + #src", %%"#dest" ":::XMM_REGs); #define _XOR(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::XMM_REGs) ; + #src2", %%"#dest" ":::XMM_REGs); #define _OR(dest, src1, src2) __asm__ volatile("vpor %%"#src1", %%"\ - #src2", %%"#dest" ":::XMM_REGs) ; + #src2", %%"#dest" ":::XMM_REGs); #define _ADD(dest, src1, src2) __asm__ volatile("vpaddq %%"#src1", %%"\ - #src2", %%"#dest" ":::XMM_REGs) ; + #src2", %%"#dest" ":::XMM_REGs); #define _ADD_MEM(dest, src1, mem) __asm__ volatile("vpaddq %0, %%"#src1", %%"\ - #dest" "::"m"(mem):XMM_REGs) ; + #dest" "::"m"(mem):XMM_REGs); #define MOVE_to_REG(xymm, mem) _MOVE_to_REG(xymm, mem) #define MOVE_to_MEM(mem, i, xymm) _MOVE_to_MEM(mem, i, xymm) -#define MOVE(dest, src) _MOVE(dest, src) +#define MOVE(dest, src) _MOVE(dest, src) #define XOR(dest, src1, src2) _XOR(dest, src1, src2) #define OR(dest, src1, src2) _OR(dest, src1, src2) @@ -692,19 +800,19 @@ int wc_Sha512Final(Sha512* sha512, byte* hash) #define AVX1_R(dest, src, bits) _AVX1_R(dest, src, bits) #define Init_Mask(mask) \ - __asm__ volatile("vmovdqu %0, %%xmm1\n\t"::"m"(mask):"%xmm1") ; - + __asm__ volatile("vmovdqu %0, %%xmm1\n\t"::"m"(mask):"%xmm1"); + #define _W_from_buff1(w, buff, xmm) \ /* X0..3(xmm4..7), W[0..15] = sha512->buffer[0.15]; */\ __asm__ volatile("vmovdqu %1, %%"#xmm"\n\t"\ "vpshufb %%xmm1, %%"#xmm", %%"#xmm"\n\t"\ "vmovdqu %%"#xmm", %0"\ - :"=m"(w): "m"(buff):"%xmm0") ; + :"=m"(w): "m"(buff):"%xmm0"); -#define W_from_buff1(w, buff, xmm) _W_from_buff1(w, buff, xmm) +#define W_from_buff1(w, buff, xmm) _W_from_buff1(w, buff, xmm) #define W_from_buff(w, buff)\ - Init_Mask(mBYTE_FLIP_MASK[0]) ;\ + Init_Mask(mBYTE_FLIP_MASK[0]);\ W_from_buff1(w[0], buff[0], W_0);\ W_from_buff1(w[2], buff[2], W_2);\ W_from_buff1(w[4], buff[4], W_4);\ @@ -713,8 +821,8 @@ int wc_Sha512Final(Sha512* sha512, byte* hash) W_from_buff1(w[10],buff[10],W_10);\ W_from_buff1(w[12],buff[12],W_12);\ W_from_buff1(w[14],buff[14],W_14); - -static word64 mBYTE_FLIP_MASK[] = { 0x0001020304050607, 0x08090a0b0c0d0e0f } ; + +static word64 mBYTE_FLIP_MASK[] = { 0x0001020304050607, 0x08090a0b0c0d0e0f }; #define W_I_15 xmm14 #define W_I_7 xmm11 @@ -735,193 +843,189 @@ static word64 mBYTE_FLIP_MASK[] = { 0x0001020304050607, 0x08090a0b0c0d0e0f } ; #define XMM_REGs -#define s0_1(dest, src) AVX1_S(dest, src, 1); -#define s0_2(dest, src) AVX1_S(G_TEMP, src, 8); XOR(dest, G_TEMP, dest) ; -#define s0_3(dest, src) AVX1_R(G_TEMP, src, 7); XOR(dest, G_TEMP, dest) ; +#define s0_1(dest, src) AVX1_S(dest, src, 1); +#define s0_2(dest, src) AVX1_S(G_TEMP, src, 8); XOR(dest, G_TEMP, dest); +#define s0_3(dest, src) AVX1_R(G_TEMP, src, 7); XOR(dest, G_TEMP, dest); #define s1_1(dest, src) AVX1_S(dest, src, 19); -#define s1_2(dest, src) AVX1_S(G_TEMP, src, 61); XOR(dest, G_TEMP, dest) ; -#define s1_3(dest, src) AVX1_R(G_TEMP, src, 6); XOR(dest, G_TEMP, dest) ; +#define s1_2(dest, src) AVX1_S(G_TEMP, src, 61); XOR(dest, G_TEMP, dest); +#define s1_3(dest, src) AVX1_R(G_TEMP, src, 6); XOR(dest, G_TEMP, dest); + +#define s0_(dest, src) s0_1(dest, src); s0_2(dest, src); s0_3(dest, src) +#define s1_(dest, src) s1_1(dest, src); s1_2(dest, src); s1_3(dest, src) -#define s0_(dest, src) s0_1(dest, src) ; s0_2(dest, src) ; s0_3(dest, src) -#define s1_(dest, src) s1_1(dest, src) ; s1_2(dest, src) ; s1_3(dest, src) - #define Block_xx_1(i) \ - MOVE_to_REG(W_I_15, W_X[(i-15)&15]) ;\ - MOVE_to_REG(W_I_7, W_X[(i- 7)&15]) ;\ - + MOVE_to_REG(W_I_15, W_X[(i-15)&15]);\ + MOVE_to_REG(W_I_7, W_X[(i- 7)&15]);\ + #define Block_xx_2(i) \ - MOVE_to_REG(W_I_2, W_X[(i- 2)&15]) ;\ - MOVE_to_REG(W_I, W_X[(i)]) ;\ - + MOVE_to_REG(W_I_2, W_X[(i- 2)&15]);\ + MOVE_to_REG(W_I, W_X[(i)]);\ + #define Block_xx_3(i) \ - s0_ (XMM_TEMP0, W_I_15) ;\ - + s0_ (XMM_TEMP0, W_I_15);\ + #define Block_xx_4(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - ADD(W_I, W_I, W_I_7) ;\ - + ADD(W_I, W_I, XMM_TEMP0);\ + ADD(W_I, W_I, W_I_7);\ + #define Block_xx_5(i) \ - s1_ (XMM_TEMP0, W_I_2) ;\ - + s1_ (XMM_TEMP0, W_I_2);\ + #define Block_xx_6(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - MOVE_to_MEM(W_X,i, W_I) ;\ - if(i==0)\ - MOVE_to_MEM(W_X,16, W_I) ;\ + ADD(W_I, W_I, XMM_TEMP0);\ + MOVE_to_MEM(W_X,i, W_I);\ + if (i==0)\ + MOVE_to_MEM(W_X,16, W_I);\ #define Block_xx_7(i) \ - MOVE_to_REG(W_I_15, W_X[(i-15)&15]) ;\ - MOVE_to_REG(W_I_7, W_X[(i- 7)&15]) ;\ - + MOVE_to_REG(W_I_15, W_X[(i-15)&15]);\ + MOVE_to_REG(W_I_7, W_X[(i- 7)&15]);\ + #define Block_xx_8(i) \ - MOVE_to_REG(W_I_2, W_X[(i- 2)&15]) ;\ - MOVE_to_REG(W_I, W_X[(i)]) ;\ + MOVE_to_REG(W_I_2, W_X[(i- 2)&15]);\ + MOVE_to_REG(W_I, W_X[(i)]);\ #define Block_xx_9(i) \ - s0_ (XMM_TEMP0, W_I_15) ;\ + s0_ (XMM_TEMP0, W_I_15);\ #define Block_xx_10(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - ADD(W_I, W_I, W_I_7) ;\ + ADD(W_I, W_I, XMM_TEMP0);\ + ADD(W_I, W_I, W_I_7);\ #define Block_xx_11(i) \ - s1_ (XMM_TEMP0, W_I_2) ;\ + s1_ (XMM_TEMP0, W_I_2);\ #define Block_xx_12(i) \ - ADD(W_I, W_I, XMM_TEMP0) ;\ - MOVE_to_MEM(W_X,i, W_I) ;\ - if((i)==0)\ - MOVE_to_MEM(W_X,16, W_I) ;\ - -static INLINE void Block_0_1(word64 *W_X) { Block_xx_1(0) ; } -static INLINE void Block_0_2(word64 *W_X) { Block_xx_2(0) ; } -static INLINE void Block_0_3(void) { Block_xx_3(0) ; } -static INLINE void Block_0_4(void) { Block_xx_4(0) ; } -static INLINE void Block_0_5(void) { Block_xx_5(0) ; } -static INLINE void Block_0_6(word64 *W_X) { Block_xx_6(0) ; } -static INLINE void Block_0_7(word64 *W_X) { Block_xx_7(2) ; } -static INLINE void Block_0_8(word64 *W_X) { Block_xx_8(2) ; } -static INLINE void Block_0_9(void) { Block_xx_9(2) ; } -static INLINE void Block_0_10(void){ Block_xx_10(2) ; } -static INLINE void Block_0_11(void){ Block_xx_11(2) ; } -static INLINE void Block_0_12(word64 *W_X){ Block_xx_12(2) ; } - -static INLINE void Block_4_1(word64 *W_X) { Block_xx_1(4) ; } -static INLINE void Block_4_2(word64 *W_X) { Block_xx_2(4) ; } -static INLINE void Block_4_3(void) { Block_xx_3(4) ; } -static INLINE void Block_4_4(void) { Block_xx_4(4) ; } -static INLINE void Block_4_5(void) { Block_xx_5(4) ; } -static INLINE void Block_4_6(word64 *W_X) { Block_xx_6(4) ; } -static INLINE void Block_4_7(word64 *W_X) { Block_xx_7(6) ; } -static INLINE void Block_4_8(word64 *W_X) { Block_xx_8(6) ; } -static INLINE void Block_4_9(void) { Block_xx_9(6) ; } -static INLINE void Block_4_10(void){ Block_xx_10(6) ; } -static INLINE void Block_4_11(void){ Block_xx_11(6) ; } -static INLINE void Block_4_12(word64 *W_X){ Block_xx_12(6) ; } - -static INLINE void Block_8_1(word64 *W_X) { Block_xx_1(8) ; } -static INLINE void Block_8_2(word64 *W_X) { Block_xx_2(8) ; } -static INLINE void Block_8_3(void) { Block_xx_3(8) ; } -static INLINE void Block_8_4(void) { Block_xx_4(8) ; } -static INLINE void Block_8_5(void) { Block_xx_5(8) ; } -static INLINE void Block_8_6(word64 *W_X) { Block_xx_6(8) ; } -static INLINE void Block_8_7(word64 *W_X) { Block_xx_7(10) ; } -static INLINE void Block_8_8(word64 *W_X) { Block_xx_8(10) ; } -static INLINE void Block_8_9(void) { Block_xx_9(10) ; } -static INLINE void Block_8_10(void){ Block_xx_10(10) ; } -static INLINE void Block_8_11(void){ Block_xx_11(10) ; } -static INLINE void Block_8_12(word64 *W_X){ Block_xx_12(10) ; } - -static INLINE void Block_12_1(word64 *W_X) { Block_xx_1(12) ; } -static INLINE void Block_12_2(word64 *W_X) { Block_xx_2(12) ; } -static INLINE void Block_12_3(void) { Block_xx_3(12) ; } -static INLINE void Block_12_4(void) { Block_xx_4(12) ; } -static INLINE void Block_12_5(void) { Block_xx_5(12) ; } -static INLINE void Block_12_6(word64 *W_X) { Block_xx_6(12) ; } -static INLINE void Block_12_7(word64 *W_X) { Block_xx_7(14) ; } -static INLINE void Block_12_8(word64 *W_X) { Block_xx_8(14) ; } -static INLINE void Block_12_9(void) { Block_xx_9(14) ; } -static INLINE void Block_12_10(void){ Block_xx_10(14) ; } -static INLINE void Block_12_11(void){ Block_xx_11(14) ; } -static INLINE void Block_12_12(word64 *W_X){ Block_xx_12(14) ; } - -#endif + ADD(W_I, W_I, XMM_TEMP0);\ + MOVE_to_MEM(W_X,i, W_I);\ + if ((i)==0)\ + MOVE_to_MEM(W_X,16, W_I);\ + +static INLINE void Block_0_1(word64 *W_X) { Block_xx_1(0); } +static INLINE void Block_0_2(word64 *W_X) { Block_xx_2(0); } +static INLINE void Block_0_3(void) { Block_xx_3(0); } +static INLINE void Block_0_4(void) { Block_xx_4(0); } +static INLINE void Block_0_5(void) { Block_xx_5(0); } +static INLINE void Block_0_6(word64 *W_X) { Block_xx_6(0); } +static INLINE void Block_0_7(word64 *W_X) { Block_xx_7(2); } +static INLINE void Block_0_8(word64 *W_X) { Block_xx_8(2); } +static INLINE void Block_0_9(void) { Block_xx_9(2); } +static INLINE void Block_0_10(void){ Block_xx_10(2); } +static INLINE void Block_0_11(void){ Block_xx_11(2); } +static INLINE void Block_0_12(word64 *W_X){ Block_xx_12(2); } + +static INLINE void Block_4_1(word64 *W_X) { Block_xx_1(4); } +static INLINE void Block_4_2(word64 *W_X) { Block_xx_2(4); } +static INLINE void Block_4_3(void) { Block_xx_3(4); } +static INLINE void Block_4_4(void) { Block_xx_4(4); } +static INLINE void Block_4_5(void) { Block_xx_5(4); } +static INLINE void Block_4_6(word64 *W_X) { Block_xx_6(4); } +static INLINE void Block_4_7(word64 *W_X) { Block_xx_7(6); } +static INLINE void Block_4_8(word64 *W_X) { Block_xx_8(6); } +static INLINE void Block_4_9(void) { Block_xx_9(6); } +static INLINE void Block_4_10(void){ Block_xx_10(6); } +static INLINE void Block_4_11(void){ Block_xx_11(6); } +static INLINE void Block_4_12(word64 *W_X){ Block_xx_12(6); } + +static INLINE void Block_8_1(word64 *W_X) { Block_xx_1(8); } +static INLINE void Block_8_2(word64 *W_X) { Block_xx_2(8); } +static INLINE void Block_8_3(void) { Block_xx_3(8); } +static INLINE void Block_8_4(void) { Block_xx_4(8); } +static INLINE void Block_8_5(void) { Block_xx_5(8); } +static INLINE void Block_8_6(word64 *W_X) { Block_xx_6(8); } +static INLINE void Block_8_7(word64 *W_X) { Block_xx_7(10); } +static INLINE void Block_8_8(word64 *W_X) { Block_xx_8(10); } +static INLINE void Block_8_9(void) { Block_xx_9(10); } +static INLINE void Block_8_10(void){ Block_xx_10(10); } +static INLINE void Block_8_11(void){ Block_xx_11(10); } +static INLINE void Block_8_12(word64 *W_X){ Block_xx_12(10); } + +static INLINE void Block_12_1(word64 *W_X) { Block_xx_1(12); } +static INLINE void Block_12_2(word64 *W_X) { Block_xx_2(12); } +static INLINE void Block_12_3(void) { Block_xx_3(12); } +static INLINE void Block_12_4(void) { Block_xx_4(12); } +static INLINE void Block_12_5(void) { Block_xx_5(12); } +static INLINE void Block_12_6(word64 *W_X) { Block_xx_6(12); } +static INLINE void Block_12_7(word64 *W_X) { Block_xx_7(14); } +static INLINE void Block_12_8(word64 *W_X) { Block_xx_8(14); } +static INLINE void Block_12_9(void) { Block_xx_9(14); } +static INLINE void Block_12_10(void){ Block_xx_10(14); } +static INLINE void Block_12_11(void){ Block_xx_11(14); } +static INLINE void Block_12_12(word64 *W_X){ Block_xx_12(14); } + +#endif /* HAVE_INTEL_AVX1 */ #if defined(HAVE_INTEL_AVX2) static const unsigned long mBYTE_FLIP_MASK_Y[] = - { 0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f } ; + { 0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f }; #define W_from_buff_Y(buff)\ { /* X0..3(ymm9..12), W_X[0..15] = sha512->buffer[0.15]; */\ - __asm__ volatile("vmovdqu %0, %%ymm8\n\t"::"m"(mBYTE_FLIP_MASK_Y[0]):YMM_REGs) ;\ + __asm__ volatile("vmovdqu %0, %%ymm8\n\t"::"m"(mBYTE_FLIP_MASK_Y[0]):YMM_REGs);\ __asm__ volatile("vmovdqu %0, %%ymm12\n\t"\ "vmovdqu %1, %%ymm4\n\t"\ "vpshufb %%ymm8, %%ymm12, %%ymm12\n\t"\ "vpshufb %%ymm8, %%ymm4, %%ymm4\n\t"\ - :: "m"(buff[0]), "m"(buff[4]):YMM_REGs) ;\ + :: "m"(buff[0]), "m"(buff[4]):YMM_REGs);\ __asm__ volatile("vmovdqu %0, %%ymm5\n\t"\ "vmovdqu %1, %%ymm6\n\t"\ "vpshufb %%ymm8, %%ymm5, %%ymm5\n\t"\ "vpshufb %%ymm8, %%ymm6, %%ymm6\n\t"\ - :: "m"(buff[8]), "m"(buff[12]):YMM_REGs) ;\ + :: "m"(buff[8]), "m"(buff[12]):YMM_REGs);\ } #if defined(DEBUG_YMM) + #define SAVE_REG_Y(i) __asm__ volatile("vmovdqu %%ymm"#i", %0 \n\t":"=m"(reg[i-4][0])::YMM_REGs); + #define RECV_REG_Y(i) __asm__ volatile("vmovdqu %0, %%ymm"#i" \n\t"::"m"(reg[i-4][0]):YMM_REGs); + + #define _DUMP_REG_Y(REG, name)\ + { word64 buf[16];word64 reg[16][2];int k;\ + SAVE_REG_Y(4); SAVE_REG_Y(5); SAVE_REG_Y(6); SAVE_REG_Y(7); \ + SAVE_REG_Y(8); SAVE_REG_Y(9); SAVE_REG_Y(10); SAVE_REG_Y(11); SAVE_REG_Y(12);\ + SAVE_REG_Y(13); SAVE_REG_Y(14); SAVE_REG_Y(15); \ + __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::YMM_REGs);\ + printf(" "#name":\t"); for(k=0; k<4; k++) printf("%016lx.", (word64)buf[k]); printf("\n"); \ + RECV_REG_Y(4); RECV_REG_Y(5); RECV_REG_Y(6); RECV_REG_Y(7); \ + RECV_REG_Y(8); RECV_REG_Y(9); RECV_REG_Y(10); RECV_REG_Y(11); RECV_REG_Y(12); \ + RECV_REG_Y(13); RECV_REG_Y(14); RECV_REG_Y(15);\ + } -#define SAVE_REG_Y(i) __asm__ volatile("vmovdqu %%ymm"#i", %0 \n\t":"=m"(reg[i-4][0])::YMM_REGs); -#define RECV_REG_Y(i) __asm__ volatile("vmovdqu %0, %%ymm"#i" \n\t"::"m"(reg[i-4][0]):YMM_REGs); - -#define _DUMP_REG_Y(REG, name)\ - { word64 buf[16] ;word64 reg[16][2];int k ;\ - SAVE_REG_Y(4); SAVE_REG_Y(5); SAVE_REG_Y(6); SAVE_REG_Y(7); \ - SAVE_REG_Y(8); SAVE_REG_Y(9); SAVE_REG_Y(10); SAVE_REG_Y(11); SAVE_REG_Y(12);\ - SAVE_REG_Y(13); SAVE_REG_Y(14); SAVE_REG_Y(15); \ - __asm__ volatile("vmovdqu %%"#REG", %0 \n\t":"=m"(buf[0])::YMM_REGs);\ - printf(" "#name":\t") ; for(k=0; k<4; k++) printf("%016lx.", (word64)buf[k]) ; printf("\n") ; \ - RECV_REG_Y(4); RECV_REG_Y(5); RECV_REG_Y(6); RECV_REG_Y(7); \ - RECV_REG_Y(8); RECV_REG_Y(9); RECV_REG_Y(10); RECV_REG_Y(11); RECV_REG_Y(12); \ - RECV_REG_Y(13); RECV_REG_Y(14); RECV_REG_Y(15);\ - } - -#define DUMP_REG_Y(REG) _DUMP_REG_Y(REG, #REG) -#define DUMP_REG2_Y(REG) _DUMP_REG_Y(REG, #REG) -#define PRINTF_Y(fmt, ...) - + #define DUMP_REG_Y(REG) _DUMP_REG_Y(REG, #REG) + #define DUMP_REG2_Y(REG) _DUMP_REG_Y(REG, #REG) + #define PRINTF_Y(fmt, ...) #else - -#define DUMP_REG_Y(REG) -#define DUMP_REG2_Y(REG) -#define PRINTF_Y(fmt, ...) - -#endif + #define DUMP_REG_Y(REG) + #define DUMP_REG2_Y(REG) + #define PRINTF_Y(fmt, ...) +#endif /* DEBUG_YMM */ #define _MOVE_to_REGy(ymm, mem) __asm__ volatile("vmovdqu %0, %%"#ymm" "\ - :: "m"(mem):YMM_REGs) ; + :: "m"(mem):YMM_REGs); #define _MOVE_to_MEMy(mem,i, ymm) __asm__ volatile("vmovdqu %%"#ymm", %0" \ - : "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::YMM_REGs) ; + : "=m"(mem[i]),"=m"(mem[i+1]),"=m"(mem[i+2]),"=m"(mem[i+3])::YMM_REGs); #define _MOVE_128y(ymm0, ymm1, ymm2, map) __asm__ volatile("vperm2i128 $"\ - #map", %%"#ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs) ; + #map", %%"#ymm2", %%"#ymm1", %%"#ymm0" ":::YMM_REGs); #define _S_TEMPy(dest, src, bits, temp) \ __asm__ volatile("vpsrlq $"#bits", %%"#src", %%"#dest"\n\tvpsllq $64-"#bits\ - ", %%"#src", %%"#temp"\n\tvpor %%"#temp",%%"#dest", %%"#dest" ":::YMM_REGs) ; + ", %%"#src", %%"#temp"\n\tvpor %%"#temp",%%"#dest", %%"#dest" ":::YMM_REGs); #define _AVX2_R(dest, src, bits) __asm__ volatile("vpsrlq $"#bits", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; + #src", %%"#dest" ":::YMM_REGs); #define _XORy(dest, src1, src2) __asm__ volatile("vpxor %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; + #src2", %%"#dest" ":::YMM_REGs); #define _ADDy(dest, src1, src2) __asm__ volatile("vpaddq %%"#src1", %%"\ - #src2", %%"#dest" ":::YMM_REGs) ; + #src2", %%"#dest" ":::YMM_REGs); #define _BLENDy(map, dest, src1, src2) __asm__ volatile("vpblendd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; + #src1", %%"#src2", %%"#dest" ":::YMM_REGs); #define _BLENDQy(map, dest, src1, src2) __asm__ volatile("vblendpd $"#map", %%"\ - #src1", %%"#src2", %%"#dest" ":::YMM_REGs) ; + #src1", %%"#src2", %%"#dest" ":::YMM_REGs); #define _PERMQy(map, dest, src) __asm__ volatile("vpermq $"#map", %%"\ - #src", %%"#dest" ":::YMM_REGs) ; + #src", %%"#dest" ":::YMM_REGs); #define MOVE_to_REGy(ymm, mem) _MOVE_to_REGy(ymm, mem) #define MOVE_to_MEMy(mem, i, ymm) _MOVE_to_MEMy(mem, i, ymm) -#define MOVE_128y(ymm0, ymm1, ymm2, map) _MOVE_128y(ymm0, ymm1, ymm2, map) +#define MOVE_128y(ymm0, ymm1, ymm2, map) _MOVE_128y(ymm0, ymm1, ymm2, map) #define XORy(dest, src1, src2) _XORy(dest, src1, src2) #define ADDy(dest, src1, src2) _ADDy(dest, src1, src2) #define BLENDy(map, dest, src1, src2) _BLENDy(map, dest, src1, src2) @@ -934,15 +1038,15 @@ static const unsigned long mBYTE_FLIP_MASK_Y[] = #define AVX2_R(dest, src, bits) _AVX2_R(dest, src, bits) -#define FEEDBACK1_to_W_I_2(w_i_2, w_i) MOVE_128y(YMM_TEMP0, w_i, w_i, 0x08) ;\ - BLENDy(0xf0, w_i_2, YMM_TEMP0, w_i_2) ; +#define FEEDBACK1_to_W_I_2(w_i_2, w_i) MOVE_128y(YMM_TEMP0, w_i, w_i, 0x08);\ + BLENDy(0xf0, w_i_2, YMM_TEMP0, w_i_2); -#define MOVE_W_to_W_I_15(w_i_15, w_0, w_4) BLENDQy(0x1, w_i_15, w_4, w_0) ;\ - PERMQy(0x39, w_i_15, w_i_15) ; -#define MOVE_W_to_W_I_7(w_i_7, w_8, w_12) BLENDQy(0x1, w_i_7, w_12, w_8) ;\ - PERMQy(0x39, w_i_7, w_i_7) ; -#define MOVE_W_to_W_I_2(w_i_2, w_12) BLENDQy(0xc, w_i_2, w_12, w_i_2) ;\ - PERMQy(0x0e, w_i_2, w_i_2) ; +#define MOVE_W_to_W_I_15(w_i_15, w_0, w_4) BLENDQy(0x1, w_i_15, w_4, w_0);\ + PERMQy(0x39, w_i_15, w_i_15); +#define MOVE_W_to_W_I_7(w_i_7, w_8, w_12) BLENDQy(0x1, w_i_7, w_12, w_8);\ + PERMQy(0x39, w_i_7, w_i_7); +#define MOVE_W_to_W_I_2(w_i_2, w_12) BLENDQy(0xc, w_i_2, w_12, w_i_2);\ + PERMQy(0x0e, w_i_2, w_i_2); #define W_I_16y ymm8 @@ -967,64 +1071,63 @@ static const unsigned long mBYTE_FLIP_MASK_Y[] = /* "%ymm7","%ymm8","%ymm9","%ymm10","%ymm11","%ymm12","%ymm13","%ymm14","%ymm15"*/ #define MOVE_15_to_16(w_i_16, w_i_15, w_i_7)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_15", %%"#w_i_15", %%"#w_i_15" ":::YMM_REGs);\ + __asm__ volatile("vpblendd $0x08, %%"#w_i_15", %%"#w_i_7", %%"#w_i_16" ":::YMM_REGs);\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i_7", %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs);\ + __asm__ volatile("vpblendd $0x80, %%"#w_i_15", %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs);\ + __asm__ volatile("vpshufd $0x93, %%"#w_i_16", %%"#w_i_16" ":::YMM_REGs);\ #define MOVE_7_to_15(w_i_15, w_i_7)\ - __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs) ;\ + __asm__ volatile("vmovdqu %%"#w_i_7", %%"#w_i_15" ":::YMM_REGs);\ #define MOVE_I_to_7(w_i_7, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_7" ":::YMM_REGs);\ + __asm__ volatile("vpblendd $0x01, %%"#w_i_7", %%"#w_i", %%"#w_i_7" ":::YMM_REGs);\ + __asm__ volatile("vpshufd $0x39, %%"#w_i_7", %%"#w_i_7" ":::YMM_REGs);\ #define MOVE_I_to_2(w_i_2, w_i)\ - __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs) ;\ - __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs) ;\ + __asm__ volatile("vperm2i128 $0x01, %%"#w_i", %%"#w_i", %%"#w_i_2" ":::YMM_REGs);\ + __asm__ volatile("vpshufd $0x0e, %%"#w_i_2", %%"#w_i_2" ":::YMM_REGs);\ -#endif +#endif /* HAVE_INTEL_AVX2 */ /*** Transform Body ***/ #if defined(HAVE_INTEL_AVX1) - static int Transform_AVX1(Sha512* sha512) { const word64* K = K512; - word64 W_X[16+4]; + word64 W_X[16+4] = {0}; word32 j; word64 T[8]; + /* Copy digest to working vars */ XMEMCPY(T, sha512->digest, sizeof(T)); - W_from_buff(W_X, sha512->buffer) ; + W_from_buff(W_X, sha512->buffer); for (j = 0; j < 80; j += 16) { - Rx_1( 0); Block_0_1(W_X); Rx_2( 0); Block_0_2(W_X); Rx_3( 0); Block_0_3(); - Rx_1( 1); Block_0_4(); Rx_2( 1); Block_0_5(); Rx_3( 1); Block_0_6(W_X); + Rx_1( 0); Block_0_1(W_X); Rx_2( 0); Block_0_2(W_X); Rx_3( 0); Block_0_3(); + Rx_1( 1); Block_0_4(); Rx_2( 1); Block_0_5(); Rx_3( 1); Block_0_6(W_X); Rx_1( 2); Block_0_7(W_X); Rx_2( 2); Block_0_8(W_X); Rx_3( 2); Block_0_9(); - Rx_1( 3); Block_0_10();Rx_2( 3); Block_0_11();Rx_3( 3); Block_0_12(W_X); - - Rx_1( 4); Block_4_1(W_X); Rx_2( 4); Block_4_2(W_X); Rx_3( 4); Block_4_3(); - Rx_1( 5); Block_4_4(); Rx_2( 5); Block_4_5(); Rx_3( 5); Block_4_6(W_X); + Rx_1( 3); Block_0_10();Rx_2( 3); Block_0_11();Rx_3( 3); Block_0_12(W_X); + + Rx_1( 4); Block_4_1(W_X); Rx_2( 4); Block_4_2(W_X); Rx_3( 4); Block_4_3(); + Rx_1( 5); Block_4_4(); Rx_2( 5); Block_4_5(); Rx_3( 5); Block_4_6(W_X); Rx_1( 6); Block_4_7(W_X); Rx_2( 6); Block_4_8(W_X); Rx_3( 6); Block_4_9(); - Rx_1( 7); Block_4_10();Rx_2( 7); Block_4_11();Rx_3( 7); Block_4_12(W_X); - - Rx_1( 8); Block_8_1(W_X); Rx_2( 8); Block_8_2(W_X); Rx_3( 8); Block_8_3(); - Rx_1( 9); Block_8_4(); Rx_2( 9); Block_8_5(); Rx_3( 9); Block_8_6(W_X); + Rx_1( 7); Block_4_10();Rx_2( 7); Block_4_11();Rx_3( 7); Block_4_12(W_X); + + Rx_1( 8); Block_8_1(W_X); Rx_2( 8); Block_8_2(W_X); Rx_3( 8); Block_8_3(); + Rx_1( 9); Block_8_4(); Rx_2( 9); Block_8_5(); Rx_3( 9); Block_8_6(W_X); Rx_1(10); Block_8_7(W_X); Rx_2(10); Block_8_8(W_X); Rx_3(10); Block_8_9(); - Rx_1(11); Block_8_10();Rx_2(11); Block_8_11();Rx_3(11); Block_8_12(W_X); - - Rx_1(12); Block_12_1(W_X); Rx_2(12); Block_12_2(W_X); Rx_3(12); Block_12_3(); - Rx_1(13); Block_12_4(); Rx_2(13); Block_12_5(); Rx_3(13); Block_12_6(W_X); + Rx_1(11); Block_8_10();Rx_2(11); Block_8_11();Rx_3(11); Block_8_12(W_X); + + Rx_1(12); Block_12_1(W_X); Rx_2(12); Block_12_2(W_X); Rx_3(12); Block_12_3(); + Rx_1(13); Block_12_4(); Rx_2(13); Block_12_5(); Rx_3(13); Block_12_6(W_X); Rx_1(14); Block_12_7(W_X); Rx_2(14); Block_12_8(W_X); Rx_3(14); Block_12_9(); - Rx_1(15); Block_12_10();Rx_2(15); Block_12_11();Rx_3(15); Block_12_12(W_X); + Rx_1(15); Block_12_10();Rx_2(15); Block_12_11();Rx_3(15); Block_12_12(W_X); } /* Add the working vars back into digest */ - sha512->digest[0] += a(0); sha512->digest[1] += b(0); sha512->digest[2] += c(0); @@ -1035,67 +1138,66 @@ static int Transform_AVX1(Sha512* sha512) sha512->digest[7] += h(0); /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) +#if !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) XMEMSET(W_X, 0, sizeof(word64) * 16); - #endif +#endif XMEMSET(T, 0, sizeof(T)); return 0; } - -#endif +#endif /* HAVE_INTEL_AVX1 */ #if defined(HAVE_INTEL_AVX2) && defined(HAVE_INTEL_AVX1) && defined(HAVE_INTEL_RORX) - static int Transform_AVX1_RORX(Sha512* sha512) { const word64* K = K512; - word64 W_X[16+4]; + word64 W_X[16+4] = {0}; word32 j; word64 T[8]; + /* Copy digest to working vars */ XMEMCPY(T, sha512->digest, sizeof(T)); - W_from_buff(W_X, sha512->buffer) ; + W_from_buff(W_X, sha512->buffer); for (j = 0; j < 80; j += 16) { - Rx_RORX_1( 0); Block_0_1(W_X); Rx_RORX_2( 0); Block_0_2(W_X); - Rx_RORX_3( 0); Block_0_3(); - Rx_RORX_1( 1); Block_0_4(); Rx_RORX_2( 1); Block_0_5(); - Rx_RORX_3( 1); Block_0_6(W_X); - Rx_RORX_1( 2); Block_0_7(W_X); Rx_RORX_2( 2); Block_0_8(W_X); + Rx_RORX_1( 0); Block_0_1(W_X); Rx_RORX_2( 0); Block_0_2(W_X); + Rx_RORX_3( 0); Block_0_3(); + Rx_RORX_1( 1); Block_0_4(); Rx_RORX_2( 1); Block_0_5(); + Rx_RORX_3( 1); Block_0_6(W_X); + Rx_RORX_1( 2); Block_0_7(W_X); Rx_RORX_2( 2); Block_0_8(W_X); Rx_RORX_3( 2); Block_0_9(); Rx_RORX_1( 3); Block_0_10();Rx_RORX_2( 3); Block_0_11(); - Rx_RORX_3( 3); Block_0_12(W_X); - - Rx_RORX_1( 4); Block_4_1(W_X); Rx_RORX_2( 4); Block_4_2(W_X); - Rx_RORX_3( 4); Block_4_3(); - Rx_RORX_1( 5); Block_4_4(); Rx_RORX_2( 5); Block_4_5(); - Rx_RORX_3( 5); Block_4_6(W_X); - Rx_RORX_1( 6); Block_4_7(W_X); Rx_RORX_2( 6); Block_4_8(W_X); + Rx_RORX_3( 3); Block_0_12(W_X); + + Rx_RORX_1( 4); Block_4_1(W_X); Rx_RORX_2( 4); Block_4_2(W_X); + Rx_RORX_3( 4); Block_4_3(); + Rx_RORX_1( 5); Block_4_4(); Rx_RORX_2( 5); Block_4_5(); + Rx_RORX_3( 5); Block_4_6(W_X); + Rx_RORX_1( 6); Block_4_7(W_X); Rx_RORX_2( 6); Block_4_8(W_X); Rx_RORX_3( 6); Block_4_9(); Rx_RORX_1( 7); Block_4_10();Rx_RORX_2( 7); Block_4_11(); - Rx_RORX_3( 7); Block_4_12(W_X); - - Rx_RORX_1( 8); Block_8_1(W_X); Rx_RORX_2( 8); Block_8_2(W_X); - Rx_RORX_3( 8); Block_8_3(); - Rx_RORX_1( 9); Block_8_4(); Rx_RORX_2( 9); Block_8_5(); - Rx_RORX_3( 9); Block_8_6(W_X); - Rx_RORX_1(10); Block_8_7(W_X); Rx_RORX_2(10); Block_8_8(W_X); + Rx_RORX_3( 7); Block_4_12(W_X); + + Rx_RORX_1( 8); Block_8_1(W_X); Rx_RORX_2( 8); Block_8_2(W_X); + Rx_RORX_3( 8); Block_8_3(); + Rx_RORX_1( 9); Block_8_4(); Rx_RORX_2( 9); Block_8_5(); + Rx_RORX_3( 9); Block_8_6(W_X); + Rx_RORX_1(10); Block_8_7(W_X); Rx_RORX_2(10); Block_8_8(W_X); Rx_RORX_3(10); Block_8_9(); Rx_RORX_1(11); Block_8_10();Rx_RORX_2(11); Block_8_11(); - Rx_RORX_3(11); Block_8_12(W_X); - - Rx_RORX_1(12); Block_12_1(W_X); Rx_RORX_2(12); Block_12_2(W_X); - Rx_RORX_3(12); Block_12_3(); - Rx_RORX_1(13); Block_12_4(); Rx_RORX_2(13); Block_12_5(); - Rx_RORX_3(13); Block_12_6(W_X); - Rx_RORX_1(14); Block_12_7(W_X); Rx_RORX_2(14); Block_12_8(W_X); + Rx_RORX_3(11); Block_8_12(W_X); + + Rx_RORX_1(12); Block_12_1(W_X); Rx_RORX_2(12); Block_12_2(W_X); + Rx_RORX_3(12); Block_12_3(); + Rx_RORX_1(13); Block_12_4(); Rx_RORX_2(13); Block_12_5(); + Rx_RORX_3(13); Block_12_6(W_X); + Rx_RORX_1(14); Block_12_7(W_X); Rx_RORX_2(14); Block_12_8(W_X); Rx_RORX_3(14); Block_12_9(); Rx_RORX_1(15); Block_12_10();Rx_RORX_2(15); Block_12_11(); - Rx_RORX_3(15); Block_12_12(W_X); + Rx_RORX_3(15); Block_12_12(W_X); } - /* Add the working vars back into digest */ + /* Add the working vars back into digest */ sha512->digest[0] += a(0); sha512->digest[1] += b(0); sha512->digest[2] += c(0); @@ -1106,176 +1208,176 @@ static int Transform_AVX1_RORX(Sha512* sha512) sha512->digest[7] += h(0); /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) +#if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) XMEMSET(W_X, 0, sizeof(word64) * 16); - #endif +#endif XMEMSET(T, 0, sizeof(T)); return 0; } -#endif +#endif /* HAVE_INTEL_AVX2 && HAVE_INTEL_AVX1 && HAVE_INTEL_RORX */ #if defined(HAVE_INTEL_AVX2) -#define s0_1y(dest, src) AVX2_S(dest, src, 1); -#define s0_2y(dest, src) AVX2_S(G_TEMPy, src, 8); XORy(dest, G_TEMPy, dest) ; -#define s0_3y(dest, src) AVX2_R(G_TEMPy, src, 7); XORy(dest, G_TEMPy, dest) ; +#define s0_1y(dest, src) AVX2_S(dest, src, 1); +#define s0_2y(dest, src) AVX2_S(G_TEMPy, src, 8); XORy(dest, G_TEMPy, dest); +#define s0_3y(dest, src) AVX2_R(G_TEMPy, src, 7); XORy(dest, G_TEMPy, dest); #define s1_1y(dest, src) AVX2_S(dest, src, 19); -#define s1_2y(dest, src) AVX2_S(G_TEMPy, src, 61); XORy(dest, G_TEMPy, dest) ; -#define s1_3y(dest, src) AVX2_R(G_TEMPy, src, 6); XORy(dest, G_TEMPy, dest) ; +#define s1_2y(dest, src) AVX2_S(G_TEMPy, src, 61); XORy(dest, G_TEMPy, dest); +#define s1_3y(dest, src) AVX2_R(G_TEMPy, src, 6); XORy(dest, G_TEMPy, dest); -#define s0_y(dest, src) s0_1y(dest, src) ; s0_2y(dest, src) ; s0_3y(dest, src) -#define s1_y(dest, src) s1_1y(dest, src) ; s1_2y(dest, src) ; s1_3y(dest, src) +#define s0_y(dest, src) s0_1y(dest, src); s0_2y(dest, src); s0_3y(dest, src) +#define s1_y(dest, src) s1_1y(dest, src); s1_2y(dest, src); s1_3y(dest, src) #define Block_Y_xx_1(i, w_0, w_4, w_8, w_12)\ - MOVE_W_to_W_I_15(W_I_15y, w_0, w_4) ;\ - MOVE_W_to_W_I_7 (W_I_7y, w_8, w_12) ;\ - MOVE_W_to_W_I_2 (W_I_2y, w_12) ;\ + MOVE_W_to_W_I_15(W_I_15y, w_0, w_4);\ + MOVE_W_to_W_I_7 (W_I_7y, w_8, w_12);\ + MOVE_W_to_W_I_2 (W_I_2y, w_12);\ #define Block_Y_xx_2(i, w_0, w_4, w_8, w_12)\ - s0_1y (YMM_TEMP0, W_I_15y) ;\ + s0_1y (YMM_TEMP0, W_I_15y);\ #define Block_Y_xx_3(i, w_0, w_4, w_8, w_12)\ - s0_2y (YMM_TEMP0, W_I_15y) ;\ + s0_2y (YMM_TEMP0, W_I_15y);\ #define Block_Y_xx_4(i, w_0, w_4, w_8, w_12)\ - s0_3y (YMM_TEMP0, W_I_15y) ;\ + s0_3y (YMM_TEMP0, W_I_15y);\ #define Block_Y_xx_5(i, w_0, w_4, w_8, w_12)\ - ADDy(W_I_TEMPy, w_0, YMM_TEMP0) ;\ + ADDy(W_I_TEMPy, w_0, YMM_TEMP0);\ #define Block_Y_xx_6(i, w_0, w_4, w_8, w_12)\ - ADDy(W_I_TEMPy, W_I_TEMPy, W_I_7y) ;\ - s1_1y (YMM_TEMP0, W_I_2y) ;\ + ADDy(W_I_TEMPy, W_I_TEMPy, W_I_7y);\ + s1_1y (YMM_TEMP0, W_I_2y);\ #define Block_Y_xx_7(i, w_0, w_4, w_8, w_12)\ - s1_2y (YMM_TEMP0, W_I_2y) ;\ + s1_2y (YMM_TEMP0, W_I_2y);\ #define Block_Y_xx_8(i, w_0, w_4, w_8, w_12)\ - s1_3y (YMM_TEMP0, W_I_2y) ;\ - ADDy(w_0, W_I_TEMPy, YMM_TEMP0) ;\ + s1_3y (YMM_TEMP0, W_I_2y);\ + ADDy(w_0, W_I_TEMPy, YMM_TEMP0);\ #define Block_Y_xx_9(i, w_0, w_4, w_8, w_12)\ - FEEDBACK1_to_W_I_2(W_I_2y, w_0) ;\ + FEEDBACK1_to_W_I_2(W_I_2y, w_0);\ #define Block_Y_xx_10(i, w_0, w_4, w_8, w_12) \ - s1_1y (YMM_TEMP0, W_I_2y) ;\ + s1_1y (YMM_TEMP0, W_I_2y);\ #define Block_Y_xx_11(i, w_0, w_4, w_8, w_12) \ - s1_2y (YMM_TEMP0, W_I_2y) ;\ + s1_2y (YMM_TEMP0, W_I_2y);\ #define Block_Y_xx_12(i, w_0, w_4, w_8, w_12)\ - s1_3y (YMM_TEMP0, W_I_2y) ;\ - ADDy(w_0, W_I_TEMPy, YMM_TEMP0) ;\ - MOVE_to_MEMy(w,0, w_4) ;\ - - -static INLINE void Block_Y_0_1(void) { Block_Y_xx_1(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_2(void) { Block_Y_xx_2(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_3(void) { Block_Y_xx_3(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_4(void) { Block_Y_xx_4(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_5(void) { Block_Y_xx_5(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_6(void) { Block_Y_xx_6(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_7(void) { Block_Y_xx_7(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_8(void) { Block_Y_xx_8(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_9(void) { Block_Y_xx_9(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_10(void){ Block_Y_xx_10(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_11(void){ Block_Y_xx_11(0, W_0y, W_4y, W_8y, W_12y) ; } -static INLINE void Block_Y_0_12(word64 *w){ Block_Y_xx_12(0, W_0y, W_4y, W_8y, W_12y) ; } - -static INLINE void Block_Y_4_1(void) { Block_Y_xx_1(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_2(void) { Block_Y_xx_2(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_3(void) { Block_Y_xx_3(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_4(void) { Block_Y_xx_4(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_5(void) { Block_Y_xx_5(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_6(void) { Block_Y_xx_6(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_7(void) { Block_Y_xx_7(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_8(void) { Block_Y_xx_8(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_9(void) { Block_Y_xx_9(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_10(void) { Block_Y_xx_10(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_11(void) { Block_Y_xx_11(4, W_4y, W_8y, W_12y, W_0y) ; } -static INLINE void Block_Y_4_12(word64 *w) { Block_Y_xx_12(4, W_4y, W_8y, W_12y, W_0y) ; } - -static INLINE void Block_Y_8_1(void) { Block_Y_xx_1(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_2(void) { Block_Y_xx_2(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_3(void) { Block_Y_xx_3(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_4(void) { Block_Y_xx_4(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_5(void) { Block_Y_xx_5(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_6(void) { Block_Y_xx_6(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_7(void) { Block_Y_xx_7(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_8(void) { Block_Y_xx_8(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_9(void) { Block_Y_xx_9(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_10(void) { Block_Y_xx_10(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_11(void) { Block_Y_xx_11(8, W_8y, W_12y, W_0y, W_4y) ; } -static INLINE void Block_Y_8_12(word64 *w) { Block_Y_xx_12(8, W_8y, W_12y, W_0y, W_4y) ; } - -static INLINE void Block_Y_12_1(void) { Block_Y_xx_1(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_2(void) { Block_Y_xx_2(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_3(void) { Block_Y_xx_3(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_4(void) { Block_Y_xx_4(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_5(void) { Block_Y_xx_5(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_6(void) { Block_Y_xx_6(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_7(void) { Block_Y_xx_7(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_8(void) { Block_Y_xx_8(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_9(void) { Block_Y_xx_9(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_10(void) { Block_Y_xx_10(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_11(void) { Block_Y_xx_11(12, W_12y, W_0y, W_4y, W_8y) ; } -static INLINE void Block_Y_12_12(word64 *w) { Block_Y_xx_12(12, W_12y, W_0y, W_4y, W_8y) ; } + s1_3y (YMM_TEMP0, W_I_2y);\ + ADDy(w_0, W_I_TEMPy, YMM_TEMP0);\ + MOVE_to_MEMy(w,0, w_4);\ + + +static INLINE void Block_Y_0_1(void) { Block_Y_xx_1(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_2(void) { Block_Y_xx_2(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_3(void) { Block_Y_xx_3(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_4(void) { Block_Y_xx_4(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_5(void) { Block_Y_xx_5(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_6(void) { Block_Y_xx_6(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_7(void) { Block_Y_xx_7(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_8(void) { Block_Y_xx_8(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_9(void) { Block_Y_xx_9(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_10(void){ Block_Y_xx_10(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_11(void){ Block_Y_xx_11(0, W_0y, W_4y, W_8y, W_12y); } +static INLINE void Block_Y_0_12(word64 *w){ Block_Y_xx_12(0, W_0y, W_4y, W_8y, W_12y); } + +static INLINE void Block_Y_4_1(void) { Block_Y_xx_1(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_2(void) { Block_Y_xx_2(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_3(void) { Block_Y_xx_3(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_4(void) { Block_Y_xx_4(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_5(void) { Block_Y_xx_5(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_6(void) { Block_Y_xx_6(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_7(void) { Block_Y_xx_7(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_8(void) { Block_Y_xx_8(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_9(void) { Block_Y_xx_9(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_10(void) { Block_Y_xx_10(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_11(void) { Block_Y_xx_11(4, W_4y, W_8y, W_12y, W_0y); } +static INLINE void Block_Y_4_12(word64 *w) { Block_Y_xx_12(4, W_4y, W_8y, W_12y, W_0y); } + +static INLINE void Block_Y_8_1(void) { Block_Y_xx_1(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_2(void) { Block_Y_xx_2(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_3(void) { Block_Y_xx_3(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_4(void) { Block_Y_xx_4(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_5(void) { Block_Y_xx_5(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_6(void) { Block_Y_xx_6(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_7(void) { Block_Y_xx_7(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_8(void) { Block_Y_xx_8(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_9(void) { Block_Y_xx_9(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_10(void) { Block_Y_xx_10(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_11(void) { Block_Y_xx_11(8, W_8y, W_12y, W_0y, W_4y); } +static INLINE void Block_Y_8_12(word64 *w) { Block_Y_xx_12(8, W_8y, W_12y, W_0y, W_4y); } + +static INLINE void Block_Y_12_1(void) { Block_Y_xx_1(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_2(void) { Block_Y_xx_2(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_3(void) { Block_Y_xx_3(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_4(void) { Block_Y_xx_4(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_5(void) { Block_Y_xx_5(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_6(void) { Block_Y_xx_6(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_7(void) { Block_Y_xx_7(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_8(void) { Block_Y_xx_8(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_9(void) { Block_Y_xx_9(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_10(void) { Block_Y_xx_10(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_11(void) { Block_Y_xx_11(12, W_12y, W_0y, W_4y, W_8y); } +static INLINE void Block_Y_12_12(word64 *w) { Block_Y_xx_12(12, W_12y, W_0y, W_4y, W_8y); } static int Transform_AVX2(Sha512* sha512) { const word64* K = K512; - word64 w[4] ; - word32 j /*, k*/; + word64 w[4]; + word32 j; word64 T[8]; + /* Copy digest to working vars */ XMEMCPY(T, sha512->digest, sizeof(T)); - W_from_buff_Y(sha512->buffer) ; - MOVE_to_MEMy(w,0, W_0y) ; + W_from_buff_Y(sha512->buffer); + MOVE_to_MEMy(w,0, W_0y); for (j = 0; j < 80; j += 16) { - Ry_1( 0, w[0]); Block_Y_0_1(); Ry_2( 0, w[0]); Block_Y_0_2(); - Ry_3( 0, w[0]); Block_Y_0_3(); - Ry_1( 1, w[1]); Block_Y_0_4(); Ry_2( 1, w[1]); Block_Y_0_5(); - Ry_3( 1, w[1]); Block_Y_0_6(); - Ry_1( 2, w[2]); Block_Y_0_7(); Ry_2( 2, w[2]); Block_Y_0_8(); + Ry_1( 0, w[0]); Block_Y_0_1(); Ry_2( 0, w[0]); Block_Y_0_2(); + Ry_3( 0, w[0]); Block_Y_0_3(); + Ry_1( 1, w[1]); Block_Y_0_4(); Ry_2( 1, w[1]); Block_Y_0_5(); + Ry_3( 1, w[1]); Block_Y_0_6(); + Ry_1( 2, w[2]); Block_Y_0_7(); Ry_2( 2, w[2]); Block_Y_0_8(); Ry_3( 2, w[2]); Block_Y_0_9(); Ry_1( 3, w[3]); Block_Y_0_10();Ry_2( 3, w[3]); Block_Y_0_11(); Ry_3( 3, w[3]); Block_Y_0_12(w); - - Ry_1( 4, w[0]); Block_Y_4_1(); Ry_2( 4, w[0]); Block_Y_4_2(); - Ry_3( 4, w[0]); Block_Y_4_3(); - Ry_1( 5, w[1]); Block_Y_4_4(); Ry_2( 5, w[1]); Block_Y_4_5(); + + Ry_1( 4, w[0]); Block_Y_4_1(); Ry_2( 4, w[0]); Block_Y_4_2(); + Ry_3( 4, w[0]); Block_Y_4_3(); + Ry_1( 5, w[1]); Block_Y_4_4(); Ry_2( 5, w[1]); Block_Y_4_5(); Ry_3( 5, w[1]); Block_Y_4_6(); - Ry_1( 6, w[2]); Block_Y_4_7(); Ry_2( 6, w[2]); Block_Y_4_8(); + Ry_1( 6, w[2]); Block_Y_4_7(); Ry_2( 6, w[2]); Block_Y_4_8(); Ry_3( 6, w[2]); Block_Y_4_9(); - Ry_1( 7, w[3]); Block_Y_4_10(); Ry_2( 7, w[3]);Block_Y_4_11(); - Ry_3( 7, w[3]);Block_Y_4_12(w); - - Ry_1( 8, w[0]); Block_Y_8_1(); Ry_2( 8, w[0]); Block_Y_8_2(); + Ry_1( 7, w[3]); Block_Y_4_10(); Ry_2( 7, w[3]);Block_Y_4_11(); + Ry_3( 7, w[3]);Block_Y_4_12(w); + + Ry_1( 8, w[0]); Block_Y_8_1(); Ry_2( 8, w[0]); Block_Y_8_2(); Ry_3( 8, w[0]); Block_Y_8_3(); - Ry_1( 9, w[1]); Block_Y_8_4(); Ry_2( 9, w[1]); Block_Y_8_5(); + Ry_1( 9, w[1]); Block_Y_8_4(); Ry_2( 9, w[1]); Block_Y_8_5(); Ry_3( 9, w[1]); Block_Y_8_6(); - Ry_1(10, w[2]); Block_Y_8_7(); Ry_2(10, w[2]); Block_Y_8_8(); - Ry_3(10, w[2]); Block_Y_8_9(); + Ry_1(10, w[2]); Block_Y_8_7(); Ry_2(10, w[2]); Block_Y_8_8(); + Ry_3(10, w[2]); Block_Y_8_9(); Ry_1(11, w[3]); Block_Y_8_10();Ry_2(11, w[3]); Block_Y_8_11(); Ry_3(11, w[3]); Block_Y_8_12(w); - - Ry_1(12, w[0]); Block_Y_12_1(); Ry_2(12, w[0]); Block_Y_12_2(); + + Ry_1(12, w[0]); Block_Y_12_1(); Ry_2(12, w[0]); Block_Y_12_2(); Ry_3(12, w[0]); Block_Y_12_3(); - Ry_1(13, w[1]); Block_Y_12_4(); Ry_2(13, w[1]); Block_Y_12_5(); - Ry_3(13, w[1]); Block_Y_12_6(); - Ry_1(14, w[2]); Block_Y_12_7(); Ry_2(14, w[2]); Block_Y_12_8(); + Ry_1(13, w[1]); Block_Y_12_4(); Ry_2(13, w[1]); Block_Y_12_5(); + Ry_3(13, w[1]); Block_Y_12_6(); + Ry_1(14, w[2]); Block_Y_12_7(); Ry_2(14, w[2]); Block_Y_12_8(); Ry_3(14, w[2]); Block_Y_12_9(); Ry_1(15, w[3]); Block_Y_12_10();Ry_2(15, w[3]); Block_Y_12_11(); Ry_3(15, w[3]);Block_Y_12_12(w); } - - /* Add the working vars back into digest */ + /* Add the working vars back into digest */ sha512->digest[0] += a(0); sha512->digest[1] += b(0); sha512->digest[2] += c(0); @@ -1286,20 +1388,27 @@ static int Transform_AVX2(Sha512* sha512) sha512->digest[7] += h(0); /* Wipe variables */ - #if !defined(HAVE_INTEL_AVX1)&&!defined(HAVE_INTEL_AVX2) +#if !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) XMEMSET(W, 0, sizeof(word64) * 16); - #endif +#endif XMEMSET(T, 0, sizeof(T)); return 0; } +#endif /* HAVE_INTEL_AVX2 */ -#endif +/* -------------------------------------------------------------------------- */ +/* SHA384 */ +/* -------------------------------------------------------------------------- */ #ifdef WOLFSSL_SHA384 -int wc_InitSha384(Sha384* sha384) +static int InitSha384(Sha384* sha384) { + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8); sha384->digest[1] = W64LIT(0x629a292a367cd507); sha384->digest[2] = W64LIT(0x9159015a3070dd17); @@ -1313,32 +1422,158 @@ int wc_InitSha384(Sha384* sha384) sha384->loLen = 0; sha384->hiLen = 0; -#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) - set_Transform() ; -#endif - return 0; } int wc_Sha384Update(Sha384* sha384, const byte* data, word32 len) { - return Sha512Update((Sha512 *)sha384, data, len); + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha384(&sha384->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return Sha512Update((Sha512*)sha384, data, len); } int wc_Sha384Final(Sha384* sha384, byte* hash) { - int ret = Sha512Final((Sha512 *)sha384); + int ret; + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha384(&sha384->asyncDev, hash, NULL, + SHA384_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final((Sha512*)sha384); if (ret != 0) return ret; XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE); - return wc_InitSha384(sha384); /* reset state */ + return InitSha384(sha384); /* reset state */ +} + + +int wc_InitSha384_ex(Sha384* sha384, void* heap, int devId) +{ + int ret; + + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + + sha384->heap = heap; + ret = InitSha384(sha384); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384, + sha384->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } + +int wc_InitSha384(Sha384* sha384) +{ + return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID); +} + +void wc_Sha384Free(Sha384* sha384) +{ + if (sha384 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + wolfAsync_DevCtxFree(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + #endif /* WOLFSSL_SHA384 */ #endif /* HAVE_FIPS */ -#endif /* WOLFSSL_SHA512 */ +int wc_Sha512GetHash(Sha512* sha512, byte* hash) +{ + int ret; + Sha512 tmpSha512; + + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha512Copy(sha512, &tmpSha512); + if (ret == 0) { + ret = wc_Sha512Final(&tmpSha512, hash); + } + return ret; +} + +int wc_Sha512Copy(Sha512* src, Sha512* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha512)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} + +#ifdef WOLFSSL_SHA384 +int wc_Sha384GetHash(Sha384* sha384, byte* hash) +{ + int ret; + Sha384 tmpSha384; + + if (sha384 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha384Copy(sha384, &tmpSha384); + if (ret == 0) { + ret = wc_Sha384Final(&tmpSha384, hash); + } + return ret; +} +int wc_Sha384Copy(Sha384* src, Sha384* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha384)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif + + return ret; +} +#endif /* WOLFSSL_SHA384 */ + +#endif /* WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index 388aafde03..5d430d3de3 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -175,7 +175,15 @@ int wc_SignatureVerify( int is_valid_sig = 0; /* Perform verification of signature using provided ECC key */ - ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, &is_valid_sig, (ecc_key*)key); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, + &is_valid_sig, (ecc_key*)key); + } while (ret == WC_PENDING_E); if (ret != 0 || is_valid_sig != 1) { ret = SIG_VERIFY_E; } @@ -198,6 +206,7 @@ int wc_SignatureVerify( /* Otherwise fall-through and perform normal RSA verify against updated * DER encoding + hash */ #endif + FALL_THROUGH; case WC_SIGNATURE_TYPE_RSA: { @@ -212,8 +221,15 @@ int wc_SignatureVerify( plain_data = (byte*)XMALLOC(plain_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (plain_data) { /* Perform verification of signature using provided RSA key */ - ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, plain_len, - (RsaKey*)key); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, + plain_len, (RsaKey*)key); + } while (ret == WC_PENDING_E); if (ret >= 0) { if ((word32)ret == hash_len && XMEMCMP(plain_data, hash_data, hash_len) == 0) { @@ -296,7 +312,15 @@ int wc_SignatureGenerate( case WC_SIGNATURE_TYPE_ECC: #if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) /* Create signature using provided ECC key */ - ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, + rng, (ecc_key*)key); + } while (ret == WC_PENDING_E); #else ret = SIG_TYPE_E; #endif @@ -315,11 +339,19 @@ int wc_SignatureGenerate( /* Otherwise fall-through and perform normal RSA sign against updated * DER encoding + hash */ #endif - + FALL_THROUGH; case WC_SIGNATURE_TYPE_RSA: #ifndef NO_RSA /* Create signature using provided RSA key */ - ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + (RsaKey*)key, rng); + } while (ret == WC_PENDING_E); if (ret >= 0) { *sig_len = ret; ret = 0; /* Success */ diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 246db1d707..a889b05757 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -310,7 +310,8 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, byte digest1[SRP_MAX_DIGEST_SIZE]; byte digest2[SRP_MAX_DIGEST_SIZE]; byte pad = 0; - int i, j, r; + int i, r; + int j = 0; if (!srp || !N || !g || !salt || nSz < gSz) return BAD_FUNC_ARG; @@ -348,8 +349,9 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, /* Set k = H(N, g) */ r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); - for (i = 0; (word32)i < nSz - gSz; i++) - SrpHashUpdate(&hash, &pad, 1); + for (i = 0; (word32)i < nSz - gSz; i++) { + if (!r) r = SrpHashUpdate(&hash, &pad, 1); + } if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); if (!r) r = SrpHashFinal(&hash, srp->k); @@ -454,12 +456,12 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) return mp_read_unsigned_bin(&srp->auth, verifier, size); } -int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) +int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size) { mp_int p; int r; - if (!srp || !private || !size) + if (!srp || !priv || !size) return BAD_FUNC_ARG; if (mp_iszero(&srp->auth) == MP_YES) @@ -468,7 +470,7 @@ int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) r = mp_init(&p); if (r != MP_OKAY) return MP_INIT_E; - if (!r) r = mp_read_unsigned_bin(&p, private, size); + if (!r) r = mp_read_unsigned_bin(&p, priv, size); if (!r) r = mp_mod(&p, &srp->N, &srp->priv); if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0; @@ -551,6 +553,8 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) byte counter[4]; int r = BAD_FUNC_ARG; + XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); + srp->key = (byte*)XMALLOC(2 * digestSz, srp->heap, DYNAMIC_TYPE_SRP); if (srp->key == NULL) return MEMORY_E; @@ -567,7 +571,7 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) if (!r) r = SrpHashUpdate(&hash, secret, size); if (!r) r = SrpHashUpdate(&hash, counter, 4); - if(j + digestSz > srp->keySz) { + if (j + digestSz > srp->keySz) { if (!r) r = SrpHashFinal(&hash, digest); XMEMCPY(srp->key + j, digest, srp->keySz - j); j = srp->keySz; diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 71b5735ea4..c5ccdfb6a2 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -49,6 +49,7 @@ #include #include #include /* will define asm MACROS or C ones */ +#include /* common functions */ #if defined(FREESCALE_LTC_TFM) #include @@ -197,11 +198,7 @@ void s_fp_sub(fp_int *a, fp_int *b, fp_int *c) } /* c = a * b */ -#if defined(FREESCALE_LTC_TFM) -void wolfcrypt_fp_mul(fp_int *A, fp_int *B, fp_int *C) -#else void fp_mul(fp_int *A, fp_int *B, fp_int *C) -#endif { int y, yy, oldused; @@ -479,12 +476,11 @@ void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) pa = FP_SIZE-1; } - if (A == C || B == C) { + /* Always take branch to use tmp variable. This avoids a cache attack for + * determining if C equals A */ + if (1) { fp_init(&tmp); dst = &tmp; - } else { - fp_zero(C); - dst = C; } for (ix = 0; ix < pa; ix++) { @@ -742,11 +738,7 @@ void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) } /* c = a mod b, 0 <= c < b */ -#if defined(FREESCALE_LTC_TFM) -int wolfcrypt_fp_mod(fp_int *a, fp_int *b, fp_int *c) -#else int fp_mod(fp_int *a, fp_int *b, fp_int *c) -#endif { fp_int t; int err; @@ -897,11 +889,7 @@ static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c) } /* c = 1/a (mod b) for odd b only */ -#if defined(FREESCALE_LTC_TFM) -int wolfcrypt_fp_invmod(fp_int *a, fp_int *b, fp_int *c) -#else int fp_invmod(fp_int *a, fp_int *b, fp_int *c) -#endif { fp_int x, y, u, v, B, D; int neg; @@ -993,23 +981,22 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) } /* d = a * b (mod c) */ -#if defined(FREESCALE_LTC_TFM) -int wolfcrypt_fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) -#else int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) -#endif { int err; fp_int t; fp_init(&t); fp_mul(a, b, &t); -#ifdef ALT_ECC_SIZE - err = fp_mod(&t, c, &t); - fp_copy(&t, d); -#else - err = fp_mod(&t, c, d); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(&t, c, &t); + fp_copy(&t, d); + } else #endif + { + err = fp_mod(&t, c, d); + } return err; } @@ -1022,12 +1009,15 @@ int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) fp_init(&t); fp_sub(a, b, &t); -#ifdef ALT_ECC_SIZE - err = fp_mod(&t, c, &t); - fp_copy(&t, d); -#else - err = fp_mod(&t, c, d); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(&t, c, &t); + fp_copy(&t, d); + } else #endif + { + err = fp_mod(&t, c, d); + } return err; } @@ -1040,47 +1030,26 @@ int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) fp_init(&t); fp_add(a, b, &t); -#ifdef ALT_ECC_SIZE - err = fp_mod(&t, c, &t); - fp_copy(&t, d); -#else - err = fp_mod(&t, c, d); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(&t, c, &t); + fp_copy(&t, d); + } else #endif + { + err = fp_mod(&t, c, d); + } return err; } #ifdef TFM_TIMING_RESISTANT -#ifndef WC_NO_CACHE_RESISTANT -/* all off / all on pointer addresses for constant calculations */ -/* ecc.c uses same table */ -const wolfssl_word wc_off_on_addr[2] = -{ -#if defined(WC_64BIT_CPU) - W64LIT(0x0000000000000000), - W64LIT(0xffffffffffffffff) -#elif defined(WC_16BIT_CPU) - 0x0000U, - 0xffffU -#else - /* 32 bit */ - 0x00000000U, - 0xffffffffU -#endif -}; - -#endif /* WC_NO_CACHE_RESISTANT */ - /* timing resistant montgomery ladder based exptmod Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 */ -#if defined(FREESCALE_LTC_TFM) -int _wolfcrypt_fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) -#else static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) -#endif { #ifdef WC_NO_CACHE_RESISTANT fp_int R[2]; @@ -1983,6 +1952,41 @@ void fp_set(fp_int *a, fp_digit b) a->used = a->dp[0] ? 1 : 0; } + +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif +void fp_set_int(fp_int *a, unsigned long b) +{ + int x; + + /* use direct fp_set if b is less than fp_digit max */ + if (b < FP_DIGIT_MAX) { + fp_set (a, b); + return; + } + + fp_zero (a); + + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + fp_mul_2d (a, MP_SET_CHUNK_BITS, a); + + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); + + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + + /* clamp digits */ + fp_clamp(a); +} + /* check if a bit is set */ int fp_is_bit_set (fp_int *a, fp_digit b) { @@ -2063,26 +2067,26 @@ int fp_leading_bit(fp_int *a) void fp_lshd(fp_int *a, int x) { - int y; + int y; - /* move up and truncate as required */ - y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); + /* move up and truncate as required */ + y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); - /* store new size */ - a->used = y + 1; + /* store new size */ + a->used = y + 1; - /* move digits */ - for (; y >= x; y--) { - a->dp[y] = a->dp[y-x]; - } + /* move digits */ + for (; y >= x; y--) { + a->dp[y] = a->dp[y-x]; + } - /* zero lower digits */ - for (; y >= 0; y--) { - a->dp[y] = 0; - } + /* zero lower digits */ + for (; y >= 0; y--) { + a->dp[y] = 0; + } - /* clamp digits */ - fp_clamp(a); + /* clamp digits */ + fp_clamp(a); } @@ -2115,6 +2119,9 @@ void fp_rshb(fp_int *c, int x) /* set the carry to the carry bits of the current word found above */ r = rr; } + + /* clamp digits */ + fp_clamp(c); } @@ -2167,12 +2174,15 @@ void fp_sub_d(fp_int *a, fp_digit b, fp_int *c) fp_int tmp; fp_init(&tmp); fp_set(&tmp, b); -#ifdef ALT_ECC_SIZE - fp_sub(a, &tmp, &tmp); - fp_copy(&tmp, c); -#else - fp_sub(a, &tmp, c); - #endif +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (c->size < FP_SIZE) { + fp_sub(a, &tmp, &tmp); + fp_copy(&tmp, c); + } else +#endif + { + fp_sub(a, &tmp, c); + } } @@ -2186,33 +2196,81 @@ int mp_init (mp_int * a) return MP_OKAY; } -#ifdef ALT_ECC_SIZE void fp_init(fp_int *a) { +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) a->size = FP_SIZE; +#endif +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif fp_zero(a); } void fp_zero(fp_int *a) { + int size = FP_SIZE; a->used = 0; a->sign = FP_ZPOS; - XMEMSET(a->dp, 0, a->size * sizeof(fp_digit)); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); } void fp_clear(fp_int *a) { + int size = FP_SIZE; a->used = 0; a->sign = FP_ZPOS; - ForceZero(a->dp, a->size * sizeof(fp_digit)); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); + fp_free(a); } + +void fp_forcezero (mp_int * a) +{ + int size = FP_SIZE; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; #endif + ForceZero(a->dp, size * sizeof(fp_digit)); +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif + fp_free(a); +} + +void mp_forcezero (mp_int * a) +{ + fp_forcezero(a); +} + +void fp_free(fp_int* a) +{ +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#else + (void)a; +#endif +} /* clear one (frees) */ void mp_clear (mp_int * a) { - fp_zero(a); + if (a == NULL) + return; + fp_clear(a); +} + +void mp_free(mp_int* a) +{ + fp_free(a); } /* handle up to 6 inits */ @@ -2250,14 +2308,28 @@ int mp_sub (mp_int * a, mp_int * b, mp_int * c) } /* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int * a, mp_int * b, mp_int * c) +#else int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif { fp_mul(a, b, c); return MP_OKAY; } +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + fp_mul_d(a, b, c); + return MP_OKAY; +} + /* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#else int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif { return fp_mulmod(a, b, c, d); } @@ -2275,13 +2347,21 @@ int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) } /* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod (mp_int * a, mp_int * b, mp_int * c) +#else int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif { return fp_mod (a, b, c); } /* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#else int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif { return fp_invmod(a, b, c); } @@ -2291,7 +2371,11 @@ int mp_invmod (mp_int * a, mp_int * b, mp_int * c) * embedded in the normal function but that wasted alot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { return fp_exptmod(G, X, P, Y); } @@ -2314,6 +2398,11 @@ int mp_unsigned_bin_size (mp_int * a) return fp_unsigned_bin_size(a); } +int mp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) +{ + return fp_to_unsigned_bin_at_pos(x, t, b); +} + /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { @@ -2341,27 +2430,45 @@ int mp_mul_2d(fp_int *a, int b, fp_int *c) return MP_OKAY; } +int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d) +{ + return fp_div(a, b, c, d); +} + int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) { fp_div_2d(a, b, c, d); return MP_OKAY; } -#ifdef ALT_ECC_SIZE void fp_copy(fp_int *a, fp_int *b) { - if (a != b && b->size >= a->used) { - int x, oldused; - oldused = b->used; + /* if source and destination are different */ + if (a != b) { +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + /* verify a will fit in b */ + if (b->size >= a->used) { + int x, oldused; + oldused = b->used; + b->used = a->used; + b->sign = a->sign; + + XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit)); + + /* zero any excess digits on the destination that we didn't write to */ + for (x = b->used; x < oldused; x++) { + b->dp[x] = 0; + } + } + else { + /* TODO: Handle error case */ + } +#else + /* all dp's are same size, so do straight copy */ b->used = a->used; b->sign = a->sign; - - XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit)); - - /* zero any excess digits on the destination that we didn't write to */ - for (x = b->used; x < oldused; x++) { - b->dp[x] = 0; - } + XMEMCPY(b->dp, a->dp, FP_SIZE * sizeof(fp_digit)); +#endif } } @@ -2372,7 +2479,6 @@ void fp_init_copy(fp_int *a, fp_int* b) fp_copy(b, a); } } -#endif /* fast math wrappers */ int mp_copy(fp_int* a, fp_int* b) @@ -2406,9 +2512,14 @@ void mp_rshb (mp_int* a, int x) fp_rshb(a, x); } -int mp_set_int(mp_int *a, mp_digit b) +void mp_rshd (mp_int* a, int x) +{ + fp_rshd(a, x); +} + +int mp_set_int(mp_int *a, unsigned long b) { - fp_set(a, b); + fp_set_int(a, b); return MP_OKAY; } @@ -2432,12 +2543,17 @@ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c) fp_init(&t); fp_sqr(a, &t); -#ifdef ALT_ECC_SIZE - err = fp_mod(&t, b, &t); - fp_copy(&t, c); -#else - err = fp_mod(&t, b, c); + +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (c->size < FP_SIZE) { + err = fp_mod(&t, b, &t); + fp_copy(&t, c); + } + else #endif + { + err = fp_mod(&t, b, c); + } return err; } @@ -2645,10 +2761,8 @@ int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) switch(err) { case FP_VAL: return MP_VAL; - break; case FP_MEM: return MP_MEM; - break; default: break; } @@ -2850,7 +2964,7 @@ int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) XMEMSET(buf, 0, len); XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); - + return FP_OKAY; } @@ -3008,12 +3122,6 @@ int mp_read_radix(mp_int *a, const char *str, int radix) return fp_read_radix(a, str, radix); } -/* fast math conversion */ -void mp_set(fp_int *a, fp_digit b) -{ - fp_set(a,b); -} - /* fast math conversion */ int mp_sqr(fp_int *A, fp_int *B) { @@ -3059,6 +3167,15 @@ int mp_cnt_lsb(fp_int* a) #endif /* HAVE_ECC */ +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) +/* fast math conversion */ +int mp_set(fp_int *a, fp_digit b) +{ + fp_set(a,b); + return MP_OKAY; +} +#endif + #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ defined(WOLFSSL_DEBUG_MATH) @@ -3174,7 +3291,7 @@ void mp_dump(const char* desc, mp_int* a, byte verbose) char buffer[FP_SIZE * sizeof(fp_digit) * 2]; int size = FP_SIZE; -#ifdef ALT_ECC_SIZE +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) size = a->size; #endif diff --git a/wolfcrypt/src/wc_encrypt.c b/wolfcrypt/src/wc_encrypt.c index dc4e4c1b30..a14e7a451d 100644 --- a/wolfcrypt/src/wc_encrypt.c +++ b/wolfcrypt/src/wc_encrypt.c @@ -32,6 +32,7 @@ #if !defined(NO_AES) && defined(HAVE_AES_CBC) +#ifdef HAVE_AES_DECRYPT int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, const byte* key, word32 keySz, const byte* iv) { @@ -58,6 +59,7 @@ int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, return ret; } +#endif /* HAVE_AES_DECRYPT */ int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, const byte* key, word32 keySz, const byte* iv) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c old mode 100644 new mode 100755 index 669298cb6c..5478b96926 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -28,6 +28,13 @@ #include #include #include +#include +#ifdef HAVE_ECC + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif /* IPP header files for library initialization */ #ifdef HAVE_FAST_RSA @@ -43,6 +50,14 @@ #include #endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + #include +#endif + +#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) + #include +#endif + #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ #pragma warning(disable: 4996) @@ -59,9 +74,31 @@ int wolfCrypt_Init(void) int ret = 0; if (initRefCount == 0) { + WOLFSSL_ENTER("wolfCrypt_Init"); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_HardwareStart(); + if (ret != 0) { + WOLFSSL_MSG("Async hardware start failed"); + return ret; + } + #endif + + #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ret = InitMemoryTracker(); + if (ret != 0) { + WOLFSSL_MSG("InitMemoryTracker failed"); + return ret; + } + #endif + #if WOLFSSL_CRYPT_HW_MUTEX /* If crypto hardware mutex protection is enabled, then initialize it */ - wolfSSL_CryptHwMutexInit(); + ret = wolfSSL_CryptHwMutexInit(); + if (ret != 0) { + WOLFSSL_MSG("Hw crypt mutex init failed"); + return ret; + } #endif /* if defined have fast RSA then initialize Intel IPP */ @@ -74,11 +111,16 @@ int wolfCrypt_Init(void) WOLFSSL_MSG(ippGetStatusString(ret)); WOLFSSL_MSG("Using default fast IPP library"); ret = 0; + (void)ret; /* suppress not read warning */ } #endif #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) - ksdk_port_init(); + ret = ksdk_port_init(); + if (ret != 0) { + WOLFSSL_MSG("KSDK port init failed"); + return ret; + } #endif #ifdef WOLFSSL_ATMEL @@ -89,23 +131,220 @@ int wolfCrypt_Init(void) WOLFSSL_MSG("Using ARM hardware acceleration"); #endif + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + wolfSSL_EVP_init(); + #endif + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + if ((ret = wc_LoggingInit()) != 0) { + WOLFSSL_MSG("Error creating logging mutex"); + return ret; + } + #endif + +#ifdef HAVE_ECC + #ifdef ECC_CACHE_CURVE + if ((ret = wc_ecc_curve_cache_init()) != 0) { + WOLFSSL_MSG("Error creating curve cache"); + return ret; + } + #endif +#endif + initRefCount = 1; } return ret; } + +/* return success value is the same as wolfCrypt_Init */ +int wolfCrypt_Cleanup(void) +{ + int ret = 0; + + if (initRefCount == 1) { + WOLFSSL_ENTER("wolfCrypt_Cleanup"); + +#ifdef HAVE_ECC + #ifdef FP_ECC + wc_ecc_fp_free(); + #endif + #ifdef ECC_CACHE_CURVE + wc_ecc_curve_cache_free(); + #endif +#endif /* HAVE_ECC */ + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + ret = wc_LoggingCleanup(); + #endif + + #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ShowMemoryTracker(); + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_HardwareStop(); + #endif + + initRefCount = 0; /* allow re-init */ + } + + return ret; +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + +/* File Handling Helpers */ +int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = 0; + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + +#ifdef USE_WINDOWS_API + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 4); + XSTRNCAT(ctx->name, "\\*", 3); + + ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData); + if (ctx->hFind == INVALID_HANDLE_VALUE) { + WOLFSSL_MSG("FindFirstFile for path verify locations failed"); + return BAD_PATH_ERROR; + } + + do { + if (ctx->FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 3); + XSTRNCAT(ctx->name, "\\", 2); + XSTRNCAT(ctx->name, ctx->FindFileData.cFileName, MAX_FILENAME_SZ/2); + if (name) + *name = ctx->name; + return 0; + } + } while (FindNextFileA(ctx->hFind, &ctx->FindFileData)); +#else + ctx->dir = opendir(path); + if (ctx->dir == NULL) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 2); + XSTRNCAT(ctx->name, "/", 1); + XSTRNCAT(ctx->name, ctx->entry->d_name, MAX_FILENAME_SZ/2); + + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.st_mode & S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + wc_ReadDirClose(ctx); + + return ret; +} + +int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = -1; + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + +#ifdef USE_WINDOWS_API + while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) { + if (ctx->FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 3); + XSTRNCAT(ctx->name, "\\", 2); + XSTRNCAT(ctx->name, ctx->FindFileData.cFileName, MAX_FILENAME_SZ/2); + if (name) + *name = ctx->name; + return 0; + } + } +#else + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ/2 - 2); + XSTRNCAT(ctx->name, "/", 1); + XSTRNCAT(ctx->name, ctx->entry->d_name, MAX_FILENAME_SZ/2); + + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.st_mode & S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + + wc_ReadDirClose(ctx); + + return ret; +} + +void wc_ReadDirClose(ReadDirCtx* ctx) +{ + if (ctx == NULL) { + return; + } + +#ifdef USE_WINDOWS_API + if (ctx->hFind != INVALID_HANDLE_VALUE) { + FindClose(ctx->hFind); + ctx->hFind = INVALID_HANDLE_VALUE; + } +#else + if (ctx->dir) { + closedir(ctx->dir); + ctx->dir = NULL; + } +#endif +} + +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + + wolfSSL_Mutex* wc_InitAndAllocMutex() { wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL, DYNAMIC_TYPE_MUTEX); - if(m && wc_InitMutex(m)) - return m; - XFREE(m, NULL, DYNAMIC_TYPE_MUTEX); - m = NULL; + if (m != NULL) { + if (wc_InitMutex(m) != 0) { + WOLFSSL_MSG("Init Mutex failed"); + XFREE(m, NULL, DYNAMIC_TYPE_MUTEX); + m = NULL; + } + } + else { + WOLFSSL_MSG("Memory error with Mutex allocation"); + } + return m; } + #if WOLFSSL_CRYPT_HW_MUTEX /* Mutex for protection of cryptography hardware */ static wolfSSL_Mutex wcCryptHwMutex; @@ -145,653 +384,738 @@ int wolfSSL_CryptHwMutexUnLock(void) { #endif /* WOLFSSL_CRYPT_HW_MUTEX */ +/* ---------------------------------------------------------------------------*/ +/* Mutex Ports */ +/* ---------------------------------------------------------------------------*/ #ifdef SINGLE_THREADED -int wc_InitMutex(wolfSSL_Mutex* m) -{ - (void)m; - return 0; -} + int wc_InitMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } -int wc_FreeMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_FreeMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -int wc_LockMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_LockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -int wc_UnLockMutex(wolfSSL_Mutex *m) -{ - (void)m; - return 0; -} + int wc_UnLockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } -#else /* MULTI_THREAD */ +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(FREESCALE_FREE_RTOS) - #if defined(FREERTOS) || defined(FREERTOS_TCP) || \ - defined(FREESCALE_FREE_RTOS) + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; - int wc_InitMutex(wolfSSL_Mutex* m) - { - int iReturn; + *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); + if( *m != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; - *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); - if( *m != NULL ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; + return iReturn; + } - return iReturn; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + vSemaphoreDelete( *m ); + return 0; + } + int wc_LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block, or should there be zero block? */ + xSemaphoreTake( *m, portMAX_DELAY ); + return 0; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - vSemaphoreDelete( *m ); - return 0; - } + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive( *m ); + return 0; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - /* Assume an infinite block, or should there be zero block? */ - xSemaphoreTake( *m, portMAX_DELAY ); - return 0; - } +#elif defined(WOLFSSL_SAFERTOS) - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - xSemaphoreGive( *m ); - return 0; - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); + if (m->mutex == NULL) + return BAD_MUTEX_E; - #elif defined(WOLFSSL_SAFERTOS) + return 0; + } - int wc_InitMutex(wolfSSL_Mutex* m) - { - vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); - if (m->mutex == NULL) - return BAD_MUTEX_E; + int wc_FreeMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } - return 0; - } + int wc_LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block */ + xSemaphoreTake(m->mutex, portMAX_DELAY); + return 0; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - (void)m; - return 0; - } + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive(m->mutex); + return 0; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - /* Assume an infinite block */ - xSemaphoreTake(m->mutex, portMAX_DELAY); - return 0; - } +#elif defined(USE_WINDOWS_API) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + InitializeCriticalSection(m); + return 0; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - xSemaphoreGive(m->mutex); - return 0; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + DeleteCriticalSection(m); + return 0; + } - #elif defined(USE_WINDOWS_API) - int wc_InitMutex(wolfSSL_Mutex* m) - { - InitializeCriticalSection(m); - return 0; - } + int wc_LockMutex(wolfSSL_Mutex* m) + { + EnterCriticalSection(m); + return 0; + } + + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + LeaveCriticalSection(m); + return 0; + } +#elif defined(WOLFSSL_PTHREADS) - int wc_FreeMutex(wolfSSL_Mutex* m) - { - DeleteCriticalSection(m); + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_init(m, 0) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - EnterCriticalSection(m); + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_destroy(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - LeaveCriticalSection(m); + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_lock(m) == 0) return 0; - } + else + return BAD_MUTEX_E; + } - #elif defined(WOLFSSL_PTHREADS) - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_init(m, 0) == 0) - return 0; - else - return BAD_MUTEX_E; - } + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_unlock(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } +#elif defined(THREADX) - int wc_FreeMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_destroy(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) + return 0; + else + return BAD_MUTEX_E; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_lock(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_delete(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - if (pthread_mutex_unlock(m) == 0) - return 0; - else - return BAD_MUTEX_E; - } + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_put(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } - #elif defined(THREADX) +#elif defined(MICRIUM) - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) + int wc_InitMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_MutexCreate(m) == 0) return 0; else return BAD_MUTEX_E; - } - + #else + return 0; + #endif + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_delete(m) == 0) + int wc_FreeMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_wc_FreeMutex(m) == 0) return 0; else return BAD_MUTEX_E; - } - + #else + return 0; + #endif + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) + int wc_LockMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_wc_LockMutex(m) == 0) return 0; else return BAD_MUTEX_E; - } - + #else + return 0; + #endif + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - if (tx_mutex_put(m) == 0) + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + if (NetSecure_OS_wc_UnLockMutex(m) == 0) return 0; else return BAD_MUTEX_E; - } - - #elif defined(MICRIUM) - - int wc_InitMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_MutexCreate(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } - + #else + return 0; + #endif - int wc_FreeMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_wc_FreeMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } + } +#elif defined(EBSNET) - int wc_LockMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_wc_LockMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) + return BAD_MUTEX_E; + else + return 0; + } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_free(*m); + return 0; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) - if (NetSecure_OS_wc_UnLockMutex(m) == 0) - return 0; - else - return BAD_MUTEX_E; - #else - return 0; - #endif + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) + return 0; + else + return BAD_MUTEX_E; + } - } + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_release(*m); + return 0; + } - #elif defined(EBSNET) +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) - return BAD_MUTEX_E; - else - return 0; - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (_mutex_init(m, NULL) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - rtp_sig_mutex_free(*m); + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (_mutex_destroy(m) == MQX_EOK) return 0; - } + else + return BAD_MUTEX_E; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) - return 0; - else - return BAD_MUTEX_E; - } + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (_mutex_lock(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - rtp_sig_mutex_release(*m); + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (_mutex_unlock(m) == MQX_EOK) return 0; - } + else + return BAD_MUTEX_E; + } - #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) +#elif defined(WOLFSSL_TIRTOS) + #include - int wc_InitMutex(wolfSSL_Mutex* m) - { - if (_mutex_init(m, NULL) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + Semaphore_Params params; + Error_Block eb; - int wc_FreeMutex(wolfSSL_Mutex* m) - { - if (_mutex_destroy(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } + Error_init(&eb); + Semaphore_Params_init(¶ms); + params.mode = Semaphore_Mode_BINARY; - int wc_LockMutex(wolfSSL_Mutex* m) - { - if (_mutex_lock(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; + *m = Semaphore_create(1, ¶ms, &eb); + if (Error_check(&eb)) { + Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.", + NULL); + return BAD_MUTEX_E; } + else + return 0; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - if (_mutex_unlock(m) == MQX_EOK) - return 0; - else - return BAD_MUTEX_E; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + Semaphore_delete(m); - #elif defined (WOLFSSL_TIRTOS) - #include - int wc_InitMutex(wolfSSL_Mutex* m) - { - Semaphore_Params params; - Error_Block eb; - Error_init(&eb); - Semaphore_Params_init(¶ms); - params.mode = Semaphore_Mode_BINARY; - - *m = Semaphore_create(1, ¶ms, &eb); - if( Error_check( &eb ) ) - { - Error_raise( &eb, Error_E_generic, "Failed to Create the semaphore.",NULL); - } else return 0; - } + return 0; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - Semaphore_delete(m); + int wc_LockMutex(wolfSSL_Mutex* m) + { + Semaphore_pend(*m, BIOS_WAIT_FOREVER); - return 0; - } + return 0; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - Semaphore_pend(*m, BIOS_WAIT_FOREVER); + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + Semaphore_post(*m); - return 0; - } + return 0; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - Semaphore_post(*m); +#elif defined(WOLFSSL_uITRON4) - return 0; - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + m->sem.sematr = TA_TFIFO; + m->sem.isemcnt = 1; + m->sem.maxsem = 1; + m->sem.name = NULL; - #elif defined(WOLFSSL_uITRON4) - #include "stddef.h" - #include "kernel.h" - int wc_InitMutex(wolfSSL_Mutex* m) - { - int iReturn; - m->sem.sematr = TA_TFIFO ; - m->sem.isemcnt = 1 ; - m->sem.maxsem = 1 ; - m->sem.name = NULL ; - - m->id = acre_sem(&m->sem); - if( m->id != E_OK ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; + m->id = acre_sem(&m->sem); + if( m->id != E_OK ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; - return iReturn; - } + return iReturn; + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - del_sem( m->id ); - return 0; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + del_sem( m->id ); + return 0; + } - int wc_LockMutex(wolfSSL_Mutex* m) - { - wai_sem(m->id); - return 0; - } + int wc_LockMutex(wolfSSL_Mutex* m) + { + wai_sem(m->id); + return 0; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - sig_sem(m->id); - return 0; - } + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + sig_sem(m->id); + return 0; + } - /**** uITRON malloc/free ***/ - static ID ID_wolfssl_MPOOL = 0 ; - static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"}; + /**** uITRON malloc/free ***/ + static ID ID_wolfssl_MPOOL = 0; + static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"}; - int uITRON4_minit(size_t poolsz) { - ER ercd; - wolfssl_MPOOL.mplsz = poolsz ; - ercd = acre_mpl(&wolfssl_MPOOL); - if (ercd > 0) { - ID_wolfssl_MPOOL = ercd; - return 0; - } else { - return -1; - } + int uITRON4_minit(size_t poolsz) { + ER ercd; + wolfssl_MPOOL.mplsz = poolsz; + ercd = acre_mpl(&wolfssl_MPOOL); + if (ercd > 0) { + ID_wolfssl_MPOOL = ercd; + return 0; + } else { + return -1; } + } - void *uITRON4_malloc(size_t sz) { - ER ercd; - void *p ; - ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p); - if (ercd == E_OK) { - return p; - } else { - return 0 ; - } + void *uITRON4_malloc(size_t sz) { + ER ercd; + void *p; + ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p); + if (ercd == E_OK) { + return p; + } else { + return 0; } + } - void *uITRON4_realloc(void *p, size_t sz) { - ER ercd; - void *newp ; - if(p) { - ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); + void *uITRON4_realloc(void *p, size_t sz) { + ER ercd; + void *newp; + if(p) { + ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { - XMEMCPY(newp, p, sz) ; - ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return newp; - } + return newp; } } - return 0 ; - } + } + return 0; + } - void uITRON4_free(void *p) { - ER ercd; - ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return ; - } else { - return ; - } + void uITRON4_free(void *p) { + ER ercd; + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return; + } else { + return; } + } #elif defined(WOLFSSL_uTKERNEL2) - #include "tk/tkernel.h" - int wc_InitMutex(wolfSSL_Mutex* m) - { - int iReturn; - m->sem.sematr = TA_TFIFO ; - m->sem.isemcnt = 1 ; - m->sem.maxsem = 1 ; - - m->id = tk_cre_sem(&m->sem); - if( m->id != NULL ) - iReturn = 0; - else - iReturn = BAD_MUTEX_E; - return iReturn; - } + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + m->sem.sematr = TA_TFIFO; + m->sem.isemcnt = 1; + m->sem.maxsem = 1; - int wc_FreeMutex(wolfSSL_Mutex* m) - { - tk_del_sem( m->id ); - return 0; - } + m->id = tk_cre_sem(&m->sem); + if( m->id != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; - int wc_LockMutex(wolfSSL_Mutex* m) - { - tk_wai_sem(m->id, 1, TMO_FEVR); - return 0; - } + return iReturn; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - tk_sig_sem(m->id, 1); - return 0; - } + int wc_FreeMutex(wolfSSL_Mutex* m) + { + tk_del_sem(m->id); + return 0; + } - /**** uT-Kernel malloc/free ***/ - static ID ID_wolfssl_MPOOL = 0 ; - static T_CMPL wolfssl_MPOOL = - {(void *)NULL, - TA_TFIFO , 0, "wolfSSL_MPOOL"}; - - int uTKernel_init_mpool(unsigned int sz) { - ER ercd; - wolfssl_MPOOL.mplsz = sz ; - ercd = tk_cre_mpl(&wolfssl_MPOOL); - if (ercd > 0) { - ID_wolfssl_MPOOL = ercd; - return 0; - } else { - return -1; - } + int wc_LockMutex(wolfSSL_Mutex* m) + { + tk_wai_sem(m->id, 1, TMO_FEVR); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + tk_sig_sem(m->id, 1); + return 0; + } + + /**** uT-Kernel malloc/free ***/ + static ID ID_wolfssl_MPOOL = 0; + static T_CMPL wolfssl_MPOOL = { + NULL, /* Extended information */ + TA_TFIFO, /* Memory pool attribute */ + 0, /* Size of whole memory pool (byte) */ + "wolfSSL" /* Object name (max 8-char) */ + }; + + int uTKernel_init_mpool(unsigned int sz) { + ER ercd; + wolfssl_MPOOL.mplsz = sz; + ercd = tk_cre_mpl(&wolfssl_MPOOL); + if (ercd > 0) { + ID_wolfssl_MPOOL = ercd; + return 0; + } else { + return (int)ercd; } + } - void *uTKernel_malloc(unsigned int sz) { - ER ercd; - void *p ; - ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); - if (ercd == E_OK) { - return p; - } else { - return 0 ; - } + void *uTKernel_malloc(unsigned int sz) { + ER ercd; + void *p; + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); + if (ercd == E_OK) { + return p; + } else { + return 0; } + } - void *uTKernel_realloc(void *p, unsigned int sz) { - ER ercd; - void *newp ; - if(p) { - ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); + void *uTKernel_realloc(void *p, unsigned int sz) { + ER ercd; + void *newp; + if (p) { + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); if (ercd == E_OK) { - XMEMCPY(newp, p, sz) ; - ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return newp; - } + return newp; } } - return 0 ; - } + } + return 0; + } - void uTKernel_free(void *p) { - ER ercd; - ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); - if (ercd == E_OK) { - return ; - } else { - return ; - } - } - #elif defined (WOLFSSL_FROSTED) - int wc_InitMutex(wolfSSL_Mutex* m) - { - *m = mutex_init(); - if (*m) - return 0; - else - return -1; + void uTKernel_free(void *p) { + ER ercd; + ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return; + } else { + return; } + } - int wc_FreeMutex(wolfSSL_Mutex* m) - { - mutex_destroy(*m); - return(0) ; - } +#elif defined (WOLFSSL_FROSTED) - int wc_LockMutex(wolfSSL_Mutex* m) - { - mutex_lock(*m); + int wc_InitMutex(wolfSSL_Mutex* m) + { + *m = mutex_init(); + if (*m) return 0; - } + else + return -1; + } - int wc_UnLockMutex(wolfSSL_Mutex* m) - { - mutex_unlock(*m); - return 0; - } - #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_CMSIS_RTOS) - - #if defined(WOLFSSL_CMSIS_RTOS) - #include "cmsis_os.h" - #define CMSIS_NMUTEX 10 - osMutexDef(wolfSSL_mt0) ; osMutexDef(wolfSSL_mt1) ; osMutexDef(wolfSSL_mt2) ; - osMutexDef(wolfSSL_mt3) ; osMutexDef(wolfSSL_mt4) ; osMutexDef(wolfSSL_mt5) ; - osMutexDef(wolfSSL_mt6) ; osMutexDef(wolfSSL_mt7) ; osMutexDef(wolfSSL_mt8) ; - osMutexDef(wolfSSL_mt9) ; - - static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0), - osMutex(wolfSSL_mt1), osMutex(wolfSSL_mt2), osMutex(wolfSSL_mt3), - osMutex(wolfSSL_mt4), osMutex(wolfSSL_mt5), osMutex(wolfSSL_mt6), - osMutex(wolfSSL_mt7), osMutex(wolfSSL_mt8), osMutex(wolfSSL_mt9) } ; - - static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0} ; - - int wc_InitMutex(wolfSSL_Mutex* m) - { - int i ; - for (i=0; i /* initialize and Mutex for TI Crypt Engine */ #include /* md5, sha1, sha224, sha256 */ #endif diff --git a/wolfcrypt/src/wolfevent.c b/wolfcrypt/src/wolfevent.c index 6a8379bfe2..6e3eae2b31 100644 --- a/wolfcrypt/src/wolfevent.c +++ b/wolfcrypt/src/wolfevent.c @@ -103,16 +103,7 @@ int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* 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; + ret = wolfEventQueue_Add(queue, event); #ifndef SINGLE_THREADED wc_UnLockMutex(&queue->lock); @@ -147,6 +138,26 @@ int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event) return ret; } +/* assumes queue is locked by caller */ +int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + 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++; + + return 0; +} + /* assumes queue is locked by caller */ int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) { diff --git a/wolfcrypt/src/wolfmath.c b/wolfcrypt/src/wolfmath.c new file mode 100644 index 0000000000..bb76bfe812 --- /dev/null +++ b/wolfcrypt/src/wolfmath.c @@ -0,0 +1,272 @@ +/* wolfmath.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 + */ + + +/* common functions for either math library */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set USE_FAST_MATH there */ +#include + +#ifdef USE_FAST_MATH + #include +#else + #include +#endif + +#include +#include + +#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + /* all off / all on pointer addresses for constant calculations */ + /* ecc.c uses same table */ + const wolfssl_word wc_off_on_addr[2] = + { + #if defined(WC_64BIT_CPU) + W64LIT(0x0000000000000000), + W64LIT(0xffffffffffffffff) + #elif defined(WC_16BIT_CPU) + 0x0000U, + 0xffffU + #else + /* 32 bit */ + 0x00000000U, + 0xffffffffU + #endif + }; +#endif + + +int get_digit_count(mp_int* a) +{ + if (a == NULL) + return 0; + + return a->used; +} + +mp_digit get_digit(mp_int* a, int n) +{ + if (a == NULL) + return 0; + + return (n >= a->used || n < 0) ? 0 : a->dp[n]; +} + +int get_rand_digit(WC_RNG* rng, mp_digit* d) +{ + return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); +} + +#ifdef WC_RSA_BLINDING +int mp_rand(mp_int* a, int digits, WC_RNG* rng) +{ + int ret; + mp_digit d; + + if (rng == NULL) + return MISSING_RNG_E; + + if (a == NULL) + return BAD_FUNC_ARG; + + mp_zero(a); + if (digits <= 0) { + return MP_OKAY; + } + + /* first place a random non-zero digit */ + do { + ret = get_rand_digit(rng, &d); + if (ret != 0) { + return ret; + } + } while (d == 0); + + if ((ret = mp_add_d(a, d, a)) != MP_OKAY) { + return ret; + } + + while (--digits > 0) { + if ((ret = mp_lshd(a, 1)) != MP_OKAY) { + return ret; + } + if ((ret = get_rand_digit(rng, &d)) != 0) { + return ret; + } + if ((ret = mp_add_d(a, d, a)) != MP_OKAY) { + return ret; + } + } + + return ret; +} +#endif /* WC_RSA_BLINDING */ + + +#ifdef HAVE_WOLF_BIGINT +void wc_bigint_init(WC_BIGINT* a) +{ + if (a != NULL) { + a->buf = NULL; + a->len = 0; + a->heap = NULL; + } +} + +int wc_bigint_alloc(WC_BIGINT* a, word32 sz) +{ + int err = MP_OKAY; + + if (a == NULL) + return BAD_FUNC_ARG; + + if (sz > 0) { + if (a->buf && sz > a->len) { + wc_bigint_free(a); + } + if (a->buf == NULL) { + a->buf = (byte*)XMALLOC(sz, a->heap, DYNAMIC_TYPE_WOLF_BIGINT); + } + if (a->buf == NULL) { + err = MP_MEM; + } + else { + XMEMSET(a->buf, 0, sz); + } + } + a->len = sz; + + return err; +} + +/* assumes input is big endian format */ +int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen) +{ + int err; + + if (a == NULL || in == NULL || inlen == 0) + return BAD_FUNC_ARG; + + err = wc_bigint_alloc(a, inlen); + if (err == 0) { + XMEMCPY(a->buf, in, inlen); + } + + return err; +} + +int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen) +{ + word32 sz; + + if (a == NULL || out == NULL || outlen == NULL || *outlen == 0) + return BAD_FUNC_ARG; + + /* trim to fit into output buffer */ + sz = a->len; + if (a->len > *outlen) { + WOLFSSL_MSG("wc_bigint_export: Truncating output"); + sz = *outlen; + } + + if (a->buf) { + XMEMCPY(out, a->buf, sz); + } + + *outlen = sz; + + return MP_OKAY; +} + +void wc_bigint_zero(WC_BIGINT* a) +{ + if (a && a->buf) { + ForceZero(a->buf, a->len); + } +} + +void wc_bigint_free(WC_BIGINT* a) +{ + if (a) { + if (a->buf) { + XFREE(a->buf, a->heap, DYNAMIC_TYPE_WOLF_BIGINT); + } + a->buf = NULL; + a->len = 0; + } +} + +int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst) +{ + int err; + word32 sz; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + sz = mp_unsigned_bin_size(src); + err = wc_bigint_alloc(dst, sz); + if (err == MP_OKAY) + err = mp_to_unsigned_bin(src, dst->buf); + + return err; +} + +int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst) +{ + int err; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + if (src->buf == NULL) + return BAD_FUNC_ARG; + + err = mp_read_unsigned_bin(dst, src->buf, src->len); + wc_bigint_free(src); + + return err; +} + +#endif /* HAVE_WOLF_BIGINT */ + +#endif /* USE_FAST_MATH || !NO_BIG_INT */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 8f79648906..fd4c689480 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -39,6 +39,9 @@ #define HEAP_HINT NULL #endif /* WOLFSSL_STATIC_MEMORY */ +#include +#include + #ifdef WOLFSSL_TEST_CERT #include #else @@ -59,9 +62,11 @@ #endif #include +#include #include #include #include +#include #include #include #include @@ -101,6 +106,17 @@ #ifdef WOLFSSL_ASYNC_CRYPT #include #endif +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + #include +#endif + +/* only for stack size check */ +#ifdef HAVE_STACK_SIZE + #include + #define err_sys err_sys_remap /* remap err_sys */ + #include + #undef err_sys +#endif #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ @@ -111,10 +127,21 @@ #include #include #include + #include #include #endif +#if defined(NO_FILESYSTEM) + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(USE_CERT_BUFFERS_4096) + #define USE_CERT_BUFFERS_2048 + #endif + #if !defined(USE_CERT_BUFFERS_256) + #define USE_CERT_BUFFERS_256 + #endif +#endif + #include #if defined(WOLFSSL_MDK_ARM) @@ -136,6 +163,10 @@ #else #include #endif +#elif defined(FREESCALE_KSDK_BM) + #include "fsl_debug_console.h" + #undef printf + #define printf PRINTF #else #include #endif @@ -150,9 +181,6 @@ #include "wolfcrypt/test/test.h" -#ifdef USE_WOLFSSL_MEMORY - #include "wolfssl/wolfcrypt/mem_track.h" -#endif /* for async devices */ static int devId = INVALID_DEVID; @@ -169,6 +197,9 @@ typedef struct testVector { size_t outLen; } testVector; +int error_test(void); +int base64_test(void); +int asn_test(void); int md2_test(void); int md5_test(void); int md4_test(void); @@ -177,6 +208,7 @@ int sha224_test(void); int sha256_test(void); int sha512_test(void); int sha384_test(void); +int hash_test(void); int hmac_md5_test(void); int hmac_sha_test(void); int hmac_sha224_test(void); @@ -194,6 +226,8 @@ int chacha20_poly1305_aead_test(void); int des_test(void); int des3_test(void); int aes_test(void); +int aes192_test(void); +int aes256_test(void); int cmac_test(void); int poly1305_test(void); int aesgcm_test(void); @@ -241,6 +275,9 @@ int scrypt_test(void); int pkcs7signed_test(void); int pkcs7encrypted_test(void); #endif +#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) +int cert_test(void); +#endif #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) int certext_test(void); #endif @@ -250,8 +287,17 @@ int idea_test(void); #ifdef WOLFSSL_STATIC_MEMORY int memory_test(void); #endif +#ifdef HAVE_VALGRIND +int mp_test(void); +#endif +int logging_test(void); +int mutex_test(void); +#ifdef USE_WOLFSSL_MEMORY +int memcb_test(void); +#endif -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && !defined(OPENSSL_EXTRA) +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ + !defined(OPENSSL_EXTRA) && !defined(HAVE_STACK_SIZE) int wolfSSL_Debugging_ON(void); #endif @@ -261,22 +307,25 @@ int memory_test(void); #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } - +#ifdef HAVE_STACK_SIZE +static THREAD_RETURN err_sys(const char* msg, int es) +#else static int err_sys(const char* msg, int es) - +#endif { printf("%s error = %d\n", msg, es); EXIT_TEST(-1); } -/* func_args from test.h, so don't have to pull in other junk */ +#ifndef HAVE_STACK_SIZE +/* func_args from test.h, so don't have to pull in other stuff */ typedef struct func_args { int argc; char** argv; int return_code; } func_args; - +#endif /* !HAVE_STACK_SIZE */ #ifdef HAVE_FIPS @@ -294,36 +343,41 @@ static void myFipsCb(int ok, int err, const char* hash) #endif /* HAVE_FIPS */ -int wolfcrypt_test(void* args) -{ - int ret = 0; #ifdef WOLFSSL_STATIC_MEMORY #ifdef BENCH_EMBEDDED - byte memory[10000]; + static byte gTestMemory[10000]; + #elif defined(USE_FAST_MATH) && !defined(ALT_ECC_SIZE) + static byte gTestMemory[130000]; #else - byte memory[100000]; + static byte gTestMemory[80000]; #endif #endif +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD wolfcrypt_test(void* args) +#else +int wolfcrypt_test(void* args) +#endif +{ + int ret; + ((func_args*)args)->return_code = -1; /* error state */ #ifdef WOLFSSL_STATIC_MEMORY - if (wc_LoadStaticMemory(&HEAP_HINT, memory, sizeof(memory), + if (wc_LoadStaticMemory(&HEAP_HINT, gTestMemory, sizeof(gTestMemory), WOLFMEM_GENERAL, 1) != 0) { printf("unable to load static memory"); exit(EXIT_FAILURE); } #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(); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + wc_SetLoggingHeap(HEAP_HINT); +#endif #ifdef HAVE_FIPS wolfCrypt_SetCb_fips(myFipsCb); @@ -331,25 +385,43 @@ int wolfcrypt_test(void* args) #if !defined(NO_BIG_INT) if (CheckCtcSettings() != 1) - return err_sys("Build vs runtime math mismatch\n", -1234); + return err_sys("Build vs runtime math mismatch\n", -1000); #ifdef USE_FAST_MATH if (CheckFastMathSettings() != 1) return err_sys("Build vs runtime fastmath FP_MAX_BITS mismatch\n", - -1235); + -1001); #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; + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } #else (void)devId; #endif /* WOLFSSL_ASYNC_CRYPT */ + if ( (ret = error_test()) != 0) + return err_sys("error test failed!\n", ret); + else + printf( "error test passed!\n"); + +#if !defined(NO_CODING) && defined(WOLFSSL_BASE64_ENCODE) + if ( (ret = base64_test()) != 0) + return err_sys("base64 test failed!\n", ret); + else + printf( "base64 test passed!\n"); +#endif + +#ifndef NO_ASN + if ( (ret = asn_test()) != 0) + return err_sys("base64 test failed!\n", ret); + else + printf( "base64 test passed!\n"); +#endif + #ifndef NO_MD5 if ( (ret = md5_test()) != 0) return err_sys("MD5 test failed!\n", ret); @@ -406,6 +478,11 @@ int wolfcrypt_test(void* args) printf( "SHA-512 test passed!\n"); #endif + if ( (ret = hash_test()) != 0) + return err_sys("Hash test failed!\n", ret); + else + printf( "Hash test passed!\n"); + #ifdef WOLFSSL_RIPEMD if ( (ret = ripemd_test()) != 0) return err_sys("RIPEMD test failed!\n", ret); @@ -476,9 +553,9 @@ int wolfcrypt_test(void* args) else printf( "HMAC-KDF test passed!\n"); #endif -#endif +#endif /* !NO_HMAC */ -#ifdef HAVE_X963_KDF +#if defined(HAVE_X963_KDF) && defined(HAVE_ECC) if ( (ret = x963kdf_test()) != 0) return err_sys("X963-KDF test failed!\n", ret); else @@ -554,6 +631,16 @@ int wolfcrypt_test(void* args) else printf( "AES test passed!\n"); + if ( (ret = aes192_test()) != 0) + return err_sys("AES192 test failed!\n", ret); + else + printf( "AES192 test passed!\n"); + + if ( (ret = aes256_test()) != 0) + return err_sys("AES256 test failed!\n", ret); + else + printf( "AES256 test passed!\n"); + #ifdef HAVE_AESGCM if ( (ret = aesgcm_test()) != 0) return err_sys("AES-GCM test failed!\n", ret); @@ -610,6 +697,13 @@ int wolfcrypt_test(void* args) printf( "RSA test passed!\n"); #endif +#if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) + if ( (ret = cert_test()) != 0) + return err_sys("CERT test failed!\n", ret); + else + printf( "CERT test passed!\n"); +#endif + #if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) if ( (ret = certext_test()) != 0) return err_sys("CERT EXT test failed!\n", ret); @@ -716,47 +810,270 @@ int wolfcrypt_test(void* args) printf( "PKCS7encrypted test passed!\n"); #endif -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - ShowMemoryTracker(); +#ifdef HAVE_VALGRIND + if ( (ret = mp_test()) != 0) + return err_sys("mp test failed!\n", ret); + else + printf( "mp test passed!\n"); +#endif + +#ifdef HAVE_VALGRIND + if ( (ret = logging_test()) != 0) + return err_sys("logging test failed!\n", ret); + else + printf( "logging test passed!\n"); +#endif + + if ( (ret = mutex_test()) != 0) + return err_sys("mutex test failed!\n", ret); + else + printf( "mutex test passed!\n"); + +#ifdef USE_WOLFSSL_MEMORY + if ( (ret = memcb_test()) != 0) + return err_sys("memcb test failed!\n", ret); + else + printf( "memcb test passed!\n"); +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); #endif ((func_args*)args)->return_code = ret; - return ret; + EXIT_TEST(ret); } #ifndef NO_MAIN_DRIVER /* so overall tests can pull in test function */ - int main(int argc, char** argv) { func_args args; #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { - err_sys("Whitewood netRandom global config failed", -1237); - return -1237; + err_sys("Whitewood netRandom global config failed", -1002); + return -1002; } #endif args.argc = argc; args.argv = argv; + wolfCrypt_Init(); + + #ifdef HAVE_STACK_SIZE + StackSizeCheck(&args, wolfcrypt_test); + #else wolfcrypt_test(&args); + #endif + + if (wolfCrypt_Cleanup() != 0) { + err_sys("Error with wolfCrypt_Cleanup!\n", -1003); + } #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) - err_sys("Failed to free netRandom context", -1238); + err_sys("Failed to free netRandom context", -1004); #endif /* HAVE_WNR */ - EXIT_TEST(args.return_code); + return args.return_code; } #endif /* NO_MAIN_DRIVER */ +int error_test() +{ + const char* errStr; + char out[WOLFSSL_MAX_ERROR_SZ]; + const char* unknownStr = wc_GetErrorString(0); + +#ifdef NO_ERROR_STRINGS + /* Ensure a valid error code's string matches an invalid code's. + * The string is that error strings are not available. + */ + errStr = wc_GetErrorString(OPEN_RAN_E); + wc_ErrorString(OPEN_RAN_E, out); + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1100; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1101; +#else + int i; + int j = 0; + /* Values that are not or no longer error codes. */ + int missing[] = { -122, -123, -124, -127, -128, -129, + -161, -162, -163, -164, -165, -166, -167, -168, -169, + -178, -179, -233, + 0 }; + + /* Check that all errors have a string and it's the same through the two + * APIs. Check that the values that are not errors map to the unknown + * string. + */ + for (i = MAX_CODE_E-1; i >= WC_LAST_E; i--) { + errStr = wc_GetErrorString(i); + wc_ErrorString(i, out); + + if (i != missing[j]) { + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) == 0) + return -1102; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) == 0) + return -1103; + if (XSTRNCMP(errStr, out, XSTRLEN(errStr)) != 0) + return -1104; + } + else { + j++; + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1105; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1106; + } + } + + /* Check if the next possible value has been given a string. */ + errStr = wc_GetErrorString(i); + wc_ErrorString(i, out); + if (XSTRNCMP(errStr, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1107; + if (XSTRNCMP(out, unknownStr, XSTRLEN(unknownStr)) != 0) + return -1108; +#endif + + return 0; +} + +#if !defined(NO_CODING) && defined(WOLFSSL_BASE64_ENCODE) +int base64_test() +{ + int ret; + const byte good[] = "A+Gd\0\0\0"; + const byte goodEnd[] = "A+Gd \r\n"; + byte out[128]; + word32 outLen; + byte data[3]; + word32 dataLen; + byte longData[79] = { 0 }; + const byte symbols[] = "+/A="; + const byte badSmall[] = "AAA Gdj="; + const byte badLarge[] = "AAA~Gdj="; + const byte badEOL[] = "A+Gd "; + int i; + + /* Good Base64 encodings. */ + outLen = sizeof(out); + ret = Base64_Decode(good, sizeof(good), out, &outLen); + if (ret != 0) + return -1200; + outLen = sizeof(out); + ret = Base64_Decode(goodEnd, sizeof(goodEnd), out, &outLen); + if (ret != 0) + return -1201; + + /* Bad parameters. */ + outLen = 1; + ret = Base64_Decode(good, sizeof(good), out, &outLen); + if (ret != BAD_FUNC_ARG) + return -1202; + + outLen = sizeof(out); + ret = Base64_Decode(badEOL, sizeof(badEOL), out, &outLen); + if (ret != ASN_INPUT_E) + return -1203; + /* Bad character at each offset 0-3. */ + for (i = 0; i < 4; i++) { + outLen = sizeof(out); + ret = Base64_Decode(badSmall + i, 4, out, &outLen); + if (ret != ASN_INPUT_E) + return -1204 - i; + ret = Base64_Decode(badLarge + i, 4, out, &outLen); + if (ret != ASN_INPUT_E) + return -1214 - i; + } + + /* Decode and encode all symbols - non-alphanumeric. */ + dataLen = sizeof(data); + ret = Base64_Decode(symbols, sizeof(symbols), data, &dataLen); + if (ret != 0) + return -1224; + outLen = sizeof(out); + ret = Base64_Encode(data, dataLen, NULL, &outLen); + if (ret != LENGTH_ONLY_E) + return -1225; + outLen = sizeof(out); + ret = Base64_Encode(data, dataLen, out, &outLen); + if (ret != 0) + return -1226; + outLen = 7; + ret = Base64_EncodeEsc(data, dataLen, out, &outLen); + if (ret != BUFFER_E) + return -1227; + outLen = sizeof(out); + ret = Base64_EncodeEsc(data, dataLen, NULL, &outLen); + if (ret != LENGTH_ONLY_E) + return -1228; + outLen = sizeof(out); + ret = Base64_EncodeEsc(data, dataLen, out, &outLen); + if (ret != 0) + return -1229; + outLen = sizeof(out); + ret = Base64_Encode_NoNl(data, dataLen, out, &outLen); + if (ret != 0) + return -1230; + + /* Data that results in an encoding longer than one line. */ + outLen = sizeof(out); + dataLen = sizeof(longData); + ret = Base64_Encode(longData, dataLen, out, &outLen); + if (ret != 0) + return -1231; + outLen = sizeof(out); + ret = Base64_EncodeEsc(longData, dataLen, out, &outLen); + if (ret != 0) + return -1232; + outLen = sizeof(out); + ret = Base64_Encode_NoNl(longData, dataLen, out, &outLen); + if (ret != 0) + return -1233; + + return 0; +} +#endif + +#ifndef NO_ASN +int asn_test() +{ +#ifndef NO_ASN_TIME + #ifdef WORD64_AVAILABLE + word64 now; + #else + word32 now; + #endif + + /* Parameter Validation tests. */ + if (wc_GetTime(NULL, sizeof(now)) != BAD_FUNC_ARG) + return -1300; + if (wc_GetTime(&now, 0) != BUFFER_E) + return -1301; + + now = 0; + if (wc_GetTime(&now, sizeof(now)) != 0) { + return -1302; + } + if (now == 0) { + return -1303; + } +#endif + + return 0; +} +#endif + #ifdef WOLFSSL_MD2 int md2_test() { @@ -826,7 +1143,7 @@ int md2_test() wc_Md2Final(&md2, hash); if (XMEMCMP(hash, test_md2[i].output, MD2_DIGEST_SIZE) != 0) - return -155 - i; + return -1400 - i; } return 0; @@ -836,8 +1153,10 @@ int md2_test() #ifndef NO_MD5 int md5_test(void) { + int ret; Md5 md5; byte hash[MD5_DIGEST_SIZE]; + byte hashcopy[MD5_DIGEST_SIZE]; testVector a, b, c, d, e; testVector test_md5[5]; @@ -881,16 +1200,32 @@ int md5_test(void) test_md5[3] = d; test_md5[4] = e; - wc_InitMd5(&md5); + ret = wc_InitMd5_ex(&md5, HEAP_HINT, devId); + if (ret != 0) + return -1500; for (i = 0; i < times; ++i) { - wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); - wc_Md5Final(&md5, hash); + ret = wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); + if (ret != 0) + return -1510 - i; + + ret = wc_Md5GetHash(&md5, hashcopy); + if (ret != 0) + return -1520 - i; + + ret = wc_Md5Final(&md5, hash); + if (ret != 0) + return -1530 - i; if (XMEMCMP(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0) - return -5 - i; + return -1540 - i; + + if (XMEMCMP(hash, hashcopy, MD5_DIGEST_SIZE) != 0) + return -1550 - i; } + wc_Md5Free(&md5); + return 0; } #endif /* NO_MD5 */ @@ -966,7 +1301,7 @@ int md4_test(void) wc_Md4Final(&md4, hash); if (XMEMCMP(hash, test_md4[i].output, MD4_DIGEST_SIZE) != 0) - return -205 - i; + return -1600 - i; } return 0; @@ -980,6 +1315,7 @@ int sha_test(void) { Sha sha; byte hash[SHA_DIGEST_SIZE]; + byte hashcopy[SHA_DIGEST_SIZE]; testVector a, b, c, d; testVector test_sha[4]; @@ -1018,18 +1354,32 @@ int sha_test(void) test_sha[2] = c; test_sha[3] = d; - ret = wc_InitSha(&sha); + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4001; + return -1700; for (i = 0; i < times; ++i) { - wc_ShaUpdate(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen); - wc_ShaFinal(&sha, hash); + ret = wc_ShaUpdate(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen); + if (ret != 0) + return -1710 - i; + + ret = wc_ShaGetHash(&sha, hashcopy); + if (ret != 0) + return -1720 - i; + + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) + return -1730 - i; if (XMEMCMP(hash, test_sha[i].output, SHA_DIGEST_SIZE) != 0) - return -10 - i; + return -1740 - i; + + if (XMEMCMP(hash, hashcopy, SHA_DIGEST_SIZE) != 0) + return -1750 - i; } + wc_ShaFree(&sha); + return 0; } @@ -1039,6 +1389,7 @@ int sha_test(void) int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -1075,15 +1426,25 @@ int ripemd_test(void) test_ripemd[2] = c; test_ripemd[3] = d; - wc_InitRipeMd(&ripemd); + ret = wc_InitRipeMd(&ripemd); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, - (word32)test_ripemd[i].inLen); - wc_RipeMdFinal(&ripemd, hash); + ret = wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, + (word32)test_ripemd[i].inLen); + if (ret) { + return ret; + } + + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret) { + return ret; + } if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) - return -10 - i; + return -1800 - i; } return 0; @@ -1145,18 +1506,18 @@ int blake2b_test(void) for (i = 0; i < BLAKE2_TESTS; i++) { ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) - return -4002; + return -1900 - i; ret = wc_Blake2bUpdate(&b2b, input, i); if (ret != 0) - return -4003; + return -1910 - 1; ret = wc_Blake2bFinal(&b2b, digest, 64); if (ret != 0) - return -4004; + return -1920 - i; if (XMEMCMP(digest, blake2b_vec[i], 64) != 0) { - return -300 - i; + return -1930 - i; } } @@ -1170,6 +1531,7 @@ int sha224_test(void) { Sha224 sha; byte hash[SHA224_DIGEST_SIZE]; + byte hashcopy[SHA224_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -1191,21 +1553,28 @@ int sha224_test(void) test_sha[0] = a; test_sha[1] = b; - ret = wc_InitSha224(&sha); + ret = wc_InitSha224_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4005; + return -2000; for (i = 0; i < times; ++i) { ret = wc_Sha224Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); if (ret != 0) - return -4006; + return -2010 - i; + ret = wc_Sha224GetHash(&sha, hashcopy); + if (ret != 0) + return -2020 - i; ret = wc_Sha224Final(&sha, hash); if (ret != 0) - return -4007; + return -2030 - i; if (XMEMCMP(hash, test_sha[i].output, SHA224_DIGEST_SIZE) != 0) - return -10 - i; + return -2040 - i; + + if (XMEMCMP(hash, hashcopy, SHA224_DIGEST_SIZE) != 0) + return -2050 - i; } + wc_Sha224Free(&sha); return 0; } @@ -1217,6 +1586,7 @@ int sha256_test(void) { Sha256 sha; byte hash[SHA256_DIGEST_SIZE]; + byte hashcopy[SHA256_DIGEST_SIZE]; testVector a, b; testVector test_sha[2]; @@ -1240,22 +1610,29 @@ int sha256_test(void) test_sha[0] = a; test_sha[1] = b; - ret = wc_InitSha256(&sha); + ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4005; + return -2100; for (i = 0; i < times; ++i) { ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); if (ret != 0) - return -4006; + return -2110 - i; + ret = wc_Sha256GetHash(&sha, hashcopy); + if (ret != 0) + return -2120 - i; ret = wc_Sha256Final(&sha, hash); if (ret != 0) - return -4007; + return -2130 - i; if (XMEMCMP(hash, test_sha[i].output, SHA256_DIGEST_SIZE) != 0) - return -10 - i; + return -2140 - i; + if (XMEMCMP(hash, hashcopy, SHA256_DIGEST_SIZE) != 0) + return -2150 - i; } + wc_Sha256Free(&sha); + return 0; } #endif @@ -1266,6 +1643,7 @@ int sha512_test(void) { Sha512 sha; byte hash[SHA512_DIGEST_SIZE]; + byte hashcopy[SHA512_DIGEST_SIZE]; int ret; testVector a, b; @@ -1294,23 +1672,29 @@ int sha512_test(void) test_sha[0] = a; test_sha[1] = b; - ret = wc_InitSha512(&sha); + ret = wc_InitSha512_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4009; + return -2200; for (i = 0; i < times; ++i) { ret = wc_Sha512Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); if (ret != 0) - return -4010; - + return -2210 - i; + ret = wc_Sha512GetHash(&sha, hashcopy); + if (ret != 0) + return -2220 - i; ret = wc_Sha512Final(&sha, hash); if (ret != 0) - return -4011; + return -2230 - i; if (XMEMCMP(hash, test_sha[i].output, SHA512_DIGEST_SIZE) != 0) - return -10 - i; + return -2240 - i; + if (XMEMCMP(hash, hashcopy, SHA512_DIGEST_SIZE) != 0) + return -2250 - i; } + wc_Sha512Free(&sha); + return 0; } #endif @@ -1321,6 +1705,7 @@ int sha384_test(void) { Sha384 sha; byte hash[SHA384_DIGEST_SIZE]; + byte hashcopy[SHA384_DIGEST_SIZE]; int ret; testVector a, b; @@ -1347,27 +1732,198 @@ int sha384_test(void) test_sha[0] = a; test_sha[1] = b; - ret = wc_InitSha384(&sha); + ret = wc_InitSha384_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4012; + return -2300; for (i = 0; i < times; ++i) { ret = wc_Sha384Update(&sha, (byte*)test_sha[i].input,(word32)test_sha[i].inLen); if (ret != 0) - return -4013; - + return -2310 - i; + ret = wc_Sha384GetHash(&sha, hashcopy); + if (ret != 0) + return -2320 - i; ret = wc_Sha384Final(&sha, hash); if (ret != 0) - return -4014; + return -2330 - i; if (XMEMCMP(hash, test_sha[i].output, SHA384_DIGEST_SIZE) != 0) - return -10 - i; + return -2340 - i; + if (XMEMCMP(hash, hashcopy, SHA384_DIGEST_SIZE) != 0) + return -2350 - i; } + wc_Sha384Free(&sha); + return 0; } #endif /* WOLFSSL_SHA384 */ +int hash_test(void) +{ + wc_HashAlg hash; + int ret, exp_ret; + int i, j; + byte data[] = "0123456789abcdef0123456789abcdef012345"; + byte out[MAX_DIGEST_SIZE]; + enum wc_HashType typesGood[] = { WC_HASH_TYPE_MD5, WC_HASH_TYPE_SHA, + WC_HASH_TYPE_SHA224, WC_HASH_TYPE_SHA384, + WC_HASH_TYPE_SHA512, WC_HASH_TYPE_SHA256 }; + enum wc_HashType typesNoImpl[] = { +#ifdef NO_MD5 + WC_HASH_TYPE_MD5, +#endif +#ifdef NO_SHA + WC_HASH_TYPE_SHA, +#endif +#ifndef WOLFSSL_SHA224 + WC_HASH_TYPE_SHA224, +#endif +#ifdef NO_SHA256 + WC_HASH_TYPE_SHA256, +#endif +#ifndef WOLFSSL_SHA384 + WC_HASH_TYPE_SHA384, +#endif +#ifndef WOLFSSL_SHA512 + WC_HASH_TYPE_SHA512, +#endif + WC_HASH_TYPE_NONE + }; + enum wc_HashType typesBad[] = { WC_HASH_TYPE_NONE, WC_HASH_TYPE_MD5_SHA, + WC_HASH_TYPE_MD2, WC_HASH_TYPE_MD4 }; + + /* Parameter Validation testing. */ + ret = wc_HashInit(NULL, WC_HASH_TYPE_SHA256); + if (ret != BAD_FUNC_ARG) + return -2400; + ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2401; + ret = wc_HashUpdate(&hash, WC_HASH_TYPE_SHA256, NULL, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2402; + ret = wc_HashUpdate(NULL, WC_HASH_TYPE_SHA256, data, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2403; + ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, NULL); + if (ret != BAD_FUNC_ARG) + return -2404; + ret = wc_HashFinal(&hash, WC_HASH_TYPE_SHA256, NULL); + if (ret != BAD_FUNC_ARG) + return -2405; + ret = wc_HashFinal(NULL, WC_HASH_TYPE_SHA256, out); + if (ret != BAD_FUNC_ARG) + return -2406; + + /* Try invalid hash algorithms. */ + for (i = 0; i < (int)(sizeof(typesBad)/sizeof(*typesBad)); i++) { + ret = wc_HashInit(&hash, typesBad[i]); + if (ret != BAD_FUNC_ARG) + return -2407 - i; + ret = wc_HashUpdate(&hash, typesBad[i], data, sizeof(data)); + if (ret != BAD_FUNC_ARG) + return -2417 - i; + ret = wc_HashFinal(&hash, typesBad[i], out); + if (ret != BAD_FUNC_ARG) + return -2427 - i; + } + + /* Try valid hash algorithms. */ + for (i = 0, j = 0; i < (int)(sizeof(typesGood)/sizeof(*typesGood)); i++) { + exp_ret = 0; + if (typesGood[i] == typesNoImpl[j]) { + /* Recognized but no implementation compiled in. */ + exp_ret = HASH_TYPE_E; + j++; + } + ret = wc_HashInit(&hash, typesGood[i]); + if (ret != exp_ret) + return -2437 - i; + ret = wc_HashUpdate(&hash, typesGood[i], data, sizeof(data)); + if (ret != exp_ret) + return -2447 - i; + ret = wc_HashFinal(&hash, typesGood[i], out); + if (ret != exp_ret) + return -2457 - i; +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + ret = wc_HashGetOID(typesGood[i]); + if (ret == BAD_FUNC_ARG || + (exp_ret == 0 && ret == HASH_TYPE_E) || + (exp_ret != 0 && ret != HASH_TYPE_E)) { + return -2467 - i; + } +#endif /* !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) */ + } + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + ret = wc_HashGetOID(WC_HASH_TYPE_MD2); +#ifdef WOLFSSL_MD2 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -2477; +#else + if (ret != HASH_TYPE_E) + return -2478; +#endif + ret = wc_HashGetOID(WC_HASH_TYPE_MD5_SHA); +#ifndef NO_MD5 + if (ret == HASH_TYPE_E || ret == BAD_FUNC_ARG) + return -2479; +#else + if (ret != HASH_TYPE_E) + return -2480; +#endif + ret = wc_HashGetOID(WC_HASH_TYPE_MD4); + if (ret != BAD_FUNC_ARG) + return -2481; + ret = wc_HashGetOID(WC_HASH_TYPE_NONE); + if (ret != BAD_FUNC_ARG) + return -2482; +#endif /* !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) */ + +#ifndef NO_ASN +#ifdef WOLFSSL_MD2 + ret = wc_GetCTC_HashOID(MD2); + if (ret == 0) + return -2483; +#endif +#ifndef NO_MD5 + ret = wc_GetCTC_HashOID(MD5); + if (ret == 0) + return -2484; +#endif +#ifndef NO_SHA + ret = wc_GetCTC_HashOID(SHA); + if (ret == 0) + return -2485; +#endif +#ifdef WOLFSSL_SHA224 + ret = wc_GetCTC_HashOID(SHA224); + if (ret == 0) + return -2486; +#endif +#ifndef NO_SHA256 + ret = wc_GetCTC_HashOID(SHA256); + if (ret == 0) + return -2487; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_GetCTC_HashOID(SHA384); + if (ret == 0) + return -2488; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_GetCTC_HashOID(SHA512); + if (ret == 0) + return -2489; +#endif + ret = wc_GetCTC_HashOID(-1); + if (ret != 0) + return -2490; +#endif + + return 0; +} #if !defined(NO_HMAC) && !defined(NO_MD5) int hmac_md5_test(void) @@ -1420,31 +1976,32 @@ int hmac_md5_test(void) } #endif - #ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) { - return -20009; + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) { + return -2500; } - #endif ret = wc_HmacSetKey(&hmac, MD5, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4015; + return -2501; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4016; + return -2502; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4017; + return -2503; if (XMEMCMP(hash, test_hmac[i].output, MD5_DIGEST_SIZE) != 0) - return -20 - i; + return -2504 - i; - #ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); - #endif + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(MD5) != MD5_DIGEST_SIZE) + return -2514; +#endif + return 0; } #endif /* NO_HMAC && NO_MD5 */ @@ -1500,28 +2057,32 @@ int hmac_sha_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) return -20010; -#endif + ret = wc_HmacSetKey(&hmac, SHA, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4018; + return -2601; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4019; + return -2602; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4020; + return -2603; if (XMEMCMP(hash, test_hmac[i].output, SHA_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + return -2604 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(SHA) != SHA_DIGEST_SIZE) + return -2614; +#endif + return 0; } #endif @@ -1578,28 +2139,32 @@ int hmac_sha224_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) - return -20011; -#endif + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -2700; + ret = wc_HmacSetKey(&hmac, SHA224, (byte*)keys[i],(word32)XSTRLEN(keys[i])); if (ret != 0) - return -4021; + return -2701; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4022; + return -2702; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4023; + return -2703; if (XMEMCMP(hash, test_hmac[i].output, SHA224_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + return -2704 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(SHA224) != SHA224_DIGEST_SIZE) + return -2714; +#endif + return 0; } #endif @@ -1659,28 +2224,36 @@ int hmac_sha256_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_HmacAsyncInit(&hmac, devId) != 0) - return -20011; -#endif + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -2800; + ret = wc_HmacSetKey(&hmac, SHA256, (byte*)keys[i],(word32)XSTRLEN(keys[i])); if (ret != 0) - return -4021; + return -2801; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4022; + return -2802; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4023; + return -2803; if (XMEMCMP(hash, test_hmac[i].output, SHA256_DIGEST_SIZE) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + return -2804 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(SHA256) != SHA256_DIGEST_SIZE) + return -2814; + if (wc_HmacSizeByType(20) != BAD_FUNC_ARG) + return -2815; +#endif + if (wolfSSL_GetHmacMaxSize() != MAX_DIGEST_SIZE) + return -2816; + return 0; } #endif @@ -1740,33 +2313,36 @@ int hmac_blake2b_test(void) if (i == 1) continue; /* cavium can't handle short keys, fips not allowed */ #endif -#ifdef WOLFSSL_ASYNC_CRYPT - #ifdef HAVE_CAVIUM_V - /* Blake2 not supported on Cavium V, but SHA3 is */ - return 0; + + #if defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + /* Blake2 only supported on Cavium Nitrox III */ + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -2900; #endif - if (wc_HmacAsyncInit(&hmac, devId) != 0) - return -20011; -#endif + ret = wc_HmacSetKey(&hmac, BLAKE2B_ID, (byte*)keys[i], (word32)XSTRLEN(keys[i])); if (ret != 0) - return -4024; + return -2901; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4025; + return -2902; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4026; + return -2903; if (XMEMCMP(hash, test_hmac[i].output, BLAKE2B_256) != 0) - return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif + return -2904 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(BLAKE2B_ID) != BLAKE2B_OUTBYTES) + return -2914; +#endif + return 0; } #endif @@ -1829,21 +2405,32 @@ int hmac_sha384_test(void) if (i == 1) continue; /* fips not allowed */ #endif + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3000; + ret = wc_HmacSetKey(&hmac, SHA384, (byte*)keys[i],(word32)XSTRLEN(keys[i])); if (ret != 0) - return -4027; + return -3001; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4028; + return -3002; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4029; + return -3003; if (XMEMCMP(hash, test_hmac[i].output, SHA384_DIGEST_SIZE) != 0) - return -20 - i; + return -3004 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(SHA384) != SHA384_DIGEST_SIZE) + return -3013; +#endif + return 0; } #endif @@ -1909,21 +2496,32 @@ int hmac_sha512_test(void) if (i == 1) continue; /* fips not allowed */ #endif + + if (wc_HmacInit(&hmac, HEAP_HINT, devId) != 0) + return -3100; + ret = wc_HmacSetKey(&hmac, SHA512, (byte*)keys[i],(word32)XSTRLEN(keys[i])); if (ret != 0) - return -4030; + return -3101; ret = wc_HmacUpdate(&hmac, (byte*)test_hmac[i].input, (word32)test_hmac[i].inLen); if (ret != 0) - return -4031; + return -3102; ret = wc_HmacFinal(&hmac, hash); if (ret != 0) - return -4032; + return -3103; if (XMEMCMP(hash, test_hmac[i].output, SHA512_DIGEST_SIZE) != 0) - return -20 - i; + return -3104 - i; + + wc_HmacFree(&hmac); } +#ifndef HAVE_FIPS + if (wc_HmacSizeByType(SHA512) != SHA512_DIGEST_SIZE) + return -3113; +#endif + return 0; } #endif @@ -1980,12 +2578,10 @@ int arc4_test(void) if (i == 3) keylen = 4; - #ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Arc4AsyncInit(&enc, devId) != 0) - return -20001; - if (wc_Arc4AsyncInit(&dec, devId) != 0) - return -20002; - #endif + if (wc_Arc4Init(&enc, HEAP_HINT, devId) != 0) + return -3200; + if (wc_Arc4Init(&dec, HEAP_HINT, devId) != 0) + return -3201; wc_Arc4SetKey(&enc, (byte*)keys[i], keylen); wc_Arc4SetKey(&dec, (byte*)keys[i], keylen); @@ -1995,15 +2591,13 @@ int arc4_test(void) wc_Arc4Process(&dec, plain, cipher, (word32)test_arc4[i].outLen); if (XMEMCMP(plain, test_arc4[i].input, test_arc4[i].outLen)) - return -20 - i; + return -3202 - i; if (XMEMCMP(cipher, test_arc4[i].output, test_arc4[i].outLen)) - return -20 - 5 - i; + return -3212 - i; - #ifdef WOLFSSL_ASYNC_CRYPT - wc_Arc4AsyncFree(&enc); - wc_Arc4AsyncFree(&dec); - #endif + wc_Arc4Free(&enc); + wc_Arc4Free(&dec); } return 0; @@ -2079,18 +2673,18 @@ int hc128_test(void) XMEMCPY(plain, test_hc128[i].input, test_hc128[i].outLen); if (wc_Hc128_Process(&enc, cipher, plain, (word32)test_hc128[i].outLen) != 0) { - return -110; + return -3300; } - if (wc_Hc128_Process(&dec, plain, cipher, + if (wc_Hc128_Process(&dec, plain, cipher, (word32)test_hc128[i].outLen) != 0) { - return -115; + return -3301; } if (XMEMCMP(plain, test_hc128[i].input, test_hc128[i].outLen)) - return -120 - i; + return -3302 - i; if (XMEMCMP(cipher, test_hc128[i].output, test_hc128[i].outLen)) - return -120 - 5 - i; + return -3312 - i; } #endif /* HAVE_HC128 */ @@ -2163,10 +2757,10 @@ int rabbit_test(void) wc_RabbitProcess(&dec, plain, cipher, (word32)test_rabbit[i].outLen); if (XMEMCMP(plain, test_rabbit[i].input, test_rabbit[i].outLen)) - return -130 - i; + return -3400 - i; if (XMEMCMP(cipher, test_rabbit[i].output, test_rabbit[i].outLen)) - return -130 - 5 - i; + return -3410 - i; } return 0; @@ -2272,10 +2866,10 @@ int chacha_test(void) return ret; if (XMEMCMP(test_chacha[i], cipher, 8)) - return -130 - 5 - i; + return -3500 - i; if (XMEMCMP(plain, input, 8)) - return -130 - i; + return -3510 - i; } /* test of starting at a different counter @@ -2301,7 +2895,7 @@ int chacha_test(void) return ret; if (XMEMCMP(plain + 64, sliver, 64)) - return -140; + return -3520; return 0; } @@ -2418,33 +3012,33 @@ int poly1305_test(void) for (i = 0; i < 3; i++) { ret = wc_Poly1305SetKey(&enc, keys[i], 32); if (ret != 0) - return -1001; + return -3600; ret = wc_Poly1305Update(&enc, msgs[i], szm[i]); if (ret != 0) - return -1005; + return -3601; ret = wc_Poly1305Final(&enc, tag); if (ret != 0) - return -60; + return -3602; if (XMEMCMP(tag, tests[i], sizeof(tag))) - return -61; + return -3603; } /* Check TLS MAC function from 2.8.2 https://tools.ietf.org/html/rfc7539 */ XMEMSET(tag, 0, sizeof(tag)); ret = wc_Poly1305SetKey(&enc, key4, sizeof(key4)); if (ret != 0) - return -62; + return -3604; ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional), (byte*)msg4, sizeof(msg4), tag, sizeof(tag)); if (ret != 0) - return -63; + return -3605; if (XMEMCMP(tag, correct4, sizeof(tag))) - return -64; + return -3606; /* Check fail of TLS MAC function if altering additional data */ XMEMSET(tag, 0, sizeof(tag)); @@ -2452,10 +3046,10 @@ int poly1305_test(void) ret = wc_Poly1305_MAC(&enc, additional, sizeof(additional), (byte*)msg4, sizeof(msg4), tag, sizeof(tag)); if (ret != 0) - return -65; + return -3607; if (XMEMCMP(tag, correct4, sizeof(tag)) == 0) - return -66; + return -3608; return 0; @@ -2635,27 +3229,77 @@ int chacha20_poly1305_aead_test(void) XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext)); + /* Parameter Validation testing */ + /* Encrypt */ + err = wc_ChaCha20Poly1305_Encrypt(NULL, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3700; + err = wc_ChaCha20Poly1305_Encrypt(key1, NULL, aad1, sizeof(aad1), + plaintext1, sizeof(plaintext1), generatedCiphertext, + generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3701; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), NULL, + sizeof(plaintext1), generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3702; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), NULL, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3703; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + sizeof(plaintext1), generatedCiphertext, NULL); + if (err != BAD_FUNC_ARG) + return -3704; + err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, + 0, generatedCiphertext, generatedAuthTag); + if (err != BAD_FUNC_ARG) + return -3705; + /* Decrypt */ + err = wc_ChaCha20Poly1305_Decrypt(NULL, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3706; + err = wc_ChaCha20Poly1305_Decrypt(key2, NULL, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3707; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), NULL, + sizeof(cipher2), authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3708; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), NULL, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3709; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + sizeof(cipher2), authTag2, NULL); + if (err != BAD_FUNC_ARG) + return -3710; + err = wc_ChaCha20Poly1305_Decrypt(key2, iv2, aad2, sizeof(aad2), cipher2, + 0, authTag2, generatedPlaintext); + if (err != BAD_FUNC_ARG) + return -3711; + /* Test #1 */ err = wc_ChaCha20Poly1305_Encrypt(key1, iv1, aad1, sizeof(aad1), plaintext1, sizeof(plaintext1), generatedCiphertext, generatedAuthTag); - if (err) - { + if (err) { return err; } /* -- Check the ciphertext and authtag */ - if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) - { - return -1064; + if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) { + return -3712; } - if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) - { - return -1065; + if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) { + return -3713; } /* -- Verify decryption works */ @@ -2664,14 +3308,12 @@ int chacha20_poly1305_aead_test(void) aad1, sizeof(aad1), cipher1, sizeof(cipher1), authTag1, generatedPlaintext); - if (err) - { + if (err) { return err; } - if (XMEMCMP(generatedPlaintext, plaintext1, sizeof( plaintext1))) - { - return -1066; + if (XMEMCMP(generatedPlaintext, plaintext1, sizeof( plaintext1))) { + return -3714; } XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); @@ -2684,21 +3326,18 @@ int chacha20_poly1305_aead_test(void) aad2, sizeof(aad2), plaintext2, sizeof(plaintext2), generatedCiphertext, generatedAuthTag); - if (err) - { + if (err) { return err; } /* -- Check the ciphertext and authtag */ - if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) - { - return -1067; + if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) { + return -3715; } - if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) - { - return -1068; + if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) { + return -3716; } /* -- Verify decryption works */ @@ -2707,14 +3346,12 @@ int chacha20_poly1305_aead_test(void) aad2, sizeof(aad2), cipher2, sizeof(cipher2), authTag2, generatedPlaintext); - if (err) - { + if (err) { return err; } - if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) - { - return -1069; + if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) { + return -3717; } return err; @@ -2758,25 +3395,25 @@ int des_test(void) ret = wc_Des_SetKey(&enc, key, iv, DES_ENCRYPTION); if (ret != 0) - return -31; + return -3800; ret = wc_Des_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); if (ret != 0) - return -32; + return -3801; ret = wc_Des_SetKey(&dec, key, iv, DES_DECRYPTION); if (ret != 0) - return -33; + return -3802; ret = wc_Des_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); if (ret != 0) - return -34; + return -3803; if (XMEMCMP(plain, vector, sizeof(plain))) - return -35; + return -3804; if (XMEMCMP(cipher, verify, sizeof(cipher))) - return -36; + return -3805; return 0; } @@ -2822,50 +3459,181 @@ int des3_test(void) int ret; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Des3AsyncInit(&enc, devId) != 0) - return -20005; - if (wc_Des3AsyncInit(&dec, devId) != 0) - return -20006; -#endif + if (wc_Des3Init(&enc, HEAP_HINT, devId) != 0) + return -3900; + if (wc_Des3Init(&dec, HEAP_HINT, devId) != 0) + return -3901; + ret = wc_Des3_SetKey(&enc, key3, iv3, DES_ENCRYPTION); if (ret != 0) - return -31; + return -3902; ret = wc_Des3_SetKey(&dec, key3, iv3, DES_DECRYPTION); if (ret != 0) - return -32; + return -3903; ret = wc_Des3_CbcEncrypt(&enc, cipher, vector, sizeof(vector)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -33; + return -3904; ret = wc_Des3_CbcDecrypt(&dec, plain, cipher, sizeof(cipher)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -34; + return -3905; if (XMEMCMP(plain, vector, sizeof(plain))) - return -35; + return -3906; if (XMEMCMP(cipher, verify3, sizeof(cipher))) - return -36; + return -3907; + + wc_Des3Free(&enc); + wc_Des3Free(&dec); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Des3AsyncFree(&enc); - wc_Des3AsyncFree(&dec); -#endif return 0; } #endif /* NO_DES */ #ifndef NO_AES +static int aes_key_size_test(void) +{ + int ret; + Aes aes; + byte key16[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; + byte key24[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; + byte key32[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66 }; + byte iv[] = "1234567890abcdef"; +#ifndef HAVE_FIPS + word32 keySize; +#endif + +#ifdef WC_INITAES_H + ret = wc_InitAes_h(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -4000; + ret = wc_InitAes_h(&aes, NULL); + if (ret != 0) + return -4001; +#endif + +#ifndef HAVE_FIPS + /* Parameter Validation testing. */ + ret = wc_AesGetKeySize(NULL, NULL); + if (ret != BAD_FUNC_ARG) + return -4002; + ret = wc_AesGetKeySize(&aes, NULL); + if (ret != BAD_FUNC_ARG) + return -4003; + ret = wc_AesGetKeySize(NULL, &keySize); + if (ret != BAD_FUNC_ARG) + return -4004; + /* Crashes in FIPS */ + ret = wc_AesSetKey(NULL, key16, sizeof(key16), iv, AES_ENCRYPTION); + if (ret != BAD_FUNC_ARG) + return -4005; +#endif + /* NULL IV indicates to use all zeros IV. */ + ret = wc_AesSetKey(&aes, key16, sizeof(key16), NULL, AES_ENCRYPTION); + if (ret != 0) + return -4006; + ret = wc_AesSetKey(&aes, key32, sizeof(key32) - 1, iv, AES_ENCRYPTION); + if (ret != BAD_FUNC_ARG) + return -4007; +#ifndef HAVE_FIPS + /* Force invalid rounds */ + aes.rounds = 16; + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != BAD_FUNC_ARG) + return -4008; +#endif + + ret = wc_AesSetKey(&aes, key16, sizeof(key16), iv, AES_ENCRYPTION); + if (ret != 0) + return -4009; +#ifndef HAVE_FIPS + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key16)) + return -4010; +#endif + + ret = wc_AesSetKey(&aes, key24, sizeof(key24), iv, AES_ENCRYPTION); + if (ret != 0) + return -4011; +#ifndef HAVE_FIPS + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key24)) + return -4012; +#endif + + ret = wc_AesSetKey(&aes, key32, sizeof(key32), iv, AES_ENCRYPTION); + if (ret != 0) + return -4013; +#ifndef HAVE_FIPS + ret = wc_AesGetKeySize(&aes, &keySize); + if (ret != 0 || keySize != sizeof(key32)) + return -4014; +#endif + + return 0; +} + +#if defined(HAVE_AES_CBC) +static int aes_cbc_test(void) +{ + byte cipher[AES_BLOCK_SIZE]; + byte plain[AES_BLOCK_SIZE]; + int ret; + const byte msg[] = { /* "Now is the time for all " w/o trailing 0 */ + 0x6e,0x6f,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6d,0x65,0x20, + 0x66,0x6f,0x72,0x20,0x61,0x6c,0x6c,0x20 + }; + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + /* Parameter Validation testing. */ + ret = wc_AesCbcEncryptWithKey(cipher, msg, AES_BLOCK_SIZE, key, 17, NULL); + if (ret != BAD_FUNC_ARG) + return -4100; + ret = wc_AesCbcDecryptWithKey(plain, cipher, AES_BLOCK_SIZE, key, 17, NULL); + if (ret != BAD_FUNC_ARG) + return -4101; + + ret = wc_AesCbcEncryptWithKey(cipher, msg, AES_BLOCK_SIZE, key, + AES_BLOCK_SIZE, iv); + if (ret != 0) + return -4102; + ret = wc_AesCbcDecryptWithKey(plain, cipher, AES_BLOCK_SIZE, key, + AES_BLOCK_SIZE, iv); + if (ret != 0) + return -4103; + + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE) != 0) + return -4104; + + return 0; +} +#endif + int aes_test(void) { #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_COUNTER) Aes enc; - Aes dec; - byte cipher[AES_BLOCK_SIZE * 4]; +#ifdef HAVE_AES_DECRYPT + Aes dec; byte plain [AES_BLOCK_SIZE * 4]; #endif +#endif /* HAVE_AES_CBC || WOLFSSL_AES_COUNTER */ int ret = 0; #ifdef HAVE_AES_CBC @@ -2885,31 +3653,40 @@ int aes_test(void) byte iv[] = "1234567890abcdef "; /* align */ #ifdef WOLFSSL_ASYNC_CRYPT - if (wc_AesAsyncInit(&enc, devId) != 0) - return -20003; - if (wc_AesAsyncInit(&dec, devId) != 0) - return -20004; + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4200; + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4201; #endif + ret = wc_AesSetKey(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); if (ret != 0) - return -1001; + return -4202; +#ifdef HAVE_AES_DECRYPT ret = wc_AesSetKey(&dec, key, AES_BLOCK_SIZE, iv, AES_DECRYPTION); if (ret != 0) - return -1002; + return -4203; +#endif - ret = wc_AesCbcEncrypt(&enc, cipher, msg, AES_BLOCK_SIZE); + ret = wc_AesCbcEncrypt(&enc, cipher, msg, AES_BLOCK_SIZE); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -1005; + return -4204; #ifdef HAVE_AES_DECRYPT ret = wc_AesCbcDecrypt(&dec, plain, cipher, AES_BLOCK_SIZE); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (ret != 0) - return -1006; + return -4205; if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) - return -60; + return -4206; #endif /* HAVE_AES_DECRYPT */ if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) - return -61; + return -4207; #if defined(WOLFSSL_AESNI) && defined(HAVE_AES_DECRYPT) { @@ -2980,31 +3757,32 @@ int aes_test(void) XMEMSET(bigPlain, 0, sizeof(bigPlain)); ret = wc_AesSetKey(&enc, bigKey, keySz, iv, AES_ENCRYPTION); if (ret != 0) - return -1030; + return -4208; ret = wc_AesSetKey(&dec, bigKey, keySz, iv, AES_DECRYPTION); if (ret != 0) - return -1031; + return -4209; ret = wc_AesCbcEncrypt(&enc, bigCipher, bigMsg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); + #endif if (ret != 0) - return -1032; + return -4210; ret = wc_AesCbcDecrypt(&dec, bigPlain, bigCipher, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); + #endif if (ret != 0) - return -1033; + return -4211; if (XMEMCMP(bigPlain, bigMsg, msgSz)) - return -1034; + return -4212; } } } #endif /* WOLFSSL_AESNI HAVE_AES_DECRYPT */ -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); - wc_AesAsyncFree(&dec); -#endif /* WOLFSSL_ASYNC_CRYPT */ - #endif /* HAVE_AES_CBC */ #ifdef WOLFSSL_AES_COUNTER @@ -3103,10 +3881,10 @@ int aes_test(void) wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(ctrPlain)); if (XMEMCMP(plain, ctrPlain, sizeof(ctrPlain))) - return -66; + return -4213; if (XMEMCMP(cipher, ctr128Cipher, sizeof(ctr128Cipher))) - return -67; + return -4214; /* let's try with just 9 bytes, non block size test */ wc_AesSetKeyDirect(&enc, ctr128Key, AES_BLOCK_SIZE, @@ -3119,20 +3897,20 @@ int aes_test(void) wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); if (XMEMCMP(plain, ctrPlain, sizeof(oddCipher))) - return -68; + return -4215; if (XMEMCMP(cipher, ctr128Cipher, sizeof(oddCipher))) - return -69; + return -4216; /* and an additional 9 bytes to reuse tmp left buffer */ wc_AesCtrEncrypt(&enc, cipher, ctrPlain, sizeof(oddCipher)); wc_AesCtrEncrypt(&dec, plain, cipher, sizeof(oddCipher)); if (XMEMCMP(plain, ctrPlain, sizeof(oddCipher))) - return -70; + return -4217; if (XMEMCMP(cipher, oddCipher, sizeof(oddCipher))) - return -71; + return -4218; /* 192 bit key */ wc_AesSetKeyDirect(&enc, ctr192Key, sizeof(ctr192Key), @@ -3145,11 +3923,11 @@ int aes_test(void) wc_AesCtrEncrypt(&enc, plain, ctr192Cipher, sizeof(ctr192Cipher)); if (XMEMCMP(plain, ctrPlain, sizeof(ctr192Cipher))) - return -72; + return -4219; wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); if (XMEMCMP(ctr192Cipher, cipher, sizeof(ctr192Cipher))) - return -73; + return -4220; /* 256 bit key */ wc_AesSetKeyDirect(&enc, ctr256Key, sizeof(ctr256Key), @@ -3162,11 +3940,11 @@ int aes_test(void) wc_AesCtrEncrypt(&enc, plain, ctr256Cipher, sizeof(ctr256Cipher)); if (XMEMCMP(plain, ctrPlain, sizeof(ctrPlain))) - return -74; + return -4221; wc_AesCtrEncrypt(&dec, cipher, ctrPlain, sizeof(ctrPlain)); if (XMEMCMP(ctr256Cipher, cipher, sizeof(ctr256Cipher))) - return -75; + return -4222; } #endif /* WOLFSSL_AES_COUNTER */ @@ -3195,24 +3973,198 @@ int aes_test(void) XMEMSET(cipher, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(&enc, niKey, sizeof(niKey), cipher, AES_ENCRYPTION); if (ret != 0) - return -1003; + return -4223; wc_AesEncryptDirect(&enc, cipher, niPlain); if (XMEMCMP(cipher, niCipher, AES_BLOCK_SIZE) != 0) - return -20006; + return -4224; XMEMSET(plain, 0, AES_BLOCK_SIZE); ret = wc_AesSetKey(&dec, niKey, sizeof(niKey), plain, AES_DECRYPTION); if (ret != 0) - return -1004; + return -4225; wc_AesDecryptDirect(&dec, plain, niCipher); if (XMEMCMP(plain, niPlain, AES_BLOCK_SIZE) != 0) - return -20007; + return -4226; } #endif /* WOLFSSL_AES_DIRECT */ + ret = aes_key_size_test(); + if (ret != 0) + return ret; + +#if defined(HAVE_AES_CBC) + ret = aes_cbc_test(); + if (ret != 0) + return ret; +#endif + + wc_AesFree(&enc); +#ifdef HAVE_AES_DECRYPT + wc_AesFree(&dec); +#endif + + return ret; +} + +int aes192_test(void) +{ +#ifdef HAVE_AES_CBC + Aes enc; + byte cipher[AES_BLOCK_SIZE]; +#ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain[AES_BLOCK_SIZE]; +#endif +#endif /* HAVE_AES_CBC */ + int ret = 0; + +#ifdef HAVE_AES_CBC + /* Test vectors from NIST Special Publication 800-38A, 2001 Edition + * Appendix F.2.3 */ + + const byte msg[] = { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0x4f,0x02,0x1d,0xb2,0x43,0xbc,0x63,0x3d, + 0x71,0x78,0x18,0x3a,0x9f,0xa0,0x71,0xe8 + }; + + byte key[] = { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + byte iv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + }; + + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4230; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4231; +#endif + + + ret = wc_AesSetKey(&enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + return -4232; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesSetKey(&dec, key, (int) sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) + return -4233; +#endif + + ret = wc_AesCbcEncrypt(&enc, cipher, msg, (int) sizeof(msg)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4234; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesCbcDecrypt(&dec, plain, cipher, (int) sizeof(cipher)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4235; + if (XMEMCMP(plain, msg, (int) sizeof(plain))) { + return -4236; + } +#endif + + if (XMEMCMP(cipher, verify, (int) sizeof(cipher))) + return -4237; +#endif /* HAVE_AES_CBC */ + return ret; } +int aes256_test(void) +{ +#ifdef HAVE_AES_CBC + Aes enc; + byte cipher[AES_BLOCK_SIZE]; +#ifdef HAVE_AES_DECRYPT + Aes dec; + byte plain[AES_BLOCK_SIZE]; +#endif +#endif /* HAVE_AES_CBC */ + int ret = 0; + +#ifdef HAVE_AES_CBC + /* Test vectors from NIST Special Publication 800-38A, 2001 Edition, + * Appendix F.2.5 */ + const byte msg[] = { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf5,0x8c,0x4c,0x04,0xd6,0xe5,0xf1,0xba, + 0x77,0x9e,0xab,0xfb,0x5f,0x7b,0xfb,0xd6 + }; + + byte key[] = { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + byte iv[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F + }; + + + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) + return -4240; +#ifdef HAVE_AES_DECRYPT + if (wc_AesInit(&dec, HEAP_HINT, devId) != 0) + return -4241; +#endif + + + ret = wc_AesSetKey(&enc, key, (int) sizeof(key), iv, AES_ENCRYPTION); + if (ret != 0) + return -4242; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesSetKey(&dec, key, (int) sizeof(key), iv, AES_DECRYPTION); + if (ret != 0) + return -4243; +#endif + + ret = wc_AesCbcEncrypt(&enc, cipher, msg, (int) sizeof(msg)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4244; +#ifdef HAVE_AES_DECRYPT + ret = wc_AesCbcDecrypt(&dec, plain, cipher, (int) sizeof(cipher)); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &dec.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) + return -4245; + if (XMEMCMP(plain, msg, (int) sizeof(plain))) { + return -4246; + } +#endif + + if (XMEMCMP(cipher, verify, (int) sizeof(cipher))) + return -4247; +#endif /* HAVE_AES_CBC */ + return 0; +} + #ifdef HAVE_AESGCM int aesgcm_test(void) @@ -3275,7 +4227,7 @@ int aesgcm_test(void) 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }; -#ifndef HAVE_FIPS +#if !defined(HAVE_FIPS) && !defined(HAVE_INTEL_QA) /* Test Case 12, uses same plaintext and AAD data. */ const byte k2[] = { @@ -3313,7 +4265,7 @@ int aesgcm_test(void) 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }; -#endif /* HAVE_FIPS */ +#endif /* !HAVE_FIPS && !HAVE_INTEL_QA */ byte resultT[sizeof(t1)]; byte resultP[sizeof(p)]; @@ -3324,43 +4276,69 @@ int aesgcm_test(void) XMEMSET(resultC, 0, sizeof(resultC)); XMEMSET(resultP, 0, sizeof(resultP)); - wc_AesGcmSetKey(&enc, k1, sizeof(k1)); + if (wc_AesInit(&enc, HEAP_HINT, devId) != 0) { + return -4300; + } + + result = wc_AesGcmSetKey(&enc, k1, sizeof(k1)); + if (result != 0) + return -4301; + /* AES-GCM encrypt and decrypt both use AES encrypt internally */ - wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv1, sizeof(iv1), + result = wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv1, sizeof(iv1), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -4302; if (XMEMCMP(c1, resultC, sizeof(resultC))) - return -68; + return -4303; if (XMEMCMP(t1, resultT, sizeof(resultT))) - return -69; + return -4304; result = wc_AesGcmDecrypt(&enc, resultP, resultC, sizeof(resultC), iv1, sizeof(iv1), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (result != 0) - return -70; + return -4305; if (XMEMCMP(p, resultP, sizeof(resultP))) - return -71; + return -4306; -#ifndef HAVE_FIPS + /* QAT only supports 12-byte IV */ +#if !defined(HAVE_FIPS) && !defined(HAVE_INTEL_QA) XMEMSET(resultT, 0, sizeof(resultT)); XMEMSET(resultC, 0, sizeof(resultC)); XMEMSET(resultP, 0, sizeof(resultP)); wc_AesGcmSetKey(&enc, k2, sizeof(k2)); /* AES-GCM encrypt and decrypt both use AES encrypt internally */ - wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv2, sizeof(iv2), + result = wc_AesGcmEncrypt(&enc, resultC, p, sizeof(p), iv2, sizeof(iv2), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (result != 0) + return -4307; if (XMEMCMP(c2, resultC, sizeof(resultC))) - return -230; + return -4308; if (XMEMCMP(t2, resultT, sizeof(resultT))) - return -231; + return -4309; result = wc_AesGcmDecrypt(&enc, resultP, resultC, sizeof(resultC), iv2, sizeof(iv2), resultT, sizeof(resultT), a, sizeof(a)); +#if defined(WOLFSSL_ASYNC_CRYPT) + result = wc_AsyncWait(result, &enc.asyncDev, WC_ASYNC_FLAG_NONE); +#endif if (result != 0) - return -232; + return -4310; if (XMEMCMP(p, resultP, sizeof(resultP))) - return -233; -#endif /* HAVE_FIPS */ + return -4311; +#endif /* !HAVE_FIPS && !HAVE_INTEL_QA */ + + wc_AesFree(&enc); return 0; } @@ -3411,45 +4389,20 @@ int gmac_test(void) 0x8d, 0x83, 0xb0, 0xbb, 0x14, 0xb6, 0x91 }; - const byte k3[] = - { - 0xb8, 0xe4, 0x9a, 0x5e, 0x37, 0xf9, 0x98, 0x2b, - 0xb9, 0x6d, 0xd0, 0xc9, 0xb6, 0xab, 0x26, 0xac - }; - const byte iv3[] = - { - 0xe4, 0x4a, 0x42, 0x18, 0x8c, 0xae, 0x94, 0x92, - 0x6a, 0x9c, 0x26, 0xb0 - }; - const byte a3[] = - { - 0x9d, 0xb9, 0x61, 0x68, 0xa6, 0x76, 0x7a, 0x31, - 0xf8, 0x29, 0xe4, 0x72, 0x61, 0x68, 0x3f, 0x8a - }; - const byte t3[] = - { - 0x23, 0xe2, 0x9f, 0x66, 0xe4, 0xc6, 0x52, 0x48 - }; - byte tag[16]; + XMEMSET(&gmac, 0, sizeof(Gmac)); /* clear context */ XMEMSET(tag, 0, sizeof(tag)); wc_GmacSetKey(&gmac, k1, sizeof(k1)); wc_GmacUpdate(&gmac, iv1, sizeof(iv1), a1, sizeof(a1), tag, sizeof(t1)); if (XMEMCMP(t1, tag, sizeof(t1)) != 0) - return -126; + return -4400; XMEMSET(tag, 0, sizeof(tag)); wc_GmacSetKey(&gmac, k2, sizeof(k2)); wc_GmacUpdate(&gmac, iv2, sizeof(iv2), a2, sizeof(a2), tag, sizeof(t2)); if (XMEMCMP(t2, tag, sizeof(t2)) != 0) - return -127; - - XMEMSET(tag, 0, sizeof(tag)); - wc_GmacSetKey(&gmac, k3, sizeof(k3)); - wc_GmacUpdate(&gmac, iv3, sizeof(iv3), a3, sizeof(a3), tag, sizeof(t3)); - if (XMEMCMP(t3, tag, sizeof(t3)) != 0) - return -128; + return -4401; return 0; } @@ -3505,43 +4458,44 @@ int aesccm_test(void) int result; + XMEMSET(&enc, 0, sizeof(Aes)); /* clear context */ XMEMSET(t2, 0, sizeof(t2)); XMEMSET(c2, 0, sizeof(c2)); XMEMSET(p2, 0, sizeof(p2)); result = wc_AesCcmSetKey(&enc, k, sizeof(k)); if (result != 0) - return -105; + return -4500; /* AES-CCM encrypt and decrypt both use AES encrypt internally */ result = wc_AesCcmEncrypt(&enc, c2, p, sizeof(c2), iv, sizeof(iv), t2, sizeof(t2), a, sizeof(a)); if (result != 0) - return -106; + return -4501; if (XMEMCMP(c, c2, sizeof(c2))) - return -107; + return -4502; if (XMEMCMP(t, t2, sizeof(t2))) - return -108; + return -4503; result = wc_AesCcmDecrypt(&enc, p2, c2, sizeof(p2), iv, sizeof(iv), t2, sizeof(t2), a, sizeof(a)); if (result != 0) - return -109; + return -4504; if (XMEMCMP(p, p2, sizeof(p2))) - return -110; + return -4505; /* Test the authentication failure */ t2[0]++; /* Corrupt the authentication tag. */ result = wc_AesCcmDecrypt(&enc, p2, c, sizeof(p2), iv, sizeof(iv), t2, sizeof(t2), a, sizeof(a)); if (result == 0) - return -111; + return -4506; /* Clear c2 to compare against p2. p2 should be set to zero in case of * authentication fail. */ XMEMSET(c2, 0, sizeof(c2)); if (XMEMCMP(p2, c2, sizeof(p2))) - return -112; + return -4507; return 0; } @@ -3710,20 +4664,20 @@ int aeskeywrap_test(void) output, sizeof(output), NULL); if ( (wrapSz < 0) || (wrapSz != (int)test_wrap[i].verifyLen) ) - return -101; + return -4600; if (XMEMCMP(output, test_wrap[i].verify, test_wrap[i].verifyLen) != 0) - return -102; + return -4601; plainSz = wc_AesKeyUnWrap((byte*)test_wrap[i].kek, test_wrap[i].kekLen, output, wrapSz, plain, sizeof(plain), NULL); if ( (plainSz < 0) || (plainSz != (int)test_wrap[i].dataLen) ) - return -103; + return -4602; if (XMEMCMP(plain, test_wrap[i].data, test_wrap[i].dataLen) != 0) - return -104; + return -4610 - i; } return 0; @@ -3910,24 +4864,24 @@ int camellia_test(void) /* Setting the IV and checking it was actually set. */ wc_CamelliaSetIV(&cam, ivc); if (XMEMCMP(cam.reg, ivc, CAMELLIA_BLOCK_SIZE)) - return -1; + return -4700; /* Setting the IV to NULL should be same as all zeros IV */ if (wc_CamelliaSetIV(&cam, NULL) != 0 || XMEMCMP(cam.reg, ive, CAMELLIA_BLOCK_SIZE)) - return -1; + return -4701; /* First parameter should never be null */ if (wc_CamelliaSetIV(NULL, NULL) == 0) - return -1; + return -4702; /* First parameter should never be null, check it fails */ if (wc_CamelliaSetKey(NULL, k1, sizeof(k1), NULL) == 0) - return -1; + return -4703; /* Key should have a size of 16, 24, or 32 */ if (wc_CamelliaSetKey(&cam, k1, 0, NULL) == 0) - return -1; + return -4704; return 0; } @@ -4004,14 +4958,14 @@ int idea_test(void) NULL, IDEA_ENCRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (enc) failed\n"); - return -1; + return -4800; } /* Data encryption */ wc_IdeaCipher(&idea, data, v1_plain[i]); if (XMEMCMP(&v1_cipher[i], data, IDEA_BLOCK_SIZE)) { printf("Bad encryption\n"); - return -1; + return -4801; } /* Set decryption key */ @@ -4020,14 +4974,14 @@ int idea_test(void) NULL, IDEA_DECRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (dec) failed\n"); - return -1; + return -4802; } /* Data decryption */ wc_IdeaCipher(&idea, data, data); if (XMEMCMP(v1_plain[i], data, IDEA_BLOCK_SIZE)) { printf("Bad decryption\n"); - return -1; + return -4803; } /* Set encryption key */ @@ -4036,7 +4990,7 @@ int idea_test(void) v_key[i], IDEA_ENCRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (enc) failed\n"); - return -1; + return -4804; } XMEMSET(msg_enc, 0, sizeof(msg_enc)); @@ -4044,7 +4998,7 @@ int idea_test(void) (word32)XSTRLEN(message)+1); if (ret != 0) { printf("wc_IdeaCbcEncrypt failed\n"); - return -1; + return -4805; } /* Set decryption key */ @@ -4053,7 +5007,7 @@ int idea_test(void) v_key[i], IDEA_DECRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (dec) failed\n"); - return -1; + return -4806; } XMEMSET(msg_dec, 0, sizeof(msg_dec)); @@ -4061,12 +5015,12 @@ int idea_test(void) (word32)XSTRLEN(message)+1); if (ret != 0) { printf("wc_IdeaCbcDecrypt failed\n"); - return -1; + return -4807; } if (XMEMCMP(message, msg_dec, (word32)XSTRLEN(message))) { printf("Bad CBC decryption\n"); - return -1; + return -4808; } } @@ -4077,7 +5031,7 @@ int idea_test(void) NULL, IDEA_ENCRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (enc) failed\n"); - return -1; + return -4809; } /* 100 times data encryption */ @@ -4088,7 +5042,7 @@ int idea_test(void) if (XMEMCMP(v1_cipher_100[i], data, IDEA_BLOCK_SIZE)) { printf("Bad encryption (100 times)\n"); - return -1; + return -4810; } /* 1000 times data encryption */ @@ -4099,7 +5053,7 @@ int idea_test(void) if (XMEMCMP(v1_cipher_1000[i], data, IDEA_BLOCK_SIZE)) { printf("Bad encryption (100 times)\n"); - return -1; + return -4811; } } @@ -4111,32 +5065,36 @@ int idea_test(void) rnd[1000], enc[1000], dec[1000]; /* random values */ + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); + #else ret = wc_InitRng(&rng); + #endif if (ret != 0) - return -39; + return -4812; for (i = 0; i < 1000; i++) { /* random key */ ret = wc_RNG_GenerateBlock(&rng, key, sizeof(key)); if (ret != 0) - return -40; + return -4813; /* random iv */ ret = wc_RNG_GenerateBlock(&rng, iv, sizeof(iv)); if (ret != 0) - return -40; + return -4814; /* random data */ ret = wc_RNG_GenerateBlock(&rng, rnd, sizeof(rnd)); if (ret != 0) - return -41; + return -4815; /* Set encryption key */ XMEMSET(&idea, 0, sizeof(Idea)); ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, iv, IDEA_ENCRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (enc) failed\n"); - return -42; + return -4816; } /* Data encryption */ @@ -4144,7 +5102,7 @@ int idea_test(void) ret = wc_IdeaCbcEncrypt(&idea, enc, rnd, sizeof(rnd)); if (ret != 0) { printf("wc_IdeaCbcEncrypt failed\n"); - return -43; + return -4817; } /* Set decryption key */ @@ -4152,7 +5110,7 @@ int idea_test(void) ret = wc_IdeaSetKey(&idea, key, IDEA_KEY_SIZE, iv, IDEA_DECRYPTION); if (ret != 0) { printf("wc_IdeaSetKey (enc) failed\n"); - return -44; + return -4818; } /* Data decryption */ @@ -4160,12 +5118,12 @@ int idea_test(void) ret = wc_IdeaCbcDecrypt(&idea, dec, enc, sizeof(enc)); if (ret != 0) { printf("wc_IdeaCbcDecrypt failed\n"); - return -45; + return -4819; } if (XMEMCMP(rnd, dec, sizeof(rnd))) { printf("Bad CBC decryption\n"); - return -46; + return -4820; } } @@ -4185,14 +5143,18 @@ static int random_rng_test(void) byte block[32]; int ret, i; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); - if (ret != 0) return -39; +#endif + if (ret != 0) return -4900; XMEMSET(block, 0, sizeof(block)); ret = wc_RNG_GenerateBlock(&rng, block, sizeof(block)); if (ret != 0) { - ret = -40; + ret = -4901; goto exit; } @@ -4204,10 +5166,15 @@ static int random_rng_test(void) } /* All zeros count check */ if (ret >= (int)sizeof(block)) { - ret = -38; + ret = -4902; + goto exit; + } + + ret = wc_RNG_GenerateByte(&rng, block); + if (ret != 0) { + ret = -4903; goto exit; } - ret = 0; exit: /* Make sure and free RNG */ @@ -4216,7 +5183,7 @@ static int random_rng_test(void) return ret; } -#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) +#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) int random_test(void) { @@ -4275,37 +5242,36 @@ int random_test(void) ret = wc_RNG_HealthTest(0, test1Entropy, sizeof(test1Entropy), NULL, 0, output, sizeof(output)); if (ret != 0) - return -39; + return -5000; if (XMEMCMP(test1Output, output, sizeof(output)) != 0) - return -40; + return -5001; ret = wc_RNG_HealthTest(1, test2EntropyA, sizeof(test2EntropyA), test2EntropyB, sizeof(test2EntropyB), output, sizeof(output)); if (ret != 0) - return -41; + return -5002; if (XMEMCMP(test2Output, output, sizeof(output)) != 0) - return -42; + return -5003; /* Basic RNG generate block test */ - random_rng_test(); + if (random_rng_test() != 0) + return -5004; return 0; } -#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#else int random_test(void) { /* Basic RNG generate block test */ - random_rng_test(); - - return 0; + return random_rng_test(); } -#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ +#endif /* HAVE_HASHDRBG && !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* WC_NO_RNG */ @@ -4317,86 +5283,90 @@ int memory_test(void) word32 size[] = { WOLFMEM_BUCKETS }; word32 dist[] = { WOLFMEM_DIST }; byte buffer[30000]; /* make large enough to involve many bucket sizes */ + int pad = -(int)((wolfssl_word)&(buffer[0])) & (WOLFSSL_STATIC_ALIGN - 1); + /* pad to account for if head of buffer is not at set memory + * alignment when tests are ran */ /* check macro settings */ if (sizeof(size)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { - return -97; + return -5100; } if (sizeof(dist)/sizeof(word32) != WOLFMEM_MAX_BUCKETS) { - return -98; + return -5101; } for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { if ((size[i] % WOLFSSL_STATIC_ALIGN) != 0) { /* each element in array should be divisable by alignment size */ - return -99; + return -5102; } } for (i = 1; i < WOLFMEM_MAX_BUCKETS; i++) { if (size[i - 1] >= size[i]) { - return -100; /* sizes should be in increasing order */ + return -5103; /* sizes should be in increasing order */ } } /* check that padding size returned is possible */ - if (wolfSSL_MemoryPaddingSz() <= WOLFSSL_STATIC_ALIGN) { - return -101; /* no room for wc_Memory struct */ + if (wolfSSL_MemoryPaddingSz() < WOLFSSL_STATIC_ALIGN) { + return -5104; /* no room for wc_Memory struct */ } if (wolfSSL_MemoryPaddingSz() < 0) { - return -102; + return -5105; } if (wolfSSL_MemoryPaddingSz() % WOLFSSL_STATIC_ALIGN != 0) { - return -103; /* not aligned! */ + return -5106; /* not aligned! */ } /* check function to return optimum buffer size (rounded down) */ - if ((ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_GENERAL)) - % WOLFSSL_STATIC_ALIGN != 0) { - return -104; /* not aligned! */ + ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_GENERAL); + if ((ret - pad) % WOLFSSL_STATIC_ALIGN != 0) { + return -5107; /* not aligned! */ } if (ret < 0) { - return -105; + return -5108; } if ((unsigned int)ret > sizeof(buffer)) { - return -106; /* did not round down as expected */ + return -5109; /* did not round down as expected */ } if (ret != wolfSSL_StaticBufferSz(buffer, ret, WOLFMEM_GENERAL)) { - return -107; /* retrun value changed when using suggested value */ + return -5110; /* retrun value changed when using suggested value */ } ret = wolfSSL_MemoryPaddingSz(); + ret += pad; /* add space that is going to be needed if buffer not aligned */ if (wolfSSL_StaticBufferSz(buffer, size[0] + ret + 1, WOLFMEM_GENERAL) != (ret + (int)size[0])) { - return -108; /* did not round down to nearest bucket value */ + return -5111; /* did not round down to nearest bucket value */ } ret = wolfSSL_StaticBufferSz(buffer, sizeof(buffer), WOLFMEM_IO_POOL); - if (ret < 0) { - return -109; + if ((ret - pad) < 0) { + return -5112; } - if ((ret % (WOLFMEM_IO_SZ + wolfSSL_MemoryPaddingSz())) != 0) { - return -110; /* not even chunks of memory for IO size */ + if (((ret - pad) % (WOLFMEM_IO_SZ + wolfSSL_MemoryPaddingSz())) != 0) { + return -5113; /* not even chunks of memory for IO size */ } - if ((ret % WOLFSSL_STATIC_ALIGN) != 0) { - return -111; /* memory not aligned */ + if (((ret - pad) % WOLFSSL_STATIC_ALIGN) != 0) { + return -5114; /* memory not aligned */ } /* check for passing bad or unknown argments to functions */ if (wolfSSL_StaticBufferSz(NULL, 1, WOLFMEM_GENERAL) > 0) { - return -112; + return -5115; } if (wolfSSL_StaticBufferSz(buffer, 1, WOLFMEM_GENERAL) != 0) { - return -113; /* should round to 0 since struct + bucket will not fit */ + return -5116; /* should round to 0 since struct + bucket will not fit */ } (void)dist; /* avoid static analysis warning of variable not used */ @@ -4433,95 +5403,166 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #endif /* HAVE_NTRU */ -#ifndef NO_RSA +#ifndef NO_FILESYSTEM -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #ifdef FREESCALE_MQX - static const char* clientKey = "a:\\certs\\client-key.der"; - static const char* clientCert = "a:\\certs\\client-cert.der"; - #ifdef HAVE_PKCS7 - static const char* eccClientKey = "a:\\certs\\ecc-client-key.der"; - static const char* eccClientCert = "a:\\certs\\client-ecc-cert.der"; - #endif - #ifdef WOLFSSL_CERT_EXT - static const char* clientKeyPub = "a:\\certs\\client-keyPub.der"; - #endif - #ifdef WOLFSSL_CERT_GEN - static const char* caKeyFile = "a:\\certs\\ca-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* caKeyPubFile = "a:\\certs\\ca-keyPub.der"; - #endif - static const char* caCertFile = "a:\\certs\\ca-cert.pem"; - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "a:\\certs\\ecc-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* eccCaKeyPubFile = "a:\\certs\\ecc-keyPub.der"; - #endif - static const char* eccCaCertFile = "a:\\certs\\server-ecc.pem"; - #endif - #endif - #elif defined(WOLFSSL_MKD_SHELL) - static char* clientKey = "certs/client-key.der"; - static char* clientCert = "certs/client-cert.der"; - void set_clientKey(char *key) { clientKey = key ; } - void set_clientCert(char *cert) { clientCert = cert ; } - #ifdef HAVE_PKCS7 - static const char* eccClientKey = "certs/ecc-client-key.der"; - static const char* eccClientCert = "certs/client-ecc-cert.der"; - void set_eccClientKey(char* key) { eccClientKey = key ; } - void set_eccClientCert(char* cert) { eccClientCert = cert ; } +/* Cert Paths */ +#ifdef FREESCALE_MQX + #define CERT_PREFIX "a:\\" + #define CERT_PATH_SEP "\\" +#elif defined(WOLFSSL_MKD_SHELL) + #define CERT_PREFIX "" + #define CERT_PATH_SEP "/" +#elif defined(WOLFSSL_uTKERNEL2) + #define CERT_PREFIX "/uda/" + #define CERT_PATH_SEP "/" +#else + #define CERT_PREFIX "./" + #define CERT_PATH_SEP "/" +#endif +#define CERT_ROOT CERT_PREFIX "certs" CERT_PATH_SEP + +/* Generated Test Certs */ +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN) + #ifndef NO_RSA + static const char* clientKey = CERT_ROOT "client-key.der"; + static const char* clientCert = CERT_ROOT "client-cert.der"; + #if defined(HAVE_PKCS7) && defined(HAVE_ECC) + static const char* eccClientKey = CERT_ROOT "ecc-client-key.der"; + static const char* eccClientCert = CERT_ROOT "client-ecc-cert.der"; #endif #ifdef WOLFSSL_CERT_EXT - static const char* clientKeyPub = "certs/client-keyPub.der"; - void set_clientKeyPub(char *key) { clientKeyPub = key ; } + static const char* clientKeyPub = CERT_ROOT "client-keyPub.der"; #endif #ifdef WOLFSSL_CERT_GEN - static char* caKeyFile = "certs/ca-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* caKeyPubFile = "certs/ca-keyPub.der"; - void set_caKeyPubFile (char * key) { caKeyPubFile = key ; } - #endif - static char* caCertFile = "certs/ca-cert.pem"; - void set_caKeyFile (char * key) { caKeyFile = key ; } - void set_caCertFile(char * cert) { caCertFile = cert ; } - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "certs/ecc-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* eccCaKeyPubFile = "certs/ecc-keyPub.der"; - void set_eccCaKeyPubFile(char * key) { eccCaKeyPubFile = key ; } - #endif - static const char* eccCaCertFile = "certs/server-ecc.pem"; - void set_eccCaKeyFile (char * key) { eccCaKeyFile = key ; } - void set_eccCaCertFile(char * cert) { eccCaCertFile = cert ; } - #endif + static const char* rsaCaKeyFile = CERT_ROOT "ca-key.der"; + static const char* rsaCaCertFile = CERT_ROOT "ca-cert.pem"; #endif - #else - static const char* clientKey = "./certs/client-key.der"; - static const char* clientCert = "./certs/client-cert.der"; - #ifdef HAVE_PKCS7 - static const char* eccClientKey = "./certs/ecc-client-key.der"; - static const char* eccClientCert = "./certs/client-ecc-cert.der"; + #endif /* !NO_RSA */ + #ifndef NO_DH + static const char* dhKey = CERT_ROOT "dh2048.der"; + #endif + #ifndef NO_DSA + static const char* dsaKey = CERT_ROOT "dsa2048.der"; + #endif +#endif /* !USE_CERT_BUFFER_* */ +#if !defined(USE_CERT_BUFFERS_256) && !defined(NO_ASN) + #ifdef HAVE_ECC + /* cert files to be used in rsa cert gen test, check if RSA enabled */ + #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) + static const char* eccCaCertFile = CERT_ROOT "server-ecc.pem"; + static const char* eccCaKeyFile = CERT_ROOT "ecc-key.der"; #endif #ifdef WOLFSSL_CERT_EXT - static const char* clientKeyPub = "./certs/client-keyPub.der"; - #endif - #ifdef WOLFSSL_CERT_GEN - static const char* caKeyFile = "./certs/ca-key.der"; - static const char* caCertFile = "./certs/ca-cert.pem"; - #ifdef HAVE_ECC - static const char* eccCaKeyFile = "./certs/ecc-key.der"; - #ifdef WOLFSSL_CERT_EXT - static const char* eccCaKeyPubFile = "./certs/ecc-keyPub.der"; - #endif - static const char* eccCaCertFile = "./certs/server-ecc.pem"; - #endif + static const char* eccCaKeyPubFile = CERT_ROOT "ecc-keyPub.der"; #endif + #endif /* HAVE_ECC */ +#endif /* !USE_CERT_BUFFER_* */ + +#ifndef NO_WRITE_TEMP_FILES +#ifdef HAVE_ECC + /* Temporary Cert Files to be used in rsa cert gen test, is RSA enabled */ + #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) + static const char* certEccPemFile = CERT_PREFIX "certecc.pem"; #endif -#endif + #ifdef WOLFSSL_KEY_GEN + static const char* eccCaKeyPemFile = CERT_PREFIX "ecc-key.pem"; + static const char* eccPubKeyDerFile = CERT_PREFIX "ecc-public-key.der"; + static const char* eccCaKeyTempFile = CERT_PREFIX "ecc-key.der"; + #endif + #ifndef NO_RSA + #if defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)) + static const char* certEccDerFile = CERT_PREFIX "certecc.der"; + #endif + #endif +#endif /* HAVE_ECC */ +#ifndef NO_RSA + #if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) + static const char* otherCertDerFile = CERT_PREFIX "othercert.der"; + static const char* certDerFile = CERT_PREFIX "cert.der"; + #endif + #ifdef WOLFSSL_CERT_GEN + static const char* otherCertPemFile = CERT_PREFIX "othercert.pem"; + static const char* certPemFile = CERT_PREFIX "cert.pem"; + #endif + #ifdef WOLFSSL_KEY_GEN + static const char* keyDerFile = CERT_PREFIX "key.der"; + static const char* keyPemFile = CERT_PREFIX "key.pem"; + #endif + #ifdef WOLFSSL_CERT_REQ + static const char* certReqDerFile = CERT_PREFIX "certreq.der"; + static const char* certReqPemFile = CERT_PREFIX "certreq.pem"; + #endif +#endif /* !NO_RSA */ +#endif /* !NO_WRITE_TEMP_FILES */ +#endif /* !NO_FILESYSTEM */ -#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) -int certext_test(void) +#ifndef NO_RSA + +#if !defined(NO_ASN_TIME) && defined(WOLFSSL_TEST_CERT) +int cert_test(void) +{ + DecodedCert cert; + byte* tmp; + size_t bytes; + FILE *file; + int ret; + + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return -5200; + + /* Certificate with Name Constraints extension. */ +#ifdef FREESCALE_MQX + file = fopen(".\\certs\\test\\cert-ext-nc.der", "rb"); +#else + file = fopen("./certs/test/cert-ext-nc.der", "rb"); +#endif + if (!file) { + ret = -5201; + goto done; + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ret = -5202; + goto done; + } + FreeDecodedCert(&cert); + + /* Certificate with Inhibit Any Policy extension. */ +#ifdef FREESCALE_MQX + file = fopen(".\\certs\\test\\cert-ext-ia.der", "rb"); +#else + file = fopen("./certs/test/cert-ext-ia.der", "rb"); +#endif + if (!file) { + ret = -5203; + goto done; + } + bytes = fread(tmp, 1, FOURK_BUF, file); + fclose(file); + InitDecodedCert(&cert, tmp, (word32)bytes, 0); + ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + ret = -5204; + goto done; + } + +done: + FreeDecodedCert(&cert); + XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif + +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT) +int certext_test(void) { DecodedCert cert; byte* tmp; @@ -4549,17 +5590,13 @@ int certext_test(void) tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) - return -200; + return -5300; - /* load othercert.pem (Cert signed by an authority) */ -#ifdef FREESCALE_MQX - file = fopen("a:\\certs\\othercert.der", "rb"); -#else - file = fopen("./othercert.der", "rb"); -#endif + /* load othercert.der (Cert signed by an authority) */ + file = fopen(otherCertDerFile, "rb"); if (!file) { XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -200; + return -5301; } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -4569,48 +5606,44 @@ int certext_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) - return -201; + return -5302; /* check the SKID from a RSA certificate */ if (XMEMCMP(skid_rsa, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) - return -202; + return -5303; /* check the AKID from an RSA certificate */ if (XMEMCMP(akid_rsa, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) - return -203; + return -5304; /* check the Key Usage from an RSA certificate */ if (!cert.extKeyUsageSet) - return -204; + return -5305; if (cert.extKeyUsage != (KEYUSE_KEY_ENCIPHER|KEYUSE_KEY_AGREE)) - return -205; + return -5306; /* check the CA Basic Constraints from an RSA certificate */ if (cert.isCA) - return -206; + return -5307; #ifndef WOLFSSL_SEP /* test only if not using SEP policies */ /* check the Certificate Policies Id */ if (cert.extCertPoliciesNb != 1) - return -227; + return -5308; if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) - return -228; + return -5309; #endif FreeDecodedCert(&cert); #ifdef HAVE_ECC - /* load certecc.pem (Cert signed by an authority) */ -#ifdef FREESCALE_MQX - file = fopen("a:\\certs\\certecc.der", "rb"); -#else - file = fopen("./certecc.der", "rb"); -#endif + /* load certecc.der (Cert signed by an authority) */ + file = fopen(certEccDerFile, "rb"); if (!file) { XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -210; + return -5310; } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -4620,51 +5653,47 @@ int certext_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) - return -211; + return -5311; /* check the SKID from a ECC certificate */ if (XMEMCMP(skid_rsa, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) - return -212; + return -5312; /* check the AKID from an ECC certificate */ if (XMEMCMP(akid_ecc, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) - return -213; + return -5313; /* check the Key Usage from an ECC certificate */ if (!cert.extKeyUsageSet) - return -214; + return -5314; if (cert.extKeyUsage != (KEYUSE_DIGITAL_SIG|KEYUSE_CONTENT_COMMIT)) - return -215; + return -5315; /* check the CA Basic Constraints from an ECC certificate */ if (cert.isCA) - return -216; + return -5316; #ifndef WOLFSSL_SEP /* test only if not using SEP policies */ /* check the Certificate Policies Id */ if (cert.extCertPoliciesNb != 2) - return -217; + return -5317; if (strncmp(cert.extCertPolicies[0], "2.4.589440.587.101.2.1.9632587.1", 32)) - return -218; + return -5318; if (strncmp(cert.extCertPolicies[1], "1.2.13025.489.1.113549", 22)) - return -219; + return -5319; #endif FreeDecodedCert(&cert); #endif /* HAVE_ECC */ - /* load cert.pem (self signed certificate) */ -#ifdef FREESCALE_MQX - file = fopen("a:\\certs\\cert.der", "rb"); -#else - file = fopen("./cert.der", "rb"); -#endif + /* load cert.der (self signed certificate) */ + file = fopen(certDerFile, "rb"); if (!file) { XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -220; + return -5320; } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -4674,37 +5703,37 @@ int certext_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) - return -221; + return -5321; /* check the SKID from a CA certificate */ if (XMEMCMP(kid_ca, cert.extSubjKeyId, sizeof(cert.extSubjKeyId))) - return -222; + return -5322; /* check the AKID from an CA certificate */ if (XMEMCMP(kid_ca, cert.extAuthKeyId, sizeof(cert.extAuthKeyId))) - return -223; + return -5323; /* check the Key Usage from CA certificate */ if (!cert.extKeyUsageSet) - return -224; + return -5324; if (cert.extKeyUsage != (KEYUSE_KEY_CERT_SIGN|KEYUSE_CRL_SIGN)) - return -225; + return -5325; /* check the CA Basic Constraints CA certificate */ if (!cert.isCA) - return -226; + return -5326; #ifndef WOLFSSL_SEP /* test only if not using SEP policies */ /* check the Certificate Policies Id */ if (cert.extCertPoliciesNb != 2) - return -227; + return -5327; if (strncmp(cert.extCertPolicies[0], "2.16.840.1.101.3.4.1.42", 23)) - return -228; + return -5328; if (strncmp(cert.extCertPolicies[1], "1.2.840.113549.1.9.16.6.5", 25)) - return -229; + return -5329; #endif FreeDecodedCert(&cert); @@ -4714,32 +5743,557 @@ int certext_test(void) } #endif /* WOLFSSL_CERT_EXT && WOLFSSL_TEST_CERT */ +static int rsa_flatten_test(RsaKey* key) +{ + int ret; + byte e[256]; + byte n[256]; + word32 eSz = sizeof(e); + word32 nSz = sizeof(n); + + /* Parameter Validation testing. */ + ret = wc_RsaFlattenPublicKey(NULL, e, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5330; + ret = wc_RsaFlattenPublicKey(key, NULL, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5331; + ret = wc_RsaFlattenPublicKey(key, e, NULL, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5332; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, NULL, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5333; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, NULL); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != BAD_FUNC_ARG) +#endif + return -5334; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); + if (ret != 0) + return -5335; + eSz = 0; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#elif defined(HAVE_FIPS) + if (ret != 0) +#else + if (ret != RSA_BUFFER_E) +#endif + return -5336; + eSz = sizeof(e); + nSz = 0; + ret = wc_RsaFlattenPublicKey(key, e, &eSz, n, &nSz); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#else + if (ret != RSA_BUFFER_E) +#endif + return -5337; + + return 0; +} + +static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng) +{ + int ret; + word32 sigSz; + byte in[] = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)in); + byte out[256]; + + /* Parameter Validation testing. */ + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_NONE, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5338; + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, key, 0); + if (ret != BAD_FUNC_ARG) + return -5339; + + sigSz = modLen; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, NULL, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5340; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + 0, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5341; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, NULL, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5342; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, NULL, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5343; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, NULL, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5344; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, 0, rng); + if (ret != BAD_FUNC_ARG) + return -5345; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, NULL); +#ifdef HAVE_USER_RSA + /* Implementation using IPP Libraries returns: + * -101 = USER_CRYPTO_ERROR + */ + if (ret == 0) +#elif defined(WOLFSSL_ASYNC_CRYPT) + /* async may not require RNG */ + if (ret != 0 && ret != MISSING_RNG_E) +#elif defined(HAVE_FIPS) || defined(WOLFSSL_ASYNC_CRYPT) || \ + !defined(WC_RSA_BLINDING) + /* FIPS140 implementation does not do blinding */ + if (ret != 0) +#else + if (ret != MISSING_RNG_E) +#endif + return -5346; + sigSz = 0; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != BAD_FUNC_ARG) + return -5347; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, NULL, + inLen, out, modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5348; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + 0, out, modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5349; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, NULL, modLen, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5350; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, 0, key, keyLen); + if (ret != BAD_FUNC_ARG) + return -5351; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, modLen, NULL, keyLen); + if (ret != BAD_FUNC_ARG) + return -5352; + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, modLen, key, 0); + if (ret != BAD_FUNC_ARG) + return -5353; + +#ifndef HAVE_ECC + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, keyLen); + if (ret != SIG_TYPE_E) + return -5354; +#endif + + /* Use APIs. */ + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA, key, keyLen); + if (ret != modLen) + return -5355; + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_RSA_W_ENC, key, keyLen); + if (ret != modLen) + return -5356; + + sigSz = ret; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -5357; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, modLen, key, keyLen); + if (ret != 0) + return -5358; + + sigSz = sizeof(out); + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + in, inLen, out, &sigSz, key, keyLen, rng); + if (ret != 0) + return -5359; + + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, + in, inLen, out, modLen, key, keyLen); + if (ret != 0) + return -5360; + + /* Wrong signature type. */ + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, in, + inLen, out, modLen, key, keyLen); + if (ret == 0) + return -5361; + + return 0; +} + +#ifndef HAVE_USER_RSA +static int rsa_decode_test(void) +{ + int ret; + word32 inSz; + word32 inOutIdx; + RsaKey keyPub; + const byte n[2] = { 0x00, 0x23 }; + const byte e[2] = { 0x00, 0x03 }; + const byte good[] = { 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte goodAlgId[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte goodAlgIdNull[] = { 0x30, 0x11, 0x30, 0x0f, 0x06, 0x00, + 0x05, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, + 0x02, 0x1, 0x03 }; + const byte badAlgIdNull[] = { 0x30, 0x12, 0x30, 0x10, 0x06, 0x00, + 0x05, 0x01, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, + 0x02, 0x1, 0x03 }; + const byte badNotBitString[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x04, 0x09, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badBitStringLen[] = { 0x30, 0x0f, 0x30, 0x0d, 0x06, 0x00, + 0x03, 0x0a, 0x00, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badNoSeq[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, 0x03, 0x07, + 0x00, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badNoObj[] = { + 0x30, 0x0f, 0x30, 0x0d, 0x05, 0x00, 0x03, 0x09, 0x00, 0x30, 0x06, + 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badIntN[] = { 0x30, 0x06, 0x02, 0x05, 0x23, 0x02, 0x1, 0x03 }; + const byte badNotIntE[] = { 0x30, 0x06, 0x02, 0x01, 0x23, 0x04, 0x1, 0x03 }; + const byte badLength[] = { 0x30, 0x04, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + const byte badBitStrNoZero[] = { 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x00, + 0x03, 0x08, 0x30, 0x06, 0x02, 0x01, 0x23, 0x02, 0x1, 0x03 }; + + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5400; + + /* Parameter Validation testing. */ + ret = wc_RsaPublicKeyDecodeRaw(NULL, sizeof(n), e, sizeof(e), &keyPub); + if (ret != BAD_FUNC_ARG) { + ret = -5401; + goto done; + } + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), NULL, sizeof(e), &keyPub); + if (ret != BAD_FUNC_ARG) { + ret = -5402; + goto done; + } + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), NULL); + if (ret != BAD_FUNC_ARG) { + ret = -5403; + goto done; + } + /* TODO: probably should fail when length is -1! */ + ret = wc_RsaPublicKeyDecodeRaw(n, -1, e, sizeof(e), &keyPub); + if (ret != 0) { + ret = -5404; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5405; + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, -1, &keyPub); + if (ret != 0) { + ret = -5406; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5407; + + /* Use API. */ + ret = wc_RsaPublicKeyDecodeRaw(n, sizeof(n), e, sizeof(e), &keyPub); + if (ret != 0) { + ret = -5408; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5409; + + /* Parameter Validation testing. */ + inSz = sizeof(good); + ret = wc_RsaPublicKeyDecode(NULL, &inOutIdx, &keyPub, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -5410; + goto done; + } + ret = wc_RsaPublicKeyDecode(good, NULL, &keyPub, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -5411; + goto done; + } + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, NULL, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -5412; + goto done; + } + + /* Use good data and offest to bad data. */ + inOutIdx = 2; + inSz = sizeof(good) - inOutIdx; + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5413; + goto done; + } + inOutIdx = 2; + inSz = sizeof(goodAlgId) - inOutIdx; + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5414; + goto done; + } + /* Try different bad data. */ + inSz = sizeof(badAlgIdNull); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badAlgIdNull, &inOutIdx, &keyPub, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -5415; + goto done; + } + inSz = sizeof(badNotBitString); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNotBitString, &inOutIdx, &keyPub, inSz); + if (ret != ASN_BITSTR_E) { + ret = -5416; + goto done; + } + inSz = sizeof(badBitStringLen); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badBitStringLen, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5417; + goto done; + } + inSz = sizeof(badNoSeq); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNoSeq, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5418; + goto done; + } + inSz = sizeof(badNoObj); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNoObj, &inOutIdx, &keyPub, inSz); + if (ret != ASN_PARSE_E) { + ret = -5419; + goto done; + } + inSz = sizeof(badIntN); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badIntN, &inOutIdx, &keyPub, inSz); + if (ret != ASN_RSA_KEY_E) { + ret = -5420; + goto done; + } + inSz = sizeof(badNotIntE); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badNotIntE, &inOutIdx, &keyPub, inSz); + if (ret != ASN_RSA_KEY_E) { + ret = -5421; + goto done; + } + /* TODO: Shouldn't pass as the sequence length is too small. */ + inSz = sizeof(badLength); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badLength, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5422; + goto done; + } + /* TODO: Shouldn't ignore object id's data. */ + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5423; + + /* Valid data cases. */ + inSz = sizeof(good); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(good, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5424; + goto done; + } + if (inOutIdx != inSz) { + ret = -5425; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5426; + + inSz = sizeof(goodAlgId); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(goodAlgId, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5427; + goto done; + } + if (inOutIdx != inSz) { + ret = -5428; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5429; + + inSz = sizeof(goodAlgIdNull); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(goodAlgIdNull, &inOutIdx, &keyPub, inSz); + if (ret != 0) { + ret = -5430; + goto done; + } + if (inOutIdx != inSz) { + ret = -5431; + goto done; + } + wc_FreeRsaKey(&keyPub); + ret = wc_InitRsaKey(&keyPub, NULL); + if (ret != 0) + return -5432; + + inSz = sizeof(badBitStrNoZero); + inOutIdx = 0; + ret = wc_RsaPublicKeyDecode(badBitStrNoZero, &inOutIdx, &keyPub, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -5433; + goto done; + } + ret = 0; +done: + wc_FreeRsaKey(&keyPub); + return ret; +} +#endif + +#define RSA_TEST_BYTES 256 int rsa_test(void) { - byte* tmp; + int ret; + byte* tmp = NULL; + byte* der = NULL; + byte* pem = NULL; size_t bytes; + WC_RNG rng; RsaKey key; #ifdef WOLFSSL_CERT_EXT RsaKey keypub; #endif - WC_RNG rng; +#ifdef WOLFSSL_KEY_GEN + RsaKey genKey; +#endif +#if defined(WOLFSSL_CERT_GEN) || defined(HAVE_NTRU) + RsaKey caKey; +#endif +#ifdef HAVE_ECC + #ifdef WOLFSSL_CERT_GEN + ecc_key caEccKey; + #ifdef WOLFSSL_CERT_EXT + ecc_key caEccKeyPub; + #endif + #endif +#endif /* HAVE_ECC */ word32 idx = 0; - int ret; - byte in[] = "Everyone gets Friday off."; - word32 inLen = (word32)XSTRLEN((char*)in); - byte out[256]; - byte plain[256]; -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + byte* res; + const char* inStr = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)inStr); + const word32 outSz = RSA_TEST_BYTES; + const word32 plainSz = RSA_TEST_BYTES; +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) \ + && !defined(NO_FILESYSTEM) FILE *file, *file2; #endif #ifdef WOLFSSL_TEST_CERT DecodedCert cert; #endif + DECLARE_VAR_INIT(in, byte, inLen, inStr, HEAP_HINT); + DECLARE_VAR(out, byte, RSA_TEST_BYTES, HEAP_HINT); + DECLARE_VAR(plain, byte, RSA_TEST_BYTES, HEAP_HINT); + + /* initialize stack structures */ + XMEMSET(&rng, 0, sizeof(rng)); + XMEMSET(&key, 0, sizeof(key)); +#ifdef WOLFSSL_CERT_EXT + XMEMSET(&keypub, 0, sizeof(keypub)); +#endif +#ifdef WOLFSSL_KEY_GEN + XMEMSET(&genKey, 0, sizeof(genKey)); +#endif +#if defined(WOLFSSL_CERT_GEN) || defined(HAVE_NTRU) + XMEMSET(&caKey, 0, sizeof(caKey)); +#endif +#ifdef HAVE_ECC + #ifdef WOLFSSL_CERT_GEN + XMEMSET(&caEccKey, 0, sizeof(caEccKey)); + #ifdef WOLFSSL_CERT_EXT + XMEMSET(&caEccKeyPub, 0, sizeof(caEccKeyPub)); + #endif + #endif +#endif /* HAVE_ECC */ + +#ifndef HAVE_USER_RSA + ret = rsa_decode_test(); + if (ret != 0) + return ret; +#endif + tmp = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) - return -40; + if (tmp == NULL + #ifdef WOLFSSL_ASYNC_CRYPT + || out == NULL || plain == NULL + #endif + ) { + return -5500; + } #ifdef USE_CERT_BUFFERS_1024 XMEMCPY(tmp, client_key_der_1024, sizeof_client_key_der_1024); @@ -4747,47 +6301,53 @@ int rsa_test(void) #elif defined(USE_CERT_BUFFERS_2048) XMEMCPY(tmp, client_key_der_2048, sizeof_client_key_der_2048); bytes = sizeof_client_key_der_2048; -#else +#elif !defined(NO_FILESYSTEM) file = fopen(clientKey, "rb"); - if (!file) { err_sys("can't open ./certs/client-key.der, " "Please run from wolfSSL home dir", -40); - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -40; + ERROR_OUT(-5501, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, file); fclose(file); +#else + /* No key to use. */ + ERROR_OUT(-5502, exit_rsa); #endif /* USE_CERT_BUFFERS */ ret = wc_InitRsaKey_ex(&key, HEAP_HINT, devId); if (ret != 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -39; + ERROR_OUT(-5503, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx, &key, (word32)bytes); if (ret != 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -41; + ERROR_OUT(-5504, exit_rsa); } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -42; + ERROR_OUT(-5505, exit_rsa); } + ret = rsa_sig_test(&key, sizeof(RsaKey), wc_RsaEncryptSize(&key), &rng); + if (ret != 0) + goto exit_rsa; + do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt(in, inLen, out, sizeof(out), &key, &rng); + ret = wc_RsaPublicEncrypt(in, inLen, out, outSz, &key, &rng); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -43; + ERROR_OUT(-5506, exit_rsa); } #ifdef WC_RSA_BLINDING @@ -4795,8 +6355,7 @@ int rsa_test(void) int tmpret = ret; ret = wc_RsaSetRNG(&key, &rng); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -843; + ERROR_OUT(-5507, exit_rsa); } ret = tmpret; } @@ -4805,53 +6364,65 @@ int rsa_test(void) idx = ret; /* save off encrypted length */ do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt(out, idx, plain, sizeof(plain), &key); + ret = wc_RsaPrivateDecrypt(out, idx, plain, plainSz, &key); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -44; + ERROR_OUT(-5508, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -45; + ERROR_OUT(-5509, exit_rsa); + } + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecryptInline(out, idx, &res, &key); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5510, exit_rsa); + } + if (ret != (int)inLen) { + ERROR_OUT(-5511, exit_rsa); + } + if (XMEMCMP(res, in, inLen)) { + ERROR_OUT(-5512, exit_rsa); } do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaSSL_Sign(in, inLen, out, sizeof(out), &key, &rng); + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, &key, &rng); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -46; + ERROR_OUT(-5513, exit_rsa); } idx = ret; - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaSSL_Verify(out, idx, plain, sizeof(plain), &key); + ret = wc_RsaSSL_Verify(out, idx, plain, plainSz, &key); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); - return -47; + ERROR_OUT(-5514, exit_rsa); } if (XMEMCMP(plain, in, ret)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -48; + ERROR_OUT(-5515, exit_rsa); } #ifndef WC_NO_RSA_OAEP @@ -4859,179 +6430,191 @@ int rsa_test(void) #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ !defined(HAVE_FIPS) #ifndef NO_SHA - XMEMSET(plain, 0, sizeof(plain)); - + XMEMSET(plain, 0, plainSz); + do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -143; + ERROR_OUT(-5516, exit_rsa); } idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -144; + ERROR_OUT(-5517, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -145; + ERROR_OUT(-5518, exit_rsa); } #endif /* NO_SHA */ #ifndef NO_SHA256 - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -243; + ERROR_OUT(-5519, exit_rsa); } idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -244; + ERROR_OUT(-5520, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -245; + ERROR_OUT(-5521, exit_rsa); + } + + do { +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif + if (ret >= 0) { + ret = wc_RsaPrivateDecryptInline_ex(out, idx, &res, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5522, exit_rsa); + } + if (ret != (int)inLen) { + ERROR_OUT(-5523, exit_rsa); + } + if (XMEMCMP(res, in, inLen)) { + ERROR_OUT(-5524, exit_rsa); } /* check fails if not using the same optional label */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -246; + ERROR_OUT(-5525, exit_rsa); } +/* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ +#ifndef HAVE_CAVIUM idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #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)); + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret > 0) { /* in this case decrypt should fail */ - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -247; + ERROR_OUT(-5526, exit_rsa); } ret = 0; +#endif /* !HAVE_CAVIUM */ /* check using optional label with encrypt/decrypt */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #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)); + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -248; + ERROR_OUT(-5527, exit_rsa); } idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #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)); + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -249; + ERROR_OUT(-5528, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -250; + ERROR_OUT(-5529, exit_rsa); } #ifndef NO_SHA /* check fail using mismatch hash algorithms */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #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)); + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, in, inLen); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -251; + ERROR_OUT(-5530, exit_rsa); } +/* TODO: investigate why Cavium Nitrox doesn't detect decrypt error here */ +#ifndef HAVE_CAVIUM idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #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)); + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, WC_MGF1SHA256, in, inLen); } } while (ret == WC_PENDING_E); if (ret > 0) { /* should fail */ - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -252; + ERROR_OUT(-5531, exit_rsa); } ret = 0; +#endif /* !HAVE_CAVIUM */ #endif /* NO_SHA*/ #endif /* NO_SHA256 */ @@ -5041,81 +6624,79 @@ int rsa_test(void) and test, since OAEP padding requires this. 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)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -343; + ERROR_OUT(-5532, exit_rsa); } idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA512, WC_MGF1SHA512, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -344; + ERROR_OUT(-5533, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -345; + ERROR_OUT(-5534, exit_rsa); } } #endif /* WOLFSSL_SHA512 */ /* check using pkcsv15 padding with _ex API */ - XMEMSET(plain, 0, sizeof(plain)); + XMEMSET(plain, 0, plainSz); do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPublicEncrypt_ex(in, inLen, out, sizeof(out), &key, &rng, + ret = wc_RsaPublicEncrypt_ex(in, inLen, out, outSz, &key, &rng, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -443; + ERROR_OUT(-5535, exit_rsa); } idx = ret; do { #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, &key); + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, sizeof(plain), &key, + ret = wc_RsaPrivateDecrypt_ex(out, idx, plain, plainSz, &key, WC_RSA_PKCSV15_PAD, WC_HASH_TYPE_NONE, 0, NULL, 0); } } while (ret == WC_PENDING_E); if (ret < 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -444; + ERROR_OUT(-5536, exit_rsa); } if (XMEMCMP(plain, in, inLen)) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -445; + ERROR_OUT(-5537, exit_rsa); } #endif /* !HAVE_FAST_RSA && !HAVE_FIPS */ #endif /* WC_NO_RSA_OAEP */ + ret = rsa_flatten_test(&key); + if (ret != 0) + return ret; + #if defined(WOLFSSL_MDK_ARM) #define sizeof(s) XSTRLEN((char *)(s)) #endif @@ -5126,15 +6707,17 @@ int rsa_test(void) #elif defined(USE_CERT_BUFFERS_2048) XMEMCPY(tmp, client_cert_der_2048, sizeof_client_cert_der_2048); bytes = sizeof_client_cert_der_2048; -#else +#elif !defined(NO_FILESYSTEM) file2 = fopen(clientCert, "rb"); if (!file2) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -49; + ERROR_OUT(-5538, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, file2); fclose(file2); +#else + /* No certificate to use. */ + ERROR_OUT(-5539, exit_rsa); #endif #ifdef sizeof @@ -5146,8 +6729,8 @@ int rsa_test(void) ret = ParseCert(&cert, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - free(tmp); - return -491; + FreeDecodedCert(&cert); + ERROR_OUT(-5540, exit_rsa); } FreeDecodedCert(&cert); @@ -5168,8 +6751,7 @@ int rsa_test(void) if (!file) { err_sys("can't open ./certs/client-keyPub.der, " "Please run from wolfSSL home dir", -40); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -50; + ERROR_OUT(-5541, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, file); @@ -5178,139 +6760,93 @@ int rsa_test(void) ret = wc_InitRsaKey(&keypub, HEAP_HINT); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -51; + ERROR_OUT(-5542, exit_rsa); } idx = 0; ret = wc_RsaPublicKeyDecode(tmp, &idx, &keypub, (word32)bytes); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&keypub); - return -52; + ERROR_OUT(-5543, exit_rsa); } #endif /* WOLFSSL_CERT_EXT */ #ifdef WOLFSSL_KEY_GEN { - byte* der; - byte* pem; int derSz = 0; int pemSz = 0; - RsaKey derIn; - RsaKey genKey; + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* keyFile; FILE* pemFile; + #endif ret = wc_InitRsaKey(&genKey, HEAP_HINT); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -300; + ERROR_OUT(-5550, exit_rsa); } ret = wc_MakeRsaKey(&genKey, 1024, 65537, &rng); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -301; + ERROR_OUT(-5551, exit_rsa); } der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -307; + ERROR_OUT(-5552, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -308; + ERROR_OUT(-5553, exit_rsa); } derSz = wc_RsaKeyToDer(&genKey, der, FOURK_BUF); if (derSz < 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -302; + ERROR_OUT(-5554, exit_rsa); } -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\key.der", "wb"); -#else - keyFile = fopen("./key.der", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + keyFile = fopen(keyDerFile, "wb"); if (!keyFile) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -303; + ERROR_OUT(-5555, exit_rsa); } ret = (int)fwrite(der, 1, derSz, keyFile); fclose(keyFile); if (ret != derSz) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -313; + ERROR_OUT(-5556, exit_rsa); } + #endif pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, PRIVATEKEY_TYPE); if (pemSz < 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -304; + ERROR_OUT(-5557, exit_rsa); } -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\key.pem", "wb"); -#else - pemFile = fopen("./key.pem", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(keyPemFile, "wb"); if (!pemFile) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -305; + ERROR_OUT(-5558, exit_rsa); } ret = (int)fwrite(pem, 1, pemSz, pemFile); fclose(pemFile); if (ret != pemSz) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -314; + ERROR_OUT(-5559, exit_rsa); } + #endif - ret = wc_InitRsaKey(&derIn, HEAP_HINT); + wc_FreeRsaKey(&genKey); + ret = wc_InitRsaKey(&genKey, HEAP_HINT); if (ret != 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&genKey); - return -3060; + ERROR_OUT(-5560, exit_rsa); } idx = 0; - ret = wc_RsaPrivateKeyDecode(der, &idx, &derIn, derSz); + ret = wc_RsaPrivateKeyDecode(der, &idx, &genKey, derSz); if (ret != 0) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&derIn); - wc_FreeRsaKey(&genKey); - return -306; + ERROR_OUT(-5561, exit_rsa); } - wc_FreeRsaKey(&derIn); wc_FreeRsaKey(&genKey); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* WOLFSSL_KEY_GEN */ @@ -5318,27 +6854,23 @@ int rsa_test(void) /* self signed */ { Cert myCert; - byte* derCert; - byte* pem; + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* derFile; FILE* pemFile; + #endif int certSz; int pemSz; -#ifdef WOLFSSL_TEST_CERT + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif + #endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -309; + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5570, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -310; + ERROR_OUT(-5571, exit_rsa); } wc_InitCert(&myCert); @@ -5353,7 +6885,7 @@ int rsa_test(void) myCert.isCA = 1; myCert.sigType = CTC_SHA256wRSA; -#ifdef WOLFSSL_CERT_EXT + #ifdef WOLFSSL_CERT_EXT /* add Policies */ strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", CTC_MAX_CERTPOL_SZ); @@ -5363,162 +6895,135 @@ int rsa_test(void) /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -398; + ERROR_OUT(-5572, exit_rsa); } /* add AKID from the Public Key */ if (wc_SetAuthKeyIdFromPublicKey(&myCert, &keypub, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -399; + ERROR_OUT(-5573, exit_rsa); } /* add Key Usage */ if (wc_SetKeyUsage(&myCert,"cRLSign,keyCertSign") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -400; + ERROR_OUT(-5574, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ - certSz = wc_MakeSelfCert(&myCert, derCert, FOURK_BUF, &key, &rng); - if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -401; + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_MakeSelfCert(&myCert, der, FOURK_BUF, &key, &rng); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5575, exit_rsa); } + certSz = ret; -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, HEAP_HINT); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -402; + FreeDecodedCert(&decode); + ERROR_OUT(-5576, exit_rsa); } FreeDecodedCert(&decode); -#endif + #endif -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\cert.der", "wb"); -#else - derFile = fopen("./cert.der", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + derFile = fopen(certDerFile, "wb"); if (!derFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -403; + ERROR_OUT(-5577, exit_rsa); } - ret = (int)fwrite(derCert, 1, certSz, derFile); + ret = (int)fwrite(der, 1, certSz, derFile); fclose(derFile); if (ret != certSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -414; + ERROR_OUT(-5578, exit_rsa); } + #endif - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); + pemSz = wc_DerToPem(der, certSz, pem, FOURK_BUF, CERT_TYPE); if (pemSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -404; + ERROR_OUT(-5579, exit_rsa); } -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\cert.pem", "wb"); -#else - pemFile = fopen("./cert.pem", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(certPemFile, "wb"); if (!pemFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -405; + ERROR_OUT(-5580, exit_rsa); } ret = (int)fwrite(pem, 1, pemSz, pemFile); fclose(pemFile); if (ret != pemSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -406; + ERROR_OUT(-5581, exit_rsa); } + #endif + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } /* CA style */ { - RsaKey caKey; Cert myCert; - byte* derCert; - byte* pem; + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* derFile; FILE* pemFile; + #endif int certSz; int pemSz; size_t bytes3; word32 idx3 = 0; - FILE* file3 ; -#ifdef WOLFSSL_TEST_CERT + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + FILE* file3; + #endif + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif + #endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -311; + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5600, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -312; + ERROR_OUT(-5601, exit_rsa); } - file3 = fopen(caKeyFile, "rb"); - + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, ca_key_der_1024, sizeof_ca_key_der_1024); + bytes3 = sizeof_ca_key_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, ca_key_der_2048, sizeof_ca_key_der_2048); + bytes3 = sizeof_ca_key_der_2048; + #else + file3 = fopen(rsaCaKeyFile, "rb"); if (!file3) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -412; + ERROR_OUT(-5602, exit_rsa); } bytes3 = fread(tmp, 1, FOURK_BUF, file3); fclose(file3); + #endif /* USE_CERT_BUFFERS */ ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -411; + ERROR_OUT(-5603, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -413; + ERROR_OUT(-5604, exit_rsa); } wc_InitCert(&myCert); -#ifdef NO_SHA + #ifdef NO_SHA myCert.sigType = CTC_SHA256wRSA; -#endif + #endif strncpy(myCert.subject.country, "US", CTC_NAME_SIZE); strncpy(myCert.subject.state, "OR", CTC_NAME_SIZE); @@ -5528,7 +7033,7 @@ int rsa_test(void) strncpy(myCert.subject.commonName, "www.yassl.com", CTC_NAME_SIZE); strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); -#ifdef WOLFSSL_CERT_EXT + #ifdef WOLFSSL_CERT_EXT /* add Policies */ strncpy(myCert.certPolicies[0], "2.16.840.1.101.3.4.1.42", CTC_MAX_CERTPOL_SZ); @@ -5536,180 +7041,156 @@ int rsa_test(void) /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -398; + ERROR_OUT(-5605, exit_rsa); } /* add AKID from the CA certificate */ - if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -399; + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetAuthKeyId(&myCert, rsaCaCertFile); + #endif + if (ret != 0) { + ERROR_OUT(-5606, exit_rsa); } /* add Key Usage */ if (wc_SetKeyUsage(&myCert,"keyEncipherment,keyAgreement") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -400; + ERROR_OUT(-5607, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ - ret = wc_SetIssuer(&myCert, caCertFile); + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetIssuer(&myCert, rsaCaCertFile); + #endif if (ret < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -405; + ERROR_OUT(-5608, exit_rsa); } - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng); + certSz = wc_MakeCert(&myCert, der, FOURK_BUF, &key, NULL, &rng); if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -407; + ERROR_OUT(-5609, exit_rsa); } - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, FOURK_BUF, &caKey, NULL, &rng); - if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -408; + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5610, exit_rsa); } + certSz = ret; -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, HEAP_HINT); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -409; + FreeDecodedCert(&decode); + ERROR_OUT(-5611, exit_rsa); } FreeDecodedCert(&decode); -#endif + #endif -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\othercert.der", "wb"); -#else - derFile = fopen("./othercert.der", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + derFile = fopen(otherCertDerFile, "wb"); if (!derFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -410; + ERROR_OUT(-5612, exit_rsa); } - ret = (int)fwrite(derCert, 1, certSz, derFile); + ret = (int)fwrite(der, 1, certSz, derFile); fclose(derFile); if (ret != certSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -416; + ERROR_OUT(-5613, exit_rsa); } + #endif - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); + pemSz = wc_DerToPem(der, certSz, pem, FOURK_BUF, CERT_TYPE); if (pemSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -411; + ERROR_OUT(-5614, exit_rsa); } -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\othercert.pem", "wb"); -#else - pemFile = fopen("./othercert.pem", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(otherCertPemFile, "wb"); if (!pemFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - return -412; + ERROR_OUT(-5615, exit_rsa); } ret = (int)fwrite(pem, 1, pemSz, pemFile); if (ret != pemSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); fclose(pemFile); - wc_FreeRsaKey(&caKey); - return -415; + ERROR_OUT(-5616, exit_rsa); } fclose(pemFile); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + wc_FreeRsaKey(&caKey); + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #ifdef HAVE_ECC /* ECC CA style */ { - ecc_key caKey; Cert myCert; - byte* derCert; - byte* pem; + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* derFile; FILE* pemFile; + #endif int certSz; int pemSz; size_t bytes3; word32 idx3 = 0; + #ifndef USE_CERT_BUFFERS_256 FILE* file3; -#ifdef WOLFSSL_CERT_EXT - ecc_key caKeyPub; -#endif -#ifdef WOLFSSL_TEST_CERT + #endif + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif + #endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5311; + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5620, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5312; + ERROR_OUT(-5621, exit_rsa); } + #ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ecc_key_der_256, sizeof_ecc_key_der_256); + bytes3 = sizeof_ecc_key_der_256; + #else file3 = fopen(eccCaKeyFile, "rb"); - if (!file3) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5412; + ERROR_OUT(-5622, exit_rsa); } bytes3 = fread(tmp, 1, FOURK_BUF, file3); fclose(file3); + #endif /* USE_CERT_BUFFERS_256 */ - wc_ecc_init(&caKey); - ret = wc_EccPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes3); + ret = wc_ecc_init_ex(&caEccKey, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-5623, exit_rsa); + } + ret = wc_EccPrivateKeyDecode(tmp, &idx3, &caEccKey, (word32)bytes3); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5413; + ERROR_OUT(-5624, exit_rsa); } wc_InitCert(&myCert); @@ -5731,190 +7212,147 @@ int rsa_test(void) CTC_MAX_CERTPOL_SZ); myCert.certPoliciesNb = 2; - + #ifdef USE_CERT_BUFFERS_256 + XMEMCPY(tmp, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256); + bytes3 = sizeof_ecc_key_pub_der_256; + #else file3 = fopen(eccCaKeyPubFile, "rb"); if (!file3) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5500; + ERROR_OUT(-5625, exit_rsa); } bytes3 = fread(tmp, 1, FOURK_BUF, file3); fclose(file3); + #endif - wc_ecc_init(&caKeyPub); + ret = wc_ecc_init_ex(&caEccKeyPub, HEAP_HINT, devId); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5501; + ERROR_OUT(-5626, exit_rsa); } idx3 = 0; - ret = wc_EccPublicKeyDecode(tmp, &idx3, &caKeyPub, (word32)bytes3); + ret = wc_EccPublicKeyDecode(tmp, &idx3, &caEccKeyPub, (word32)bytes3); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKeyPub); - return -5502; + ERROR_OUT(-5627, exit_rsa); } /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&myCert, &key, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKeyPub); - return -5503; + ERROR_OUT(-5628, exit_rsa); } /* add AKID from the Public Key */ - if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caKeyPub) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKeyPub); - return -5504; + if (wc_SetAuthKeyIdFromPublicKey(&myCert, NULL, &caEccKeyPub) != 0) { + ERROR_OUT(-5629, exit_rsa); } - wc_ecc_free(&caKeyPub); + wc_ecc_free(&caEccKeyPub); /* add Key Usage */ if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5505; + ERROR_OUT(-5630, exit_rsa); } #endif /* WOLFSSL_CERT_EXT */ + #if defined(USE_CERT_BUFFERS_256) + ret = wc_SetIssuerBuffer(&myCert, serv_ecc_der_256, + sizeof_serv_ecc_der_256); + #else ret = wc_SetIssuer(&myCert, eccCaCertFile); + #endif if (ret < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5405; + ERROR_OUT(-5631, exit_rsa); } - certSz = wc_MakeCert(&myCert, derCert, FOURK_BUF, &key, NULL, &rng); + certSz = wc_MakeCert(&myCert, der, FOURK_BUF, &key, NULL, &rng); if (certSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5407; + ERROR_OUT(-5632, exit_rsa); } - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, - NULL, &caKey, &rng); - if (certSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5408; + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caEccKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, + FOURK_BUF, NULL, &caEccKey, &rng); + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5633, exit_rsa); } + certSz = ret; -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, 0); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, 0); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - return -5409; + FreeDecodedCert(&decode); + ERROR_OUT(-5634, exit_rsa); + } FreeDecodedCert(&decode); -#endif + #endif -#ifdef FREESCALE_MQX - derFile = fopen("a:\\certs\\certecc.der", "wb"); -#else - derFile = fopen("./certecc.der", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + derFile = fopen(certEccDerFile, "wb"); if (!derFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5410; + ERROR_OUT(-5635, exit_rsa); } - ret = (int)fwrite(derCert, 1, certSz, derFile); + ret = (int)fwrite(der, 1, certSz, derFile); fclose(derFile); if (ret != certSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5414; + ERROR_OUT(-5636, exit_rsa); } + #endif - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); + pemSz = wc_DerToPem(der, certSz, pem, FOURK_BUF, CERT_TYPE); if (pemSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5411; + ERROR_OUT(-5637, exit_rsa); } -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\certecc.pem", "wb"); -#else - pemFile = fopen("./certecc.pem", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(certEccPemFile, "wb"); if (!pemFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5412; + ERROR_OUT(-5638, exit_rsa); } ret = (int)fwrite(pem, 1, pemSz, pemFile); if (ret != pemSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -5415; + fclose(pemFile); + ERROR_OUT(-5639, exit_rsa); } - fclose(pemFile); + #endif + + wc_ecc_free(&caEccKey); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_ecc_free(&caKey); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* HAVE_ECC */ #ifdef HAVE_NTRU { - RsaKey caKey; Cert myCert; - byte* derCert; - byte* pem; FILE* derFile; FILE* pemFile; + #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) FILE* caFile; + #endif FILE* ntruPrivFile; int certSz; int pemSz; word32 idx3 = 0; -#ifdef WOLFSSL_TEST_CERT + #ifdef WOLFSSL_TEST_CERT DecodedCert decode; -#endif - derCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, - DYNAMIC_TYPE_TMP_BUFFER); - if (derCert == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -311; + #endif + der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + ERROR_OUT(-5650, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -312; + ERROR_OUT(-5651, exit_rsa); } byte public_key[557]; /* sized for EES401EP2 */ @@ -5928,66 +7366,51 @@ int rsa_test(void) word32 rc = ntru_crypto_drbg_instantiate(112, pers_str, sizeof(pers_str), GetEntropy, &drbg); if (rc != DRBG_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -448; + ERROR_OUT(-5652, exit_rsa); } rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, NULL, &private_key_len, NULL); if (rc != NTRU_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -449; + ERROR_OUT(-5653, exit_rsa); } rc = ntru_crypto_ntru_encrypt_keygen(drbg, NTRU_EES401EP2, &public_key_len, public_key, &private_key_len, private_key); if (rc != NTRU_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -450; + ERROR_OUT(-5654, exit_rsa); } rc = ntru_crypto_drbg_uninstantiate(drbg); - if (rc != NTRU_OK) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -451; + ERROR_OUT(-5655, exit_rsa); } - caFile = fopen(caKeyFile, "rb"); - + #ifdef USE_CERT_BUFFERS_1024 + XMEMCPY(tmp, ca_key_der_1024, sizeof_ca_key_der_1024); + bytes = sizeof_ca_key_der_1024; + #elif defined(USE_CERT_BUFFERS_2048) + XMEMCPY(tmp, ca_key_der_2048, sizeof_ca_key_der_2048); + bytes = sizeof_ca_key_der_2048; + #else + caFile = fopen(rsaCaKeyFile, "rb"); if (!caFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -452; + ERROR_OUT(-5656, exit_rsa); } bytes = fread(tmp, 1, FOURK_BUF, caFile); fclose(caFile); + #endif /* USE_CERT_BUFFERS */ ret = wc_InitRsaKey(&caKey, HEAP_HINT); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -453; + ERROR_OUT(-5657, exit_rsa); } ret = wc_RsaPrivateKeyDecode(tmp, &idx3, &caKey, (word32)bytes); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -454; + ERROR_OUT(-5658, exit_rsa); } wc_InitCert(&myCert); @@ -6001,154 +7424,140 @@ int rsa_test(void) strncpy(myCert.subject.email, "info@yassl.com", CTC_NAME_SIZE); myCert.daysValid = 1000; -#ifdef WOLFSSL_CERT_EXT - + #ifdef WOLFSSL_CERT_EXT /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromNtruPublicKey(&myCert, public_key, public_key_len) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -496; + ERROR_OUT(-5659, exit_rsa); } /* add AKID from the CA certificate */ - if (wc_SetAuthKeyId(&myCert, caCertFile) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -495; + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetAuthKeyIdFromCert(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetAuthKeyId(&myCert, rsaCaCertFile); + #endif + if (ret != 0) { + ERROR_OUT(-5660, exit_rsa); } /* add Key Usage */ if (wc_SetKeyUsage(&myCert,"digitalSignature,nonRepudiation," "keyEncipherment,keyAgreement") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -494; + ERROR_OUT(-5661, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ - ret = wc_SetIssuer(&myCert, caCertFile); + #if defined(USE_CERT_BUFFERS_2048) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_2048, + sizeof_ca_cert_der_2048); + #elif defined(USE_CERT_BUFFERS_1024) + ret = wc_SetIssuerBuffer(&myCert, ca_cert_der_1024, + sizeof_ca_cert_der_1024); + #else + ret = wc_SetIssuer(&myCert, rsaCaCertFile); + #endif if (ret < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -455; + ERROR_OUT(-5662, exit_rsa); } - certSz = wc_MakeNtruCert(&myCert, derCert, FOURK_BUF, public_key, + certSz = wc_MakeNtruCert(&myCert, der, FOURK_BUF, public_key, public_key_len, &rng); if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRsaKey(&caKey); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -456; + ERROR_OUT(-5663, exit_rsa); } - certSz = wc_SignCert(myCert.bodySz, myCert.sigType, derCert, FOURK_BUF, + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &caKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(myCert.bodySz, myCert.sigType, der, FOURK_BUF, &caKey, NULL, &rng); + } + } while (ret == WC_PENDING_E); wc_FreeRsaKey(&caKey); - if (certSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -457; + if (ret < 0) { + ERROR_OUT(-5664, exit_rsa); } + certSz = ret; - -#ifdef WOLFSSL_TEST_CERT - InitDecodedCert(&decode, derCert, certSz, HEAP_HINT); + #ifdef WOLFSSL_TEST_CERT + InitDecodedCert(&decode, der, certSz, HEAP_HINT); ret = ParseCert(&decode, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -458; + FreeDecodedCert(&decode); + ERROR_OUT(-5665, exit_rsa); } FreeDecodedCert(&decode); -#endif + #endif + + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) derFile = fopen("./ntru-cert.der", "wb"); if (!derFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -459; + ERROR_OUT(-5666, exit_rsa); } - ret = (int)fwrite(derCert, 1, certSz, derFile); + ret = (int)fwrite(der, 1, certSz, derFile); fclose(derFile); if (ret != certSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -473; + ERROR_OUT(-5667, exit_rsa); } + #endif - pemSz = wc_DerToPem(derCert, certSz, pem, FOURK_BUF, CERT_TYPE); + pemSz = wc_DerToPem(der, certSz, pem, FOURK_BUF, CERT_TYPE); if (pemSz < 0) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -460; + ERROR_OUT(-5668, exit_rsa); } + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) pemFile = fopen("./ntru-cert.pem", "wb"); if (!pemFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -461; + ERROR_OUT(-5669, exit_rsa); } ret = (int)fwrite(pem, 1, pemSz, pemFile); fclose(pemFile); if (ret != pemSz) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -474; + ERROR_OUT(-5670, exit_rsa); } ntruPrivFile = fopen("./ntru-key.raw", "wb"); if (!ntruPrivFile) { - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -462; + ERROR_OUT(-5671, exit_rsa); } ret = (int)fwrite(private_key, 1, private_key_len, ntruPrivFile); fclose(ntruPrivFile); if (ret != private_key_len) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -475; + ERROR_OUT(-5672, exit_rsa); } + #endif + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(derCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* HAVE_NTRU */ #ifdef WOLFSSL_CERT_REQ { Cert req; - byte* der; - byte* pem; int derSz; int pemSz; + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* reqFile; + #endif der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -463; + ERROR_OUT(-5680, exit_rsa); } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -464; + ERROR_OUT(-5681, exit_rsa); } wc_InitCert(&req); @@ -6165,108 +7574,110 @@ int rsa_test(void) strncpy(req.subject.email, "info@yassl.com", CTC_NAME_SIZE); req.sigType = CTC_SHA256wRSA; -#ifdef WOLFSSL_CERT_EXT + #ifdef WOLFSSL_CERT_EXT /* add SKID from the Public Key */ if (wc_SetSubjectKeyIdFromPublicKey(&req, &keypub, NULL) != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -496; + ERROR_OUT(-5682, exit_rsa); } /* add Key Usage */ if (wc_SetKeyUsage(&req,"digitalSignature,nonRepudiation," "keyEncipherment,keyAgreement") != 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -494; + ERROR_OUT(-5683, exit_rsa); } -#endif /* WOLFSSL_CERT_EXT */ + #endif /* WOLFSSL_CERT_EXT */ derSz = wc_MakeCertReq(&req, der, FOURK_BUF, &key, NULL); if (derSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -465; + ERROR_OUT(-5684, exit_rsa); } - derSz = wc_SignCert(req.bodySz, req.sigType, der, FOURK_BUF, + ret = 0; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_SignCert(req.bodySz, req.sigType, der, FOURK_BUF, &key, NULL, &rng); - if (derSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -466; + } + } while (ret == WC_PENDING_E); + if (ret < 0) { + ERROR_OUT(-5685, exit_rsa); } + derSz = ret; pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, CERTREQ_TYPE); if (pemSz < 0) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -467; + ERROR_OUT(-5686, exit_rsa); } -#ifdef FREESCALE_MQX - reqFile = fopen("a:\\certs\\certreq.der", "wb"); -#else - reqFile = fopen("./certreq.der", "wb"); -#endif + #if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + reqFile = fopen(certReqDerFile, "wb"); if (!reqFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -468; + ERROR_OUT(-5687, exit_rsa); } ret = (int)fwrite(der, 1, derSz, reqFile); fclose(reqFile); if (ret != derSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -471; + ERROR_OUT(-5688, exit_rsa); } -#ifdef FREESCALE_MQX - reqFile = fopen("a:\\certs\\certreq.pem", "wb"); -#else - reqFile = fopen("./certreq.pem", "wb"); -#endif + reqFile = fopen(certReqPemFile, "wb"); if (!reqFile) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -469; + ERROR_OUT(-5689, exit_rsa); } ret = (int)fwrite(pem, 1, pemSz, reqFile); fclose(reqFile); if (ret != pemSz) { - XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -470; + ERROR_OUT(-5690, exit_rsa); } + #endif XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + pem = NULL; XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; } #endif /* WOLFSSL_CERT_REQ */ #endif /* WOLFSSL_CERT_GEN */ +exit_rsa: wc_FreeRsaKey(&key); #ifdef WOLFSSL_CERT_EXT wc_FreeRsaKey(&keypub); #endif -#ifdef HAVE_CAVIUM - wc_RsaFreeCavium(&key); +#ifdef WOLFSSL_KEY_GEN + wc_FreeRsaKey(&genKey); +#endif +#ifdef WOLFSSL_CERT_GEN + wc_FreeRsaKey(&caKey); + #ifdef HAVE_ECC + wc_ecc_free(&caEccKey); + #ifdef WOLFSSL_CERT_EXT + wc_ecc_free(&caEccKeyPub); + #endif + #endif #endif + + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(tmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeRng(&rng); - return 0; + FREE_VAR(in, HEAP_HINT); + FREE_VAR(out, HEAP_HINT); + FREE_VAR(plain, HEAP_HINT); + + /* ret can be greater then 0 with certgen but all negative values should + * be returned and treated as an error */ + if (ret >= 0) { + return 0; + } + else { + return ret; + } } #endif @@ -6274,15 +7685,64 @@ int rsa_test(void) #ifndef NO_DH -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #ifdef FREESCALE_MQX - static const char* dhKey = "a:\\certs\\dh2048.der"; - #elif defined(NO_ASN) - /* don't use file, no DER parsing */ - #else - static const char* dhKey = "./certs/dh2048.der"; - #endif +static int dh_generate_test(WC_RNG *rng) +{ + int ret = 0; + DhKey smallKey; + byte p[2] = { 0, 5 }; + byte g[2] = { 0, 2 }; +#ifdef WOLFSSL_DH_CONST + /* the table for constant DH lookup will round to the lowest byte size 21 */ + byte priv[21]; + byte pub[21]; +#else + byte priv[2]; + byte pub[2]; #endif + word32 privSz = sizeof(priv); + word32 pubSz = sizeof(pub); + + ret = wc_InitDhKey_ex(&smallKey, HEAP_HINT, devId); + if (ret != 0) + return -5700; + + /* Parameter Validation testing. */ + ret = wc_DhSetKey(NULL, p, sizeof(p), g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5701, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, NULL, sizeof(p), g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5702, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, 0, g, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5703, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), NULL, sizeof(g)); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5704, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, 0); + if (ret != BAD_FUNC_ARG) { + ERROR_OUT(-5705, exit_gen_test); + } + ret = wc_DhSetKey(&smallKey, p, sizeof(p), g, sizeof(g)); + if (ret != 0) { + ERROR_OUT(-5706, exit_gen_test); + } + + /* Use API. */ + ret = wc_DhGenerateKeyPair(&smallKey, rng, priv, &privSz, pub, &pubSz); + if (ret != 0) { + ret = -5707; + } + +exit_gen_test: + wc_FreeDhKey(&smallKey); + + return ret; +} int dh_test(void) { @@ -6308,63 +7768,108 @@ int dh_test(void) bytes = sizeof_dh_key_der_2048; #elif defined(NO_ASN) /* don't use file, no DER parsing */ -#else +#elif !defined(NO_FILESYSTEM) FILE* file = fopen(dhKey, "rb"); - if (!file) - return -50; + return -5710; bytes = (word32) fread(tmp, 1, sizeof(tmp), file); fclose(file); +#else + /* No DH key to use. */ + return -5711; #endif /* USE_CERT_BUFFERS */ (void)idx; (void)tmp; (void)bytes; - wc_InitDhKey(&key); - wc_InitDhKey(&key2); + ret = wc_InitDhKey_ex(&key, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-5712, done); + } + ret = wc_InitDhKey_ex(&key2, HEAP_HINT, devId); + if (ret != 0) { + ERROR_OUT(-5713, done); + } + #ifdef NO_ASN ret = wc_DhSetKey(&key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-5714, done); + } ret = wc_DhSetKey(&key2, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-5715, done); + } #else ret = wc_DhKeyDecode(tmp, &idx, &key, bytes); - if (ret != 0) - return -51; + if (ret != 0) { + ERROR_OUT(-5716, done); + } idx = 0; ret = wc_DhKeyDecode(tmp, &idx, &key2, bytes); - if (ret != 0) - return -52; + if (ret != 0) { + ERROR_OUT(-5717, done); + } #endif +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); - if (ret != 0) - return -53; +#endif + if (ret != 0) { + ERROR_OUT(-5718, done); + } - ret = wc_DhGenerateKeyPair(&key, &rng, priv, &privSz, pub, &pubSz); - ret += wc_DhGenerateKeyPair(&key2, &rng, priv2, &privSz2, pub2, &pubSz2); - if (ret != 0) - return -54; + ret = wc_DhGenerateKeyPair(&key, &rng, priv, &privSz, pub, &pubSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5719, done); + } - ret = wc_DhAgree(&key, agree, &agreeSz, priv, privSz, pub2, pubSz2); - ret += wc_DhAgree(&key2, agree2, &agreeSz2, priv2, privSz2, pub, pubSz); - if (ret != 0) - return -55; + ret = wc_DhGenerateKeyPair(&key2, &rng, priv2, &privSz2, pub2, &pubSz2); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key2.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5720, done); + } + + ret = wc_DhAgree(&key, agree, &agreeSz, priv, privSz, pub2, pubSz2); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5721, done); + } + + ret = wc_DhAgree(&key2, agree2, &agreeSz2, priv2, privSz2, pub, pubSz); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &key2.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0) { + ERROR_OUT(-5722, done); + } + + if (agreeSz != agreeSz2 || XMEMCMP(agree, agree2, agreeSz)) { + ERROR_OUT(-5723, done); + } + + ret = dh_generate_test(&rng); - if (XMEMCMP(agree, agree2, agreeSz)) - return -56; +done: wc_FreeDhKey(&key); wc_FreeDhKey(&key2); wc_FreeRng(&rng); - return 0; + return ret; } #endif /* NO_DH */ @@ -6372,14 +7877,6 @@ int dh_test(void) #ifndef NO_DSA -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - #ifdef FREESCALE_MQX - static const char* dsaKey = "a:\\certs\\dsa2048.der"; - #else - static const char* dsaKey = "./certs/dsa2048.der"; - #endif -#endif - int dsa_test(void) { int ret, answer; @@ -6392,7 +7889,6 @@ int dsa_test(void) byte hash[SHA_DIGEST_SIZE]; byte signature[40]; - #ifdef USE_CERT_BUFFERS_1024 XMEMCPY(tmp, dsa_key_der_1024, sizeof_dsa_key_der_1024); bytes = sizeof_dsa_key_der_1024; @@ -6401,33 +7897,39 @@ int dsa_test(void) bytes = sizeof_dsa_key_der_2048; #else FILE* file = fopen(dsaKey, "rb"); - if (!file) - return -60; + return -5800; bytes = (word32) fread(tmp, 1, sizeof(tmp), file); fclose(file); #endif /* USE_CERT_BUFFERS */ - ret = wc_InitSha(&sha); + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); if (ret != 0) - return -4002; + return -5801; wc_ShaUpdate(&sha, tmp, bytes); wc_ShaFinal(&sha, hash); + wc_ShaFree(&sha); + + ret = wc_InitDsaKey(&key); + if (ret != 0) return -5802; - wc_InitDsaKey(&key); ret = wc_DsaPrivateKeyDecode(tmp, &idx, &key, bytes); - if (ret != 0) return -61; + if (ret != 0) return -5803; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); - if (ret != 0) return -62; +#endif + if (ret != 0) return -5804; ret = wc_DsaSign(hash, signature, &key, &rng); - if (ret != 0) return -63; + if (ret != 0) return -5805; ret = wc_DsaVerify(hash, signature, &key, &answer); - if (ret != 0) return -64; - if (answer != 1) return -65; + if (ret != 0) return -5806; + if (answer != 1) return -5807; wc_FreeDsaKey(&key); @@ -6439,45 +7941,52 @@ int dsa_test(void) int pemSz = 0; DsaKey derIn; DsaKey genKey; +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* keyFile; FILE* pemFile; +#endif + + ret = wc_InitDsaKey(&genKey); + if (ret != 0) return -5808; - wc_InitDsaKey(&genKey); ret = wc_MakeDsaParameters(&rng, 1024, &genKey); - if (ret != 0) return -362; + if (ret != 0) { + wc_FreeDsaKey(&genKey); + return -5809; + } ret = wc_MakeDsaKey(&rng, &genKey); - if (ret != 0) return -363; + if (ret != 0) { + wc_FreeDsaKey(&genKey); + return -5810; + } der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (der == NULL) { wc_FreeDsaKey(&genKey); - return -364; + return -5811; } pem = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -365; + return -5812; } derSz = wc_DsaKeyToDer(&genKey, der, FOURK_BUF); if (derSz < 0) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -366; + return -5813; } -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\key.der", "wb"); -#else - keyFile = fopen("./key.der", "wb"); -#endif +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + keyFile = fopen(keyDerFile, "wb"); if (!keyFile) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -367; + return -5814; } ret = (int)fwrite(der, 1, derSz, keyFile); fclose(keyFile); @@ -6485,27 +7994,25 @@ int dsa_test(void) XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -368; + return -5815; } +#endif pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, DSA_PRIVATEKEY_TYPE); if (pemSz < 0) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -369; + return -5816; } -#ifdef FREESCALE_MQX - pemFile = fopen("a:\\certs\\key.pem", "wb"); -#else - pemFile = fopen("./key.pem", "wb"); -#endif +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(keyPemFile, "wb"); if (!pemFile) { XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -370; + return -5817; } ret = (int)fwrite(pem, 1, pemSz, pemFile); fclose(pemFile); @@ -6513,10 +8020,18 @@ int dsa_test(void) XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&genKey); - return -371; + return -5818; + } +#endif + + ret = wc_InitDsaKey(&derIn); + if (ret != 0) { + XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeDsaKey(&genKey); + return -5819; } - wc_InitDsaKey(&derIn); idx = 0; ret = wc_DsaPrivateKeyDecode(der, &idx, &derIn, derSz); if (ret != 0) { @@ -6524,7 +8039,7 @@ int dsa_test(void) XFREE(pem, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_FreeDsaKey(&derIn); wc_FreeDsaKey(&genKey); - return -373; + return -5820; } wc_FreeDsaKey(&derIn); @@ -6544,13 +8059,13 @@ int dsa_test(void) static int generate_random_salt(byte *buf, word32 size) { - int ret = -1; + int ret = -5821; WC_RNG rng; if(NULL == buf || !size) - return -1; + return -5822; - if (buf && size && wc_InitRng(&rng) == 0) { + if (buf && size && wc_InitRng_ex(&rng, HEAP_HINT, devId) == 0) { ret = wc_RNG_GenerateBlock(&rng, (byte *)buf, size); wc_FreeRng(&rng); @@ -6676,7 +8191,7 @@ int openssl_test(void) byte* p; p = (byte*)CRYPTO_malloc(10, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (p == NULL) { - return -70; + return -5900; } XMEMSET(p, 0, 10); CRYPTO_free(p, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -6698,7 +8213,7 @@ int openssl_test(void) EVP_DigestFinal(&md_ctx, hash, 0); if (XMEMCMP(hash, a.output, MD5_DIGEST_SIZE) != 0) - return -71; + return -5901; #endif /* NO_MD5 */ @@ -6719,7 +8234,7 @@ int openssl_test(void) EVP_DigestFinal(&md_ctx, hash, 0); if (XMEMCMP(hash, b.output, SHA_DIGEST_SIZE) != 0) - return -72; + return -5902; #endif /* NO_SHA */ @@ -6739,7 +8254,7 @@ int openssl_test(void) EVP_DigestFinal(&md_ctx, hash, 0); if (XMEMCMP(hash, e.output, SHA224_DIGEST_SIZE) != 0) - return -79; + return -5903; #endif /* WOLFSSL_SHA224 */ @@ -6758,7 +8273,7 @@ int openssl_test(void) EVP_DigestFinal(&md_ctx, hash, 0); if (XMEMCMP(hash, d.output, SHA256_DIGEST_SIZE) != 0) - return -78; + return -5904; #ifdef WOLFSSL_SHA384 @@ -6778,7 +8293,7 @@ int openssl_test(void) EVP_DigestFinal(&md_ctx, hash, 0); if (XMEMCMP(hash, e.output, SHA384_DIGEST_SIZE) != 0) - return -79; + return -5905; #endif /* WOLFSSL_SHA384 */ @@ -6802,14 +8317,14 @@ int openssl_test(void) EVP_DigestFinal(&md_ctx, hash, 0); if (XMEMCMP(hash, f.output, SHA512_DIGEST_SIZE) != 0) - return -80; + return -5906; #endif /* WOLFSSL_SHA512 */ #ifndef NO_MD5 if (RAND_bytes(hash, sizeof(hash)) != 1) - return -73; + return -5907; c.input = "what do ya want for nothing?"; c.output = "\x55\x78\xe8\x48\x4b\xcc\x93\x80\x93\xec\x53\xaf\x22\xd6\x14" @@ -6821,7 +8336,7 @@ int openssl_test(void) "JefeJefeJefeJefe", 16, (byte*)c.input, (int)c.inLen, hash, 0); if (XMEMCMP(hash, c.output, MD5_DIGEST_SIZE) != 0) - return -74; + return -5908; #endif /* NO_MD5 */ @@ -6861,17 +8376,17 @@ int openssl_test(void) DES_cbc_encrypt(cipher, plain, sizeof(vector), &sched, &iv, DES_DECRYPT); if (XMEMCMP(plain, vector, sizeof(vector)) != 0) - return -75; + return -5909; if (XMEMCMP(cipher, verify, sizeof(verify)) != 0) - return -76; + return -5910; /* test changing iv */ DES_ncbc_encrypt(vector, cipher, 8, &sched, &iv, DES_ENCRYPT); DES_ncbc_encrypt(vector + 8, cipher + 8, 16, &sched, &iv, DES_ENCRYPT); if (XMEMCMP(cipher, verify, sizeof(verify)) != 0) - return -77; + return -5911; } /* end des test */ @@ -6879,7 +8394,7 @@ int openssl_test(void) #ifndef NO_AES - { /* evp_cipher test */ + { /* evp_cipher test: EVP_aes_128_cbc */ EVP_CIPHER_CTX ctx; @@ -6903,32 +8418,456 @@ int openssl_test(void) EVP_CIPHER_CTX_init(&ctx); if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 1) == 0) - return -81; + return -5912; if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) - return -82; + return -5913; if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) - return -83; + return -5914; EVP_CIPHER_CTX_init(&ctx); if (EVP_CipherInit(&ctx, EVP_aes_128_cbc(), key, iv, 0) == 0) - return -84; + return -5915; if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) - return -85; + return -5916; if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) - return -86; + return -5917; + + + } /* end evp_cipher test: EVP_aes_128_cbc*/ + +#ifdef HAVE_AES_ECB + { /* evp_cipher test: EVP_aes_128_ecb*/ + EVP_CIPHER_CTX ctx; + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const byte key[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + + byte cipher[AES_BLOCK_SIZE * 4]; + byte plain [AES_BLOCK_SIZE * 4]; + + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, NULL, 1) == 0) + return -5918; + + if (EVP_Cipher(&ctx, cipher, (byte*)msg, 16) == 0) + return -5919; + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return -5920; + EVP_CIPHER_CTX_init(&ctx); + if (EVP_CipherInit(&ctx, EVP_aes_256_ecb(), (unsigned char*)key, NULL, 0) == 0) + return -5921; + + if (EVP_Cipher(&ctx, plain, cipher, 16) == 0) + return -5922; + + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return -5923; } /* end evp_cipher test */ +#endif #endif /* NO_AES */ +#define OPENSSL_TEST_ERROR (-10000) + + +#ifndef NO_AES +#ifdef WOLFSSL_AES_DIRECT + /* enable HAVE_AES_DECRYPT for AES_encrypt/decrypt */ +{ + + /* Test: AES_encrypt/decrypt/set Key */ + AES_KEY enc; +#ifdef HAVE_AES_DECRYPT + AES_KEY dec; +#endif + + const byte msg[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte verify[] = + { + 0xf3,0xee,0xd1,0xbd,0xb5,0xd2,0xa0,0x3c, + 0x06,0x4b,0x5a,0x7e,0x3d,0xb1,0x81,0xf8 + }; + + const byte key[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + byte plain[sizeof(msg)]; + byte cipher[sizeof(msg)]; + + printf("openSSL extra test\n") ; + + + AES_set_encrypt_key(key, sizeof(key)*8, &enc); + AES_set_decrypt_key(key, sizeof(key)*8, &dec); + + AES_encrypt(msg, cipher, &enc); + +#ifdef HAVE_AES_DECRYPT + AES_decrypt(cipher, plain, &dec); + if (XMEMCMP(plain, msg, AES_BLOCK_SIZE)) + return OPENSSL_TEST_ERROR-60; +#endif /* HAVE_AES_DECRYPT */ + + if (XMEMCMP(cipher, verify, AES_BLOCK_SIZE)) + return OPENSSL_TEST_ERROR-61; +} + +#endif + +/* EVP_Cipher with EVP_aes_xxx_ctr() */ +#ifdef WOLFSSL_AES_COUNTER +{ + const byte ctrKey[] = + { + 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, + 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c + }; + + const byte ctrIv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctrPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + const byte ctrCipher[] = + { + 0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26, + 0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce, + 0x98,0x06,0xf6,0x6b,0x79,0x70,0xfd,0xff, + 0x86,0x17,0x18,0x7b,0xb9,0xff,0xfd,0xff, + 0x5a,0xe4,0xdf,0x3e,0xdb,0xd5,0xd3,0x5e, + 0x5b,0x4f,0x09,0x02,0x0d,0xb0,0x3e,0xab, + 0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1, + 0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee + }; + + byte plainBuff [64]; + byte cipherBuff[64]; + + const byte oddCipher[] = + { + 0xb9,0xd7,0xcb,0x08,0xb0,0xe1,0x7b,0xa0, + 0xc2 + }; + + + /* test vector from "Recommendation for Block Cipher Modes of Operation" + * NIST Special Publication 800-38A */ + const byte ctr192Key[] = + { + 0x8e,0x73,0xb0,0xf7,0xda,0x0e,0x64,0x52, + 0xc8,0x10,0xf3,0x2b,0x80,0x90,0x79,0xe5, + 0x62,0xf8,0xea,0xd2,0x52,0x2c,0x6b,0x7b + }; + + const byte ctr192Iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctr192Plain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte ctr192Cipher[] = + { + 0x1a,0xbc,0x93,0x24,0x17,0x52,0x1c,0xa2, + 0x4f,0x2b,0x04,0x59,0xfe,0x7e,0x6e,0x0b + }; + + /* test vector from "Recommendation for Block Cipher Modes of Operation" + * NIST Special Publication 800-38A */ + const byte ctr256Key[] = + { + 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, + 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, + 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, + 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 + }; + + const byte ctr256Iv[] = + { + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, + 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff + }; + + + const byte ctr256Plain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a + }; + + const byte ctr256Cipher[] = + { + 0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5, + 0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28 + }; + + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; + EVP_CIPHER_CTX *p_en; + EVP_CIPHER_CTX *p_de; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -5924; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, AES_BLOCK_SIZE*4) == 0) + return -5925; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -5926; + + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE*4) == 0) + return -5927; + + if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) + return -5928; + if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) + return -5929; + + p_en = wolfSSL_EVP_CIPHER_CTX_new(); + if(p_en == NULL)return -5930; + p_de = wolfSSL_EVP_CIPHER_CTX_new(); + if(p_de == NULL)return -5931; + + if (EVP_CipherInit(p_en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -5932; + if (EVP_Cipher(p_en, (byte*)cipherBuff, (byte*)ctrPlain, AES_BLOCK_SIZE*4) == 0) + return -5933; + if (EVP_CipherInit(p_de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -5934; + + if (EVP_Cipher(p_de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE*4) == 0) + return -5935; + + wolfSSL_EVP_CIPHER_CTX_free(p_en); + wolfSSL_EVP_CIPHER_CTX_free(p_de); + + if (XMEMCMP(cipherBuff, ctrCipher, AES_BLOCK_SIZE*4)) + return -5936; + if (XMEMCMP(plainBuff, ctrPlain, AES_BLOCK_SIZE*4)) + return -5937; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -5938; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) + return -5939; + + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_ctr(), + (unsigned char*)ctrKey, (unsigned char*)ctrIv, 0) == 0) + return -5940; + + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) + return -5941; + + if (XMEMCMP(plainBuff, ctrPlain, 9)) + return -5942; + if (XMEMCMP(cipherBuff, ctrCipher, 9)) + return -5943; + + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctrPlain, 9) == 0) + return -5944; + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, 9) == 0) + return -5945; + + if (XMEMCMP(plainBuff, ctrPlain, 9)) + return -5946; + if (XMEMCMP(cipherBuff, oddCipher, 9)) + return -5947; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_192_ctr(), + (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) + return -5948; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr192Plain, AES_BLOCK_SIZE) == 0) + return -5949; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_192_ctr(), + (unsigned char*)ctr192Key, (unsigned char*)ctr192Iv, 0) == 0) + return -5950; + + XMEMSET(plainBuff, 0, sizeof(plainBuff)); + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE) == 0) + return -5951; + + if (XMEMCMP(plainBuff, ctr192Plain, sizeof(ctr192Plain))) + return -5952; + if (XMEMCMP(ctr192Cipher, cipherBuff, sizeof(ctr192Cipher))) + return -5953; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_256_ctr(), + (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) + return -5954; + if (EVP_Cipher(&en, (byte*)cipherBuff, (byte*)ctr256Plain, AES_BLOCK_SIZE) == 0) + return -5955; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_256_ctr(), + (unsigned char*)ctr256Key, (unsigned char*)ctr256Iv, 0) == 0) + return -5956; + + XMEMSET(plainBuff, 0, sizeof(plainBuff)); + if (EVP_Cipher(&de, (byte*)plainBuff, (byte*)cipherBuff, AES_BLOCK_SIZE) == 0) + return -5957; + + if (XMEMCMP(plainBuff, ctr256Plain, sizeof(ctr256Plain))) + return -5958; + if (XMEMCMP(ctr256Cipher, cipherBuff, sizeof(ctr256Cipher))) + return -5959; +} +#endif /* HAVE_AES_COUNTER */ + +{ + /* EVP_CipherUpdate test */ + + + const byte cbcPlain[] = + { + 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, + 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, + 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c, + 0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, + 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11, + 0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, + 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17, + 0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10 + }; + + byte key[] = "0123456789abcdef "; /* align */ + byte iv[] = "1234567890abcdef "; /* align */ + + byte cipher[AES_BLOCK_SIZE * 4]; + byte plain [AES_BLOCK_SIZE * 4]; + EVP_CIPHER_CTX en; + EVP_CIPHER_CTX de; + int outlen ; + int total = 0; + + EVP_CIPHER_CTX_init(&en); + if (EVP_CipherInit(&en, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 1) == 0) + return -5960; + if (EVP_CipherUpdate(&en, (byte*)cipher, &outlen, (byte*)cbcPlain, 9) == 0) + return -5961; + if(outlen != 0) + return -5962; + total += outlen; + + if (EVP_CipherUpdate(&en, (byte*)&cipher[total], &outlen, (byte*)&cbcPlain[9] , 9) == 0) + return -5963; + if(outlen != 16) + return -5964; + total += outlen; + + if (EVP_CipherFinal(&en, (byte*)&cipher[total], &outlen) == 0) + return -5965; + if(outlen != 16) + return -5966; + total += outlen; + if(total != 32) + return -5967; + + total = 0; + EVP_CIPHER_CTX_init(&de); + if (EVP_CipherInit(&de, EVP_aes_128_cbc(), + (unsigned char*)key, (unsigned char*)iv, 0) == 0) + return -5968; + + if (EVP_CipherUpdate(&de, (byte*)plain, &outlen, (byte*)cipher, 6) == 0) + return -5969; + if(outlen != 0) + return -5970; + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, (byte*)&cipher[6], 12) == 0) + return -5971; + if(outlen != 0) + total += outlen; + + if (EVP_CipherUpdate(&de, (byte*)&plain[total], &outlen, (byte*)&cipher[6+12], 14) == 0) + return -5972; + if(outlen != 16) + return -5973; + total += outlen; + + if (EVP_CipherFinal(&de, (byte*)&plain[total], &outlen) == 0) + return -5974; + if(outlen != 2) + return -5975; + total += outlen; + + if(total != 18) + return -5976; + + if (XMEMCMP(plain, cbcPlain, 18)) + return -5977; + + } +#endif /* ifndef NO_AES */ + return 0; } + #endif /* OPENSSL_EXTRA */ @@ -6988,31 +8927,31 @@ int scrypt_test(void) ret = wc_scrypt(derived, NULL, 0, NULL, 0, 4, 1, 1, sizeof(verify1)); if (ret != 0) - return -108; + return -6000; if (XMEMCMP(derived, verify1, sizeof(verify1)) != 0) - return -109; + return -6001; ret = wc_scrypt(derived, (byte*)"password", 8, (byte*)"NaCl", 4, 10, 8, 16, sizeof(verify2)); if (ret != 0) - return -110; + return -6002; if (XMEMCMP(derived, verify2, sizeof(verify2)) != 0) - return -111; + return -6003; ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(verify3)); if (ret != 0) - return -112; + return -6004; if (XMEMCMP(derived, verify3, sizeof(verify3)) != 0) - return -113; + return -6005; #ifdef SCRYPT_TEST_ALL ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, (byte*)"SodiumChloride", 14, 20, 8, 1, sizeof(verify4)); if (ret != 0) - return -114; + return -6006; if (XMEMCMP(derived, verify4, sizeof(verify4)) != 0) - return -115; + return -6007; #endif return 0; @@ -7049,24 +8988,24 @@ int pkcs12_test(void) iterations, kLen, SHA256, id); if (ret < 0) - return -103; + return -6100; if ( (ret = XMEMCMP(derived, verify, kLen)) != 0) - return -104; + return -6101; iterations = 1000; ret = wc_PKCS12_PBKDF(derived, passwd2, sizeof(passwd2), salt2, 8, iterations, kLen, SHA256, id); if (ret < 0) - return -105; + return -6102; ret = wc_PKCS12_PBKDF_ex(derived, passwd2, sizeof(passwd2), salt2, 8, iterations, kLen, SHA256, id, HEAP_HINT); if (ret < 0) - return -106; + return -6103; if ( (ret = XMEMCMP(derived, verify2, 24)) != 0) - return -107; + return -6104; return 0; } @@ -7091,9 +9030,10 @@ int pbkdf2_test(void) return ret; if (XMEMCMP(derived, verify, sizeof(verify)) != 0) - return -102; + return -6200; return 0; + } @@ -7115,7 +9055,7 @@ int pbkdf1_test(void) kLen, SHA); if (XMEMCMP(derived, verify, sizeof(verify)) != 0) - return -101; + return -6300; return 0; } @@ -7188,38 +9128,38 @@ int hkdf_test(void) #ifndef NO_SHA ret = wc_HKDF(SHA, ikm1, 22, NULL, 0, NULL, 0, okm1, L); if (ret != 0) - return -2001; + return -6400; if (XMEMCMP(okm1, res1, L) != 0) - return -2002; + return -6401; #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ ret = wc_HKDF(SHA, ikm1, 11, salt1, 13, info1, 10, okm1, L); if (ret != 0) - return -2003; + return -6402; if (XMEMCMP(okm1, res2, L) != 0) - return -2004; + return -6403; #endif /* HAVE_FIPS */ #endif /* NO_SHA */ #ifndef NO_SHA256 ret = wc_HKDF(SHA256, ikm1, 22, NULL, 0, NULL, 0, okm1, L); if (ret != 0) - return -2005; + return -6404; if (XMEMCMP(okm1, res3, L) != 0) - return -2006; + return -6405; #ifndef HAVE_FIPS /* fips can't have key size under 14 bytes, salt is key too */ ret = wc_HKDF(SHA256, ikm1, 22, salt1, 13, info1, 10, okm1, L); if (ret != 0) - return -2007; + return -6406; if (XMEMCMP(okm1, res4, L) != 0) - return -2007; + return -6407; #endif /* HAVE_FIPS */ #endif /* NO_SHA256 */ @@ -7229,7 +9169,7 @@ int hkdf_test(void) #endif /* HAVE_HKDF */ -#if defined(HAVE_X963_KDF) +#if defined(HAVE_ECC) && defined(HAVE_X963_KDF) int x963kdf_test(void) { @@ -7335,38 +9275,38 @@ int x963kdf_test(void) ret = wc_X963_KDF(WC_HASH_TYPE_SHA, Z, sizeof(Z), NULL, 0, kek, sizeof(verify)); if (ret != 0) - return -2001; + return -6500; if (XMEMCMP(verify, kek, sizeof(verify)) != 0) - return -2002; + return -6501; #endif #ifndef NO_SHA256 ret = wc_X963_KDF(WC_HASH_TYPE_SHA256, Z2, sizeof(Z2), NULL, 0, kek, sizeof(verify2)); if (ret != 0) - return -2003; + return -6502; if (XMEMCMP(verify2, kek, sizeof(verify2)) != 0) - return -2004; + return -6503; #endif #ifdef WOLFSSL_SHA512 ret = wc_X963_KDF(WC_HASH_TYPE_SHA512, Z3, sizeof(Z3), NULL, 0, kek, sizeof(verify3)); if (ret != 0) - return -2005; + return -6504; if (XMEMCMP(verify3, kek, sizeof(verify3)) != 0) - return -2006; + return -6505; ret = wc_X963_KDF(WC_HASH_TYPE_SHA512, Z4, sizeof(Z4), info4, sizeof(info4), kek, sizeof(verify4)); if (ret != 0) - return -2007; + return -6506; if (XMEMCMP(verify4, kek, sizeof(verify4)) != 0) - return -2008; + return -6507; #endif return 0; @@ -7377,6 +9317,14 @@ int x963kdf_test(void) #ifdef HAVE_ECC +#ifdef BENCH_EMBEDDED + #define ECC_SHARED_SIZE 128 +#else + #define ECC_SHARED_SIZE 1024 +#endif +#define ECC_DIGEST_SIZE MAX_ECC_BYTES +#define ECC_SIG_SIZE ECC_MAX_SIG_SIZE + #ifndef NO_ECC_VECTOR_TEST #if (defined(HAVE_ECC192) || defined(HAVE_ECC224) ||\ !defined(NO_ECC256) || defined(HAVE_ECC384) ||\ @@ -7403,12 +9351,12 @@ static int ecc_test_vector_item(const eccVector* vector) int ret = 0, verify; word32 x; ecc_key userA; - byte sig[1024]; + DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); - wc_ecc_init(&userA); + wc_ecc_init_ex(&userA, HEAP_HINT, devId); - XMEMSET(sig, 0, sizeof(sig)); - x = sizeof(sig); + XMEMSET(sig, 0, ECC_SIG_SIZE); + x = ECC_SIG_SIZE; ret = wc_ecc_import_raw(&userA, vector->Qx, vector->Qy, vector->d, vector->curveName); @@ -7419,17 +9367,27 @@ static int ecc_test_vector_item(const eccVector* vector) if (ret != 0) goto done; - ret = wc_ecc_verify_hash(sig, x, (byte*)vector->msg, vector->msgLen, - &verify, &userA); + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_verify_hash(sig, x, (byte*)vector->msg, vector->msgLen, + &verify, &userA); + } + } while (ret == WC_PENDING_E); + if (ret != 0) goto done; if (verify != 1) - ret = -1023; + ret = -6508; done: wc_ecc_free(&userA); + FREE_VAR(sig, HEAP_HINT); + return ret; } @@ -7622,6 +9580,63 @@ static int ecc_test_vector(int keySize) return 0; } +#ifdef HAVE_ECC_CDH +static int ecc_test_cdh_vectors(void) +{ + int ret; + ecc_key pub_key, priv_key; + byte sharedA[32] = {0}, sharedB[32] = {0}; + word32 x, z; + + const char* QCAVSx = "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287"; + const char* QCAVSy = "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac"; + const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534"; + const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230"; + const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141"; + const char* ZIUT = "46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"; + + /* setup private and public keys */ + ret = wc_ecc_init(&pub_key); + if (ret != 0) + return ret; + ret = wc_ecc_init(&priv_key); + if (ret != 0) { + wc_ecc_free(&pub_key); + goto done; + } + wc_ecc_set_flags(&pub_key, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(&priv_key, WC_ECC_FLAG_COFACTOR); + ret = wc_ecc_import_raw(&pub_key, QCAVSx, QCAVSy, NULL, "SECP256R1"); + if (ret != 0) + goto done; + ret = wc_ecc_import_raw(&priv_key, QIUTx, QIUTy, dIUT, "SECP256R1"); + if (ret != 0) + goto done; + + /* compute ECC Cofactor shared secret */ + x = sizeof(sharedA); + ret = wc_ecc_shared_secret(&priv_key, &pub_key, sharedA, &x); + if (ret != 0) { + goto done; + } + + /* read in expected Z */ + z = sizeof(sharedB); + ret = Base16_Decode((const byte*)ZIUT, (word32)XSTRLEN(ZIUT), sharedB, &z); + if (ret != 0) + goto done; + + /* compare results */ + if (x != z || XMEMCMP(sharedA, sharedB, x)) { + ERROR_OUT(-6509, done); + } + +done: + wc_ecc_free(&priv_key); + wc_ecc_free(&pub_key); + return ret; +} +#endif /* HAVE_ECC_CDH */ #endif /* HAVE_ECC_VECTOR_TEST */ #ifdef WOLFSSL_KEY_GEN @@ -7631,14 +9646,21 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) int derSz, pemSz; byte der[FOURK_BUF]; byte pem[FOURK_BUF]; +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) FILE* keyFile; FILE* pemFile; +#endif ecc_key userA; - wc_ecc_init(&userA); + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) + goto done; ret = wc_ecc_make_key(rng, keySize, &userA); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif if (ret != 0) goto done; @@ -7651,30 +9673,34 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) ERROR_OUT(derSz, done); } - keyFile = fopen("./ecc-key.der", "wb"); +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + keyFile = fopen(eccCaKeyTempFile, "wb"); if (!keyFile) { - ERROR_OUT(-1025, done); + ERROR_OUT(-6510, done); } ret = (int)fwrite(der, 1, derSz, keyFile); fclose(keyFile); if (ret != derSz) { - ERROR_OUT(-1026, done); + ERROR_OUT(-6511, done); } +#endif pemSz = wc_DerToPem(der, derSz, pem, FOURK_BUF, ECC_PRIVATEKEY_TYPE); if (pemSz < 0) { ERROR_OUT(pemSz, done); } - pemFile = fopen("./ecc-key.pem", "wb"); +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + pemFile = fopen(eccCaKeyPemFile, "wb"); if (!pemFile) { - ERROR_OUT(-1028, done); + ERROR_OUT(-6512, done); } ret = (int)fwrite(pem, 1, pemSz, pemFile); fclose(pemFile); if (ret != pemSz) { - ERROR_OUT(-1029, done); + ERROR_OUT(-6513, done); } +#endif /* test export of public key */ derSz = wc_EccPublicKeyToDer(&userA, der, FOURK_BUF, 1); @@ -7682,21 +9708,21 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) ERROR_OUT(derSz, done); } if (derSz == 0) { - ERROR_OUT(-5416, done); + ERROR_OUT(-6514, done); } -#ifdef FREESCALE_MQX - keyFile = fopen("a:\\certs\\ecc-public-key.der", "wb"); -#else - keyFile = fopen("./ecc-public-key.der", "wb"); -#endif + +#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES) + keyFile = fopen(eccPubKeyDerFile, "wb"); if (!keyFile) { - ERROR_OUT(-5417, done); + ERROR_OUT(-6515, done); } ret = (int)fwrite(der, 1, derSz, keyFile); fclose(keyFile); if (ret != derSz) { - ERROR_OUT(-5418, done); + ERROR_OUT(-6516, done); } +#endif + ret = 0; done: @@ -7705,23 +9731,19 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) return ret; } #endif /* WOLFSSL_KEY_GEN */ + static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, int curve_id) { -#ifdef BENCH_EMBEDDED - byte sharedA[128]; /* Needs to be at least keySize */ - byte sharedB[128]; /* Needs to be at least keySize */ -#else - byte sharedA[1024]; - byte sharedB[1024]; -#endif + DECLARE_VAR(sharedA, byte, ECC_SHARED_SIZE, HEAP_HINT); + DECLARE_VAR(sharedB, byte, ECC_SHARED_SIZE, HEAP_HINT); #ifdef HAVE_ECC_KEY_EXPORT byte exportBuf[1024]; #endif word32 x, y; #ifdef HAVE_ECC_SIGN - byte sig[1024]; - byte digest[20]; + DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT); + DECLARE_VAR(digest, byte, ECC_DIGEST_SIZE, HEAP_HINT); int i; #ifdef HAVE_ECC_VERIFY int verify; @@ -7732,11 +9754,24 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, (void)testVerifyCount; - wc_ecc_init(&userA); - wc_ecc_init(&userB); - wc_ecc_init(&pubKey); + XMEMSET(&userA, 0, sizeof(ecc_key)); + XMEMSET(&userB, 0, sizeof(ecc_key)); + XMEMSET(&pubKey, 0, sizeof(ecc_key)); + + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) + goto done; + ret = wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) + goto done; + ret = wc_ecc_init_ex(&pubKey, HEAP_HINT, devId); + if (ret != 0) + goto done; ret = wc_ecc_make_key_ex(rng, keySize, &userA, curve_id); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif if (ret != 0) goto done; @@ -7745,10 +9780,48 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, goto done; ret = wc_ecc_make_key_ex(rng, keySize, &userB, curve_id); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); +#endif if (ret != 0) goto done; #ifdef HAVE_ECC_DHE + x = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); + } while (ret == WC_PENDING_E); + if (ret != 0) { + goto done; + } + + y = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userB, &userA, sharedB, &y); + } while (ret == WC_PENDING_E); + if (ret != 0) + goto done; + + if (y != x) + ERROR_OUT(-6517, done); + + if (XMEMCMP(sharedA, sharedB, x)) + ERROR_OUT(-6518, done); +#endif /* HAVE_ECC_DHE */ + +#ifdef HAVE_ECC_CDH + /* add cofactor flag */ + wc_ecc_set_flags(&userA, WC_ECC_FLAG_COFACTOR); + wc_ecc_set_flags(&userB, WC_ECC_FLAG_COFACTOR); + x = sizeof(sharedA); ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); if (ret != 0) { @@ -7761,15 +9834,19 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, goto done; if (y != x) - ERROR_OUT(-1004, done); + ERROR_OUT(-6519, done); if (XMEMCMP(sharedA, sharedB, x)) - ERROR_OUT(-1005, done); -#endif /* HAVE_ECC_DHE */ + ERROR_OUT(-6520, done); + + /* remove cofactor flag */ + wc_ecc_set_flags(&userA, 0); + wc_ecc_set_flags(&userB, 0); +#endif /* HAVE_ECC_CDH */ #ifdef HAVE_ECC_KEY_EXPORT x = sizeof(exportBuf); - ret = wc_ecc_export_x963(&userA, exportBuf, &x); + ret = wc_ecc_export_x963_ex(&userA, exportBuf, &x, 0); if (ret != 0) goto done; @@ -7779,13 +9856,19 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, goto done; #ifdef HAVE_ECC_DHE - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + y = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (XMEMCMP(sharedA, sharedB, y)) - ERROR_OUT(-1009, done); + ERROR_OUT(-6521, done); #endif /* HAVE_ECC_DHE */ #ifdef HAVE_COMP_KEY @@ -7795,20 +9878,28 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, if (ret != 0) goto done; wc_ecc_free(&pubKey); - wc_ecc_init(&pubKey); + ret = wc_ecc_init_ex(&pubKey, HEAP_HINT, devId); + if (ret != 0) + goto done; ret = wc_ecc_import_x963_ex(exportBuf, x, &pubKey, curve_id); if (ret != 0) goto done; #ifdef HAVE_ECC_DHE - y = sizeof(sharedB); - ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + y = ECC_SHARED_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (XMEMCMP(sharedA, sharedB, y)) - ERROR_OUT(-1013, done); + ERROR_OUT(-6522, done); #endif /* HAVE_ECC_DHE */ #endif /* HAVE_COMP_KEY */ @@ -7816,48 +9907,77 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_SIGN -#ifdef ECC_SHAMIR /* ECC w/out Shamir has issue with all 0 digest */ + /* ECC w/out Shamir has issue with all 0 digest */ + /* WC_BIGINT doesn't have 0 len well on hardware */ +#if defined(ECC_SHAMIR) && !defined(WOLFSSL_ASYNC_CRYPT) /* test DSA sign hash with zeros */ - for (i = 0; i < (int)sizeof(digest); i++) { + for (i = 0; i < (int)ECC_DIGEST_SIZE; i++) { digest[i] = 0; } - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, rng, &userA); + x = ECC_SIG_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(digest, ECC_DIGEST_SIZE, sig, &x, rng, + &userA); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; #ifdef HAVE_ECC_VERIFY for (i=0; i= 0) + ret = wc_ecc_verify_hash(sig, x, digest, ECC_DIGEST_SIZE, + &verify, &userA); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (verify != 1) - ERROR_OUT(-1016, done); + ERROR_OUT(-6523, done); } #endif /* HAVE_ECC_VERIFY */ -#endif /* ECC_SHAMIR */ +#endif /* ECC_SHAMIR && !WOLFSSL_ASYNC_CRYPT */ /* test DSA sign hash with sequence (0,1,2,3,4,...) */ - for (i = 0; i < (int)sizeof(digest); i++) { + for (i = 0; i < (int)ECC_DIGEST_SIZE; i++) { digest[i] = (byte)i; } - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, rng, &userA); - + x = ECC_SIG_SIZE; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(digest, ECC_DIGEST_SIZE, sig, &x, rng, + &userA); + } while (ret == WC_PENDING_E); if (ret != 0) - ERROR_OUT(-1014, done); + ERROR_OUT(-6524, done); #ifdef HAVE_ECC_VERIFY for (i=0; i= 0) + ret = wc_ecc_verify_hash(sig, x, digest, ECC_DIGEST_SIZE, + &verify, &userA); + } while (ret == WC_PENDING_E); if (ret != 0) goto done; if (verify != 1) - ERROR_OUT(-1016, done); + ERROR_OUT(-6525, done); } #endif /* HAVE_ECC_VERIFY */ #endif /* HAVE_ECC_SIGN */ @@ -7874,6 +9994,13 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, wc_ecc_free(&userB); wc_ecc_free(&userA); + FREE_VAR(sharedA, HEAP_HINT); + FREE_VAR(sharedB, HEAP_HINT); +#ifdef HAVE_ECC_SIGN + FREE_VAR(sig, HEAP_HINT); + FREE_VAR(digest, HEAP_HINT); +#endif + return ret; } @@ -7885,346 +10012,984 @@ static int ecc_test_curve(WC_RNG* rng, int keySize) ret = ecc_test_curve_size(rng, keySize, ECC_TEST_VERIFY_COUNT, ECC_CURVE_DEF); if (ret < 0) { - printf("ecc_test_curve_size %d failed!: %d\n", keySize, ret); + if (ret == ECC_CURVE_OID_E) { + /* ignore error for curves not found */ + /* some curve sizes are only available with: + HAVE_ECC_SECPR2, HAVE_ECC_SECPR3, HAVE_ECC_BRAINPOOL and HAVE_ECC_KOBLITZ */ + } + else { + printf("ecc_test_curve_size %d failed!: %d\n", keySize, ret); + return ret; + } + } + +#ifdef HAVE_ECC_VECTOR_TEST + ret = ecc_test_vector(keySize); + if (ret < 0) { + printf("ecc_test_vector %d failed!: %d\n", keySize, ret); return ret; } +#endif - #ifdef HAVE_ECC_VECTOR_TEST - ret = ecc_test_vector(keySize); - if (ret < 0) { - printf("ecc_test_vector %d failed!: %d\n", keySize, ret); - return ret; +#ifdef WOLFSSL_KEY_GEN + ret = ecc_test_key_gen(rng, keySize); + if (ret < 0) { + if (ret == ECC_CURVE_OID_E) { + /* ignore error for curves not found */ } - #endif - - #ifdef WOLFSSL_KEY_GEN - ret = ecc_test_key_gen(rng, keySize); - if (ret < 0) { + else { printf("ecc_test_key_gen %d failed!: %d\n", keySize, ret); return ret; } - #endif + } +#endif return 0; } -int ecc_test(void) +#if !defined(WOLFSSL_ATECC508A) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) +static int ecc_point_test(void) { - int ret; - WC_RNG rng; - - ret = wc_InitRng(&rng); - if (ret != 0) - return -1001; + int ret; + ecc_point* point; + ecc_point* point2; +#ifdef HAVE_COMP_KEY + ecc_point* point3; + ecc_point* point4; +#endif + word32 outLen; + byte out[65]; + byte der[] = { 0x04, /* = Uncompressed */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +#ifdef HAVE_COMP_KEY + byte derComp0[] = { 0x02, /* = Compressed, y even */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + byte derComp1[] = { 0x03, /* = Compressed, y odd */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +#endif + byte altDer[] = { 0x04, /* = Uncompressed */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; + int curve_idx = wc_ecc_get_curve_idx(ECC_SECP256R1); + + /* if curve P256 is not enabled then test should not fail */ + if (curve_idx == ECC_CURVE_INVALID) + return 0; -#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 14); - if (ret < 0) { + outLen = sizeof(out); + point = wc_ecc_new_point(); + if (point == NULL) + return -6600; + point2 = wc_ecc_new_point(); + if (point2 == NULL) { + wc_ecc_del_point(point); + return -6601; + } +#ifdef HAVE_COMP_KEY + point3 = wc_ecc_new_point(); + if (point3 == NULL) { + wc_ecc_del_point(point2); + wc_ecc_del_point(point); + return -6602; + } + point4 = wc_ecc_new_point(); + if (point4 == NULL) { + wc_ecc_del_point(point3); + wc_ecc_del_point(point2); + wc_ecc_del_point(point); + return -6603; + } +#endif + + /* Parameter Validation testing. */ + wc_ecc_del_point(NULL); + ret = wc_ecc_import_point_der(NULL, sizeof(der), curve_idx, point); + if (ret != ECC_BAD_ARG_E) { + ret = -6604; goto done; } -#endif /* HAVE_ECC112 */ -#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 16); - if (ret < 0) { + ret = wc_ecc_import_point_der(der, sizeof(der), ECC_CURVE_INVALID, point); + if (ret != ECC_BAD_ARG_E) { + ret = -6605; goto done; } -#endif /* HAVE_ECC128 */ -#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 20); - if (ret < 0) { + ret = wc_ecc_import_point_der(der, sizeof(der), curve_idx, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6606; goto done; } -#endif /* HAVE_ECC160 */ -#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 24); - if (ret < 0) { + ret = wc_ecc_export_point_der(-1, point, out, &outLen); + if (ret != ECC_BAD_ARG_E) { + ret = -6607; goto done; } -#endif /* HAVE_ECC192 */ -#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 28); - if (ret < 0) { + ret = wc_ecc_export_point_der(curve_idx, NULL, out, &outLen); + if (ret != ECC_BAD_ARG_E) { + ret = -6608; goto done; } -#endif /* HAVE_ECC224 */ -#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 30); - if (ret < 0) { + ret = wc_ecc_export_point_der(curve_idx, point, NULL, &outLen); + if (ret != LENGTH_ONLY_E || outLen != sizeof(out)) { + ret = -6609; goto done; } -#endif /* HAVE_ECC239 */ -#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 32); - if (ret < 0) { + ret = wc_ecc_export_point_der(curve_idx, point, out, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6610; goto done; } -#endif /* !NO_ECC256 */ -#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 40); - if (ret < 0) { + outLen = 0; + ret = wc_ecc_export_point_der(curve_idx, point, out, &outLen); + if (ret != BUFFER_E) { + ret = -6611; goto done; } -#endif /* HAVE_ECC320 */ -#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 48); - if (ret < 0) { + ret = wc_ecc_copy_point(NULL, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6612; goto done; } -#endif /* HAVE_ECC384 */ -#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 64); - if (ret < 0) { + ret = wc_ecc_copy_point(NULL, point2); + if (ret != ECC_BAD_ARG_E) { + ret = -6613; goto done; } -#endif /* HAVE_ECC512 */ -#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) - ret = ecc_test_curve(&rng, 66); - if (ret < 0) { + ret = wc_ecc_copy_point(point, NULL); + if (ret != ECC_BAD_ARG_E) { + ret = -6614; + goto done; + } + ret = wc_ecc_cmp_point(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + ret = -6615; + goto done; + } + ret = wc_ecc_cmp_point(NULL, point2); + if (ret != BAD_FUNC_ARG) { + ret = -6616; + goto done; + } + ret = wc_ecc_cmp_point(point, NULL); + if (ret != BAD_FUNC_ARG) { + ret = -6617; goto done; } -#endif /* HAVE_ECC521 */ -#if defined(WOLFSSL_CUSTOM_CURVES) - #if defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ) - { - int curve_id; - #ifdef HAVE_ECC_BRAINPOOL - curve_id = ECC_BRAINPOOLP256R1; - #else - curve_id = ECC_SECP256K1; - #endif - /* Test and demonstrate use of non-SECP curve */ - ret = ecc_test_curve_size(&rng, 0, ECC_TEST_VERIFY_COUNT, curve_id); - if (ret < 0) { - printf("ecc_test_curve_size: type %d: failed!: %d\n", curve_id, ret); - goto done; - } + /* Use API. */ + ret = wc_ecc_import_point_der(der, sizeof(der), curve_idx, point); + if (ret != 0) { + ret = -6618; + goto done; + } + + outLen = sizeof(out); + ret = wc_ecc_export_point_der(curve_idx, point, out, &outLen); + if (ret != 0) { + ret = -6619; + goto done; + } + if (outLen != sizeof(der)) { + ret = -6620; + goto done; + } + if (XMEMCMP(out, der, outLen) != 0) { + ret = -6621; + goto done; + } + + ret = wc_ecc_copy_point(point2, point); + if (ret != MP_OKAY) { + ret = -6622; + goto done; + } + ret = wc_ecc_cmp_point(point2, point); + if (ret != MP_EQ) { + ret = -6623; + goto done; + } + + ret = wc_ecc_import_point_der(altDer, sizeof(altDer), curve_idx, point2); + if (ret != 0) { + ret = -6624; + goto done; + } + ret = wc_ecc_cmp_point(point2, point); + if (ret != MP_GT) { + ret = -6625; + goto done; + } + +#ifdef HAVE_COMP_KEY + ret = wc_ecc_import_point_der(derComp0, sizeof(der), curve_idx, point3); + if (ret != 0) { + ret = -6626; + goto done; + } + + ret = wc_ecc_import_point_der(derComp1, sizeof(der), curve_idx, point4); + if (ret != 0) { + ret = -6627; + goto done; } - #endif #endif done: - wc_FreeRng(&rng); +#ifdef HAVE_COMP_KEY + wc_ecc_del_point(point4); + wc_ecc_del_point(point3); +#endif + wc_ecc_del_point(point2); + wc_ecc_del_point(point); return ret; } +#endif /* !WOLFSSL_ATECC508A && HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ -#ifdef HAVE_ECC_ENCRYPT - -int ecc_encrypt_test(void) +#ifndef NO_SIG_WRAPPER +static int ecc_sig_test(WC_RNG* rng, ecc_key* key) { - WC_RNG rng; int ret; - ecc_key userA, userB; - byte msg[48]; - byte plain[48]; - byte out[80]; - word32 outSz = sizeof(out); - word32 plainSz = sizeof(plain); - int i; - - ret = wc_InitRng(&rng); - if (ret != 0) - return -3001; + word32 sigSz; + int size; + byte out[ECC_MAX_SIG_SIZE]; + byte in[] = "Everyone gets Friday off."; + word32 inLen = (word32)XSTRLEN((char*)in); - wc_ecc_init(&userA); - wc_ecc_init(&userB); + size = wc_ecc_sig_size(key); - ret = wc_ecc_make_key(&rng, 32, &userA); - ret += wc_ecc_make_key(&rng, 32, &userB); + ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, sizeof(*key)); + if (ret != size) + return -6628; + sigSz = ret; + ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in, + inLen, out, &sigSz, key, sizeof(*key), rng); if (ret != 0) - return -3002; - - for (i = 0; i < 48; i++) - msg[i] = i; + return -6629; - /* encrypt msg to B */ - ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); + ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in, + inLen, out, sigSz, key, sizeof(*key)); if (ret != 0) - return -3003; + return -6630; - /* decrypt msg from A */ - ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); - if (ret != 0) - return -3004; + return 0; +} +#endif - if (XMEMCMP(plain, msg, sizeof(msg)) != 0) - return -3005; +#if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) +static int ecc_exp_imp_test(ecc_key* key) +{ + int ret; + int curve_id; + ecc_key keyImp; + byte priv[32]; + word32 privLen; + byte pub[65]; + word32 pubLen; + const char qx[] = "01020304050607080102030405060708" + "01020304050607080102030405060708"; + const char qy[] = "01020304050607080102030405060708" + "01020304050607080102030405060708"; + const char d[] = "01020304050607080102030405060708"; + + wc_ecc_init(&keyImp); + + privLen = sizeof(priv); + ret = wc_ecc_export_private_only(key, priv, &privLen); + if (ret != 0) { + ret = -6631; + goto done; + } + pubLen = sizeof(pub); + ret = wc_ecc_export_point_der(key->idx, &key->pubkey, pub, &pubLen); + if (ret != 0) { + ret = -6632; + goto done; + } + ret = wc_ecc_import_private_key(priv, privLen, pub, pubLen, &keyImp); + if (ret != 0) { + ret = -6633; + goto done; + } - { /* let's verify message exchange works, A is client, B is server */ - ecEncCtx* cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); - ecEncCtx* srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); + wc_ecc_free(&keyImp); + wc_ecc_init(&keyImp); - byte cliSalt[EXCHANGE_SALT_SZ]; - byte srvSalt[EXCHANGE_SALT_SZ]; - const byte* tmpSalt; + ret = wc_ecc_import_raw_ex(&keyImp, qx, qy, d, ECC_SECP256R1); + if (ret != 0) { + ret = -6634; + goto done; + } - if (cliCtx == NULL || srvCtx == NULL) - return -3006; + wc_ecc_free(&keyImp); + wc_ecc_init(&keyImp); - /* get salt to send to peer */ - tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx); - if (tmpSalt == NULL) - return -3007; - XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); + curve_id = wc_ecc_get_curve_id(key->idx); + if (curve_id < 0) + return -6635; - tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); - if (tmpSalt == NULL) - return -3007; - XMEMCPY(srvSalt, tmpSalt, EXCHANGE_SALT_SZ); + /* test import private only */ + ret = wc_ecc_import_private_key_ex(priv, privLen, NULL, 0, &keyImp, + curve_id); + if (ret != 0) + return -6636; - /* in actual use, we'd get the peer's salt over the transport */ - ret = wc_ecc_ctx_set_peer_salt(cliCtx, srvSalt); - ret += wc_ecc_ctx_set_peer_salt(srvCtx, cliSalt); +done: + wc_ecc_free(&keyImp); + return ret; +} +#endif /* HAVE_ECC_KEY_IMPORT && HAVE_ECC_KEY_EXPORT */ - ret += wc_ecc_ctx_set_info(cliCtx, (byte*)"wolfSSL MSGE", 11); - ret += wc_ecc_ctx_set_info(srvCtx, (byte*)"wolfSSL MSGE", 11); +#ifdef HAVE_ECC_KEY_IMPORT +static int ecc_mulmod_test(ecc_key* key1) +{ + int ret; + ecc_key key2; + ecc_key key3; - if (ret != 0) - return -3008; + wc_ecc_init(&key2); + wc_ecc_init(&key3); - /* get encrypted msg (request) to send to B */ - outSz = sizeof(out); - ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz,cliCtx); - if (ret != 0) - return -3009; + /* TODO: Use test data. */ + /* Need base point (Gx,Gy) and parameter A - load them as the public and + * private key in key2. + */ + ret = wc_ecc_import_raw_ex(&key2, key1->dp->Gx, key1->dp->Gy, key1->dp->Af, + ECC_SECP256R1); + if (ret != 0) + goto done; - /* B decrypts msg (request) from A */ - plainSz = sizeof(plain); - ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, srvCtx); - if (ret != 0) - return -3010; + /* Need a point (Gx,Gy) and prime - load them as the public and private key + * in key3. + */ + ret = wc_ecc_import_raw_ex(&key3, key1->dp->Gx, key1->dp->Gy, + key1->dp->prime, ECC_SECP256R1); + if (ret != 0) + goto done; - if (XMEMCMP(plain, msg, sizeof(msg)) != 0) - return -3011; + ret = wc_ecc_mulmod(&key1->k, &key2.pubkey, &key3.pubkey, &key2.k, &key3.k, + 1); + if (ret != 0) { + ret = -6637; + goto done; + } - { - /* msg2 (response) from B to A */ - byte msg2[48]; - byte plain2[48]; - byte out2[80]; - word32 outSz2 = sizeof(out2); - word32 plainSz2 = sizeof(plain2); - - for (i = 0; i < 48; i++) - msg2[i] = i+48; - - /* get encrypted msg (response) to send to B */ - ret = wc_ecc_encrypt(&userB, &userA, msg2, sizeof(msg2), out2, - &outSz2, srvCtx); - if (ret != 0) - return -3012; +done: + wc_ecc_free(&key3); + wc_ecc_free(&key2); + return ret; +} +#endif - /* A decrypts msg (response) from B */ - ret = wc_ecc_decrypt(&userA, &userB, out2, outSz2, plain2, &plainSz2, - cliCtx); - if (ret != 0) - return -3013; +#ifndef WOLFSSL_ATECC508A +static int ecc_ssh_test(ecc_key* key) +{ + int ret; + byte out[128]; + word32 outLen = sizeof(out); + + /* Parameter Validation testing. */ + ret = wc_ecc_shared_secret_ssh(NULL, &key->pubkey, out, &outLen); + if (ret != BAD_FUNC_ARG) + return -6638; + ret = wc_ecc_shared_secret_ssh(key, NULL, out, &outLen); + if (ret != BAD_FUNC_ARG) + return -6639; + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, NULL, &outLen); + if (ret != BAD_FUNC_ARG) + return -6640; + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, NULL); + if (ret != BAD_FUNC_ARG) + return -6641; + + /* Use API. */ + ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, &outLen); + if (ret != 0) + return -6642; + return 0; +} +#endif - if (XMEMCMP(plain2, msg2, sizeof(msg2)) != 0) - return -3014; - } +static int ecc_def_curve_test(WC_RNG *rng) +{ + int ret; + ecc_key key; - /* cleanup */ - wc_ecc_ctx_free(srvCtx); - wc_ecc_ctx_free(cliCtx); - } + wc_ecc_init(&key); - /* cleanup */ - wc_ecc_free(&userB); - wc_ecc_free(&userA); - wc_FreeRng(&rng); + ret = wc_ecc_make_key(rng, 32, &key); + if (ret != 0) { + ret = -6643; + goto done; + } - return 0; +#ifndef NO_SIG_WRAPPER + ret = ecc_sig_test(rng, &key); + if (ret < 0) + goto done; +#endif +#if defined(HAVE_ECC_KEY_IMPORT) && defined(HAVE_ECC_KEY_EXPORT) + ret = ecc_exp_imp_test(&key); + if (ret < 0) + goto done; +#endif +#ifdef HAVE_ECC_KEY_IMPORT + ret = ecc_mulmod_test(&key); + if (ret < 0) + goto done; +#endif +#ifndef WOLFSSL_ATECC508A + ret = ecc_ssh_test(&key); + if (ret < 0) + goto done; +#endif +done: + wc_ecc_free(&key); + return ret; } -#endif /* HAVE_ECC_ENCRYPT */ - -#ifdef USE_CERT_BUFFERS_256 -int ecc_test_buffers() { - size_t bytes; - ecc_key cliKey; - ecc_key servKey; #ifdef WOLFSSL_CERT_EXT - ecc_key keypub; -#endif - WC_RNG rng; - word32 idx = 0; - int ret; - /* pad our test message to 32 bytes so evenly divisible by AES_BLOCK_SZ */ - byte in[] = "Everyone gets Friday off. ecc p"; - word32 inLen = (word32)XSTRLEN((char*)in); - byte out[256]; - byte plain[256]; - int verify = 0; - word32 x; +static int ecc_decode_test(void) +{ + int ret; + word32 inSz; + word32 inOutIdx; + ecc_key key; + const byte good[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, 0x06, 0x01, 0x01, + 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badNoObjId[] = { 0x30, 0x08, 0x30, 0x06, 0x03, 0x04, + 0x00, 0x04, 0x01, 0x01 }; + const byte badOneObjId[] = { 0x30, 0x0a, 0x30, 0x08, 0x06, 0x00, 0x03, 0x04, + 0x00, 0x04, 0x01, 0x01 }; + const byte badObjId1Len[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x09, + 0x06, 0x00, 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badObj2d1Len[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x00, + 0x06, 0x07, 0x03, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badNotBitStr[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x04, 0x04, 0x00, 0x04, 0x01, 0x01 }; + const byte badBitStrLen[] = { 0x30, 0x0d, 0x30, 0x0b, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x03, 0x05, 0x00, 0x04, 0x01, 0x01 }; + const byte badNoBitStrZero[] = { 0x30, 0x0c, 0x30, 0x0a, 0x06, 0x00, + 0x06, 0x01, 0x01, 0x03, 0x03, 0x04, 0x01, 0x01 }; + const byte badPoint[] = { 0x30, 0x0b, 0x30, 0x09, 0x06, 0x00, 0x06, 0x01, + 0x01, 0x03, 0x03, 0x00, 0x04, 0x01 }; + + XMEMSET(&key, 0, sizeof(key)); + wc_ecc_init(&key); + + inSz = sizeof(good); + ret = wc_EccPublicKeyDecode(NULL, &inOutIdx, &key, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -6700; + goto done; + } + ret = wc_EccPublicKeyDecode(good, NULL, &key, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -6701; + goto done; + } + ret = wc_EccPublicKeyDecode(good, &inOutIdx, NULL, inSz); + if (ret != BAD_FUNC_ARG) { + ret = -6702; + goto done; + } + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, 0); + if (ret != BAD_FUNC_ARG) { + ret = -6703; + goto done; + } - bytes = sizeof_ecc_clikey_der_256; - /* place client key into ecc_key struct cliKey */ - ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &cliKey, - (word32)bytes); - if (ret != 0) - return -41; + /* Change offset to produce bad input data. */ + inOutIdx = 2; + inSz = sizeof(good) - inOutIdx; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6704; + goto done; + } + inOutIdx = 4; + inSz = sizeof(good) - inOutIdx; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6705; + goto done; + } + /* Bad data. */ + inSz = sizeof(badNoObjId); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNoObjId, &inOutIdx, &key, inSz); + if (ret != ASN_OBJECT_ID_E) { + ret = -6706; + goto done; + } + inSz = sizeof(badOneObjId); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badOneObjId, &inOutIdx, &key, inSz); + if (ret != ASN_OBJECT_ID_E) { + ret = -6707; + goto done; + } + inSz = sizeof(badObjId1Len); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badObjId1Len, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6708; + goto done; + } + inSz = sizeof(badObj2d1Len); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badObj2d1Len, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6709; + goto done; + } + inSz = sizeof(badNotBitStr); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNotBitStr, &inOutIdx, &key, inSz); + if (ret != ASN_BITSTR_E) { + ret = -6710; + goto done; + } + inSz = sizeof(badBitStrLen); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badBitStrLen, &inOutIdx, &key, inSz); + if (ret != ASN_PARSE_E) { + ret = -6711; + goto done; + } + inSz = sizeof(badNoBitStrZero); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badNoBitStrZero, &inOutIdx, &key, inSz); + if (ret != ASN_EXPECT_0_E) { + ret = -6712; + goto done; + } + inSz = sizeof(badPoint); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(badPoint, &inOutIdx, &key, inSz); + if (ret != ASN_ECC_KEY_E) { + ret = -6713; + goto done; + } - idx = 0; - bytes = sizeof_ecc_key_der_256; + inSz = sizeof(good); + inOutIdx = 0; + ret = wc_EccPublicKeyDecode(good, &inOutIdx, &key, inSz); + if (ret != 0) { + ret = -6714; + goto done; + } - /* place server key into ecc_key struct servKey */ - ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, &servKey, - (word32)bytes); - if (ret != 0) - return -41; +done: + wc_ecc_free(&key); + return ret; +} +#endif /* WOLFSSL_CERT_EXT */ + +int ecc_test(void) +{ + int ret; + WC_RNG rng; + +#ifdef WOLFSSL_CERT_EXT + ret = ecc_decode_test(); + if (ret < 0) + return ret; +#endif +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else ret = wc_InitRng(&rng); +#endif if (ret != 0) - return -42; - -#if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_HKDF) - { - word32 y; - /* test encrypt and decrypt if they're available */ - x = sizeof(out); - ret = wc_ecc_encrypt(&cliKey, &servKey, in, sizeof(in), out, &x, NULL); - if (ret < 0) - return -43; + return -6800; - y = sizeof(plain); - ret = wc_ecc_decrypt(&cliKey, &servKey, out, x, plain, &y, NULL); - if (ret < 0) - return -44; +#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 14); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC112 */ +#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 16); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC128 */ +#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 20); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC160 */ +#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 24); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC192 */ +#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 28); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC224 */ +#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 30); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC239 */ +#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 32); + if (ret < 0) { + goto done; + } +#if !defined(WOLFSSL_ATECC508A) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) + ret = ecc_point_test(); + if (ret < 0) { + goto done; + } +#endif + ret = ecc_def_curve_test(&rng); + if (ret < 0) { + goto done; + } +#endif /* !NO_ECC256 */ +#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 40); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC320 */ +#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 48); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC384 */ +#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 64); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC512 */ +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + ret = ecc_test_curve(&rng, 66); + if (ret < 0) { + goto done; + } +#endif /* HAVE_ECC521 */ - if (XMEMCMP(plain, in, inLen)) - return -45; +#if defined(WOLFSSL_CUSTOM_CURVES) + #if defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ) + { + int curve_id; + #ifdef HAVE_ECC_BRAINPOOL + curve_id = ECC_BRAINPOOLP256R1; + #else + curve_id = ECC_SECP256K1; + #endif + /* Test and demonstrate use of non-SECP curve */ + ret = ecc_test_curve_size(&rng, 0, ECC_TEST_VERIFY_COUNT, curve_id); + if (ret < 0) { + printf("ecc_test_curve_size: type %d: failed!: %d\n", curve_id, ret); + goto done; + } } + #endif #endif +#ifdef HAVE_ECC_CDH + ret = ecc_test_cdh_vectors(); + if (ret != 0) { + printf("ecc_test_cdh_vectors failed! %d\n", ret); + } +#endif - x = sizeof(out); - ret = wc_ecc_sign_hash(in, inLen, out, &x, &rng, &cliKey); - if (ret < 0) - return -46; +done: + wc_FreeRng(&rng); - XMEMSET(plain, 0, sizeof(plain)); + return ret; +} - ret = wc_ecc_verify_hash(out, x, plain, sizeof(plain), &verify, &cliKey); - if (ret < 0) - return -47; +#ifdef HAVE_ECC_ENCRYPT - if (XMEMCMP(plain, in, ret)) - return -48; +int ecc_encrypt_test(void) +{ + WC_RNG rng; + int ret = 0; + ecc_key userA, userB; + byte msg[48]; + byte plain[48]; + byte out[80]; + word32 outSz = sizeof(out); + word32 plainSz = sizeof(plain); + int i; + ecEncCtx* cliCtx = NULL; + ecEncCtx* srvCtx = NULL; + byte cliSalt[EXCHANGE_SALT_SZ]; + byte srvSalt[EXCHANGE_SALT_SZ]; + const byte* tmpSalt; + byte msg2[48]; + byte plain2[48]; + byte out2[80]; + word32 outSz2 = sizeof(out2); + word32 plainSz2 = sizeof(plain2); - idx = 0; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -6900; - bytes = sizeof_ecc_clikeypub_der_256; + XMEMSET(&userA, 0, sizeof(userA)); + XMEMSET(&userB, 0, sizeof(userB)); - ret = wc_EccPublicKeyDecode(ecc_clikeypub_der_256, &idx, &cliKey, - (word32) bytes); + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); if (ret != 0) - return -52; + goto done; + ret = wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) + goto done; - return 0; + ret = wc_ecc_make_key(&rng, 32, &userA); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userA.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0){ + ret = -6901; goto done; + } + + ret = wc_ecc_make_key(&rng, 32, &userB); +#if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &userB.asyncDev, WC_ASYNC_FLAG_NONE); +#endif + if (ret != 0){ + ret = -6902; goto done; + } + + /* set message to incrementing 0,1,2,etc... */ + for (i = 0; i < (int)sizeof(msg); i++) + msg[i] = i; + + /* encrypt msg to B */ + ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); + if (ret != 0) { + ret = -6903; goto done; + } + + /* decrypt msg from A */ + ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); + if (ret != 0) { + ret = -6904; goto done; + } + + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -6905; goto done; + } + + /* let's verify message exchange works, A is client, B is server */ + cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng); + srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng); + if (cliCtx == NULL || srvCtx == NULL) { + ret = -6906; goto done; + } + + /* get salt to send to peer */ + tmpSalt = wc_ecc_ctx_get_own_salt(cliCtx); + if (tmpSalt == NULL) { + ret = -6907; goto done; + } + XMEMCPY(cliSalt, tmpSalt, EXCHANGE_SALT_SZ); + + tmpSalt = wc_ecc_ctx_get_own_salt(srvCtx); + if (tmpSalt == NULL) { + ret = -6908; goto done; + } + XMEMCPY(srvSalt, tmpSalt, EXCHANGE_SALT_SZ); + + /* in actual use, we'd get the peer's salt over the transport */ + ret = wc_ecc_ctx_set_peer_salt(cliCtx, srvSalt); + if (ret != 0) + goto done; + ret = wc_ecc_ctx_set_peer_salt(srvCtx, cliSalt); + if (ret != 0) + goto done; + + ret = wc_ecc_ctx_set_info(cliCtx, (byte*)"wolfSSL MSGE", 11); + if (ret != 0) + goto done; + ret = wc_ecc_ctx_set_info(srvCtx, (byte*)"wolfSSL MSGE", 11); + if (ret != 0) + goto done; + + /* get encrypted msg (request) to send to B */ + outSz = sizeof(out); + ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz,cliCtx); + if (ret != 0) + goto done; + + /* B decrypts msg (request) from A */ + plainSz = sizeof(plain); + ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, srvCtx); + if (ret != 0) + goto done; + + if (XMEMCMP(plain, msg, sizeof(msg)) != 0) { + ret = -6909; goto done; + } + + /* msg2 (response) from B to A */ + for (i = 0; i < (int)sizeof(msg2); i++) + msg2[i] = i + sizeof(msg2); + + /* get encrypted msg (response) to send to B */ + ret = wc_ecc_encrypt(&userB, &userA, msg2, sizeof(msg2), out2, + &outSz2, srvCtx); + if (ret != 0) + goto done; + + /* A decrypts msg (response) from B */ + ret = wc_ecc_decrypt(&userA, &userB, out2, outSz2, plain2, &plainSz2, + cliCtx); + if (ret != 0) + goto done; + + if (XMEMCMP(plain2, msg2, sizeof(msg2)) != 0) { + ret = -6910; goto done; + } + +done: + + /* cleanup */ + wc_ecc_ctx_free(srvCtx); + wc_ecc_ctx_free(cliCtx); + + wc_ecc_free(&userB); + wc_ecc_free(&userA); + wc_FreeRng(&rng); + + return ret; +} + +#endif /* HAVE_ECC_ENCRYPT */ + +#ifdef USE_CERT_BUFFERS_256 +int ecc_test_buffers() { + size_t bytes; + ecc_key cliKey; + ecc_key servKey; + WC_RNG rng; + word32 idx = 0; + int ret; + /* pad our test message to 32 bytes so evenly divisible by AES_BLOCK_SZ */ + byte in[] = "Everyone gets Friday off. ecc p"; + word32 inLen = (word32)XSTRLEN((char*)in); + byte out[256]; + byte plain[256]; + int verify = 0; + word32 x; + + bytes = sizeof_ecc_clikey_der_256; + /* place client key into ecc_key struct cliKey */ + ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &cliKey, + (word32)bytes); + if (ret != 0) + return -6915; + + idx = 0; + bytes = sizeof_ecc_key_der_256; + + /* place server key into ecc_key struct servKey */ + ret = wc_EccPrivateKeyDecode(ecc_key_der_256, &idx, &servKey, + (word32)bytes); + if (ret != 0) + return -6916; + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -6917; + +#if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_HKDF) + { + word32 y; + /* test encrypt and decrypt if they're available */ + x = sizeof(out); + ret = wc_ecc_encrypt(&cliKey, &servKey, in, sizeof(in), out, &x, NULL); + if (ret < 0) + return -6918; + + y = sizeof(plain); + ret = wc_ecc_decrypt(&cliKey, &servKey, out, x, plain, &y, NULL); + if (ret < 0) + return -6919; + + if (XMEMCMP(plain, in, inLen)) + return -6920; + } +#endif + + + x = sizeof(out); + ret = wc_ecc_sign_hash(in, inLen, out, &x, &rng, &cliKey); + if (ret < 0) + return -6921; + + XMEMSET(plain, 0, sizeof(plain)); + + ret = wc_ecc_verify_hash(out, x, plain, sizeof(plain), &verify, &cliKey); + if (ret < 0) + return -6922; + + if (XMEMCMP(plain, in, ret)) + return -6923; + +#ifdef WOLFSSL_CERT_EXT + idx = 0; + + bytes = sizeof_ecc_clikeypub_der_256; + + ret = wc_EccPublicKeyDecode(ecc_clikeypub_der_256, &idx, &cliKey, + (word32) bytes); + if (ret != 0) + return -6924; +#endif + + wc_ecc_free(&cliKey); + wc_ecc_free(&servKey); + wc_FreeRng(&rng); + + return 0; } #endif /* USE_CERT_BUFFERS_256 */ #endif /* HAVE_ECC */ @@ -8235,6 +11000,7 @@ int ecc_test_buffers() { int curve25519_test(void) { WC_RNG rng; + int ret; #ifdef HAVE_CURVE25519_SHARED_SECRET byte sharedA[32]; byte sharedB[32]; @@ -8292,8 +11058,13 @@ int curve25519_test(void) }; #endif /* HAVE_CURVE25519_SHARED_SECRET */ - if (wc_InitRng(&rng) != 0) - return -1001; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7000; wc_curve25519_init(&userA); wc_curve25519_init(&userB); @@ -8301,38 +11072,38 @@ int curve25519_test(void) /* make curve25519 keys */ if (wc_curve25519_make_key(&rng, 32, &userA) != 0) - return -1002; + return -7001; if (wc_curve25519_make_key(&rng, 32, &userB) != 0) - return -1003; + return -7002; #ifdef HAVE_CURVE25519_SHARED_SECRET /* find shared secret key */ x = sizeof(sharedA); if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0) - return -1004; + return -7003; y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1005; + return -7004; /* compare shared secret keys to test they are the same */ if (y != x) - return -1006; + return -7005; if (XMEMCMP(sharedA, sharedB, x)) - return -1007; + return -7006; #endif #ifdef HAVE_CURVE25519_KEY_EXPORT /* export a public key and import it for another user */ x = sizeof(exportBuf); if (wc_curve25519_export_public(&userA, exportBuf, &x) != 0) - return -1008; + return -7007; #ifdef HAVE_CURVE25519_KEY_IMPORT if (wc_curve25519_import_public(exportBuf, x, &pubKey) != 0) - return -1009; + return -7008; #endif #endif @@ -8341,60 +11112,60 @@ int curve25519_test(void) XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &pubKey, sharedB, &y) != 0) - return -1010; + return -7009; if (XMEMCMP(sharedA, sharedB, y)) - return -1011; + return -7010; /* import RFC test vectors and compare shared key */ if (wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) != 0) - return -1012; + return -7011; if (wc_curve25519_import_private_raw(sb, sizeof(sb), pb, sizeof(pb), &userB) != 0) - return -1013; + return -7012; /* test against known test vector */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userA, &userB, sharedB, &y) != 0) - return -1014; + return -7013; if (XMEMCMP(ss, sharedB, y)) - return -1015; + return -7014; /* test swaping roles of keys and generating same shared key */ XMEMSET(sharedB, 0, sizeof(sharedB)); y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1016; + return -7015; if (XMEMCMP(ss, sharedB, y)) - return -1017; + return -7016; /* test with 1 generated key and 1 from known test vector */ if (wc_curve25519_import_private_raw(sa, sizeof(sa), pa, sizeof(pa), &userA) != 0) - return -1018; + return -7017; if (wc_curve25519_make_key(&rng, 32, &userB) != 0) - return -1019; + return -7018; x = sizeof(sharedA); if (wc_curve25519_shared_secret(&userA, &userB, sharedA, &x) != 0) - return -1020; + return -7019; y = sizeof(sharedB); if (wc_curve25519_shared_secret(&userB, &userA, sharedB, &y) != 0) - return -1021; + return -7020; /* compare shared secret keys to test they are the same */ if (y != x) - return -1022; + return -7021; if (XMEMCMP(sharedA, sharedB, x)) - return -1023; + return -7022; #endif /* HAVE_CURVE25519_SHARED_SECRET */ /* clean up keys when done */ @@ -8420,7 +11191,7 @@ int ed25519_test(void) byte exportSKey[ED25519_KEY_SIZE]; word32 exportPSz; word32 exportSSz; - int i; + int i, ret; word32 outlen; #ifdef HAVE_ED25519_VERIFY int verify; @@ -8747,7 +11518,14 @@ int ed25519_test(void) #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ /* create ed25519 keys */ - wc_InitRng(&rng); +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + return -7100; + wc_ed25519_init(&key); wc_ed25519_init(&key2); wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key); @@ -8765,57 +11543,57 @@ int ed25519_test(void) if (wc_ed25519_import_private_key(sKeys[i], ED25519_KEY_SIZE, pKeys[i], pKeySz[i], &key) != 0) - return -1021 - i; + return -7101 - i; if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key) != 0) - return -1027 - i; + return -7111 - i; if (XMEMCMP(out, sigs[i], 64)) - return -1033 - i; + return -7121 - i; #if defined(HAVE_ED25519_VERIFY) /* test verify on good msg */ if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key) != 0 || verify != 1) - return -1039 - i; + return -7131 - i; /* test verify on bad msg */ out[outlen-1] = out[outlen-1] + 1; if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key) == 0 || verify == 1) - return -1045 - i; + return -7141 - i; #endif /* HAVE_ED25519_VERIFY */ /* test api for import/exporting keys */ exportPSz = sizeof(exportPKey); exportSSz = sizeof(exportSKey); if (wc_ed25519_export_public(&key, exportPKey, &exportPSz) != 0) - return -1051 - i; + return -7151 - i; if (wc_ed25519_import_public(exportPKey, exportPSz, &key2) != 0) - return -1057 - i; + return -7161 - i; if (wc_ed25519_export_private_only(&key, exportSKey, &exportSSz) != 0) - return -1063 - i; + return -7171 - i; if (wc_ed25519_import_private_key(exportSKey, exportSSz, exportPKey, exportPSz, &key2) != 0) - return -1069 - i; + return -7181 - i; /* clear "out" buffer and test sign with imported keys */ outlen = sizeof(out); XMEMSET(out, 0, sizeof(out)); if (wc_ed25519_sign_msg(msgs[i], msgSz[i], out, &outlen, &key2) != 0) - return -1075 - i; + return -7191 - i; #if defined(HAVE_ED25519_VERIFY) if (wc_ed25519_verify_msg(out, outlen, msgs[i], msgSz[i], &verify, &key2) != 0 || verify != 1) - return -1081 - i; + return -7201 - i; if (XMEMCMP(out, sigs[i], 64)) - return -1087 - i; + return -7211 - i; #endif /* HAVE_ED25519_VERIFY */ } #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ @@ -8838,7 +11616,7 @@ int ed25519_test(void) #if defined(WOLFSSL_CMAC) && !defined(NO_AES) - + typedef struct CMAC_Test_Case { int type; int partial; @@ -8989,202 +11767,760 @@ int cmac_test(void) XMEMSET(tag, 0, sizeof(tag)); tagSz = AES_BLOCK_SIZE; if (wc_InitCmac(&cmac, tc->k, tc->kSz, tc->type, NULL) != 0) - return -4033; + return -7300; if (tc->partial) { if (wc_CmacUpdate(&cmac, tc->m, tc->mSz/2 - tc->partial) != 0) - return -4034; + return -7301; if (wc_CmacUpdate(&cmac, tc->m + tc->mSz/2 - tc->partial, tc->mSz/2 + tc->partial) != 0) - return -4035; + return -7302; } else { if (wc_CmacUpdate(&cmac, tc->m, tc->mSz) != 0) - return -4034; + return -7303; } if (wc_CmacFinal(&cmac, tag, &tagSz) != 0) - return -4036; + return -7304; if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) - return -4037; + return -7305; + + XMEMSET(tag, 0, sizeof(tag)); + tagSz = sizeof(tag); + if (wc_AesCmacGenerate(tag, &tagSz, tc->m, tc->mSz, + tc->k, tc->kSz) != 0) + return -7306; + if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) + return -7307; + if (wc_AesCmacVerify(tc->t, tc->tSz, tc->m, tc->mSz, + tc->k, tc->kSz) != 0) + return -7308; + } + + return 0; +} + +#endif /* NO_AES && WOLFSSL_CMAC */ + +#ifdef HAVE_LIBZ + +const byte sample_text[] = + "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n" + "polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n" + "marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n" + "plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\n" + "selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\n" + "small batch meggings kogi dolore food truck bespoke gastropub.\n" + "\n" + "Terry richardson adipisicing actually typewriter tumblr, twee whatever\n" + "four loko you probably haven't heard of them high life. Messenger bag\n" + "whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\n" + "et, banksy ullamco messenger bag umami pariatur direct trade forage.\n" + "Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\n" + "food truck next level, tousled irony non semiotics PBR ethical anim cred\n" + "readymade. Mumblecore brunch lomo odd future, portland organic terry\n" + "richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\n" + "mixtape polaroid, pork belly readymade organic cray typewriter helvetica\n" + "four loko whatever street art yr farm-to-table.\n" + "\n" + "Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\n" + "pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\n" + "et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\n" + "nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\n" + "seitan fingerstache kale chips. Terry richardson artisan williamsburg,\n" + "eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\n" + "readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\n" + "ethnic art party qui letterpress nisi proident jean shorts mlkshk\n" + "locavore.\n" + "\n" + "Narwhal flexitarian letterpress, do gluten-free voluptate next level\n" + "banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\n" + "cillum pickled velit, YOLO officia you probably haven't heard of them\n" + "trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\n" + "small batch american apparel. Put a bird on it cosby sweater before they\n" + "sold out pork belly kogi hella. Street art mollit sustainable polaroid,\n" + "DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\n" + "Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\n" + "excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\n" + "neutra PBR selvage.\n" + "\n" + "Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\n" + "next level jean shorts exercitation. Hashtag keytar whatever, nihil\n" + "authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\n" + "wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\n" + "tattooed. Labore high life commodo, meggings raw denim fingerstache pug\n" + "trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\n" + "incididunt flannel sustainable helvetica pork belly pug banksy you\n" + "probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\n" + "mollit magna, sriracha sartorial helvetica.\n" + "\n" + "Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\n" + "ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\n" + "of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\n" + "reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\n" + "skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\n" + "organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\n" + "Veniam sunt food truck leggings, sint vinyl fap.\n" + "\n" + "Hella dolore pork belly, truffaut carles you probably haven't heard of\n" + "them PBR helvetica in sapiente. Fashion axe ugh bushwick american\n" + "apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\n" + "flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\n" + "letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\n" + "Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\n" + "delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\n" + "magna pop-up literally. Swag thundercats ennui shoreditch vegan\n" + "pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\n" + "\n" + "Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\n" + "meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\n" + "dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\n" + "locavore kale chips. Sriracha swag thundercats, chillwave disrupt\n" + "tousled beard mollit mustache leggings portland next level. Nihil esse\n" + "est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\n" + "swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n" + "bag dolor terry richardson sapiente.\n"; + + +int compress_test(void) +{ + int ret = 0; + word32 dSz = sizeof(sample_text); + word32 cSz = (dSz + (word32)(dSz * 0.001) + 12); + byte *c = NULL; + byte *d = NULL; + + c = XMALLOC(cSz * sizeof(byte), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + d = XMALLOC(dSz * sizeof(byte), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + /* follow calloc and initialize to 0 */ + XMEMSET(c, 0, cSz); + XMEMSET(d, 0, dSz); + + if (c == NULL || d == NULL) + ret = -7400; + + if (ret == 0 && (ret = wc_Compress(c, cSz, sample_text, dSz, 0)) < 0) + ret = -7401; + + if (ret > 0) { + cSz = (word32)ret; + ret = 0; + } + + if (ret == 0 && wc_DeCompress(d, dSz, c, cSz) != (int)dSz) + ret = -7402; + + if (ret == 0 && XMEMCMP(d, sample_text, dSz)) + ret = -7403; + + if (c) XFREE(c, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (d) XFREE(d, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +#endif /* HAVE_LIBZ */ + +#ifdef HAVE_PKCS7 + +/* External Debugging/Testing Note: + * + * PKCS#7 test functions can output generated PKCS#7/CMS bundles for + * additional testing. To dump bundles to files DER encoded files, please + * define: + * + * #define PKCS7_OUTPUT_TEST_BUNDLES + */ + + +/* Loads certs and keys for use with PKCS7 tests, from either files + * or buffers. + * + * rsaCert - output buffer for RSA cert + * rsaCertSz - IN/OUT size of output buffer, size of RSA cert + * rsaPrivKey - output buffer for RSA private key + * rsaPrivKeySz - IN/OUT size of output buffer, size of RSA key + * eccCert - output buffer for ECC cert + * eccCertSz - IN/OUT size of output buffer, size of ECC cert + * eccPrivKey - output buffer for ECC private key + * eccPrivKeySz - IN/OUT size of output buffer, size of ECC private key + * + * Returns 0 on success, negative on error + */ +static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz, + byte* rsaPrivKey, word32* rsaPrivKeySz, + byte* eccCert, word32* eccCertSz, + byte* eccPrivKey, word32* eccPrivKeySz) +{ +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + FILE* certFile; + FILE* keyFile; +#endif + +#ifndef NO_RSA + if (rsaCert == NULL || rsaCertSz == NULL || + rsaPrivKey == NULL || rsaPrivKeySz == NULL) + return BAD_FUNC_ARG; +#endif + +#ifdef HAVE_ECC + if (eccCert == NULL || eccCertSz == NULL || + eccPrivKey == NULL || eccPrivKeySz == NULL) + return BAD_FUNC_ARG; +#endif + +/* RSA */ +#ifndef NO_RSA + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaCertSz < (word32)sizeof_client_cert_der_1024) + return -7410; + + XMEMCPY(rsaCert, client_cert_der_1024, sizeof_client_cert_der_1024); + *rsaCertSz = sizeof_client_cert_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaCertSz < (word32)sizeof_client_cert_der_2048) + return -7411; + + XMEMCPY(rsaCert, client_cert_der_2048, sizeof_client_cert_der_2048); + *rsaCertSz = sizeof_client_cert_der_2048; +#else + certFile = fopen(clientCert, "rb"); + if (!certFile) + return -7412; + + *rsaCertSz = (word32)fread(rsaCert, 1, *rsaCertSz, certFile); + fclose(certFile); +#endif + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaPrivKeySz < (word32)sizeof_client_key_der_1024) + return -7413; + + XMEMCPY(rsaPrivKey, client_key_der_1024, sizeof_client_key_der_1024); + *rsaPrivKeySz = sizeof_client_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaPrivKeySz < (word32)sizeof_client_key_der_2048) + return -7414; + + XMEMCPY(rsaPrivKey, client_key_der_2048, sizeof_client_key_der_2048); + *rsaPrivKeySz = sizeof_client_key_der_2048; +#else + keyFile = fopen(clientKey, "rb"); + if (!keyFile) + return -7415; + + *rsaPrivKeySz = (word32)fread(rsaPrivKey, 1, *rsaPrivKeySz, keyFile); + fclose(keyFile); +#endif /* USE_CERT_BUFFERS */ + +#endif /* NO_RSA */ + +/* ECC */ +#ifdef HAVE_ECC + +#ifdef USE_CERT_BUFFERS_256 + if (*eccCertSz < (word32)sizeof_cliecc_cert_der_256) + return -7416; + + XMEMCPY(eccCert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + *eccCertSz = sizeof_cliecc_cert_der_256; +#else + certFile = fopen(eccClientCert, "rb"); + if (!certFile) + return -7417; + + *eccCertSz = (word32)fread(eccCert, 1, *eccCertSz, certFile); + fclose(certFile); +#endif /* USE_CERT_BUFFERS_256 */ + +#ifdef USE_CERT_BUFFERS_256 + if (*eccPrivKeySz < (word32)sizeof_ecc_clikey_der_256) + return -7418; + + XMEMCPY(eccPrivKey, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + *eccPrivKeySz = sizeof_ecc_clikey_der_256; +#else + keyFile = fopen(eccClientKey, "rb"); + if (!keyFile) + return -7419; + + *eccPrivKeySz = (word32)fread(eccPrivKey, 1, *eccPrivKeySz, keyFile); + fclose(keyFile); +#endif /* USE_CERT_BUFFERS_256 */ +#endif /* HAVE_ECC */ + + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + return 0; +} + + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + int keyWrapOID; + int keyAgreeOID; + byte* cert; + size_t certSz; + byte* privateKey; + word32 privateKeySz; + byte* optionalUkm; + word32 optionalUkmSz; + const char* outFileName; +} pkcs7EnvelopedVector; + + +static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) +{ + int ret, testSz, i; + int envelopedSz, decodedSz; + + byte enveloped[2048]; + byte decoded[2048]; + PKCS7 pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + FILE* pkcs7File; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + +#if !defined(NO_AES) && defined(HAVE_ECC) + byte optionalUkm[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; +#endif /* NO_AES */ + + const pkcs7EnvelopedVector testVectors[] = + { + /* key transport key encryption technique */ +#ifndef NO_RSA + {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataDES3.der"}, + + #ifndef NO_AES + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES128CBC.der"}, + + {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES192CBC.der"}, + + {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES256CBC.der"}, + #endif /* NO_AES */ +#endif + + /* key agreement key encryption technique*/ +#ifdef HAVE_ECC + #ifndef NO_AES + #ifndef NO_SHA + {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, + dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, + "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, + #endif + + #ifndef NO_SHA256 + {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, + "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, + #endif /* NO_SHA256 */ + + #ifdef WOLFSSL_SHA512 + {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, + "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, + + /* with optional user keying material (ukm) */ + {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, optionalUkm, sizeof(optionalUkm), + "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, + #endif /* WOLFSSL_SHA512 */ + #endif /* NO_AES */ +#endif + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); + + for (i = 0; i < testSz; i++) { + + ret = wc_PKCS7_InitWithCert(&pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + if (ret != 0) + return -7420; + + pkcs7.content = (byte*)testVectors[i].content; + pkcs7.contentSz = testVectors[i].contentSz; + pkcs7.contentOID = testVectors[i].contentOID; + pkcs7.encryptOID = testVectors[i].encryptOID; + pkcs7.keyWrapOID = testVectors[i].keyWrapOID; + pkcs7.keyAgreeOID = testVectors[i].keyAgreeOID; + pkcs7.privateKey = testVectors[i].privateKey; + pkcs7.privateKeySz = testVectors[i].privateKeySz; + pkcs7.ukm = testVectors[i].optionalUkm; + pkcs7.ukmSz = testVectors[i].optionalUkmSz; + + /* encode envelopedData */ + envelopedSz = wc_PKCS7_EncodeEnvelopedData(&pkcs7, enveloped, + sizeof(enveloped)); + if (envelopedSz <= 0) { + printf("DEBUG: i = %d, envelopedSz = %d\n", i, envelopedSz); + return -7421; + } + + /* decode envelopedData */ + decodedSz = wc_PKCS7_DecodeEnvelopedData(&pkcs7, enveloped, envelopedSz, + decoded, sizeof(decoded)); + if (decodedSz <= 0) + return -7422; + + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) + return -7423; + +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 envelopedData for external testing */ + pkcs7File = fopen(testVectors[i].outFileName, "wb"); + if (!pkcs7File) + return -7424; + + ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); + fclose(pkcs7File); + if (ret != envelopedSz) { + return -7425; + } +#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(&pkcs7); + } + + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + return 0; +} + + +int pkcs7enveloped_test(void) +{ + int ret = 0; + + byte* rsaCert = NULL; + byte* eccCert = NULL; + byte* rsaPrivKey = NULL; + byte* eccPrivKey = NULL; + + word32 rsaCertSz = 0; + word32 eccCertSz = 0; + word32 rsaPrivKeySz = 0; + word32 eccPrivKeySz = 0; + +#ifndef NO_RSA + /* read client RSA cert and key in DER format */ + rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaCert == NULL) + return -7500; + + rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7501; + } + + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + /* read client ECC cert and key in DER format */ + eccCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccCert == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7504; + } + + eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7505; + } + + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ + + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + if (ret < 0) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + byte* encryptionKey; + word32 encryptionKeySz; + PKCS7Attrib* attribs; + word32 attribsSz; + const char* outFileName; +} pkcs7EncryptedVector; + + +int pkcs7encrypted_test(void) +{ + int ret = 0; + int i, testSz; + int encryptedSz, decodedSz, attribIdx; + PKCS7 pkcs7; + byte encrypted[2048]; + byte decoded[2048]; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + FILE* pkcs7File; +#endif + + PKCS7Attrib* expectedAttrib; + PKCS7DecodedAttrib* decodedAttrib; + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + +#ifndef NO_DES3 + byte desKey[] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef + }; + byte des3Key[] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 + }; +#endif + +#ifndef NO_AES + byte aes128Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; + byte aes192Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; + byte aes256Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; + + /* Attribute example from RFC 4134, Section 7.2 + * OID = 1.2.5555 + * OCTET STRING = 'This is a test General ASN Attribute, number 1.' */ + static byte genAttrOid[] = { 0x06, 0x03, 0x2a, 0xab, 0x33 }; + static byte genAttr[] = { 0x04, 47, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41, + 0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x31, 0x2e }; + + static byte genAttrOid2[] = { 0x06, 0x03, 0x2a, 0xab, 0x34 }; + static byte genAttr2[] = { 0x04, 47, + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41, + 0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x20, 0x32, 0x2e }; + + PKCS7Attrib attribs[] = + { + { genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) } + }; + + PKCS7Attrib multiAttribs[] = + { + { genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) }, + { genAttrOid2, sizeof(genAttrOid2), genAttr2, sizeof(genAttr2) } + }; +#endif /* NO_AES */ + + const pkcs7EncryptedVector testVectors[] = + { +#ifndef NO_DES3 + {data, (word32)sizeof(data), DATA, DES3b, des3Key, sizeof(des3Key), + NULL, 0, "pkcs7encryptedDataDES3.der"}, + + {data, (word32)sizeof(data), DATA, DESb, desKey, sizeof(desKey), + NULL, 0, "pkcs7encryptedDataDES.der"}, +#endif /* NO_DES3 */ + +#ifndef NO_AES + {data, (word32)sizeof(data), DATA, AES128CBCb, aes128Key, + sizeof(aes128Key), NULL, 0, "pkcs7encryptedDataAES128CBC.der"}, - XMEMSET(tag, 0, sizeof(tag)); - tagSz = sizeof(tag); - if (wc_AesCmacGenerate(tag, &tagSz, tc->m, tc->mSz, - tc->k, tc->kSz) != 0) - return -4038; - if (XMEMCMP(tag, tc->t, AES_BLOCK_SIZE) != 0) - return -4039; - if (wc_AesCmacVerify(tc->t, tc->tSz, tc->m, tc->mSz, - tc->k, tc->kSz) != 0) - return -4040; - } + {data, (word32)sizeof(data), DATA, AES192CBCb, aes192Key, + sizeof(aes192Key), NULL, 0, "pkcs7encryptedDataAES192CBC.der"}, - return 0; -} + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), NULL, 0, "pkcs7encryptedDataAES256CBC.der"}, -#endif /* NO_AES && WOLFSSL_CMAC */ + /* test with optional unprotected attributes */ + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7encryptedDataAES256CBC_attribs.der"}, -#ifdef HAVE_LIBZ + /* test with multiple optional unprotected attributes */ + {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), multiAttribs, + (sizeof(multiAttribs)/sizeof(PKCS7Attrib)), + "pkcs7encryptedDataAES256CBC_multi_attribs.der"}, +#endif /* NO_AES */ + }; -const byte sample_text[] = - "Biodiesel cupidatat marfa, cliche aute put a bird on it incididunt elit\n" - "polaroid. Sunt tattooed bespoke reprehenderit. Sint twee organic id\n" - "marfa. Commodo veniam ad esse gastropub. 3 wolf moon sartorial vero,\n" - "plaid delectus biodiesel squid +1 vice. Post-ironic keffiyeh leggings\n" - "selfies cray fap hoodie, forage anim. Carles cupidatat shoreditch, VHS\n" - "small batch meggings kogi dolore food truck bespoke gastropub.\n" - "\n" - "Terry richardson adipisicing actually typewriter tumblr, twee whatever\n" - "four loko you probably haven't heard of them high life. Messenger bag\n" - "whatever tattooed deep v mlkshk. Brooklyn pinterest assumenda chillwave\n" - "et, banksy ullamco messenger bag umami pariatur direct trade forage.\n" - "Typewriter culpa try-hard, pariatur sint brooklyn meggings. Gentrify\n" - "food truck next level, tousled irony non semiotics PBR ethical anim cred\n" - "readymade. Mumblecore brunch lomo odd future, portland organic terry\n" - "richardson elit leggings adipisicing ennui raw denim banjo hella. Godard\n" - "mixtape polaroid, pork belly readymade organic cray typewriter helvetica\n" - "four loko whatever street art yr farm-to-table.\n" - "\n" - "Vinyl keytar vice tofu. Locavore you probably haven't heard of them pug\n" - "pickled, hella tonx labore truffaut DIY mlkshk elit cosby sweater sint\n" - "et mumblecore. Elit swag semiotics, reprehenderit DIY sartorial nisi ugh\n" - "nesciunt pug pork belly wayfarers selfies delectus. Ethical hoodie\n" - "seitan fingerstache kale chips. Terry richardson artisan williamsburg,\n" - "eiusmod fanny pack irony tonx ennui lo-fi incididunt tofu YOLO\n" - "readymade. 8-bit sed ethnic beard officia. Pour-over iphone DIY butcher,\n" - "ethnic art party qui letterpress nisi proident jean shorts mlkshk\n" - "locavore.\n" - "\n" - "Narwhal flexitarian letterpress, do gluten-free voluptate next level\n" - "banh mi tonx incididunt carles DIY. Odd future nulla 8-bit beard ut\n" - "cillum pickled velit, YOLO officia you probably haven't heard of them\n" - "trust fund gastropub. Nisi adipisicing tattooed, Austin mlkshk 90's\n" - "small batch american apparel. Put a bird on it cosby sweater before they\n" - "sold out pork belly kogi hella. Street art mollit sustainable polaroid,\n" - "DIY ethnic ea pug beard dreamcatcher cosby sweater magna scenester nisi.\n" - "Sed pork belly skateboard mollit, labore proident eiusmod. Sriracha\n" - "excepteur cosby sweater, anim deserunt laborum eu aliquip ethical et\n" - "neutra PBR selvage.\n" - "\n" - "Raw denim pork belly truffaut, irony plaid sustainable put a bird on it\n" - "next level jean shorts exercitation. Hashtag keytar whatever, nihil\n" - "authentic aliquip disrupt laborum. Tattooed selfies deserunt trust fund\n" - "wayfarers. 3 wolf moon synth church-key sartorial, gastropub leggings\n" - "tattooed. Labore high life commodo, meggings raw denim fingerstache pug\n" - "trust fund leggings seitan forage. Nostrud ullamco duis, reprehenderit\n" - "incididunt flannel sustainable helvetica pork belly pug banksy you\n" - "probably haven't heard of them nesciunt farm-to-table. Disrupt nostrud\n" - "mollit magna, sriracha sartorial helvetica.\n" - "\n" - "Nulla kogi reprehenderit, skateboard sustainable duis adipisicing viral\n" - "ad fanny pack salvia. Fanny pack trust fund you probably haven't heard\n" - "of them YOLO vice nihil. Keffiyeh cray lo-fi pinterest cardigan aliqua,\n" - "reprehenderit aute. Culpa tousled williamsburg, marfa lomo actually anim\n" - "skateboard. Iphone aliqua ugh, semiotics pariatur vero readymade\n" - "organic. Marfa squid nulla, in laborum disrupt laboris irure gastropub.\n" - "Veniam sunt food truck leggings, sint vinyl fap.\n" - "\n" - "Hella dolore pork belly, truffaut carles you probably haven't heard of\n" - "them PBR helvetica in sapiente. Fashion axe ugh bushwick american\n" - "apparel. Fingerstache sed iphone, jean shorts blue bottle nisi bushwick\n" - "flexitarian officia veniam plaid bespoke fap YOLO lo-fi. Blog\n" - "letterpress mumblecore, food truck id cray brooklyn cillum ad sed.\n" - "Assumenda chambray wayfarers vinyl mixtape sustainable. VHS vinyl\n" - "delectus, culpa williamsburg polaroid cliche swag church-key synth kogi\n" - "magna pop-up literally. Swag thundercats ennui shoreditch vegan\n" - "pitchfork neutra truffaut etsy, sed single-origin coffee craft beer.\n" - "\n" - "Odio letterpress brooklyn elit. Nulla single-origin coffee in occaecat\n" - "meggings. Irony meggings 8-bit, chillwave lo-fi adipisicing cred\n" - "dreamcatcher veniam. Put a bird on it irony umami, trust fund bushwick\n" - "locavore kale chips. Sriracha swag thundercats, chillwave disrupt\n" - "tousled beard mollit mustache leggings portland next level. Nihil esse\n" - "est, skateboard art party etsy thundercats sed dreamcatcher ut iphone\n" - "swag consectetur et. Irure skateboard banjo, nulla deserunt messenger\n" - "bag dolor terry richardson sapiente.\n"; + testSz = sizeof(testVectors) / sizeof(pkcs7EncryptedVector); + for (i = 0; i < testSz; i++) { + pkcs7.content = (byte*)testVectors[i].content; + pkcs7.contentSz = testVectors[i].contentSz; + pkcs7.contentOID = testVectors[i].contentOID; + pkcs7.encryptOID = testVectors[i].encryptOID; + pkcs7.encryptionKey = testVectors[i].encryptionKey; + pkcs7.encryptionKeySz = testVectors[i].encryptionKeySz; + pkcs7.unprotectedAttribs = testVectors[i].attribs; + pkcs7.unprotectedAttribsSz = testVectors[i].attribsSz; -int compress_test(void) -{ - int ret = 0; - word32 dSz = sizeof(sample_text); - word32 cSz = (dSz + (word32)(dSz * 0.001) + 12); - byte *c = NULL; - byte *d = NULL; + /* encode encryptedData */ + encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + sizeof(encrypted)); + if (encryptedSz <= 0) + return -7600; - c = XMALLOC(cSz * sizeof(byte), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - d = XMALLOC(dSz * sizeof(byte), HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + /* decode encryptedData */ + decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, + decoded, sizeof(decoded)); + if (decodedSz <= 0) + return -7601; - /* follow calloc and initialize to 0 */ - XMEMSET(c, 0, cSz); - XMEMSET(d, 0, dSz); + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) + return -7602; - if (c == NULL || d == NULL) - ret = -300; + /* verify decoded unprotected attributes */ + if (pkcs7.decodedAttrib != NULL) { + decodedAttrib = pkcs7.decodedAttrib; + attribIdx = 1; - if (ret == 0 && (ret = wc_Compress(c, cSz, sample_text, dSz, 0)) < 0) - ret = -301; + while (decodedAttrib != NULL) { - if (ret > 0) { - cSz = (word32)ret; - ret = 0; - } + /* expected attribute, stored list is reversed */ + expectedAttrib = &(pkcs7.unprotectedAttribs + [pkcs7.unprotectedAttribsSz - attribIdx]); - if (ret == 0 && wc_DeCompress(d, dSz, c, cSz) != (int)dSz) - ret = -302; + /* verify oid */ + if (XMEMCMP(decodedAttrib->oid, expectedAttrib->oid, + decodedAttrib->oidSz) != 0) + return -7603; - if (ret == 0 && XMEMCMP(d, sample_text, dSz)) - ret = -303; + /* verify value */ + if (XMEMCMP(decodedAttrib->value, expectedAttrib->value, + decodedAttrib->valueSz) != 0) + return -7604; - if (c) XFREE(c, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (d) XFREE(d, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + decodedAttrib = decodedAttrib->next; + attribIdx++; + } + } - return ret; -} +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 envelopedData for external testing */ + pkcs7File = fopen(testVectors[i].outFileName, "wb"); + if (!pkcs7File) + return -7605; -#endif /* HAVE_LIBZ */ + ret = (int)fwrite(encrypted, encryptedSz, 1, pkcs7File); + fclose(pkcs7File); -#ifdef HAVE_PKCS7 + if (ret > 0) + ret = 0; +#endif + + wc_PKCS7_Free(&pkcs7); + } + + return ret; +} -/* External Debugging/Testing Note: - * - * PKCS#7 test functions can output generated PKCS#7/CMS bundles for - * additional testing. To dump bundles to files DER encoded files, please - * define: - * - * #define PKCS7_OUTPUT_TEST_BUNDLES - */ typedef struct { const byte* content; word32 contentSz; - int contentOID; + int hashOID; int encryptOID; - int keyWrapOID; - int keyAgreeOID; - byte* cert; - size_t certSz; byte* privateKey; word32 privateKeySz; - byte* optionalUkm; - word32 optionalUkmSz; + byte* cert; + size_t certSz; + PKCS7Attrib* signedAttribs; + word32 signedAttribsSz; const char* outFileName; -} pkcs7EnvelopedVector; +} pkcs7SignedVector; -static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, - byte* rsaPrivKey, word32 rsaPrivKeySz, - byte* eccCert, word32 eccCertSz, - byte* eccPrivKey, word32 eccPrivKeySz) +static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) { int ret, testSz, i; - int envelopedSz, decodedSz; - - byte enveloped[2048]; - byte decoded[2048]; + int encodedSz; + byte* out; + word32 outSz; + WC_RNG rng; PKCS7 pkcs7; #ifdef PKCS7_OUTPUT_TEST_BUNDLES - FILE* pkcs7File; + FILE* file; #endif const byte data[] = { /* Hello World */ @@ -9192,124 +12528,249 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, 0x72,0x6c,0x64 }; -#ifndef NO_AES - byte optionalUkm[] = { - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + static byte transIdOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x07 }; + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte senderNonceOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x05 }; + static byte transId[(SHA_DIGEST_SIZE + 1) * 2 + 1]; + static byte messageType[] = { 0x13, 2, '1', '9' }; + static byte senderNonce[PKCS7_NONCE_SZ + 2]; + + PKCS7Attrib attribs[] = + { + { transIdOid, sizeof(transIdOid), + transId, sizeof(transId) - 1 }, /* take off the null */ + { messageTypeOid, sizeof(messageTypeOid), + messageType, sizeof(messageType) }, + { senderNonceOid, sizeof(senderNonceOid), + senderNonce, sizeof(senderNonce) } }; -#endif /* NO_AES */ - const pkcs7EnvelopedVector testVectors[] = + const pkcs7SignedVector testVectors[] = { - /* key transport key encryption technique */ #ifndef NO_RSA - {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataDES3.der"}, - - #ifndef NO_AES - {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES128CBC.der"}, - - {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES192CBC.der"}, - - {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES256CBC.der"}, - #endif /* NO_AES */ -#endif + #ifndef NO_SHA + /* RSA with SHA */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA.der"}, + + /* RSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, NULL, 0, + "pkcs7signedData_RSA_SHA_noattr.der"}, + #endif + #ifdef WOLFSSL_SHA224 + /* RSA with SHA224 */ + {data, (word32)sizeof(data), SHA224h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA224.der"}, + #endif + #ifndef NO_SHA256 + /* RSA with SHA256 */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256.der"}, + #endif + #if defined(WOLFSSL_SHA384) + /* RSA with SHA384 */ + {data, (word32)sizeof(data), SHA384h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA384.der"}, + #endif + #if defined(WOLFSSL_SHA512) + /* RSA with SHA512 */ + {data, (word32)sizeof(data), SHA512h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA512.der"}, + #endif +#endif /* NO_RSA */ - /* key agreement key encryption technique*/ #ifdef HAVE_ECC - #ifndef NO_AES - #ifndef NO_SHA - {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, - dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, - "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, - #endif + #ifndef NO_SHA + /* ECDSA with SHA */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA.der"}, + + /* ECDSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, NULL, 0, + "pkcs7signedData_ECDSA_SHA_noattr.der"}, + #endif + #ifdef WOLFSSL_SHA224 + /* ECDSA with SHA224 */ + {data, (word32)sizeof(data), SHA224h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA224.der"}, + #endif + #ifndef NO_SHA256 + /* ECDSA with SHA256 */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256.der"}, + #endif + #ifdef WOLFSSL_SHA384 + /* ECDSA with SHA384 */ + {data, (word32)sizeof(data), SHA384h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA384.der"}, + #endif + #ifdef WOLFSSL_SHA512 + /* ECDSA with SHA512 */ + {data, (word32)sizeof(data), SHA512h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA512.der"}, + #endif +#endif /* HAVE_ECC */ + }; - #ifndef NO_SHA256 - {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, - dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, - "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, - #endif /* NO_SHA256 */ + testSz = sizeof(testVectors) / sizeof(pkcs7SignedVector); - #ifdef WOLFSSL_SHA512 - {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, - dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, - "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, + outSz = FOURK_BUF; + out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (out == NULL) + return -7700; - /* with optional user keying material (ukm) */ - {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, - dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, optionalUkm, sizeof(optionalUkm), - "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, - #endif /* WOLFSSL_SHA512 */ - #endif /* NO_AES */ +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); #endif - }; - - testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7701; + } for (i = 0; i < testSz; i++) { ret = wc_PKCS7_InitWithCert(&pkcs7, testVectors[i].cert, (word32)testVectors[i].certSz); + if (ret != 0) - return -209; + return -7702; + + pkcs7.rng = &rng; + pkcs7.content = (byte*)testVectors[i].content; + pkcs7.contentSz = testVectors[i].contentSz; + pkcs7.hashOID = testVectors[i].hashOID; + pkcs7.encryptOID = testVectors[i].encryptOID; + pkcs7.privateKey = testVectors[i].privateKey; + pkcs7.privateKeySz = testVectors[i].privateKeySz; + pkcs7.signedAttribs = testVectors[i].signedAttribs; + pkcs7.signedAttribsSz = testVectors[i].signedAttribsSz; + + /* generate senderNonce */ + { + senderNonce[0] = 0x04; + senderNonce[1] = PKCS7_NONCE_SZ; - pkcs7.content = (byte*)testVectors[i].content; - pkcs7.contentSz = testVectors[i].contentSz; - pkcs7.contentOID = testVectors[i].contentOID; - pkcs7.encryptOID = testVectors[i].encryptOID; - pkcs7.keyWrapOID = testVectors[i].keyWrapOID; - pkcs7.keyAgreeOID = testVectors[i].keyAgreeOID; - pkcs7.privateKey = testVectors[i].privateKey; - pkcs7.privateKeySz = testVectors[i].privateKeySz; - pkcs7.ukm = testVectors[i].optionalUkm; - pkcs7.ukmSz = testVectors[i].optionalUkmSz; + ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7703; + } + } - /* encode envelopedData */ - envelopedSz = wc_PKCS7_EncodeEnvelopedData(&pkcs7, enveloped, - sizeof(enveloped)); - if (envelopedSz <= 0) { - printf("DEBUG: i = %d, envelopedSz = %d\n", i, envelopedSz); - return -210; + /* generate trans ID */ + { + Sha sha; + byte digest[SHA_DIGEST_SIZE]; + int j,k; + + transId[0] = 0x13; + transId[1] = SHA_DIGEST_SIZE * 2; + + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7704; + } + wc_ShaUpdate(&sha, pkcs7.publicKey, pkcs7.publicKeySz); + wc_ShaFinal(&sha, digest); + wc_ShaFree(&sha); + + for (j = 0, k = 2; j < SHA_DIGEST_SIZE; j++, k += 2) { + snprintf((char*)&transId[k], 3, "%02x", digest[j]); + } } - /* decode envelopedData */ - decodedSz = wc_PKCS7_DecodeEnvelopedData(&pkcs7, enveloped, envelopedSz, - decoded, sizeof(decoded)); - if (decodedSz <= 0) - return -211; + encodedSz = wc_PKCS7_EncodeSignedData(&pkcs7, out, outSz); + if (encodedSz < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7705; + } - /* test decode result */ - if (XMEMCMP(decoded, data, sizeof(data)) != 0) - return -212; + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* write PKCS#7 to output file for more testing */ + file = fopen(testVectors[i].outFileName, "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7706; + } + ret = (int)fwrite(out, 1, encodedSz, file); + fclose(file); + if (ret != (int)encodedSz) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7707; + } + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - /* output pkcs7 envelopedData for external testing */ - pkcs7File = fopen(testVectors[i].outFileName, "wb"); - if (!pkcs7File) - return -213; + wc_PKCS7_Free(&pkcs7); + wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); - ret = (int)fwrite(enveloped, envelopedSz, 1, pkcs7File); - fclose(pkcs7File); -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + ret = wc_PKCS7_VerifySignedData(&pkcs7, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7708; + } + + if (pkcs7.singleCert == NULL || pkcs7.singleCertSz == 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7709; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + file = fopen("./pkcs7cert.der", "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -7710; + } + ret = (int)fwrite(pkcs7.singleCert, 1, pkcs7.singleCertSz, file); + fclose(file); + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ wc_PKCS7_Free(&pkcs7); } + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRng(&rng); + + if (ret > 0) + return 0; + (void)eccCert; (void)eccCertSz; (void)eccPrivKey; (void)eccPrivKeySz; - return 0; + return ret; } -int pkcs7enveloped_test(void) +int pkcs7signed_test(void) { int ret = 0; @@ -9318,49 +12779,25 @@ int pkcs7enveloped_test(void) byte* rsaPrivKey = NULL; byte* eccPrivKey = NULL; - size_t rsaCertSz = 0; - size_t eccCertSz = 0; - size_t rsaPrivKeySz = 0; - size_t eccPrivKeySz = 0; - - FILE* certFile; - FILE* keyFile; + word32 rsaCertSz = 0; + word32 eccCertSz = 0; + word32 rsaPrivKeySz = 0; + word32 eccPrivKeySz = 0; #ifndef NO_RSA /* read client RSA cert and key in DER format */ rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rsaCert == NULL) - return -201; + return -7720; rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rsaPrivKey == NULL) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -202; - } - - certFile = fopen(clientCert, "rb"); - if (!certFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -42); - return -203; - } - - rsaCertSz = fread(rsaCert, 1, FOURK_BUF, certFile); - fclose(certFile); - - keyFile = fopen(clientKey, "rb"); - if (!keyFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -43); - return -204; + return -7721; } - rsaPrivKeySz = fread(rsaPrivKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; #endif /* NO_RSA */ #ifdef HAVE_ECC @@ -9369,476 +12806,386 @@ int pkcs7enveloped_test(void) if (eccCert == NULL) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -205; - } - - eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (eccPrivKey == NULL) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -206; - } - - certFile = fopen(eccClientCert, "rb"); - if (!certFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-ecc-cert.der, " - "Please run from wolfSSL home dir", -42); - return -207; - } - - eccCertSz = fread(eccCert, 1, FOURK_BUF, certFile); - fclose(certFile); - - keyFile = fopen(eccClientKey, "rb"); - if (!keyFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/ecc-client-key.der, " - "Please run from wolfSSL home dir", -43); - return -208; - } - - eccPrivKeySz = fread(eccPrivKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); -#endif /* HAVE_ECC */ - - ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, - rsaPrivKey, (word32)rsaPrivKeySz, - eccCert, (word32)eccCertSz, - eccPrivKey, (word32)eccPrivKeySz); - if (ret != 0) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } - - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - - return 0; -} - - -typedef struct { - const byte* content; - word32 contentSz; - int contentOID; - int encryptOID; - byte* encryptionKey; - word32 encryptionKeySz; - PKCS7Attrib* attribs; - word32 attribsSz; - const char* outFileName; -} pkcs7EncryptedVector; - - -int pkcs7encrypted_test(void) -{ - int ret = 0; - int i, testSz; - int encryptedSz, decodedSz, attribIdx; - PKCS7 pkcs7; - byte encrypted[2048]; - byte decoded[2048]; -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - FILE* pkcs7File; -#endif - - PKCS7Attrib* expectedAttrib; - PKCS7DecodedAttrib* decodedAttrib; - - const byte data[] = { /* Hello World */ - 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, - 0x72,0x6c,0x64 - }; - -#ifndef NO_DES3 - byte desKey[] = { - 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef - }; - byte des3Key[] = { - 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, - 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, - 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 - }; -#endif - -#ifndef NO_AES - byte aes128Key[] = { - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 - }; - byte aes192Key[] = { - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 - }; - byte aes256Key[] = { - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 - }; - - /* Attribute example from RFC 4134, Section 7.2 - * OID = 1.2.5555 - * OCTET STRING = 'This is a test General ASN Attribute, number 1.' */ - static byte genAttrOid[] = { 0x06, 0x03, 0x2a, 0xab, 0x33 }; - static byte genAttr[] = { 0x04, 47, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41, - 0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x31, 0x2e }; + return -7722; + } - static byte genAttrOid2[] = { 0x06, 0x03, 0x2a, 0xab, 0x34 }; - static byte genAttr2[] = { 0x04, 47, - 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, - 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41, - 0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x20, 0x32, 0x2e }; + eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -7723; + } - PKCS7Attrib attribs[] = - { - { genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) } - }; + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ - PKCS7Attrib multiAttribs[] = - { - { genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) }, - { genAttrOid2, sizeof(genAttrOid2), genAttr2, sizeof(genAttr2) } - }; -#endif /* NO_AES */ + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + if (ret < 0) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } - const pkcs7EncryptedVector testVectors[] = - { -#ifndef NO_DES3 - {data, (word32)sizeof(data), DATA, DES3b, des3Key, sizeof(des3Key), - NULL, 0, "pkcs7encryptedDataDES3.der"}, + ret = pkcs7signed_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); - {data, (word32)sizeof(data), DATA, DESb, desKey, sizeof(desKey), - NULL, 0, "pkcs7encryptedDataDES.der"}, -#endif /* NO_DES3 */ + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); -#ifndef NO_AES - {data, (word32)sizeof(data), DATA, AES128CBCb, aes128Key, - sizeof(aes128Key), NULL, 0, "pkcs7encryptedDataAES128CBC.der"}, + return ret; +} - {data, (word32)sizeof(data), DATA, AES192CBCb, aes192Key, - sizeof(aes192Key), NULL, 0, "pkcs7encryptedDataAES192CBC.der"}, +#endif /* HAVE_PKCS7 */ - {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, - sizeof(aes256Key), NULL, 0, "pkcs7encryptedDataAES256CBC.der"}, +#ifdef HAVE_VALGRIND +/* Need a static build to have access to symbols. */ - /* test with optional unprotected attributes */ - {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, - sizeof(aes256Key), attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7encryptedDataAES256CBC_attribs.der"}, +/* Maximum number of bytes in a number to test. */ +#define MP_MAX_TEST_BYTE_LEN 16 - /* test with multiple optional unprotected attributes */ - {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, - sizeof(aes256Key), multiAttribs, - (sizeof(multiAttribs)/sizeof(PKCS7Attrib)), - "pkcs7encryptedDataAES256CBC_multi_attribs.der"}, -#endif /* NO_AES */ - }; +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) +static int randNum(mp_int* n, int len, WC_RNG* rng, void* heap) +{ + byte d[MP_MAX_TEST_BYTE_LEN]; + int ret; - testSz = sizeof(testVectors) / sizeof(pkcs7EncryptedVector); + (void)heap; - for (i = 0; i < testSz; i++) { - pkcs7.content = (byte*)testVectors[i].content; - pkcs7.contentSz = testVectors[i].contentSz; - pkcs7.contentOID = testVectors[i].contentOID; - pkcs7.encryptOID = testVectors[i].encryptOID; - pkcs7.encryptionKey = testVectors[i].encryptionKey; - pkcs7.encryptionKeySz = testVectors[i].encryptionKeySz; - pkcs7.unprotectedAttribs = testVectors[i].attribs; - pkcs7.unprotectedAttribsSz = testVectors[i].attribsSz; + do { + ret = wc_RNG_GenerateBlock(rng, d, len); + if (ret != 0) + return ret; + ret = mp_read_unsigned_bin(n, d, len); + if (ret != 0) + return ret; + } while (mp_iszero(n)); - /* encode encryptedData */ - encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, - sizeof(encrypted)); - if (encryptedSz <= 0) - return -203; + return 0; +} +#endif - /* decode encryptedData */ - decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, - decoded, sizeof(decoded)); - if (decodedSz <= 0) - return -204; +int mp_test() +{ + WC_RNG rng; + int ret; +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + int i, j, k; +#endif + mp_int a, b, r1, r2, p; + mp_digit d; - /* test decode result */ - if (XMEMCMP(decoded, data, sizeof(data)) != 0) - return -205; + ret = mp_init_multi(&a, &b, &r1, &r2, NULL, NULL); + if (ret != 0) + return -7800; - /* verify decoded unprotected attributes */ - if (pkcs7.decodedAttrib != NULL) { - decodedAttrib = pkcs7.decodedAttrib; - attribIdx = 1; + mp_init_copy(&p, &a); - while (decodedAttrib != NULL) { +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) + goto done; - /* expected attribute, stored list is reversed */ - expectedAttrib = &(pkcs7.unprotectedAttribs - [pkcs7.unprotectedAttribsSz - attribIdx]); +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) + mp_set_int(&a, 0); + if (a.used != 0 || a.dp[0] != 0) + return -7801; - /* verify oid */ - if (XMEMCMP(decodedAttrib->oid, expectedAttrib->oid, - decodedAttrib->oidSz) != 0) - return -206; + for (j = 1; j <= MP_MAX_TEST_BYTE_LEN; j++) { + for (i = 0; i < 4 * j; i++) { + /* New values to use. */ + ret = randNum(&p, j, &rng, NULL); + if (ret != 0) + return -7802; + ret = randNum(&a, j, &rng, NULL); + if (ret != 0) + return -7803; + ret = randNum(&b, j, &rng, NULL); + if (ret != 0) + return -7804; + ret = wc_RNG_GenerateBlock(&rng, (byte*)&d, sizeof(d)); + if (ret != 0) + return -7805; + d &= MP_MASK; - /* verify value */ - if (XMEMCMP(decodedAttrib->value, expectedAttrib->value, - decodedAttrib->valueSz) != 0) - return -207; + /* Ensure sqrmod produce same result as mulmod. */ + ret = mp_sqrmod(&a, &p, &r1); + if (ret != 0) + return -7806; + ret = mp_mulmod(&a, &a, &p, &r2); + if (ret != 0) + return -7807; + if (mp_cmp(&r1, &r2) != 0) + return -7808; - decodedAttrib = decodedAttrib->next; - attribIdx++; + /* Ensure add with mod produce same result as sub with mod. */ + ret = mp_addmod(&a, &b, &p, &r1); + if (ret != 0) + return -7809; + b.sign ^= 1; + ret = mp_submod(&a, &b, &p, &r2); + if (ret != 0) + return -7810; + if (mp_cmp(&r1, &r2) != 0) + return -7811; + + /* Ensure add digit produce same result as sub digit. */ + ret = mp_add_d(&a, d, &r1); + if (ret != 0) + return -7812; + ret = mp_sub_d(&r1, d, &r2); + if (ret != 0) + return -7813; + if (mp_cmp(&a, &r2) != 0) + return -7814; + + /* Invert - if p is even it will use the slow impl. + * - if p and a are even it will fail. + */ + ret = mp_invmod(&a, &p, &r1); + if (ret != 0 && ret != MP_VAL) + return -7815; + ret = 0; + + /* Shift up and down number all bits in a digit. */ + for (k = 0; k < DIGIT_BIT; k++) { + mp_mul_2d(&a, k, &r1); + mp_div_2d(&r1, k, &r2, &p); + if (mp_cmp(&a, &r2) != 0) + return -7816; + if (!mp_iszero(&p)) + return -7817; + mp_rshb(&r1, k); + if (mp_cmp(&a, &r1) != 0) + return -7818; } } + } -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - /* output pkcs7 envelopedData for external testing */ - pkcs7File = fopen(testVectors[i].outFileName, "wb"); - if (!pkcs7File) - return -208; + /* Check that setting a 32-bit digit works. */ + d &= 0xffffffff; + mp_set_int(&a, d); + if (a.used != 1 || a.dp[0] != d) + return -7819; - ret = (int)fwrite(encrypted, encryptedSz, 1, pkcs7File); - fclose(pkcs7File); + /* Check setting a bit and testing a bit works. */ + for (i = 0; i < MP_MAX_TEST_BYTE_LEN * 8; i++) { + mp_zero(&a); + mp_set_bit(&a, i); + if (!mp_is_bit_set(&a, i)) + return -7820; + } #endif - wc_PKCS7_Free(&pkcs7); - } +done: + mp_clear(&p); + mp_clear(&r2); + mp_clear(&r1); + mp_clear(&b); + mp_clear(&a); + wc_FreeRng(&rng); + return ret; +} +#endif - if (ret > 0) - return 0; +#ifdef HAVE_VALGRIND +/* Need a static build to have access to symbols. */ - return ret; +#ifndef WOLFSSL_SSL_H +/* APIs hiding in ssl.h */ +extern int wolfSSL_Debugging_ON(void); +extern void wolfSSL_Debugging_OFF(void); +#endif + +#ifdef DEBUG_WOLFSSL +static int log_cnt = 0; +static void my_Logging_cb(const int logLevel, const char *const logMessage) +{ + (void)logLevel; + (void)logMessage; + log_cnt++; } +#endif -int pkcs7signed_test(void) +int logging_test() { - int ret = 0; +#ifdef DEBUG_WOLFSSL + const char* msg = "Testing, testing. 1, 2, 3, 4 ..."; + byte a[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + byte b[256]; + size_t i; - FILE* file; - byte* certDer; - byte* keyDer; - byte* out; - char data[] = "Hello World"; - word32 dataSz, outSz, certDerSz, keyDerSz; - PKCS7 msg; - WC_RNG rng; + for (i = 0; i < sizeof(b); i++) + b[i] = i; - static byte transIdOid[] = - { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, - 0x09, 0x07 }; - static byte messageTypeOid[] = - { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, - 0x09, 0x02 }; - static byte senderNonceOid[] = - { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, - 0x09, 0x05 }; - static byte transId[(SHA_DIGEST_SIZE + 1) * 2 + 1]; - static byte messageType[] = { 0x13, 2, '1', '9' }; - static byte senderNonce[PKCS7_NONCE_SZ + 2]; + if (wolfSSL_Debugging_ON() != 0) + return -7900; + if (wolfSSL_SetLoggingCb(NULL) != BAD_FUNC_ARG) + return -7901; - PKCS7Attrib attribs[] = - { - { transIdOid, sizeof(transIdOid), - transId, sizeof(transId) - 1 }, /* take off the null */ - { messageTypeOid, sizeof(messageTypeOid), - messageType, sizeof(messageType) }, - { senderNonceOid, sizeof(senderNonceOid), - senderNonce, sizeof(senderNonce) } - }; + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(a, sizeof(a)); + WOLFSSL_BUFFER(b, sizeof(b)); + WOLFSSL_BUFFER(NULL, 0); - dataSz = (word32) XSTRLEN(data); - outSz = FOURK_BUF; + wolfSSL_Debugging_OFF(); - certDer =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (certDer == NULL) - return -207; - keyDer = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyDer == NULL) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -208; - } - out = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (out == NULL) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -209; - } + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(b, sizeof(b)); - /* read in DER cert of recipient, into cert of size certSz */ - file = fopen(clientCert, "rb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -44); - return -44; - } - certDerSz = (word32)fread(certDer, 1, FOURK_BUF, file); - fclose(file); + if (wolfSSL_SetLoggingCb(my_Logging_cb) != 0) + return -7902; - file = fopen(clientKey, "rb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -45); - return -45; - } - keyDerSz = (word32)fread(keyDer, 1, FOURK_BUF, file); - fclose(file); + wolfSSL_Debugging_OFF(); - ret = wc_InitRng(&rng); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -210; - } + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(b, sizeof(b)); - senderNonce[0] = 0x04; - senderNonce[1] = PKCS7_NONCE_SZ; + if (log_cnt != 0) + return -7903; + if (wolfSSL_Debugging_ON() != 0) + return -7904; - ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -211; - } + WOLFSSL_MSG(msg); + WOLFSSL_BUFFER(b, sizeof(b)); - wc_PKCS7_InitWithCert(&msg, certDer, certDerSz); - msg.privateKey = keyDer; - msg.privateKeySz = keyDerSz; - msg.content = (byte*)data; - msg.contentSz = dataSz; - msg.hashOID = SHAh; - msg.encryptOID = RSAk; - msg.signedAttribs = attribs; - msg.signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib); - msg.rng = &rng; - { - Sha sha; - byte digest[SHA_DIGEST_SIZE]; - int i,j; + /* One call for each line of output. */ + if (log_cnt != 17) + return -7905; +#else + if (wolfSSL_Debugging_ON() != NOT_COMPILED_IN) + return -7906; + wolfSSL_Debugging_OFF(); + if (wolfSSL_SetLoggingCb(NULL) != NOT_COMPILED_IN) + return -7907; +#endif + return 0; +} +#endif - transId[0] = 0x13; - transId[1] = SHA_DIGEST_SIZE * 2; +int mutex_test() +{ +#ifdef WOLFSSL_PTHREADS + wolfSSL_Mutex m; +#endif + wolfSSL_Mutex *mm = wc_InitAndAllocMutex(); + if (mm == NULL) + return -8000; + wc_FreeMutex(mm); + XFREE(mm, NULL, DYNAMIC_TYPE_MUTEX); + +#ifdef WOLFSSL_PTHREADS + if (wc_InitMutex(&m) != 0) + return -8001; + if (wc_LockMutex(&m) != 0) + return -8002; + if (wc_FreeMutex(&m) != BAD_MUTEX_E) + return -8003; + if (wc_UnLockMutex(&m) != 0) + return -8004; + if (wc_FreeMutex(&m) != 0) + return -8005; + if (wc_LockMutex(&m) != BAD_MUTEX_E) + return -8006; + if (wc_UnLockMutex(&m) != BAD_MUTEX_E) + return -8007; +#endif - ret = wc_InitSha(&sha); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -4003; - } - wc_ShaUpdate(&sha, msg.publicKey, msg.publicKeySz); - wc_ShaFinal(&sha, digest); + return 0; +} - for (i = 0, j = 2; i < SHA_DIGEST_SIZE; i++, j += 2) { - snprintf((char*)&transId[j], 3, "%02x", digest[i]); - } - } - ret = wc_PKCS7_EncodeSignedData(&msg, out, outSz); - if (ret < 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -212; - } - else - outSz = ret; +#ifdef USE_WOLFSSL_MEMORY +static int malloc_cnt = 0; +static int realloc_cnt = 0; +static int free_cnt = 0; -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - /* write PKCS#7 to output file for more testing */ - file = fopen("./pkcs7signedData.der", "wb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -213; - } - ret = (int)fwrite(out, 1, outSz, file); - fclose(file); - if (ret != (int)outSz) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -218; - } -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ +static void *my_Malloc_cb(size_t size) +{ + malloc_cnt++; + return malloc(size); +} +static void my_Free_cb(void *ptr) +{ + free_cnt++; + free(ptr); +} +static void *my_Realloc_cb(void *ptr, size_t size) +{ + realloc_cnt++; + return realloc(ptr, size); +} - wc_PKCS7_Free(&msg); - wc_PKCS7_InitWithCert(&msg, NULL, 0); +int memcb_test() +{ + int ret = 0; + byte* b = NULL; + wolfSSL_Malloc_cb mc; + wolfSSL_Free_cb fc; + wolfSSL_Realloc_cb rc; - ret = wc_PKCS7_VerifySignedData(&msg, out, outSz); - if (ret < 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -214; + /* Save existing memory callbacks */ + if (wolfSSL_GetAllocators(&mc, &fc, &rc) != 0) + return -8100; + + /* test realloc */ + b = (byte*)XREALLOC(b, 1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) { + ERROR_OUT(-8101, exit_memcb); } + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + b = NULL; - if (msg.singleCert == NULL || msg.singleCertSz == 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -215; + /* Parameter Validation testing. */ + if (wolfSSL_SetAllocators(NULL, (wolfSSL_Free_cb)&my_Free_cb, + (wolfSSL_Realloc_cb)&my_Realloc_cb) != BAD_FUNC_ARG) { + ERROR_OUT(-8102, exit_memcb); + } + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)&my_Malloc_cb, NULL, + (wolfSSL_Realloc_cb)&my_Realloc_cb) != BAD_FUNC_ARG) { + ERROR_OUT(-8103, exit_memcb); + } + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)&my_Malloc_cb, + (wolfSSL_Free_cb)&my_Free_cb, NULL) != BAD_FUNC_ARG) { + ERROR_OUT(-8104, exit_memcb); } -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - file = fopen("./pkcs7cert.der", "wb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -216; + /* Use API. */ + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)&my_Malloc_cb, + (wolfSSL_Free_cb)&my_Free_cb, (wolfSSL_Realloc_cb)my_Realloc_cb) != 0) { + ERROR_OUT(-8105, exit_memcb); } - ret = (int)fwrite(msg.singleCert, 1, msg.singleCertSz, file); - fclose(file); -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); + b = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + b = (byte*)XREALLOC(b, 1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); - wc_FreeRng(&rng); +#ifndef WOLFSSL_STATIC_MEMORY + if (malloc_cnt != 1 || free_cnt != 1 || realloc_cnt != 1) +#else + if (malloc_cnt != 0 || free_cnt != 0 || realloc_cnt != 0) +#endif + ret = -8106; - if (ret > 0) - return 0; +exit_memcb: + + /* restore memory callbacks */ + wolfSSL_SetAllocators(mc, fc, rc); return ret; } - -#endif /* HAVE_PKCS7 */ +#endif #undef ERROR_OUT diff --git a/wolfcrypt/test/test.h b/wolfcrypt/test/test.h index 47d8b74c20..d65b27f4fa 100644 --- a/wolfcrypt/test/test.h +++ b/wolfcrypt/test/test.h @@ -28,7 +28,11 @@ extern "C" { #endif +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD wolfcrypt_test(void* args); +#else int wolfcrypt_test(void* args); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfcrypt/user-crypto/src/rsa.c b/wolfcrypt/user-crypto/src/rsa.c index 8beb6bf8c1..3040211bd5 100644 --- a/wolfcrypt/user-crypto/src/rsa.c +++ b/wolfcrypt/user-crypto/src/rsa.c @@ -792,39 +792,39 @@ static int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { int length = 0; - word32 i = *inOutIdx; + word32 idx = *inOutIdx; byte b; *len = 0; /* default length */ - if ( (i+1) > maxIdx) { /* for first read */ + if ((idx + 1) > maxIdx) { /* for first read */ USER_DEBUG(("GetLength bad index on input\n")); return USER_CRYPTO_ERROR; } - b = input[i++]; + b = input[idx++]; if (b >= 0x80) { word32 bytes = b & 0x7F; - if ( (i+bytes) > maxIdx) { /* for reading bytes */ + if ((idx + bytes) > maxIdx) { /* for reading bytes */ USER_DEBUG(("GetLength bad long length\n")); return USER_CRYPTO_ERROR; } while (bytes--) { - b = input[i++]; + b = input[idx++]; length = (length << 8) | b; } } else length = b; - if ( (i+length) > maxIdx) { /* for user of length */ + if ((idx + length) > maxIdx) { /* for user of length */ USER_DEBUG(("GetLength value exceeds buffer length\n")); return USER_CRYPTO_ERROR; } - *inOutIdx = i; + *inOutIdx = idx; if (length > 0) *len = length; @@ -836,21 +836,28 @@ static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx, word32 maxIdx) { IppStatus ret; - word32 i = *inOutIdx; - byte b = input[i++]; + word32 idx = *inOutIdx; + byte b; int length; int ctxSz; + if ((idx + 1) > maxIdx) + return USER_CRYPTO_ERROR; + + b = input[idx++]; if (b != 0x02) return USER_CRYPTO_ERROR; - if (GetLength(input, &i, &length, maxIdx) < 0) + if (GetLength(input, &idx, &length, maxIdx) < 0) return USER_CRYPTO_ERROR; - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + if (length > 0) { + /* remove leading zero */ + if ( (b = input[idx++]) == 0x00) + length--; + else + idx--; + } ret = ippsBigNumGetSize(length, &ctxSz); if (ret != ippStsNoErr) @@ -864,11 +871,11 @@ static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx, if (ret != ippStsNoErr) return USER_CRYPTO_ERROR; - ret = ippsSetOctString_BN((Ipp8u*)input + i, length, *mpi); + ret = ippsSetOctString_BN((Ipp8u*)input + idx, length, *mpi); if (ret != ippStsNoErr) return USER_CRYPTO_ERROR; - *inOutIdx = i + length; + *inOutIdx = idx + length; return 0; } @@ -879,6 +886,9 @@ static int GetSequence(const byte* input, word32* inOutIdx, int* len, int length = -1; word32 idx = *inOutIdx; + if ((idx + 1) > maxIdx) + return USER_CRYPTO_ERROR; + if (input[idx++] != (0x10 | 0x20) || GetLength(input, &idx, &length, maxIdx) < 0) return USER_CRYPTO_ERROR; @@ -891,10 +901,13 @@ static int GetSequence(const byte* input, word32* inOutIdx, int* len, static int GetMyVersion(const byte* input, word32* inOutIdx, - int* version) + int* version, word32 maxIdx) { word32 idx = *inOutIdx; + if ((idx + 3) > maxIdx) + return USER_CRYPTO_ERROR; + if (input[idx++] != 0x02) return USER_CRYPTO_ERROR; @@ -921,7 +934,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return USER_CRYPTO_ERROR; - if (GetMyVersion(input, inOutIdx, &version) < 0) + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) return USER_CRYPTO_ERROR; key->type = RSA_PRIVATE; @@ -1046,9 +1059,12 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { - int length; + int length; int ctxSz; IppStatus ret; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + byte b; +#endif USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); @@ -1058,8 +1074,10 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, key->type = RSA_PUBLIC; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; + if ((*inOutIdx + 1) > inSz) + return USER_CRYPTO_ERROR; + + b = input[*inOutIdx]; if (b != ASN_INTEGER) { /* not from decoded cert, will have algo id, skip past */ if (GetSequence(input, inOutIdx, &length, inSz) < 0) @@ -1082,16 +1100,17 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (b != 0) return USER_CRYPTO_ERROR; } - else - /* go back, didn't have it */ + else { + /* go back, didn't have it */ (*inOutIdx)--; + } /* should have bit tag length and seq next */ b = input[(*inOutIdx)++]; if (b != ASN_BIT_STRING) return USER_CRYPTO_ERROR; - if (GetLength(input, inOutIdx, &length, inSz) < 0) + if (GetLength(input, inOutIdx, &length, inSz) <= 0) return USER_CRYPTO_ERROR; /* could have 0 */ @@ -1101,12 +1120,13 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return USER_CRYPTO_ERROR; - } /* end if */ - } /* openssl var block */ -#endif /* OPENSSL_EXTRA */ + } +#endif /* OPENSSL_EXTRA || RSA_DECODE_EXTRA */ if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return USER_CRYPTO_ERROR; + GetInt(&key->e, input, inOutIdx, inSz) < 0) { + return USER_CRYPTO_ERROR; + } /* get sizes set for IPP BN states */ ret = ippsGetSize_BN(key->n, &key->nSz); @@ -1930,13 +1950,13 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) return USER_CRYPTO_ERROR; - bytSz = sizeof(byte); + bytSz = sizeof(byte) * 8; ret = ippsExtGet_BN(NULL, &sz, NULL, key->e); if (ret != ippStsNoErr) return USER_CRYPTO_ERROR; /* sz is in bits change to bytes */ - sz = (sz / bytSz) + (sz % bytSz); + sz = (sz / bytSz) + ((sz % bytSz)? 1 : 0); if (*eSz < (word32)sz) return USER_CRYPTO_ERROR; @@ -1953,7 +1973,7 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, return USER_CRYPTO_ERROR; /* sz is in bits change to bytes */ - sz = (sz / bytSz) + (sz % bytSz); + sz = (sz / bytSz) + ((sz % bytSz)? 1: 0); if (*nSz < (word32)sz) return USER_CRYPTO_ERROR; diff --git a/wolfssl-ntru.vcproj b/wolfssl-ntru.vcproj index a9f5c45770..3b7703c1b8 100755 --- a/wolfssl-ntru.vcproj +++ b/wolfssl-ntru.vcproj @@ -274,6 +274,10 @@ RelativePath=".\wolfcrypt\src\wc_port.c" > + + diff --git a/wolfssl.vcproj b/wolfssl.vcproj index 106ba29fe8..6843f4072b 100755 --- a/wolfssl.vcproj +++ b/wolfssl.vcproj @@ -271,6 +271,10 @@ RelativePath=".\wolfcrypt\src\wc_port.c" > + + diff --git a/wolfssl.vcxproj b/wolfssl.vcxproj index 985f3383be..7824a9b180 100644 --- a/wolfssl.vcxproj +++ b/wolfssl.vcxproj @@ -318,6 +318,7 @@ + diff --git a/wolfssl/certs_test.h b/wolfssl/certs_test.h index 2d52511d7e..64d10e50d4 100644 --- a/wolfssl/certs_test.h +++ b/wolfssl/certs_test.h @@ -1219,6 +1219,132 @@ static const unsigned char rsa_key_der_2048[] = }; static const int sizeof_rsa_key_der_2048 = sizeof(rsa_key_der_2048); +/* ./certs/ca-key.der, 2048-bit */ +static const unsigned char ca_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xBF, 0x0C, 0xCA, 0x2D, 0x14, 0xB2, 0x1E, 0x84, + 0x42, 0x5B, 0xCD, 0x38, 0x1F, 0x4A, 0xF2, 0x4D, 0x75, 0x10, + 0xF1, 0xB6, 0x35, 0x9F, 0xDF, 0xCA, 0x7D, 0x03, 0x98, 0xD3, + 0xAC, 0xDE, 0x03, 0x66, 0xEE, 0x2A, 0xF1, 0xD8, 0xB0, 0x7D, + 0x6E, 0x07, 0x54, 0x0B, 0x10, 0x98, 0x21, 0x4D, 0x80, 0xCB, + 0x12, 0x20, 0xE7, 0xCC, 0x4F, 0xDE, 0x45, 0x7D, 0xC9, 0x72, + 0x77, 0x32, 0xEA, 0xCA, 0x90, 0xBB, 0x69, 0x52, 0x10, 0x03, + 0x2F, 0xA8, 0xF3, 0x95, 0xC5, 0xF1, 0x8B, 0x62, 0x56, 0x1B, + 0xEF, 0x67, 0x6F, 0xA4, 0x10, 0x41, 0x95, 0xAD, 0x0A, 0x9B, + 0xE3, 0xA5, 0xC0, 0xB0, 0xD2, 0x70, 0x76, 0x50, 0x30, 0x5B, + 0xA8, 0xE8, 0x08, 0x2C, 0x7C, 0xED, 0xA7, 0xA2, 0x7A, 0x8D, + 0x38, 0x29, 0x1C, 0xAC, 0xC7, 0xED, 0xF2, 0x7C, 0x95, 0xB0, + 0x95, 0x82, 0x7D, 0x49, 0x5C, 0x38, 0xCD, 0x77, 0x25, 0xEF, + 0xBD, 0x80, 0x75, 0x53, 0x94, 0x3C, 0x3D, 0xCA, 0x63, 0x5B, + 0x9F, 0x15, 0xB5, 0xD3, 0x1D, 0x13, 0x2F, 0x19, 0xD1, 0x3C, + 0xDB, 0x76, 0x3A, 0xCC, 0xB8, 0x7D, 0xC9, 0xE5, 0xC2, 0xD7, + 0xDA, 0x40, 0x6F, 0xD8, 0x21, 0xDC, 0x73, 0x1B, 0x42, 0x2D, + 0x53, 0x9C, 0xFE, 0x1A, 0xFC, 0x7D, 0xAB, 0x7A, 0x36, 0x3F, + 0x98, 0xDE, 0x84, 0x7C, 0x05, 0x67, 0xCE, 0x6A, 0x14, 0x38, + 0x87, 0xA9, 0xF1, 0x8C, 0xB5, 0x68, 0xCB, 0x68, 0x7F, 0x71, + 0x20, 0x2B, 0xF5, 0xA0, 0x63, 0xF5, 0x56, 0x2F, 0xA3, 0x26, + 0xD2, 0xB7, 0x6F, 0xB1, 0x5A, 0x17, 0xD7, 0x38, 0x99, 0x08, + 0xFE, 0x93, 0x58, 0x6F, 0xFE, 0xC3, 0x13, 0x49, 0x08, 0x16, + 0x0B, 0xA7, 0x4D, 0x67, 0x00, 0x52, 0x31, 0x67, 0x23, 0x4E, + 0x98, 0xED, 0x51, 0x45, 0x1D, 0xB9, 0x04, 0xD9, 0x0B, 0xEC, + 0xD8, 0x28, 0xB3, 0x4B, 0xBD, 0xED, 0x36, 0x79, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x3D, 0x6E, 0x4E, + 0x60, 0x1A, 0x84, 0x7F, 0x9D, 0x85, 0x7C, 0xE1, 0x4B, 0x07, + 0x7C, 0xE0, 0xD6, 0x99, 0x2A, 0xDE, 0x9D, 0xF9, 0x36, 0x34, + 0x0E, 0x77, 0x0E, 0x3E, 0x08, 0xEA, 0x4F, 0xE5, 0x06, 0x26, + 0xD4, 0xF6, 0x38, 0xF7, 0xDF, 0x0D, 0x0F, 0x1C, 0x2E, 0x06, + 0xA2, 0xF4, 0x2A, 0x68, 0x9C, 0x63, 0x72, 0xE3, 0x35, 0xE6, + 0x04, 0x91, 0x91, 0xB5, 0xC1, 0xB1, 0xA4, 0x54, 0xAC, 0xD7, + 0xC6, 0xFB, 0x41, 0xA0, 0xD6, 0x75, 0x6F, 0xBD, 0x0B, 0x4E, + 0xBF, 0xB1, 0x52, 0xE8, 0x5F, 0x49, 0x26, 0x98, 0x56, 0x47, + 0xC7, 0xDE, 0xE9, 0xEA, 0x3C, 0x60, 0x01, 0xBF, 0x28, 0xDC, + 0x31, 0xBF, 0x49, 0x5F, 0x93, 0x49, 0x87, 0x7A, 0x81, 0x5B, + 0x96, 0x4B, 0x4D, 0xCA, 0x5C, 0x38, 0x4F, 0xB7, 0xE1, 0xB2, + 0xD3, 0xC7, 0x21, 0xDA, 0x3C, 0x12, 0x87, 0x07, 0xE4, 0x1B, + 0xDC, 0x43, 0xEC, 0xE8, 0xEC, 0x54, 0x61, 0xE7, 0xF6, 0xED, + 0xA6, 0x0B, 0x2E, 0xF5, 0xDF, 0x82, 0x7F, 0xC6, 0x1F, 0x61, + 0x19, 0x9C, 0xA4, 0x83, 0x39, 0xDF, 0x21, 0x85, 0x89, 0x6F, + 0x77, 0xAF, 0x86, 0x15, 0x32, 0x08, 0xA2, 0x5A, 0x0B, 0x26, + 0x61, 0xFB, 0x70, 0x0C, 0xCA, 0x9C, 0x38, 0x7D, 0xBC, 0x22, + 0xEE, 0xEB, 0xA3, 0xA8, 0x16, 0x00, 0xF9, 0x8A, 0x80, 0x1E, + 0x00, 0x84, 0xA8, 0x4A, 0x41, 0xF8, 0x84, 0x03, 0x67, 0x2F, + 0x23, 0x5B, 0x2F, 0x9B, 0x6B, 0x26, 0xC3, 0x07, 0x34, 0x94, + 0xA3, 0x03, 0x3B, 0x72, 0xD5, 0x9F, 0x72, 0xE0, 0xAD, 0xCC, + 0x34, 0xAB, 0xBD, 0xC7, 0xD5, 0xF5, 0x26, 0x30, 0x85, 0x0F, + 0x30, 0x23, 0x39, 0x52, 0xFF, 0x3C, 0xCB, 0x99, 0x21, 0x4D, + 0x88, 0xA5, 0xAB, 0xEE, 0x62, 0xB9, 0xC7, 0xE0, 0xBB, 0x47, + 0x87, 0xC1, 0x69, 0xCF, 0x73, 0xF3, 0x30, 0xBE, 0xCE, 0x39, + 0x04, 0x9C, 0xE5, 0x02, 0x81, 0x81, 0x00, 0xE1, 0x76, 0x45, + 0x80, 0x59, 0xB6, 0xD3, 0x49, 0xDF, 0x0A, 0xEF, 0x12, 0xD6, + 0x0F, 0xF0, 0xB7, 0xCB, 0x2A, 0x37, 0xBF, 0xA7, 0xF8, 0xB5, + 0x4D, 0xF5, 0x31, 0x35, 0xAD, 0xE4, 0xA3, 0x94, 0xA1, 0xDB, + 0xF1, 0x96, 0xAD, 0xB5, 0x05, 0x64, 0x85, 0x83, 0xFC, 0x1B, + 0x5B, 0x29, 0xAA, 0xBE, 0xF8, 0x26, 0x3F, 0x76, 0x7E, 0xAD, + 0x1C, 0xF0, 0xCB, 0xD7, 0x26, 0xB4, 0x1B, 0x05, 0x8E, 0x56, + 0x86, 0x7E, 0x08, 0x62, 0x21, 0xC1, 0x86, 0xD6, 0x47, 0x79, + 0x3E, 0xB7, 0x5D, 0xA4, 0xC6, 0x3A, 0xD7, 0xB1, 0x74, 0x20, + 0xF6, 0x50, 0x97, 0x41, 0x04, 0x53, 0xED, 0x3F, 0x26, 0xD6, + 0x6F, 0x91, 0xFA, 0x68, 0x26, 0xEC, 0x2A, 0xDC, 0x9A, 0xF1, + 0xE7, 0xDC, 0xFB, 0x73, 0xF0, 0x79, 0x43, 0x1B, 0x21, 0xA3, + 0x59, 0x04, 0x63, 0x52, 0x07, 0xC9, 0xD7, 0xE6, 0xD1, 0x1B, + 0x5D, 0x5E, 0x96, 0xFA, 0x53, 0x02, 0x81, 0x81, 0x00, 0xD8, + 0xED, 0x4E, 0x64, 0x61, 0x6B, 0x91, 0x0C, 0x61, 0x01, 0xB5, + 0x0F, 0xBB, 0x44, 0x67, 0x53, 0x1E, 0xDC, 0x07, 0xC4, 0x24, + 0x7E, 0x9E, 0x6C, 0x84, 0x23, 0x91, 0x0C, 0xE4, 0x12, 0x04, + 0x16, 0x4D, 0x78, 0x98, 0xCC, 0x96, 0x3D, 0x20, 0x4E, 0x0F, + 0x45, 0x9A, 0xB6, 0xF8, 0xB3, 0x93, 0x0D, 0xB2, 0xA2, 0x1B, + 0x29, 0xF2, 0x26, 0x79, 0xC8, 0xC5, 0xD2, 0x78, 0x7E, 0x5E, + 0x73, 0xF2, 0xD7, 0x70, 0x61, 0xBB, 0x40, 0xCE, 0x61, 0x05, + 0xFE, 0x69, 0x1E, 0x82, 0x29, 0xE6, 0x14, 0xB8, 0xA1, 0xE7, + 0x96, 0xD0, 0x23, 0x3F, 0x05, 0x93, 0x00, 0xF2, 0xE1, 0x4D, + 0x7E, 0xED, 0xB7, 0x96, 0x6C, 0xF7, 0xF0, 0xE4, 0xD1, 0xCF, + 0x01, 0x98, 0x4F, 0xDC, 0x74, 0x54, 0xAA, 0x6D, 0x5E, 0x5A, + 0x41, 0x31, 0xFE, 0xFF, 0x9A, 0xB6, 0xA0, 0x05, 0xDD, 0xA9, + 0x10, 0x54, 0xF8, 0x6B, 0xD0, 0xAA, 0x83, 0x02, 0x81, 0x80, + 0x21, 0xD3, 0x04, 0x8A, 0x44, 0xEB, 0x50, 0xB7, 0x7C, 0x66, + 0xBF, 0x87, 0x2B, 0xE6, 0x28, 0x4E, 0xEA, 0x83, 0xE2, 0xE9, + 0x35, 0xE1, 0xF2, 0x11, 0x47, 0xFF, 0xA1, 0xF5, 0xFC, 0x9F, + 0x2D, 0xE5, 0x3A, 0x81, 0xFC, 0x01, 0x03, 0x6F, 0x53, 0xAD, + 0x54, 0x27, 0xB6, 0x52, 0xEE, 0xE5, 0x56, 0xD1, 0x13, 0xAB, + 0xE1, 0xB3, 0x0F, 0x75, 0x90, 0x0A, 0x84, 0xB4, 0xA1, 0xC0, + 0x8C, 0x0C, 0xD6, 0x9E, 0x46, 0xBA, 0x2B, 0x3E, 0xB5, 0x31, + 0xED, 0x63, 0xBB, 0xA4, 0xD5, 0x0D, 0x8F, 0x72, 0xCD, 0xD1, + 0x1E, 0x26, 0x35, 0xEB, 0xBE, 0x1B, 0x72, 0xFD, 0x9B, 0x39, + 0xB4, 0x87, 0xB7, 0x13, 0xF5, 0xEA, 0x83, 0x45, 0x93, 0x98, + 0xBA, 0x8F, 0xE4, 0x4A, 0xCC, 0xB4, 0x4C, 0xA8, 0x7F, 0x08, + 0xBA, 0x41, 0x49, 0xA8, 0x49, 0x28, 0x3D, 0x5E, 0x3D, 0xC1, + 0xCE, 0x37, 0x00, 0xCB, 0xF9, 0x2C, 0xDD, 0x51, 0x02, 0x81, + 0x81, 0x00, 0xA1, 0x57, 0x9F, 0x3E, 0xB9, 0xD6, 0xAF, 0x83, + 0x6D, 0x83, 0x3F, 0x8F, 0xFB, 0xD0, 0xDC, 0xA8, 0xCE, 0x03, + 0x09, 0x23, 0xB1, 0xA1, 0x1B, 0x63, 0xCA, 0xC4, 0x49, 0x56, + 0x35, 0x2B, 0xD1, 0x2E, 0x65, 0x60, 0x95, 0x05, 0x55, 0x99, + 0x11, 0x35, 0xFD, 0xD5, 0xDF, 0x44, 0xC7, 0xA5, 0x88, 0x72, + 0x5F, 0xB2, 0x82, 0x51, 0xA8, 0x71, 0x45, 0x93, 0x36, 0xCF, + 0x5C, 0x1F, 0x61, 0x51, 0x0C, 0x05, 0x80, 0xE8, 0xAF, 0xC5, + 0x7B, 0xBA, 0x5E, 0x22, 0xE3, 0x3C, 0x75, 0xC3, 0x84, 0x05, + 0x55, 0x6D, 0xD6, 0x3A, 0x2D, 0x84, 0x89, 0x93, 0x33, 0xCB, + 0x38, 0xDA, 0xAA, 0x31, 0x05, 0xCD, 0xCE, 0x6C, 0x2D, 0xDD, + 0x55, 0xD3, 0x57, 0x0B, 0xF0, 0xA5, 0x35, 0x6A, 0xB0, 0xAE, + 0x31, 0xBA, 0x43, 0x96, 0xCA, 0x00, 0xC7, 0x4B, 0xE3, 0x19, + 0x12, 0x43, 0xD3, 0x42, 0xFA, 0x6F, 0xEA, 0x80, 0xC0, 0xD1, + 0x02, 0x81, 0x81, 0x00, 0xB9, 0xDB, 0x89, 0x20, 0x34, 0x27, + 0x70, 0x62, 0x34, 0xEA, 0x5F, 0x25, 0x62, 0x12, 0xF3, 0x9D, + 0x81, 0xBF, 0x48, 0xEE, 0x9A, 0x0E, 0xC1, 0x8D, 0x10, 0xFF, + 0x65, 0x9A, 0x9D, 0x2D, 0x1A, 0x8A, 0x94, 0x5A, 0xC8, 0xC0, + 0xA5, 0xA5, 0x84, 0x61, 0x9E, 0xD4, 0x24, 0xB9, 0xEF, 0xA9, + 0x9D, 0xC9, 0x77, 0x0B, 0xC7, 0x70, 0x66, 0x3D, 0xBA, 0xC8, + 0x54, 0xDF, 0xD2, 0x33, 0xE1, 0xF5, 0x7F, 0xF9, 0x27, 0x61, + 0xBE, 0x57, 0x45, 0xDD, 0xB7, 0x45, 0x17, 0x24, 0xF5, 0x23, + 0xE4, 0x38, 0x0E, 0x91, 0x27, 0xEE, 0xE3, 0x20, 0xD8, 0x14, + 0xC8, 0x94, 0x47, 0x77, 0x40, 0x77, 0x45, 0x18, 0x9E, 0x0D, + 0xCE, 0x79, 0x3F, 0x57, 0x31, 0x56, 0x09, 0x49, 0x67, 0xBE, + 0x94, 0x58, 0x4F, 0xF6, 0xC4, 0xAB, 0xE2, 0x89, 0xE3, 0xE3, + 0x8A, 0xC0, 0x05, 0x55, 0x2C, 0x24, 0xC0, 0x4A, 0x97, 0x04, + 0x27, 0x9A +}; +static const int sizeof_ca_key_der_2048 = sizeof(ca_key_der_2048); + /* ./certs/ca-cert.der, 2048-bit */ static const unsigned char ca_cert_der_2048[] = { diff --git a/wolfssl/crl.h b/wolfssl/crl.h index 9828423848..88e0f10981 100644 --- a/wolfssl/crl.h +++ b/wolfssl/crl.h @@ -34,13 +34,11 @@ extern "C" { #endif -typedef struct WOLFSSL_CRL WOLFSSL_CRL; - WOLFSSL_LOCAL int InitCRL(WOLFSSL_CRL*, WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL void FreeCRL(WOLFSSL_CRL*, int dynamic); WOLFSSL_LOCAL int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int mon); -WOLFSSL_LOCAL int BufferLoadCRL(WOLFSSL_CRL*, const byte*, long, int); +WOLFSSL_LOCAL int BufferLoadCRL(WOLFSSL_CRL*, const byte*, long, int, int); WOLFSSL_LOCAL int CheckCertCRL(WOLFSSL_CRL*, DecodedCert*); diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 77d964e88f..c797c7f551 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -90,7 +90,7 @@ enum wolfSSL_ErrorCodes { ECC_EXPORT_ERROR = -354, /* Bad ECC Export Key */ ECC_SHARED_ERROR = -355, /* Bad ECC Shared Secret */ NOT_CA_ERROR = -357, /* Not a CA cert error */ - BAD_PATH_ERROR = -358, /* Bad path for opendir */ + BAD_CERT_MANAGER_ERROR = -359, /* Bad Cert Manager */ OCSP_CERT_REVOKED = -360, /* OCSP Certificate revoked */ CRL_CERT_REVOKED = -361, /* CRL Certificate revoked */ @@ -152,12 +152,22 @@ enum wolfSSL_ErrorCodes { EXT_MASTER_SECRET_NEEDED_E = -414, /* need EMS enabled to resume */ DTLS_POOL_SZ_E = -415, /* exceeded DTLS pool size */ DECODE_E = -416, /* decode handshake message error */ + HTTP_TIMEOUT = -417, /* HTTP timeout for OCSP or CRL req */ + WRITE_DUP_READ_E = -418, /* Write dup write side can't read */ + WRITE_DUP_WRITE_E = -419, /* Write dup read side can't write */ + INVALID_CERT_CTX_E = -420, /* TLS cert ctx not matching */ + BAD_KEY_SHARE_DATA = -421, /* Key Share data invalid */ + MISSING_HANDSHAKE_DATA = -422, /* Handshake message missing data */ + BAD_BINDER = -423, /* Binder does not match */ + EXT_NOT_ALLOWED = -424, /* Extension not allowed in msg */ + INVALID_PARAMETER = -425, /* Security parameter invalid */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* begin negotiation parameter errors */ UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ MATCH_SUITE_ERROR = -501, /* can't match cipher suite */ - COMPRESSION_ERROR = -502 /* compression mismatch */ + COMPRESSION_ERROR = -502, /* compression mismatch */ + KEY_SHARE_ERROR = -503 /* key share mismatch */ /* end negotiation parameter errors only 10 for now */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/include.am b/wolfssl/include.am index 03883b0861..029bc3d17a 100644 --- a/wolfssl/include.am +++ b/wolfssl/include.am @@ -17,7 +17,8 @@ nobase_include_HEADERS+= \ wolfssl/test.h \ wolfssl/version.h \ wolfssl/ocsp.h \ - wolfssl/crl.h + wolfssl/crl.h \ + wolfssl/io.h noinst_HEADERS+= \ wolfssl/internal.h diff --git a/wolfssl/internal.h b/wolfssl/internal.h old mode 100644 new mode 100755 index 3859c15349..ea56d93b67 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -81,18 +81,24 @@ #ifdef WOLFSSL_SHA512 #include #endif - #ifdef HAVE_AESGCM #include #endif - #ifdef WOLFSSL_RIPEMD #include #endif - #ifdef HAVE_IDEA #include #endif +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifndef NO_DH + #include +#endif #include @@ -140,6 +146,8 @@ #elif defined(MBED) #elif defined(WOLFSSL_TIRTOS) /* do nothing */ +#elif defined(INTIME_RTOS) + #include #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS @@ -150,6 +158,11 @@ #endif #endif +#ifndef CHAR_BIT + /* Needed for DTLS without big math */ + #include +#endif + #ifdef HAVE_LIBZ #include "zlib.h" @@ -164,12 +177,6 @@ #pragma warning(disable: 4996) #endif -#ifdef NO_AES - #if !defined (ALIGN16) - #define ALIGN16 - #endif -#endif - #ifdef NO_SHA #define SHA_DIGEST_SIZE 20 #endif @@ -188,13 +195,6 @@ #endif -#ifdef USE_WINDOWS_API - typedef unsigned int SOCKET_T; -#else - typedef int SOCKET_T; -#endif - - typedef byte word24[3]; /* Define or comment out the cipher suites you'd like to be compiled in @@ -627,6 +627,29 @@ typedef byte word24[3]; #endif #endif +#if defined(WOLFSSL_TLS13) + #ifdef HAVE_AESGCM + #ifndef NO_SHA256 + #define BUILD_TLS_AES_128_GCM_SHA256 + #endif + #ifdef WOLFSSL_SHA384 + #define BUILD_TLS_AES_256_GCM_SHA384 + #endif + #endif + + #ifdef HAVE_CHACHA + #ifndef NO_SHA256 + #define BUILD_TLS_CHACHA20_POLY1305_SHA256 + #endif + #endif + + #ifdef HAVE_AESCCM + #ifndef NO_SHA256 + #define BUILD_TLS_AES_128_CCM_SHA256 + #define BUILD_TLS_AES_128_CCM_8_SHA256 + #endif + #endif +#endif #if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \ defined(BUILD_SSL_RSA_WITH_RC4_128_MD5) @@ -675,8 +698,9 @@ typedef byte word24[3]; #define BUILD_DES3 #endif -#ifdef NO_AES +#if defined(NO_AES) || defined(NO_AES_DECRYPT) #define AES_BLOCK_SIZE 16 + #undef BUILD_AES #else #undef BUILD_AES #define BUILD_AES @@ -852,6 +876,13 @@ enum { TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14, TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x15, + /* TLS v1.3 cipher suites */ + TLS_AES_128_GCM_SHA256 = 0x01, + TLS_AES_256_GCM_SHA384 = 0x02, + TLS_CHACHA20_POLY1305_SHA256 = 0x03, + TLS_AES_128_CCM_SHA256 = 0x04, + TLS_AES_128_CCM_8_SHA256 = 0x05, + /* Renegotiation Indication Extension Special Suite */ TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0xff }; @@ -875,6 +906,7 @@ enum Misc { ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ QSH_BYTE = 0xD0, /* Quantum-safe Handshake cipher suite */ CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */ + TLS13_BYTE = 0x13, /* TLS v.13 first byte of cipher suite */ SEND_CERT = 1, SEND_BLANK_CERT = 2, @@ -887,6 +919,9 @@ enum Misc { TLSv1_MINOR = 1, /* TLSv1 minor version number */ TLSv1_1_MINOR = 2, /* TLSv1_1 minor version number */ TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */ + TLSv1_3_MINOR = 4, /* TLSv1_3 minor version number */ + TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */ + TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ NO_COMPRESSION = 0, @@ -924,12 +959,15 @@ enum Misc { LENGTH_SZ = 2, /* length field for HMAC, data only */ VERSION_SZ = 2, /* length of proctocol version */ SEQ_SZ = 8, /* 64 bit sequence number */ - BYTE3_LEN = 3, /* up to 24 bit byte lengths */ ALERT_SIZE = 2, /* level + description */ VERIFY_HEADER = 2, /* always use 2 bytes */ + EXTS_SZ = 2, /* always use 2 bytes */ EXT_ID_SZ = 2, /* always use 2 bytes */ MAX_DH_SIZE = 513, /* 4096 bit plus possible leading 0 */ + NAMED_DH_MASK = 0x100, /* Named group mask for DH parameters */ SESSION_HINT_SZ = 4, /* session timeout hint */ + SESSION_ADD_SZ = 4, /* session age add */ + MAX_LIFETIME = 604800, /* maximum ticket lifetime */ RAN_LEN = 32, /* random length */ SEED_LEN = RAN_LEN * 2, /* tls prf seed length */ @@ -946,6 +984,7 @@ enum Misc { OPAQUE64_LEN = 8, /* 8 bytes */ COMP_LEN = 1, /* compression length */ CURVE_LEN = 2, /* ecc named curve length */ + KE_GROUP_LEN = 2, /* key exchange group length */ SERVER_ID_LEN = 20, /* server session id length */ HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */ @@ -986,6 +1025,11 @@ enum Misc { MAX_PRF_HALF = 256, /* Maximum half secret len */ MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ MAX_PRF_DIG = 224, /* Maximum digest len */ + PROTOCOL_LABEL_SZ = 9, /* Length of the protocol label */ + MAX_LABEL_SZ = 34, /* Maximum length of a label */ + MAX_HKDF_LABEL_SZ = OPAQUE16_LEN + + OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ + + OPAQUE8_LEN + MAX_DIGEST_SIZE, MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */ SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ @@ -1004,6 +1048,7 @@ enum Misc { AEAD_VMIN_OFFSET = 10, /* Auth Data: Minor Version */ AEAD_LEN_OFFSET = 11, /* Auth Data: Length */ AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */ + AEAD_NONCE_SZ = 12, AESGCM_IMP_IV_SZ = 4, /* Size of GCM/CCM AEAD implicit IV */ AESGCM_EXP_IV_SZ = 8, /* Size of GCM/CCM AEAD explicit IV */ AESGCM_NONCE_SZ = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ, @@ -1017,6 +1062,7 @@ enum Misc { AES_GCM_AUTH_SZ = 16, /* AES-GCM Auth Tag length */ AES_CCM_16_AUTH_SZ = 16, /* AES-CCM-16 Auth Tag length */ AES_CCM_8_AUTH_SZ = 8, /* AES-CCM-8 Auth Tag Length */ + AESCCM_NONCE_SZ = 12, CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */ CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */ @@ -1055,17 +1101,19 @@ enum Misc { DTLS_TIMEOUT_MULTIPLIER = 2, /* default timeout multiplier for DTLS recv */ MAX_PSK_ID_LEN = 128, /* max psk identity/hint supported */ + NULL_TERM_LEN = 1, /* length of null '\0' termination character */ MAX_PSK_KEY_LEN = 64, /* max psk key supported */ + MIN_PSK_ID_LEN = 6, /* min length of identities */ + MIN_PSK_BINDERS_LEN= 33, /* min length of binders */ MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4, /* 4 mb file size alloc limit */ -#if defined(FORTRESS) || defined (HAVE_STUNNEL) - MAX_EX_DATA = 3, /* allow for three items of ex_data */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + MAX_EX_DATA = 5, /* allow for five items of ex_data */ #endif MAX_X509_SIZE = 2048, /* max static x509 buffer size */ CERT_MIN_SIZE = 256, /* min PEM cert size with header/footer */ - MAX_FILENAME_SZ = 256, /* max file name length */ FILE_BUFFER_SIZE = 1024, /* default static file buffer size for input, will use dynamic buffer if not big enough */ @@ -1087,11 +1135,7 @@ enum Misc { /* Set max implicit IV size for AEAD cipher suites */ -#ifdef HAVE_CHACHA - #define AEAD_MAX_IMP_SZ 12 -#else - #define AEAD_MAX_IMP_SZ 4 -#endif +#define AEAD_MAX_IMP_SZ 12 /* Set max explicit IV size for AEAD cipher suites */ #define AEAD_MAX_EXP_SZ 8 @@ -1200,10 +1244,12 @@ enum states { SERVER_HELLOVERIFYREQUEST_COMPLETE, SERVER_HELLO_COMPLETE, + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE, SERVER_CERT_COMPLETE, SERVER_KEYEXCHANGE_COMPLETE, SERVER_HELLODONE_COMPLETE, SERVER_FINISHED_COMPLETE, + SERVER_HELLO_RETRY_REQUEST, CLIENT_HELLO_COMPLETE, CLIENT_KEYEXCHANGE_COMPLETE, @@ -1230,6 +1276,7 @@ WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void); WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void); WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void); WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void); +WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); #ifdef WOLFSSL_DTLS WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void); @@ -1249,7 +1296,9 @@ enum BIO_TYPE { BIO_BUFFER = 1, BIO_SOCKET = 2, BIO_SSL = 3, - BIO_MEMORY = 4 + BIO_MEMORY = 4, + BIO_BIO = 5, + BIO_FILE = 6 }; @@ -1261,15 +1310,24 @@ struct WOLFSSL_BIO_METHOD { /* wolfSSL BIO type */ struct WOLFSSL_BIO { - byte type; /* method type */ - byte close; /* close flag */ - byte eof; /* eof flag */ WOLFSSL* ssl; /* possible associated ssl */ - byte* mem; /* memory buffer */ - int memLen; /* memory buffer length */ - int fd; /* possible file descriptor */ +#ifndef NO_FILESYSTEM + XFILE file; +#endif WOLFSSL_BIO* prev; /* previous in chain */ WOLFSSL_BIO* next; /* next in chain */ + WOLFSSL_BIO* pair; /* BIO paired with */ + void* heap; /* user heap hint */ + byte* mem; /* memory buffer */ + int wrSz; /* write buffer size (mem) */ + int wrIdx; /* current index for write buffer */ + int rdIdx; /* current read index */ + int readRq; /* read request */ + int memLen; /* memory buffer length */ + int fd; /* possible file descriptor */ + int eof; /* eof flag */ + byte type; /* method type */ + byte close; /* close flag */ }; @@ -1280,6 +1338,9 @@ struct WOLFSSL_METHOD { byte downgrade; /* whether to downgrade version, default no */ }; +/* wolfSSL buffer type - internal uses "buffer" type */ +typedef WOLFSSL_BUFFER_INFO buffer; + /* defaults to client */ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); @@ -1288,10 +1349,40 @@ WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, word32 totalSz, int sniff); WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx); - - -/* wolfSSL buffer type - internal uses "buffer" type */ -typedef WOLFSSL_BUFFER_INFO buffer; +/* TLS v1.3 needs these */ +WOLFSSL_LOCAL int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, + word32); +WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, + word32); +WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); +WOLFSSL_LOCAL void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, + word32 hashSigAlgoSz); +WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length); +WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl); +WOLFSSL_LOCAL int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size); +WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str); +#ifndef NO_CERTS +WOLFSSL_LOCAL int CheckAltNames(DecodedCert* dCert, char* domain); +#endif +WOLFSSL_LOCAL int CreateTicket(WOLFSSL* ssl); +WOLFSSL_LOCAL int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz); +WOLFSSL_LOCAL int HashOutput(WOLFSSL* ssl, const byte* output, int sz, + int ivSz); +WOLFSSL_LOCAL int HashInput(WOLFSSL* ssl, const byte* input, int sz); +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) +WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl); +#endif +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz); +WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, + word32* inOutIdx, byte type, + word32 size, word32 totalSz); +WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz); +WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 helloSz); +#endif #ifndef NO_CERTS /* wolfSSL DER buffer */ @@ -1393,11 +1484,10 @@ typedef struct Suites { } Suites; -WOLFSSL_LOCAL -void InitSuites(Suites*, ProtocolVersion, word16, word16, word16, word16, - word16, word16, word16, int); -WOLFSSL_LOCAL -int SetCipherList(Suites*, const char* list); +WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, word16, word16, word16, word16, + word16, word16, word16, int); +WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); +WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); #ifndef PSK_TYPES_DEFINED typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, @@ -1410,11 +1500,6 @@ int SetCipherList(Suites*, const char* list); unsigned char* exportBuffer, unsigned int sz, void* userCtx); #endif -#ifdef HAVE_NETX - WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); - WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx); -#endif /* HAVE_NETX */ - /* wolfSSL Cipher type just points back to SSL */ struct WOLFSSL_CIPHER { @@ -1453,6 +1538,9 @@ struct WOLFSSL_OCSP { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ OcspEntry* ocspList; /* OCSP response list */ wolfSSL_Mutex ocspLock; /* OCSP list lock */ +#if defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + int(*statusCb)(WOLFSSL*, void*); +#endif }; #ifndef MAX_DATE_SIZE @@ -1483,6 +1571,16 @@ struct CRL_Entry { byte nextDateFormat; /* next date format */ RevokedCert* certs; /* revoked cert list */ int totalCerts; /* number on list */ + int verified; + byte* toBeSigned; + word32 tbsSz; + byte* signature; + word32 signatureSz; + word32 signatureOID; +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyIdSet; + byte extAuthKeyId[KEYID_SIZE]; +#endif }; @@ -1495,10 +1593,6 @@ struct CRL_Monitor { }; -#ifndef HAVE_CRL - typedef struct WOLFSSL_CRL WOLFSSL_CRL; -#endif - #if defined(HAVE_CRL) && defined(NO_FILESYSTEM) #undef HAVE_CRL_MONITOR #endif @@ -1507,6 +1601,9 @@ struct CRL_Monitor { struct WOLFSSL_CRL { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ CRL_Entry* crlList; /* our CRL list */ +#ifdef HAVE_CRL_IO + CbCrlIO crlIOCb; +#endif wolfSSL_Mutex crlLock; /* CRL list lock */ CRL_Monitor monitors[2]; /* PEM and DER possible */ #ifdef HAVE_CRL_MONITOR @@ -1643,6 +1740,10 @@ typedef struct Keys { word32 padSz; /* how much to advance after decrypt part */ byte encryptionOn; /* true after change cipher spec */ byte decryptedCur; /* only decrypt current record once */ +#ifdef WOLFSSL_TLS13 + byte updateResponseReq:1; /* KeyUpdate response from peer required. */ + byte keyUpdateRespond:1; /* KeyUpdate is to be responded to. */ +#endif } Keys; @@ -1656,16 +1757,28 @@ typedef enum { TLSX_TRUNCATED_HMAC = 0x0004, TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */ TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ + TLSX_SIGNATURE_ALGORITHMS = 0x000d, TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ TLSX_SESSION_TICKET = 0x0023, +#ifdef WOLFSSL_TLS13 + TLSX_KEY_SHARE = 0x0028, + #ifndef NO_PSK + TLSX_PRE_SHARED_KEY = 0x0029, + #endif + TLSX_SUPPORTED_VERSIONS = 0x002b, + #ifndef NO_PSK + TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d, + #endif +#endif TLSX_RENEGOTIATION_INFO = 0xff01 } TLSX_Type; typedef struct TLSX { TLSX_Type type; /* Extension Type */ void* data; /* Extension Data */ + word32 val; /* Extension Value */ byte resp; /* IsResponse Flag */ struct TLSX* next; /* List Behavior */ } TLSX; @@ -1681,12 +1794,13 @@ WOLFSSL_LOCAL word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output); #endif #ifndef NO_WOLFSSL_SERVER -WOLFSSL_LOCAL word16 TLSX_GetResponseSize(WOLFSSL* ssl); -WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output); +WOLFSSL_LOCAL word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType); +WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output, + byte msgType); #endif -WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, - byte isRequest, Suites *suites); +WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType, Suites *suites); #elif defined(HAVE_SNI) \ || defined(HAVE_MAX_FRAGMENT) \ @@ -1777,9 +1891,11 @@ typedef struct { } CertificateStatusRequest; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, - byte status_type, byte options, void* heap); + byte status_type, byte options, void* heap, int devId); +#ifndef NO_CERTS WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap); +#endif WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); @@ -1799,9 +1915,11 @@ typedef struct CSRIv2 { } CertificateStatusRequestItemV2; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, - byte status_type, byte options, void* heap); + byte status_type, byte options, void* heap, int devId); +#ifndef NO_CERTS WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap); +#endif WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index); WOLFSSL_LOCAL int TLSX_CSR2_ForceRequest(WOLFSSL* ssl); @@ -1862,6 +1980,10 @@ WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap); typedef struct SessionTicket { word32 lifetime; +#ifdef WOLFSSL_TLS13 + word64 seen; + word32 ageAdd; +#endif byte* data; word16 size; } SessionTicket; @@ -1916,6 +2038,69 @@ WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name); #endif /* HAVE_QSH */ +#ifdef WOLFSSL_TLS13 +/* Key Share - TLS v1.3 Specification */ + +/* The KeyShare extension information - entry in a linked list. */ +typedef struct KeyShareEntry { + word16 group; /* NamedGroup */ + byte* ke; /* Key exchange data */ + word32 keLen; /* Key exchange data length */ + void* key; /* Private key */ + word32 keyLen; /* Private key length */ + struct KeyShareEntry* next; /* List pointer */ +} KeyShareEntry; + +WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, + byte* data, KeyShareEntry **kse); +WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl); + +#ifndef NO_PSK +/* The PreSharedKey extension information - entry in a linked list. */ +typedef struct PreSharedKey { + word16 identityLen; /* Length of identity */ + byte* identity; /* PSK identity */ + word32 ticketAge; /* Age of the ticket */ + word32 binderLen; /* Length of HMAC */ + byte binder[MAX_DIGEST_SIZE]; /* HMAC of hanshake */ + byte hmac; /* HMAC algorithm */ + byte resumption:1; /* Resumption PSK */ + byte chosen:1; /* Server's choice */ + struct PreSharedKey* next; /* List pointer */ +} PreSharedKey; + +WOLFSSL_LOCAL word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, + byte* output, byte msgType); +WOLFSSL_LOCAL word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, + byte msgType); +WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, + word16 len, word32 age, byte hmac, + byte resumption, + PreSharedKey **preSharedKey); + +enum PskKeyExchangeMode { + PSK_KE, + PSK_DHE_KE +}; + +WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes); +#endif /* NO_PSK */ + +/* The types of keys to derive for. */ +enum DeriveKeyType { + handshake_key, + traffic_key, + update_traffic_key +}; + +/* The key update request values for KeyUpdate message. */ +enum KeyUpdateRequest { + update_not_requested, + update_requested +}; +#endif /* WOLFSSL_TLS13 */ + /* wolfSSL context type */ struct WOLFSSL_CTX { @@ -1934,11 +2119,21 @@ struct WOLFSSL_CTX { DerBuffer* certificate; DerBuffer* certChain; /* chain after self, in DER, with leading size for each cert */ + #ifdef OPENSSL_EXTRA + STACK_OF(WOLFSSL_X509_NAME)* ca_names; + #endif + #if defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + STACK_OF(WOLFSSL_X509)* x509Chain; + #endif +#ifdef WOLFSSL_TLS13 + int certChainCnt; +#endif DerBuffer* privateKey; WOLFSSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ #endif #ifdef KEEP_OUR_CERT WOLFSSL_X509* ourCert; /* keep alive a X509 struct of cert */ + int ownOurCert; /* Dispose of certificate if we own */ #endif Suites* suites; /* make dynamic, user may not need/set */ void* heap; /* for user memory overrides */ @@ -1948,6 +2143,9 @@ struct WOLFSSL_CTX { byte failNoCertxPSK; /* fail if no cert with the exception of PSK*/ byte sessionCacheOff; byte sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + byte internalCacheOff; +#endif byte sendVerify; /* for client side */ byte haveRSA; /* RSA available */ byte haveECC; /* ECC available */ @@ -1960,6 +2158,11 @@ struct WOLFSSL_CTX { byte groupMessages; /* group handshake messages before sending */ byte minDowngrade; /* minimum downgrade version */ byte haveEMS; /* have extended master secret extension */ + byte useClientOrder; /* Use client's cipher preference order */ +#ifdef WOLFSSL_TLS13 + byte noTicketTls13; /* Server won't create new Ticket */ + byte noPskDheKe; /* Don't use (EC)DHE with PSK */ +#endif #if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) byte dtlsSctp; /* DTLS-over-SCTP mode */ word16 dtlsMtuSz; /* DTLS MTU size */ @@ -1972,6 +2175,9 @@ struct WOLFSSL_CTX { #endif #ifdef HAVE_ECC short minEccKeySz; /* minimum ECC key size */ +#endif +#ifdef OPENSSL_EXTRA + unsigned long mask; /* store SSL_OP_ flags */ #endif CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; @@ -1987,23 +2193,33 @@ struct WOLFSSL_CTX { word32 timeout; /* session timeout */ #ifdef HAVE_ECC word16 eccTempKeySz; /* in octets 20 - 66 */ + word32 ecdhCurveOID; /* curve Ecc_Sum */ word32 pkCurveOID; /* curve Ecc_Sum */ #endif #ifndef NO_PSK byte havePSK; /* psk key set by user */ wc_psk_client_callback client_psk_cb; /* client callback */ wc_psk_server_callback server_psk_cb; /* server callback */ - char server_hint[MAX_PSK_ID_LEN]; + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; #endif /* NO_PSK */ #ifdef HAVE_ANON byte haveAnon; /* User wants to allow Anon suites */ #endif /* HAVE_ANON */ #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - pem_password_cb passwd_cb; + pem_password_cb* passwd_cb; void* userdata; + WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */ + byte readAhead; + void* userPRFArg; /* passed to prf callback */ #endif /* OPENSSL_EXTRA */ -#ifdef HAVE_STUNNEL +#ifdef HAVE_EX_DATA void* ex_data[MAX_EX_DATA]; +#endif +#if defined(HAVE_ALPN) && (defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; +#endif +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) CallbackSniRecv sniRecvCb; void* sniRecvCbArg; #endif @@ -2027,6 +2243,9 @@ struct WOLFSSL_CTX { void* ticketEncCtx; /* session encrypt context */ int ticketHint; /* ticket hint in seconds */ #endif + #ifdef HAVE_SUPPORTED_CURVES + byte userCurves; /* indicates user called wolfSSL_CTX_UseSupportedCurve */ + #endif #endif #ifdef ATOMIC_USER CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */ @@ -2048,6 +2267,11 @@ struct WOLFSSL_CTX { #ifdef HAVE_WOLF_EVENT WOLF_EVENT_QUEUE event_queue; #endif /* HAVE_WOLF_EVENT */ +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*); + int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*); + void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*); +#endif }; @@ -2065,6 +2289,7 @@ int DeriveTlsKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 inSz, word16 sz); + #ifndef NO_CERTS WOLFSSL_LOCAL int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); @@ -2130,10 +2355,11 @@ enum KeyExchangeAlgorithm { /* Supported Authentication Schemes */ enum SignatureAlgorithm { - anonymous_sa_algo, - rsa_sa_algo, - dsa_sa_algo, - ecc_dsa_sa_algo + anonymous_sa_algo = 0, + rsa_sa_algo = 1, + dsa_sa_algo = 2, + ecc_dsa_sa_algo = 3, + rsa_pss_sa_algo = 8 }; @@ -2175,6 +2401,10 @@ typedef struct Ciphers { #endif #if defined(BUILD_AES) || defined(BUILD_AESGCM) Aes* aes; + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + byte* additional; + byte* nonce; + #endif #endif #ifdef HAVE_CAMELLIA Camellia* cam; @@ -2191,6 +2421,7 @@ typedef struct Ciphers { #ifdef HAVE_IDEA Idea* idea; #endif + byte state; byte setup; /* have we set it up flag for detection */ } Ciphers; @@ -2213,10 +2444,12 @@ WOLFSSL_LOCAL void FreeCiphers(WOLFSSL* ssl); /* hashes type */ typedef struct Hashes { - #ifndef NO_OLD_TLS + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) byte md5[MD5_DIGEST_SIZE]; #endif - byte sha[SHA_DIGEST_SIZE]; + #if !defined(NO_SHA) + byte sha[SHA_DIGEST_SIZE]; + #endif #ifndef NO_SHA256 byte sha256[SHA256_DIGEST_SIZE]; #endif @@ -2228,6 +2461,21 @@ typedef struct Hashes { #endif } Hashes; +WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); + +#ifdef WOLFSSL_TLS13 +typedef union Digest { +#ifndef NO_WOLFSSL_SHA256 + Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA384 + Sha384 sha384; +#endif +#ifdef WOLFSSL_SHA512 + Sha512 sha512; +#endif +} Digest; +#endif /* Static x509 buffer */ typedef struct x509_buffer { @@ -2245,30 +2493,41 @@ struct WOLFSSL_X509_CHAIN { /* wolfSSL session type */ struct WOLFSSL_SESSION { - word32 bornOn; /* create time in seconds */ - word32 timeout; /* timeout in seconds */ - byte sessionID[ID_LEN]; /* id for protocol */ - byte sessionIDSz; - byte masterSecret[SECRET_LEN]; /* stored secret */ - word16 haveEMS; /* ext master secret flag */ + word32 bornOn; /* create time in seconds */ + word32 timeout; /* timeout in seconds */ + byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionIDSz; + byte masterSecret[SECRET_LEN]; /* stored secret */ + word16 haveEMS; /* ext master secret flag */ #ifdef SESSION_CERTS - WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ - ProtocolVersion version; /* which version was used */ - byte cipherSuite0; /* first byte, normally 0 */ - byte cipherSuite; /* 2nd byte, actual suite */ + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ProtocolVersion version; /* which version was used */ + byte cipherSuite0; /* first byte, normally 0 */ + byte cipherSuite; /* 2nd byte, actual suite */ #endif #ifndef NO_CLIENT_CACHE - word16 idLen; /* serverID length */ - byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ + word16 idLen; /* serverID length */ + byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ #endif #ifdef HAVE_SESSION_TICKET - byte* ticket; - word16 ticketLen; - byte staticTicket[SESSION_TICKET_LEN]; - byte isDynamic; + #ifdef WOLFSSL_TLS13 + byte namedGroup; + word32 ticketSeen; /* Time ticket seen (ms) */ + word32 ticketAdd; /* Added by client */ + #endif + byte* ticket; + word16 ticketLen; + byte staticTicket[SESSION_TICKET_LEN]; + byte isDynamic; #endif -#ifdef HAVE_STUNNEL - void* ex_data[MAX_EX_DATA]; +#ifdef HAVE_EXT_CACHE + byte isAlloced; +#endif +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; #endif }; @@ -2304,9 +2563,12 @@ enum ConnectState { enum AcceptState { ACCEPT_BEGIN = 0, ACCEPT_CLIENT_HELLO_DONE, + ACCEPT_HELLO_RETRY_REQUEST_DONE, ACCEPT_FIRST_REPLY_DONE, SERVER_HELLO_SENT, + SERVER_EXTENSIONS_SENT, CERT_SENT, + CERT_VERIFY_SENT, CERT_STATUS_SENT, KEY_EXCHANGE_SENT, CERT_REQ_SENT, @@ -2318,16 +2580,6 @@ enum AcceptState { ACCEPT_THIRD_REPLY_DONE }; -/* sub-states for send/do key share (key exchange) */ -enum KeyShareState { - KEYSHARE_BEGIN = 0, - KEYSHARE_BUILD, - KEYSHARE_DO, - KEYSHARE_VERIFY, - KEYSHARE_FINALIZE, - KEYSHARE_END -}; - /* buffers for struct WOLFSSL */ typedef struct Buffers { bufferStatic inputBuffer; @@ -2349,12 +2601,16 @@ typedef struct Buffers { buffer serverDH_G; /* WOLFSSL_CTX owns, unless we own */ buffer serverDH_Pub; buffer serverDH_Priv; + DhKey* serverDH_Key; #endif #ifndef NO_CERTS DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ /* chain after self, in DER, with leading size for each cert */ +#ifdef WOLFSSL_TLS13 + int certChainCnt; +#endif #endif #ifdef WOLFSSL_DTLS WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ @@ -2372,17 +2628,33 @@ typedef struct Buffers { #endif /* HAVE_PK_CALLBACKS */ } Buffers; +/* sub-states for send/do key share (key exchange) */ +enum asyncState { + TLS_ASYNC_BEGIN = 0, + TLS_ASYNC_BUILD, + TLS_ASYNC_DO, + TLS_ASYNC_VERIFY, + TLS_ASYNC_FINALIZE, + TLS_ASYNC_END +}; + typedef struct Options { #ifndef NO_PSK wc_psk_client_callback client_psk_cb; wc_psk_server_callback server_psk_cb; word16 havePSK:1; /* psk key set by user */ #endif /* NO_PSK */ +#ifdef OPENSSL_EXTRA + unsigned long mask; /* store SSL_OP_ flags */ +#endif /* on/off or small bit flags, optimize layout */ word16 sendVerify:2; /* false = 0, true = 1, sendBlank = 2 */ word16 sessionCacheOff:1; word16 sessionCacheFlushOff:1; +#ifdef HAVE_EXT_CACHE + word16 internalCacheOff:1; +#endif word16 side:1; /* client or server end */ word16 verifyPeer:1; word16 verifyNone:1; @@ -2393,6 +2665,7 @@ typedef struct Options { word16 haveSessionId:1; /* server may not send */ word16 tls:1; /* using TLS ? */ word16 tls1_1:1; /* using TLSv1.1+ ? */ + word16 tls1_3:1; /* using TLSv1.3+ ? */ word16 dtls:1; /* using datagrams ? */ word16 connReset:1; /* has the peer reset */ word16 isClosed:1; /* if we consider conn closed */ @@ -2410,6 +2683,7 @@ typedef struct Options { word16 havePeerVerify:1; /* and peer's cert verify */ word16 usingPSK_cipher:1; /* are using psk as cipher */ word16 usingAnon_cipher:1; /* are we using an anon cipher */ + word16 noPskDheKe:1; /* Don't use (EC)DHE with PSK */ word16 sendAlertState:1; /* nonblocking resume */ word16 partialWrite:1; /* only one msg per write call */ word16 quietShutdown:1; /* don't send close notify */ @@ -2429,6 +2703,9 @@ typedef struct Options { word16 createTicket:1; /* Server to create new Ticket */ word16 useTicket:1; /* Use Ticket not session cache */ word16 rejectTicket:1; /* Callback rejected ticket */ +#ifdef WOLFSSL_TLS13 + word16 noTicketTls13:1; /* Server won't create new Ticket */ +#endif #endif #ifdef WOLFSSL_DTLS word16 dtlsHsRetain:1; /* DTLS retaining HS data */ @@ -2437,6 +2714,11 @@ typedef struct Options { #endif #endif word16 haveEMS:1; /* using extended master secret */ +#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) + word16 userCurves:1; /* indicates user called wolfSSL_UseSupportedCurve */ +#endif + word16 keepResources:1; /* Keep resources after handshake */ + word16 useClientOrder:1; /* Use client's cipher order */ /* need full byte values for this section */ byte processReply; /* nonblocking resume */ @@ -2449,8 +2731,8 @@ typedef struct Options { byte minDowngrade; /* minimum downgrade version */ byte connectState; /* nonblocking resume */ byte acceptState; /* nonblocking resume */ - byte keyShareState; /* sub-state for key share (key exchange). - See enum KeyShareState. */ + byte asyncState; /* sub-state for enum asyncState */ + byte buildMsgState; /* sub-state for enum buildMsgState */ #ifndef NO_DH word16 minDhKeySz; /* minimum DH key size */ word16 dhKeySz; /* actual DH key size */ @@ -2466,20 +2748,25 @@ typedef struct Options { typedef struct Arrays { byte* pendingMsg; /* defrag buffer */ + byte* preMasterSecret; word32 preMasterSz; /* differs for DH, actual size */ word32 pendingMsgSz; /* defrag buffer size */ word32 pendingMsgOffset; /* current offset into defrag buffer */ #ifndef NO_PSK word32 psk_keySz; /* actual size */ - char client_identity[MAX_PSK_ID_LEN]; - char server_hint[MAX_PSK_ID_LEN]; + char client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN]; + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; byte psk_key[MAX_PSK_KEY_LEN]; #endif byte clientRandom[RAN_LEN]; byte serverRandom[RAN_LEN]; byte sessionID[ID_LEN]; byte sessionIDSz; - byte preMasterSecret[ENCRYPT_LEN]; +#ifdef WOLFSSL_TLS13 + byte clientSecret[SECRET_LEN]; + byte serverSecret[SECRET_LEN]; + byte secret[SECRET_LEN]; +#endif byte masterSecret[SECRET_LEN]; #ifdef WOLFSSL_DTLS byte cookie[MAX_COOKIE_LEN]; @@ -2500,8 +2787,11 @@ struct WOLFSSL_STACK { unsigned long num; /* number of nodes in stack * (saftey measure for freeing and shortcut for count) */ union { - WOLFSSL_X509* x509; - WOLFSSL_BIO* bio; + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* name; + WOLFSSL_BIO* bio; + WOLFSSL_ASN1_OBJECT* obj; + char* string; } data; WOLFSSL_STACK* next; }; @@ -2565,9 +2855,24 @@ struct WOLFSSL_X509 { void* heap; /* heap hint */ byte dynamicMemory; /* dynamic memory flag */ byte isCa; +#ifdef WOLFSSL_CERT_EXT + char certPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int certPoliciesNb; +#endif /* WOLFSSL_CERT_EXT */ #ifdef OPENSSL_EXTRA +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; +#endif word32 pathLength; word16 keyUsage; + byte CRLdistSet; + byte CRLdistCrit; + byte* CRLInfo; + int CRLInfoSz; + byte authInfoSet; + byte authInfoCrit; + byte* authInfo; + int authInfoSz; byte basicConstSet; byte basicConstCrit; byte basicConstPlSet; @@ -2583,6 +2888,10 @@ struct WOLFSSL_X509 { word32 subjKeyIdSz; byte keyUsageSet; byte keyUsageCrit; + byte extKeyUsageCrit; + byte* extKeyUsageSrc; + word32 extKeyUsageSz; + word32 extKeyUsageCount; #endif /* OPENSSL_EXTRA */ }; @@ -2641,10 +2950,12 @@ typedef struct DtlsMsg { /* Handshake messages received from peer (plus change cipher */ typedef struct MsgsReceived { word16 got_hello_request:1; - word16 got_client_hello:1; + word16 got_client_hello:2; word16 got_server_hello:1; word16 got_hello_verify_request:1; word16 got_session_ticket:1; + word16 got_hello_retry_request:1; + word16 got_encrypted_extensions:1; word16 got_certificate:1; word16 got_certificate_status:1; word16 got_server_key_exchange:1; @@ -2653,6 +2964,7 @@ typedef struct MsgsReceived { word16 got_certificate_verify:1; word16 got_client_key_exchange:1; word16 got_finished:1; + word16 got_key_update:1; word16 got_change_cipher:1; } MsgsReceived; @@ -2661,14 +2973,12 @@ typedef struct MsgsReceived { typedef struct HS_Hashes { Hashes verifyHashes; Hashes certHashes; /* for cert verify */ -#ifndef NO_OLD_TLS #ifndef NO_SHA Sha hashSha; /* sha hash of handshake msgs */ #endif -#ifndef NO_MD5 +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) Md5 hashMd5; /* md5 hash of handshake msgs */ #endif -#endif /* NO_OLD_TLS */ #ifndef NO_SHA256 Sha256 hashSha256; /* sha256 hash of handshake msgs */ #endif @@ -2681,6 +2991,33 @@ typedef struct HS_Hashes { } HS_Hashes; +#ifdef WOLFSSL_ASYNC_CRYPT + #define MAX_ASYNC_ARGS 16 + typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs); + + struct WOLFSSL_ASYNC { + WC_ASYNC_DEV* dev; + FreeArgsCb freeArgs; /* function pointer to cleanup args */ + word32 args[MAX_ASYNC_ARGS]; /* holder for current args */ + }; +#endif + +#ifdef HAVE_WRITE_DUP + + #define WRITE_DUP_SIDE 1 + #define READ_DUP_SIDE 2 + + typedef struct WriteDup { + wolfSSL_Mutex dupMutex; /* reference count mutex */ + int dupCount; /* reference count */ + int dupErr; /* under dupMutex, pass to other side */ + } WriteDup; + + WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl); + WOLFSSL_LOCAL int NotifyWriteSide(WOLFSSL* ssl, int err); +#endif /* HAVE_WRITE_DUP */ + + /* wolfSSL ssl type */ struct WOLFSSL { WOLFSSL_CTX* ctx; @@ -2693,6 +3030,11 @@ struct WOLFSSL { void* verifyCbCtx; /* cert verify callback user ctx*/ VerifyCallback verifyCallback; /* cert verification callback */ void* heap; /* for user overrides */ +#ifdef HAVE_WRITE_DUP + WriteDup* dupWrite; /* valid pointer indicates ON */ + /* side that decrements dupCount to zero frees overall structure */ + byte dupSide; /* write side or read side */ +#endif #ifdef WOLFSSL_STATIC_MEMORY WOLFSSL_HEAP_HINT heap_hint; #endif @@ -2701,18 +3043,19 @@ struct WOLFSSL { void* hsDoneCtx; /* user handshake cb context */ #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptSSLState async; - AsyncCryptDev asyncDev; + struct WOLFSSL_ASYNC async; #endif - void* sigKey; /* RsaKey or ecc_key allocated from heap */ - word32 sigType; /* Type of sigKey */ - word32 sigLen; /* Actual signature length */ + void* hsKey; /* Handshake key (RsaKey or ecc_key) allocated from heap */ + word32 hsType; /* Type of Handshake key (hsKey) */ WOLFSSL_CIPHER cipher; hmacfp hmac; Ciphers encrypt; Ciphers decrypt; Buffers buffers; WOLFSSL_SESSION session; +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION* extSession; +#endif WOLFSSL_ALERT_HISTORY alert_history; int error; int rfd; /* read file descriptor */ @@ -2732,6 +3075,11 @@ struct WOLFSSL { #ifdef OPENSSL_EXTRA WOLFSSL_BIO* biord; /* socket bio read to free/close */ WOLFSSL_BIO* biowr; /* socket bio write to free/close */ + unsigned long peerVerifyRet; + byte readAhead; +#ifdef HAVE_PK_CALLBACKS + void* loggingCtx; /* logging callback argument */ +#endif #endif #ifndef NO_RSA RsaKey* peerRsaKey; @@ -2749,6 +3097,9 @@ struct WOLFSSL { byte maxRequest; byte user_set_QSHSchemes; #endif +#ifdef WOLFSSL_TLS13 + word16 namedGroup; +#endif #ifdef HAVE_NTRU word16 peerNtruKeyLen; byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; @@ -2758,7 +3109,9 @@ struct WOLFSSL { ecc_key* peerEccKey; /* peer's ECDHE key */ ecc_key* peerEccDsaKey; /* peer's ECDSA key */ ecc_key* eccTempKey; /* private ECDHE key */ + int eccVerifyRes; word32 pkCurveOID; /* curve Ecc_Sum */ + word32 ecdhCurveOID; /* curve Ecc_Sum */ word16 eccTempKeySz; /* in octets 20 - 66 */ byte peerEccKeyPresent; byte peerEccDsaKeyPresent; @@ -2794,6 +3147,9 @@ struct WOLFSSL { CallbackFuzzer fuzzerCb; /* for testing with using fuzzer */ void* fuzzerCtx; /* user defined pointer */ #endif +#ifdef WOLFSSL_TLS13 + buffer clientCertCtx; /* Certificate context in request */ +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509 peerCert; /* X509 peer cert */ #endif @@ -2803,8 +3159,8 @@ struct WOLFSSL { flag found in buffers.weOwnCert) */ #endif byte keepCert; /* keep certificate after handshake */ -#if defined(FORTRESS) || defined(HAVE_STUNNEL) - void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ #endif int devId; /* async device id to use */ #ifdef HAVE_ONE_TIME_AUTH @@ -2830,6 +3186,10 @@ struct WOLFSSL { #endif /* user turned on */ #ifdef HAVE_ALPN char* alpn_client_list; /* keep the client's list */ + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; + #endif #endif /* of accepted protocols */ #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) CallbackSessionTicket session_ticket_cb; @@ -2837,6 +3197,13 @@ struct WOLFSSL { byte expect_session_ticket; #endif #endif /* HAVE_TLS_EXTENSIONS */ +#ifdef OPENSSL_EXTRA + byte* ocspResp; + int ocspRespSz; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + char* url; +#endif +#endif #ifdef HAVE_NETX NetX_Ctx nxCtx; /* NetX IO Context */ #endif @@ -2867,16 +3234,13 @@ struct WOLFSSL { #ifdef WOLFSSL_JNI void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */ #endif /* WOLFSSL_JNI */ -#ifdef HAVE_WOLF_EVENT - WOLF_EVENT event; -#endif /* HAVE_WOLF_EVENT */ }; WOLFSSL_LOCAL -int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*); +int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int); WOLFSSL_LOCAL -int InitSSL(WOLFSSL*, WOLFSSL_CTX*); +int InitSSL(WOLFSSL*, WOLFSSL_CTX*, int); WOLFSSL_LOCAL void FreeSSL(WOLFSSL*, void* heap); WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */ @@ -2913,6 +3277,11 @@ typedef struct EncryptedInfo { WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl); + + #ifdef OPENSSL_EXTRA + WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName, + size_t domainNameLen); + #endif #endif @@ -2970,6 +3339,8 @@ enum HandShakeType { server_hello = 2, hello_verify_request = 3, /* DTLS addition */ session_ticket = 4, + hello_retry_request = 6, + encrypted_extensions = 8, certificate = 11, server_key_exchange = 12, certificate_request = 13, @@ -2978,6 +3349,7 @@ enum HandShakeType { client_key_exchange = 16, finished = 20, certificate_status = 22, + key_update = 24, change_cipher_hs = 55, /* simulate unique handshake type for sanity checks. record layer change_cipher conflicts with handshake finished */ @@ -2997,13 +3369,27 @@ WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*); WOLFSSL_LOCAL int SendTicket(WOLFSSL*); WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32); WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*); +WOLFSSL_LOCAL int SendTls13EncryptedExtensions(WOLFSSL*); +#endif WOLFSSL_LOCAL int SendCertificate(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int SendTls13Certificate(WOLFSSL*); +#endif WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int SendTls13CertificateRequest(WOLFSSL*); +#endif WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*); WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*); WOLFSSL_LOCAL int SendBuffered(WOLFSSL*); WOLFSSL_LOCAL int ReceiveData(WOLFSSL*, byte*, int, int); WOLFSSL_LOCAL int SendFinished(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int SendTls13Finished(WOLFSSL*); +WOLFSSL_LOCAL int SendTls13NewSessionTicket(WOLFSSL*); +#endif WOLFSSL_LOCAL int SendAlert(WOLFSSL*, int, int); WOLFSSL_LOCAL int ProcessReply(WOLFSSL*); @@ -3016,6 +3402,7 @@ WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData); WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); +WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv); WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); @@ -3031,7 +3418,8 @@ WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, - byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx); + byte** out, int sigAlgo, int hashAlgo, 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, @@ -3083,12 +3471,20 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #ifndef NO_WOLFSSL_CLIENT WOLFSSL_LOCAL int SendClientHello(WOLFSSL*); + #ifdef WOLFSSL_TLS13 + WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL*); + #endif WOLFSSL_LOCAL int SendClientKeyExchange(WOLFSSL*); WOLFSSL_LOCAL int SendCertificateVerify(WOLFSSL*); #endif /* NO_WOLFSSL_CLIENT */ + WOLFSSL_LOCAL int SendTls13CertificateVerify(WOLFSSL*); + #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL int SendServerHello(WOLFSSL*); + #ifdef WOLFSSL_TLS13 + WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*); + #endif WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*); #endif /* NO_WOLFSSL_SERVER */ @@ -3115,7 +3511,9 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #endif /* NO_TLS */ - +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void); +#endif WOLFSSL_LOCAL word32 LowResTimer(void); #ifndef NO_CERTS @@ -3126,7 +3524,7 @@ WOLFSSL_LOCAL word32 LowResTimer(void); WOLFSSL_LOCAL int CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*); #endif -/* used by ssl.c and wolfssl_int.c */ +/* used by ssl.c and internal.c */ WOLFSSL_LOCAL void c32to24(word32 in, word24 out); WOLFSSL_LOCAL const char* const* GetCipherNames(void); @@ -3146,27 +3544,40 @@ WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); #ifndef NO_DH - WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, + WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz); - WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, - byte* priv, word32* privSz, - byte* pub, word32* pubSz, + WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, byte* agree, word32* agreeSz); -#endif +#endif /* !NO_DH */ #ifdef HAVE_ECC WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer); #endif +WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl); +WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl); + WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int inSz, int type, int hashOutput, - int sizeOnly); + int sizeOnly, int asyncOkay); + +#ifdef WOLFSSL_TLS13 +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly); +#endif + +WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey); +WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey); + +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_LOCAL int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state); + WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, + word32 flags); +#endif + #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/io.h b/wolfssl/io.h new file mode 100644 index 0000000000..51d7545a38 --- /dev/null +++ b/wolfssl/io.h @@ -0,0 +1,413 @@ +/* io.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 WOLFSSL_IO_H +#define WOLFSSL_IO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* OCSP and CRL_IO require HTTP client */ +#if defined(HAVE_OCSP) || defined(HAVE_CRL_IO) + #ifndef HAVE_HTTP_CLIENT + #define HAVE_HTTP_CLIENT + #endif +#endif + +#if !defined(WOLFSSL_USER_IO) + #ifndef USE_WOLFSSL_IO + #define USE_WOLFSSL_IO + #endif +#endif + + +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifndef USE_WINDOWS_API + #ifdef WOLFSSL_LWIP + /* lwIP needs to be configured to use sockets API in this mode */ + /* LWIP_SOCKET 1 in lwip/opt.h or in build */ + #include "lwip/sockets.h" + #include + #ifndef LWIP_PROVIDE_ERRNO + #define LWIP_PROVIDE_ERRNO 1 + #endif + #elif defined(FREESCALE_MQX) + #include + #include + #elif defined(FREESCALE_KSDK_MQX) + #include + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #if !defined(WOLFSSL_MDK_ARM) + #include "cmsis_os.h" + #include "rl_net.h" + #else + #include + #endif + #include "errno.h" + #define SOCKET_T int + #elif defined(WOLFSSL_TIRTOS) + #include + #elif defined(FREERTOS_TCP) + #include "FreeRTOS_Sockets.h" + #elif defined(WOLFSSL_IAR_ARM) + /* nothing */ + #elif defined(WOLFSSL_VXWORKS) + #include + #include + #elif defined(WOLFSSL_ATMEL) + #include "socket/include/socket.h" + #elif defined(INTIME_RTOS) + #undef MIN + #undef MAX + #include + #include + #include + #include + #include + #include + /* defines these, to avoid conflict, do undef */ + #undef SOCKADDR + #undef SOCKADDR_IN + #elif defined(WOLFSSL_PRCONNECT_PRO) + #include + #include + #include + #include + #include + #include + #include + #elif !defined(WOLFSSL_NO_SOCK) + #include + #include + #ifndef EBSNET + #include + #endif + #include + + #if defined(HAVE_RTP_SYS) + #include + #elif defined(EBSNET) + #include "rtipapi.h" /* errno */ + #include "socket.h" + #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) + #include + #include + #include + #include + #ifdef __PPU + #include + #else + #include + #endif + #endif + #endif +#endif /* USE_WINDOWS_API */ + +#ifdef __sun + #include +#endif + +#ifdef USE_WINDOWS_API + /* no epipe yet */ + #ifndef WSAEPIPE + #define WSAEPIPE -12345 + #endif + #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK + #define SOCKET_EAGAIN WSAETIMEDOUT + #define SOCKET_ECONNRESET WSAECONNRESET + #define SOCKET_EINTR WSAEINTR + #define SOCKET_EPIPE WSAEPIPE + #define SOCKET_ECONNREFUSED WSAENOTCONN + #define SOCKET_ECONNABORTED WSAECONNABORTED + #define close(s) closesocket(s) +#elif defined(__PPU) + #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK + #define SOCKET_EAGAIN SYS_NET_EAGAIN + #define SOCKET_ECONNRESET SYS_NET_ECONNRESET + #define SOCKET_EINTR SYS_NET_EINTR + #define SOCKET_EPIPE SYS_NET_EPIPE + #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED + #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + /* RTCS old I/O doesn't have an EWOULDBLOCK */ + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED + #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED + #else + #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK + #define SOCKET_EAGAIN NIO_EAGAIN + #define SOCKET_ECONNRESET NIO_ECONNRESET + #define SOCKET_EINTR NIO_EINTR + #define SOCKET_EPIPE NIO_EPIPE + #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED + #define SOCKET_ECONNABORTED NIO_ECONNABORTED + #endif +#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + #if !defined(WOLFSSL_MDK_ARM) + #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK + #define SOCKET_EAGAIN BSD_ERROR_LOCKED + #define SOCKET_ECONNRESET BSD_ERROR_CLOSED + #define SOCKET_EINTR BSD_ERROR + #define SOCKET_EPIPE BSD_ERROR + #define SOCKET_ECONNREFUSED BSD_ERROR + #define SOCKET_ECONNABORTED BSD_ERROR + #else + #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK + #define SOCKET_EAGAIN SCK_ELOCKED + #define SOCKET_ECONNRESET SCK_ECLOSED + #define SOCKET_EINTR SCK_ERROR + #define SOCKET_EPIPE SCK_ERROR + #define SOCKET_ECONNREFUSED SCK_ERROR + #define SOCKET_ECONNABORTED SCK_ERROR + #endif +#elif defined(WOLFSSL_PICOTCP) + #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN + #define SOCKET_EAGAIN PICO_ERR_EAGAIN + #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET + #define SOCKET_EINTR PICO_ERR_EINTR + #define SOCKET_EPIPE PICO_ERR_EIO + #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED + #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN +#elif defined(FREERTOS_TCP) + #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK + #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK + #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR + #define SOCKET_EINTR FREERTOS_SOCKET_ERROR + #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR +#else + #define SOCKET_EWOULDBLOCK EWOULDBLOCK + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET ECONNRESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED ECONNREFUSED + #define SOCKET_ECONNABORTED ECONNABORTED +#endif /* USE_WINDOWS_API */ + + +#ifdef DEVKITPRO + /* from network.h */ + int net_send(int, const void*, int, unsigned int); + int net_recv(int, void*, int, unsigned int); + #define SEND_FUNCTION net_send + #define RECV_FUNCTION net_recv +#elif defined(WOLFSSL_LWIP) + #define SEND_FUNCTION lwip_send + #define RECV_FUNCTION lwip_recv +#elif defined(WOLFSSL_PICOTCP) + #define SEND_FUNCTION pico_send + #define RECV_FUNCTION pico_recv +#elif defined(FREERTOS_TCP) + #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) + #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) +#else + #define SEND_FUNCTION send + #define RECV_FUNCTION recv + #if !defined(HAVE_SOCKADDR) && !defined(WOLFSSL_NO_SOCK) + #define HAVE_SOCKADDR + #endif +#endif + +#ifdef USE_WINDOWS_API + typedef unsigned int SOCKET_T; +#else + typedef int SOCKET_T; +#endif + +#ifndef WOLFSSL_NO_SOCK + #ifndef XSOCKLENT + #ifdef USE_WINDOWS_API + #define XSOCKLENT int + #else + #define XSOCKLENT socklen_t + #endif + #endif + + /* Socket Addr Support */ + #ifdef HAVE_SOCKADDR + typedef struct sockaddr SOCKADDR; + typedef struct sockaddr_storage SOCKADDR_S; + typedef struct sockaddr_in SOCKADDR_IN; + #ifdef WOLFSSL_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN6; + #endif + typedef struct hostent HOSTENT; + #endif /* HAVE_SOCKADDR */ + + #ifdef HAVE_GETADDRINFO + typedef struct addrinfo ADDRINFO; + #endif +#endif /* WOLFSSL_NO_SOCK */ + + +/* IO API's */ +#ifdef HAVE_IO_TIMEOUT + WOLFSSL_API int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking); + WOLFSSL_API void wolfIO_SetTimeout(int to_sec);; + WOLFSSL_API int wolfIO_Select(SOCKET_T sockfd, int to_sec); +#endif +WOLFSSL_API int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, + unsigned short port, int to_sec); +WOLFSSL_API int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags); +WOLFSSL_API int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags); + +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#if defined(USE_WOLFSSL_IO) + /* default IO callbacks */ + WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + + #ifdef WOLFSSL_DTLS + WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*); + WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, + int sz, void*); + #ifdef WOLFSSL_SESSION_EXPORT + WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + #endif /* WOLFSSL_SESSION_EXPORT */ + #endif /* WOLFSSL_DTLS */ +#endif /* USE_WOLFSSL_IO */ + +#ifdef HAVE_OCSP + WOLFSSL_API int wolfIO_HttpBuildRequestOcsp(const char* domainName, + const char* path, int ocspReqSz, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponseOcsp(int sfd, + unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz, + void* heap); + + WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*, + int, unsigned char**); + WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*); +#endif + +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, + unsigned char* httpBuf, int httpBufSz); + + WOLFSSL_API int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, + int urlSz); +#endif + + +#if defined(HAVE_HTTP_CLIENT) + WOLFSSL_API int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, + char* outPath, unsigned short* outPort); + + WOLFSSL_API int wolfIO_HttpBuildRequest(const char* reqType, + const char* domainName, const char* path, int pathLen, int reqSz, + const char* contentType, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponse(int sfd, const char* appStr, + unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz, + int dynType, void* heap); +#endif /* HAVE_HTTP_CLIENT */ + + +/* I/O callbacks */ +typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); +WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); + +WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); +WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); + +WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); +WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); + + +#ifdef HAVE_NETX + WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx); + + WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, + ULONG waitoption); +#endif /* HAVE_NETX */ + +#ifdef WOLFSSL_DTLS + typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, + void* ctx); + WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie); + WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); + WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); + + #ifdef WOLFSSL_SESSION_EXPORT + typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + + WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, CallbackGetPeer); + WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, CallbackSetPeer); + #endif /* WOLFSSL_SESSION_EXPORT */ +#endif + + + +#ifndef XINET_NTOP + #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) +#endif +#ifndef XINET_PTON + #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) +#endif +#ifndef XHTONS + #define XHTONS(a) htons((a)) +#endif +#ifndef XNTOHS + #define XNTOHS(a) ntohs((a)) +#endif + +#ifndef WOLFSSL_IP4 + #define WOLFSSL_IP4 AF_INET +#endif +#ifndef WOLFSSL_IP6 + #define WOLFSSL_IP6 AF_INET6 +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_IO_H */ diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 5331245c94..844ce272e2 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -37,6 +37,14 @@ typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; + +typedef struct OcspRequest WOLFSSL_OCSP_CERTID; + +typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; +#endif + WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); @@ -45,6 +53,48 @@ WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*, WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +WOLFSSL_API int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd); +WOLFSSL_API const char *wolfSSL_OCSP_cert_status_str(long s); +WOLFSSL_API int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec); + +WOLFSSL_API void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId); +WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer); + +WOLFSSL_API void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse); +WOLFSSL_API int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags); + +WOLFSSL_API void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len); +WOLFSSL_API int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data); +WOLFSSL_API int wolfSSL_OCSP_response_status(OcspResponse *response); +WOLFSSL_API const char *wolfSSL_OCSP_response_status_str(long s); +WOLFSSL_API WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic( + OcspResponse* response); + +WOLFSSL_API OcspRequest* wolfSSL_OCSP_REQUEST_new(void); +WOLFSSL_API void wolfSSL_OCSP_REQUEST_free(OcspRequest* request); +WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, + unsigned char** data); +WOLFSSL_API WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid); + +#endif + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/aes.h b/wolfssl/openssl/aes.h new file mode 100644 index 0000000000..418914808a --- /dev/null +++ b/wolfssl/openssl/aes.h @@ -0,0 +1,73 @@ +/* aes.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 + */ + + + +/* aes.h defines mini des openssl compatibility layer + * + */ + + +#ifndef WOLFSSL_AES_H_ +#define WOLFSSL_AES_H_ + +#include + +#ifndef NO_AES +#ifdef WOLFSSL_AES_DIRECT + +#ifdef __cplusplus + extern "C" { +#endif + + +typedef Aes AES_KEY; + +WOLFSSL_API void wolfSSL_AES_set_encrypt_key + (const unsigned char *, const int bits, AES_KEY *); +WOLFSSL_API void wolfSSL_AES_set_decrypt_key + (const unsigned char *, const int bits, AES_KEY *); +WOLFSSL_API void wolfSSL_AES_encrypt + (const unsigned char* input, unsigned char* output, AES_KEY *); +WOLFSSL_API void wolfSSL_AES_decrypt + (const unsigned char* input, unsigned char* output, AES_KEY *); + +#define AES_set_encrypt_key wolfSSL_AES_set_encrypt_key +#define AES_set_decrypt_key wolfSSL_AES_set_decrypt_key +#define AES_encrypt wolfSSL_AES_encrypt +#define AES_decrypt wolfSSL_AES_decrypt + +#define wolfSSL_AES_set_encrypt_key(key, bits, aes) \ + wc_AesSetKey(aes, key, ((bits)/8), NULL, AES_ENCRYPTION) +#define wolfSSL_AES_set_decrypt_key(key, bits, aes) \ + wc_AesSetKey(aes, key, ((bits)/8), NULL, AES_DECRYPTION) + +#define wolfSSL_AES_encrypt(in, out, aes) wc_AesEncryptDirect(aes, out, in) +#define wolfSSL_AES_decrypt(in, out, aes) wc_AesDecryptDirect(aes, out, in) + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_AES_DIRECT */ +#endif /* NO_AES */ + +#endif /* WOLFSSL_DES_H_ */ diff --git a/wolfssl/openssl/bn.h b/wolfssl/openssl/bn.h index c56a3cfcad..ba5648a883 100644 --- a/wolfssl/openssl/bn.h +++ b/wolfssl/openssl/bn.h @@ -35,7 +35,8 @@ WOLFSSL_API int wolfSSL_BN_sub(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*); WOLFSSL_API int wolfSSL_BN_mod(WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, const WOLFSSL_BIGNUM*, const WOLFSSL_BN_CTX*); - +WOLFSSL_API int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx); WOLFSSL_API const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void); @@ -109,6 +110,7 @@ typedef WOLFSSL_BN_GENCB BN_GENCB; #define BN_bin2bn wolfSSL_BN_bin2bn #define BN_mod wolfSSL_BN_mod +#define BN_mod_exp wolfSSL_BN_mod_exp #define BN_sub wolfSSL_BN_sub #define BN_value_one wolfSSL_BN_value_one @@ -148,4 +150,3 @@ typedef WOLFSSL_BN_GENCB BN_GENCB; #endif /* WOLFSSL__H_ */ - diff --git a/wolfssl/openssl/crypto.h b/wolfssl/openssl/crypto.h index 7032c24df3..e00c00a900 100644 --- a/wolfssl/openssl/crypto.h +++ b/wolfssl/openssl/crypto.h @@ -3,6 +3,7 @@ #ifndef WOLFSSL_CRYPTO_H_ #define WOLFSSL_CRYPTO_H_ +#include #include @@ -23,7 +24,7 @@ WOLFSSL_API unsigned long wolfSSLeay(void); #define SSLEAY_VERSION 0x0090600fL #define SSLEAY_VERSION_NUMBER SSLEAY_VERSION -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #define CRYPTO_set_mem_ex_functions wolfSSL_CRYPTO_set_mem_ex_functions #define FIPS_mode wolfSSL_FIPS_mode #define FIPS_mode_set wolfSSL_FIPS_mode_set @@ -41,7 +42,9 @@ typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int i #define CRYPTO_THREAD_r_lock wc_LockMutex #define CRYPTO_THREAD_unlock wc_UnLockMutex -#endif /* HAVE_STUNNEL */ +#define OPENSSL_malloc(a) XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL) + +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ #endif /* header */ diff --git a/wolfssl/openssl/des.h b/wolfssl/openssl/des.h index 0425511963..d154b72be1 100644 --- a/wolfssl/openssl/des.h +++ b/wolfssl/openssl/des.h @@ -53,9 +53,9 @@ enum { }; -WOLFSSL_API void wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, +WOLFSSL_API int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, WOLFSSL_DES_key_schedule* key); -WOLFSSL_API void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, +WOLFSSL_API int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, WOLFSSL_DES_key_schedule* key); WOLFSSL_API void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock*, WOLFSSL_DES_key_schedule*); diff --git a/wolfssl/openssl/dsa.h b/wolfssl/openssl/dsa.h index 98048bd9cf..a4c4a5f544 100644 --- a/wolfssl/openssl/dsa.h +++ b/wolfssl/openssl/dsa.h @@ -4,13 +4,19 @@ #ifndef WOLFSSL_DSA_H_ #define WOLFSSL_DSA_H_ -#include #include #ifdef __cplusplus extern "C" { #endif +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_DSA DSA; + struct WOLFSSL_DSA { WOLFSSL_BIGNUM* p; WOLFSSL_BIGNUM* q; diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 27fa7a600c..9802c3db36 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -3,7 +3,6 @@ #ifndef WOLFSSL_EC_H_ #define WOLFSSL_EC_H_ -#include #include #include @@ -44,6 +43,17 @@ enum { OPENSSL_EC_NAMED_CURVE = 0x001 }; +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +typedef WOLFSSL_EC_KEY EC_KEY; +typedef WOLFSSL_EC_GROUP EC_GROUP; +typedef WOLFSSL_EC_POINT EC_POINT; + struct WOLFSSL_EC_POINT { WOLFSSL_BIGNUM *X; WOLFSSL_BIGNUM *Y; @@ -57,6 +67,7 @@ struct WOLFSSL_EC_POINT { struct WOLFSSL_EC_GROUP { int curve_idx; /* index of curve, used by WolfSSL as reference */ int curve_nid; /* NID of curve, used by OpenSSL/OpenSSH as reference */ + int curve_oid; /* OID of curve, used by OpenSSL/OpenSSH as reference */ }; struct WOLFSSL_EC_KEY { diff --git a/wolfssl/openssl/ecdsa.h b/wolfssl/openssl/ecdsa.h index a92841fffc..a56d26d3a5 100644 --- a/wolfssl/openssl/ecdsa.h +++ b/wolfssl/openssl/ecdsa.h @@ -3,7 +3,6 @@ #ifndef WOLFSSL_ECDSA_H_ #define WOLFSSL_ECDSA_H_ -#include #include @@ -11,6 +10,13 @@ extern "C" { #endif +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_ECDSA_SIG ECDSA_SIG; + struct WOLFSSL_ECDSA_SIG { WOLFSSL_BIGNUM *r; WOLFSSL_BIGNUM *s; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index e13e60ed16..bdd01b733e 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -21,7 +21,7 @@ -/* evp.h defines mini evp openssl compatibility layer +/* evp.h defines mini evp openssl compatibility layer * */ @@ -47,14 +47,16 @@ #include #include #include - +#ifdef HAVE_IDEA + #include +#endif #ifdef __cplusplus extern "C" { #endif -typedef char WOLFSSL_EVP_MD; typedef char WOLFSSL_EVP_CIPHER; +typedef char WOLFSSL_EVP_MD; #ifndef NO_MD5 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void); @@ -66,12 +68,17 @@ WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void); WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void); +WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void); WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void); @@ -101,8 +108,8 @@ typedef union { typedef struct WOLFSSL_EVP_MD_CTX { - unsigned char macType; WOLFSSL_Hasher hash; + unsigned char macType; } WOLFSSL_EVP_MD_CTX; @@ -128,39 +135,83 @@ enum { AES_128_CTR_TYPE = 4, AES_192_CTR_TYPE = 5, AES_256_CTR_TYPE = 6, - DES_CBC_TYPE = 7, - DES_EDE3_CBC_TYPE = 8, - ARC4_TYPE = 9, - NULL_CIPHER_TYPE = 10, - EVP_PKEY_RSA = 11, - EVP_PKEY_DSA = 12, - EVP_PKEY_EC = 13, - IDEA_CBC_TYPE = 14, + AES_128_ECB_TYPE = 7, + AES_192_ECB_TYPE = 8, + AES_256_ECB_TYPE = 9, + DES_CBC_TYPE = 10, + DES_ECB_TYPE = 11, + DES_EDE3_CBC_TYPE = 12, + DES_EDE3_ECB_TYPE = 13, + ARC4_TYPE = 14, + NULL_CIPHER_TYPE = 15, + EVP_PKEY_RSA = 16, + EVP_PKEY_DSA = 17, + EVP_PKEY_EC = 18, + IDEA_CBC_TYPE = 19, NID_sha1 = 64, NID_md2 = 3, NID_md5 = 4 }; - +#define WOLFSSL_EVP_BUF_SIZE 16 typedef struct WOLFSSL_EVP_CIPHER_CTX { int keyLen; /* user may set for variable */ + int block_size; + unsigned long flags; unsigned char enc; /* if encrypt side, then true */ unsigned char cipherType; #ifndef NO_AES - unsigned char iv[AES_BLOCK_SIZE]; /* working iv pointer into cipher */ + /* working iv pointer into cipher */ + ALIGN16 unsigned char iv[AES_BLOCK_SIZE]; #elif !defined(NO_DES3) - unsigned char iv[DES_BLOCK_SIZE]; /* working iv pointer into cipher */ + /* working iv pointer into cipher */ + ALIGN16 unsigned char iv[DES_BLOCK_SIZE]; #endif WOLFSSL_Cipher cipher; + ALIGN16 byte buf[WOLFSSL_EVP_BUF_SIZE]; + int bufUsed; + ALIGN16 byte lastBlock[WOLFSSL_EVP_BUF_SIZE]; + int lastUsed; } WOLFSSL_EVP_CIPHER_CTX; +#ifndef WOLFSSL_EVP_PKEY_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +#define WOLFSSL_EVP_PKEY_TYPE_DEFINED +#endif + +struct WOLFSSL_EVP_PKEY { + int type; /* openssh dereference */ + int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; /* der format of key / or raw for NTRU */ + } pkey; + #ifdef HAVE_ECC + int pkey_curve; + #endif +}; + +typedef int WOLFSSL_ENGINE ; +typedef WOLFSSL_ENGINE ENGINE; + +WOLFSSL_API void wolfSSL_EVP_init(void); WOLFSSL_API int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md); +WOLFSSL_API int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md); + +WOLFSSL_API WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new (void); +WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX* ctx); WOLFSSL_API void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx); +WOLFSSL_API const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx); +WOLFSSL_API const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name); +WOLFSSL_API const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name); WOLFSSL_API int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type); +WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl); WOLFSSL_API int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, unsigned long sz); WOLFSSL_API int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, @@ -178,12 +229,50 @@ WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX*); +WOLFSSL_API int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER*); WOLFSSL_API int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, unsigned char* key, unsigned char* iv, int enc); +WOLFSSL_API int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv, + int enc); +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv); +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl); +WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_CipherFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, int enc); +WOLFSSL_API int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl); + +WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void); +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, int keylen); @@ -209,6 +298,35 @@ WOLFSSL_API void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, WOLFSSL_API int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx); +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher); +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags); +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx); +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *c, int pad); +WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest); + +#define EVP_CIPH_STREAM_CIPHER WOLFSSL_EVP_CIPH_STREAM_CIPHER +#define EVP_CIPH_ECB_MODE WOLFSSL_EVP_CIPH_ECB_MODE +#define EVP_CIPH_CBC_MODE WOLFSSL_EVP_CIPH_CBC_MODE +#define EVP_CIPH_CFB_MODE WOLFSSL_EVP_CIPH_CFB_MODE +#define EVP_CIPH_OFB_MODE WOLFSSL_EVP_CIPH_OFB_MODE +#define EVP_CIPH_CTR_MODE WOLFSSL_EVP_CIPH_CTR_MODE +#define EVP_CIPH_GCM_MODE WOLFSSL_EVP_CIPH_GCM_MODE +#define EVP_CIPH_CCM_MODE WOLFSSL_EVP_CIPH_CCM_MODE + +#define WOLFSSL_EVP_CIPH_MODE 0x0007 +#define WOLFSSL_EVP_CIPH_STREAM_CIPHER 0x0 +#define WOLFSSL_EVP_CIPH_ECB_MODE 0x1 +#define WOLFSSL_EVP_CIPH_CBC_MODE 0x2 +#define WOLFSSL_EVP_CIPH_CFB_MODE 0x3 +#define WOLFSSL_EVP_CIPH_OFB_MODE 0x4 +#define WOLFSSL_EVP_CIPH_CTR_MODE 0x5 +#define WOLFSSL_EVP_CIPH_GCM_MODE 0x6 +#define WOLFSSL_EVP_CIPH_CCM_MODE 0x7 +#define WOLFSSL_EVP_CIPH_NO_PADDING 0x100 /* end OpenSSH compat */ @@ -230,38 +348,86 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_aes_128_cbc wolfSSL_EVP_aes_128_cbc #define EVP_aes_192_cbc wolfSSL_EVP_aes_192_cbc #define EVP_aes_256_cbc wolfSSL_EVP_aes_256_cbc +#define EVP_aes_128_ecb wolfSSL_EVP_aes_128_ecb +#define EVP_aes_192_ecb wolfSSL_EVP_aes_192_ecb +#define EVP_aes_256_ecb wolfSSL_EVP_aes_256_ecb #define EVP_aes_128_ctr wolfSSL_EVP_aes_128_ctr #define EVP_aes_192_ctr wolfSSL_EVP_aes_192_ctr #define EVP_aes_256_ctr wolfSSL_EVP_aes_256_ctr #define EVP_des_cbc wolfSSL_EVP_des_cbc +#define EVP_des_ecb wolfSSL_EVP_des_ecb #define EVP_des_ede3_cbc wolfSSL_EVP_des_ede3_cbc +#define EVP_des_ede3_ecb wolfSSL_EVP_des_ede3_ecb #define EVP_rc4 wolfSSL_EVP_rc4 #define EVP_idea_cbc wolfSSL_EVP_idea_cbc #define EVP_enc_null wolfSSL_EVP_enc_null #define EVP_MD_size wolfSSL_EVP_MD_size +#define EVP_MD_CTX_new wolfSSL_EVP_MD_CTX_new +#define EVP_MD_CTX_create wolfSSL_EVP_MD_CTX_new +#define EVP_MD_CTX_free wolfSSL_EVP_MD_CTX_free +#define EVP_MD_CTX_destroy wolfSSL_EVP_MD_CTX_free #define EVP_MD_CTX_init wolfSSL_EVP_MD_CTX_init #define EVP_MD_CTX_cleanup wolfSSL_EVP_MD_CTX_cleanup +#define EVP_MD_CTX_md wolfSSL_EVP_MD_CTX_md +#define EVP_MD_CTX_type wolfSSL_EVP_MD_type +#define EVP_MD_type wolfSSL_EVP_MD_type + #define EVP_DigestInit wolfSSL_EVP_DigestInit +#define EVP_DigestInit_ex wolfSSL_EVP_DigestInit_ex #define EVP_DigestUpdate wolfSSL_EVP_DigestUpdate #define EVP_DigestFinal wolfSSL_EVP_DigestFinal #define EVP_DigestFinal_ex wolfSSL_EVP_DigestFinal_ex #define EVP_BytesToKey wolfSSL_EVP_BytesToKey +#define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname +#define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname + #define EVP_CIPHER_CTX_init wolfSSL_EVP_CIPHER_CTX_init #define EVP_CIPHER_CTX_cleanup wolfSSL_EVP_CIPHER_CTX_cleanup #define EVP_CIPHER_CTX_iv_length wolfSSL_EVP_CIPHER_CTX_iv_length #define EVP_CIPHER_CTX_key_length wolfSSL_EVP_CIPHER_CTX_key_length #define EVP_CIPHER_CTX_set_key_length wolfSSL_EVP_CIPHER_CTX_set_key_length +#define EVP_CIPHER_CTX_mode wolfSSL_EVP_CIPHER_CTX_mode + +#define EVP_CIPHER_iv_length wolfSSL_EVP_CIPHER_iv_length + #define EVP_CipherInit wolfSSL_EVP_CipherInit +#define EVP_CipherInit_ex wolfSSL_EVP_CipherInit_ex +#define EVP_EncryptInit wolfSSL_EVP_EncryptInit +#define EVP_EncryptInit_ex wolfSSL_EVP_EncryptInit_ex +#define EVP_DecryptInit wolfSSL_EVP_DecryptInit +#define EVP_DecryptInit_ex wolfSSL_EVP_DecryptInit_ex + #define EVP_Cipher wolfSSL_EVP_Cipher +#define EVP_CipherUpdate wolfSSL_EVP_CipherUpdate +#define EVP_EncryptUpdate wolfSSL_EVP_CipherUpdate +#define EVP_DecryptUpdate wolfSSL_EVP_CipherUpdate +#define EVP_CipherFinal wolfSSL_EVP_CipherFinal +#define EVP_CipherFinal_ex wolfSSL_EVP_CipherFinal +#define EVP_EncryptFinal wolfSSL_EVP_CipherFinal +#define EVP_EncryptFinal_ex wolfSSL_EVP_CipherFinal +#define EVP_DecryptFinal wolfSSL_EVP_CipherFinal +#define EVP_DecryptFinal_ex wolfSSL_EVP_CipherFinal + +#define EVP_CIPHER_CTX_free wolfSSL_EVP_CIPHER_CTX_free +#define EVP_CIPHER_CTX_new wolfSSL_EVP_CIPHER_CTX_new #define EVP_get_digestbynid wolfSSL_EVP_get_digestbynid +#define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname +#define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname #define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA #define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA #define EVP_PKEY_get1_EC_KEY wolfSSL_EVP_PKEY_get1_EC_KEY +#define EVP_CIPHER_CTX_block_size wolfSSL_EVP_CIPHER_CTX_block_size +#define EVP_CIPHER_block_size wolfSSL_EVP_CIPHER_block_size +#define EVP_CIPHER_flags wolfSSL_EVP_CIPHER_flags +#define EVP_CIPHER_CTX_set_flags wolfSSL_EVP_CIPHER_CTX_set_flags +#define EVP_CIPHER_CTX_set_padding wolfSSL_EVP_CIPHER_CTX_set_padding +#define EVP_CIPHER_CTX_flags wolfSSL_EVP_CIPHER_CTX_flags +#define EVP_add_digest wolfSSL_EVP_add_digest #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 /* sha512 */ diff --git a/wolfssl/openssl/hmac.h b/wolfssl/openssl/hmac.h index 76d2481bfa..3cf92fe1cb 100644 --- a/wolfssl/openssl/hmac.h +++ b/wolfssl/openssl/hmac.h @@ -57,6 +57,8 @@ typedef struct WOLFSSL_HMAC_CTX { WOLFSSL_API void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, const EVP_MD* type); +WOLFSSL_API int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int len, const EVP_MD* md, void* impl); WOLFSSL_API void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, int len); WOLFSSL_API void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, @@ -69,6 +71,7 @@ typedef struct WOLFSSL_HMAC_CTX HMAC_CTX; #define HMAC(a,b,c,d,e,f,g) wolfSSL_HMAC((a),(b),(c),(d),(e),(f),(g)) #define HMAC_Init wolfSSL_HMAC_Init +#define HMAC_Init_ex wolfSSL_HMAC_Init_ex #define HMAC_Update wolfSSL_HMAC_Update #define HMAC_Final wolfSSL_HMAC_Final #define HMAC_cleanup wolfSSL_HMAC_cleanup diff --git a/wolfssl/openssl/include.am b/wolfssl/openssl/include.am index 21d99ef00c..e4dcdf80a9 100644 --- a/wolfssl/openssl/include.am +++ b/wolfssl/openssl/include.am @@ -3,6 +3,7 @@ nobase_include_HEADERS+= \ wolfssl/openssl/asn1.h \ + wolfssl/openssl/aes.h\ wolfssl/openssl/bio.h \ wolfssl/openssl/bn.h \ wolfssl/openssl/conf.h \ @@ -32,6 +33,7 @@ nobase_include_HEADERS+= \ wolfssl/openssl/rand.h \ wolfssl/openssl/rsa.h \ wolfssl/openssl/sha.h \ + wolfssl/openssl/ssl23.h \ wolfssl/openssl/ssl.h \ wolfssl/openssl/stack.h \ wolfssl/openssl/ui.h \ diff --git a/wolfssl/openssl/md5.h b/wolfssl/openssl/md5.h index bdcda5b98a..c4f05d30cb 100644 --- a/wolfssl/openssl/md5.h +++ b/wolfssl/openssl/md5.h @@ -18,7 +18,7 @@ typedef struct WOLFSSL_MD5_CTX { - int holder[24]; /* big enough to hold wolfcrypt md5, but check on init */ + int holder[28 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; /* big enough to hold wolfcrypt md5, but check on init */ } WOLFSSL_MD5_CTX; WOLFSSL_API void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX*); @@ -32,11 +32,16 @@ typedef WOLFSSL_MD5_CTX MD5_CTX; #define MD5_Update wolfSSL_MD5_Update #define MD5_Final wolfSSL_MD5_Final +#ifdef OPENSSL_EXTRA_BSD + #define MD5Init wolfSSL_MD5_Init + #define MD5Update wolfSSL_MD5_Update + #define MD5Final wolfSSL_MD5_Final +#endif + #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif #endif /* NO_MD5 */ #endif /* WOLFSSL_MD5_H_ */ - diff --git a/wolfssl/openssl/ocsp.h b/wolfssl/openssl/ocsp.h index 7463eec968..98f2c9c815 100644 --- a/wolfssl/openssl/ocsp.h +++ b/wolfssl/openssl/ocsp.h @@ -1 +1,44 @@ /* ocsp.h for libcurl */ + +#ifndef WOLFSSL_OCSP_H_ +#define WOLFSSL_OCSP_H_ + +#ifdef HAVE_OCSP +#include + +#define OCSP_REQUEST OcspRequest +#define OCSP_RESPONSE OcspResponse +#define OCSP_BASICRESP WOLFSSL_OCSP_BASICRESP +#define OCSP_CERTID WOLFSSL_OCSP_CERTID +#define OCSP_ONEREQ WOLFSSL_OCSP_ONEREQ + +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define V_OCSP_CERTSTATUS_GOOD 0 + +#define OCSP_resp_find_status wolfSSL_OCSP_resp_find_status +#define OCSP_cert_status_str wolfSSL_OCSP_cert_status_str +#define OCSP_check_validity wolfSSL_OCSP_check_validity + +#define OCSP_CERTID_free wolfSSL_OCSP_CERTID_free +#define OCSP_cert_to_id wolfSSL_OCSP_cert_to_id + +#define OCSP_BASICRESP_free wolfSSL_OCSP_BASICRESP_free +#define OCSP_basic_verify wolfSSL_OCSP_basic_verify + +#define OCSP_RESPONSE_free wolfSSL_OCSP_RESPONSE_free +#define d2i_OCSP_RESPONSE_bio wolfSSL_d2i_OCSP_RESPONSE_bio +#define d2i_OCSP_RESPONSE wolfSSL_d2i_OCSP_RESPONSE +#define i2d_OCSP_RESPONSE wolfSSL_i2d_OCSP_RESPONSE +#define OCSP_response_status wolfSSL_OCSP_response_status +#define OCSP_response_status_str wolfSSL_OCSP_response_status_str +#define OCSP_response_get1_basic wolfSSL_OCSP_response_get1_basic + +#define OCSP_REQUEST_new wolfSSL_OCSP_REQUEST_new +#define OCSP_REQUEST_free wolfSSL_OCSP_REQUEST_free +#define i2d_OCSP_REQUEST wolfSSL_i2d_OCSP_REQUEST +#define OCSP_request_add0_id wolfSSL_OCSP_request_add0_id + +#endif /* HAVE_OCSP */ + +#endif /* WOLFSSL_OCSP_H_ */ + diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index 48955f9ec2..c7b143c9fb 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -5,7 +5,7 @@ /* api version compatibility */ -#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) +#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) /* version number can be increased for Lighty after compatibility for ECDH is added */ #define OPENSSL_VERSION_NUMBER 0x10001000L diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 76a391f542..00e7abdb48 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -13,13 +13,14 @@ extern "C" { #endif +#define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey /* RSA */ WOLFSSL_API int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, const EVP_CIPHER* cipher, unsigned char* passwd, int len, - pem_password_cb cb, void* arg); + pem_password_cb* cb, void* arg); WOLFSSL_API int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, unsigned char* passwd, int len, @@ -46,7 +47,7 @@ int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, const EVP_CIPHER* cipher, unsigned char* passwd, int len, - pem_password_cb cb, void* arg); + pem_password_cb* cb, void* arg); WOLFSSL_API int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, const EVP_CIPHER* cipher, @@ -67,7 +68,7 @@ WOLFSSL_API int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec, const EVP_CIPHER* cipher, unsigned char* passwd, int len, - pem_password_cb cb, void* arg); + pem_password_cb* cb, void* arg); WOLFSSL_API int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* key, const EVP_CIPHER* cipher, @@ -87,17 +88,35 @@ int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *key); WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY**, - pem_password_cb cb, + pem_password_cb* cb, void* arg); WOLFSSL_API +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg); + +WOLFSSL_API int wolfSSL_EVP_PKEY_type(int type); +WOLFSSL_API +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey); + #if !defined(NO_FILESYSTEM) WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u); +WOLFSSL_API +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, + pem_password_cb *cb, void *u); #endif /* NO_FILESYSTEM */ +#define PEM_read_X509 wolfSSL_PEM_read_X509 +#define PEM_read_PrivateKey wolfSSL_PEM_read_PrivateKey +#define PEM_write_bio_PrivateKey wolfSSL_PEM_write_bio_PrivateKey /* RSA */ #define PEM_write_bio_RSAPrivateKey wolfSSL_PEM_write_bio_RSAPrivateKey #define PEM_write_RSAPrivateKey wolfSSL_PEM_write_RSAPrivateKey diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 210a24e4c1..7c8d4e63ed 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -4,7 +4,6 @@ #ifndef WOLFSSL_RSA_H_ #define WOLFSSL_RSA_H_ -#include #include @@ -24,6 +23,13 @@ enum { NID_sha512 = 674 }; +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_RSA RSA; + struct WOLFSSL_RSA { WOLFSSL_BIGNUM* n; WOLFSSL_BIGNUM* e; diff --git a/wolfssl/openssl/sha.h b/wolfssl/openssl/sha.h index a881a0bd0b..7495d4a370 100644 --- a/wolfssl/openssl/sha.h +++ b/wolfssl/openssl/sha.h @@ -5,6 +5,7 @@ #define WOLFSSL_SHA_H_ #include +#include #ifdef WOLFSSL_PREFIX #include "prefix_sha.h" @@ -16,7 +17,8 @@ typedef struct WOLFSSL_SHA_CTX { - int holder[24]; /* big enough to hold wolfcrypt sha, but check on init */ + /* big enough to hold wolfcrypt Sha, but check on init */ + int holder[28 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; } WOLFSSL_SHA_CTX; WOLFSSL_API void wolfSSL_SHA_Init(WOLFSSL_SHA_CTX*); @@ -46,8 +48,12 @@ typedef WOLFSSL_SHA_CTX SHA_CTX; #ifdef WOLFSSL_SHA224 +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 + * struct are 16 byte aligned. Any derefrence to those elements after casting to + * Sha224, is expected to also be 16 byte aligned addresses. */ typedef struct WOLFSSL_SHA224_CTX { - long long holder[28]; /* big enough, but check on init */ + /* big enough to hold wolfcrypt Sha224, but check on init */ + ALIGN16 int holder[34 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; } WOLFSSL_SHA224_CTX; WOLFSSL_API void wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX*); @@ -69,8 +75,12 @@ typedef WOLFSSL_SHA224_CTX SHA224_CTX; #endif /* WOLFSSL_SHA224 */ +/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 + * struct are 16 byte aligned. Any derefrence to those elements after casting to + * Sha256, is expected to also be 16 byte aligned addresses. */ typedef struct WOLFSSL_SHA256_CTX { - int holder[28]; /* big enough to hold wolfcrypt sha, but check on init */ + /* big enough to hold wolfcrypt Sha256, but check on init */ + ALIGN16 int holder[34 + (WC_ASYNC_DEV_SIZE / sizeof(int))]; } WOLFSSL_SHA256_CTX; WOLFSSL_API void wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX*); @@ -93,7 +103,8 @@ typedef WOLFSSL_SHA256_CTX SHA256_CTX; #ifdef WOLFSSL_SHA384 typedef struct WOLFSSL_SHA384_CTX { - long long holder[32]; /* big enough, but check on init */ + /* big enough to hold wolfCrypt Sha384, but check on init */ + long long holder[32 + (WC_ASYNC_DEV_SIZE / sizeof(long long))]; } WOLFSSL_SHA384_CTX; WOLFSSL_API void wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX*); @@ -117,7 +128,8 @@ typedef WOLFSSL_SHA384_CTX SHA384_CTX; #ifdef WOLFSSL_SHA512 typedef struct WOLFSSL_SHA512_CTX { - long long holder[36]; /* big enough, but check on init */ + /* big enough to hold wolfCrypt Sha384, but check on init */ + long long holder[36 + (WC_ASYNC_DEV_SIZE / sizeof(long long))]; } WOLFSSL_SHA512_CTX; WOLFSSL_API void wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX*); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 22592f7d7d..c00c8fe6c4 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -21,7 +21,7 @@ -/* ssl.h defines wolfssl_openssl compatibility layer +/* ssl.h defines wolfssl_openssl compatibility layer * */ @@ -32,6 +32,8 @@ /* wolfssl_openssl compatibility layer */ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -61,33 +63,34 @@ typedef WOLFSSL_X509_CHAIN X509_CHAIN; #define WOLFSSL_TYPES_DEFINED -typedef WOLFSSL_EVP_PKEY EVP_PKEY; -typedef WOLFSSL_RSA RSA; -typedef WOLFSSL_DSA DSA; -typedef WOLFSSL_EC_KEY EC_KEY; -typedef WOLFSSL_EC_GROUP EC_GROUP; -typedef WOLFSSL_EC_POINT EC_POINT; -typedef WOLFSSL_ECDSA_SIG ECDSA_SIG; -typedef WOLFSSL_BIO BIO; -typedef WOLFSSL_BIO_METHOD BIO_METHOD; -typedef WOLFSSL_CIPHER SSL_CIPHER; -typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; -typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; -typedef WOLFSSL_X509_CRL X509_CRL; -typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; -typedef WOLFSSL_ASN1_TIME ASN1_TIME; -typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; -typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; -typedef WOLFSSL_ASN1_STRING ASN1_STRING; -typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; - -#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +typedef WOLFSSL_EVP_PKEY EVP_PKEY; +typedef WOLFSSL_BIO BIO; +typedef WOLFSSL_BIO_METHOD BIO_METHOD; +typedef WOLFSSL_CIPHER SSL_CIPHER; +typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; +typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; +typedef WOLFSSL_X509_CRL X509_CRL; +typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; +typedef WOLFSSL_ASN1_TIME ASN1_TIME; +typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; +typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; +typedef WOLFSSL_ASN1_STRING ASN1_STRING; +typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; +typedef WOLFSSL_BUF_MEM BUF_MEM; + +/* GENERAL_NAME and BASIC_CONSTRAINTS structs may need implemented as + * compatibility layer expands. For now treating them as an ASN1_OBJECT */ +typedef WOLFSSL_ASN1_OBJECT GENERAL_NAME; +typedef WOLFSSL_ASN1_OBJECT BASIC_CONSTRAINTS; + +#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME typedef WOLFSSL_MD4_CTX MD4_CTX; typedef WOLFSSL_COMP_METHOD COMP_METHOD; -typedef WOLFSSL_X509_STORE X509_STORE; typedef WOLFSSL_X509_REVOKED X509_REVOKED; typedef WOLFSSL_X509_OBJECT X509_OBJECT; +typedef WOLFSSL_X509_STORE X509_STORE; typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define CRYPTO_free XFREE @@ -98,19 +101,26 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list((i)) #define SSL_get_cipher_name(ctx) wolfSSL_get_cipher((ctx)) #define SSL_get_shared_ciphers(ctx,buf,len) \ - strncpy(buf, "Not Implemented, SSLv2 only", len) + wolfSSL_get_shared_ciphers((ctx),(buf),(len)) -/* @TODO */ -#define ERR_print_errors_fp(file) +#define ERR_print_errors_fp(file) wolfSSL_ERR_dump_errors_fp((file)) /* at the moment only returns ok */ -#define SSL_get_verify_result(ctx) X509_V_OK +#define SSL_get_verify_result wolfSSL_get_verify_result #define SSL_get_verify_mode wolfSSL_SSL_get_mode #define SSL_get_verify_depth wolfSSL_get_verify_depth #define SSL_CTX_get_verify_mode wolfSSL_CTX_get_verify_mode #define SSL_CTX_get_verify_depth wolfSSL_CTX_get_verify_depth #define SSL_get_certificate wolfSSL_get_certificate +#define SSL_use_certificate wolfSSL_use_certificate +#define SSL_use_certificate_ASN1 wolfSSL_use_certificate_ASN1 + +#define SSL_use_PrivateKey wolfSSL_use_PrivateKey +#define SSL_use_PrivateKey_ASN1 wolfSSL_use_PrivateKey_ASN1 +#define SSL_use_RSAPrivateKey_ASN1 wolfSSL_use_RSAPrivateKey_ASN1 +#define SSL_get_privatekey wolfSSL_get_privatekey +#define SSLv23_method wolfSSLv23_method #define SSLv3_server_method wolfSSLv3_server_method #define SSLv3_client_method wolfSSLv3_client_method #define TLSv1_server_method wolfTLSv1_server_method @@ -134,7 +144,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_CTX_load_verify_locations wolfSSL_CTX_load_verify_locations #define SSL_CTX_use_certificate_chain_file wolfSSL_CTX_use_certificate_chain_file #define SSL_CTX_use_RSAPrivateKey_file wolfSSL_CTX_use_RSAPrivateKey_file - + #define SSL_use_certificate_file wolfSSL_use_certificate_file #define SSL_use_PrivateKey_file wolfSSL_use_PrivateKey_file #define SSL_use_certificate_chain_file wolfSSL_use_certificate_chain_file @@ -147,6 +157,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_get_fd wolfSSL_get_fd #define SSL_connect wolfSSL_connect #define SSL_clear wolfSSL_clear +#define SSL_state wolfSSL_state #define SSL_write wolfSSL_write #define SSL_read wolfSSL_read @@ -201,7 +212,12 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_get_keyblock_size wolfSSL_get_keyblock_size #define SSL_get_keys wolfSSL_get_keys +#define SSL_SESSION_get_master_key wolfSSL_SESSION_get_master_key +#define SSL_SESSION_get_master_key_length wolfSSL_SESSION_get_master_key_length +#define SSL_X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID +#define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i +#define X509_digest wolfSSL_X509_digest #define X509_free wolfSSL_X509_free #define OPENSSL_free wolfSSL_OPENSSL_free @@ -217,7 +233,11 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define BIO_new wolfSSL_BIO_new #define BIO_free wolfSSL_BIO_free #define BIO_free_all wolfSSL_BIO_free_all +#define BIO_nread0 wolfSSL_BIO_nread0 +#define BIO_nread wolfSSL_BIO_nread #define BIO_read wolfSSL_BIO_read +#define BIO_nwrite0 wolfSSL_BIO_nwrite0 +#define BIO_nwrite wolfSSL_BIO_nwrite #define BIO_write wolfSSL_BIO_write #define BIO_push wolfSSL_BIO_push #define BIO_pop wolfSSL_BIO_pop @@ -239,9 +259,10 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define BIO_f_base64 wolfSSL_BIO_f_base64 #define BIO_set_flags wolfSSL_BIO_set_flags +#define OpenSSL_add_all_digests() #define OpenSSL_add_all_algorithms wolfSSL_add_all_algorithms #define SSLeay_add_ssl_algorithms wolfSSL_add_all_algorithms -#define SSLeay_add_all_algorithms wolfSSL_add_all_algorithms +#define SSLeay_add_all_algorithms wolfSSL_add_all_algorithms #define RAND_screen wolfSSL_RAND_screen #define RAND_file_name wolfSSL_RAND_file_name @@ -271,6 +292,9 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; # define CRYPTO_WRITE 8 #define X509_STORE_CTX_get_current_cert wolfSSL_X509_STORE_CTX_get_current_cert +#define X509_STORE_add_cert wolfSSL_X509_STORE_add_cert +#define X509_STORE_set_flags wolfSSL_X509_STORE_set_flags +#define X509_STORE_CTX_get_chain wolfSSL_X509_STORE_CTX_get_chain #define X509_STORE_CTX_get_error wolfSSL_X509_STORE_CTX_get_error #define X509_STORE_CTX_get_error_depth wolfSSL_X509_STORE_CTX_get_error_depth @@ -297,7 +321,10 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define X509_CRL_verify wolfSSL_X509_CRL_verify #define X509_STORE_CTX_set_error wolfSSL_X509_STORE_CTX_set_error #define X509_OBJECT_free_contents wolfSSL_X509_OBJECT_free_contents +#define EVP_PKEY_new wolfSSL_PKEY_new #define EVP_PKEY_free wolfSSL_EVP_PKEY_free +#define EVP_PKEY_type wolfSSL_EVP_PKEY_type +#define EVP_PKEY_base_id wolfSSL_EVP_PKEY_base_id #define X509_cmp_current_time wolfSSL_X509_cmp_current_time #define sk_X509_REVOKED_num wolfSSL_sk_X509_REVOKED_num #define X509_CRL_get_REVOKED wolfSSL_X509_CRL_get_REVOKED @@ -308,14 +335,20 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define X509_get_serialNumber wolfSSL_X509_get_serialNumber -#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print #define ASN1_INTEGER_cmp wolfSSL_ASN1_INTEGER_cmp #define ASN1_INTEGER_get wolfSSL_ASN1_INTEGER_get +#define ASN1_INTEGER_to_BN wolfSSL_ASN1_INTEGER_to_BN +#define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 #define SSL_load_client_CA_file wolfSSL_load_client_CA_file +#define SSL_CTX_get_client_CA_list wolfSSL_SSL_CTX_get_client_CA_list #define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list +#define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store +#define SSL_CTX_get_cert_store wolfSSL_CTX_get_cert_store #define X509_STORE_CTX_get_ex_data wolfSSL_X509_STORE_CTX_get_ex_data #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx #define SSL_get_ex_data wolfSSL_get_ex_data @@ -327,6 +360,8 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_CTX_set_info_callback wolfSSL_CTX_set_info_callback #define ERR_peek_error wolfSSL_ERR_peek_error +#define ERR_peek_last_error_line wolfSSL_ERR_peek_last_error_line +#define ERR_peek_errors_fp wolfSSL_ERR_peek_errors_fp #define ERR_GET_REASON wolfSSL_ERR_GET_REASON #define SSL_alert_type_string wolfSSL_alert_type_string @@ -377,7 +412,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define RAND_status wolfSSL_RAND_status #define RAND_bytes wolfSSL_RAND_bytes #define SSLv23_server_method wolfSSLv23_server_method -#define SSL_CTX_set_options wolfSSL_CTX_set_options +#define SSL_CTX_set_options wolfSSL_CTX_set_options #define SSL_CTX_check_private_key wolfSSL_CTX_check_private_key #define ERR_free_strings wolfSSL_ERR_free_strings @@ -405,6 +440,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define sk_value wolfSSL_sk_value #define sk_X509_pop wolfSSL_sk_X509_pop #define sk_X509_free wolfSSL_sk_X509_free +#define d2i_X509_bio wolfSSL_d2i_X509_bio #define SSL_CTX_get_ex_data wolfSSL_CTX_get_ex_data #define SSL_CTX_set_ex_data wolfSSL_CTX_set_ex_data @@ -418,26 +454,42 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_SESSION_get_timeout wolfSSL_SESSION_get_timeout #define SSL_SESSION_get_time wolfSSL_SESSION_get_time #define SSL_CTX_get_ex_new_index wolfSSL_CTX_get_ex_new_index +#define PEM_read_bio_X509 wolfSSL_PEM_read_bio_X509 +#define PEM_read_bio_X509_AUX wolfSSL_PEM_read_bio_X509_AUX + +/*#if OPENSSL_API_COMPAT < 0x10100000L*/ +#define CONF_modules_free() +#define ENGINE_cleanup() +#define HMAC_CTX_cleanup wolfSSL_HMAC_cleanup +#define SSL_CTX_need_tmp_RSA(ctx) 0 +#define SSL_CTX_set_tmp_rsa(ctx,rsa) 1 +#define SSL_need_tmp_RSA(ssl) 0 +#define SSL_set_tmp_rsa(ssl,rsa) 1 +/*#endif*/ +#define CONF_modules_unload(a) + +#define SSL_get_hit wolfSSL_session_reused /* yassl had set the default to be 500 */ #define SSL_get_default_timeout(ctx) 500 /* Lighthttp compatibility */ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY) typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; -#define SSL_CB_HANDSHAKE_START 0x10 #define X509_NAME_free wolfSSL_X509_NAME_free #define SSL_CTX_use_certificate wolfSSL_CTX_use_certificate #define SSL_CTX_use_PrivateKey wolfSSL_CTX_use_PrivateKey #define BIO_read_filename wolfSSL_BIO_read_filename #define BIO_s_file wolfSSL_BIO_s_file -#define OBJ_nid2sn wolf_OBJ_nid2sn -#define OBJ_obj2nid wolf_OBJ_obj2nid -#define OBJ_sn2nid wolf_OBJ_sn2nid -#define PEM_read_bio_X509 PEM_read_bio_WOLFSSL_X509 +#define OBJ_nid2sn wolfSSL_OBJ_nid2sn +#define OBJ_obj2nid wolfSSL_OBJ_obj2nid +#define OBJ_sn2nid wolfSSL_OBJ_sn2nid #define SSL_CTX_set_verify_depth wolfSSL_CTX_set_verify_depth +#define SSL_set_verify_depth wolfSSL_set_verify_depth #define SSL_get_app_data wolfSSL_get_app_data #define SSL_set_app_data wolfSSL_set_app_data #define X509_NAME_entry_count wolfSSL_X509_NAME_entry_count @@ -453,26 +505,121 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define SSL_dup_CA_list wolfSSL_dup_CA_list #define NID_commonName 0x03 /* matchs ASN_COMMON_NAME in asn.h */ -#endif -#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) - -#define OBJ_nid2ln wolf_OBJ_nid2ln -#define OBJ_txt2nid wolf_OBJ_txt2nid +#define OBJ_nid2ln wolfSSL_OBJ_nid2ln +#define OBJ_txt2nid wolfSSL_OBJ_txt2nid #define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams -#define PEM_write_bio_X509 PEM_write_bio_WOLFSSL_X509 -#define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh -#define BIO_new_file wolfSSL_BIO_new_file +#define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams +#define PEM_write_bio_X509 wolfSSL_PEM_write_bio_X509 + + +#ifdef WOLFSSL_HAPROXY +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_get_ciphers(x) wolfSSL_get_ciphers_compat(x) +#define SSL_SESSION_get_id wolfSSL_SESSION_get_id +#define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data +#define SSL_get_cipher_bits(s,np) wolfSSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +#define sk_SSL_CIPHER_num wolfSSL_sk_SSL_CIPHER_num +#define sk_SSL_COMP_zero wolfSSL_sk_SSL_COMP_zero +#define sk_SSL_CIPHER_value wolfSSL_sk_SSL_CIPHER_value +#endif /* WOLFSSL_HAPROXY */ +#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh -#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE */ - -#ifdef HAVE_STUNNEL +#define BIO_new_file wolfSSL_BIO_new_file +#define BIO_ctrl wolfSSL_BIO_ctrl +#define BIO_ctrl_pending wolfSSL_BIO_ctrl_pending +#define BIO_get_mem_ptr wolfSSL_BIO_get_mem_ptr +#define BIO_int_ctrl wolfSSL_BIO_int_ctrl +#define BIO_reset wolfSSL_BIO_reset +#define BIO_s_file wolfSSL_BIO_s_file +#define BIO_s_bio wolfSSL_BIO_s_bio +#define BIO_s_socket wolfSSL_BIO_s_socket +#define BIO_set_fd wolfSSL_BIO_set_fd +#define BIO_ctrl_reset_read_request wolfSSL_BIO_ctrl_reset_read_request + +#define BIO_set_write_buf_size wolfSSL_BIO_set_write_buf_size +#define BIO_make_bio_pair wolfSSL_BIO_make_bio_pair + +#define BIO_set_fp wolfSSL_BIO_set_fp +#define BIO_get_fp wolfSSL_BIO_get_fp +#define BIO_seek wolfSSL_BIO_seek +#define BIO_write_filename wolfSSL_BIO_write_filename +#define BIO_set_mem_eof_return wolfSSL_BIO_set_mem_eof_return + +#define SSL_set_options wolfSSL_set_options +#define SSL_get_options wolfSSL_get_options +#define SSL_set_tmp_dh wolfSSL_set_tmp_dh +#define SSL_clear_num_renegotiations wolfSSL_clear_num_renegotiations +#define SSL_total_renegotiations wolfSSL_total_renegotiations +#define SSL_set_tlsext_debug_arg wolfSSL_set_tlsext_debug_arg +#define SSL_set_tlsext_status_type wolfSSL_set_tlsext_status_type +#define SSL_set_tlsext_status_exts wolfSSL_set_tlsext_status_exts +#define SSL_get_tlsext_status_ids wolfSSL_get_tlsext_status_ids +#define SSL_set_tlsext_status_ids wolfSSL_set_tlsext_status_ids +#define SSL_get_tlsext_status_ocsp_resp wolfSSL_get_tlsext_status_ocsp_resp +#define SSL_set_tlsext_status_ocsp_resp wolfSSL_set_tlsext_status_ocsp_resp + +#define SSL_CTX_add_extra_chain_cert wolfSSL_CTX_add_extra_chain_cert +#define SSL_CTX_get_read_ahead wolfSSL_CTX_get_read_ahead +#define SSL_CTX_set_read_ahead wolfSSL_CTX_set_read_ahead +#define SSL_CTX_set_tlsext_status_arg wolfSSL_CTX_set_tlsext_status_arg +#define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg \ + wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg +#define SSL_get_server_random wolfSSL_get_server_random + +#define SSL_get_tlsext_status_exts wolfSSL_get_tlsext_status_exts + +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130 +#define BIO_C_SET_WRITE_BUF_SIZE 136 +#define BIO_C_MAKE_BIO_PAIR 138 + +#define BIO_CTRL_RESET 1 +#define BIO_CTRL_INFO 3 +#define BIO_CTRL_FLUSH 11 +#define BIO_CLOSE 0x01 +#define BIO_FP_WRITE 0x04 + +#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 + +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_EXTRA_CHAIN_CERT 14 + +#define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +#define SSL_CTRL_GET_READ_AHEAD 40 +#define SSL_CTRL_SET_READ_AHEAD 41 + +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 + +#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 + +#define SSL_ctrl wolfSSL_ctrl +#define SSL_CTX_ctrl wolfSSL_CTX_ctrl + +#define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK +#define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL + +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) #include -/* defined as: (SSL_ST_ACCEPT|SSL_CB_LOOP), which becomes 0x2001*/ -#define SSL_CB_ACCEPT_LOOP 0x2001 #define SSL2_VERSION 0x0002 #define SSL3_VERSION 0x0300 #define TLS1_VERSION 0x0301 @@ -518,8 +665,8 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_get_servername wolfSSL_get_servername #define SSL_set_SSL_CTX wolfSSL_set_SSL_CTX #define SSL_CTX_get_verify_callback wolfSSL_CTX_get_verify_callback -#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_servername_callback -#define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg +#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_tlsext_servername_callback +#define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg #define PSK_MAX_PSK_LEN 256 #define PSK_MAX_IDENTITY_LEN 128 @@ -527,7 +674,130 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_CTX_clear_options wolfSSL_CTX_clear_options -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ +#define SSL_CTX_get_default_passwd_cb wolfSSL_CTX_get_default_passwd_cb +#define SSL_CTX_get_default_passwd_cb_userdata wolfSSL_CTX_get_default_passwd_cb_userdata + +/* certificate extension NIDs */ +#define NID_basic_constraints 133 +#define NID_key_usage 129 /* 2.5.29.15 */ +#define NID_ext_key_usage 151 /* 2.5.29.37 */ +#define NID_subject_key_identifier 128 +#define NID_authority_key_identifier 149 +#define NID_private_key_usage_period 130 /* 2.5.29.16 */ +#define NID_subject_alt_name 131 +#define NID_issuer_alt_name 132 +#define NID_info_access 69 +#define NID_sinfo_access 79 /* id-pe 11 */ +#define NID_name_constraints 144 /* 2.5.29.30 */ +#define NID_certificate_policies 146 +#define NID_policy_mappings 147 +#define NID_policy_constraints 150 +#define NID_inhibit_any_policy 168 /* 2.5.29.54 */ +#define NID_tlsfeature 92 /* id-pe 24 */ + + +#define SSL_CTX_set_msg_callback wolfSSL_CTX_set_msg_callback +#define SSL_set_msg_callback wolfSSL_set_msg_callback +#define SSL_CTX_set_msg_callback_arg wolfSSL_CTX_set_msg_callback_arg +#define SSL_set_msg_callback_arg wolfSSL_set_msg_callback_arg + +/* certificate extension NIDs */ +#define NID_basic_constraints 133 +#define NID_key_usage 129 /* 2.5.29.15 */ +#define NID_ext_key_usage 151 /* 2.5.29.37 */ +#define NID_subject_key_identifier 128 +#define NID_authority_key_identifier 149 +#define NID_private_key_usage_period 130 /* 2.5.29.16 */ +#define NID_subject_alt_name 131 +#define NID_issuer_alt_name 132 +#define NID_info_access 69 +#define NID_sinfo_access 79 /* id-pe 11 */ +#define NID_name_constraints 144 /* 2.5.29.30 */ +#define NID_certificate_policies 146 +#define NID_policy_mappings 147 +#define NID_policy_constraints 150 +#define NID_inhibit_any_policy 168 /* 2.5.29.54 */ +#define NID_tlsfeature 92 /* id-pe 24 */ + + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +#include + +#define OPENSSL_STRING WOLFSSL_STRING + +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +#define OPENSSL_NPN_UNSUPPORTED 0 +#define OPENSSL_NPN_NEGOTIATED 1 +#define OPENSSL_NPN_NO_OVERLAP 2 + +/* Nginx checks these to see if the error was a handshake error. */ +#define SSL_R_BAD_CHANGE_CIPHER_SPEC LENGTH_ERROR +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG BUFFER_E +#define SSL_R_DIGEST_CHECK_FAILED VERIFY_MAC_ERROR +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST SUITES_ERROR +#define SSL_R_EXCESSIVE_MESSAGE_SIZE BUFFER_ERROR +#define SSL_R_LENGTH_MISMATCH LENGTH_ERROR +#define SSL_R_NO_CIPHERS_SPECIFIED SUITES_ERROR +#define SSL_R_NO_COMPRESSION_SPECIFIED COMPRESSION_ERROR +#define SSL_R_NO_SHARED_CIPHER MATCH_SUITE_ERROR +#define SSL_R_RECORD_LENGTH_MISMATCH HANDSHAKE_SIZE_ERROR +#define SSL_R_UNEXPECTED_MESSAGE OUT_OF_ORDER_E +#define SSL_R_UNEXPECTED_RECORD SANITY_MSG_E +#define SSL_R_UNKNOWN_ALERT_TYPE BUFFER_ERROR +#define SSL_R_UNKNOWN_PROTOCOL VERSION_ERROR +#define SSL_R_WRONG_VERSION_NUMBER VERSION_ERROR +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC ENCRYPT_ERROR + +/* Nginx uses this to determine if reached end of certs in file. + * PEM_read_bio_X509 is called and the return error is lost. + * The error that needs to be detected is: SSL_NO_PEM_HEADER. + */ +#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +#define PEM_R_NO_START_LINE 108 +#define ERR_LIB_PEM 9 + +#ifdef HAVE_SESSION_TICKET +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +#endif + +#define OPENSSL_config wolfSSL_OPENSSL_config +#define X509_get_ex_new_index wolfSSL_X509_get_ex_new_index +#define X509_get_ex_data wolfSSL_X509_get_ex_data +#define X509_set_ex_data wolfSSL_X509_set_ex_data +#define X509_NAME_digest wolfSSL_X509_NAME_digest +#define SSL_CTX_get_timeout wolfSSL_SSL_CTX_get_timeout +#define SSL_CTX_set_tmp_ecdh wolfSSL_SSL_CTX_set_tmp_ecdh +#define SSL_CTX_remove_session wolfSSL_SSL_CTX_remove_session +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_in_init wolfSSL_SSL_in_init +#define SSL_get0_session wolfSSL_SSL_get0_session +#define X509_check_host wolfSSL_X509_check_host +#define i2a_ASN1_INTEGER wolfSSL_i2a_ASN1_INTEGER +#define ERR_peek_error_line_data wolfSSL_ERR_peek_error_line_data +#define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb +#define X509_email_free wolfSSL_X509_email_free +#define X509_get1_ocsp wolfSSL_X509_get1_ocsp +#define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb +#define X509_check_issued wolfSSL_X509_check_issued +#define X509_dup wolfSSL_X509_dup +#define X509_STORE_CTX_new wolfSSL_X509_STORE_CTX_new +#define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free +#define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer +#define sk_OPENSSL_STRING_value wolfSSL_sk_WOLFSSL_STRING_value +#define SSL_get0_alpn_selected wolfSSL_get0_alpn_selected +#define SSL_select_next_proto wolfSSL_select_next_proto +#define SSL_CTX_set_alpn_select_cb wolfSSL_CTX_set_alpn_select_cb +#define SSL_CTX_set_next_protos_advertised_cb wolfSSL_CTX_set_next_protos_advertised_cb +#define SSL_CTX_set_next_proto_select_cb wolfSSL_CTX_set_next_proto_select_cb +#define SSL_get0_next_proto_negotiated wolfSSL_get0_next_proto_negotiated + +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/openssl/ssl23.h b/wolfssl/openssl/ssl23.h new file mode 100644 index 0000000000..fc3ddfb5ff --- /dev/null +++ b/wolfssl/openssl/ssl23.h @@ -0,0 +1 @@ +/* ssl23.h for openssl */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 24fee4e10e..42750e788c 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -59,16 +59,25 @@ #undef OCSP_RESPONSE #endif - +#ifdef OPENSSL_EXTRA + #include + #include +#endif #ifdef __cplusplus extern "C" { #endif +#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_TYPE_DEFINED typedef struct WOLFSSL WOLFSSL; +#endif typedef struct WOLFSSL_SESSION WOLFSSL_SESSION; typedef struct WOLFSSL_METHOD WOLFSSL_METHOD; +#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED typedef struct WOLFSSL_CTX WOLFSSL_CTX; +#endif typedef struct WOLFSSL_STACK WOLFSSL_STACK; typedef struct WOLFSSL_X509 WOLFSSL_X509; @@ -78,10 +87,13 @@ typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN; typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER; typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; +typedef struct WOLFSSL_CRL WOLFSSL_CRL; /* redeclare guard */ #define WOLFSSL_TYPES_DEFINED +#include + #ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_RSA WOLFSSL_RSA; @@ -93,15 +105,28 @@ typedef struct WOLFSSL_RSA WOLFSSL_RSA; #define WC_RNG_TYPE_DEFINED #endif +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + typedef struct WOLFSSL_CIPHER WOLFSSL_CIPHER; typedef struct WOLFSSL_X509_LOOKUP WOLFSSL_X509_LOOKUP; typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD; typedef struct WOLFSSL_X509_CRL WOLFSSL_X509_CRL; +typedef struct WOLFSSL_X509_STORE WOLFSSL_X509_STORE; typedef struct WOLFSSL_BIO WOLFSSL_BIO; typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD; typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION; @@ -113,20 +138,28 @@ typedef struct WOLFSSL_ASN1_STRING WOLFSSL_ASN1_STRING; typedef struct WOLFSSL_dynlock_value WOLFSSL_dynlock_value; typedef struct WOLFSSL_DH WOLFSSL_DH; typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; +typedef unsigned char* WOLFSSL_BUF_MEM; -#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME -typedef struct WOLFSSL_EVP_PKEY { - int type; /* openssh dereference */ - int save_type; /* openssh dereference */ - int pkey_sz; - union { - char* ptr; - } pkey; - #ifdef HAVE_ECC - int pkey_curve; - #endif -} WOLFSSL_EVP_PKEY; +struct WOLFSSL_ASN1_INTEGER { + /* size can be increased set at 20 for tag, length then to hold at least 16 + * byte type */ + unsigned char data[20]; + /* ASN_INTEGER | LENGTH | hex of number */ +}; + +struct WOLFSSL_ASN1_TIME { + /* MAX_DATA_SIZE is 32 */ + unsigned char data[32 + 2]; + /* ASN_TIME | LENGTH | date bytes */ +}; + +#ifndef WOLFSSL_EVP_PKEY_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +#define WOLFSSL_EVP_PKEY_TYPE_DEFINED +#endif typedef struct WOLFSSL_MD4_CTX { int buffer[32]; /* big enough to hold, check size in Init */ @@ -137,11 +170,22 @@ typedef struct WOLFSSL_COMP_METHOD { int type; /* stunnel dereference */ } WOLFSSL_COMP_METHOD; +struct WOLFSSL_X509_LOOKUP_METHOD { + int type; +}; + +struct WOLFSSL_X509_LOOKUP { + WOLFSSL_X509_STORE *store; +}; -typedef struct WOLFSSL_X509_STORE { - int cache; /* stunnel dereference */ +struct WOLFSSL_X509_STORE { + int cache; /* stunnel dereference */ WOLFSSL_CERT_MANAGER* cm; -} WOLFSSL_X509_STORE; + WOLFSSL_X509_LOOKUP lookup; +#ifdef OPENSSL_EXTRA + int isDynamic; +#endif +}; typedef struct WOLFSSL_ALERT { int code; @@ -174,6 +218,7 @@ typedef struct WOLFSSL_BUFFER_INFO { typedef struct WOLFSSL_X509_STORE_CTX { WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ WOLFSSL_X509* current_cert; /* stunnel dereference */ + WOLFSSL_STACK* chain; char* domain; /* subject CN domain name */ void* ex_data; /* external data, for fortress build */ void* userCtx; /* user ctx */ @@ -184,6 +229,7 @@ typedef struct WOLFSSL_X509_STORE_CTX { WOLFSSL_BUFFER_INFO* certs; /* peer certs */ } WOLFSSL_X509_STORE_CTX; +typedef char* WOLFSSL_STRING; /* Valid Alert types from page 16/17 */ enum AlertDescription { @@ -230,6 +276,10 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap); +#endif WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); @@ -239,6 +289,7 @@ WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap); WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap); #endif +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void); @@ -247,6 +298,10 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void); WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void); +#endif #ifdef WOLFSSL_DTLS WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void); @@ -328,21 +383,36 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int); WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); +WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*); WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int); WOLFSSL_API int wolfSSL_set_write_fd (WOLFSSL*, int); WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL*, int); WOLFSSL_API char* wolfSSL_get_cipher_list(int priority); WOLFSSL_API int wolfSSL_get_ciphers(char*, int); WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); +WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, + int len); +WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*); WOLFSSL_API void wolfSSL_set_using_nonblock(WOLFSSL*, int); WOLFSSL_API int wolfSSL_get_using_nonblock(WOLFSSL*); -WOLFSSL_API int wolfSSL_connect(WOLFSSL*); /* please see note at top of README - if you get an error from connect */ +/* please see note at top of README if you get an error from connect */ +WOLFSSL_API int wolfSSL_connect(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); +#endif WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int); WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int); WOLFSSL_API int wolfSSL_peek(WOLFSSL*, void*, int); WOLFSSL_API int wolfSSL_accept(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*); +#endif WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); WOLFSSL_API void wolfSSL_free(WOLFSSL*); WOLFSSL_API int wolfSSL_shutdown(WOLFSSL*); @@ -373,7 +443,7 @@ WOLFSSL_API #endif /* SESSION_INDEX && SESSION_CERTS */ typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); -typedef int (*pem_password_cb)(char*, int, int, void*); +typedef int (pem_password_cb)(char*, int, int, void*); WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, VerifyCallback verify_callback); @@ -438,6 +508,14 @@ WOLFSSL_API int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509); WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(STACK_OF(WOLFSSL_X509_NAME)* sk); WOLFSSL_API void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void); +WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, + WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop( + STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in); WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*); WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*); @@ -455,7 +533,7 @@ WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL*); WOLFSSL_API const char* wolfSSL_get_version(WOLFSSL*); WOLFSSL_API int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL*); -WOLFSSL_API char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER*, char*, int); +WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int); WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher); WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); @@ -497,15 +575,38 @@ WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void); WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void); WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int); -WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,const unsigned char** p); +WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p); WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len); -WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag); -WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); - +WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag); +WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag); +WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); WOLFSSL_API int wolfSSL_add_all_algorithms(void); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void); +#endif + +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void); + +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); + +WOLFSSL_API int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size); +WOLFSSL_API int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2); +WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b); +WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf); +WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_reset(WOLFSSL_BIO *bio); + +WOLFSSL_API int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); +WOLFSSL_API int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); +WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v); +WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m); + WOLFSSL_API void wolfSSL_RAND_screen(void); WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long); WOLFSSL_API int wolfSSL_RAND_write_file(const char*); @@ -574,6 +675,10 @@ WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void); WOLFSSL_API void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*); WOLFSSL_API int wolfSSL_X509_STORE_add_cert( WOLFSSL_X509_STORE*, WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, + unsigned long flag); WOLFSSL_API int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*); WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*, int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*); @@ -591,6 +696,9 @@ WOLFSSL_API int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKE WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX*, int); WOLFSSL_API void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, + WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void); WOLFSSL_API void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY*); WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*); @@ -606,8 +714,14 @@ WOLFSSL_API int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*, const WOLFSSL_ASN1_INTEGER*); WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn); WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +#endif +WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s); WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, STACK_OF(WOLFSSL_X509_NAME)*); WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int); @@ -616,7 +730,8 @@ WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int); WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*, void* userdata); -WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, pem_password_cb); +WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, + pem_password_cb*); WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*, @@ -648,11 +763,72 @@ WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*); WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*); + +WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v); +WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg); +WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg( + WOLFSSL_CTX*, void* arg); + +WOLFSSL_API unsigned long wolfSSL_set_options(WOLFSSL *s, unsigned long op); +WOLFSSL_API unsigned long wolfSSL_get_options(const WOLFSSL *s); +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh); +WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type); +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp); +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len); + +WOLFSSL_API void wolfSSL_CONF_modules_unload(int all); +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl); + #define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ #define WOLFSSL_RSA_F4 0x10001L +/* seperated out from other enums because of size */ +enum { + SSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001, + SSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000004, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 0x00000008, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000010, + SSL_OP_MSIE_SSLV2_RSA_PADDING = 0x00000020, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000040, + SSL_OP_TLS_D5_BUG = 0x00000080, + SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000100, + SSL_OP_TLS_ROLLBACK_BUG = 0x00000200, + SSL_OP_ALL = 0x00000400, + SSL_OP_EPHEMERAL_RSA = 0x00000800, + SSL_OP_NO_SSLv3 = 0x00001000, + SSL_OP_NO_TLSv1 = 0x00002000, + SSL_OP_PKCS1_CHECK_1 = 0x00004000, + SSL_OP_PKCS1_CHECK_2 = 0x00008000, + SSL_OP_NETSCAPE_CA_DN_BUG = 0x00010000, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x00020000, + SSL_OP_SINGLE_DH_USE = 0x00040000, + SSL_OP_NO_TICKET = 0x00080000, + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00100000, + SSL_OP_NO_QUERY_MTU = 0x00200000, + SSL_OP_COOKIE_EXCHANGE = 0x00400000, + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000, + SSL_OP_SINGLE_ECDH_USE = 0x01000000, + SSL_OP_CIPHER_SERVER_PREFERENCE = 0x02000000, + SSL_OP_NO_TLSv1_1 = 0x04000000, + SSL_OP_NO_TLSv1_2 = 0x08000000, + SSL_OP_NO_COMPRESSION = 0x10000000, +}; + + enum { OCSP_NOCERTS = 1, OCSP_NOINTERN = 2, @@ -677,46 +853,29 @@ enum { WOLFSSL_OCSP_CHECKALL = 4, WOLFSSL_CRL_CHECKALL = 1, + WOLFSSL_CRL_CHECK = 27, ASN1_GENERALIZEDTIME = 4, - - SSL_OP_MICROSOFT_SESS_ID_BUG = 1, - SSL_OP_NETSCAPE_CHALLENGE_BUG = 2, - SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 3, - SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 4, - SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 5, - SSL_OP_MSIE_SSLV2_RSA_PADDING = 6, - SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 7, - SSL_OP_TLS_D5_BUG = 8, - SSL_OP_TLS_BLOCK_PADDING_BUG = 9, - SSL_OP_TLS_ROLLBACK_BUG = 10, - SSL_OP_ALL = 11, - SSL_OP_EPHEMERAL_RSA = 12, - SSL_OP_NO_SSLv3 = 13, - SSL_OP_NO_TLSv1 = 14, - SSL_OP_PKCS1_CHECK_1 = 15, - SSL_OP_PKCS1_CHECK_2 = 16, - SSL_OP_NETSCAPE_CA_DN_BUG = 17, - SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 18, - SSL_OP_SINGLE_DH_USE = 19, - SSL_OP_NO_TICKET = 20, - SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 21, - SSL_OP_NO_QUERY_MTU = 22, - SSL_OP_COOKIE_EXCHANGE = 23, - SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 24, - SSL_OP_SINGLE_ECDH_USE = 25, - SSL_OP_CIPHER_SERVER_PREFERENCE = 26, - SSL_MAX_SSL_SESSION_ID_LENGTH = 32, EVP_R_BAD_DECRYPT = 2, - SSL_CB_LOOP = 4, - SSL_ST_CONNECT = 5, - SSL_ST_ACCEPT = 6, - SSL_CB_ALERT = 7, - SSL_CB_READ = 8, - SSL_CB_HANDSHAKE_DONE = 9, + SSL_ST_CONNECT = 0x1000, + SSL_ST_ACCEPT = 0x2000, + + SSL_CB_LOOP = 0x01, + SSL_CB_EXIT = 0x02, + SSL_CB_READ = 0x04, + SSL_CB_WRITE = 0x08, + SSL_CB_HANDSHAKE_START = 0x10, + SSL_CB_HANDSHAKE_DONE = 0x20, + SSL_CB_ALERT = 0x4000, + SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ), + SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE), + SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP), + SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT), + SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP), + SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT), SSL_MODE_ENABLE_PARTIAL_WRITE = 2, @@ -730,21 +889,56 @@ enum { X509_LU_X509 = 9, X509_LU_CRL = 12, - X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, - X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, - X509_V_ERR_CRL_HAS_EXPIRED = 15, - X509_V_ERR_CERT_REVOKED = 16, - X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, - X509_V_ERR_CERT_NOT_YET_VALID = 19, - X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, - X509_V_ERR_CERT_HAS_EXPIRED = 21, - X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, - X509_V_ERR_CERT_REJECTED = 23, - X509_V_OK = 0, + X509_V_OK = 0, + X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, + X509_V_ERR_CRL_HAS_EXPIRED = 15, + X509_V_ERR_CERT_REVOKED = 16, + X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, + X509_V_ERR_CERT_NOT_YET_VALID = 19, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, + X509_V_ERR_CERT_HAS_EXPIRED = 21, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, + X509_V_ERR_CERT_REJECTED = 23, + /* Required for Nginx */ + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 24, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 25, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26, + X509_V_ERR_CERT_UNTRUSTED = 27, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 28, + X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29, + /* additional X509_V_ERR_* enums not used in wolfSSL */ + X509_V_ERR_UNABLE_TO_GET_CRL, + X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, + X509_V_ERR_CERT_SIGNATURE_FAILURE, + X509_V_ERR_CRL_NOT_YET_VALID, + X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, + X509_V_ERR_OUT_OF_MEM, + X509_V_ERR_INVALID_CA, + X509_V_ERR_PATH_LENGTH_EXCEEDED, + X509_V_ERR_INVALID_PURPOSE, + X509_V_ERR_AKID_SKID_MISMATCH, + X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, + X509_V_ERR_KEYUSAGE_NO_CERTSIGN, + X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, + X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, + X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, + X509_V_ERR_INVALID_NON_CA, + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, + X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, + X509_V_ERR_INVALID_EXTENSION, + X509_V_ERR_INVALID_POLICY_EXTENSION, + X509_V_ERR_NO_EXPLICIT_POLICY, + X509_V_ERR_UNNESTED_RESOURCE, XN_FLAG_SPC_EQ = (1 << 23), XN_FLAG_ONELINE = 0, + XN_FLAG_RFC2253 = 1, CRYPTO_LOCK = 1, CRYPTO_NUM_LOCKS = 10, @@ -759,6 +953,9 @@ enum { since not using thread storage error queue */ #include WOLFSSL_API void wolfSSL_ERR_print_errors_fp(FILE*, int err); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(FILE* fp); +#endif #endif enum { /* ssl Constants */ @@ -788,12 +985,14 @@ enum { /* ssl Constants */ SSL_VERIFY_CLIENT_ONCE = 4, SSL_VERIFY_FAIL_EXCEPT_PSK = 8, - SSL_SESS_CACHE_OFF = 30, - SSL_SESS_CACHE_CLIENT = 31, - SSL_SESS_CACHE_SERVER = 32, - SSL_SESS_CACHE_BOTH = 33, - SSL_SESS_CACHE_NO_AUTO_CLEAR = 34, - SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35, + SSL_SESS_CACHE_OFF = 0x0000, + SSL_SESS_CACHE_CLIENT = 0x0001, + SSL_SESS_CACHE_SERVER = 0x0002, + SSL_SESS_CACHE_BOTH = 0x0003, + SSL_SESS_CACHE_NO_AUTO_CLEAR = 0x0008, + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100, + SSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200, + SSL_SESS_CACHE_NO_INTERNAL = 0x0300, SSL_ERROR_WANT_READ = 2, SSL_ERROR_WANT_WRITE = 3, @@ -854,6 +1053,14 @@ enum { /* ERR Constants */ ERR_TXT_STRING = 1 }; +/* bio misc */ +enum { + WOLFSSL_BIO_ERROR = -1, + WOLFSSL_BIO_UNSET = -2, + WOLFSSL_BIO_SIZE = 17000 /* default BIO write size if not set */ +}; + + WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*, const char**, int *); @@ -873,6 +1080,7 @@ WOLFSSL_API void wolfSSL_ERR_free_strings(void); WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long); WOLFSSL_API void wolfSSL_EVP_cleanup(void); WOLFSSL_API int wolfSSL_clear(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_state(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void); WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode); @@ -880,7 +1088,6 @@ WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx); WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m); WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl); -WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); WOLFSSL_API int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*, @@ -893,6 +1100,8 @@ WOLFSSL_API int wolfSSL_want_write(WOLFSSL*); WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...); WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_UTCTIME*); +WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_GENERALIZEDTIME*); WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_X509_REVOKED*); WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED*, int); @@ -1116,9 +1325,6 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*); -/* I/O callbacks */ -typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); -typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); #ifdef HAVE_FUZZER enum fuzzer_type { @@ -1135,64 +1341,7 @@ typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz, WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx); #endif -WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); -WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); - -WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); -WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); - -WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl); -WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); - -WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); -WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); - -#ifndef WOLFSSL_USER_IO - /* default IO callbacks */ - WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); - WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); - #ifdef HAVE_OCSP - WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*, - int, unsigned char**); - WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*); - #endif - - #ifdef WOLFSSL_DTLS - WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*); - WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); - WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, - int sz, void*); - #ifdef WOLFSSL_SESSION_EXPORT - WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, - unsigned short* port, int* fam); - WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, - unsigned short port, int fam); - - typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz, - unsigned short* port, int* fam); - typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz, - unsigned short port, int fam); - - WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, - CallbackGetPeer); - WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, - CallbackSetPeer); - #endif /* WOLFSSL_SESSION_EXPORT */ - #endif /* WOLFSSL_DTLS */ -#endif /* WOLFSSL_USER_IO */ - - -#ifdef HAVE_NETX - WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, - ULONG waitoption); -#endif - -typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, - void* ctx); -WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie); -WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); -WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_DTLS_SetCookieSecret(WOLFSSL*, const unsigned char*, unsigned int); @@ -1250,6 +1399,10 @@ typedef int (*CbOCSPIO)(void*, const char*, int, unsigned char*, int, unsigned char**); typedef void (*CbOCSPRespFree)(void*,unsigned char*); +#ifdef HAVE_CRL_IO +typedef int (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz); +#endif + /* User Atomic Record Layer CallBacks */ typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut, const unsigned char* macIn, unsigned int macInSz, int macContent, @@ -1290,6 +1443,7 @@ WOLFSSL_API int wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char enum { WOLFSSL_SERVER_END = 0, WOLFSSL_CLIENT_END = 1, + WOLFSSL_NEITHER_END = 3, WOLFSSL_BLOCK_TYPE = 2, WOLFSSL_STREAM_TYPE = 3, WOLFSSL_AEAD_TYPE = 4, @@ -1420,6 +1574,10 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*, + CbCrlIO); +#endif WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*, unsigned char*, int sz); WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*, @@ -1439,6 +1597,9 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*, const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb); +#endif WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options); WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*); WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*); @@ -1450,6 +1611,9 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*, const unsigned char*, long sz, int); WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO); +#endif WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options); WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*); WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*); @@ -1470,6 +1634,11 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*); WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*); +WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl); /* async additions */ WOLFSSL_API int wolfSSL_UseAsync(WOLFSSL*, int devId); @@ -1545,6 +1714,12 @@ enum { WOLFSSL_MAX_ALPN_NUMBER = 257 }; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out, + unsigned char* outLen, const unsigned char* in, unsigned int inLen, + void *arg); +#endif + WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, unsigned int protocol_name_listSz, unsigned char options); @@ -1634,7 +1809,7 @@ WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, #endif #endif -/* Elliptic Curves */ +/* Named Groups */ enum { #if 0 /* Not Supported */ WOLFSSL_ECC_SECT163K1 = 1, @@ -1666,6 +1841,19 @@ enum { WOLFSSL_ECC_BRAINPOOLP256R1 = 26, WOLFSSL_ECC_BRAINPOOLP384R1 = 27, WOLFSSL_ECC_BRAINPOOLP512R1 = 28, +#ifdef WOLFSSL_TLS13 + /* Not implemented. */ + WOLFSSL_ECC_X25519 = 29, + /* Not implemented. */ + WOLFSSL_ECC_X448 = 30, + + /* Not implemented. */ + WOLFSSL_FFDHE_2048 = 256, + WOLFSSL_FFDHE_3072 = 257, + WOLFSSL_FFDHE_4096 = 258, + WOLFSSL_FFDHE_6144 = 259, + WOLFSSL_FFDHE_8192 = 260, +#endif }; #ifdef HAVE_SUPPORTED_CURVES @@ -1678,6 +1866,11 @@ WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, #endif #endif +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, unsigned short group); +WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl); +#endif + /* Secure Renegotiation */ #ifdef HAVE_SECURE_RENEGOTIATION @@ -1694,7 +1887,7 @@ WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx); WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, unsigned int*); -WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, unsigned char*, unsigned int); +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, unsigned int); typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*); WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*, CallbackSessionTicket, void*); @@ -1748,7 +1941,8 @@ WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name); then will not send keys in the hello extension */ WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag); #endif -#endif + +#endif /* QSH */ /* TLS Extended Master Secret Extension */ WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl); @@ -1814,16 +2008,63 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, WOLFSSL_API void wolfSSL_cert_service(void); #endif -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len); #endif /* WOLFSSL_MYSQL_COMPATIBLE */ #ifdef OPENSSL_EXTRA -WOLFSSL_API int wolfSSL_get_client_random(WOLFSSL* ssl, unsigned char* out, - int outSz); +#ifndef NO_FILESYSTEM +WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c); +WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp); +#endif +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line); +WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); +WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); + +#ifndef NO_CERTS +WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx); +WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509, + const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len); +WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, + int derSz); +WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey); +WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, + unsigned char* der, long derSz); +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl); +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, + long derSz); +#endif +#endif /* NO_CERTS */ + +WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r); + +WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz); +WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses); + +WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, + WOLFSSL_X509_STORE* str); +WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); + +WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); +WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl, + unsigned char *out, size_t outlen); +WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, + unsigned char* out, size_t outSz); +WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx); +WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx); +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX + (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); /*lighttp compatibility */ @@ -1836,20 +2077,22 @@ struct WOLFSSL_X509_NAME_ENTRY { int size; }; -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name); WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x); -WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); -WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void); /* These are to be merged shortly */ -WOLFSSL_API const char * wolf_OBJ_nid2sn(int n); -WOLFSSL_API int wolf_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); -WOLFSSL_API int wolf_OBJ_sn2nid(const char *sn); -WOLFSSL_API WOLFSSL_X509 *PEM_read_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API const char * wolfSSL_OBJ_nid2sn(int n); +WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); +WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn); WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); -WOLFSSL_API void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); +WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc); WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)); @@ -1857,26 +2100,32 @@ WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsign WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X509_NAME) *sk ); -/* end lighttpd, mysql, have_stunnel*/ +/* end lighttpd*/ #endif #endif #if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) -WOLFSSL_API char * wolf_OBJ_nid2ln(int n); -WOLFSSL_API int wolf_OBJ_txt2nid(const char *sn); +WOLFSSL_API char* wolfSSL_OBJ_nid2ln(int n); +WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn); WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode); WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*); WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, pem_password_cb *cb, void *u); -WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x); +WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, + WOLFSSL_DSA **x, pem_password_cb *cb, void *u); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x); +WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); + #endif /* HAVE_STUNNEL || HAVE_LIGHTY */ -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #include @@ -1928,8 +2177,6 @@ WOLFSSL_API void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)*, int); WOLFSSL_API STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); -WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); - WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int); WOLFSSL_API int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*); @@ -1953,24 +2200,31 @@ WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *, CallbackSniRecv); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); WOLFSSL_API void WOLFSSL_ERR_remove_thread_state(void*); +#ifndef NO_FILESYSTEM +WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE *fp); +#endif + WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long); WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*)); WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val); -WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX*, - WOLFSSL_X509_NAME*); +WOLFSSL_API STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); WOLFSSL_API void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ -#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx); @@ -1988,6 +2242,141 @@ WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int WOLF_EVENT_FLAG flags, int* eventCount); #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef OPENSSL_EXTRA +typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type, + const void *buf, size_t len, WOLFSSL *ssl, void *arg); + +WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg); +WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg); +#endif + +#ifdef OPENSSL_EXTRA +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, + int *line, const char **data, int *flags); +#endif + +#if defined WOLFSSL_NGINX || defined WOLFSSL_HAPROXY +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response); +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl); +/* Not an OpenSSL API. */ +WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); + +WOLFSSL_API STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl); +WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); +WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, + void *b, void *c); +WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); +WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, + void *data); + +WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len); + +WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx); +WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, + WOLFSSL_EC_KEY *ecdh); +WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *, + WOLFSSL_SESSION *c); + +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */ +WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, + size_t chklen, unsigned int flags, char **peername); + +WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, + const WOLFSSL_ASN1_INTEGER *a); + +#ifdef HAVE_SESSION_TICKET +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +#endif + +#ifdef HAVE_OCSP +WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, + STACK_OF(X509)** chain); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*)(WOLFSSL*, void*)); + +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x); + +WOLFSSL_API void wolfSSL_X509_email_free(STACK_OF(WOLFSSL_STRING) *sk); +WOLFSSL_API STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x); + +WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, + WOLFSSL_X509 *subject); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x); + +WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value( + STACK_OF(WOLFSSL_STRING)* strings, int idx); +#endif /* HAVE_OCSP */ + +WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, + WOLFSSL_X509 *cert); +#endif /* WOLFSSL_NGINX */ + +WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, + const unsigned char **data, unsigned int *len); +WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out, + unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); +WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len); + + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context( + const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length); +#endif + +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len); +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len); +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x); +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor); +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x); +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub); +WOLFSSL_API int EVP_PKEY_bits(WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API int i2d_X509(WOLFSSL_X509 *x, unsigned char **out); +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count); +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count); +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); +WOLFSSL_API STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir); +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p); +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx); +WOLFSSL_API void ERR_load_SSL_strings(void); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/test.h b/wolfssl/test.h index e0a3c1a0ef..9cc8ff6b55 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -10,7 +10,6 @@ #include #include #include -#include #ifdef ATOMIC_USER #include @@ -19,6 +18,9 @@ #endif #ifdef HAVE_PK_CALLBACKS #include + #ifndef NO_RSA + #include + #endif #ifdef HAVE_ECC #include #endif /* HAVE_ECC */ @@ -245,37 +247,37 @@ /* all certs relative to wolfSSL home directory now */ #if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL) -#define caCert "certs/ca-cert.pem" -#define eccCert "certs/server-ecc.pem" -#define eccKey "certs/ecc-key.pem" -#define svrCert "certs/server-cert.pem" -#define svrKey "certs/server-key.pem" -#define cliCert "certs/client-cert.pem" -#define cliKey "certs/client-key.pem" -#define ntruCert "certs/ntru-cert.pem" -#define ntruKey "certs/ntru-key.raw" -#define dhParam "certs/dh2048.pem" -#define cliEccKey "certs/ecc-client-key.pem" -#define cliEccCert "certs/client-ecc-cert.pem" -#define crlPemDir "certs/crl" +#define caCertFile "certs/ca-cert.pem" +#define eccCertFile "certs/server-ecc.pem" +#define eccKeyFile "certs/ecc-key.pem" +#define svrCertFile "certs/server-cert.pem" +#define svrKeyFile "certs/server-key.pem" +#define cliCertFile "certs/client-cert.pem" +#define cliKeyFile "certs/client-key.pem" +#define ntruCertFile "certs/ntru-cert.pem" +#define ntruKeyFile "certs/ntru-key.raw" +#define dhParamFile "certs/dh2048.pem" +#define cliEccKeyFile "certs/ecc-client-key.pem" +#define cliEccCertFile "certs/client-ecc-cert.pem" +#define crlPemDir "certs/crl" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "wnr-example.conf" #endif #else -#define caCert "./certs/ca-cert.pem" -#define eccCert "./certs/server-ecc.pem" -#define eccKey "./certs/ecc-key.pem" -#define svrCert "./certs/server-cert.pem" -#define svrKey "./certs/server-key.pem" -#define cliCert "./certs/client-cert.pem" -#define cliKey "./certs/client-key.pem" -#define ntruCert "./certs/ntru-cert.pem" -#define ntruKey "./certs/ntru-key.raw" -#define dhParam "./certs/dh2048.pem" -#define cliEccKey "./certs/ecc-client-key.pem" -#define cliEccCert "./certs/client-ecc-cert.pem" -#define crlPemDir "./certs/crl" +#define caCertFile "./certs/ca-cert.pem" +#define eccCertFile "./certs/server-ecc.pem" +#define eccKeyFile "./certs/ecc-key.pem" +#define svrCertFile "./certs/server-cert.pem" +#define svrKeyFile "./certs/server-key.pem" +#define cliCertFile "./certs/client-cert.pem" +#define cliKeyFile "./certs/client-key.pem" +#define ntruCertFile "./certs/ntru-cert.pem" +#define ntruKeyFile "./certs/ntru-key.raw" +#define dhParamFile "./certs/dh2048.pem" +#define cliEccKeyFile "./certs/ecc-client-key.pem" +#define cliEccCertFile "./certs/client-ecc-cert.pem" +#define crlPemDir "./certs/crl" #ifdef HAVE_WNR /* Whitewood netRandom default config file */ #define wnrConfig "./wnr-example.conf" @@ -300,8 +302,8 @@ static INLINE void InitTcpReady(tcp_ready* ready) ready->srfName = NULL; #ifdef SINGLE_THREADED #elif defined(_POSIX_THREADS) && !defined(__MINGW32__) - pthread_mutex_init(&ready->mutex, 0); - pthread_cond_init(&ready->cond, 0); + pthread_mutex_init(&ready->mutex, 0); + pthread_cond_init(&ready->cond, 0); #endif } @@ -514,6 +516,12 @@ static INLINE void showPeer(WOLFSSL* ssl) { WOLFSSL_CIPHER* cipher; +#ifdef HAVE_ECC + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); if (peer) @@ -524,6 +532,7 @@ static INLINE void showPeer(WOLFSSL* ssl) #endif #if defined(SHOW_CERTS) && defined(OPENSSL_EXTRA) && defined(KEEP_OUR_CERT) ShowX509(wolfSSL_get_certificate(ssl), "our cert info:"); + printf("Peer verify result = %lu\n", wolfSSL_get_verify_result(ssl)); #endif /* SHOW_CERTS */ printf("SSL version is %s\n", wolfSSL_get_version(ssl)); @@ -534,6 +543,16 @@ static INLINE void showPeer(WOLFSSL* ssl) #else printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); #endif +#ifdef HAVE_ECC + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("SSL curve name is %s\n", name); +#endif +#ifndef NO_DH + if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("SSL DH size is %d bits\n", bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("SSL reused session\n"); #if defined(SESSION_CERTS) && defined(SHOW_CERTS) { @@ -578,7 +597,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, #ifndef TEST_IPV6 /* peer could be in human readable form */ - if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) { + if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) { #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) int err; struct hostent* entry = gethostbyname(peer, &err); @@ -607,8 +626,8 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, #else addr->sin_family = AF_INET_V; #endif - addr->sin_port = htons(port); - if (peer == INADDR_ANY) + addr->sin_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) addr->sin_addr.s_addr = INADDR_ANY; else { if (!useLookup) @@ -616,7 +635,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } #else addr->sin6_family = AF_INET_V; - addr->sin6_port = htons(port); + addr->sin6_port = XHTONS(port); if (peer == INADDR_ANY) addr->sin6_addr = in6addr_any; else { @@ -664,6 +683,8 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, static INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) { + (void)sctp; + if (udp) *sockfd = socket(AF_INET_V, SOCK_DGRAM, IPPROTO_UDP); #ifdef WOLFSSL_SCTP @@ -805,9 +826,9 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, socklen_t len = sizeof(addr); if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { #ifndef TEST_IPV6 - *port = ntohs(addr.sin_port); + *port = XNTOHS(addr.sin_port); #else - *port = ntohs(addr.sin6_port); + *port = XNTOHS(addr.sin6_port); #endif } } @@ -866,9 +887,9 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, socklen_t len = sizeof(addr); if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { #ifndef TEST_IPV6 - port = ntohs(addr.sin_port); + port = XNTOHS(addr.sin_port); #else - port = ntohs(addr.sin6_port); + port = XNTOHS(addr.sin6_port); #endif } } @@ -987,6 +1008,9 @@ static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) #ifndef NO_PSK +/* identity is OpenSSL testing default for openssl s_client, keep same */ +static const char* kIdentityStr = "Client_identity"; + static INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, char* identity, unsigned int id_max_len, unsigned char* key, unsigned int key_max_len) @@ -995,9 +1019,8 @@ static INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, (void)hint; (void)key_max_len; - /* identity is OpenSSL testing default for openssl s_client, keep same */ - strncpy(identity, "Client_identity", id_max_len); - + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + strncpy(identity, kIdentityStr, id_max_len); /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using unsigned binary */ @@ -1016,8 +1039,8 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, (void)ssl; (void)key_max_len; - /* identity is OpenSSL testing default for openssl s_client, keep same */ - if (strncmp(identity, "Client_identity", 15) != 0) + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0) return 0; /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using @@ -1080,7 +1103,55 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, #endif /* USE_WINDOWS_API */ -#if defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(FORCE_BUFFER_TEST) +#if !defined(NO_CERTS) + #if !defined(NO_FILESYSTEM) || \ + (defined(NO_FILESYSTEM) && defined(FORCE_BUFFER_TEST)) + + /* reads file size, allocates buffer, reads into buffer, returns buffer */ + static INLINE int load_file(const char* fname, byte** buf, size_t* bufLen) + { + int ret; + long int fileSz; + FILE* file; + + if (fname == NULL || buf == NULL || bufLen == NULL) + return BAD_FUNC_ARG; + + /* set defaults */ + *buf = NULL; + *bufLen = 0; + + /* open file (read-only binary) */ + file = fopen(fname, "rb"); + if (!file) { + printf("Error loading %s\n", fname); + return BAD_PATH_ERROR; + } + + fseek(file, 0, SEEK_END); + fileSz = (int)ftell(file); + rewind(file); + if (fileSz > 0) { + *bufLen = (size_t)fileSz; + *buf = (byte*)malloc(*bufLen); + if (*buf == NULL) { + ret = MEMORY_E; + printf("Error allocating %lu bytes\n", (unsigned long)*bufLen); + } + else { + size_t readLen = fread(*buf, *bufLen, 1, file); + + /* check response code */ + ret = (readLen > 0) ? 0 : -1; + } + } + else { + ret = BUFFER_E; + } + fclose(file); + + return ret; + } enum { WOLFSSL_CA = 1, @@ -1092,60 +1163,52 @@ static INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, static INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type) { int format = SSL_FILETYPE_PEM; + byte* buff = NULL; + size_t sz = 0; - /* test buffer load */ - long sz = 0; - byte buff[10000]; - FILE* file = fopen(fname, "rb"); - - if (!file) + if (load_file(fname, &buff, &sz) != 0) { err_sys("can't open file for buffer load " "Please run from wolfSSL home directory if not"); - fseek(file, 0, SEEK_END); - sz = ftell(file); - rewind(file); - fread(buff, sizeof(buff), 1, file); + } /* determine format */ if (strstr(fname, ".der")) format = SSL_FILETYPE_ASN1; if (type == WOLFSSL_CA) { - if (wolfSSL_CTX_load_verify_buffer(ctx, buff, sz, format) + if (wolfSSL_CTX_load_verify_buffer(ctx, buff, (long)sz, format) != SSL_SUCCESS) err_sys("can't load buffer ca file"); } else if (type == WOLFSSL_CERT) { - if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, sz, + if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, (long)sz, format) != SSL_SUCCESS) err_sys("can't load buffer cert file"); } else if (type == WOLFSSL_KEY) { - if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, sz, + if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, (long)sz, format) != SSL_SUCCESS) err_sys("can't load buffer key file"); } else if (type == WOLFSSL_CERT_CHAIN) { - if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buff, sz, - format) != SSL_SUCCESS) + if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buff, + (long)sz, format) != SSL_SUCCESS) err_sys("can't load cert chain buffer"); } - fclose(file); + if (buff) + free(buff); } - -#endif /* NO_FILESYSTEM */ - -#ifdef VERIFY_CALLBACK + #endif /* !NO_FILESYSTEM || (NO_FILESYSTEM && FORCE_BUFFER_TEST) */ +#endif /* !NO_CERTS */ static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) { - (void)preverify; char buffer[WOLFSSL_MAX_ERROR_SZ]; - #ifdef OPENSSL_EXTRA WOLFSSL_X509* peer; #endif + (void)preverify; printf("In verification callback, error = %d, %s\n", store->error, wolfSSL_ERR_error_string(store->error, buffer)); @@ -1181,8 +1244,6 @@ static INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) return 1; } -#endif /* VERIFY_CALLBACK */ - static INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) { @@ -1282,10 +1343,6 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) /* Wolf Root Directory Helper */ /* KEIL-RL File System does not support relative directory */ #if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) - #ifndef MAX_PATH - #define MAX_PATH 256 - #endif - /* Maximum depth to search for WolfSSL root */ #define MAX_WOLF_ROOT_DEPTH 5 @@ -1295,7 +1352,7 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) int depth, res; FILE* file; for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { - file = fopen(ntruKey, "rb"); + file = fopen(ntruKeyFile, "rb"); if (file != NULL) { fclose(file); return depth; @@ -1324,9 +1381,10 @@ static INLINE void CaCb(unsigned char* der, int sz, int type) typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); -static INLINE void StackSizeCheck(func_args* args, thread_func tf) +static INLINE int StackSizeCheck(func_args* args, thread_func tf) { int ret, i, used; + void* status; unsigned char* myStack = NULL; int stackSize = 1024*128; pthread_attr_t myAttr; @@ -1357,7 +1415,7 @@ static INLINE void StackSizeCheck(func_args* args, thread_func tf) exit(EXIT_FAILURE); } - ret = pthread_join(threadId, NULL); + ret = pthread_join(threadId, &status); if (ret != 0) err_sys("pthread_join failed"); @@ -1367,8 +1425,12 @@ static INLINE void StackSizeCheck(func_args* args, thread_func tf) } } + free(myStack); + used = stackSize - i; printf("stack used = %d\n", used); + + return (int)((size_t)status); } @@ -1673,12 +1735,13 @@ static INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret != 0) return ret; - wc_ecc_init(&myKey); - - ret = wc_EccPrivateKeyDecode(key, &idx, &myKey, keySz); - if (ret == 0) - ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); - wc_ecc_free(&myKey); + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); + wc_ecc_free(&myKey); + } wc_FreeRng(&rng); return ret; @@ -1695,12 +1758,13 @@ static INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, (void)ssl; (void)ctx; - wc_ecc_init(&myKey); - - ret = wc_ecc_import_x963(key, keySz, &myKey); - if (ret == 0) - ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); - wc_ecc_free(&myKey); + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_ecc_import_x963(key, keySz, &myKey); + if (ret == 0) + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); + wc_ecc_free(&myKey); + } return ret; } @@ -1780,16 +1844,17 @@ static INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret != 0) return ret; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); - if (ret == 0) - ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); - if (ret > 0) { /* save and convert to 0 success */ - *outSz = ret; - ret = 0; + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); } - wc_FreeRsaKey(&myKey); wc_FreeRng(&rng); return ret; @@ -1808,12 +1873,13 @@ static INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, (void)ssl; (void)ctx; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); - if (ret == 0) - ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); - wc_FreeRsaKey(&myKey); + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); + wc_FreeRsaKey(&myKey); + } return ret; } @@ -1835,17 +1901,18 @@ static INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret != 0) return ret; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + ret = wc_InitRsaKey(&myKey, NULL); if (ret == 0) { - ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); - if (ret > 0) { - *outSz = ret; - ret = 0; /* reset to success */ + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { + *outSz = ret; + ret = 0; /* reset to success */ + } } + wc_FreeRsaKey(&myKey); } - wc_FreeRsaKey(&myKey); wc_FreeRng(&rng); return ret; @@ -1862,20 +1929,21 @@ static INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, (void)ssl; (void)ctx; - wc_InitRsaKey(&myKey, NULL); - - ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + ret = wc_InitRsaKey(&myKey, NULL); if (ret == 0) { - #ifdef WC_RSA_BLINDING - ret = wc_RsaSetRNG(&myKey, wolfSSL_GetRNG(ssl)); - if (ret != 0) { - wc_FreeRsaKey(&myKey); - return ret; - } - #endif - ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&myKey, wolfSSL_GetRNG(ssl)); + if (ret != 0) { + wc_FreeRsaKey(&myKey); + return ret; + } + #endif + ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + } + wc_FreeRsaKey(&myKey); } - wc_FreeRsaKey(&myKey); return ret; } @@ -1976,8 +2044,8 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) #include typedef struct key_ctx { - byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */ - byte key[16]; /* cipher key */ + byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */ + byte key[CHACHA20_POLY1305_AEAD_KEYSIZE]; /* cipher key */ } key_ctx; static key_ctx myKey_ctx; @@ -2013,7 +2081,7 @@ static INLINE const char* mymktemp(char *tempfn, int len, int num) (void)userCtx; int ret; - word16 sLen = htons(inLen); + word16 sLen = XHTONS(inLen); byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2]; int aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2; byte* tmp = aad; diff --git a/wolfssl/version.h b/wolfssl/version.h index bd92deb26b..1cdc11c58e 100644 --- a/wolfssl/version.h +++ b/wolfssl/version.h @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "3.10.0" -#define LIBWOLFSSL_VERSION_HEX 0x03010000 +#define LIBWOLFSSL_VERSION_STRING "3.11.1" +#define LIBWOLFSSL_VERSION_HEX 0x03011001 #ifdef __cplusplus } diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h old mode 100644 new mode 100755 index b7fb2c776e..785edc1817 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -73,6 +73,7 @@ typedef struct Aes { /* AESNI needs key first, rounds 2nd, not sure why yet */ ALIGN16 word32 key[60]; word32 rounds; + int keylen; ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ @@ -88,10 +89,9 @@ typedef struct Aes { byte use_aesni; #endif /* WOLFSSL_AESNI */ #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; - #ifdef HAVE_CAVIUM - AesType type; /* aes key type */ - #endif + const byte* asyncKey; + const byte* asyncIv; + WC_ASYNC_DEV asyncDev; #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AES_COUNTER word32 left; /* unused bytes left from last call */ @@ -99,10 +99,6 @@ typedef struct Aes { #ifdef WOLFSSL_PIC32MZ_CRYPT word32 key_ce[AES_BLOCK_SIZE*2/sizeof(word32)] ; word32 iv_ce [AES_BLOCK_SIZE /sizeof(word32)] ; - int keylen ; -#endif -#ifdef WOLFSSL_TI_CRYPT - int keylen ; #endif void* heap; /* memory hint to use */ } Aes; @@ -115,7 +111,20 @@ typedef struct Gmac { #endif /* HAVE_AESGCM */ #endif /* HAVE_FIPS */ -WOLFSSL_LOCAL int wc_InitAes_h(Aes* aes, void* h); + +/* Authenticate cipher function prototypes */ +typedef int (*wc_AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +typedef int (*wc_AesAuthDecryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +/* AES-CBC */ WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, int dir); WOLFSSL_API int wc_AesSetIV(Aes* aes, const byte* iv); @@ -124,6 +133,13 @@ WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz); +#ifdef HAVE_AES_ECB +WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif + /* AES-CTR */ #ifdef WOLFSSL_AES_COUNTER WOLFSSL_API void wc_AesCtrEncrypt(Aes* aes, byte* out, @@ -180,10 +196,8 @@ WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_AesAsyncInit(Aes*, int); - WOLFSSL_API void wc_AesAsyncFree(Aes*); -#endif +WOLFSSL_API int wc_AesInit(Aes*, void*, int); +WOLFSSL_API void wc_AesFree(Aes*); #ifdef __cplusplus } /* extern "C" */ @@ -192,4 +206,3 @@ WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); #endif /* NO_AES */ #endif /* WOLF_CRYPT_AES_H */ - diff --git a/wolfssl/wolfcrypt/arc4.h b/wolfssl/wolfcrypt/arc4.h index 752f1d0623..aab0fb984e 100644 --- a/wolfssl/wolfcrypt/arc4.h +++ b/wolfssl/wolfcrypt/arc4.h @@ -45,17 +45,16 @@ typedef struct Arc4 { byte y; byte state[ARC4_STATE_SIZE]; #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; #endif + void* heap; } Arc4; -WOLFSSL_API void wc_Arc4Process(Arc4*, byte*, const byte*, word32); -WOLFSSL_API void wc_Arc4SetKey(Arc4*, const byte*, word32); +WOLFSSL_API int wc_Arc4Process(Arc4*, byte*, const byte*, word32); +WOLFSSL_API int wc_Arc4SetKey(Arc4*, const byte*, word32); -#ifdef WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_Arc4AsyncInit(Arc4*, int); - WOLFSSL_API void wc_Arc4AsyncFree(Arc4*); -#endif +WOLFSSL_API int wc_Arc4Init(Arc4*, void*, int); +WOLFSSL_API void wc_Arc4Free(Arc4*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index fdb8dc7dc9..c0603f2a16 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -28,9 +28,6 @@ #ifndef NO_ASN #include -#ifndef NO_RSA - #include -#endif /* fips declare of RsaPrivateKeyDecode @wc_fips */ #if defined(HAVE_FIPS) && !defined(NO_RSA) @@ -51,9 +48,7 @@ #endif #include #include /* public interface */ -#ifdef HAVE_ECC - #include -#endif + #ifdef __cplusplus extern "C" { @@ -134,7 +129,8 @@ enum Misc_ASN { MAX_KEY_SIZE = 64, /* MAX PKCS Key length */ PKCS5 = 5, /* PKCS oid tag */ PKCS5v2 = 6, /* PKCS #5 v2.0 */ - PKCS12 = 12, /* PKCS #12 */ + PKCS8v0 = 0, /* default PKCS#8 version */ + PKCS12v1 = 12, /* PKCS #12 */ MAX_UNICODE_SZ = 256, ASN_BOOL_SIZE = 2, /* including type */ ASN_ECC_HEADER_SZ = 2, /* String type + 1 byte len */ @@ -188,7 +184,7 @@ enum Misc_ASN { MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif - OCSP_NONCE_EXT_SZ = 37, /* OCSP Nonce Extension size */ + OCSP_NONCE_EXT_SZ = 35, /* OCSP Nonce Extension size */ MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ EIGHTK_BUF = 8192, /* Tmp buffer size */ @@ -196,7 +192,10 @@ enum Misc_ASN { /* use bigger NTRU size */ HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */ TRAILING_ZERO = 1, /* Used for size of zero pad */ - MIN_VERSION_SZ = 3 /* Min bytes needed for GetMyVersion */ + MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + MAX_TIME_STRING_SZ = 21, /* Max length of formatted time string */ +#endif }; @@ -303,14 +302,20 @@ enum Extensions_Sum { BASIC_CA_OID = 133, ALT_NAMES_OID = 131, CRL_DIST_OID = 145, - AUTH_INFO_OID = 69, + AUTH_INFO_OID = 69, /* id-pe 1 */ AUTH_KEY_OID = 149, SUBJ_KEY_OID = 128, CERT_POLICY_OID = 146, KEY_USAGE_OID = 129, /* 2.5.29.15 */ INHIBIT_ANY_OID = 168, /* 2.5.29.54 */ - EXT_KEY_USAGE_OID = 151, /* 2.5.29.37 */ - NAME_CONS_OID = 144 /* 2.5.29.30 */ + EXT_KEY_USAGE_OID = 151, /* 2.5.29.37 */ + NAME_CONS_OID = 144, /* 2.5.29.30 */ + PRIV_KEY_USAGE_PERIOD_OID = 130, /* 2.5.29.16 */ + SUBJECT_INFO_ACCESS = 79, /* id-pe 11 */ + POLICY_MAP_OID = 147, + POLICY_CONST_OID = 150, + ISSUE_ALT_NAMES_OID = 132, + TLS_FEATURE_OID = 92 /* id-pe 24 */ }; enum CertificatePolicy_Sum { @@ -408,6 +413,60 @@ struct DecodedName { int serialLen; }; +enum SignatureState { + SIG_STATE_BEGIN, + SIG_STATE_HASH, + SIG_STATE_KEY, + SIG_STATE_DO, + SIG_STATE_CHECK, +}; + +struct SignatureCtx { + void* heap; + byte* digest; +#ifndef NO_RSA + byte* out; + byte* plain; +#endif +#ifdef HAVE_ECC + int verify; +#endif + union { + #ifndef NO_RSA + struct RsaKey* rsa; + #endif + #ifdef HAVE_ECC + struct ecc_key* ecc; + #endif + void* ptr; + } key; + int devId; + int state; + int typeH; + int digestSz; + word32 keyOID; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev; +#endif +}; + +enum CertSignState { + CERTSIGN_STATE_BEGIN, + CERTSIGN_STATE_DIGEST, + CERTSIGN_STATE_ENCODE, + CERTSIGN_STATE_DO, +}; + +struct CertSignCtx { + byte* sig; + byte* digest; + #ifndef NO_RSA + byte* encSig; + int encSigSz; + #endif + int state; /* enum CertSignState */ +}; + typedef struct DecodedCert DecodedCert; typedef struct DecodedName DecodedName; @@ -415,6 +474,8 @@ typedef struct Signer Signer; #ifdef WOLFSSL_TRUST_PEER_CERT typedef struct TrustedPeerCert TrustedPeerCert; #endif /* WOLFSSL_TRUST_PEER_CERT */ +typedef struct SignatureCtx SignatureCtx; +typedef struct CertSignCtx CertSignCtx; struct DecodedCert { @@ -475,6 +536,10 @@ struct DecodedCert { byte extExtKeyUsageSet; /* Extended Key Usage */ byte extExtKeyUsage; /* Extended Key usage bitfield */ #ifdef OPENSSL_EXTRA + byte extCRLdistSet; + byte extCRLdistCrit; + byte extAuthInfoSet; + byte extAuthInfoCrit; byte extBasicConstSet; byte extBasicConstCrit; byte extSubjAltNameSet; @@ -552,12 +617,27 @@ struct DecodedCert { char extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; int extCertPoliciesNb; #endif /* WOLFSSL_CERT_EXT */ + + Signer* ca; + SignatureCtx sigCtx; +}; + + +struct WOLFSSL_ASN1_OBJECT { + void* heap; + byte* obj; + int type; /* oid */ + word32 objSz; + byte dynamic; /* if 1 then obj was dynamiclly created, 0 otherwise */ }; + extern const char* BEGIN_CERT; extern const char* END_CERT; extern const char* BEGIN_CERT_REQ; extern const char* END_CERT_REQ; +extern const char* BEGIN_DSA_PARAM; +extern const char* END_DSA_PARAM; extern const char* BEGIN_DH_PARAM; extern const char* END_DH_PARAM; extern const char* BEGIN_X509_CRL; @@ -655,11 +735,15 @@ WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*); #endif /* WOLFSSL_TRUST_PEER_CERT */ WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length); +WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx, + word32 length); WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); +WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, + word32* oidSz, int* algoID, void* heap); typedef struct tm wolfssl_tm; -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); #endif WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, @@ -717,6 +801,10 @@ WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); mp_int* r, mp_int* s); #endif +WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId); +WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); + + #ifdef WOLFSSL_CERT_GEN enum cert_enums { @@ -785,6 +873,10 @@ struct CertStatus { byte nextDate[MAX_DATE_SIZE]; byte thisDateFormat; byte nextDateFormat; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + byte* thisDateAsn; + byte* nextDateAsn; +#endif byte* rawOcspResponse; word32 rawOcspResponseSz; @@ -831,11 +923,15 @@ struct OcspRequest { byte nonce[MAX_OCSP_NONCE_SZ]; int nonceSz; void* heap; + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + void* ssl; +#endif }; WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); -WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); @@ -880,6 +976,11 @@ struct DecodedCRL { }; WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*, void* heap); +WOLFSSL_LOCAL int VerifyCRL_Signature(SignatureCtx* sigCtx, + const byte* toBeSigned, word32 tbsSz, + const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, + void* heap); WOLFSSL_LOCAL int ParseCRL(DecodedCRL*, const byte* buff, word32 sz, void* cm); WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index c9d95459d6..1fdfa61ef5 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -25,22 +25,31 @@ #define WOLF_CRYPT_ASN_PUBLIC_H #include -#ifdef HAVE_ECC - #include -#endif -#if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) - #include -#endif #ifdef __cplusplus extern "C" { #endif +/* guard on redeclaration */ +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif +#ifndef WC_RNG_TYPE_DEFINED + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + /* Certificate file Type */ enum CertType { CERT_TYPE = 0, PRIVATEKEY_TYPE, DH_PARAM_TYPE, + DSA_PARAM_TYPE, CRL_TYPE, CA_TYPE, ECC_PRIVATEKEY_TYPE, @@ -94,14 +103,8 @@ enum Ctc_Misc { #endif /* WOLFSSL_CERT_EXT */ }; -#ifdef WOLFSSL_CERT_GEN -#ifndef HAVE_ECC - typedef struct ecc_key ecc_key; -#endif -#ifdef NO_RSA - typedef struct RsaKey RsaKey; -#endif +#ifdef WOLFSSL_CERT_GEN typedef struct CertName { char country[CTC_NAME_SIZE]; @@ -157,11 +160,6 @@ typedef struct Cert { #endif void* heap; /* heap hint */ } Cert; -#endif /* WOLFSSL_CERT_GEN */ - - -#ifdef WOLFSSL_CERT_GEN - /* Initialize and Set Certificate defaults: @@ -244,7 +242,8 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); #endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */ #endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) \ + || defined(OPENSSL_EXTRA) WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outputSz, int type); WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, @@ -256,6 +255,8 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, ecc_key*, word32); WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, + word32 inLen); /* public key helper */ WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*, @@ -271,6 +272,11 @@ WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, int hashOID); WOLFSSL_API int wc_GetCTC_HashOID(int type); +WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, + word32* inOutIdx, word32 sz); +WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, + byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); + /* Time */ /* Returns seconds (Epoch/UTC) * timePtr: is "time_t", which is typically "long" diff --git a/wolfssl/wolfcrypt/coding.h b/wolfssl/wolfcrypt/coding.h index 5395cc2f4f..427f3a6cbf 100644 --- a/wolfssl/wolfcrypt/coding.h +++ b/wolfssl/wolfcrypt/coding.h @@ -61,7 +61,8 @@ WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); #endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) WOLFSSL_API int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/des3.h b/wolfssl/wolfcrypt/des3.h index db12cc9002..5eb94a1c8f 100644 --- a/wolfssl/wolfcrypt/des3.h +++ b/wolfssl/wolfcrypt/des3.h @@ -80,11 +80,15 @@ typedef struct Des3 { word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + const byte* key_raw; + const byte* iv_raw; + WC_ASYNC_DEV asyncDev; #endif + void* heap; } Des3; #endif /* HAVE_FIPS */ + WOLFSSL_API int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir); WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv); @@ -94,6 +98,12 @@ WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz); WOLFSSL_API int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz); +WOLFSSL_API int wc_Des3_EcbEncrypt(Des3* des, byte* out, + const byte* in, word32 sz); + +/* ECB decrypt same process as encrypt but with decrypt key */ +#define wc_Des_EcbDecrypt wc_Des_EcbEncrypt +#define wc_Des3_EcbDecrypt wc_Des3_EcbEncrypt WOLFSSL_API int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv,int dir); @@ -103,10 +113,10 @@ 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 WOLFSSL_ASYNC_CRYPT - WOLFSSL_API int wc_Des3AsyncInit(Des3*, int); - WOLFSSL_API void wc_Des3AsyncFree(Des3*); -#endif +/* These are only required when using either: + static memory (WOLFSSL_STATIC_MEMORY) or asynchronous (WOLFSSL_ASYNC_CRYPT) */ +WOLFSSL_API int wc_Des3Init(Des3*, void*, int); +WOLFSSL_API void wc_Des3Free(Des3*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index 6ac7be65e7..e4753e42c3 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/wolfssl/wolfcrypt/dh.h @@ -34,14 +34,44 @@ extern "C" { #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +typedef struct DhParams { + const byte* p; + word32 p_len; + const byte* g; + word32 g_len; +} DhParams; /* Diffie-Hellman Key */ typedef struct DhKey { mp_int p, g; /* group parameters */ + void* heap; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif } DhKey; -WOLFSSL_API void wc_InitDhKey(DhKey* key); +#ifdef HAVE_FFDHE_2048 +WOLFSSL_API const DhParams* wc_Dh_ffdhe2048_Get(void); +#endif +#ifdef HAVE_FFDHE_3072 +WOLFSSL_API const DhParams* wc_Dh_ffdhe3072_Get(void); +#endif +#ifdef HAVE_FFDHE_4096 +WOLFSSL_API const DhParams* wc_Dh_ffdhe4096_Get(void); +#endif +#ifdef HAVE_FFDHE_6144 +WOLFSSL_API const DhParams* wc_Dh_ffdhe6144_Get(void); +#endif +#ifdef HAVE_FFDHE_8192 +WOLFSSL_API const DhParams* wc_Dh_ffdhe8192_Get(void); +#endif + +WOLFSSL_API int wc_InitDhKey(DhKey* key); +WOLFSSL_API int wc_InitDhKey_ex(DhKey* key, void* heap, int devId); WOLFSSL_API void wc_FreeDhKey(DhKey* key); WOLFSSL_API int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, @@ -56,7 +86,7 @@ WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g word32 gSz); WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz); - +WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/dsa.h b/wolfssl/wolfcrypt/dsa.h index a8d14bbc7f..3476a556a2 100644 --- a/wolfssl/wolfcrypt/dsa.h +++ b/wolfssl/wolfcrypt/dsa.h @@ -56,8 +56,8 @@ typedef struct DsaKey { void* heap; /* memory hint */ } DsaKey; -WOLFSSL_API void wc_InitDsaKey(DsaKey* key); -WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h); +WOLFSSL_API int wc_InitDsaKey(DsaKey* key); +WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h); WOLFSSL_API void wc_FreeDsaKey(DsaKey* key); WOLFSSL_API int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng); diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 060e5f8619..df29e71681 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -36,6 +36,9 @@ #ifdef WOLFSSL_ASYNC_CRYPT #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif #endif #ifdef WOLFSSL_ATECC508A @@ -47,6 +50,53 @@ extern "C" { #endif + +/* Enable curve B parameter if needed */ +#if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE) + #ifndef USE_ECC_B_PARAM /* Allow someone to force enable */ + #define USE_ECC_B_PARAM + #endif +#endif + + +/* Use this as the key->idx if a custom ecc_set is used for key->dp */ +#define ECC_CUSTOM_IDX (-1) + + +/* Determine max ECC bits based on enabled curves */ +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define MAX_ECC_BITS 521 +#elif defined(HAVE_ECC512) + #define MAX_ECC_BITS 512 +#elif defined(HAVE_ECC384) + #define MAX_ECC_BITS 384 +#elif defined(HAVE_ECC320) + #define MAX_ECC_BITS 320 +#elif defined(HAVE_ECC239) + #define MAX_ECC_BITS 239 +#elif defined(HAVE_ECC224) + #define MAX_ECC_BITS 224 +#elif !defined(NO_ECC256) + #define MAX_ECC_BITS 256 +#elif defined(HAVE_ECC192) + #define MAX_ECC_BITS 192 +#elif defined(HAVE_ECC160) + #define MAX_ECC_BITS 160 +#elif defined(HAVE_ECC128) + #define MAX_ECC_BITS 128 +#elif defined(HAVE_ECC112) + #define MAX_ECC_BITS 112 +#endif + +/* calculate max ECC bytes */ +#if ((MAX_ECC_BITS * 2) % 8) == 0 + #define MAX_ECC_BYTES (MAX_ECC_BITS / 8) +#else + /* add byte if not aligned */ + #define MAX_ECC_BYTES ((MAX_ECC_BITS / 8) + 1) +#endif + + enum { ECC_PUBLICKEY = 1, ECC_PRIVATEKEY = 2, @@ -58,11 +108,13 @@ enum { ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ ECC_MAX_PAD_SZ = 4, /* ECC maximum padding size */ ECC_MAX_OID_LEN = 16, + ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ) }; /* Curve Types */ typedef enum ecc_curve_id { - ECC_CURVE_DEF, /* NIST or SECP */ + ECC_CURVE_INVALID = -1, + ECC_CURVE_DEF = 0, /* NIST or SECP */ /* NIST Prime Curves */ ECC_SECP192R1, @@ -98,6 +150,14 @@ typedef enum ecc_curve_id { ECC_BRAINPOOLP320R1, ECC_BRAINPOOLP384R1, ECC_BRAINPOOLP512R1, + + /* Twisted Edwards Curves */ +#ifdef HAVE_CURVE25519 + ECC_X25519, +#endif +#ifdef HAVE_X448 + ECC_X448, +#endif } ecc_curve_id; #ifdef HAVE_OID_ENCODING @@ -110,7 +170,7 @@ typedef byte ecc_oid_t; #endif /* ECC set type defined a GF(p) curve */ -typedef struct { +typedef struct ecc_set_type { int size; /* The size of the curve in octets */ int id; /* id of this curve */ const char* name; /* name of this curve */ @@ -127,37 +187,6 @@ typedef struct { } ecc_set_type; -/* Use this as the key->idx if a custom ecc_set is used for key->dp */ -#define ECC_CUSTOM_IDX (-1) - - -/* Determine max ECC bits based on enabled curves */ -#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) - #define MAX_ECC_BITS 521 -#elif defined(HAVE_ECC512) - #define MAX_ECC_BITS 512 -#elif defined(HAVE_ECC384) - #define MAX_ECC_BITS 384 -#elif defined(HAVE_ECC320) - #define MAX_ECC_BITS 320 -#elif defined(HAVE_ECC239) - #define MAX_ECC_BITS 239 -#elif defined(HAVE_ECC224) - #define MAX_ECC_BITS 224 -#elif !defined(NO_ECC256) - #define MAX_ECC_BITS 256 -#elif defined(HAVE_ECC192) - #define MAX_ECC_BITS 192 -#elif defined(HAVE_ECC160) - #define MAX_ECC_BITS 160 -#elif defined(HAVE_ECC128) - #define MAX_ECC_BITS 128 -#elif defined(HAVE_ECC112) - #define MAX_ECC_BITS 112 -#endif - - - #ifdef ALT_ECC_SIZE /* Note on ALT_ECC_SIZE: @@ -216,6 +245,7 @@ typedef struct alt_fp_int { } alt_fp_int; #endif /* ALT_ECC_SIZE */ + /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ typedef struct { @@ -231,13 +261,22 @@ typedef struct { #endif } ecc_point; +/* ECC Flags */ +enum { + WC_ECC_FLAG_NONE = 0x00, +#ifdef HAVE_ECC_CDH + WC_ECC_FLAG_COFACTOR = 0x01, +#endif +}; /* An ECC Key */ -typedef struct ecc_key { +struct ecc_key { int type; /* Public or Private */ int idx; /* Index into the ecc_sets[] for the parameters of this curve if -1, this key is using user supplied curve in dp */ + int state; + word32 flags; const ecc_set_type* dp; /* domain parameters, either points to NIST curves (idx >= 0) or user supplied */ void* heap; /* heap hint */ @@ -248,16 +287,43 @@ typedef struct ecc_key { ecc_point pubkey; /* public key */ mp_int k; /* private key */ #endif - #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + mp_int* r; /* sign/verify temps */ + mp_int* s; + WC_ASYNC_DEV asyncDev; + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +}; + +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED #endif -} ecc_key; /* ECC predefined curve sets */ extern const ecc_set_type ecc_sets[]; +WOLFSSL_API +const char* wc_ecc_get_name(int curve_id); + +#ifndef WOLFSSL_ATECC508A + +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL + #define ECC_API WOLFSSL_API +#else + #define ECC_API WOLFSSL_LOCAL +#endif + +ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit); +ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, + mp_int* a, mp_int* modulus, mp_digit mp); +ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, + mp_int* modulus, mp_digit mp); + +#endif WOLFSSL_API int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key); @@ -266,16 +332,20 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id); WOLFSSL_API int wc_ecc_check_key(ecc_key* key); +WOLFSSL_API +int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime); #ifdef HAVE_ECC_DHE WOLFSSL_API int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen); -#ifndef WOLFSSL_ATECC508A +WOLFSSL_LOCAL +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen); WOLFSSL_API -int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, byte* out, word32 *outlen); -#endif /* !WOLFSSL_ATECC508A */ +#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret_ex /* For backwards compat */ #endif /* HAVE_ECC_DHE */ #ifdef HAVE_ECC_SIGN @@ -303,10 +373,34 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); WOLFSSL_API void wc_ecc_free(ecc_key* key); WOLFSSL_API +int wc_ecc_set_flags(ecc_key* key, word32 flags); +WOLFSSL_API void wc_ecc_fp_free(void); +WOLFSSL_API +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id); + WOLFSSL_API int wc_ecc_is_valid_idx(int n); +WOLFSSL_API +int wc_ecc_get_curve_idx(int curve_id); +WOLFSSL_API +int wc_ecc_get_curve_id(int curve_idx); +#define wc_ecc_get_curve_name_from_id wc_ecc_get_name +WOLFSSL_API +int wc_ecc_get_curve_size_from_id(int curve_id); + +WOLFSSL_API +int wc_ecc_get_curve_idx_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_size_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_id_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor); #ifndef WOLFSSL_ATECC508A @@ -357,6 +451,9 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, WOLFSSL_API int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen); WOLFSSL_API +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen); +WOLFSSL_API int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, const char* d, const char* curveName); WOLFSSL_API @@ -367,6 +464,12 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, #ifdef HAVE_ECC_KEY_EXPORT WOLFSSL_API int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen); +WOLFSSL_API +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen); #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_EXPORT @@ -463,12 +566,12 @@ WOLFSSL_API int wc_X963_KDF(enum wc_HashType type, const byte* secret, byte* out, word32 outSz); #endif -#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); +#ifdef ECC_CACHE_CURVE +WOLFSSL_API int wc_ecc_curve_cache_init(void); +WOLFSSL_API void wc_ecc_curve_cache_free(void); #endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 9ebdc5d21f..df29accc41 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -153,13 +153,14 @@ enum { IS_POINT_E = -214, /* ECC is point on curve failed */ ECC_INF_E = -215, /* ECC point infinity error */ ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ + ECC_OUT_OF_RANGE_E = -217, /* ECC key component out of range */ - SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ - SRP_VERIFY_E = -218, /* SRP proof verification failed. */ - SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */ + SRP_CALL_ORDER_E = -218, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -219, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -220, /* SRP bad ephemeral values. */ - ASN_NO_SKID = -220, /* ASN no Subject Key Identifier found */ - ASN_NO_AKID = -221, /* ASN no Authority Key Identifier found */ + ASN_NO_SKID = -221, /* ASN no Subject Key Identifier found */ + ASN_NO_AKID = -222, /* ASN no Authority Key Identifier found */ ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */ SKID_E = -224, /* setting Subject Key Identifier error */ AKID_E = -225, /* setting Authority Key Identifier error */ @@ -180,7 +181,14 @@ enum { BAD_KEYWRAP_ALG_E = -239, BAD_KEYWRAP_IV_E = -240, /* Decrypted AES key wrap IV incorrect */ + WC_CLEANUP_E = -241, /* wolfcrypt cleanup failed */ + ECC_CDH_KAT_FIPS_E = -242, /* ECC CDH Known Answer Test failure */ + DH_CHECK_PUB_E = -243, /* DH Check Pub Key error */ + BAD_PATH_ERROR = -244, /* Bad path for opendir */ + ASYNC_OP_E = -245, /* Async operation error */ + + WC_LAST_E = -245, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ /* add new companion error id strings for any new error codes diff --git a/wolfssl/wolfcrypt/fe_operations.h b/wolfssl/wolfcrypt/fe_operations.h index ae15dab1f4..5bbe1b2997 100644 --- a/wolfssl/wolfcrypt/fe_operations.h +++ b/wolfssl/wolfcrypt/fe_operations.h @@ -43,6 +43,8 @@ Bounds on each t[i] vary depending on context. #ifdef CURVED25519_SMALL #define F25519_SIZE 32 typedef byte fe[32]; +#elif defined(HAVE___UINT128_T) + typedef int64_t fe[5]; #else typedef int32_t fe[10]; #endif @@ -71,9 +73,9 @@ WOLFSSL_LOCAL void fe_tobytes(unsigned char *, const fe); WOLFSSL_LOCAL void fe_sq(fe, const fe); WOLFSSL_LOCAL void fe_sq2(fe,const fe); WOLFSSL_LOCAL void fe_frombytes(fe,const unsigned char *); -WOLFSSL_LOCAL void fe_cswap(fe,fe,unsigned int); +WOLFSSL_LOCAL void fe_cswap(fe, fe, int); WOLFSSL_LOCAL void fe_mul121666(fe,fe); -WOLFSSL_LOCAL void fe_cmov(fe,const fe,unsigned int); +WOLFSSL_LOCAL void fe_cmov(fe,const fe, int); WOLFSSL_LOCAL void fe_pow22523(fe,const fe); /* 64 type needed for SHA512 */ diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index fa1883bc6d..beaeb65ea4 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -114,59 +114,32 @@ WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, #ifndef NO_MD5 #include -WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); -WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*); -#if defined(WOLFSSL_TI_HASH) - WOLFSSL_API void wc_Md5Free(Md5*); -#else - #define wc_Md5Free(d) -#endif +WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash); #endif #ifndef NO_SHA #include -WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); -WOLFSSL_API void wc_ShaRestorePos(Sha*, Sha*); WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); -#if defined(WOLFSSL_TI_HASH) - WOLFSSL_API void wc_ShaFree(Sha*); -#else - #define wc_ShaFree(d) -#endif #endif #ifndef NO_SHA256 #include -WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); -WOLFSSL_API void wc_Sha256RestorePos(Sha256*, Sha256*); WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); -#if defined(WOLFSSL_TI_HASH) - WOLFSSL_API void wc_Sha256Free(Sha256*); -#else - #define wc_Sha256Free(d) -#endif #if defined(WOLFSSL_SHA224) - WOLFSSL_API int wc_Sha224GetHash(Sha224*, byte*); WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*); - #define wc_Sha224Free(d) #endif /* defined(WOLFSSL_SHA224) */ #endif #ifdef WOLFSSL_SHA512 #include -WOLFSSL_API int wc_Sha512GetHash(Sha512*, byte*); WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); -#define wc_Sha512Free(d) #if defined(WOLFSSL_SHA384) - WOLFSSL_API int wc_Sha384GetHash(Sha384*, byte*); WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); - #define wc_Sha384Free(d) #endif /* defined(WOLFSSL_SHA384) */ #endif /* WOLFSSL_SHA512 */ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/hmac.h b/wolfssl/wolfcrypt/hmac.h index 1d49306641..9501b84b6f 100644 --- a/wolfssl/wolfcrypt/hmac.h +++ b/wolfssl/wolfcrypt/hmac.h @@ -58,7 +58,7 @@ extern "C" { #endif #ifndef HAVE_FIPS - + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif @@ -95,7 +95,7 @@ enum { /* Select the largest available hash for the buffer size. */ #if defined(WOLFSSL_SHA512) MAX_DIGEST_SIZE = SHA512_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA512_BLOCK_SIZE + HMAC_BLOCK_SIZE = SHA512_BLOCK_SIZE, #elif defined(HAVE_BLAKE2) MAX_DIGEST_SIZE = BLAKE2B_OUTBYTES, HMAC_BLOCK_SIZE = BLAKE2B_BLOCKBYTES, @@ -110,10 +110,10 @@ enum { HMAC_BLOCK_SIZE = SHA224_BLOCK_SIZE #elif !defined(NO_SHA) MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, - HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE + HMAC_BLOCK_SIZE = SHA_BLOCK_SIZE, #elif !defined(NO_MD5) MAX_DIGEST_SIZE = MD5_DIGEST_SIZE, - HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE + HMAC_BLOCK_SIZE = MD5_BLOCK_SIZE, #else #error "You have to have some kind of hash if you want to use HMAC." #endif @@ -122,27 +122,27 @@ enum { /* hash union */ typedef union { - #ifndef NO_MD5 - Md5 md5; - #endif - #ifndef NO_SHA - Sha sha; - #endif - #ifdef WOLFSSL_SHA224 - Sha224 sha224; - #endif - #ifndef NO_SHA256 - Sha256 sha256; - #endif - #ifdef WOLFSSL_SHA384 - Sha384 sha384; - #endif - #ifdef WOLFSSL_SHA512 - Sha512 sha512; - #endif - #ifdef HAVE_BLAKE2 - Blake2b blake2b; - #endif +#ifndef NO_MD5 + Md5 md5; +#endif +#ifndef NO_SHA + Sha sha; +#endif +#ifdef WOLFSSL_SHA224 + Sha224 sha224; +#endif +#ifndef NO_SHA256 + Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA512 +#ifdef WOLFSSL_SHA384 + Sha384 sha384; +#endif + Sha512 sha512; +#endif +#ifdef HAVE_BLAKE2 + Blake2b blake2b; +#endif } Hash; /* Hmac digest */ @@ -154,13 +154,14 @@ typedef struct Hmac { void* heap; /* heap hint */ byte macType; /* md5 sha or sha256 */ byte innerHashKeyed; /* keyed flag */ + #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; + byte keyRaw[HMAC_BLOCK_SIZE]; + word16 keyLen; /* hmac key length */ #ifdef HAVE_CAVIUM - word16 keyLen; /* hmac key length */ - word16 dataLen; - HashType type; /* hmac key type */ byte* data; /* buffered input data for one call */ + word16 dataLen; #endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_ASYNC_CRYPT */ } Hmac; @@ -172,18 +173,20 @@ 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*); 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 wc_HmacInit(Hmac* hmac, void* heap, int devId); +WOLFSSL_API void wc_HmacFree(Hmac*); WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); - #ifdef HAVE_HKDF +WOLFSSL_API int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out); +WOLFSSL_API int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, + byte* out, word32 outSz); + WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 7c9c0fb7fd..92307a2b80 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -58,7 +58,8 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/mpi_superclass.h \ wolfssl/wolfcrypt/mem_track.h \ wolfssl/wolfcrypt/wolfevent.h \ - wolfssl/wolfcrypt/pkcs12.h + wolfssl/wolfcrypt/pkcs12.h \ + wolfssl/wolfcrypt/wolfmath.h noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ @@ -68,6 +69,16 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ wolfssl/wolfcrypt/port/atmel/atmel.h +if BUILD_ASYNCCRYPT +nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h +endif + if BUILD_CAVIUM -noinst_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h endif + +if BUILD_INTEL_QA +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist_mem.h +endif + diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index c965330ea6..9c7bc01b04 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -37,7 +37,7 @@ #include #else -#include +#include #ifndef CHAR_BIT #include @@ -45,6 +45,16 @@ #include +/* wolf big int and common functions */ +#include + + +#ifdef WOLFSSL_PUBLIC_MP + #define MP_API WOLFSSL_API +#else + #define MP_API +#endif + #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif @@ -64,7 +74,7 @@ extern "C" { /* C on the other hand doesn't care */ #define OPT_CAST(x) -#endif +#endif /* __cplusplus */ /* detect 64-bit mode if possible */ @@ -96,7 +106,7 @@ extern "C" { #elif defined(MP_16BIT) || defined(NO_64BIT) typedef unsigned short mp_digit; typedef unsigned int mp_word; - #define DIGIT_BIT 12 + #define DIGIT_BIT 12 #elif defined(MP_64BIT) /* for GCC only on supported platforms */ typedef unsigned long long mp_digit; /* 64 bit type, 128 uses mode(TI) */ @@ -178,14 +188,20 @@ typedef int mp_err; BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) -/* the infamous mp_int structure */ -typedef struct { +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT; +#endif + +/* the mp_int structure */ +typedef struct mp_int { int used, alloc, sign; mp_digit *dp; -#ifdef WOLFSSL_ASYNC_CRYPT - byte* dpraw; /* Used for hardware crypto */ + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ #endif } mp_int; +#define MP_INT_DEFINED /* callback for mp_prime_random, should fill dst with random bytes and return how many read [up to len] */ @@ -234,113 +250,121 @@ typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); extern const char *mp_s_rmap; /* 6 functions needed by Rsa */ -int mp_init (mp_int * a); -void mp_clear (mp_int * a); -void mp_forcezero(mp_int * a); -int mp_unsigned_bin_size(mp_int * a); -int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); -int mp_to_unsigned_bin (mp_int * a, unsigned char *b); -int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); +MP_API int mp_init (mp_int * a); +MP_API void mp_clear (mp_int * a); +MP_API void mp_free (mp_int * a); +MP_API void mp_forcezero(mp_int * a); +MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); +MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +MP_API int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); /* end functions needed by Rsa */ /* functions added to support above needed, removed TOOM and KARATSUBA */ -int mp_count_bits (mp_int * a); -int mp_leading_bit (mp_int * a); -int mp_init_copy (mp_int * a, mp_int * b); -int mp_copy (mp_int * a, mp_int * b); -int mp_grow (mp_int * a, int size); -int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); -void mp_zero (mp_int * a); -void mp_clamp (mp_int * a); -void mp_exch (mp_int * a, mp_int * b); -void mp_rshd (mp_int * a, int b); -void mp_rshb (mp_int * a, int b); -int mp_mod_2d (mp_int * a, int b, mp_int * c); -int mp_mul_2d (mp_int * a, int b, mp_int * c); -int mp_lshd (mp_int * a, int b); -int mp_abs (mp_int * a, mp_int * b); -int mp_invmod (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_count_bits (mp_int * a); +MP_API int mp_leading_bit (mp_int * a); +MP_API int mp_init_copy (mp_int * a, mp_int * b); +MP_API int mp_copy (mp_int * a, mp_int * b); +MP_API int mp_grow (mp_int * a, int size); +MP_API int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); +MP_API void mp_zero (mp_int * a); +MP_API void mp_clamp (mp_int * a); +MP_API void mp_exch (mp_int * a, mp_int * b); +MP_API void mp_rshd (mp_int * a, int b); +MP_API void mp_rshb (mp_int * a, int b); +MP_API int mp_mod_2d (mp_int * a, int b, mp_int * c); +MP_API int mp_mul_2d (mp_int * a, int b, mp_int * c); +MP_API int mp_lshd (mp_int * a, int b); +MP_API int mp_abs (mp_int * a, mp_int * b); +MP_API int mp_invmod (mp_int * a, mp_int * b, mp_int * c); int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c); -int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); -int mp_cmp_mag (mp_int * a, mp_int * b); -int mp_cmp (mp_int * a, mp_int * b); -int mp_cmp_d(mp_int * a, mp_digit b); -void mp_set (mp_int * a, mp_digit b); -int mp_is_bit_set (mp_int * a, mp_digit b); -int mp_mod (mp_int * a, mp_int * b, mp_int * c); -int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_div_2(mp_int * a, mp_int * b); -int mp_add (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_cmp_mag (mp_int * a, mp_int * b); +MP_API int mp_cmp (mp_int * a, mp_int * b); +MP_API int mp_cmp_d(mp_int * a, mp_digit b); +MP_API int mp_set (mp_int * a, mp_digit b); +MP_API int mp_is_bit_set (mp_int * a, mp_digit b); +MP_API int mp_mod (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_div_2(mp_int * a, mp_int * b); +MP_API int mp_add (mp_int * a, mp_int * b, mp_int * c); int s_mp_add (mp_int * a, mp_int * b, mp_int * c); int s_mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_reduce_is_2k_l(mp_int *a); -int mp_reduce_is_2k(mp_int *a); -int mp_dr_is_modulus(mp_int *a); -int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int); -int mp_montgomery_setup (mp_int * n, mp_digit * rho); +MP_API int mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_reduce_is_2k_l(mp_int *a); +MP_API int mp_reduce_is_2k(mp_int *a); +MP_API int mp_dr_is_modulus(mp_int *a); +MP_API int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, + int); +MP_API int mp_montgomery_setup (mp_int * n, mp_digit * rho); int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); -int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); -void mp_dr_setup(mp_int *a, mp_digit *d); -int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k); -int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); +MP_API int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +MP_API void mp_dr_setup(mp_int *a, mp_digit *d); +MP_API int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k); +MP_API int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs); int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs); -int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); -int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); -int mp_reduce (mp_int * x, mp_int * m, mp_int * mu); -int mp_reduce_setup (mp_int * a, mp_int * b); +MP_API int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); +MP_API int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); +MP_API int mp_reduce (mp_int * x, mp_int * m, mp_int * mu); +MP_API int mp_reduce_setup (mp_int * a, mp_int * b); int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); -int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); +MP_API int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); int s_mp_sqr (mp_int * a, mp_int * b); int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); int fast_s_mp_sqr (mp_int * a, mp_int * b); -int mp_init_size (mp_int * a, int size); -int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d); -int mp_mul_2(mp_int * a, mp_int * b); -int mp_mul (mp_int * a, mp_int * b, mp_int * c); -int mp_sqr (mp_int * a, mp_int * b); -int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); -int mp_2expt (mp_int * a, int b); -int mp_set_bit (mp_int * a, int b); -int mp_reduce_2k_setup(mp_int *a, mp_digit *d); -int mp_add_d (mp_int* a, mp_digit b, mp_int* c); -int mp_set_int (mp_int * a, unsigned long b); -int mp_sub_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_init_size (mp_int * a, int size); +MP_API int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d); +MP_API int mp_mul_2(mp_int * a, mp_int * b); +MP_API int mp_mul (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sqr (mp_int * a, mp_int * b); +MP_API int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_2expt (mp_int * a, int b); +MP_API int mp_set_bit (mp_int * a, int b); +MP_API int mp_reduce_2k_setup(mp_int *a, mp_digit *d); +MP_API int mp_add_d (mp_int* a, mp_digit b, mp_int* c); +MP_API int mp_set_int (mp_int * a, unsigned long b); +MP_API int mp_sub_d (mp_int * a, mp_digit b, mp_int * c); /* end support added functions */ /* added */ -int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, - mp_int* f); -int mp_toradix (mp_int *a, char *str, int radix); -int mp_radix_size (mp_int * a, int radix, int *size); +MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); +MP_API int mp_toradix (mp_int *a, char *str, int radix); +MP_API int mp_radix_size (mp_int * a, int radix, int *size); #ifdef WOLFSSL_DEBUG_MATH - void mp_dump(const char* desc, mp_int* a, byte verbose); + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); #else #define mp_dump(desc, a, verbose) #endif #if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); #endif #if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_read_radix(mp_int* a, const char* str, int radix); + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); #endif #ifdef WOLFSSL_KEY_GEN - int mp_prime_is_prime (mp_int * a, int t, int *result); - int mp_gcd (mp_int * a, mp_int * b, mp_int * c); - int mp_lcm (mp_int * a, mp_int * b, mp_int * c); - int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); + MP_API int mp_prime_is_prime (mp_int * a, int t, int *result); + MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c); + MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c); + MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); #endif -int mp_cnt_lsb(mp_int *a); -int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c); +MP_API int mp_cnt_lsb(mp_int *a); +MP_API int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c); + + +/* wolf big int and common functions */ +#include + #ifdef __cplusplus } diff --git a/wolfssl/wolfcrypt/logging.h b/wolfssl/wolfcrypt/logging.h old mode 100644 new mode 100755 index 29bf0abea8..4b3f4f72fd --- a/wolfssl/wolfcrypt/logging.h +++ b/wolfssl/wolfcrypt/logging.h @@ -46,7 +46,30 @@ typedef void (*wolfSSL_Logging_cb)(const int logLevel, WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_LOCAL int wc_LoggingInit(void); + WOLFSSL_LOCAL int wc_LoggingCleanup(void); + WOLFSSL_LOCAL int wc_AddErrorNode(int error, int line, char* buf, + char* file); + WOLFSSL_LOCAL int wc_PeekErrorNode(int index, const char **file, + const char **reason, int *line); + WOLFSSL_LOCAL void wc_RemoveErrorNode(int index); + WOLFSSL_LOCAL void wc_ClearErrorNodes(void); + WOLFSSL_API int wc_SetLoggingHeap(void* h); + #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + WOLFSSL_API void wc_ERR_print_errors_fp(FILE* fp); + #endif +#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */ + #ifdef DEBUG_WOLFSSL + #if defined(_WIN32) + #if defined(INTIME_RTOS) + #define __func__ NULL + #else + #define __func__ __FUNCTION__ + #endif + #endif + /* a is prepended to m and b is appended, creating a log msg a + m + b */ #define WOLFSSL_LOG_CAT(a, m, b) #a " " m " " #b @@ -55,9 +78,8 @@ WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); #define WOLFSSL_STUB(m) \ WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) - void WOLFSSL_ERROR(int); void WOLFSSL_MSG(const char* msg); - void WOLFSSL_BUFFER(byte* buffer, word32 length); + void WOLFSSL_BUFFER(const byte* buffer, word32 length); #else /* DEBUG_WOLFSSL */ @@ -65,12 +87,23 @@ WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); #define WOLFSSL_LEAVE(m, r) #define WOLFSSL_STUB(m) - #define WOLFSSL_ERROR(e) #define WOLFSSL_MSG(m) #define WOLFSSL_BUFFER(b, l) #endif /* DEBUG_WOLFSSL */ +#if (defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY) + #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) + void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line, + const char* file, void* ctx); + #define WOLFSSL_ERROR(x) WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__,NULL) + #else + void WOLFSSL_ERROR(int); + #endif +#else + #define WOLFSSL_ERROR(e) +#endif + #ifdef __cplusplus } #endif diff --git a/wolfssl/wolfcrypt/md5.h b/wolfssl/wolfcrypt/md5.h index 17783b1734..27c690e4f2 100644 --- a/wolfssl/wolfcrypt/md5.h +++ b/wolfssl/wolfcrypt/md5.h @@ -50,10 +50,15 @@ enum { }; #if defined(WOLFSSL_PIC32MZ_HASH) -#include "port/pic32/pic32mz-crypt.h" + #include "port/pic32/pic32mz-crypt.h" +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include #endif -#ifndef WOLFSSL_TI_HASH +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#else /* MD5 digest */ typedef struct Md5 { @@ -61,22 +66,29 @@ typedef struct Md5 { word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ word32 buffer[MD5_BLOCK_SIZE / sizeof(word32)]; - #if !defined(WOLFSSL_PIC32MZ_HASH) +#if !defined(WOLFSSL_PIC32MZ_HASH) word32 digest[MD5_DIGEST_SIZE / sizeof(word32)]; - #else +#else word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc ; /* Crypt Engine descriptor */ - #endif + pic32mz_desc desc; /* Crypt Engine descriptor */ +#endif + void* heap; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ } Md5; -#else /* WOLFSSL_TI_HASH */ - #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif +#endif /* WOLFSSL_TI_HASH */ + +WOLFSSL_API int wc_InitMd5(Md5*); +WOLFSSL_API int wc_InitMd5_ex(Md5*, void*, int); +WOLFSSL_API int wc_Md5Update(Md5*, const byte*, word32); +WOLFSSL_API int wc_Md5Final(Md5*, byte*); +WOLFSSL_API void wc_Md5Free(Md5*); + +WOLFSSL_API int wc_Md5GetHash(Md5*, byte*); +WOLFSSL_API int wc_Md5Copy(Md5*, Md5*); -WOLFSSL_API void wc_InitMd5(Md5*); -WOLFSSL_API void wc_Md5Update(Md5*, const byte*, word32); -WOLFSSL_API void wc_Md5Final(Md5*, byte*); -WOLFSSL_API int wc_Md5Hash(const byte*, word32, byte*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index beb280b3e0..ee916d8bc2 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -34,7 +34,7 @@ * * On startup call: * InitMemoryTracker(); - * + * * When ready to dump the memory report call: * ShowMemoryTracker(); * @@ -64,6 +64,7 @@ typedef struct memoryStats { size_t totalAllocs; /* number of allocations */ + size_t totalDeallocs; /* number of deallocations */ size_t totalBytes; /* total number of bytes allocated */ size_t peakBytes; /* concurrent max bytes */ size_t currentBytes; /* total current bytes in use */ @@ -149,6 +150,7 @@ #ifdef DO_MEM_STATS ourMemStats.currentBytes -= mt->u.hint.thisSize; + ourMemStats.totalDeallocs++; #endif #ifdef WOLFSSL_DEBUG_MEMORY @@ -194,6 +196,7 @@ return ret; } +#ifdef WOLFSSL_TRACK_MEMORY STATIC INLINE int InitMemoryTracker(void) { int ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc); @@ -204,6 +207,7 @@ #ifdef DO_MEM_STATS ourMemStats.totalAllocs = 0; + ourMemStats.totalDeallocs = 0; ourMemStats.totalBytes = 0; ourMemStats.peakBytes = 0; ourMemStats.currentBytes = 0; @@ -217,6 +221,8 @@ #ifdef DO_MEM_STATS printf("total Allocs = %9lu\n", (unsigned long)ourMemStats.totalAllocs); + printf("total Deallocs = %9lu\n", + (unsigned long)ourMemStats.totalDeallocs); printf("total Bytes = %9lu\n", (unsigned long)ourMemStats.totalBytes); printf("peak Bytes = %9lu\n", @@ -225,6 +231,7 @@ (unsigned long)ourMemStats.currentBytes); #endif } +#endif #endif /* USE_WOLFSSL_MEMORY */ diff --git a/wolfssl/wolfcrypt/memory.h b/wolfssl/wolfcrypt/memory.h index 96dce8bdd6..9ecd9cd927 100644 --- a/wolfssl/wolfcrypt/memory.h +++ b/wolfssl/wolfcrypt/memory.h @@ -70,10 +70,14 @@ #endif /* WOLFSSL_DEBUG_MEMORY */ #endif /* WOLFSSL_STATIC_MEMORY */ -/* Public set function */ -WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, - wolfSSL_Free_cb free_function, - wolfSSL_Realloc_cb realloc_function); +/* Public get/set functions */ +WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb, + wolfSSL_Free_cb, + wolfSSL_Realloc_cb); + +WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*, + wolfSSL_Free_cb*, + wolfSSL_Realloc_cb*); #ifdef WOLFSSL_STATIC_MEMORY #define WOLFSSL_STATIC_TIMEOUT 1 @@ -95,7 +99,7 @@ WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb malloc_function, #endif #endif #ifndef WOLFMEM_DIST - #define WOLFMEM_DIST 8,4,4,12,4,5,2,1,1 + #define WOLFMEM_DIST 8,4,4,12,4,5,8,1,1 #endif /* flags for loading static memory (one hot bit) */ diff --git a/wolfssl/wolfcrypt/misc.h b/wolfssl/wolfcrypt/misc.h index 959b2d87f2..ed64159c8b 100644 --- a/wolfssl/wolfcrypt/misc.h +++ b/wolfssl/wolfcrypt/misc.h @@ -67,6 +67,21 @@ WOLFSSL_LOCAL void ByteReverseWords64(word64*, const word64*, word32); #endif /* WORD64_AVAILABLE */ +#ifndef WOLFSSL_HAVE_MIN + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ + #define min min + #endif + WOLFSSL_LOCAL word32 min(word32 a, word32 b); +#endif + +#ifndef WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + WOLFSSL_LOCAL word32 max(word32 a, word32 b); +#endif /* WOLFSSL_HAVE_MAX */ + + #endif /* NO_INLINE */ diff --git a/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h b/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h deleted file mode 100644 index aed338f406..0000000000 --- a/wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +++ /dev/null @@ -1,165 +0,0 @@ -/* 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/port/nxp/ksdk_port.h b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h index 5b2673a45c..9139510734 100644 --- a/wolfssl/wolfcrypt/port/nxp/ksdk_port.h +++ b/wolfssl/wolfcrypt/port/nxp/ksdk_port.h @@ -23,7 +23,11 @@ #define _KSDK_PORT_H_ #include -#include +#ifdef USE_FAST_MATH + #include +#else + #include +#endif #include #include #include @@ -34,13 +38,12 @@ int ksdk_port_init(void); /* software algorithm, by wolfcrypt */ #if defined(FREESCALE_LTC_TFM) - void wolfcrypt_fp_mul(fp_int *A, fp_int *B, fp_int *C); - int wolfcrypt_fp_mod(fp_int *a, fp_int *b, fp_int *c); - int wolfcrypt_fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); - int wolfcrypt_fp_mod(fp_int *a, fp_int *b, fp_int *c); - int wolfcrypt_fp_invmod(fp_int *a, fp_int *b, fp_int *c); - int _wolfcrypt_fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y); - int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y); + int wolfcrypt_mp_mul(mp_int *A, mp_int *B, mp_int *C); + int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + int wolfcrypt_mp_mod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_invmod(mp_int *a, mp_int *b, mp_int *c); + int wolfcrypt_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y); #endif /* FREESCALE_LTC_TFM */ #if defined(FREESCALE_LTC_ECC) diff --git a/wolfssl/wolfcrypt/port/ti/ti-hash.h b/wolfssl/wolfcrypt/port/ti/ti-hash.h index c63a2ce20f..93311a4e24 100644 --- a/wolfssl/wolfcrypt/port/ti/ti-hash.h +++ b/wolfssl/wolfcrypt/port/ti/ti-hash.h @@ -19,47 +19,43 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ - + #ifndef WOLF_CRYPT_TI_HASH_H #define WOLF_CRYPT_TI_HASH_H #include #ifndef WOLFSSL_TI_INITBUFF -#define WOLFSSL_TI_INITBUFF 64 + #define WOLFSSL_TI_INITBUFF 64 #endif -#define WOLFSSL_MAX_HASH_SIZE 64 +#ifndef WOLFSSL_MAX_HASH_SIZE + #define WOLFSSL_MAX_HASH_SIZE 64 +#endif typedef struct { - byte *msg ; - word32 used ; - word32 len ; - byte hash[WOLFSSL_MAX_HASH_SIZE] ; -} wolfssl_TI_Hash ; + byte *msg; + word32 used; + word32 len; + byte hash[WOLFSSL_MAX_HASH_SIZE]; +} wolfssl_TI_Hash; #ifndef TI_HASH_TEST -#if !defined(NO_MD5) -typedef wolfssl_TI_Hash Md5 ; +#if !defined(NO_MD5) + typedef wolfssl_TI_Hash Md5; #endif #if !defined(NO_SHA) -typedef wolfssl_TI_Hash Sha ; + typedef wolfssl_TI_Hash Sha; #endif #if !defined(NO_SHA256) -typedef wolfssl_TI_Hash Sha256 ; + typedef wolfssl_TI_Hash Sha256; +#endif +#if defined(WOLFSSL_SHA224) + typedef wolfssl_TI_Hash Sha224; #endif -#if defined(HAVE_SHA224) -typedef wolfssl_TI_Hash Sha224 ; -#define SHA224_DIGEST_SIZE 28 - -WOLFSSL_API int wc_InitSha224(Sha224* sha224) ; -WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) ; -WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) ; -WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) ; +#endif /* !TI_HASH_TEST */ -#endif -#endif #endif /* WOLF_CRYPT_TI_HASH_H */ diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 1669a6e267..6a6f104e54 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -35,44 +35,71 @@ extern "C" { #endif -/* Maximum generate block length */ -#define RNG_MAX_BLOCK_LEN (0x10000) + /* Maximum generate block length */ +#ifndef RNG_MAX_BLOCK_LEN + #define RNG_MAX_BLOCK_LEN (0x10000) +#endif -#ifndef HAVE_FIPS /* avoid redefining structs and macros */ +/* Size of the BRBG seed */ +#ifndef DRBG_SEED_LEN + #define DRBG_SEED_LEN (440/8) +#endif -#if defined(WOLFSSL_FORCE_RC4_DRBG) && defined(NO_RC4) - #error Cannot have WOLFSSL_FORCE_RC4_DRBG and NO_RC4 defined. -#endif /* WOLFSSL_FORCE_RC4_DRBG && NO_RC4 */ +#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) + /* To maintain compatibility the default is byte */ + #define CUSTOM_RAND_TYPE byte +#endif + +/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined + or CUSTOM_RAND_GENERATE_BLOCK is defined*/ +#if !defined(WC_NO_HASHDRBG) || !defined(CUSTOM_RAND_GENERATE_BLOCK) + #undef HAVE_HASHDRBG + #define HAVE_HASHDRBG +#endif + + +#ifndef HAVE_FIPS /* avoid redefining structs and macros */ /* RNG supports the following sources (in order): * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and - * bypasses the P-RNG. - * 2. HAVE_HASHDRBG && !NO_SHA256 (SHA256 enabled): Uses SHA256 based P-RNG + * bypasses the options below. + * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU. + * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG * seeded via wc_GenerateSeed. This is the default source. - * 3. !NO_RC4 (RC4 enabled): Uses RC4 */ + /* Seed source can be overriden by defining one of these: + CUSTOM_RAND_GENERATE_SEED + CUSTOM_RAND_GENERATE_SEED_OS + CUSTOM_RAND_GENERATE */ + + #if defined(CUSTOM_RAND_GENERATE_BLOCK) /* To use define the following: * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc * extern int myRngFunc(byte* output, word32 sz); */ -#elif (defined(HAVE_HASHDRBG) || defined(NO_RC4)) +#elif defined(HAVE_HASHDRBG) #ifdef NO_SHA256 #error "Hash DRBG requires SHA-256." #endif /* NO_SHA256 */ - #include +#elif defined(HAVE_WNR) + /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ #else - #include + #error No RNG source defined! #endif - #ifdef HAVE_WNR #include #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + + #if defined(USE_WINDOWS_API) #if defined(_WIN64) typedef unsigned __int64 ProviderHandle; @@ -98,46 +125,26 @@ typedef struct OS_Seed { #define WC_RNG_TYPE_DEFINED #endif -#if (defined(HAVE_HASHDRBG) || defined(NO_RC4)) && !defined(CUSTOM_RAND_GENERATE_BLOCK) - -#define DRBG_SEED_LEN (440/8) - - -struct DRBG; /* Private DRBG state */ - +#ifdef HAVE_HASHDRBG + /* Private DRBG state */ + struct DRBG; +#endif -/* Hash-based Deterministic Random Bit Generator */ +/* RNG context */ struct WC_RNG { - struct DRBG* drbg; OS_Seed seed; void* heap; +#ifdef HAVE_HASHDRBG + /* Hash-based Deterministic Random Bit Generator */ + struct DRBG* drbg; byte status; -}; - - - -#else /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ - -#ifdef WOLFSSL_ASYNC_CRYPT - #include -#endif - -/* secure Random Number Generator */ - - -struct WC_RNG { - OS_Seed seed; -#ifndef NO_RC4 - Arc4 cipher; #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; + int devId; #endif }; - - -#endif /* (HAVE_HASHDRBG || NO_RC4) && !CUSTOM_RAND_GENERATE_BLOCK */ #endif /* HAVE_FIPS */ /* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, @@ -146,6 +153,7 @@ struct WC_RNG { #define RNG WC_RNG #endif + WOLFSSL_LOCAL int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); @@ -158,18 +166,18 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); WOLFSSL_API int wc_InitRng(WC_RNG*); -WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap); +WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId); WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz); WOLFSSL_API int wc_RNG_GenerateByte(WC_RNG*, byte*); WOLFSSL_API int wc_FreeRng(WC_RNG*); -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG WOLFSSL_API int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, byte* output, word32 outputSz); -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/ripemd.h b/wolfssl/wolfcrypt/ripemd.h index 5845d594c2..65897abaa7 100644 --- a/wolfssl/wolfcrypt/ripemd.h +++ b/wolfssl/wolfcrypt/ripemd.h @@ -51,9 +51,9 @@ typedef struct RipeMd { } RipeMd; -WOLFSSL_API void wc_InitRipeMd(RipeMd*); -WOLFSSL_API void wc_RipeMdUpdate(RipeMd*, const byte*, word32); -WOLFSSL_API void wc_RipeMdFinal(RipeMd*, byte*); +WOLFSSL_API int wc_InitRipeMd(RipeMd*); +WOLFSSL_API int wc_RipeMdUpdate(RipeMd*, const byte*, word32); +WOLFSSL_API int wc_RipeMdFinal(RipeMd*, byte*); #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index d7f5ccaf9c..6905d1dd24 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -55,6 +55,9 @@ #ifdef WOLFSSL_ASYNC_CRYPT #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif #endif enum { @@ -78,21 +81,30 @@ enum { /* RSA */ -typedef struct RsaKey { +struct RsaKey { mp_int n, e, d, p, q, dP, dQ, u; - int type; /* public or private */ void* heap; /* for user memory overrides */ + byte* data; /* temp buffer for async RSA */ + int type; /* public or private */ int state; - byte* tmp; /* temp buffer for async RSA */ - word32 tmpLen; - byte tmpIsAlloc; + word32 dataLen; #ifdef WC_RSA_BLINDING WC_RNG* rng; /* for PrivateDecrypt blinding */ #endif #ifdef WOLFSSL_ASYNC_CRYPT - AsyncCryptDev asyncDev; + WC_ASYNC_DEV asyncDev; + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif #endif /* WOLFSSL_ASYNC_CRYPT */ -} RsaKey; + byte dataIsAlloc; +}; + +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif + #endif /*HAVE_FIPS */ WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); @@ -114,6 +126,9 @@ WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key); WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, + RsaKey* key); WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); #ifndef HAVE_FIPS /* to avoid asn duplicate symbols @wc_fips */ @@ -144,6 +159,7 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); /* Padding types */ #define WC_RSA_PKCSV15_PAD 0 #define WC_RSA_OAEP_PAD 1 +#define WC_RSA_PSS_PAD 2 WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key, WC_RNG* rng, int type, @@ -163,11 +179,6 @@ 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 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 diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 734e756e6e..40188b9353 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -367,7 +367,7 @@ #define USE_CERT_BUFFERS_2048 /* uTasker port uses RAW sockets, use I/O callbacks - * See wolfSSL uTasker example for sample callbacks */ + * See wolfSSL uTasker example for sample callbacks */ #define WOLFSSL_USER_IO /* uTasker filesystem not ported */ @@ -421,26 +421,26 @@ #endif #ifdef WOLFSSL_NRF5x - #define SIZEOF_LONG 4 - #define SIZEOF_LONG_LONG 8 - #define NO_ASN_TIME - #define NO_DEV_RANDOM - #define NO_FILESYSTEM - #define NO_MAIN_DRIVER - #define NO_WRITEV - #define SINGLE_THREADED - #define USE_FAST_MATH - #define TFM_TIMING_RESISTANT - #define USE_WOLFSSL_MEMORY - #define WOLFSSL_NRF51 - #define WOLFSSL_USER_IO - #define NO_SESSION_CACHE + #define SIZEOF_LONG 4 + #define SIZEOF_LONG_LONG 8 + #define NO_ASN_TIME + #define NO_DEV_RANDOM + #define NO_FILESYSTEM + #define NO_MAIN_DRIVER + #define NO_WRITEV + #define SINGLE_THREADED + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define USE_WOLFSSL_MEMORY + #define WOLFSSL_NRF51 + #define WOLFSSL_USER_IO + #define NO_SESSION_CACHE #endif /* Micrium will use Visual Studio for compilation but not the Win32 API */ #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ - !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \ - !defined(WOLFSSL_UTASKER) + !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_EROAD) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif @@ -460,36 +460,38 @@ extern void uITRON4_free(void *p) ; #endif #if defined(WOLFSSL_uTKERNEL2) -#define WOLFSSL_CLOSESOCKET -#define XMALLOC_USER -int uTKernel_init_mpool(unsigned int sz) ; /* initializing malloc pool */ -void *uTKernel_malloc(unsigned int sz) ; -void *uTKernel_realloc(void *p, unsigned int sz) ; -void uTKernel_free(void *p) ; -#define XMALLOC(s, h, type) uTKernel_malloc((s)) -#define XREALLOC(p, n, h, t) uTKernel_realloc((p), (n)) -#define XFREE(p, h, type) uTKernel_free((p)) - -#include -#include "tm/tmonitor.h" -static char *fgets(char *buff, int sz, FILE *fp) -/*static char * gets(char *buff)*/ -{ - char * p = buff ; - *p = '\0' ; - while(1) { - *p = tm_getchar(-1) ; - tm_putchar(*p) ; - if(*p == '\r') { - tm_putchar('\n') ; - *p = '\0' ; - break ; + #ifndef NO_TKERNEL_MEM_POOL + #define XMALLOC_OVERRIDE + int uTKernel_init_mpool(unsigned int sz); /* initializing malloc pool */ + void* uTKernel_malloc(unsigned int sz); + void* uTKernel_realloc(void *p, unsigned int sz); + void uTKernel_free(void *p); + #define XMALLOC(s, h, type) uTKernel_malloc((s)) + #define XREALLOC(p, n, h, t) uTKernel_realloc((p), (n)) + #define XFREE(p, h, type) uTKernel_free((p)) + #endif + + #ifndef NO_STDIO_FGETS_REMAP + #include + #include "tm/tmonitor.h" + + /* static char* gets(char *buff); */ + static char* fgets(char *buff, int sz, FILE *fp) { + char * p = buff; + *p = '\0'; + while (1) { + *p = tm_getchar(-1); + tm_putchar(*p); + if (*p == '\r') { + tm_putchar('\n'); + *p = '\0'; + break; + } + p++; } - p ++ ; + return buff; } - return buff ; -} - + #endif /* !NO_STDIO_FGETS_REMAP */ #endif @@ -555,7 +557,6 @@ static char *fgets(char *buff, int sz, FILE *fp) #define NO_WOLFSSL_DIR #define NO_WRITEV -#define WOLFSSL_HAVE_MIN #define USE_FAST_MATH #define TFM_TIMING_RESISTANT #define NO_MAIN_DRIVER @@ -731,12 +732,12 @@ static char *fgets(char *buff, int sz, FILE *fp) /* WOLFSSL_DH_CONST */ #define NO_FILESYSTEM #define WOLFSSL_CRYPT_HW_MUTEX 1 - + #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) #define XMALLOC(s, h, type) pvPortMalloc((s)) #define XFREE(p, h, type) vPortFree((p)) #endif - + //#define USER_TICKS /* Allows use of DH with fixed points if uncommented and NO_DH is removed */ /* WOLFSSL_DH_CONST */ @@ -758,7 +759,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #define WOLFSSL_USER_IO #define SINGLE_THREADED #define NO_FILESYSTEM - #define USER_TICKS + #ifndef TIME_OVERRIDES + #define USER_TICKS + #endif #endif /* FREESCALE_KSDK_BM */ #ifdef FREESCALE_COMMON @@ -799,14 +802,24 @@ static char *fgets(char *buff, int sz, FILE *fp) #define WOLFSSL_AES_DIRECT #endif - #include "fsl_common.h" + #ifdef FREESCALE_KSDK_1_3 + #include "fsl_device_registers.h" + #else + #include "fsl_common.h" + #endif /* random seed */ #define NO_OLD_RNGNAME #if defined(FSL_FEATURE_SOC_TRNG_COUNT) && (FSL_FEATURE_SOC_TRNG_COUNT > 0) #define FREESCALE_KSDK_2_0_TRNG #elif defined(FSL_FEATURE_SOC_RNG_COUNT) && (FSL_FEATURE_SOC_RNG_COUNT > 0) - #define FREESCALE_KSDK_2_0_RNGA + #ifdef FREESCALE_KSDK_1_3 + #include "fsl_rnga_driver.h" + #define FREESCALE_RNGA + #define RNGA_INSTANCE (0) + #else + #define FREESCALE_KSDK_2_0_RNGA + #endif #elif !defined(FREESCALE_KSDK_BM) && !defined(FREESCALE_FREE_RTOS) && !defined(FREESCALE_KSDK_FREERTOS) #define FREESCALE_RNGA #define RNGA_INSTANCE (0) @@ -855,7 +868,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM #define FREESCALE_LTC_AES_GCM #endif - + #if defined(FSL_FEATURE_LTC_HAS_SHA) && FSL_FEATURE_LTC_HAS_SHA #define FREESCALE_LTC_SHA #endif @@ -870,12 +883,12 @@ static char *fgets(char *buff, int sz, FILE *fp) #define LTC_MAX_INT_BYTES (256) #endif - /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined. + /* This FREESCALE_LTC_TFM_RSA_4096_ENABLE macro can be defined. * In such a case both software and hardware algorithm * for TFM is linked in. The decision for which algorithm is used is determined at runtime * from size of inputs. If inputs and result can fit into LTC (see LTC_MAX_INT_BYTES) * then we call hardware algorithm, otherwise we call software algorithm. - * + * * Chinese reminder theorem is used to break RSA 4096 exponentiations (both public and private key) * into several computations with 2048-bit modulus and exponents. */ @@ -887,7 +900,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #define ECC_TIMING_RESISTANT /* the LTC PKHA hardware limit is 512 bits (64 bytes) for ECC. - the LTC_MAX_ECC_BITS defines the size of local variables that hold ECC parameters + the LTC_MAX_ECC_BITS defines the size of local variables that hold ECC parameters and point coordinates */ #ifndef LTC_MAX_ECC_BITS #define LTC_MAX_ECC_BITS (384) @@ -915,8 +928,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif /* FREESCALE_USE_LTC */ #ifdef FREESCALE_LTC_TFM_RSA_4096_ENABLE - #undef USE_CERT_BUFFERS_2048 + #undef USE_CERT_BUFFERS_4096 #define USE_CERT_BUFFERS_4096 + #undef FP_MAX_BITS #define FP_MAX_BITS (8192) #undef NO_DH @@ -946,9 +960,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #define NO_OLD_RNGNAME #ifdef WOLFSSL_STM32_CUBEMX #include "stm32f2xx_hal.h" - #ifndef STM32_HAL_TIMEOUT - #define STM32_HAL_TIMEOUT 0xFF - #endif + #ifndef STM32_HAL_TIMEOUT + #define STM32_HAL_TIMEOUT 0xFF + #endif #else #include "stm32f2xx.h" #include "stm32f2xx_cryp.h" @@ -972,9 +986,9 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #ifdef WOLFSSL_STM32_CUBEMX #include "stm32f4xx_hal.h" - #ifndef STM32_HAL_TIMEOUT - #define STM32_HAL_TIMEOUT 0xFF - #endif + #ifndef STM32_HAL_TIMEOUT + #define STM32_HAL_TIMEOUT 0xFF + #endif #else #include "stm32f4xx.h" #include "stm32f4xx_cryp.h" @@ -1210,7 +1224,8 @@ static char *fgets(char *buff, int sz, FILE *fp) #if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \ - !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) + !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \ + !defined(XMALLOC_OVERRIDE) #define USE_WOLFSSL_MEMORY #endif @@ -1230,6 +1245,12 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #endif +/* write dup cannot be used with secure renegotiation because write dup + * make write side write only and read side read only */ +#if defined(HAVE_WRITE_DUP) && defined(HAVE_SECURE_RENEGOTIATION) + #error "WRITE DUP and SECURE RENEGOTIATION cannot both be on" +#endif + #ifdef WOLFSSL_SGX #define WOLFCRYPT_ONLY /* limitation until IO resolved */ #define SINGLE_THREADED @@ -1396,10 +1417,10 @@ static char *fgets(char *buff, int sz, FILE *fp) #define NO_OLD_TLS #endif -/* If not forcing ARC4 as the DRBG or using custom RNG block gen, enable Hash_DRBG */ -#undef HAVE_HASHDRBG -#if !defined(WOLFSSL_FORCE_RC4_DRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) - #define HAVE_HASHDRBG + +/* Default AES minimum auth tag sz, allow user to override */ +#ifndef WOLFSSL_MIN_AUTH_TAG_SZ + #define WOLFSSL_MIN_AUTH_TAG_SZ 12 #endif @@ -1446,11 +1467,25 @@ static char *fgets(char *buff, int sz, FILE *fp) #undef HAVE_WOLF_EVENT #define HAVE_WOLF_EVENT + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + #define WC_ASYNC_DEV_SIZE 320+24 + #else + #define WC_ASYNC_DEV_SIZE 320 + #endif + #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \ !defined(WOLFSSL_ASYNC_CRYPT_TEST) #error No async hardware defined with WOLFSSL_ASYNC_CRYPT! #endif + + /* Enable ECC_CACHE_CURVE for ASYNC */ + #if !defined(ECC_CACHE_CURVE) + #define ECC_CACHE_CURVE + #endif #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifndef WC_ASYNC_DEV_SIZE + #define WC_ASYNC_DEV_SIZE 0 +#endif /* leantls checks */ #ifdef WOLFSSL_LEANTLS @@ -1464,7 +1499,7 @@ static char *fgets(char *buff, int sz, FILE *fp) #if defined(HAVE_IO_POOL) || defined(XMALLOC_USER) || defined(NO_WOLFSSL_MEMORY) #error static memory cannot be used with HAVE_IO_POOL, XMALLOC_USER or NO_WOLFSSL_MEMORY #endif - #ifndef USE_FAST_MATH + #if !defined(USE_FAST_MATH) && !defined(NO_BIG_INT) #error static memory requires fast math please define USE_FAST_MATH #endif #ifdef WOLFSSL_SMALL_STACK @@ -1487,6 +1522,16 @@ static char *fgets(char *buff, int sz, FILE *fp) #endif #endif +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_OLD_TLS) && \ + (defined(NO_SHA) || defined(NO_MD5)) + #error old TLS requires MD5 and SHA +#endif + +/* for backwards compatibility */ +#if defined(TEST_IPV6) && !defined(WOLFSSL_IPV6) + #define WOLFSSL_IPV6 +#endif + /* Place any other flags or defines here */ @@ -1495,6 +1540,30 @@ static char *fgets(char *buff, int sz, FILE *fp) #undef HAVE_GMTIME_R /* don't trust macro with windows */ #endif /* WOLFSSL_MYSQL_COMPATIBLE */ +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + #define SSL_OP_NO_COMPRESSION SSL_OP_NO_COMPRESSION + #define OPENSSL_NO_ENGINE + #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + #ifndef OPENSSL_EXTRA + #define OPENSSL_EXTRA + #endif + #ifndef HAVE_SESSION_TICKET + #define HAVE_SESSION_TICKET + #endif + #ifndef HAVE_OCSP + #define HAVE_OCSP + #endif + #ifndef KEEP_OUR_CERT + #define KEEP_OUR_CERT + #endif + #ifndef HAVE_SNI + #define HAVE_SNI + #endif +#endif + +#if defined(WOLFSSL_NGINX) + #define SSL_CTRL_SET_TLSEXT_HOSTNAME +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha.h b/wolfssl/wolfcrypt/sha.h index 6dbd91b875..db72e9118b 100644 --- a/wolfssl/wolfcrypt/sha.h +++ b/wolfssl/wolfcrypt/sha.h @@ -34,13 +34,21 @@ #ifdef FREESCALE_LTC_SHA #include "fsl_ltc.h" -#endif +#endif #ifdef __cplusplus extern "C" { #endif #ifndef HAVE_FIPS /* avoid redefining structs */ + +#ifdef WOLFSSL_PIC32MZ_HASH + #include "port/pic32/pic32mz-crypt.h" +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + /* in bytes */ enum { #if defined(STM32F2_HASH) || defined(STM32F4_HASH) @@ -52,12 +60,8 @@ enum { SHA_PAD_SIZE = 56 }; -#ifdef WOLFSSL_PIC32MZ_HASH -#include "port/pic32/pic32mz-crypt.h" -#endif #ifndef WOLFSSL_TI_HASH - /* Sha digest */ typedef struct Sha { #ifdef FREESCALE_LTC_SHA @@ -67,24 +71,36 @@ typedef struct Sha { word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ word32 buffer[SHA_BLOCK_SIZE / sizeof(word32)]; - #ifndef WOLFSSL_PIC32MZ_HASH - word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; - #else - word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; - pic32mz_desc desc; /* Crypt Engine descriptor */ - #endif - #endif /* FREESCALE_LTC_SHA */ + #ifndef WOLFSSL_PIC32MZ_HASH + word32 digest[SHA_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[PIC32_HASH_SIZE / sizeof(word32)]; + #endif + void* heap; + #ifdef WOLFSSL_PIC32MZ_HASH + pic32mz_desc desc; /* Crypt Engine descriptor */ + #endif + #ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #endif /* WOLFSSL_ASYNC_CRYPT */ +#endif /* FREESCALE_LTC_SHA */ } Sha; -#else /* WOLFSSL_TI_HASH */ +#else #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" -#endif +#endif /* WOLFSSL_TI_HASH */ + #endif /* HAVE_FIPS */ WOLFSSL_API int wc_InitSha(Sha*); +WOLFSSL_API int wc_InitSha_ex(Sha* sha, void* heap, int devId); WOLFSSL_API int wc_ShaUpdate(Sha*, const byte*, word32); WOLFSSL_API int wc_ShaFinal(Sha*, byte*); +WOLFSSL_API void wc_ShaFree(Sha*); + +WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); +WOLFSSL_API int wc_ShaCopy(Sha*, Sha*); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/sha256.h b/wolfssl/wolfcrypt/sha256.h index 790d87c94f..4d8ef1f647 100644 --- a/wolfssl/wolfcrypt/sha256.h +++ b/wolfssl/wolfcrypt/sha256.h @@ -44,9 +44,13 @@ #endif #ifndef HAVE_FIPS /* avoid redefinition of structs */ + #ifdef WOLFSSL_PIC32MZ_HASH #include "port/pic32/pic32mz-crypt.h" #endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif /* in bytes */ enum { @@ -63,14 +67,19 @@ typedef struct Sha256 { #ifdef FREESCALE_LTC_SHA ltc_hash_ctx_t ctx; #else + /* alignment on digest and buffer speeds up ARMv8 crypto operations */ + ALIGN16 word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; + ALIGN16 word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ - ALIGN16 word32 digest[SHA256_DIGEST_SIZE / sizeof(word32)]; - ALIGN16 word32 buffer[SHA256_BLOCK_SIZE / sizeof(word32)]; - #ifdef WOLFSSL_PIC32MZ_HASH - pic32mz_desc desc ; /* Crypt Engine descriptor */ - #endif + void* heap; +#ifdef WOLFSSL_PIC32MZ_HASH + pic32mz_desc desc; /* Crypt Engine descriptor */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* FREESCALE_LTC_SHA */ } Sha256; @@ -81,8 +90,13 @@ typedef struct Sha256 { #endif /* HAVE_FIPS */ WOLFSSL_API int wc_InitSha256(Sha256*); +WOLFSSL_API int wc_InitSha256_ex(Sha256*, void*, int); WOLFSSL_API int wc_Sha256Update(Sha256*, const byte*, word32); WOLFSSL_API int wc_Sha256Final(Sha256*, byte*); +WOLFSSL_API void wc_Sha256Free(Sha256*); + +WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); +WOLFSSL_API int wc_Sha256Copy(Sha256* src, Sha256* dst); #ifdef WOLFSSL_SHA224 @@ -99,8 +113,13 @@ typedef Sha256 Sha224; #endif /* HAVE_FIPS */ WOLFSSL_API int wc_InitSha224(Sha224*); +WOLFSSL_API int wc_InitSha224_ex(Sha224*, void*, int); WOLFSSL_API int wc_Sha224Update(Sha224*, const byte*, word32); WOLFSSL_API int wc_Sha224Final(Sha224*, byte*); +WOLFSSL_API void wc_Sha224Free(Sha224*); + +WOLFSSL_API int wc_Sha224GetHash(Sha224*, byte*); +WOLFSSL_API int wc_Sha224Copy(Sha224* src, Sha224* dst); #endif /* WOLFSSL_SHA224 */ diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index 2f53772e98..7fea27e6e9 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -42,6 +42,10 @@ #ifndef HAVE_FIPS /* avoid redefinition of structs */ +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + /* in bytes */ enum { SHA512 = 4, /* hash type unique */ @@ -58,13 +62,22 @@ typedef struct Sha512 { word64 hiLen; /* length in bytes */ word64 digest[SHA512_DIGEST_SIZE / sizeof(word64)]; word64 buffer[SHA512_BLOCK_SIZE / sizeof(word64)]; + void* heap; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ } Sha512; #endif /* HAVE_FIPS */ WOLFSSL_API int wc_InitSha512(Sha512*); +WOLFSSL_API int wc_InitSha512_ex(Sha512*, void*, int); WOLFSSL_API int wc_Sha512Update(Sha512*, const byte*, word32); WOLFSSL_API int wc_Sha512Final(Sha512*, byte*); +WOLFSSL_API void wc_Sha512Free(Sha512*); + +WOLFSSL_API int wc_Sha512GetHash(Sha512*, byte*); +WOLFSSL_API int wc_Sha512Copy(Sha512* src, Sha512* dst); #if defined(WOLFSSL_SHA384) @@ -81,8 +94,13 @@ typedef Sha512 Sha384; #endif /* HAVE_FIPS */ WOLFSSL_API int wc_InitSha384(Sha384*); +WOLFSSL_API int wc_InitSha384_ex(Sha384*, void*, int); WOLFSSL_API int wc_Sha384Update(Sha384*, const byte*, word32); WOLFSSL_API int wc_Sha384Final(Sha384*, byte*); +WOLFSSL_API void wc_Sha384Free(Sha384*); + +WOLFSSL_API int wc_Sha384GetHash(Sha384*, byte*); +WOLFSSL_API int wc_Sha384Copy(Sha384* src, Sha384* dst); #endif /* WOLFSSL_SHA384 */ diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index c7cf9fa06d..bc989a1590 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -28,7 +28,7 @@ /** - * Edited by Mois�s Guimar�es (moises.guimaraes@phoebus.com.br) + * Edited by Moises Guimaraes (moises.guimaraes@phoebus.com.br) * to fit CyaSSL's needs. */ @@ -43,10 +43,19 @@ #include +/* wolf big int and common functions */ +#include + #ifdef __cplusplus extern "C" { #endif +#ifdef WOLFSSL_PUBLIC_MP + #define MP_API WOLFSSL_API +#else + #define MP_API +#endif + #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif @@ -260,6 +269,7 @@ #endif #define FP_MASK (fp_digit)(-1) +#define FP_DIGIT_MAX FP_MASK #define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT) /* signs */ @@ -281,16 +291,21 @@ #define FP_YES 1 /* yes response */ #define FP_NO 0 /* no response */ +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT; +#endif + /* a FP type */ -typedef struct { - int used, - sign; -#ifdef ALT_ECC_SIZE +typedef struct fp_int { + int used; + int sign; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) int size; #endif fp_digit dp[FP_SIZE]; -#ifdef WOLFSSL_ASYNC_CRYPT - byte *dpraw; /* Used for hardware crypto */ + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ #endif } fp_int; @@ -370,15 +385,11 @@ typedef struct { /*const char *fp_ident(void);*/ /* initialize [or zero] an fp int */ -#ifdef ALT_ECC_SIZE - void fp_init(fp_int *a); - void fp_zero(fp_int *a); - void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ -#else - #define fp_init(a) (void)XMEMSET((a), 0, sizeof(fp_int)) - #define fp_zero(a) fp_init(a) - #define fp_clear(a) ForceZero((a), sizeof(fp_int)); -#endif +void fp_init(fp_int *a); +MP_API void fp_zero(fp_int *a); +MP_API void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ +MP_API void fp_forcezero (fp_int * a); +MP_API void fp_free(fp_int* a); /* zero/even/odd ? */ #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) @@ -390,6 +401,7 @@ typedef struct { /* set to a small digit */ void fp_set(fp_int *a, fp_digit b); +void fp_set_int(fp_int *a, unsigned long b); /* check if a bit is set */ int fp_is_bit_set(fp_int *a, fp_digit b); @@ -397,13 +409,8 @@ int fp_is_bit_set(fp_int *a, fp_digit b); int fp_set_bit (fp_int * a, fp_digit b); /* copy from a to b */ -#ifndef ALT_ECC_SIZE - #define fp_copy(a, b) (void)(((a) != (b)) ? ((void)XMEMCPY((b), (a), sizeof(fp_int))) : (void)0) - #define fp_init_copy(a, b) fp_copy(b, a) -#else - void fp_copy(fp_int *a, fp_int *b); - void fp_init_copy(fp_int *a, fp_int *b); -#endif +void fp_copy(fp_int *a, fp_int *b); +void fp_init_copy(fp_int *a, fp_int *b); /* clamp digits */ #define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; } @@ -608,6 +615,7 @@ void fp_sqr_comba64(fp_int *a, fp_int *b); typedef fp_digit mp_digit; typedef fp_word mp_word; typedef fp_int mp_int; +#define MP_INT_DEFINED /* Constants */ #define MP_LT FP_LT /* less than */ @@ -619,90 +627,108 @@ typedef fp_int mp_int; #define MP_OKAY FP_OKAY /* ok result */ #define MP_NO FP_NO /* yes/no result */ #define MP_YES FP_YES /* yes/no result */ +#define MP_ZPOS FP_ZPOS +#define MP_NEG FP_NEG +#define MP_MASK FP_MASK /* Prototypes */ #define mp_zero(a) fp_zero(a) #define mp_isone(a) fp_isone(a) #define mp_iseven(a) fp_iseven(a) #define mp_isneg(a) fp_isneg(a) -int mp_init (mp_int * a); -void mp_clear (mp_int * a); -#define mp_forcezero(a) fp_clear(a) -int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, mp_int* f); - -int mp_add (mp_int * a, mp_int * b, mp_int * c); -int mp_sub (mp_int * a, mp_int * b, mp_int * c); -int mp_add_d (mp_int * a, mp_digit b, mp_int * c); - -int mp_mul (mp_int * a, mp_int * b, mp_int * c); -int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); -int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); -int mp_mod(mp_int *a, mp_int *b, mp_int *c); -int mp_invmod(mp_int *a, mp_int *b, mp_int *c); -int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); -int mp_mul_2d(mp_int *a, int b, mp_int *c); - - -int mp_cmp(mp_int *a, mp_int *b); -int mp_cmp_d(mp_int *a, mp_digit b); - -int mp_unsigned_bin_size(mp_int * a); -int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); -int mp_to_unsigned_bin (mp_int * a, unsigned char *b); - -int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); -int mp_copy(fp_int* a, fp_int* b); -int mp_isodd(mp_int* a); -int mp_iszero(mp_int* a); -int mp_count_bits(mp_int *a); -int mp_leading_bit(mp_int *a); -int mp_set_int(mp_int *a, mp_digit b); -int mp_is_bit_set (mp_int * a, mp_digit b); -int mp_set_bit (mp_int * a, mp_digit b); -void mp_rshb(mp_int *a, int x); -int mp_toradix (mp_int *a, char *str, int radix); -int mp_radix_size (mp_int * a, int radix, int *size); +MP_API int mp_init (mp_int * a); +MP_API void mp_clear (mp_int * a); +MP_API void mp_free (mp_int * a); +MP_API void mp_forcezero (mp_int * a); +MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); + +MP_API int mp_add (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_add_d (mp_int * a, mp_digit b, mp_int * c); + +MP_API int mp_mul (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_mod(mp_int *a, mp_int *b, mp_int *c); +MP_API int mp_invmod(mp_int *a, mp_int *b, mp_int *c); +MP_API int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); +MP_API int mp_mul_2d(mp_int *a, int b, mp_int *c); + +MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); + +MP_API int mp_cmp(mp_int *a, mp_int *b); +MP_API int mp_cmp_d(mp_int *a, mp_digit b); + +MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); +MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); + +MP_API int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); +MP_API int mp_copy(fp_int* a, fp_int* b); +MP_API int mp_isodd(mp_int* a); +MP_API int mp_iszero(mp_int* a); +MP_API int mp_count_bits(mp_int *a); +MP_API int mp_leading_bit(mp_int *a); +MP_API int mp_set_int(mp_int *a, unsigned long b); +MP_API int mp_is_bit_set (mp_int * a, mp_digit b); +MP_API int mp_set_bit (mp_int * a, mp_digit b); +MP_API void mp_rshb(mp_int *a, int x); +MP_API void mp_rshd(mp_int *a, int x); +MP_API int mp_toradix (mp_int *a, char *str, int radix); +MP_API int mp_radix_size (mp_int * a, int radix, int *size); #ifdef WOLFSSL_DEBUG_MATH - void mp_dump(const char* desc, mp_int* a, byte verbose); + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); #else #define mp_dump(desc, a, verbose) #endif #ifdef HAVE_ECC - int mp_read_radix(mp_int* a, const char* str, int radix); - void mp_set(fp_int *a, fp_digit b); - int mp_sqr(fp_int *a, fp_int *b); - int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); - int mp_montgomery_setup(fp_int *a, fp_digit *rho); - int mp_div_2(fp_int * a, fp_int * b); - int mp_init_copy(fp_int * a, fp_int * b); + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); + MP_API int mp_sqr(fp_int *a, fp_int *b); + MP_API int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); + MP_API int mp_montgomery_setup(fp_int *a, fp_digit *rho); + MP_API int mp_div_2(fp_int * a, fp_int * b); + MP_API int mp_init_copy(fp_int * a, fp_int * b); +#endif + +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) + MP_API int mp_set(fp_int *a, fp_digit b); #endif #if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) - int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); - int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); + MP_API int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); #endif #ifdef WOLFSSL_KEY_GEN -int mp_gcd(fp_int *a, fp_int *b, fp_int *c); -int mp_lcm(fp_int *a, fp_int *b, fp_int *c); -int mp_prime_is_prime(mp_int* a, int t, int* result); -int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); -int mp_exch(mp_int *a, mp_int *b); +MP_API int mp_gcd(fp_int *a, fp_int *b, fp_int *c); +MP_API int mp_lcm(fp_int *a, fp_int *b, fp_int *c); +MP_API int mp_prime_is_prime(mp_int* a, int t, int* result); +MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); +MP_API int mp_exch(mp_int *a, mp_int *b); #endif /* WOLFSSL_KEY_GEN */ -int mp_cnt_lsb(fp_int *a); -int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); -int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); -int mp_lshd (mp_int * a, int b); +MP_API int mp_cnt_lsb(fp_int *a); +MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); +MP_API int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); +MP_API int mp_lshd (mp_int * a, int b); WOLFSSL_API word32 CheckRunTimeFastMath(void); /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math FP_SIZE must match, return 1 if a match otherwise 0 */ #define CheckFastMathSettings() (FP_SIZE == CheckRunTimeFastMath()) + + +/* wolf big int and common functions */ +#include + + #ifdef __cplusplus } #endif diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h old mode 100644 new mode 100755 index ac20cae994..7a1a57d77c --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -133,13 +133,14 @@ /* set up rotate style */ - #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && !defined(WOLFSSL_SGX) + #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && \ + !defined(WOLFSSL_SGX) && !defined(INTIME_RTOS) #define INTEL_INTRINSICS #define FAST_ROTATE #elif defined(__MWERKS__) && TARGET_CPU_PPC #define PPC_INTRINSICS #define FAST_ROTATE - #elif defined(__GNUC__) && defined(__i386__) + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) /* GCC does peephole optimizations which should result in using rotate instructions */ #define FAST_ROTATE @@ -160,10 +161,20 @@ #define THREAD_LS_T #endif + /* GCC 7 has new switch() fall-through detection */ + #if defined(__GNUC__) + #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1))) + #define FALL_THROUGH __attribute__ ((fallthrough)); + #endif + #endif + #ifndef FALL_THROUGH + #define FALL_THROUGH + #endif /* Micrium will use Visual Studio for compilation but not the Win32 API */ #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ - !defined(FREERTOS_TCP) && !defined(EBSNET) && !defined(WOLFSSL_UTASKER) + !defined(FREERTOS_TCP) && !defined(EBSNET) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) #define USE_WINDOWS_API #endif @@ -176,12 +187,26 @@ WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type); WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type); WOLFSSL_API void XFREE(void *p, void* heap, int type); - #elif defined(XMALLOC_USER) + #elif defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA) + #include + #undef USE_WOLFSSL_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t), __func__, __LINE__) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t)) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t)) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif defined(XMALLOC_USER) /* prototypes for user heap override functions */ #include /* for size_t */ extern void *XMALLOC(size_t n, void* heap, int type); extern void *XREALLOC(void *p, size_t n, void* heap, int type); extern void XFREE(void *p, void* heap, int type); + #elif defined(XMALLOC_OVERRIDE) + /* override the XMALLOC, XFREE and XREALLOC macros */ #elif defined(NO_WOLFSSL_MEMORY) /* just use plain C stdlib stuff if desired */ #include @@ -192,7 +217,7 @@ && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \ && !defined(WOLFSSL_LEANPSK) && !defined(FREERTOS) && !defined(FREERTOS_TCP)\ - && !defined(WOLFSSL_uITRON4) && !defined(WOLFSSL_uTKERNEL2) + && !defined(WOLFSSL_uITRON4) /* default C runtime, can install different routines at runtime via cbs */ #include #ifdef WOLFSSL_STATIC_MEMORY @@ -218,6 +243,41 @@ #endif /* WOLFSSL_STATIC_MEMORY */ #endif + /* declare/free variable handling for async */ + #ifdef WOLFSSL_ASYNC_CRYPT + #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT); + #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \ + VAR_TYPE* VAR_NAME = ({ \ + VAR_TYPE* ptr = XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, HEAP, DYNAMIC_TYPE_WOLF_BIGINT); \ + if (ptr && INIT_VALUE) { \ + XMEMCPY(ptr, INIT_VALUE, sizeof(VAR_TYPE) * VAR_SIZE); \ + } \ + ptr; \ + }) + #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME[VAR_ITEMS]; \ + int idx##VAR_NAME; \ + for (idx##VAR_NAME=0; idx##VAR_NAME @@ -242,7 +302,7 @@ #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) #endif - #if defined(WOLFSSL_MYSQL_COMPATIBLE) + #if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) #ifndef USE_WINDOWS_API #define XSNPRINTF snprintf #else @@ -252,7 +312,7 @@ #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN) /* use only Thread Safe version of strtok */ - #ifndef USE_WINDOWS_API + #if !defined(USE_WINDOWS_API) && !defined(INTIME_RTOS) #define XSTRTOK strtok_r #else #define XSTRTOK strtok_s @@ -280,66 +340,74 @@ /* memory allocation types for user hints */ enum { - DYNAMIC_TYPE_CA = 1, - DYNAMIC_TYPE_CERT = 2, - DYNAMIC_TYPE_KEY = 3, - DYNAMIC_TYPE_FILE = 4, - DYNAMIC_TYPE_SUBJECT_CN = 5, - DYNAMIC_TYPE_PUBLIC_KEY = 6, - DYNAMIC_TYPE_SIGNER = 7, - DYNAMIC_TYPE_NONE = 8, - DYNAMIC_TYPE_BIGINT = 9, - DYNAMIC_TYPE_RSA = 10, - DYNAMIC_TYPE_METHOD = 11, - DYNAMIC_TYPE_OUT_BUFFER = 12, - DYNAMIC_TYPE_IN_BUFFER = 13, - DYNAMIC_TYPE_INFO = 14, - DYNAMIC_TYPE_DH = 15, - DYNAMIC_TYPE_DOMAIN = 16, - DYNAMIC_TYPE_SSL = 17, - DYNAMIC_TYPE_CTX = 18, - DYNAMIC_TYPE_WRITEV = 19, - DYNAMIC_TYPE_OPENSSL = 20, - DYNAMIC_TYPE_DSA = 21, - DYNAMIC_TYPE_CRL = 22, - DYNAMIC_TYPE_REVOKED = 23, - DYNAMIC_TYPE_CRL_ENTRY = 24, - DYNAMIC_TYPE_CERT_MANAGER = 25, - DYNAMIC_TYPE_CRL_MONITOR = 26, - DYNAMIC_TYPE_OCSP_STATUS = 27, - DYNAMIC_TYPE_OCSP_ENTRY = 28, - DYNAMIC_TYPE_ALTNAME = 29, - DYNAMIC_TYPE_SUITES = 30, - DYNAMIC_TYPE_CIPHER = 31, - DYNAMIC_TYPE_RNG = 32, - DYNAMIC_TYPE_ARRAYS = 33, - DYNAMIC_TYPE_DTLS_POOL = 34, - DYNAMIC_TYPE_SOCKADDR = 35, - DYNAMIC_TYPE_LIBZ = 36, - DYNAMIC_TYPE_ECC = 37, - DYNAMIC_TYPE_TMP_BUFFER = 38, - DYNAMIC_TYPE_DTLS_MSG = 39, - DYNAMIC_TYPE_ASYNC_TMP = 40, - DYNAMIC_TYPE_ASYNC_RSA = 41, - DYNAMIC_TYPE_X509 = 42, - DYNAMIC_TYPE_TLSX = 43, - DYNAMIC_TYPE_OCSP = 44, - DYNAMIC_TYPE_SIGNATURE = 45, - DYNAMIC_TYPE_HASHES = 46, - DYNAMIC_TYPE_SRP = 47, - DYNAMIC_TYPE_COOKIE_PWD = 48, - DYNAMIC_TYPE_USER_CRYPTO = 49, - DYNAMIC_TYPE_OCSP_REQUEST = 50, - DYNAMIC_TYPE_X509_EXT = 51, - DYNAMIC_TYPE_X509_STORE = 52, - DYNAMIC_TYPE_X509_CTX = 53, - DYNAMIC_TYPE_URL = 54, - DYNAMIC_TYPE_DTLS_FRAG = 55, - DYNAMIC_TYPE_DTLS_BUFFER = 56, - DYNAMIC_TYPE_SESSION_TICK = 57, - DYNAMIC_TYPE_PKCS = 58, - DYNAMIC_TYPE_MUTEX = 59, - DYNAMIC_TYPE_PKCS7 = 60 + DYNAMIC_TYPE_CA = 1, + DYNAMIC_TYPE_CERT = 2, + DYNAMIC_TYPE_KEY = 3, + DYNAMIC_TYPE_FILE = 4, + DYNAMIC_TYPE_SUBJECT_CN = 5, + DYNAMIC_TYPE_PUBLIC_KEY = 6, + DYNAMIC_TYPE_SIGNER = 7, + DYNAMIC_TYPE_NONE = 8, + DYNAMIC_TYPE_BIGINT = 9, + DYNAMIC_TYPE_RSA = 10, + DYNAMIC_TYPE_METHOD = 11, + DYNAMIC_TYPE_OUT_BUFFER = 12, + DYNAMIC_TYPE_IN_BUFFER = 13, + DYNAMIC_TYPE_INFO = 14, + DYNAMIC_TYPE_DH = 15, + DYNAMIC_TYPE_DOMAIN = 16, + DYNAMIC_TYPE_SSL = 17, + DYNAMIC_TYPE_CTX = 18, + DYNAMIC_TYPE_WRITEV = 19, + DYNAMIC_TYPE_OPENSSL = 20, + DYNAMIC_TYPE_DSA = 21, + DYNAMIC_TYPE_CRL = 22, + DYNAMIC_TYPE_REVOKED = 23, + DYNAMIC_TYPE_CRL_ENTRY = 24, + DYNAMIC_TYPE_CERT_MANAGER = 25, + DYNAMIC_TYPE_CRL_MONITOR = 26, + DYNAMIC_TYPE_OCSP_STATUS = 27, + DYNAMIC_TYPE_OCSP_ENTRY = 28, + DYNAMIC_TYPE_ALTNAME = 29, + DYNAMIC_TYPE_SUITES = 30, + DYNAMIC_TYPE_CIPHER = 31, + DYNAMIC_TYPE_RNG = 32, + DYNAMIC_TYPE_ARRAYS = 33, + DYNAMIC_TYPE_DTLS_POOL = 34, + DYNAMIC_TYPE_SOCKADDR = 35, + DYNAMIC_TYPE_LIBZ = 36, + DYNAMIC_TYPE_ECC = 37, + DYNAMIC_TYPE_TMP_BUFFER = 38, + DYNAMIC_TYPE_DTLS_MSG = 39, + DYNAMIC_TYPE_X509 = 40, + DYNAMIC_TYPE_TLSX = 41, + DYNAMIC_TYPE_OCSP = 42, + DYNAMIC_TYPE_SIGNATURE = 43, + DYNAMIC_TYPE_HASHES = 44, + DYNAMIC_TYPE_SRP = 45, + DYNAMIC_TYPE_COOKIE_PWD = 46, + DYNAMIC_TYPE_USER_CRYPTO = 47, + DYNAMIC_TYPE_OCSP_REQUEST = 48, + DYNAMIC_TYPE_X509_EXT = 49, + DYNAMIC_TYPE_X509_STORE = 50, + DYNAMIC_TYPE_X509_CTX = 51, + DYNAMIC_TYPE_URL = 52, + DYNAMIC_TYPE_DTLS_FRAG = 53, + DYNAMIC_TYPE_DTLS_BUFFER = 54, + DYNAMIC_TYPE_SESSION_TICK = 55, + DYNAMIC_TYPE_PKCS = 56, + DYNAMIC_TYPE_MUTEX = 57, + DYNAMIC_TYPE_PKCS7 = 58, + DYNAMIC_TYPE_AES = 59, + DYNAMIC_TYPE_WOLF_BIGINT = 60, + DYNAMIC_TYPE_ASN1 = 61, + DYNAMIC_TYPE_LOG = 62, + DYNAMIC_TYPE_WRITEDUP = 63, + DYNAMIC_TYPE_DH_BUFFER = 64, + DYNAMIC_TYPE_HMAC = 65, + DYNAMIC_TYPE_ASYNC = 66, + DYNAMIC_TYPE_ASYNC_NUMA = 67, + DYNAMIC_TYPE_ASYNC_NUMA64 = 68, }; /* max error buffer string size */ @@ -390,26 +458,64 @@ /* AESNI requires alignment and ARMASM gains some performance from it */ - #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) - #if !defined (ALIGN16) - #if defined (__GNUC__) - #define ALIGN16 __attribute__ ( (aligned (16))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN16 __declspec (align (16)) - #else - #define ALIGN16 + #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || defined(USE_INTEL_SPEEDUP) + #if !defined(ALIGN16) + #if defined(__GNUC__) + #define ALIGN16 __attribute__ ( (aligned (16))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN16 __declspec (align (16)) + #else + #define ALIGN16 + #endif + #endif /* !ALIGN16 */ + + #if !defined (ALIGN32) + #if defined (__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif #endif - #endif + + #if !defined(ALIGN32) + #if defined(__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif + #endif /* !ALIGN32 */ #else #ifndef ALIGN16 #define ALIGN16 #endif - #endif /* WOLFSSL_AESNI or WOLFSSL_ARMASM */ + #ifndef ALIGN32 + #define ALIGN32 + #endif + #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */ + + + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + #ifdef WOLFSSL_RIOT_OS #define EXIT_TEST(ret) exit(ret) + #elif defined(HAVE_STACK_SIZE) + #define EXIT_TEST(ret) return (void*)((size_t)(ret)) #else #define EXIT_TEST(ret) return ret #endif diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index db8d1ee435..574700b69b 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -38,14 +38,14 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif - #ifndef WOLFCRYPT_ONLY - #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN) - /* On WinCE winsock2.h must be included before windows.h */ - #include - #endif - #include + #ifndef WOLFSSL_SGX + #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN) + /* On WinCE winsock2.h must be included before windows.h */ + #include + #endif + #include + #endif /* WOLFSSL_SGX */ #endif - #endif /* WOLFCRYPT_ONLY */ #elif defined(THREADX) #ifndef SINGLE_THREADED #include "tx_api.h" @@ -61,12 +61,13 @@ #elif defined(FREESCALE_FREE_RTOS) #include "fsl_os_abstraction.h" #elif defined(WOLFSSL_uITRON4) + #include "stddef.h" #include "kernel.h" #elif defined(WOLFSSL_uTKERNEL2) #include "tk/tkernel.h" #elif defined(WOLFSSL_MDK_ARM) #if defined(WOLFSSL_MDK5) - #include "cmsis_os.h" + #include "cmsis_os.h" #else #include #endif @@ -77,6 +78,9 @@ #include #elif defined(WOLFSSL_FROSTED) #include +#elif defined(INTIME_RTOS) + #include + #include #else #ifndef SINGLE_THREADED #define WOLFSSL_PTHREADS @@ -146,6 +150,8 @@ typedef ti_sysbios_knl_Semaphore_Handle wolfSSL_Mutex; #elif defined(WOLFSSL_FROSTED) typedef mutex_t * wolfSSL_Mutex; + #elif defined(INTIME_RTOS) + typedef RTHANDLE wolfSSL_Mutex; #else #error Need a mutex type in multithreaded mode #endif /* USE_WINDOWS_API */ @@ -186,11 +192,15 @@ WOLFSSL_API int wc_UnLockMutex(wolfSSL_Mutex*); /* main crypto initialization function */ WOLFSSL_API int wolfCrypt_Init(void); +WOLFSSL_API int wolfCrypt_Cleanup(void); /* filesystem abstraction layer, used by ssl.c */ #ifndef NO_FILESYSTEM #if defined(EBSNET) + #include "vfapi.h" + #include "vfile.h" + #define XFILE int #define XFOPEN(NAME, MODE) vf_open((const char *)NAME, VO_RDONLY, 0); #define XFSEEK vf_lseek @@ -201,6 +211,7 @@ WOLFSSL_API int wolfCrypt_Init(void); #define XFCLOSE vf_close #define XSEEK_END VSEEK_END #define XBADFILE -1 + #define XFGETS(b,s,f) -2 /* Not ported yet */ #elif defined(LSR_FS) #include #define XFILE struct fs_file* @@ -213,6 +224,7 @@ WOLFSSL_API int wolfCrypt_Init(void); #define XFCLOSE fs_close #define XSEEK_END 0 #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #define XFILE MQX_FILE_PTR #define XFOPEN fopen @@ -224,6 +236,7 @@ WOLFSSL_API int wolfCrypt_Init(void); #define XFCLOSE fclose #define XSEEK_END IO_SEEK_END #define XBADFILE NULL + #define XFGETS fgets #elif defined(MICRIUM) #include #define XFILE FS_FILE* @@ -236,6 +249,7 @@ WOLFSSL_API int wolfCrypt_Init(void); #define XFCLOSE fs_fclose #define XSEEK_END FS_SEEK_END #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ #else /* stdio, default case */ #include @@ -254,9 +268,41 @@ WOLFSSL_API int wolfCrypt_Init(void); #define XFCLOSE fclose #define XSEEK_END SEEK_END #define XBADFILE NULL + #define XFGETS fgets + + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) + #include + #include + #include + #endif #endif -#endif /* NO_FILESYSTEM */ + #ifndef MAX_FILENAME_SZ + #define MAX_FILENAME_SZ 256 /* max file name length */ + #endif + #ifndef MAX_PATH + #define MAX_PATH 256 + #endif + +#if !defined(NO_WOLFSSL_DIR) + typedef struct ReadDirCtx { + #ifdef USE_WINDOWS_API + WIN32_FIND_DATAA FindFileData; + HANDLE hFind; + #else + struct dirent* entry; + DIR* dir; + struct stat s; + #endif + char name[MAX_FILENAME_SZ]; + } ReadDirCtx; + + WOLFSSL_API int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name); + WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name); + WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx); +#endif /* !NO_WOLFSSL_DIR */ + +#endif /* !NO_FILESYSTEM */ /* Windows API defines its own min() macro. */ diff --git a/wolfssl/wolfcrypt/wolfevent.h b/wolfssl/wolfcrypt/wolfevent.h index 5dbf164505..af984c8cd2 100644 --- a/wolfssl/wolfcrypt/wolfevent.h +++ b/wolfssl/wolfcrypt/wolfevent.h @@ -29,22 +29,30 @@ #ifndef SINGLE_THREADED #include #endif +#ifdef HAVE_CAVIUM + #include +#endif +#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_TYPE_DEFINED typedef struct WOLFSSL WOLFSSL; +#endif typedef struct WOLF_EVENT WOLF_EVENT; +#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED typedef struct WOLFSSL_CTX WOLFSSL_CTX; +#endif 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 +#ifdef WOLFSSL_ASYNC_CRYPT + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, /* context is WOLFSSL* */ + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, /* context is WC_ASYNC_DEV */ + WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, +#endif /* WOLFSSL_ASYNC_CRYPT */ } WOLF_EVENT_TYPE; struct WOLF_EVENT { @@ -53,11 +61,20 @@ struct WOLF_EVENT { WOLF_EVENT* prev; void* context; + union { + void* ptr; +#ifdef WOLFSSL_ASYNC_CRYPT + struct WC_ASYNC_DEV* async; +#endif + } dev; #ifdef HAVE_CAVIUM - word64 reqId; + CavReqId reqId; #endif int ret; /* Async return code */ + unsigned int flags; WOLF_EVENT_TYPE type; + + /* event flags */ WOLF_EVENT_FLAG pending:1; WOLF_EVENT_FLAG done:1; /* Future event flags can go here */ @@ -87,12 +104,16 @@ WOLFSSL_API int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags); 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); +/* the queue mutex must be locked prior to calling these */ +WOLFSSL_API int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); +WOLFSSL_API int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); + + #endif /* HAVE_WOLF_EVENT */ diff --git a/wolfssl/wolfcrypt/wolfmath.h b/wolfssl/wolfcrypt/wolfmath.h new file mode 100644 index 0000000000..67e64466d4 --- /dev/null +++ b/wolfssl/wolfcrypt/wolfmath.h @@ -0,0 +1,69 @@ +/* wolfmath.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 + */ + +#if defined(HAVE_WOLF_BIGINT) && !defined(WOLF_BIGINT_DEFINED) + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + + #define WOLF_BIGINT_DEFINED +#endif + + +/* only define functions if mp_int has been declared */ +#ifdef MP_INT_DEFINED + +#ifndef __WOLFMATH_H__ +#define __WOLFMATH_H__ + + /* timing resistance array */ + #if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + extern const wolfssl_word wc_off_on_addr[2]; + #endif + + /* common math functions */ + int get_digit_count(mp_int* a); + mp_digit get_digit(mp_int* a, int n); + int get_rand_digit(WC_RNG* rng, mp_digit* d); + int mp_rand(mp_int* a, int digits, WC_RNG* rng); + + + #ifdef HAVE_WOLF_BIGINT + void wc_bigint_init(WC_BIGINT* a); + int wc_bigint_alloc(WC_BIGINT* a, word32 sz); + int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen); + int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen); + void wc_bigint_zero(WC_BIGINT* a); + void wc_bigint_free(WC_BIGINT* a); + + int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst); + int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst); + #endif /* HAVE_WOLF_BIGINT */ + +#endif /* __WOLFMATH_H__ */ + +#endif /* MP_INT_DEFINED */ diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs index c87288f876..5d05a64412 100644 --- a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs @@ -193,6 +193,8 @@ public void free() [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wolfSSL_CTX_use_certificate_file(IntPtr ctx, string file, int type); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] + private extern static int wolfSSL_CTX_load_verify_locations(IntPtr ctx, string file, string path); + [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wolfSSL_CTX_use_PrivateKey_file(IntPtr ctx, string file, int type); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static void wolfSSL_CTX_free(IntPtr ctx); @@ -1565,6 +1567,33 @@ public static int CTX_use_certificate_file(IntPtr ctx, string fileCert, int type } + /// + /// Used to load in the peer trusted root file + /// + /// CTX structure for TLS/SSL connections + /// Name of the file to load including absolute path + /// path to multiple certificates (try to load all in path) + /// 1 on success + public static int CTX_load_verify_locations(IntPtr ctx, string fileCert, string path) + { + try + { + IntPtr local_ctx = unwrap(ctx); + if (local_ctx == IntPtr.Zero) + { + log(ERROR_LOG, "CTX load verify locations certificate file error"); + return FAILURE; + } + + return wolfSSL_CTX_load_verify_locations(local_ctx, fileCert, path); + } + catch (Exception e) + { + log(ERROR_LOG, "wolfssl ctx load verify locations file error " + e.ToString()); + return FAILURE; + } + } + /// /// Used to load in the private key from a file /// diff --git a/wrapper/python/wolfcrypt/wolfcrypt/random.py b/wrapper/python/wolfcrypt/wolfcrypt/random.py index f819f51d8e..e034f5c583 100644 --- a/wrapper/python/wolfcrypt/wolfcrypt/random.py +++ b/wrapper/python/wolfcrypt/wolfcrypt/random.py @@ -46,23 +46,23 @@ def byte(self): """ Generate and return a random byte. """ - result = t2b("\0") + result = _ffi.new('byte[1]') ret = _lib.wc_RNG_GenerateByte(self.native_object, result) if ret < 0: raise WolfCryptError("RNG generate byte error (%d)" % ret) - return result + return _ffi.buffer(result, 1)[:] def bytes(self, length): """ Generate and return a random sequence of length bytes. """ - result = t2b("\0" * length) + result = _ffi.new('byte[%d]' % length) ret = _lib.wc_RNG_GenerateBlock(self.native_object, result, length) if ret < 0: raise WolfCryptError("RNG generate block error (%d)" % ret) - return result + return _ffi.buffer(result, length)[:]