From 918f9933d7965d166014e6f1a562322f6bc7887c Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Sat, 20 Jul 2024 13:31:46 -0700 Subject: [PATCH 1/3] ignore some known source file placeholders --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index d6c4114..436e3ed 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,9 @@ ################################################################################ /.vs +/src/wolfcrypt/src/fips.c +/src/wolfcrypt/src/fips_test.c +/src/wolfcrypt/src/selftest.c +/src/wolfcrypt/src/wolfcrypt_first.c +/src/wolfcrypt/src/wolfcrypt_last.c +/src/wolfssl/wolfcrypt/fips.h From de00d3aebaf42789257cd4d72176a6357a7756cb Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Sat, 20 Jul 2024 13:33:07 -0700 Subject: [PATCH 2/3] Add PlatformIO files for v5.7.2 --- library.json.pio | 24 ++++++++++++++++++++++++ library.properties.pio | 9 +++++++++ 2 files changed, 33 insertions(+) create mode 100644 library.json.pio create mode 100644 library.properties.pio diff --git a/library.json.pio b/library.json.pio new file mode 100644 index 0000000..b5f5981 --- /dev/null +++ b/library.json.pio @@ -0,0 +1,24 @@ +{ + "name": "Arduino-wolfSSL", + "version": "5.7.2", + "description": "5.7.2 (Arduino-wolfSSL for PlatformIO) A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments.", + "keywords": "FIPS, DO-178, TLS, DTLS, DSA, PSK, X.509, RSA, ECC, AES, GCM, PQ, SHA, SHA256, 3DES, SHA512, MD5, ASN, CMAC, Blake, camellia, ChaCha, ChaCha20, DH, OCSP, ALPN, SNI, CRL, dilithium, ed25519, ed448, kdf, pkcs7, pkcs12, poly1305, Curve25519, sakke, SM, SM2, SM3, SM4, TFM, PKI, SRP, wolfcrypt, wolfssl, Post-quantum cryptography, Certificate management, SSL-TLS handshake, Session caching, Hash, Secure hashing, Public key infrastructure, Cryptanalysis, Lightweight cryptography, Hardware-based security", + "repository": { + "type": "git", + "url": "https://github.com/wolfSSL/Arduino-wolfSSL.git" + }, + "authors": [ + { + "name": "wolfSSL Inc.", + "email": "support@wolfssl.com", + "url": "https://www.wolfssl.com/contact/", + "maintainer": true + } + ], + "license": "GPL-2.0-only", + "homepage": "https://www.wolfssl.com/", + "dependencies": { + }, + "frameworks": "*", + "platforms": "*" +} diff --git a/library.properties.pio b/library.properties.pio new file mode 100644 index 0000000..9d1ac56 --- /dev/null +++ b/library.properties.pio @@ -0,0 +1,9 @@ +name=Arduino-wolfSSL +version=5.7.2 +author=wolfSSL Inc. +maintainer=wolfSSL inc +sentence=A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments. +paragraph=Manual: https://www.wolfssl.com/documentation/manuals/wolfssl/index.html. +category=Communication +url=https://www.wolfssl.com/ +architectures=* From 6adf61383f1ca9f6c69e8ee2ac8f05b587f23f5c Mon Sep 17 00:00:00 2001 From: gojimmypi Date: Sat, 20 Jul 2024 13:40:58 -0700 Subject: [PATCH 3/3] Publish wolfSSL v5.7.2 for Arduino --- ChangeLog.md | 107 + README | 156 +- README.md | 159 +- library.properties | 2 +- src/src/bio.c | 56 +- src/src/conf.c | 29 + src/src/crl.c | 59 +- src/src/dtls.c | 33 +- src/src/dtls13.c | 3 +- src/src/internal.c | 3000 +- src/src/keys.c | 50 +- src/src/ocsp.c | 117 +- src/src/pk.c | 2847 +- src/src/quic.c | 104 +- src/src/sniffer.c | 51 +- src/src/ssl.c | 43102 ++++++---------- src/src/ssl_asn1.c | 43 +- src/src/ssl_bn.c | 2 +- src/src/ssl_certman.c | 8 +- src/src/ssl_crypto.c | 12 +- src/src/ssl_load.c | 5831 +++ src/src/ssl_misc.c | 217 +- src/src/ssl_p7p12.c | 2123 + src/src/ssl_sess.c | 4567 ++ src/src/tls.c | 598 +- src/src/tls13.c | 1618 +- src/src/wolfio.c | 116 +- src/src/x509.c | 496 +- src/src/x509_str.c | 213 +- src/user_settings.h | 2 +- src/wolfcrypt/src/aes.c | 740 +- src/wolfcrypt/src/asn.c | 890 +- src/wolfcrypt/src/bio.c | 56 +- src/wolfcrypt/src/chacha.c | 4 + src/wolfcrypt/src/cmac.c | 27 +- src/wolfcrypt/src/coding.c | 2 +- src/wolfcrypt/src/cryptocb.c | 132 +- src/wolfcrypt/src/curve25519.c | 4 +- src/wolfcrypt/src/des3.c | 8 +- src/wolfcrypt/src/dh.c | 21 +- src/wolfcrypt/src/dilithium.c | 8314 ++- src/wolfcrypt/src/dsa.c | 34 +- src/wolfcrypt/src/ecc.c | 520 +- src/wolfcrypt/src/eccsi.c | 2 +- src/wolfcrypt/src/ed25519.c | 212 +- src/wolfcrypt/src/ed448.c | 156 +- src/wolfcrypt/src/error.c | 30 + src/wolfcrypt/src/evp.c | 164 +- src/wolfcrypt/src/ext_kyber.c | 12 +- src/wolfcrypt/src/ext_lms.c | 127 +- src/wolfcrypt/src/ext_xmss.c | 4 +- src/wolfcrypt/src/falcon.c | 19 +- src/wolfcrypt/src/fe_448.c | 21 +- src/wolfcrypt/src/fe_operations.c | 18 +- src/wolfcrypt/src/ge_448.c | 32 +- src/wolfcrypt/src/hash.c | 20 +- src/wolfcrypt/src/hmac.c | 83 +- src/wolfcrypt/src/kdf.c | 186 +- src/wolfcrypt/src/logging.c | 197 +- src/wolfcrypt/src/memory.c | 447 +- src/wolfcrypt/src/misc.c | 19 + src/wolfcrypt/src/pkcs12.c | 47 +- src/wolfcrypt/src/pkcs7.c | 658 +- src/wolfcrypt/src/poly1305.c | 28 +- src/wolfcrypt/src/port/Espressif/esp32_aes.c | 15 +- src/wolfcrypt/src/port/Espressif/esp32_mp.c | 59 +- src/wolfcrypt/src/port/Espressif/esp32_sha.c | 1024 +- src/wolfcrypt/src/port/Espressif/esp32_util.c | 146 +- .../src/port/Espressif/esp_sdk_mem_lib.c | 280 + .../src/port/Espressif/esp_sdk_time_lib.c | 442 + .../src/port/Espressif/esp_sdk_wifi_lib.c | 468 + src/wolfcrypt/src/port/atmel/atmel.c | 16 +- src/wolfcrypt/src/pwdbased.c | 50 + src/wolfcrypt/src/random.c | 98 +- src/wolfcrypt/src/rsa.c | 289 +- src/wolfcrypt/src/sakke.c | 32 +- src/wolfcrypt/src/sha.c | 18 +- src/wolfcrypt/src/sha256.c | 282 +- src/wolfcrypt/src/sha3.c | 152 +- src/wolfcrypt/src/sha512.c | 336 +- src/wolfcrypt/src/signature.c | 8 +- src/wolfcrypt/src/sp_cortexm.c | 1420 +- src/wolfcrypt/src/sp_int.c | 21 + src/wolfcrypt/src/sphincs.c | 5 +- src/wolfcrypt/src/srp.c | 10 +- src/wolfcrypt/src/wc_encrypt.c | 18 +- src/wolfcrypt/src/wc_kyber.c | 96 +- src/wolfcrypt/src/wc_kyber_poly.c | 711 +- src/wolfcrypt/src/wc_lms.c | 1123 +- src/wolfcrypt/src/wc_lms_impl.c | 3072 +- src/wolfcrypt/src/wc_pkcs11.c | 16 +- src/wolfcrypt/src/wc_port.c | 33 +- src/wolfcrypt/src/wc_xmss.c | 1648 +- src/wolfcrypt/src/wc_xmss_impl.c | 4317 +- src/wolfcrypt/src/wolfevent.c | 2 +- src/wolfcrypt/src/wolfmath.c | 5 +- src/wolfssl/bio.c | 56 +- src/wolfssl/certs_test.h | 3535 +- src/wolfssl/error-ssl.h | 7 + src/wolfssl/evp.c | 164 +- src/wolfssl/internal.h | 288 +- src/wolfssl/openssl/bn.h | 2 + src/wolfssl/openssl/ec.h | 47 +- src/wolfssl/openssl/evp.h | 1 + src/wolfssl/openssl/hmac.h | 4 +- src/wolfssl/openssl/opensslv.h | 1 + src/wolfssl/openssl/sha.h | 4 +- src/wolfssl/openssl/sha3.h | 5 + src/wolfssl/openssl/ssl.h | 35 +- src/wolfssl/openssl/tls1.h | 6 +- src/wolfssl/openssl/x509.h | 2 +- src/wolfssl/openssl/x509v3.h | 2 +- src/wolfssl/ssl.h | 388 +- src/wolfssl/test.h | 85 +- src/wolfssl/version.h | 4 +- src/wolfssl/wolfcrypt/aes.h | 75 +- src/wolfssl/wolfcrypt/asn.h | 89 +- src/wolfssl/wolfcrypt/asn_public.h | 14 +- src/wolfssl/wolfcrypt/chacha.h | 2 +- src/wolfssl/wolfcrypt/cmac.h | 8 +- src/wolfssl/wolfcrypt/cryptocb.h | 27 +- src/wolfssl/wolfcrypt/dh.h | 8 +- src/wolfssl/wolfcrypt/dilithium.h | 680 +- src/wolfssl/wolfcrypt/ecc.h | 77 +- src/wolfssl/wolfcrypt/ed25519.h | 14 +- src/wolfssl/wolfcrypt/ed448.h | 13 +- src/wolfssl/wolfcrypt/error-crypt.h | 33 +- src/wolfssl/wolfcrypt/ext_lms.h | 4 +- src/wolfssl/wolfcrypt/ext_xmss.h | 4 +- src/wolfssl/wolfcrypt/fe_operations.h | 4 +- src/wolfssl/wolfcrypt/fips_test.h | 56 +- src/wolfssl/wolfcrypt/hmac.h | 20 +- src/wolfssl/wolfcrypt/kdf.h | 19 + src/wolfssl/wolfcrypt/kyber.h | 8 +- src/wolfssl/wolfcrypt/lms.h | 57 +- src/wolfssl/wolfcrypt/logging.h | 19 + src/wolfssl/wolfcrypt/mem_track.h | 45 +- src/wolfssl/wolfcrypt/memory.h | 111 +- src/wolfssl/wolfcrypt/misc.h | 2 + src/wolfssl/wolfcrypt/pkcs12.h | 7 +- src/wolfssl/wolfcrypt/poly1305.h | 11 +- .../wolfcrypt/port/Espressif/esp-sdk-lib.h | 229 + .../wolfcrypt/port/Espressif/esp32-crypt.h | 163 +- src/wolfssl/wolfcrypt/pwdbased.h | 4 + src/wolfssl/wolfcrypt/random.h | 12 +- src/wolfssl/wolfcrypt/rsa.h | 38 +- src/wolfssl/wolfcrypt/settings.h | 237 +- src/wolfssl/wolfcrypt/sha.h | 8 +- src/wolfssl/wolfcrypt/sha256.h | 18 +- src/wolfssl/wolfcrypt/sha3.h | 23 +- src/wolfssl/wolfcrypt/sha512.h | 15 +- src/wolfssl/wolfcrypt/sp_int.h | 10 +- src/wolfssl/wolfcrypt/types.h | 44 +- src/wolfssl/wolfcrypt/wc_kyber.h | 4 +- src/wolfssl/wolfcrypt/wc_lms.h | 449 +- src/wolfssl/wolfcrypt/wc_port.h | 38 +- src/wolfssl/wolfcrypt/wc_xmss.h | 264 +- src/wolfssl/wolfcrypt/xmss.h | 8 +- src/wolfssl/wolfio.h | 20 +- 159 files changed, 67228 insertions(+), 35566 deletions(-) create mode 100644 src/src/ssl_load.c create mode 100644 src/src/ssl_p7p12.c create mode 100644 src/src/ssl_sess.c create mode 100644 src/wolfcrypt/src/port/Espressif/esp_sdk_mem_lib.c create mode 100644 src/wolfcrypt/src/port/Espressif/esp_sdk_time_lib.c create mode 100644 src/wolfcrypt/src/port/Espressif/esp_sdk_wifi_lib.c create mode 100644 src/wolfssl/wolfcrypt/port/Espressif/esp-sdk-lib.h diff --git a/ChangeLog.md b/ChangeLog.md index c3b2475..01fca46 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,110 @@ +# wolfSSL Release 5.7.2 (July 08, 2024) + +Release 5.7.2 has been developed according to wolfSSL's development and QA +process (see link below) and successfully passed the quality criteria. +https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance + +NOTE: * --enable-heapmath is being deprecated and will be removed by end of 2024 + +## Vulnerabilities +* [Medium] CVE-2024-1544 +Potential ECDSA nonce side channel attack in versions of wolfSSL before 5.6.6 with wc_ecc_sign_hash calls. Generating the ECDSA nonce k samples a random number r and then truncates this randomness with a modular reduction mod n where n is the order of the elliptic curve. Analyzing the division through a control-flow revealing side-channel reveals a bias in the most significant bits of k. Depending on the curve this is either a negligible bias or a significant bias large enough to reconstruct k with lattice reduction methods. Thanks to Luca Wilke, Florian Sieck and Thomas Eisenbarth (University of Lübeck) for reporting the vulnerability. Details will appear in the proceedings of CCS 24. +Fixed https://github.com/wolfSSL/wolfssl/pull/7020 + + +* [Medium] CVE-2024-5288 +A private key blinding operation, enabled by defining the macro WOLFSSL_BLIND_PRIVATE_KEY, was added to mitigate a potential row hammer attack on ECC operations. If performing ECC private key operations in an environment where a malicious user could gain fine control over the device and perform row hammer style attacks it is recommended to update the version of wolfSSL used and to build with WOLFSSL_BLIND_PRIVATE_KEY defined. Thanks to Kemal Derya, M. Caner Tol, Berk Sunar for the report (Vernam Applied Cryptography and Cybersecurity Lab at Worcester Polytechnic Institute) +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7416 + + +* [Low] When parsing a provided maliciously crafted certificate directly using wolfSSL API, outside of a TLS connection, a certificate with an excessively large number of extensions could lead to a potential DoS. There are existing sanity checks during a TLS handshake with wolfSSL which mitigate this issue. Thanks to Bing Shi for the report. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7597 + +* [Low] CVE-2024-5991 +In the function MatchDomainName(), input param str is treated as a NULL terminated string despite being user provided and unchecked. Specifically, the Openssl compatibility function X509_check_host() takes in a pointer and length to check against, with no requirements that it be NULL terminated. While calling without a NULL terminated string is very uncommon, it is still technically allowed. If a caller was attempting to do a name check on a non*NULL terminated buffer, the code would read beyond the bounds of the input array until it found a NULL terminator. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7604 + +* [Medium] CVE-2024-5814 +A malicious TLS1.2 server can force a TLS1.3 client with downgrade capability to use a ciphersuite that it did not agree to and achieve a successful connection. This is because, aside from the extensions, the client was skipping fully parsing the server hello when downgrading from TLS 1.3. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7619 + +* [Medium] OCSP stapling version 2 response verification bypass issue when a crafted response of length 0 is received. Found with internal testing. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702 + +* [Medium] OCSP stapling version 2 revocation bypass with a retry of a TLS connection attempt. A revoked CA certificate could incorrectly be loaded into the trusted signers list and used in a repeat connection attempt. Found with internal testing. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702 + + +## New Feature Additions +* Added Dilithium/ML-DSA: Implementation of ML-DSA-44/65/87 (PR 7622) +* AES RISC-V 64-bit ASM: ECB/CBC/CTR/GCM/CCM (PR 7569) +* Added CUDA support for AES encryption (PR 7436) +* Added support for gRPC (PR 7445) +* Added function wc_RsaPrivateKeyDecodeRaw to import raw RSA private keys (PR 7608) +* Added crypto callback for SHA-3 (PR 7670) +* Support for Infineon Modus Toolbox with wolfSSL (PR 7369) +* Allow user to send a user_canceled alert by calling wolfSSL_SendUserCanceled (PR 7590) +* C# wrapper SNI support added (PR 7610) +* Quantum-safe algorithm support added to the Linux kernel module (PR 7574) +* Support for NIST 800-56C Option 1 KDF, using the macro WC_KDF_NIST_SP_800_56C added (PR 7589) +* AES-XTS streaming mode added, along with hardware acceleration and kernel module use (PR 7522, 7560, 7424) +* PlatformIO FreeRTOS with ESP build and addition of benchmark and test example applications (PR 7528, 7413, 7559, 7542) + + +## Enhancements and Optimizations +* Expanded STM32 AES hardware acceleration support for use with STM32H5 (PR 7578) +* Adjusted wc_xmss and wc_lms settings to support use with wolfBoot (PR 7393) +* Added the --enable-rpk option to autotools build for using raw public key support (PR 7379) +* SHA-3 Thumb2, ARM32 assembly implementation added (PR 7667) +* Improvements to RSA padding to expose Pad/Unpad APIs (PR 7612) +* Updates and API additions for supporting socat version 1.8.0.0 (PR 7594) +* cmake build improvements, expanding build options with SINGLE_THREADED and post-quantum algorithms, adjusting the generation of options.h file and using “yes;no” boolean instead of strings (PR 7611, 7546, 7479, 7480, 7380) +* Improvements for Renesas RZ support (PR 7474) +* Improvements to dual algorithm certificates for post-quantum keys (PR 7286) +* Added wolfSSL_SessionIsSetup so the user can check if a session ticket has been sent by the server (PR 7430) +* hostap updates: Implement PACs for EAP-FAST and filter cipher list on TLS version change (PR 7446) +* Changed subject name comparison to match different upper and lower cases (PR 7420) +* Support for DTLS 1.3 downgrade when using PSK (PR 7367) +* Update to static memory build for more generic memory pools used (PR 7418) +* Improved performance of Kyber C implementation (PR 7654) +* Support for ECC_CACHE_CURVE with no malloc (PR 7490) +* Added the configure option --enable-debug-trace-errcodes (macro WOLFSSL_DEBUG_TRACE_ERROR_CODES) which enables more debug tracking of error code values (PR 7634) +* Enhanced wc_MakeRsaKey and wc_RsaKeyToDer to work with WOLFSSL_NO_MALLOC (PR 7362) +* Improvements to assembly implementations of ChaCha20 and Poly1305 ASM for use with MSVC (PR 7319) +* Cortex-M inline assembly labels with unique number appended (PR 7649) +* Added secret logging callback to TLS <= 1.2, enabled with the macro HAVE_SECRET_CALLBACK (PR 7372) +* Made wc_RNG_DRBG_Reseed() a public wolfCrypt API (PR 7386) +* Enabled DES3 support without the DES3 ciphers. To re-enable DES3 cipher suites, use the configure flag --enable-des3-tls-suites (PR 7315) +* Added stubs required for latest nginx (1.25.5) (PR 7449) +* Added option for using a custom salt with the function wc_ecc_ctx_set_own_salt (PR 7552) +* Added PQ files for Windows (PR 7419) +* Enhancements to static memory feature, adding the option for a global heap hint (PR 7478) and build options for a lean or debug setting, enabled with --enable-staticmemory=small or --enable-staticmemory=debug (PR 7597) +* Updated --enable-jni to define SESSION_CERTS for wolfJSSE (PR 7557) +* Exposed DTLS in Ada wrapper and updated examples (PR 7397) +* Added additional minimum TLS extension size sanity checks (PR 7602) +* ESP improvements: updating the examples and libraries, updates for Apple HomeKit SHA/SRP, and fix for endianness with SHA512 software fallback (PR 7607, 7392, 7505, 7535) +* Made the wc_CheckCertSigPubKey API publicly available with the define of the macro WOLFSSL_SMALL_CERT_VERIFY (PR 7599) +* Added an alpha/preview of additional FIPS 140-3 full submission, bringing additional algorithms such as SRTP-KDF, AES-XTS, GCM streaming, AES-CFB, ED25519, and ED448 into the FIPS module boundary (PR 7295) +* XCODE support for v5.2.3 of the FIPS module (PR 7140) +* Expanded OpenSSL compatibility layer and added EC_POINT_hex2point (PR 7191) + +## Fixes +* Fixed the NXP MMCAU HW acceleration for SHA-256 (PR 7389) +* Fixed AES-CFB1 encrypt/decrypt on size (8*x-1) bits (PR 7431) +* Fixed use of %rip with SHA-256 x64 assembly (PR 7409) +* Fixed OCSP response message build for DTLS (PR 7671) +* Handled edge case in wc_ecc_mulmod() with zero (PR 7532) +* Fixed RPK (Raw Public Key) to follow certificate use correctly (PR 7375) +* Added sanity check on record header with QUIC use (PR 7638) +* Added sanity check for empty directory strings in X.509 when parsing (PR 7669) +* Added sanity check on non-conforming serial number of 0 in certificates being parsed (PR 7625) +* Fixed wolfSSL_CTX_set1_sigalgs_list() to make the TLS connection conform to the selected sig hash algorithm (PR 7693) +* Various fixes for dual algorithm certificates including small stack use and support for Certificate Signing Requests (PR 7577) +* Added sanity check for critical policy extension when wolfSSL is built without policy extension support enabled (PR 7388) +* Added sanity check that the ed25519 signature is smaller than the order (PR 7513) +* Fixed Segger emNet to handle non-blocking want read/want write (PR 7581) + + # wolfSSL Release 5.7.0 (Mar 20, 2024) Release 5.7.0 has been developed according to wolfSSL's development and QA diff --git a/README b/README index 72d5cb3..3fa99a5 100644 --- a/README +++ b/README @@ -70,99 +70,113 @@ should be used for the enum name. *** end Notes *** -# wolfSSL Release 5.7.0 (Mar 20, 2024) +# wolfSSL Release 5.7.2 (July 08, 2024) -Release 5.7.0 has been developed according to wolfSSL's development and QA +Release 5.7.2 has been developed according to wolfSSL's development and QA process (see link below) and successfully passed the quality criteria. https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance NOTE: * --enable-heapmath is being deprecated and will be removed by end of 2024 -NOTE: In future releases, --enable-des3 (which is disabled by default) will be insufficient in itself to enable DES3 in TLS cipher suites. A new option, --enable-des3-tls-suites, will need to be supplied in addition. This option should only be used in backward compatibility scenarios, as it is inherently insecure. - -NOTE: This release switches the default ASN.1 parser to the new ASN template code. If the original ASN.1 code is preferred define `WOLFSSL_ASN_ORIGINAL` to use it. See PR #7199. - - ## Vulnerabilities -* [High] CVE-2024-0901 Potential denial of service and out of bounds read. Affects TLS 1.3 on the server side when accepting a connection from a malicious TLS 1.3 client. If using TLS 1.3 on the server side it is recommended to update the version of wolfSSL used. Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7099 +* [Medium] CVE-2024-1544 +Potential ECDSA nonce side channel attack in versions of wolfSSL before 5.6.6 with wc_ecc_sign_hash calls. Generating the ECDSA nonce k samples a random number r and then truncates this randomness with a modular reduction mod n where n is the order of the elliptic curve. Analyzing the division through a control-flow revealing side-channel reveals a bias in the most significant bits of k. Depending on the curve this is either a negligible bias or a significant bias large enough to reconstruct k with lattice reduction methods. Thanks to Luca Wilke, Florian Sieck and Thomas Eisenbarth (University of Lübeck) for reporting the vulnerability. Details will appear in the proceedings of CCS 24. +Fixed https://github.com/wolfSSL/wolfssl/pull/7020 -* [Med] CVE-2024-1545 Fault Injection vulnerability in RsaPrivateDecryption function that potentially allows an attacker that has access to the same system with a victims process to perform a Rowhammer fault injection. Thanks to Junkai Liang, Zhi Zhang, Xin Zhang, Qingni Shen for the report (Peking University, The University of Western Australia)." -Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7167 +* [Medium] CVE-2024-5288 +A private key blinding operation, enabled by defining the macro WOLFSSL_BLIND_PRIVATE_KEY, was added to mitigate a potential row hammer attack on ECC operations. If performing ECC private key operations in an environment where a malicious user could gain fine control over the device and perform row hammer style attacks it is recommended to update the version of wolfSSL used and to build with WOLFSSL_BLIND_PRIVATE_KEY defined. Thanks to Kemal Derya, M. Caner Tol, Berk Sunar for the report (Vernam Applied Cryptography and Cybersecurity Lab at Worcester Polytechnic Institute) +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7416 -* [Med] Fault injection attack with EdDSA signature operations. This affects ed25519 sign operations where the system could be susceptible to Rowhammer attacks. Thanks to Junkai Liang, Zhi Zhang, Xin Zhang, Qingni Shen for the report (Peking University, The University of Western Australia). -Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7212 +* [Low] When parsing a provided maliciously crafted certificate directly using wolfSSL API, outside of a TLS connection, a certificate with an excessively large number of extensions could lead to a potential DoS. There are existing sanity checks during a TLS handshake with wolfSSL which mitigate this issue. Thanks to Bing Shi for the report. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7597 +* [Low] CVE-2024-5991 +In the function MatchDomainName(), input param str is treated as a NULL terminated string despite being user provided and unchecked. Specifically, the Openssl compatibility function X509_check_host() takes in a pointer and length to check against, with no requirements that it be NULL terminated. While calling without a NULL terminated string is very uncommon, it is still technically allowed. If a caller was attempting to do a name check on a non*NULL terminated buffer, the code would read beyond the bounds of the input array until it found a NULL terminator. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7604 -## New Feature Additions - -* Added --enable-experimental configure flag to gate out features that are currently experimental. Now liboqs, kyber, lms, xmss, and dual-alg-certs require the --enable-experimental flag. +* [Medium] CVE-2024-5814 +A malicious TLS1.2 server can force a TLS1.3 client with downgrade capability to use a ciphersuite that it did not agree to and achieve a successful connection. This is because, aside from the extensions, the client was skipping fully parsing the server hello when downgrading from TLS 1.3. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7619 -### POST QUANTUM SUPPORT ADDITIONS -* Experimental framework for using wolfSSL’s XMSS implementation (PR 7161) -* Experimental framework for using wolfSSL’s LMS implementation (PR 7283) -* Experimental wolfSSL Kyber implementation and assembly optimizations, enabled with --enable-experimental --enable-kyber (PR 7318) -* Experimental support for post quantum dual key/signature certificates. A few known issues and sanitizer checks are in progress with this feature. Enabled with the configure flags --enable-experimental --enable-dual-alg-certs (PR 7112) -* CryptoCb support for PQC algorithms (PR 7110) +* [Medium] OCSP stapling version 2 response verification bypass issue when a crafted response of length 0 is received. Found with internal testing. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702 -### OTHER FEATURE ADDITIONS -* The Linux kernel module now supports registration of AES-GCM, AES-XTS, AES-CBC, and AES-CFB with the kernel cryptosystem through the new --enable-linuxkm-lkcapi-register option, enabling automatic use of wolfCrypt implementations by the dm-crypt/luks and ESP subsystems. In particular, wolfCrypt AES-XTS with –enable-aesni is faster than the native kernel implementation. -* CryptoCb hook to one-shot CMAC functions (PR 7059) -* BER content streaming support for PKCS7_VerifySignedData and sign/encrypt operations (PR 6961 & 7184) -* IoT-Safe SHA-384 and SHA-512 support (PR 7176) -* I/O callbacks for content and output with PKCS7 bundle sign/encrypt to reduce peak memory usage (PR 7272) -* Microchip PIC24 support and example project (PR 7151) -* AutoSAR shim layer for RNG, SHA256, and AES (PR 7296) -* wolfSSL_CertManagerUnloadIntermediateCerts API to clear intermediate certs added to certificate store (PR 7245) -* Implement SSL_get_peer_signature_nid and SSL_get_peer_signature_type_nid (PR 7236) +* [Medium] OCSP stapling version 2 revocation bypass with a retry of a TLS connection attempt. A revoked CA certificate could incorrectly be loaded into the trusted signers list and used in a repeat connection attempt. Found with internal testing. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702 -## Enhancements and Optimizations +## New Feature Additions +* Added Dilithium/ML-DSA: Implementation of ML-DSA-44/65/87 (PR 7622) +* AES RISC-V 64-bit ASM: ECB/CBC/CTR/GCM/CCM (PR 7569) +* Added CUDA support for AES encryption (PR 7436) +* Added support for gRPC (PR 7445) +* Added function wc_RsaPrivateKeyDecodeRaw to import raw RSA private keys (PR 7608) +* Added crypto callback for SHA-3 (PR 7670) +* Support for Infineon Modus Toolbox with wolfSSL (PR 7369) +* Allow user to send a user_canceled alert by calling wolfSSL_SendUserCanceled (PR 7590) +* C# wrapper SNI support added (PR 7610) +* Quantum-safe algorithm support added to the Linux kernel module (PR 7574) +* Support for NIST 800-56C Option 1 KDF, using the macro WC_KDF_NIST_SP_800_56C added (PR 7589) +* AES-XTS streaming mode added, along with hardware acceleration and kernel module use (PR 7522, 7560, 7424) +* PlatformIO FreeRTOS with ESP build and addition of benchmark and test example applications (PR 7528, 7413, 7559, 7542) -* Remove obsolete user-crypto functionality and Intel IPP support (PR 7097) -* Support for RSA-PSS signatures with CRL use (PR 7119) -* Enhancement for AES-GCM use with Xilsecure on Microblaze (PR 7051) -* Support for crypto cb only build with ECC and NXP CAAM (PR 7269) -* Improve liboqs integration adding locking and init/cleanup functions (PR 7026) -* Prevent memory access before clientSession->serverRow and clientSession->serverIdx are sanitized (PR 7096) -* Enhancements to reproducible build (PR 7267) -* Update Arduino example TLS Client/Server and improve support for ESP32 (PR 7304 & 7177) -* XC32 compiler version 4.x compatibility (PR 7128) -* Porting for build on PlayStation 3 and 4 (PR 7072) -* Improvements for Espressif use; SHA HW/SW selection and use on ESP32-C2/ESP8684, wolfSSL_NewThread() type, component cmake fix, and update TLS client example for ESP8266 (PR 7081, 7173, 7077, 7148, 7240) -* Allow crypto callbacks with SHA-1 HW (PR 7087) -* Update OpenSSH port to version 9.6p1(PR 7203) -* ARM Thumb2 enhancements, AES-GCM support for GCM_SMALL, alignment fix on key, fix for ASM clobber list (PR 7291,7301,7221) -* Expand heap hint support for static memory build with more x509 functions (PR 7136) -* Improving ARMv8 ChaCha20 ASM (alignment) (PR 7182) -* Unknown extension callback wolfSSL_CertManagerSetUnknownExtCallback added to CertManager (PR 7194) -* Implement wc_rng_new_ex for use with devID’s with crypto callback (PR 7271) -* Allow reading 0-RTT data after writing 0.5-RTT data (PR 7102) -* Send alert on bad PSK binder error (PR 7235) -* Enhancements to CMake build files for use with cross compiling (PR 7188) +## Enhancements and Optimizations +* Expanded STM32 AES hardware acceleration support for use with STM32H5 (PR 7578) +* Adjusted wc_xmss and wc_lms settings to support use with wolfBoot (PR 7393) +* Added the --enable-rpk option to autotools build for using raw public key support (PR 7379) +* SHA-3 Thumb2, ARM32 assembly implementation added (PR 7667) +* Improvements to RSA padding to expose Pad/Unpad APIs (PR 7612) +* Updates and API additions for supporting socat version 1.8.0.0 (PR 7594) +* cmake build improvements, expanding build options with SINGLE_THREADED and post-quantum algorithms, adjusting the generation of options.h file and using “yes;no” boolean instead of strings (PR 7611, 7546, 7479, 7480, 7380) +* Improvements for Renesas RZ support (PR 7474) +* Improvements to dual algorithm certificates for post-quantum keys (PR 7286) +* Added wolfSSL_SessionIsSetup so the user can check if a session ticket has been sent by the server (PR 7430) +* hostap updates: Implement PACs for EAP-FAST and filter cipher list on TLS version change (PR 7446) +* Changed subject name comparison to match different upper and lower cases (PR 7420) +* Support for DTLS 1.3 downgrade when using PSK (PR 7367) +* Update to static memory build for more generic memory pools used (PR 7418) +* Improved performance of Kyber C implementation (PR 7654) +* Support for ECC_CACHE_CURVE with no malloc (PR 7490) +* Added the configure option --enable-debug-trace-errcodes (macro WOLFSSL_DEBUG_TRACE_ERROR_CODES) which enables more debug tracking of error code values (PR 7634) +* Enhanced wc_MakeRsaKey and wc_RsaKeyToDer to work with WOLFSSL_NO_MALLOC (PR 7362) +* Improvements to assembly implementations of ChaCha20 and Poly1305 ASM for use with MSVC (PR 7319) +* Cortex-M inline assembly labels with unique number appended (PR 7649) +* Added secret logging callback to TLS <= 1.2, enabled with the macro HAVE_SECRET_CALLBACK (PR 7372) +* Made wc_RNG_DRBG_Reseed() a public wolfCrypt API (PR 7386) +* Enabled DES3 support without the DES3 ciphers. To re-enable DES3 cipher suites, use the configure flag --enable-des3-tls-suites (PR 7315) +* Added stubs required for latest nginx (1.25.5) (PR 7449) +* Added option for using a custom salt with the function wc_ecc_ctx_set_own_salt (PR 7552) +* Added PQ files for Windows (PR 7419) +* Enhancements to static memory feature, adding the option for a global heap hint (PR 7478) and build options for a lean or debug setting, enabled with --enable-staticmemory=small or --enable-staticmemory=debug (PR 7597) +* Updated --enable-jni to define SESSION_CERTS for wolfJSSE (PR 7557) +* Exposed DTLS in Ada wrapper and updated examples (PR 7397) +* Added additional minimum TLS extension size sanity checks (PR 7602) +* ESP improvements: updating the examples and libraries, updates for Apple HomeKit SHA/SRP, and fix for endianness with SHA512 software fallback (PR 7607, 7392, 7505, 7535) +* Made the wc_CheckCertSigPubKey API publicly available with the define of the macro WOLFSSL_SMALL_CERT_VERIFY (PR 7599) +* Added an alpha/preview of additional FIPS 140-3 full submission, bringing additional algorithms such as SRTP-KDF, AES-XTS, GCM streaming, AES-CFB, ED25519, and ED448 into the FIPS module boundary (PR 7295) +* XCODE support for v5.2.3 of the FIPS module (PR 7140) +* Expanded OpenSSL compatibility layer and added EC_POINT_hex2point (PR 7191) ## Fixes +* Fixed the NXP MMCAU HW acceleration for SHA-256 (PR 7389) +* Fixed AES-CFB1 encrypt/decrypt on size (8*x-1) bits (PR 7431) +* Fixed use of %rip with SHA-256 x64 assembly (PR 7409) +* Fixed OCSP response message build for DTLS (PR 7671) +* Handled edge case in wc_ecc_mulmod() with zero (PR 7532) +* Fixed RPK (Raw Public Key) to follow certificate use correctly (PR 7375) +* Added sanity check on record header with QUIC use (PR 7638) +* Added sanity check for empty directory strings in X.509 when parsing (PR 7669) +* Added sanity check on non-conforming serial number of 0 in certificates being parsed (PR 7625) +* Fixed wolfSSL_CTX_set1_sigalgs_list() to make the TLS connection conform to the selected sig hash algorithm (PR 7693) +* Various fixes for dual algorithm certificates including small stack use and support for Certificate Signing Requests (PR 7577) +* Added sanity check for critical policy extension when wolfSSL is built without policy extension support enabled (PR 7388) +* Added sanity check that the ed25519 signature is smaller than the order (PR 7513) +* Fixed Segger emNet to handle non-blocking want read/want write (PR 7581) + -* Fix for checking result of MAC verify when no AAD is used with AES-GCM and Xilinx Xilsecure (PR 7051) -* Fix for Aria sign use (PR 7082) -* Fix for invalid `dh_ffdhe_test` test case using Intel QuickAssist (PR 7085) -* Fixes for TI AES and SHA on TM4C with HW acceleration and add full AES GCM and CCM support with TLS (PR 7018) -* Fixes for STM32 PKA use with ECC (PR 7098) -* Fixes for TLS 1.3 with crypto callbacks to offload KDF / HMAC operation (PR 7070) -* Fix include path for FSP 3.5 on Renesas RA6M4 (PR 7101) -* Siphash x64 asm fix for use with older compilers (PR 7299) -* Fix for SGX build with SP (PR 7308) -* Fix to Make it mandatory that the cookie is sent back in new ClientHello when seen in a HelloRetryRequest with (PR 7190) -* Fix for wrap around behavior with BIO pairs (PR 7169) -* OCSP fixes for parsing of response correctly when there was a revocation reason and returning correct error value with date checks (PR 7241 & 7255) -* Fix build with `NO_STDIO_FILESYSTEM` and improve checks for `XGETENV` (PR 7150) -* Fix for DTLS sequence number and cookie when downgrading DTLS version (PR 7214) -* Fix for write_dup use with chacha-poly cipher suites (PR 7206) -* Fix for multiple handshake messages in one record failing with OUT_OF_ORDER_E when downgrading from TLS 1.3 to TLS 1.2 (PR 7141) -* Fix for AES ECB build with Thumb and alignment (PR 7094) -* Fix for negotiate handshake until the end in wolfSSL_read/wolfSSL_write if hitting an edge case with want read/write (PR 7237) For additional vulnerability information visit the vulnerability page at: https://www.wolfssl.com/docs/security-vulnerabilities/ diff --git a/README.md b/README.md index 9b2498f..f6b00c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Arduino wolfSSL Library -This library is restructured from [wolfSSL](https://github.com/wolfSSL/wolfssl/) Release 5.7.0 for the Arduino platform. +This library is restructured from [wolfSSL](https://github.com/wolfSSL/wolfssl/) Release 5.7.2 for the Arduino platform. The Official wolfSSL Arduino Library is found in [The Library Manager index](http://downloads.arduino.cc/libraries/library_index.json). @@ -10,6 +10,8 @@ See the [Arduino-wolfSSL logs](https://downloads.arduino.cc/libraries/logs/githu The first Official wolfSSL Arduino Library is `5.6.6-Arduino.1`: a slightly modified, post [release 5.6.6](https://github.com/wolfSSL/wolfssl/releases/tag/v5.6.6-stable) version update. +The next Official wolfSSL Arduino Library is [5.7.0](https://github.com/wolfSSL/wolfssl/releases/tag/v5.7.0-stable) + See other [wolfSSL releases versions](https://github.com/wolfSSL/wolfssl/releases). The `./wolfssl-arduino.sh INSTALL` [script](https://github.com/wolfSSL/wolfssl/tree/master/IDE/ARDUINO) can be used to install specific GitHub versions as needed. # wolfSSL Embedded SSL/TLS Library @@ -88,98 +90,111 @@ single call hash function. Instead the name `WC_SHA`, `WC_SHA256`, `WC_SHA384` a `WC_SHA512` should be used for the enum name. -# wolfSSL Release 5.7.0 (Mar 20, 2024) +# wolfSSL Release 5.7.2 (July 08, 2024) -Release 5.7.0 has been developed according to wolfSSL's development and QA +Release 5.7.2 has been developed according to wolfSSL's development and QA process (see link below) and successfully passed the quality criteria. https://www.wolfssl.com/about/wolfssl-software-development-process-quality-assurance NOTE: * --enable-heapmath is being deprecated and will be removed by end of 2024 -NOTE: In future releases, --enable-des3 (which is disabled by default) will be insufficient in itself to enable DES3 in TLS cipher suites. A new option, --enable-des3-tls-suites, will need to be supplied in addition. This option should only be used in backward compatibility scenarios, as it is inherently insecure. - -NOTE: This release switches the default ASN.1 parser to the new ASN template code. If the original ASN.1 code is preferred define `WOLFSSL_ASN_ORIGINAL` to use it. See PR #7199. - ## Vulnerabilities -* [High] CVE-2024-0901 Potential denial of service and out of bounds read. Affects TLS 1.3 on the server side when accepting a connection from a malicious TLS 1.3 client. If using TLS 1.3 on the server side it is recommended to update the version of wolfSSL used. Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7099 +* [Medium] CVE-2024-1544 +Potential ECDSA nonce side channel attack in versions of wolfSSL before 5.6.6 with wc_ecc_sign_hash calls. Generating the ECDSA nonce k samples a random number r and then truncates this randomness with a modular reduction mod n where n is the order of the elliptic curve. Analyzing the division through a control-flow revealing side-channel reveals a bias in the most significant bits of k. Depending on the curve this is either a negligible bias or a significant bias large enough to reconstruct k with lattice reduction methods. Thanks to Luca Wilke, Florian Sieck and Thomas Eisenbarth (University of Lübeck) for reporting the vulnerability. Details will appear in the proceedings of CCS 24. +Fixed https://github.com/wolfSSL/wolfssl/pull/7020 -* [Med] CVE-2024-1545 Fault Injection vulnerability in RsaPrivateDecryption function that potentially allows an attacker that has access to the same system with a victims process to perform a Rowhammer fault injection. Thanks to Junkai Liang, Zhi Zhang, Xin Zhang, Qingni Shen for the report (Peking University, The University of Western Australia)." -Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7167 +* [Medium] CVE-2024-5288 +A private key blinding operation, enabled by defining the macro WOLFSSL_BLIND_PRIVATE_KEY, was added to mitigate a potential row hammer attack on ECC operations. If performing ECC private key operations in an environment where a malicious user could gain fine control over the device and perform row hammer style attacks it is recommended to update the version of wolfSSL used and to build with WOLFSSL_BLIND_PRIVATE_KEY defined. Thanks to Kemal Derya, M. Caner Tol, Berk Sunar for the report (Vernam Applied Cryptography and Cybersecurity Lab at Worcester Polytechnic Institute) +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7416 -* [Med] Fault injection attack with EdDSA signature operations. This affects ed25519 sign operations where the system could be susceptible to Rowhammer attacks. Thanks to Junkai Liang, Zhi Zhang, Xin Zhang, Qingni Shen for the report (Peking University, The University of Western Australia). -Fixed in this GitHub pull request https://github.com/wolfSSL/wolfssl/pull/7212 +* [Low] When parsing a provided maliciously crafted certificate directly using wolfSSL API, outside of a TLS connection, a certificate with an excessively large number of extensions could lead to a potential DoS. There are existing sanity checks during a TLS handshake with wolfSSL which mitigate this issue. Thanks to Bing Shi for the report. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7597 +* [Low] CVE-2024-5991 +In the function MatchDomainName(), input param str is treated as a NULL terminated string despite being user provided and unchecked. Specifically, the Openssl compatibility function X509_check_host() takes in a pointer and length to check against, with no requirements that it be NULL terminated. While calling without a NULL terminated string is very uncommon, it is still technically allowed. If a caller was attempting to do a name check on a non*NULL terminated buffer, the code would read beyond the bounds of the input array until it found a NULL terminator. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7604 -## New Feature Additions - -* Added --enable-experimental configure flag to gate out features that are currently experimental. Now liboqs, kyber, lms, xmss, and dual-alg-certs require the --enable-experimental flag. +* [Medium] CVE-2024-5814 +A malicious TLS1.2 server can force a TLS1.3 client with downgrade capability to use a ciphersuite that it did not agree to and achieve a successful connection. This is because, aside from the extensions, the client was skipping fully parsing the server hello when downgrading from TLS 1.3. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7619 -### POST QUANTUM SUPPORT ADDITIONS -* Experimental framework for using wolfSSL’s XMSS implementation (PR 7161) -* Experimental framework for using wolfSSL’s LMS implementation (PR 7283) -* Experimental wolfSSL Kyber implementation and assembly optimizations, enabled with --enable-experimental --enable-kyber (PR 7318) -* Experimental support for post quantum dual key/signature certificates. A few known issues and sanitizer checks are in progress with this feature. Enabled with the configure flags --enable-experimental --enable-dual-alg-certs (PR 7112) -* CryptoCb support for PQC algorithms (PR 7110) +* [Medium] OCSP stapling version 2 response verification bypass issue when a crafted response of length 0 is received. Found with internal testing. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702 -### OTHER FEATURE ADDITIONS -* The Linux kernel module now supports registration of AES-GCM, AES-XTS, AES-CBC, and AES-CFB with the kernel cryptosystem through the new --enable-linuxkm-lkcapi-register option, enabling automatic use of wolfCrypt implementations by the dm-crypt/luks and ESP subsystems. In particular, wolfCrypt AES-XTS with –enable-aesni is faster than the native kernel implementation. -* CryptoCb hook to one-shot CMAC functions (PR 7059) -* BER content streaming support for PKCS7_VerifySignedData and sign/encrypt operations (PR 6961 & 7184) -* IoT-Safe SHA-384 and SHA-512 support (PR 7176) -* I/O callbacks for content and output with PKCS7 bundle sign/encrypt to reduce peak memory usage (PR 7272) -* Microchip PIC24 support and example project (PR 7151) -* AutoSAR shim layer for RNG, SHA256, and AES (PR 7296) -* wolfSSL_CertManagerUnloadIntermediateCerts API to clear intermediate certs added to certificate store (PR 7245) -* Implement SSL_get_peer_signature_nid and SSL_get_peer_signature_type_nid (PR 7236) +* [Medium] OCSP stapling version 2 revocation bypass with a retry of a TLS connection attempt. A revoked CA certificate could incorrectly be loaded into the trusted signers list and used in a repeat connection attempt. Found with internal testing. +Fixed in github pull request https://github.com/wolfSSL/wolfssl/pull/7702 -## Enhancements and Optimizations +## New Feature Additions +* Added Dilithium/ML-DSA: Implementation of ML-DSA-44/65/87 (PR 7622) +* AES RISC-V 64-bit ASM: ECB/CBC/CTR/GCM/CCM (PR 7569) +* Added CUDA support for AES encryption (PR 7436) +* Added support for gRPC (PR 7445) +* Added function wc_RsaPrivateKeyDecodeRaw to import raw RSA private keys (PR 7608) +* Added crypto callback for SHA-3 (PR 7670) +* Support for Infineon Modus Toolbox with wolfSSL (PR 7369) +* Allow user to send a user_canceled alert by calling wolfSSL_SendUserCanceled (PR 7590) +* C# wrapper SNI support added (PR 7610) +* Quantum-safe algorithm support added to the Linux kernel module (PR 7574) +* Support for NIST 800-56C Option 1 KDF, using the macro WC_KDF_NIST_SP_800_56C added (PR 7589) +* AES-XTS streaming mode added, along with hardware acceleration and kernel module use (PR 7522, 7560, 7424) +* PlatformIO FreeRTOS with ESP build and addition of benchmark and test example applications (PR 7528, 7413, 7559, 7542) -* Remove obsolete user-crypto functionality and Intel IPP support (PR 7097) -* Support for RSA-PSS signatures with CRL use (PR 7119) -* Enhancement for AES-GCM use with Xilsecure on Microblaze (PR 7051) -* Support for crypto cb only build with ECC and NXP CAAM (PR 7269) -* Improve liboqs integration adding locking and init/cleanup functions (PR 7026) -* Prevent memory access before clientSession->serverRow and clientSession->serverIdx are sanitized (PR 7096) -* Enhancements to reproducible build (PR 7267) -* Update Arduino example TLS Client/Server and improve support for ESP32 (PR 7304 & 7177) -* XC32 compiler version 4.x compatibility (PR 7128) -* Porting for build on PlayStation 3 and 4 (PR 7072) -* Improvements for Espressif use; SHA HW/SW selection and use on ESP32-C2/ESP8684, wolfSSL_NewThread() type, component cmake fix, and update TLS client example for ESP8266 (PR 7081, 7173, 7077, 7148, 7240) -* Allow crypto callbacks with SHA-1 HW (PR 7087) -* Update OpenSSH port to version 9.6p1(PR 7203) -* ARM Thumb2 enhancements, AES-GCM support for GCM_SMALL, alignment fix on key, fix for ASM clobber list (PR 7291,7301,7221) -* Expand heap hint support for static memory build with more x509 functions (PR 7136) -* Improving ARMv8 ChaCha20 ASM (alignment) (PR 7182) -* Unknown extension callback wolfSSL_CertManagerSetUnknownExtCallback added to CertManager (PR 7194) -* Implement wc_rng_new_ex for use with devID’s with crypto callback (PR 7271) -* Allow reading 0-RTT data after writing 0.5-RTT data (PR 7102) -* Send alert on bad PSK binder error (PR 7235) -* Enhancements to CMake build files for use with cross compiling (PR 7188) +## Enhancements and Optimizations +* Expanded STM32 AES hardware acceleration support for use with STM32H5 (PR 7578) +* Adjusted wc_xmss and wc_lms settings to support use with wolfBoot (PR 7393) +* Added the --enable-rpk option to autotools build for using raw public key support (PR 7379) +* SHA-3 Thumb2, ARM32 assembly implementation added (PR 7667) +* Improvements to RSA padding to expose Pad/Unpad APIs (PR 7612) +* Updates and API additions for supporting socat version 1.8.0.0 (PR 7594) +* cmake build improvements, expanding build options with SINGLE_THREADED and post-quantum algorithms, adjusting the generation of options.h file and using “yes;no” boolean instead of strings (PR 7611, 7546, 7479, 7480, 7380) +* Improvements for Renesas RZ support (PR 7474) +* Improvements to dual algorithm certificates for post-quantum keys (PR 7286) +* Added wolfSSL_SessionIsSetup so the user can check if a session ticket has been sent by the server (PR 7430) +* hostap updates: Implement PACs for EAP-FAST and filter cipher list on TLS version change (PR 7446) +* Changed subject name comparison to match different upper and lower cases (PR 7420) +* Support for DTLS 1.3 downgrade when using PSK (PR 7367) +* Update to static memory build for more generic memory pools used (PR 7418) +* Improved performance of Kyber C implementation (PR 7654) +* Support for ECC_CACHE_CURVE with no malloc (PR 7490) +* Added the configure option --enable-debug-trace-errcodes (macro WOLFSSL_DEBUG_TRACE_ERROR_CODES) which enables more debug tracking of error code values (PR 7634) +* Enhanced wc_MakeRsaKey and wc_RsaKeyToDer to work with WOLFSSL_NO_MALLOC (PR 7362) +* Improvements to assembly implementations of ChaCha20 and Poly1305 ASM for use with MSVC (PR 7319) +* Cortex-M inline assembly labels with unique number appended (PR 7649) +* Added secret logging callback to TLS <= 1.2, enabled with the macro HAVE_SECRET_CALLBACK (PR 7372) +* Made wc_RNG_DRBG_Reseed() a public wolfCrypt API (PR 7386) +* Enabled DES3 support without the DES3 ciphers. To re-enable DES3 cipher suites, use the configure flag --enable-des3-tls-suites (PR 7315) +* Added stubs required for latest nginx (1.25.5) (PR 7449) +* Added option for using a custom salt with the function wc_ecc_ctx_set_own_salt (PR 7552) +* Added PQ files for Windows (PR 7419) +* Enhancements to static memory feature, adding the option for a global heap hint (PR 7478) and build options for a lean or debug setting, enabled with --enable-staticmemory=small or --enable-staticmemory=debug (PR 7597) +* Updated --enable-jni to define SESSION_CERTS for wolfJSSE (PR 7557) +* Exposed DTLS in Ada wrapper and updated examples (PR 7397) +* Added additional minimum TLS extension size sanity checks (PR 7602) +* ESP improvements: updating the examples and libraries, updates for Apple HomeKit SHA/SRP, and fix for endianness with SHA512 software fallback (PR 7607, 7392, 7505, 7535) +* Made the wc_CheckCertSigPubKey API publicly available with the define of the macro WOLFSSL_SMALL_CERT_VERIFY (PR 7599) +* Added an alpha/preview of additional FIPS 140-3 full submission, bringing additional algorithms such as SRTP-KDF, AES-XTS, GCM streaming, AES-CFB, ED25519, and ED448 into the FIPS module boundary (PR 7295) +* XCODE support for v5.2.3 of the FIPS module (PR 7140) +* Expanded OpenSSL compatibility layer and added EC_POINT_hex2point (PR 7191) ## Fixes - -* Fix for checking result of MAC verify when no AAD is used with AES-GCM and Xilinx Xilsecure (PR 7051) -* Fix for Aria sign use (PR 7082) -* Fix for invalid `dh_ffdhe_test` test case using Intel QuickAssist (PR 7085) -* Fixes for TI AES and SHA on TM4C with HW acceleration and add full AES GCM and CCM support with TLS (PR 7018) -* Fixes for STM32 PKA use with ECC (PR 7098) -* Fixes for TLS 1.3 with crypto callbacks to offload KDF / HMAC operation (PR 7070) -* Fix include path for FSP 3.5 on Renesas RA6M4 (PR 7101) -* Siphash x64 asm fix for use with older compilers (PR 7299) -* Fix for SGX build with SP (PR 7308) -* Fix to Make it mandatory that the cookie is sent back in new ClientHello when seen in a HelloRetryRequest with (PR 7190) -* Fix for wrap around behavior with BIO pairs (PR 7169) -* OCSP fixes for parsing of response correctly when there was a revocation reason and returning correct error value with date checks (PR 7241 & 7255) -* Fix build with `NO_STDIO_FILESYSTEM` and improve checks for `XGETENV` (PR 7150) -* Fix for DTLS sequence number and cookie when downgrading DTLS version (PR 7214) -* Fix for write_dup use with chacha-poly cipher suites (PR 7206) -* Fix for multiple handshake messages in one record failing with OUT_OF_ORDER_E when downgrading from TLS 1.3 to TLS 1.2 (PR 7141) -* Fix for AES ECB build with Thumb and alignment (PR 7094) -* Fix for negotiate handshake until the end in wolfSSL_read/wolfSSL_write if hitting an edge case with want read/write (PR 7237) +* Fixed the NXP MMCAU HW acceleration for SHA-256 (PR 7389) +* Fixed AES-CFB1 encrypt/decrypt on size (8*x-1) bits (PR 7431) +* Fixed use of %rip with SHA-256 x64 assembly (PR 7409) +* Fixed OCSP response message build for DTLS (PR 7671) +* Handled edge case in wc_ecc_mulmod() with zero (PR 7532) +* Fixed RPK (Raw Public Key) to follow certificate use correctly (PR 7375) +* Added sanity check on record header with QUIC use (PR 7638) +* Added sanity check for empty directory strings in X.509 when parsing (PR 7669) +* Added sanity check on non-conforming serial number of 0 in certificates being parsed (PR 7625) +* Fixed wolfSSL_CTX_set1_sigalgs_list() to make the TLS connection conform to the selected sig hash algorithm (PR 7693) +* Various fixes for dual algorithm certificates including small stack use and support for Certificate Signing Requests (PR 7577) +* Added sanity check for critical policy extension when wolfSSL is built without policy extension support enabled (PR 7388) +* Added sanity check that the ed25519 signature is smaller than the order (PR 7513) +* Fixed Segger emNet to handle non-blocking want read/want write (PR 7581) For additional vulnerability information visit the vulnerability page at: https://www.wolfssl.com/docs/security-vulnerabilities/ diff --git a/library.properties b/library.properties index 1a01ade..5f7d802 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=wolfssl -version=5.7.0 +version=5.7.2 author=wolfSSL Inc. maintainer=wolfSSL inc sentence=A lightweight SSL/TLS library written in ANSI C and targeted for embedded, RTOS, and resource-constrained environments. diff --git a/src/src/bio.c b/src/src/bio.c index 2dab43e..340cbfd 100644 --- a/src/src/bio.c +++ b/src/src/bio.c @@ -50,7 +50,7 @@ */ static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) { - word32 frmtSz = len; + word32 frmtSz = (word32)len; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read"); @@ -77,6 +77,8 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (buf == NULL || len == 0) return 0; + /* default no retry */ + bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY); sz1 = wolfSSL_BIO_nread(bio, &pt, len); if (sz1 > 0) { XMEMCPY(buf, pt, sz1); @@ -91,8 +93,10 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } } } - if (sz1 == 0) + if (sz1 == 0) { + bio->flags |= WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY; sz1 = -1; + } return sz1; } @@ -175,7 +179,7 @@ static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len) WOLFSSL_MSG("wolfSSL_BUF_MEM_resize error"); return WOLFSSL_BIO_ERROR; } - bio->mem_buf->length = bio->wrSz; + bio->mem_buf->length = (size_t)bio->wrSz; bio->ptr = bio->mem_buf->data; } } @@ -233,13 +237,13 @@ static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) { if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, - sz) != WOLFSSL_SUCCESS) + (unsigned int)sz) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } } else { - if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, sz) + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, (size_t)sz) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } @@ -305,12 +309,12 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) case WOLFSSL_BIO_FILE: #ifndef NO_FILESYSTEM if (bio->ptr) { - ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); + ret = (int)XFREAD(buf, 1, (size_t)len, (XFILE)bio->ptr); } else { - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + #if defined(XREAD) && !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - ret = (int)XREAD(bio->num, buf, len); + ret = (int)XREAD(bio->num, buf, (size_t)len); #else WOLFSSL_MSG("No file pointer and XREAD not enabled"); ret = NOT_COMPILED_IN; @@ -399,7 +403,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, /* get the encoded length */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, - &sz) != LENGTH_ONLY_E) { + &sz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Error with base64 get length"); return WOLFSSL_FATAL_ERROR; } @@ -448,7 +452,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, (void)heap; - return inLen; + return (int)inLen; } #endif /* WOLFSSL_BASE64_ENCODE */ @@ -502,8 +506,11 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, if (bio == NULL || data == NULL || len == 0) return 0; + /* default no retry */ + bio->flags &= ~(WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY); sz1 = wolfSSL_BIO_nwrite(bio, &buf, len); if (sz1 == 0) { + bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY; WOLFSSL_MSG("No room left to write"); return WOLFSSL_BIO_ERROR; } @@ -521,6 +528,8 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, if (sz2 > 0) { XMEMCPY(buf, data, sz2); sz1 += sz2; + if (len > sz2) + bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY; } } @@ -591,12 +600,12 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, - len) != WOLFSSL_SUCCESS) { + (unsigned int)len) != WOLFSSL_SUCCESS) { ret = WOLFSSL_BIO_ERROR; } } else { - if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, len) + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, (size_t)len) != WOLFSSL_SUCCESS) { ret = WOLFSSL_BIO_ERROR; } @@ -652,7 +661,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) if (ret > 0) { /* change so that data is formatted buffer */ data = frmt; - len = frmtSz; + len = (int)frmtSz; } #else WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without " @@ -670,12 +679,12 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) case WOLFSSL_BIO_FILE: #ifndef NO_FILESYSTEM if (bio->ptr) { - ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); + ret = (int)XFWRITE(data, 1, (size_t)len, (XFILE)bio->ptr); } else { - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + #if defined(XWRITE) && !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - ret = (int)XWRITE(bio->num, data, len); + ret = (int)XWRITE(bio->num, data, (size_t)len); #else WOLFSSL_MSG("No file pointer and XWRITE not enabled"); ret = NOT_COMPILED_IN; @@ -972,7 +981,7 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz) ret = wolfSSL_EVP_DigestFinal((WOLFSSL_EVP_MD_CTX*)bio->ptr, (unsigned char*)buf, &szOut); if (ret == WOLFSSL_SUCCESS) { - ret = szOut; + ret = (int)szOut; } } break; @@ -1257,8 +1266,8 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) bio->rdIdx = 0; if (bio->mem_buf != NULL) { bio->mem_buf->data = (char*)bio->ptr; - bio->mem_buf->length = bio->num; - bio->mem_buf->max = bio->num; + bio->mem_buf->length = (size_t)bio->num; + bio->mem_buf->max = (size_t)bio->num; } return WOLFSSL_SUCCESS; @@ -1608,7 +1617,12 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) XFCLOSE((XFILE)bio->ptr); } - bio->ptr = XFOPEN(name, "w"); + /* 'b' flag is ignored on POSIX targets, but on Windows it assures + * inhibition of LF<->CRLF rewriting, so that there is consistency + * between the size and contents of the representation in memory and on + * disk. + */ + bio->ptr = XFOPEN(name, "wb"); if (((XFILE)bio->ptr) == XBADFILE) { return WOLFSSL_FAILURE; } @@ -2637,7 +2651,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) len = (int)XSTRLEN((const char*)buf) + 1; } - if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, len) == 0) { + if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, (size_t)len) == 0) { wolfSSL_BIO_free(bio); return NULL; } diff --git a/src/src/conf.c b/src/src/conf.c index cfc6085..d177da5 100644 --- a/src/src/conf.c +++ b/src/src/conf.c @@ -1599,4 +1599,33 @@ int wolfSSL_CONF_cmd_value_type(WOLFSSL_CONF_CTX *cctx, const char *cmd) * END OF CONF API ******************************************************************************/ +#if defined(OPENSSL_EXTRA) +OPENSSL_INIT_SETTINGS* wolfSSL_OPENSSL_INIT_new(void) +{ + OPENSSL_INIT_SETTINGS* init = (OPENSSL_INIT_SETTINGS*)XMALLOC( + sizeof(OPENSSL_INIT_SETTINGS), NULL, DYNAMIC_TYPE_OPENSSL); + + return init; +} + +void wolfSSL_OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS* init) +{ + XFREE(init, NULL, DYNAMIC_TYPE_OPENSSL); +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_OPENSSL_INIT_set_config_appname(OPENSSL_INIT_SETTINGS* init, + char* appname) +{ + (void)init; + (void)appname; + WOLFSSL_STUB("OPENSSL_INIT_set_config_appname"); + return WOLFSSL_SUCCESS; +} +#endif + +#endif /* OPENSSL_EXTRA */ + + + #endif /* WOLFSSL_CONF_INCLUDED */ diff --git a/src/src/crl.c b/src/src/crl.c index 3e61ec9..706c1f6 100644 --- a/src/src/crl.c +++ b/src/src/crl.c @@ -110,18 +110,18 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, #if defined(OPENSSL_EXTRA) crle->lastDateAsn1.length = MAX_DATE_SIZE; XMEMCPY (crle->lastDateAsn1.data, crle->lastDate, - crle->lastDateAsn1.length); + (size_t)crle->lastDateAsn1.length); crle->lastDateAsn1.type = crle->lastDateFormat; crle->nextDateAsn1.length = MAX_DATE_SIZE; XMEMCPY (crle->nextDateAsn1.data, crle->nextDate, - crle->nextDateAsn1.length); + (size_t)crle->nextDateAsn1.length); crle->nextDateAsn1.type = crle->nextDateFormat; crle->issuer = NULL; wolfSSL_d2i_X509_NAME(&crle->issuer, (unsigned char**)&dcrl->issuer, dcrl->issuerSz); if (crle->issuer == NULL) { - return WOLFSSL_FAILURE; + return -1; } #endif #ifdef CRL_STATIC_REVOKED_LIST @@ -318,14 +318,14 @@ static int FindRevokedSerial(RevokedCert* rc, byte* serial, int serialSz, while (rc) { if (serialHash == NULL) { if (rc->serialSz == serialSz && - XMEMCMP(rc->serialNumber, serial, rc->serialSz) == 0) { + XMEMCMP(rc->serialNumber, serial, (size_t)rc->serialSz) == 0) { WOLFSSL_MSG("Cert revoked"); ret = CRL_CERT_REVOKED; break; } } else { - ret = CalcHashId(rc->serialNumber, rc->serialSz, hash); + ret = CalcHashId(rc->serialNumber, (word32)rc->serialSz, hash); if (ret != 0) break; if (XMEMCMP(hash, serialHash, SIGNER_DIGEST_SIZE) == 0) { @@ -362,7 +362,7 @@ static int VerifyCRLE(const WOLFSSL_CRL* crl, CRL_Entry* crle) ret = VerifyCRL_Signature(&sigCtx, crle->toBeSigned, crle->tbsSz, crle->signature, crle->signatureSz, crle->signatureOID, #ifdef WC_RSA_PSS - crle->sigParams, crle->sigParamsSz, + crle->sigParams, (int)crle->sigParamsSz, #else NULL, 0, #endif @@ -392,6 +392,8 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, for (crle = crl->crlList; crle != NULL; crle = crle->next) { if (XMEMCMP(crle->issuerHash, issuerHash, CRL_DIGEST_SIZE) == 0) { + int nextDateValid = 1; + WOLFSSL_MSG("Found CRL Entry on list"); if (crle->verified == 0) { @@ -426,17 +428,20 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, #if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) { WOLFSSL_MSG("CRL next date is no longer valid"); - ret = ASN_AFTER_DATE_E; + nextDateValid = 0; } #endif } - if (ret == 0) { + if (nextDateValid) { foundEntry = 1; ret = FindRevokedSerial(crle->certs, serial, serialSz, serialHash, crle->totalCerts); if (ret != 0) break; } + else if (foundEntry == 0) { + ret = ASN_AFTER_DATE_E; + } } } @@ -498,8 +503,8 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, /* Loading .rN form CRL file if find at the folder, */ /* and try again checking Cert in the CRL list. */ /* When not set the folder or not use hash_dir, do nothing. */ - if ((foundEntry == 0) && (ret != OCSP_WANT_READ)) { - if (crl->cm->x509_store_p != NULL) { + if ((foundEntry == 0) && (ret != WC_NO_ERR_TRACE(OCSP_WANT_READ))) { + if (crl->cm != NULL && crl->cm->x509_store_p != NULL) { ret = LoadCertByIssuer(crl->cm->x509_store_p, (WOLFSSL_X509_NAME*)issuerName, X509_LU_CRL); if (ret == WOLFSSL_SUCCESS) { @@ -512,18 +517,18 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, #endif if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); - if (ret != CRL_CERT_DATE_ERR) { + if (ret != WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) { ret = CRL_MISSING; } - if (crl->cm->cbMissingCRL) { + if (crl->cm != NULL && crl->cm->cbMissingCRL) { char url[256]; WOLFSSL_MSG("Issuing missing CRL callback"); url[0] = '\0'; if (extCrlInfo) { if (extCrlInfoSz < (int)sizeof(url) -1 ) { - XMEMCPY(url, extCrlInfo, extCrlInfoSz); + XMEMCPY(url, extCrlInfo, (size_t)extCrlInfoSz); url[extCrlInfoSz] = '\0'; } else { @@ -650,13 +655,15 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(crl->currentEntry->certs, dcrl, myBuffer, (word32)sz, verify, crl->cm); - if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && verify == NO_VERIFY)) { + if (ret != 0 && !(ret == WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E) + && verify == NO_VERIFY)) { WOLFSSL_MSG("ParseCRL error"); CRL_Entry_free(crl->currentEntry, crl->heap); crl->currentEntry = NULL; } else { - ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); + ret = AddCRL(crl, dcrl, myBuffer, + ret != WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E)); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); crl->currentEntry = NULL; @@ -680,8 +687,8 @@ static WOLFSSL_X509_CRL* wolfSSL_X509_crl_new(WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_X509_CRL* ret; - ret = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), cm->heap, - DYNAMIC_TYPE_CRL); + ret = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), + cm != NULL ? cm->heap : NULL, DYNAMIC_TYPE_CRL); if (ret != NULL) { if (InitCRL(ret, cm) < 0) { WOLFSSL_MSG("Unable to initialize new CRL structure"); @@ -844,7 +851,7 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl) #ifdef HAVE_CRL_MONITOR if (crl->monitors[0].path) { - int pathSz = (int)XSTRLEN(crl->monitors[0].path) + 1; + size_t pathSz = XSTRLEN(crl->monitors[0].path) + 1; dupl->monitors[0].path = (char*)XMALLOC(pathSz, dupl->heap, DYNAMIC_TYPE_CRL_MONITOR); if (dupl->monitors[0].path != NULL) { @@ -856,7 +863,7 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl) } if (crl->monitors[1].path) { - int pathSz = (int)XSTRLEN(crl->monitors[1].path) + 1; + size_t pathSz = XSTRLEN(crl->monitors[1].path) + 1; dupl->monitors[1].path = (char*)XMALLOC(pathSz, dupl->heap, DYNAMIC_TYPE_CRL_MONITOR); if (dupl->monitors[1].path != NULL) { @@ -880,6 +887,20 @@ static int DupX509_CRL(WOLFSSL_X509_CRL *dupl, const WOLFSSL_X509_CRL* crl) return 0; } +WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl) +{ + WOLFSSL_X509_CRL* ret; + + WOLFSSL_ENTER("wolfSSL_X509_CRL_dup"); + + ret = wolfSSL_X509_crl_new(crl->cm); + if (ret != NULL && DupX509_CRL(ret, crl) != 0) { + FreeCRL(ret, 1); + ret = NULL; + } + return ret; +} + /* returns WOLFSSL_SUCCESS on success. Does not take ownership of newcrl */ int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl) { diff --git a/src/src/dtls.c b/src/src/dtls.c index aecd260..52ace7e 100644 --- a/src/src/dtls.c +++ b/src/src/dtls.c @@ -107,14 +107,14 @@ int DtlsIgnoreError(int err) { /* Whitelist of errors not to ignore */ switch (err) { - case MEMORY_E: - case MEMORY_ERROR: - case ASYNC_INIT_E: - case ASYNC_OP_E: - case SOCKET_ERROR_E: - case WANT_READ: - case WANT_WRITE: - case COOKIE_ERROR: + case WC_NO_ERR_TRACE(MEMORY_E): + case WC_NO_ERR_TRACE(MEMORY_ERROR): + case WC_NO_ERR_TRACE(ASYNC_INIT_E): + case WC_NO_ERR_TRACE(ASYNC_OP_E): + case WC_NO_ERR_TRACE(SOCKET_ERROR_E): + case WC_NO_ERR_TRACE(WANT_READ): + case WC_NO_ERR_TRACE(WANT_WRITE): + case WC_NO_ERR_TRACE(COOKIE_ERROR): return 0; default: return 1; @@ -187,14 +187,14 @@ typedef struct WolfSSL_CH { byte dtls12cookieSet:1; } WolfSSL_CH; -static int ReadVector8(const byte* input, WolfSSL_ConstVector* v) +static word32 ReadVector8(const byte* input, WolfSSL_ConstVector* v) { v->size = *input; v->elements = input + OPAQUE8_LEN; return v->size + OPAQUE8_LEN; } -static int ReadVector16(const byte* input, WolfSSL_ConstVector* v) +static word32 ReadVector16(const byte* input, WolfSSL_ConstVector* v) { word16 size16; ato16(input, &size16); @@ -267,7 +267,7 @@ static int CheckDtlsCookie(const WOLFSSL* ssl, WolfSSL_CH* ch, return BUFFER_E; ret = TlsCheckCookie(ssl, ch->cookieExt.elements + OPAQUE16_LEN, (word16)(ch->cookieExt.size - OPAQUE16_LEN)); - if (ret < 0 && ret != HRR_COOKIE_ERROR) + if (ret < 0 && ret != WC_NO_ERR_TRACE(HRR_COOKIE_ERROR)) return ret; *cookieGood = ret > 0; ret = 0; @@ -1010,11 +1010,20 @@ int DoClientHelloStateless(WOLFSSL* ssl, const byte* input, word32 helloSz, ssl->options.dtlsStateful = 1; /* Update the window now that we enter the stateful parsing */ #ifdef WOLFSSL_DTLS13 - if (isTls13) + if (isTls13) { + /* Set record numbers before current record number as read */ + Dtls13Epoch* e; ret = Dtls13UpdateWindowRecordRecvd(ssl); + e = Dtls13GetEpoch(ssl, ssl->keys.curEpoch64); + if (e != NULL) + XMEMSET(e->window, 0xFF, sizeof(e->window)); + } else #endif DtlsUpdateWindow(ssl); + /* Set record numbers before current record number as read */ + XMEMSET(ssl->keys.peerSeq->window, 0xFF, + sizeof(ssl->keys.peerSeq->window)); } } diff --git a/src/src/dtls13.c b/src/src/dtls13.c index 86e5fb8..0284ffe 100644 --- a/src/src/dtls13.c +++ b/src/src/dtls13.c @@ -396,7 +396,8 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) * WANT_WRITE means that we are done with processing the msg and we are * waiting to flush the output buffer. */ if ((ret == 0 || ret == WANT_WRITE) || (msg->type == certificate_request && - ssl->options.handShakeDone && ret == WC_PENDING_E)) { + ssl->options.handShakeDone && + ret == WC_NO_ERR_TRACE(WC_PENDING_E))) { if (IsAtLeastTLSv1_3(ssl->version)) Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type); else if (downgraded) diff --git a/src/src/internal.c b/src/src/internal.c index d889f33..6bbd38f 100644 --- a/src/src/internal.c +++ b/src/src/internal.c @@ -149,7 +149,7 @@ #endif -#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } +#define ERROR_OUT(err, eLabel) { ret = (int)(err); goto eLabel; } #ifdef _MSC_VER /* disable for while(0) cases at the .c level for now */ @@ -266,6 +266,49 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, #endif /* !WOLFSSL_NO_TLS12 */ +#if !defined(NO_CERT) && defined(WOLFSSL_BLIND_PRIVATE_KEY) +int wolfssl_priv_der_blind(WC_RNG* rng, DerBuffer* key, DerBuffer** mask) +{ + int ret = 0; + WC_RNG local_rng; + + if (key != NULL) { + if (*mask != NULL) { + FreeDer(mask); + } + ret = AllocDer(mask, key->length, key->type, key->heap); + if ((ret == 0) && (rng == NULL)) { + if (wc_InitRng(&local_rng) != 0) { + ret = RNG_FAILURE_E; + } + else { + rng = &local_rng; + } + } + if (ret == 0) { + ret = wc_RNG_GenerateBlock(rng, (*mask)->buffer, (*mask)->length); + } + if (ret == 0) { + xorbuf(key->buffer, (*mask)->buffer, (*mask)->length); + } + + if (rng == &local_rng) { + wc_FreeRng(rng); + } + } + + return ret; +} + +void wolfssl_priv_der_unblind(DerBuffer* key, DerBuffer* mask) +{ + if (key != NULL) { + xorbuf(key->buffer, mask->buffer, mask->length); + } +} +#endif + + #if defined(WOLFSSL_RENESAS_FSPSM_TLS) || defined(WOLFSSL_RENESAS_TSIP_TLS) #include #endif @@ -517,6 +560,22 @@ int IsTLS(const WOLFSSL* ssl) { if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR) return 1; +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) + return 1; +#endif + + return 0; +} + +int IsTLS_ex(const ProtocolVersion pv) +{ + if (pv.major == SSLv3_MAJOR && pv.minor >=TLSv1_MINOR) + return 1; +#ifdef WOLFSSL_DTLS + if (pv.major == DTLS_MAJOR) + return 1; +#endif return 0; } @@ -2108,7 +2167,7 @@ int wolfSSL_session_export_internal(WOLFSSL* ssl, byte* buf, word32* sz, } } - if (ret != 0 && ret != LENGTH_ONLY_E && buf != NULL) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E) && buf != NULL) { /*in a fail case clear the buffer which could contain partial key info*/ XMEMSET(buf, 0, *sz); } @@ -2169,7 +2228,6 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side) ssl->options.haveECC = 1; /* server turns on with ECC key cert */ } #endif -#ifdef HAVE_PQC #ifdef HAVE_FALCON if (ssl->options.side == WOLFSSL_CLIENT_END) { ssl->options.haveFalconSig = 1; /* always on client side */ @@ -2180,7 +2238,6 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side) ssl->options.haveDilithiumSig = 1; /* always on client side */ } #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) if (ssl->options.side == WOLFSSL_CLIENT_END) { @@ -2251,6 +2308,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) #ifndef NO_CERTS ctx->privateKeyDevId = INVALID_DEVID; +#ifdef WOLFSSL_DUAL_ALG_CERTS + ctx->altPrivateKeyDevId = INVALID_DEVID; +#endif #endif #ifndef NO_DH @@ -2264,14 +2324,12 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->minEccKeySz = MIN_ECCKEY_SZ; ctx->eccTempKeySz = ECDHE_SIZE; #endif -#ifdef HAVE_PQC #ifdef HAVE_FALCON ctx->minFalconKeySz = MIN_FALCONKEY_SZ; #endif /* HAVE_FALCON */ #ifdef HAVE_DILITHIUM ctx->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ; #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ ctx->verifyDepth = MAX_CHAIN_DEPTH; #ifdef OPENSSL_EXTRA ctx->cbioFlag = WOLFSSL_CBIO_NONE; @@ -2335,7 +2393,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) wolfSSL_CTX_set_server_cert_type(ctx, NULL, 0); /* set to default */ #endif /* HAVE_RPK */ -#ifdef HAVE_PQC #ifdef HAVE_FALCON if (method->side == WOLFSSL_CLIENT_END) ctx->haveFalconSig = 1; /* always on client side */ @@ -2346,7 +2403,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) ctx->haveDilithiumSig = 1; /* always on client side */ /* server can turn on by loading key */ #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ #ifdef HAVE_ECC if (method->side == WOLFSSL_CLIENT_END) { ctx->haveECDSAsig = 1; /* always on client side */ @@ -2398,22 +2454,27 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) return MEMORY_E; } XMEMSET(ctx->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + /* WOLFSSL_X509_LOOKUP */ - if ((ctx->x509_store.lookup.dirs = - (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR), - heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { - WOLFSSL_MSG("ctx-x509_store.lookup.dir memory allocation error"); - XFREE(ctx->param, heap, DYNAMIC_TYPE_OPENSSL); - ctx->param = NULL; + if ((ctx->x509_store.lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC( + sizeof(WOLFSSL_BY_DIR), + heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("ctx->x509_store.lookup.dirs: allocation error"); return MEMORY_E; } XMEMSET(ctx->x509_store.lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR)); + + /* param */ + if ((ctx->x509_store.param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + heap, DYNAMIC_TYPE_OPENSSL)) == NULL) { + WOLFSSL_MSG("ctx->x509_store.param: allocation error"); + return MEMORY_E; + } + XMEMSET(ctx->x509_store.param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + if (wc_InitMutex(&ctx->x509_store.lookup.dirs->lock) != 0) { WOLFSSL_MSG("Bad mutex init"); - XFREE(ctx->param, heap, DYNAMIC_TYPE_OPENSSL); - ctx->param = NULL; - XFREE(ctx->x509_store.lookup.dirs, heap, DYNAMIC_TYPE_OPENSSL); - ctx->x509_store.lookup.dirs = NULL; WOLFSSL_ERROR_VERBOSE(BAD_MUTEX_E); return BAD_MUTEX_E; } @@ -2585,11 +2646,17 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) ForceZero(ctx->privateKey->buffer, ctx->privateKey->length); } FreeDer(&ctx->privateKey); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ctx->privateKeyMask); +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS if (ctx->altPrivateKey != NULL && ctx->altPrivateKey->buffer != NULL) { ForceZero(ctx->altPrivateKey->buffer, ctx->altPrivateKey->length); } FreeDer(&ctx->altPrivateKey); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ctx->altPrivateKeyMask); +#endif #endif /* WOLFSSL_DUAL_ALG_CERTS */ #ifdef OPENSSL_ALL wolfSSL_EVP_PKEY_free(ctx->privateKeyPKey); @@ -2661,6 +2728,11 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) ctx->param = NULL; } + if (ctx->x509_store.param) { + XFREE(ctx->x509_store.param, heapAtCTXInit, DYNAMIC_TYPE_OPENSSL); + ctx->x509_store.param = NULL; + } + if (ctx->x509_store.lookup.dirs) { #if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) if (ctx->x509_store.lookup.dirs->dir_entry) { @@ -2732,7 +2804,7 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx) if (ret < 0) { /* check error state, if mutex error code then mutex init failed but * CTX was still malloc'd */ - if (ctx->err == CTX_INIT_MUTEX_E) { + if (ctx->err == WC_NO_ERR_TRACE(CTX_INIT_MUTEX_E)) { SSL_CtxResourceFree(ctx); XFREE(ctx, heap, DYNAMIC_TYPE_CTX); #ifdef WOLFSSL_STATIC_MEMORY @@ -2996,7 +3068,6 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo, } else #endif - #ifdef HAVE_PQC #ifdef HAVE_FALCON if (sigAlgo == falcon_level1_sa_algo) { ADD_HASH_SIG_ALGO(hashSigAlgo, inOutIdx, @@ -3026,7 +3097,6 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo, } else #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ #ifdef WC_RSA_PSS if (sigAlgo == rsa_pss_sa_algo) { /* RSA PSS is sig then mac */ @@ -3045,7 +3115,7 @@ static WC_INLINE void AddSuiteHashSigAlgo(byte* hashSigAlgo, byte macAlgo, } } -void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2, +void InitSuitesHashSigAlgo(byte* hashSigAlgo, int haveSig, int tls1_2, int keySz, word16* len) { word16 idx = 0; @@ -3087,7 +3157,6 @@ void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2, &idx); } #endif -#if defined(HAVE_PQC) #ifdef HAVE_FALCON if (haveSig & SIG_FALCON) { AddSuiteHashSigAlgo(hashSigAlgo, no_mac, falcon_level1_sa_algo, keySz, @@ -3106,7 +3175,6 @@ void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2, keySz, &idx); } #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ if (haveSig & SIG_RSA) { #ifdef WC_RSA_PSS if (tls1_2) { @@ -3152,30 +3220,6 @@ void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int haveSig, int tls1_2, *len = idx; } -void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, - int haveFalconSig, int haveDilithiumSig, int haveAnon, int tls1_2, - int keySz) -{ - InitSuitesHashSigAlgo_ex(suites->hashSigAlgo, haveECDSAsig, haveRSAsig, - haveFalconSig, haveDilithiumSig, haveAnon, tls1_2, keySz, - &suites->hashSigAlgoSz); -} - -void InitSuitesHashSigAlgo_ex(byte* hashSigAlgo, int haveECDSAsig, - int haveRSAsig, int haveFalconSig, int haveDilithiumSig, int haveAnon, - int tls1_2, int keySz, word16* len) -{ - int have = 0; - - if (haveECDSAsig) have |= SIG_ECDSA; - if (haveRSAsig) have |= SIG_RSA; - if (haveFalconSig) have |= SIG_FALCON; - if (haveDilithiumSig) have |= SIG_DILITHIUM; - if (haveAnon) have |= SIG_ANON; - - InitSuitesHashSigAlgo_ex2(hashSigAlgo, have, tls1_2, keySz, len); -} - int AllocateCtxSuites(WOLFSSL_CTX* ctx) { if (ctx->suites == NULL) { @@ -3238,6 +3282,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, (void)haveStaticRSA; (void)haveStaticECC; (void)haveECC; + (void)haveECDSAsig; (void)side; (void)haveRSA; /* some builds won't read */ (void)haveRSAsig; /* non ecc builds won't read */ @@ -4262,18 +4307,27 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, suites->suiteSz = idx; if (suites->hashSigAlgoSz == 0) { - int haveSig = 0; - haveSig |= (haveRSAsig | haveRSA) ? SIG_RSA : 0; - haveSig |= (haveECDSAsig | haveECC) ? SIG_ECDSA : 0; - #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - haveSig |= (haveECDSAsig | haveECC) ? SIG_SM2 : 0; - #endif - haveSig |= haveFalconSig ? SIG_FALCON : 0; - haveSig |= haveDilithiumSig ? SIG_DILITHIUM : 0; - haveSig &= ~SIG_ANON; - InitSuitesHashSigAlgo_ex2(suites->hashSigAlgo, haveSig, tls1_2, keySz, + InitSuitesHashSigAlgo(suites->hashSigAlgo, SIG_ALL, tls1_2, keySz, &suites->hashSigAlgoSz); } + + /* Moved to the end as we set some of the vars but never use them */ + (void)tls; /* shut up compiler */ + (void)tls1_2; + (void)dtls; + (void)haveDH; + (void)havePSK; + (void)haveStaticRSA; + (void)haveStaticECC; + (void)haveECC; + (void)haveECDSAsig; + (void)side; + (void)haveRSA; /* some builds won't read */ + (void)haveRSAsig; /* non ecc builds won't read */ + (void)haveAnon; /* anon ciphers optional */ + (void)haveNull; + (void)haveFalconSig; + (void)haveDilithiumSig; } #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \ @@ -4331,13 +4385,17 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) } break; #endif -#ifdef HAVE_PQC +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) case PQC_SA_MAJOR: - /* Hash performed as part of sign/verify operation. */ + /* Hash performed as part of sign/verify operation. + * However, if we want a dual alg signature with a + * classic algorithm as alternative, we need an explicit + * hash algo here. + */ #ifdef HAVE_FALCON if (input[1] == FALCON_LEVEL1_SA_MINOR) { *hsType = falcon_level1_sa_algo; - *hashAlgo = sha512_mac; + *hashAlgo = sha256_mac; } else if (input[1] == FALCON_LEVEL5_SA_MINOR) { *hsType = falcon_level5_sa_algo; @@ -4347,11 +4405,11 @@ void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) #ifdef HAVE_DILITHIUM if (input[1] == DILITHIUM_LEVEL2_SA_MINOR) { *hsType = dilithium_level2_sa_algo; - *hashAlgo = sha512_mac; + *hashAlgo = sha256_mac; } else if (input[1] == DILITHIUM_LEVEL3_SA_MINOR) { *hsType = dilithium_level3_sa_algo; - *hashAlgo = sha512_mac; + *hashAlgo = sha384_mac; } else if (input[1] == DILITHIUM_LEVEL5_SA_MINOR) { *hsType = dilithium_level5_sa_algo; @@ -4852,14 +4910,14 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (key && ret == WC_PENDING_E) { + if (key && ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ /* For positive response return in outSz */ if (ret > 0) { - *outSz = ret; + *outSz = (word32)ret; ret = 0; } @@ -4872,7 +4930,7 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, int hashAlgo, RsaKey* key, buffer* keyBufInfo) { - int ret = SIG_VERIFY_E; + int ret = WC_NO_ERR_TRACE(SIG_VERIFY_E); #ifdef HAVE_PK_CALLBACKS const byte* keyBuf = NULL; @@ -4928,7 +4986,7 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, !defined(WOLFSSL_RENESAS_TSIP_TLS) else #else - if (!ssl->ctx->RsaVerifyCb || ret == CRYPTOCB_UNAVAILABLE) + if (!ssl->ctx->RsaVerifyCb || ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) #endif #endif /*HAVE_PK_CALLBACKS */ { @@ -4937,7 +4995,7 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5010,7 +5068,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, TypeHash(hashAlgo), mgf, keyBuf, keySz, ctx); if (ret > 0) { - ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, + ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, (word32)ret, hashType); if (ret != 0) { ret = VERIFY_CERT_ERROR; @@ -5028,7 +5086,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType); #else - ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, ret, + ret = wc_RsaPSS_CheckPadding_ex(plain, plainSz, out, (word32)ret, hashType, -1, mp_count_bits(&key->n)); #endif @@ -5075,7 +5133,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (key && ret == WC_PENDING_E) { + if (key && ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5135,7 +5193,7 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5155,7 +5213,7 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, RsaKey* key, buffer* keyBufInfo) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); #ifdef HAVE_PK_CALLBACKS const byte* keyBuf = NULL; word32 keySz = 0; @@ -5187,7 +5245,7 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, !defined(WOLFSSL_RENESAS_TSIP_TLS) else #else - if (!ssl->ctx->RsaEncCb || ret == CRYPTOCB_UNAVAILABLE) + if (!ssl->ctx->RsaEncCb || ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) #endif #endif /* HAVE_PK_CALLBACKS */ { @@ -5196,14 +5254,14 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ /* For positive response return in outSz */ if (ret > 0) { - *outSz = ret; + *outSz = (word32)ret; ret = 0; } @@ -5256,7 +5314,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx); #if defined(WOLFSSL_RENESAS_TSIP_TLS) - if (ret == CRYPTOCB_UNAVAILABLE) { + if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key); } #endif /* WOLFSSL_RENESAS_TSIP_TLS */ @@ -5269,7 +5327,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (key && ret == WC_PENDING_E) { + if (key && ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5282,7 +5340,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, word32 outSz, ecc_key* key, buffer* keyBufInfo) { - int ret = SIG_VERIFY_E; + int ret = WC_NO_ERR_TRACE(SIG_VERIFY_E); #ifdef HAVE_PK_CALLBACKS const byte* keyBuf = NULL; word32 keySz = 0; @@ -5316,7 +5374,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, !defined(WOLFSSL_MAXQ108X) else #else - if (!ssl->ctx->EccVerifyCb || ret == CRYPTOCB_UNAVAILABLE) + if (!ssl->ctx->EccVerifyCb || ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) #endif #endif /* HAVE_PK_CALLBACKS */ { @@ -5325,7 +5383,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } else @@ -5398,7 +5456,7 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5457,7 +5515,7 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccKeyGenCb) { void* ctx = wolfSSL_GetEccKeyGenCtx(ssl); - ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx); + ret = ssl->ctx->EccKeyGenCb(ssl, key, (unsigned int)keySz, ecc_curve, ctx); } else #endif @@ -5475,7 +5533,7 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5515,7 +5573,7 @@ int Sm2wSm3Verify(WOLFSSL* ssl, const byte* id, word32 idSz, const byte* sig, word32 sigSz, const byte* msg, word32 msgSz, ecc_key* key, buffer* keyBufInfo) { - int ret = SIG_VERIFY_E; + int ret = WC_NO_ERR_TRACE(SIG_VERIFY_E); byte hash[WC_SM3_DIGEST_SIZE]; (void)ssl; @@ -5638,7 +5696,7 @@ int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5712,7 +5770,7 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } else @@ -5738,7 +5796,6 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, */ static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey) { - int ret = NO_PEER_KEY; struct curve25519_key* tmpKey = NULL; if (ssl == NULL || otherKey == NULL) { @@ -5761,10 +5818,11 @@ int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, if (tmpKey) { *otherKey = (curve25519_key *)tmpKey; - ret = 0; + return 0; + } + else { + return NO_PEER_KEY; } - - return ret; } #endif /* HAVE_PK_CALLBACKS */ @@ -5808,7 +5866,7 @@ static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5854,7 +5912,7 @@ static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -5962,7 +6020,7 @@ int Ed448Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -6036,7 +6094,7 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } else @@ -6062,7 +6120,6 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, */ static int X448GetKey(WOLFSSL* ssl, curve448_key** otherKey) { - int ret = NO_PEER_KEY; struct curve448_key* tmpKey = NULL; if (ssl == NULL || otherKey == NULL) { @@ -6084,10 +6141,11 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, if (tmpKey) { *otherKey = (curve448_key *)tmpKey; - ret = 0; + return 0; + } + else { + return NO_PEER_KEY; } - - return ret; } #endif /* HAVE_PK_CALLBACKS */ @@ -6132,7 +6190,7 @@ static int X448SharedSecret(WOLFSSL* ssl, curve448_key* priv_key, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -6177,7 +6235,7 @@ static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer) /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -6214,7 +6272,7 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, ret = ssl->ctx->DhGenerateKeyPairCb(dhKey, ssl->rng, priv, privSz, pub, pubSz); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif { PRIVATE_KEY_UNLOCK(); @@ -6224,7 +6282,7 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -6294,7 +6352,7 @@ int DhAgree(WOLFSSL* ssl, DhKey* dhKey, /* Handle async pending response */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -6704,14 +6762,12 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef HAVE_ECC ssl->options.minEccKeySz = ctx->minEccKeySz; #endif -#ifdef HAVE_PQC #ifdef HAVE_FALCON ssl->options.minFalconKeySz = ctx->minFalconKeySz; #endif /* HAVE_FALCON */ #ifdef HAVE_DILITHIUM ssl->options.minDilithiumKeySz = ctx->minDilithiumKeySz; #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) ssl->options.verifyDepth = ctx->verifyDepth; #endif @@ -6754,16 +6810,50 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) #ifdef WOLFSSL_TLS13 ssl->buffers.certChainCnt = ctx->certChainCnt; #endif +#ifndef WOLFSSL_BLIND_PRIVATE_KEY ssl->buffers.key = ctx->privateKey; +#else + if (ctx->privateKey != NULL) { + AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer, + ctx->privateKey->length, ctx->privateKey->type, + ctx->privateKey->heap); + ssl->buffers.weOwnKey = 1; + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.key, ctx->privateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + if (ret != 0) { + return ret; + } + } +#endif ssl->buffers.keyType = ctx->privateKeyType; ssl->buffers.keyId = ctx->privateKeyId; ssl->buffers.keyLabel = ctx->privateKeyLabel; ssl->buffers.keySz = ctx->privateKeySz; ssl->buffers.keyDevId = ctx->privateKeyDevId; #ifdef WOLFSSL_DUAL_ALG_CERTS - ssl->buffers.altKey = ctx->altPrivateKey; - ssl->buffers.altKeySz = ctx->altPrivateKeySz; - ssl->buffers.altKeyType = ctx->altPrivateKeyType; +#ifndef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.altKey = ctx->altPrivateKey; +#else + if (ctx->altPrivateKey != NULL) { + AllocCopyDer(&ssl->buffers.altkey, ctx->altPrivateKey->buffer, + ctx->altPrivateKey->length, ctx->altPrivateKey->type, + ctx->altPrivateKey->heap); + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.altKey, ctx->altPrivateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + if (ret != 0) { + return ret; + } + } +#endif + ssl->buffers.altKeyType = ctx->altPrivateKeyType; + ssl->buffers.altKeyId = ctx->altPrivateKeyId; + ssl->buffers.altKeyLabel = ctx->altPrivateKeyLabel; + ssl->buffers.altKeySz = ctx->altPrivateKeySz; + ssl->buffers.altKeyDevId = ctx->altPrivateKeyDevId; #endif /* WOLFSSL_DUAL_ALG_CERTS */ #endif #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ @@ -6951,7 +7041,7 @@ void FreeHandshakeHashes(WOLFSSL* ssl) int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source, HS_Hashes** destination) { - int ret = 0; + int ret; HS_Hashes* tmpHashes; if (source == NULL) @@ -6961,7 +7051,11 @@ int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source, tmpHashes = ssl->hsHashes; ssl->hsHashes = NULL; - InitHandshakeHashes(ssl); + ret = InitHandshakeHashes(ssl); + if (ret != 0) { + WOLFSSL_MSG_EX("InitHandshakeHashes failed. err = %d", ret); + return ret; + } *destination = ssl->hsHashes; ssl->hsHashes = tmpHashes; @@ -6969,50 +7063,50 @@ int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source, /* now copy the source contents to the destination */ #ifndef NO_OLD_TLS #ifndef NO_SHA - ret = wc_ShaCopy(&source->hashSha, &(*destination)->hashSha); + ret = wc_ShaCopy(&source->hashSha, &(*destination)->hashSha); #endif #ifndef NO_MD5 - if (ret == 0) - ret = wc_Md5Copy(&source->hashMd5, &(*destination)->hashMd5); + if (ret == 0) + ret = wc_Md5Copy(&source->hashMd5, &(*destination)->hashMd5); #endif #endif /* !NO_OLD_TLS */ #ifndef NO_SHA256 - if (ret == 0) - ret = wc_Sha256Copy(&source->hashSha256, - &(*destination)->hashSha256); + if (ret == 0) + ret = wc_Sha256Copy(&source->hashSha256, + &(*destination)->hashSha256); #endif #ifdef WOLFSSL_SHA384 - if (ret == 0) - ret = wc_Sha384Copy(&source->hashSha384, - &(*destination)->hashSha384); + if (ret == 0) + ret = wc_Sha384Copy(&source->hashSha384, + &(*destination)->hashSha384); #endif #ifdef WOLFSSL_SHA512 - if (ret == 0) - ret = wc_Sha512Copy(&source->hashSha512, - &(*destination)->hashSha512); + if (ret == 0) + ret = wc_Sha512Copy(&source->hashSha512, + &(*destination)->hashSha512); #endif #ifdef WOLFSSL_SM3 - if (ret == 0) - ret = wc_Sm3Copy(&source->hashSm3, - &(*destination)->hashSm3); + if (ret == 0) + ret = wc_Sm3Copy(&source->hashSm3, + &(*destination)->hashSm3); #endif #if (defined(HAVE_ED25519) || defined(HAVE_ED448) || \ (defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3))) && \ !defined(WOLFSSL_NO_CLIENT_AUTH) - if (ret == 0 && source->messages != NULL) { - (*destination)->messages = (byte*)XMALLOC(source->length, ssl->heap, - DYNAMIC_TYPE_HASHES); - (*destination)->length = source->length; - (*destination)->prevLen = source->prevLen; + if (ret == 0 && source->messages != NULL) { + (*destination)->messages = (byte*)XMALLOC(source->length, ssl->heap, + DYNAMIC_TYPE_HASHES); + (*destination)->length = source->length; + (*destination)->prevLen = source->prevLen; - if ((*destination)->messages == NULL) { - ret = MEMORY_E; - } - else { - XMEMCPY((*destination)->messages, source->messages, - source->length); - } + if ((*destination)->messages == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY((*destination)->messages, source->messages, + source->length); } + } #endif return ret; @@ -7139,6 +7233,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap)); + ssl_hint->memory = ctx_hint->memory; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* lock and check IO count / handshake count */ if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); @@ -7166,7 +7262,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } ctx_hint->memory->curIO++; ctx_hint->memory->curHa++; - ssl_hint->memory = ctx_hint->memory; ssl_hint->haFlag = 1; wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); @@ -7202,6 +7297,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) } wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); } + #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ #ifdef WOLFSSL_HEAP_TEST } #endif @@ -7573,6 +7669,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) defined(WOLFSSL_SSLKEYLOGFILE) && defined(WOLFSSL_TLS13) (void)wolfSSL_set_tls13_secret_cb(ssl, tls13ShowSecrets, NULL); #endif +#if defined(HAVE_SECRET_CALLBACK) && defined(SHOW_SECRETS) + (void)wolfSSL_set_secret_cb(ssl, tlsShowSecrets, NULL); +#endif #ifdef WOLFSSL_DUAL_ALG_CERTS ssl->sigSpec = ctx->sigSpec; ssl->sigSpecSz = ctx->sigSpecSz; @@ -7647,7 +7746,6 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) wc_curve448_free((curve448_key*)*pKey); break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: wc_falcon_free((falcon_key*)*pKey); @@ -7658,7 +7756,6 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) wc_dilithium_free((dilithium_key*)*pKey); break; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ #ifndef NO_DH case DYNAMIC_TYPE_DH: wc_FreeDhKey((DhKey*)*pKey); @@ -7676,7 +7773,7 @@ void FreeKey(WOLFSSL* ssl, int type, void** pKey) int AllocKey(WOLFSSL* ssl, int type, void** pKey) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); int sz = 0; #ifdef HAVE_ECC ecc_key* eccKey; @@ -7695,7 +7792,7 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) WOLFSSL_MSG("Key already present!"); #ifdef WOLFSSL_ASYNC_CRYPT /* allow calling this again for async reentry */ - if (ssl->error == WC_PENDING_E) { + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { return 0; } #endif @@ -7734,7 +7831,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) sz = sizeof(curve448_key); break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: sz = sizeof(falcon_key); @@ -7745,7 +7841,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) sz = sizeof(dilithium_key); break; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ #ifndef NO_DH case DYNAMIC_TYPE_DH: sz = sizeof(DhKey); @@ -7809,7 +7904,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) ret = 0; break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: wc_falcon_init_ex((falcon_key*)*pKey, ssl->heap, ssl->devId); @@ -7822,7 +7916,6 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) ret = 0; break; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ #ifdef HAVE_CURVE448 case DYNAMIC_TYPE_CURVE448: wc_curve448_init((curve448_key*)*pKey); @@ -7848,8 +7941,7 @@ int AllocKey(WOLFSSL* ssl, int type, void** pKey) #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ defined(HAVE_CURVE25519) || defined(HAVE_ED448) || \ - defined(HAVE_CURVE448) || (defined(HAVE_PQC) && defined(HAVE_FALCON)) || \ - (defined(HAVE_PQC) && defined(HAVE_DILITHIUM)) + defined(HAVE_CURVE448) || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) { int ret = 0; @@ -7895,12 +7987,18 @@ static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) ret = wc_curve448_init((curve448_key*)pKey); break; #endif /* HAVE_CURVE448 */ - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + #if defined(HAVE_FALCON) case DYNAMIC_TYPE_FALCON: wc_falcon_free((falcon_key*)pKey); ret = wc_falcon_init((falcon_key*)pKey); break; - #endif /* HAVE_PQC && HAVE_FALCON */ + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DYNAMIC_TYPE_DILITHIUM: + wc_dilithium_free((dilithium_key*)pKey); + ret = wc_dilithium_init((dilithium_key*)pKey); + break; + #endif /* HAVE_DILITHIUM */ #ifndef NO_DH case DYNAMIC_TYPE_DH: wc_FreeDhKey((DhKey*)pKey); @@ -8194,7 +8292,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) } #endif #endif -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_FALCON) FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey); ssl->peerFalconKeyPresent = 0; #endif @@ -8277,14 +8375,17 @@ void SSL_ResourceFree(WOLFSSL* ssl) /* avoid dereferencing a test value */ if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { #endif + void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; WOLFSSL_HEAP* ctx_heap; - void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; ctx_heap = ssl_hint->memory; + #ifndef SINGLE_THREADED if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); } + #endif ctx_heap->curIO--; if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) { WOLFSSL_MSG("Error freeing fixed output buffer"); @@ -8292,15 +8393,20 @@ void SSL_ResourceFree(WOLFSSL* ssl) if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) { WOLFSSL_MSG("Error freeing fixed output buffer"); } - if (ssl_hint->haFlag && ctx_heap->curHa > 0) { /* check if handshake count has been decreased*/ + + /* check if handshake count has been decreased*/ + if (ssl_hint->haFlag && ctx_heap->curHa > 0) { ctx_heap->curHa--; } + #ifndef SINGLE_THREADED wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #endif /* check if tracking stats */ if (ctx_heap->flag & WOLFMEM_TRACK_STATS) { XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL); } + #endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL); #ifdef WOLFSSL_HEAP_TEST } @@ -8437,10 +8543,10 @@ void FreeHandshakeResources(WOLFSSL* ssl) FreeKey(ssl, DYNAMIC_TYPE_ED448, (void**)&ssl->peerEd448Key); ssl->peerEd448KeyPresent = 0; #endif /* HAVE_ED448 */ -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_FALCON) FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey); ssl->peerFalconKeyPresent = 0; -#endif /* HAVE_PQC */ +#endif /* HAVE_FALCON */ } #ifdef HAVE_ECC @@ -8503,8 +8609,14 @@ void FreeHandshakeResources(WOLFSSL* ssl) } #endif /* !NO_DH */ -#ifndef NO_CERTS - wolfSSL_UnloadCertsKeys(ssl); +#if !defined(NO_CERTS) && !defined(OPENSSL_EXTRA) && \ + !defined(WOLFSSL_WPAS_SMALL) +#ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.side != WOLFSSL_CLIENT_END) +#endif + { + wolfSSL_UnloadCertsKeys(ssl); + } #endif #ifdef HAVE_PK_CALLBACKS #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) @@ -8562,14 +8674,20 @@ void FreeHandshakeResources(WOLFSSL* ssl) WOLFSSL_HEAP* ctx_heap; ctx_heap = ssl_hint->memory; + #ifndef SINGLE_THREADED if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN if (ctx_heap->curHa > 0) { ctx_heap->curHa--; } ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */ + #endif + #ifndef SINGLE_THREADED wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #endif #ifdef WOLFSSL_HEAP_TEST } #endif @@ -9422,7 +9540,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) int inputSz, sendSz; input = pool->raw; - inputSz = pool->sz; + inputSz = (int)pool->sz; sendSz = inputSz + cipherExtraData(ssl); #ifdef HAVE_SECURE_RENEGOTIATION @@ -9686,7 +9804,12 @@ ProtocolVersion MakeDTLSv1_3(void) #elif defined(FREERTOS) - #include "task.h" + #ifdef PLATFORMIO + #include + #include + #else + #include "task.h" + #endif unsigned int LowResTimer(void) { @@ -9768,7 +9891,12 @@ ProtocolVersion MakeDTLSv1_3(void) word32 LowResTimer(void) { - return k_uptime_get() / 1000; + int64_t t; + #if defined(CONFIG_ARCH_POSIX) + k_cpu_idle(); + #endif + t = k_uptime_get(); /* returns current uptime in milliseconds */ + return (word32)(t / 1000); } #elif defined(WOLFSSL_LINUXKM) @@ -9861,7 +9989,7 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz) #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_StoreMessage(ssl, data, sz); - if (ret != 0 && ret != CRYPTOCB_UNAVAILABLE) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; } #endif /* WOLFSSL_RENESAS_TSIP_TLS */ @@ -9876,7 +10004,7 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz) if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 - ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz); + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, (word32)sz); if (ret != 0) return ret; #ifdef WOLFSSL_DEBUG_TLS @@ -9886,7 +10014,7 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz) #endif #endif #ifdef WOLFSSL_SHA384 - ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz); + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, (word32)sz); if (ret != 0) return ret; #ifdef WOLFSSL_DEBUG_TLS @@ -9896,7 +10024,7 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz) #endif #endif #ifdef WOLFSSL_SHA512 - ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz); + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, (word32)sz); if (ret != 0) return ret; #ifdef WOLFSSL_DEBUG_TLS @@ -10444,7 +10572,7 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) ssl->buffers.inputBuffer.dynamicFlag = 0; ssl->buffers.inputBuffer.offset = 0; ssl->buffers.inputBuffer.idx = 0; - ssl->buffers.inputBuffer.length = usedLength; + ssl->buffers.inputBuffer.length = (word32)usedLength; } int SendBuffered(WOLFSSL* ssl) @@ -10561,8 +10689,7 @@ static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) #else const byte align = WOLFSSL_GENERAL_ALIGNMENT; #endif - int newSz = size + ssl->buffers.outputBuffer.idx + - ssl->buffers.outputBuffer.length; + word32 newSz; #if WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by @@ -10573,7 +10700,15 @@ static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) align *= 2; #endif - tmp = (byte*)XMALLOC(newSz + align, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + if (! WC_SAFE_SUM_WORD32(ssl->buffers.outputBuffer.idx, + ssl->buffers.outputBuffer.length, newSz)) + return BUFFER_E; + if (! WC_SAFE_SUM_WORD32(newSz, (word32)size, newSz)) + return BUFFER_E; + if (! WC_SAFE_SUM_WORD32(newSz, align, newSz)) + return BUFFER_E; + tmp = (byte*)XMALLOC(newSz, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + newSz -= align; WOLFSSL_MSG("growing output buffer"); if (tmp == NULL) @@ -10692,7 +10827,7 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) ssl->buffers.inputBuffer.buffer = tmp; ssl->buffers.inputBuffer.bufferSize = size + usedLength; ssl->buffers.inputBuffer.idx = 0; - ssl->buffers.inputBuffer.length = usedLength; + ssl->buffers.inputBuffer.length = (word32)usedLength; return 0; } @@ -10996,7 +11131,7 @@ static int MsgCheckBoundary(const WOLFSSL* ssl, byte type, * @param ssl The current connection * @param type The enum HandShakeType of the current message * @param msgSz Size of the current message - * @return + * @return int (less than 0 on fail, 0 on success) */ int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type, word32 msgSz) { @@ -11152,7 +11287,9 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx, /* version 1.3 already negotiated */ if (ssl->options.tls1_3) { ret = GetDtls13RecordHeader(ssl, inOutIdx, rh, size); - if (ret == 0 || ret != SEQUENCE_ERROR || ret != DTLS_CID_ERROR) + if (ret == 0 || + ret != WC_NO_ERR_TRACE(SEQUENCE_ERROR) || + ret != WC_NO_ERR_TRACE(DTLS_CID_ERROR)) return ret; } @@ -11174,7 +11311,7 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx, if (ssl->buffers.inputBuffer.length - *inOutIdx < DTLS_RECORD_HEADER_SZ) { ret = GetInputData(ssl, DTLS_RECORD_HEADER_SZ); /* Check if Dtls13RtxTimeout(ssl) returned socket error */ - if (ret == SOCKET_ERROR_E) + if (ret == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) return ret; if (ret != 0) return LENGTH_ERROR; @@ -11243,7 +11380,13 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, ssl->fuzzerCb(ssl, ssl->buffers.inputBuffer.buffer + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD, ssl->fuzzerCtx); #endif - XMEMCPY(rh, ssl->buffers.inputBuffer.buffer + *inOutIdx, RECORD_HEADER_SZ); + /* Set explicitly rather than make assumptions on struct layout */ + rh->type = ssl->buffers.inputBuffer.buffer[*inOutIdx]; + rh->pvMajor = ssl->buffers.inputBuffer.buffer[*inOutIdx + 1]; + rh->pvMinor = ssl->buffers.inputBuffer.buffer[*inOutIdx + 2]; + rh->length[0] = ssl->buffers.inputBuffer.buffer[*inOutIdx + 3]; + rh->length[1] = ssl->buffers.inputBuffer.buffer[*inOutIdx + 4]; + *inOutIdx += RECORD_HEADER_SZ; ato16(rh->length, size); } @@ -11306,7 +11449,20 @@ static int GetRecordHeader(WOLFSSL* ssl, word32* inOutIdx, } } #endif /* WOLFSSL_DTLS13 */ - else { + /* Don't care about protocol version being lower than expected on alerts + * sent back before version negotitation. */ + else if (!(ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.connectState == CLIENT_HELLO_SENT && + rh->type == alert && + rh->pvMajor == ssl->version.major && + #ifdef WOLFSSL_DTLS + ((ssl->options.dtls && rh->pvMinor == DTLS_MINOR) || + (!ssl->options.dtls && + rh->pvMinor < ssl->version.minor)) + #else + rh->pvMinor < ssl->version.minor + #endif + )) { WOLFSSL_MSG("SSL version error"); WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); return VERSION_ERROR; /* only use requested version */ @@ -12243,53 +12399,77 @@ int CipherRequires(byte first, byte second, int requirement) *.z.com matches y.z.com but not x.y.z.com return 1 on success */ -int MatchDomainName(const char* pattern, int len, const char* str) +int MatchDomainName(const char* pattern, int patternLen, const char* str, + word32 strLen) { int ret = 0; - if (pattern == NULL || str == NULL || len <= 0) + if (pattern == NULL || str == NULL || patternLen <= 0 || strLen == 0) return 0; - while (len > 0) { - - char p = (char)XTOLOWER((unsigned char)*pattern++); + while (patternLen > 0) { + /* Get the next pattern char to evaluate */ + char p = (char)XTOLOWER((unsigned char)*pattern); if (p == '\0') break; + pattern++; + if (p == '*') { char s; + /* We will always match '*' */ + patternLen--; - while (--len > 0) { + /* Consume any extra '*' chars until the next non '*' char. */ + while (patternLen > 0) { p = (char)XTOLOWER((unsigned char)*pattern); pattern++; + if (p == '\0' && patternLen > 0) + return 0; if (p != '*') break; + + patternLen--; } - if (len == 0) - p = '\0'; + /* Consume str until we reach next char in pattern after '*' or + * end of string */ + while (strLen > 0) { + s = (char)XTOLOWER((unsigned char) *str); + str++; + strLen--; + + /* p is next char in pattern after '*', or '*' if '*' is the + * last char in the pattern (in which case patternLen is 1) */ + if ( ((s == p) && (patternLen > 0))) { + /* We had already counted the '*' as matched, this means + * we also matched the next non '*' char in pattern */ + patternLen--; + break; + } - while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') { - if (s == p) + /* If strlen is 0, we have consumed the entire string. Count that + * as a match of '*' */ + if (strLen == 0) { break; + } + if (s == '.') return 0; - str++; } } else { + /* Simple case, pattern match exactly */ if (p != (char)XTOLOWER((unsigned char) *str)) return 0; - } - - if (len > 0) { str++; - len--; + strLen--; + patternLen--; } } - if (*str == '\0' && len == 0) { + if (strLen == 0 && patternLen == 0) { ret = 1; /* success */ } @@ -12301,14 +12481,16 @@ int MatchDomainName(const char* pattern, int len, const char* str) * 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 1 : match was found. - * 0 : no match found. - * -1 : No matches and wild pattern match failed. + * dCert Decoded cert to get the alternative names from. + * domain Domain name to compare against. + * domainLen Length of the domain name. + * checkCN Whether to check the common name. + * returns 1 : match was found. + * 0 : no match found. + * -1 : No matches and wild pattern match failed. */ -int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN) +int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, + int* checkCN) { int match = 0; DNS_entry* altName = NULL; @@ -12336,10 +12518,10 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN) #endif /* OPENSSL_ALL || WOLFSSL_IP_ALT_NAME */ { buf = altName->name; - len = altName->len; + len = (word32)altName->len; } - if (MatchDomainName(buf, len, domain)) { + if (MatchDomainName(buf, (int)len, domain, domainLen)) { match = 1; if (checkCN != NULL) { *checkCN = 0; @@ -12371,12 +12553,11 @@ int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN) int CheckHostName(DecodedCert* dCert, const char *domainName, size_t domainNameLen) { int checkCN; - int ret = DOMAIN_NAME_MISMATCH; - - /* Assume name is NUL terminated. */ - (void)domainNameLen; + int ret = WC_NO_ERR_TRACE(DOMAIN_NAME_MISMATCH); - if (CheckForAltNames(dCert, domainName, &checkCN) != 1) { + if (CheckForAltNames(dCert, domainName, (word32)domainNameLen, + &checkCN) != 1) { + ret = DOMAIN_NAME_MISMATCH; WOLFSSL_MSG("DomainName match on alt names failed"); } else { @@ -12386,10 +12567,11 @@ int CheckHostName(DecodedCert* dCert, const char *domainName, size_t domainNameL #ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY if (checkCN == 1) { if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, - domainName) == 1) { + domainName, (word32)domainNameLen) == 1) { ret = 0; } else { + ret = DOMAIN_NAME_MISMATCH; WOLFSSL_MSG("DomainName match on common name failed"); } } @@ -12412,7 +12594,7 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain, { if (chain->count < MAX_CHAIN_DEPTH && certSz < MAX_X509_SIZE) { - chain->certs[chain->count].length = certSz; + chain->certs[chain->count].length = (int)certSz; XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz); chain->count++; } @@ -12426,13 +12608,20 @@ static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain, defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType) { + if (name->dynamicName) { + XFREE(name->name, name->heap, DYNAMIC_TYPE_X509); + name->name = name->staticName; + name->dynamicName = 0; + } + if (nameType == SUBJECT) { XSTRNCPY(name->name, dCert->subject, ASN_NAME_MAX); name->name[ASN_NAME_MAX - 1] = '\0'; name->sz = (int)XSTRLEN(name->name) + 1; #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) name->rawLen = min(dCert->subjectRawLen, ASN_NAME_MAX); - XMEMCPY(name->raw, dCert->subjectRaw, name->rawLen); + if (name->rawLen > 0) + XMEMCPY(name->raw, dCert->subjectRaw, name->rawLen); #endif } else { @@ -12442,59 +12631,44 @@ void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType) #if (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY)) \ && (defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT)) name->rawLen = min(dCert->issuerRawLen, ASN_NAME_MAX); - if (name->rawLen) { + if (name->rawLen > 0) { XMEMCPY(name->raw, dCert->issuerRaw, name->rawLen); } #endif } } - -#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ - !defined(IGNORE_NAME_CONSTRAINTS) -/* copies over additional alt names such as dirName - * returns 0 on success - */ -static int CopyAdditionalAltNames(DNS_entry** to, DNS_entry* from, int type, - void* heap) +static int CopyAltNames(DNS_entry** to, DNS_entry* from, int type, void* heap) { - DNS_entry* cur = from; + /* Copy from to the beginning of to */ + DNS_entry** prev_next = to; + DNS_entry* next; if (to == NULL) { return BAD_FUNC_ARG; } - while (cur != NULL) { - if (cur->type == type) { - DNS_entry* dnsEntry; - int strLen = cur->len; + next = *to; - dnsEntry = AltNameNew(heap); - if (dnsEntry == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - return MEMORY_E; - } + for (; from != NULL; from = from->next) { + DNS_entry* dnsEntry; - dnsEntry->type = type; - dnsEntry->name = (char*)XMALLOC(strLen + 1, heap, - DYNAMIC_TYPE_ALTNAME); - if (dnsEntry->name == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - XFREE(dnsEntry, heap, DYNAMIC_TYPE_ALTNAME); - return MEMORY_E; - } - dnsEntry->len = strLen; - XMEMCPY(dnsEntry->name, cur->name, strLen); - dnsEntry->name[strLen] = '\0'; + if (type != -1 && from->type != type) + continue; - dnsEntry->next = *to; - *to = dnsEntry; + dnsEntry = AltNameDup(from, heap); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; } - cur = cur->next; + + dnsEntry->next = next; + *prev_next = dnsEntry; + prev_next = &dnsEntry->next; } + return 0; } -#endif /* OPENSSL_EXTRA */ #ifdef WOLFSSL_CERT_REQ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert) @@ -12609,8 +12783,6 @@ static int CopyREQAttributes(WOLFSSL_X509* x509, DecodedCert* dCert) #endif /* WOLFSSL_CERT_REQ */ /* Copy parts X509 needs from Decoded cert, 0 on success */ -/* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the - * altNames pointers could be free'd by second x509 still active by first */ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) { int ret = 0; @@ -12690,7 +12862,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) { int minSz; if (dCert->beforeDateLen > 0) { - minSz = min(dCert->beforeDate[1], MAX_DATE_SZ); + minSz = (int)min(dCert->beforeDate[1], MAX_DATE_SZ); x509->notBefore.type = dCert->beforeDate[0]; x509->notBefore.length = minSz; XMEMCPY(x509->notBefore.data, &dCert->beforeDate[2], minSz); @@ -12698,7 +12870,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) else x509->notBefore.length = 0; if (dCert->afterDateLen > 0) { - minSz = min(dCert->afterDate[1], MAX_DATE_SZ); + minSz = (int)min(dCert->afterDate[1], MAX_DATE_SZ); x509->notAfter.type = dCert->afterDate[0]; x509->notAfter.length = minSz; XMEMCPY(x509->notAfter.data, &dCert->afterDate[2], minSz); @@ -12711,7 +12883,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->pubKey.buffer = (byte*)XMALLOC( dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (x509->pubKey.buffer != NULL) { - x509->pubKeyOID = dCert->keyOID; + x509->pubKeyOID = (int)dCert->keyOID; x509->pubKey.length = dCert->pubKeySize; XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize); } @@ -12719,7 +12891,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) ret = MEMORY_E; #if defined(OPENSSL_ALL) if (ret == 0) { - x509->key.pubKeyOID = dCert->keyOID; + x509->key.pubKeyOID = (int)dCert->keyOID; if (!x509->key.algor) { x509->key.algor = wolfSSL_X509_ALGOR_new(); @@ -12757,7 +12929,7 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) else { XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength); x509->sig.length = dCert->sigLength; - x509->sigOID = dCert->signatureOID; + x509->sigOID = (int)dCert->signatureOID; } #if defined(OPENSSL_ALL) wolfSSL_ASN1_OBJECT_free(x509->algor.algorithm); @@ -12781,19 +12953,21 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } } - x509->altNames = dCert->altNames; - dCert->weOwnAltNames = 0; + /* add alt names from dCert to X509 */ + if (CopyAltNames(&x509->altNames, dCert->altNames, -1, x509->heap) != 0) { + return MEMORY_E; + } #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ !defined(IGNORE_NAME_CONSTRAINTS) /* add copies of email names from dCert to X509 */ - if (CopyAdditionalAltNames(&x509->altNames, dCert->altEmailNames, + if (CopyAltNames(&x509->altNames, dCert->altEmailNames, ASN_RFC822_TYPE, x509->heap) != 0) { return MEMORY_E; } #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) /* add copies of alternate directory names from dCert to X509 */ - if (CopyAdditionalAltNames(&x509->altNames, dCert->altDirNames, + if (CopyAltNames(&x509->altNames, dCert->altDirNames, ASN_DIR_TYPE, x509->heap) != 0) { return MEMORY_E; } @@ -12963,23 +13137,40 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) /* Copy over alternative sig and pubkey. In this case we will allocate new * buffers for them as we have no knowledge of when the DecodedCert is * freed. */ - x509->sapkiDer = (byte*)XMALLOC(dCert->sapkiLen, x509->heap, - DYNAMIC_TYPE_X509_EXT); - x509->altSigAlgDer = (byte*)XMALLOC(dCert->altSigAlgLen, x509->heap, + if (dCert->extSapkiSet) { + x509->sapkiDer = (byte*)XMALLOC(dCert->sapkiLen, x509->heap, DYNAMIC_TYPE_X509_EXT); - x509->altSigValDer = (byte*)XMALLOC(dCert->altSigValLen, x509->heap, - DYNAMIC_TYPE_X509_EXT); - if ((x509->sapkiDer != NULL) && (x509->altSigAlgDer != NULL) && - (x509->altSigValDer != NULL)) { - XMEMCPY(x509->sapkiDer, dCert->sapkiDer, dCert->sapkiLen); - XMEMCPY(x509->altSigAlgDer, dCert->altSigAlgDer, dCert->altSigAlgLen); - XMEMCPY(x509->altSigValDer, dCert->altSigValDer, dCert->altSigValLen); - x509->sapkiLen = dCert->sapkiLen; - x509->altSigAlgLen = dCert->altSigAlgLen; - x509->altSigValLen = dCert->altSigValLen; + if (x509->sapkiDer != NULL) { + XMEMCPY(x509->sapkiDer, dCert->sapkiDer, dCert->sapkiLen); + x509->sapkiLen = dCert->sapkiLen; + } + else { + ret = MEMORY_E; + } } - else { - ret = MEMORY_E; + if (dCert->extAltSigAlgSet) { + x509->altSigAlgDer = (byte*)XMALLOC(dCert->altSigAlgLen, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->altSigAlgDer != NULL) { + XMEMCPY(x509->altSigAlgDer, dCert->altSigAlgDer, + dCert->altSigAlgLen); + x509->altSigAlgLen = dCert->altSigAlgLen; + } + else { + ret = MEMORY_E; + } + } + if (dCert->extAltSigValSet) { + x509->altSigValDer = (byte*)XMALLOC(dCert->altSigValLen, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->altSigValDer != NULL) { + XMEMCPY(x509->altSigValDer, dCert->altSigValDer, + dCert->altSigValLen); + x509->altSigValLen = dCert->altSigValLen; + } + else { + ret = MEMORY_E; + } } #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -13095,7 +13286,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, const unsigned char* keyDer, unsigned int keySz, int* result, void* ctx) { - int ret = NOT_COMPILED_IN; + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); WOLFSSL* ssl = (WOLFSSL*)ctx; if (ssl && ssl->ctx->EccVerifyCb) { @@ -13110,7 +13301,7 @@ static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, unsigned char** out, const unsigned char* keyDer, unsigned int keySz, void* ctx) { - int ret = NOT_COMPILED_IN; + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); WOLFSSL* ssl = (WOLFSSL*)ctx; if (ssl && ssl->ctx->RsaVerifyCb) { @@ -13172,24 +13363,26 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret) /* Determine alert reason */ alertWhy = bad_certificate; - if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) { + if (ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E) || + ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) { alertWhy = certificate_expired; } - else if (ret == ASN_NO_SIGNER_E || ret == ASN_PATHLEN_INV_E || - ret == ASN_PATHLEN_SIZE_E) { + else if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || + ret == WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E) || + ret == WC_NO_ERR_TRACE(ASN_PATHLEN_SIZE_E)) { alertWhy = unknown_ca; } #ifdef OPENSSL_EXTRA - else if (ret == CRL_CERT_REVOKED) { + else if (ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED)) { alertWhy = certificate_revoked; } #endif #if defined(HAVE_RPK) - else if (ret == UNSUPPORTED_CERTIFICATE) { + else if (ret == WC_NO_ERR_TRACE(UNSUPPORTED_CERTIFICATE)) { alertWhy = unsupported_certificate; } #endif /* HAVE_RPK */ - else if (ret == NO_PEER_CERT) { + else if (ret == WC_NO_ERR_TRACE(NO_PEER_CERT)) { #ifdef WOLFSSL_TLS13 if (ssl->options.tls1_3) { alertWhy = certificate_required; @@ -13206,6 +13399,167 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret) ssl->options.isClosed = 1; } + +int SetupStoreCtxCallback(WOLFSSL_X509_STORE_CTX** store_pt, + WOLFSSL* ssl, WOLFSSL_CERT_MANAGER* cm, ProcPeerCertArgs* args, + int cert_err, void* heap, int* x509Free) +{ + WOLFSSL_X509_STORE_CTX* store = NULL; + char* domain = NULL; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509* x509 = NULL; +#endif + + *x509Free = 0; + + store = wolfSSL_X509_STORE_CTX_new_ex(heap); + if (store == NULL) + goto mem_error; + domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING); + if (domain == NULL) + goto mem_error; + + domain[0] = '\0'; + + /* build subject CN as string to return in store */ + if (args->dCertInit && args->dCert && args->dCert->subjectCN) { + int subjectCNLen = args->dCert->subjectCNLen; + if (subjectCNLen > ASN_NAME_MAX-1) + subjectCNLen = ASN_NAME_MAX-1; + if (subjectCNLen > 0) { + XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen); + domain[subjectCNLen] = '\0'; + } + } + +#ifndef OPENSSL_COMPATIBLE_DEFAULTS + store->error = cert_err; +#else + store->error = GetX509Error(cert_err); +#endif + store->error_depth = args->certIdx; + store->discardSessionCerts = 0; + store->domain = domain; + if (ssl != NULL) { + if (ssl->verifyCbCtx != NULL) { + /* Use the WOLFSSL user context if set */ + store->userCtx = ssl->verifyCbCtx; + } + else { + /* Else use the WOLFSSL_CTX user context */ + store->userCtx = ssl->ctx->verifyCbCtx; + } + } + else { + store->userCtx = cm; + } + store->certs = args->certs; + store->totalCerts = args->totalCerts; +#if defined(HAVE_EX_DATA) && \ + (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) + if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX"); + } +#endif + + if (ssl != NULL) { +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + store->store = SSL_STORE(ssl); +#if defined(OPENSSL_EXTRA) + store->depth = args->count; + /* Overwrite with non-default param values in SSL */ + if (ssl->param) { + if (ssl->param->check_time) + store->param->check_time = ssl->param->check_time; + + if (ssl->param->flags) + store->param->flags = ssl->param->flags; +#ifdef WOLFSSL_LOCAL_X509_STORE + else if (SSL_STORE(ssl) && SSL_STORE(ssl)->param && + SSL_STORE(ssl)->param->flags) + store->param->flags = SSL_STORE(ssl)->param->flags; +#endif + + + if (ssl->param->hostName[0]) + XMEMCPY(store->param->hostName, ssl->param->hostName, + WOLFSSL_HOST_NAME_MAX); + + } +#endif /* defined(OPENSSL_EXTRA) */ +#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + #ifdef KEEP_PEER_CERT + if (args->certIdx == 0) { + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); + if (CopyDecodedToX509(&ssl->peerCert, args->dCert) == 0) + WOLFSSL_MSG("Unable to copy to ssl->peerCert"); + store->current_cert = &ssl->peerCert; /* use existing X509 */ + } + else + #endif + { + x509 = wolfSSL_X509_new_ex(heap); + if (x509 == NULL) + goto mem_error; + if (CopyDecodedToX509(x509, args->dCert) == 0) { + store->current_cert = x509; + *x509Free = 1; + } + else { + goto mem_error; + } + } +#endif +#ifdef SESSION_CERTS + store->sesChain = &ssl->session->chain; +#endif + } + *store_pt = store; + return 0; +mem_error: + if (store != NULL) + wolfSSL_X509_STORE_CTX_free(store); +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (x509 != NULL) + wolfSSL_X509_free(x509); +#endif + if (domain != NULL) + XFREE(domain, heap, DYNAMIC_TYPE_STRING); + return MEMORY_E; +} + +void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store, + WOLFSSL* ssl, void* heap, int x509Free) +{ + (void)ssl; + (void)x509Free; + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + wolfSSL_sk_X509_pop_free(store->chain, NULL); + store->chain = NULL; +#endif +#ifdef SESSION_CERTS + if ((ssl != NULL) && (store->discardSessionCerts)) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session->chain.count = 0; + #ifdef WOLFSSL_ALT_CERT_CHAINS + ssl->session->altChain.count = 0; + #endif + } +#endif /* SESSION_CERTS */ + XFREE(store->domain, heap, DYNAMIC_TYPE_STRING); + store->domain = NULL; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (x509Free) + wolfSSL_X509_free(store->current_cert); + store->current_cert = NULL; +#endif + wolfSSL_X509_STORE_CTX_free(store); +} + /* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */ /* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */ @@ -13214,10 +13568,10 @@ void DoCertFatalAlert(WOLFSSL* ssl, int ret) * store->error_depth member to determine index (0=peer, >1 intermediates) */ -int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, +int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int cert_err, ProcPeerCertArgs* args) { - int verify_ok = 0, use_cb = 0; + int verify_ok = 0, use_cb = 0, ret = cert_err; void *heap; if (cm == NULL) { @@ -13227,12 +13581,12 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, heap = (ssl != NULL) ? ssl->heap : cm->heap; /* Determine if verify was okay */ - if (ret == 0) { + if (cert_err == 0) { verify_ok = 1; } /* Determine if verify callback should be used */ - if (ret != 0) { + if (cert_err != 0) { if ((ssl != NULL) && (!ssl->options.verifyNone)) { use_cb = 1; /* always report errors */ } @@ -13257,8 +13611,9 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, ssl->param && ssl->param->hostName[0]) { /* If altNames names is present, then subject common name is ignored */ if (args->dCert->altNames != NULL) { - if (CheckForAltNames(args->dCert, ssl->param->hostName, NULL) != 1) { - if (ret == 0) { + if (CheckForAltNames(args->dCert, ssl->param->hostName, + (word32)XSTRLEN(ssl->param->hostName), NULL) != 1) { + if (cert_err == 0) { ret = DOMAIN_NAME_MISMATCH; WOLFSSL_ERROR_VERBOSE(ret); } @@ -13267,10 +13622,12 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, #ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY else { if (args->dCert->subjectCN) { - if (MatchDomainName(args->dCert->subjectCN, - args->dCert->subjectCNLen, - ssl->param->hostName) == 0) { - if (ret == 0) { + if (MatchDomainName( + args->dCert->subjectCN, + args->dCert->subjectCNLen, + ssl->param->hostName, + (word32)XSTRLEN(ssl->param->hostName)) == 0) { + if (cert_err == 0) { ret = DOMAIN_NAME_MISMATCH; WOLFSSL_ERROR_VERBOSE(ret); } @@ -13279,7 +13636,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, } #else else { - if (ret == 0) { + if (cert_err == 0) { ret = DOMAIN_NAME_MISMATCH; WOLFSSL_ERROR_VERBOSE(ret); } @@ -13291,7 +13648,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, if ((args->dCertInit != 0) && (args->dCert != NULL) && (ssl != NULL) && (ssl->param != NULL) && (XSTRLEN(ssl->param->ipasc) > 0)) { if (CheckIPAddr(args->dCert, ssl->param->ipasc) != 0) { - if (ret == 0) { + if (cert_err == 0) { ret = IPADDR_MISMATCH; WOLFSSL_ERROR_VERBOSE(ret); } @@ -13303,6 +13660,10 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, if ((use_cb && (ssl != NULL) && ((ssl->verifyCallback != NULL) #ifdef OPENSSL_ALL || (ssl->ctx->verifyCertCb != NULL) + #endif + #if defined(WOLFSSL_LOCAL_X509_STORE) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_QT)) + || (SSL_STORE(ssl) != NULL && SSL_STORE(ssl)->verify_cb != NULL) #endif )) #ifndef NO_WOLFSSL_CM_VERIFY @@ -13310,157 +13671,20 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, #endif ) { int verifyFail = 0; - #ifdef WOLFSSL_SMALL_STACK - WOLFSSL_X509_STORE_CTX* store; - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - WOLFSSL_X509* x509; - #endif - char* domain = NULL; - #else - WOLFSSL_X509_STORE_CTX store[1]; - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - WOLFSSL_X509 x509[1]; - #endif - char domain[ASN_NAME_MAX]; - #endif - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509_STORE_CTX* store = NULL; int x509Free = 0; - #endif - - #ifdef WOLFSSL_SMALL_STACK - store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( - sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_STORE); - if (store == NULL) { - return MEMORY_E; - } - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_X509); - if (x509 == NULL) { - XFREE(store, heap, DYNAMIC_TYPE_X509_STORE); - return MEMORY_E; - } - #endif - domain = (char*)XMALLOC(ASN_NAME_MAX, heap, DYNAMIC_TYPE_STRING); - if (domain == NULL) { - XFREE(store, heap, DYNAMIC_TYPE_X509_STORE); - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - XFREE(x509, heap, DYNAMIC_TYPE_X509); - #endif - return MEMORY_E; - } - #endif /* WOLFSSL_SMALL_STACK */ - - XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); - #endif - domain[0] = '\0'; - - /* build subject CN as string to return in store */ - if (args->dCertInit && args->dCert && args->dCert->subjectCN) { - int subjectCNLen = args->dCert->subjectCNLen; - if (subjectCNLen > ASN_NAME_MAX-1) - subjectCNLen = ASN_NAME_MAX-1; - if (subjectCNLen > 0) { - XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen); - domain[subjectCNLen] = '\0'; - } - } - -#ifndef OPENSSL_COMPATIBLE_DEFAULTS - store->error = ret; -#else - store->error = GetX509Error(ret); -#endif - store->error_depth = args->certIdx; - store->discardSessionCerts = 0; - store->domain = domain; - if (ssl != NULL) { - if (ssl->verifyCbCtx != NULL) { - /* Use the WOLFSSL user context if set */ - store->userCtx = ssl->verifyCbCtx; - } - else { - /* Else use the WOLFSSL_CTX user context */ - store->userCtx = ssl->ctx->verifyCbCtx; - } - } - else { - store->userCtx = cm; - } - store->certs = args->certs; - store->totalCerts = args->totalCerts; - #if defined(HAVE_EX_DATA) && \ - (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) - if (wolfSSL_CRYPTO_set_ex_data(&store->ex_data, 0, ssl) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to store ssl context in WOLFSSL_X509_STORE_CTX"); - } - #endif - - if (ssl != NULL) { - #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - store->store = SSL_STORE(ssl); - #if defined(OPENSSL_EXTRA) - store->depth = args->count; - store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( - sizeof(WOLFSSL_X509_VERIFY_PARAM), - heap, DYNAMIC_TYPE_OPENSSL); - if (store->param == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(domain, heap, DYNAMIC_TYPE_STRING); - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - XFREE(x509, heap, DYNAMIC_TYPE_X509); - #endif - XFREE(store, heap, DYNAMIC_TYPE_X509_STORE); - #endif - return MEMORY_E; - } - XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); - /* Overwrite with non-default param values in SSL */ - if (ssl->param) { - if (ssl->param->check_time) - store->param->check_time = ssl->param->check_time; - - if (ssl->param->flags) - store->param->flags = ssl->param->flags; + int setupRet = SetupStoreCtxCallback(&store, ssl, cm, args, cert_err, + heap, &x509Free); - if (ssl->param->hostName[0]) - XMEMCPY(store->param->hostName, ssl->param->hostName, - WOLFSSL_HOST_NAME_MAX); + if (setupRet != 0) + return setupRet; - } - #endif /* defined(OPENSSL_EXTRA) */ - #endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)*/ - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - #ifdef KEEP_PEER_CERT - if (args->certIdx == 0) { - store->current_cert = &ssl->peerCert; /* use existing X509 */ - } - else - #endif - { - InitX509(x509, 0, heap); - if (CopyDecodedToX509(x509, args->dCert) == 0) { - store->current_cert = x509; - x509Free = 1; - } - else { - FreeX509(x509); - } - } - #endif - #ifdef SESSION_CERTS - store->sesChain = &ssl->session->chain; - #endif - } #ifndef NO_WOLFSSL_CM_VERIFY /* non-zero return code indicates failure override */ if (cm->verifyCallback != NULL) { store->userCtx = cm; if (cm->verifyCallback(verify_ok, store)) { - if (ret != 0) { + if (cert_err != 0) { WOLFSSL_MSG("Verify CM callback overriding error!"); ret = 0; } @@ -13476,7 +13700,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, /* non-zero return code indicates failure override */ if (ssl->ctx->verifyCertCb) { if (ssl->ctx->verifyCertCb(store, ssl->ctx->verifyCertCbArg)) { - if (ret != 0) { + if (cert_err != 0) { WOLFSSL_MSG("Verify Cert callback overriding error!"); ret = 0; } @@ -13486,11 +13710,10 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, } } #endif - /* non-zero return code indicates failure override */ if (ssl->verifyCallback) { if (ssl->verifyCallback(verify_ok, store)) { - if (ret != 0) { + if (cert_err != 0) { WOLFSSL_MSG("Verify callback overriding error!"); ret = 0; } @@ -13499,11 +13722,25 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, verifyFail = 1; } } +#if defined(WOLFSSL_LOCAL_X509_STORE) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_QT)) + if (SSL_STORE(ssl) != NULL && SSL_STORE(ssl)->verify_cb != NULL) { + if (SSL_STORE(ssl)->verify_cb(verify_ok, store)) { + if (cert_err != 0) { + WOLFSSL_MSG("Store Verify callback overriding error!"); + ret = 0; + } + } + else { + verifyFail = 1; + } + } +#endif } if (verifyFail) { /* induce error if one not present */ - if (ret == 0) { + if (cert_err == 0) { ret = VERIFY_CERT_ERROR; WOLFSSL_ERROR_VERBOSE(ret); } @@ -13511,36 +13748,7 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, /* mark as verify error */ args->verifyErr = 1; } - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - if (x509Free) { - FreeX509(x509); - } - #endif - #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - wolfSSL_sk_X509_pop_free(store->chain, NULL); - store->chain = NULL; - #endif - #ifdef SESSION_CERTS - if ((ssl != NULL) && (store->discardSessionCerts)) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session->chain.count = 0; - #ifdef WOLFSSL_ALT_CERT_CHAINS - ssl->session->altChain.count = 0; - #endif - } - #endif /* SESSION_CERTS */ -#ifdef OPENSSL_EXTRA - if ((ssl != NULL) && (store->param)) { - XFREE(store->param, heap, DYNAMIC_TYPE_OPENSSL); - } -#endif - #ifdef WOLFSSL_SMALL_STACK - XFREE(domain, heap, DYNAMIC_TYPE_STRING); - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - XFREE(x509, heap, DYNAMIC_TYPE_X509); - #endif - XFREE(store, heap, DYNAMIC_TYPE_X509_STORE); - #endif + CleanupStoreCtxCallback(store, ssl, heap, x509Free); } (void)heap; @@ -13548,6 +13756,50 @@ int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, return ret; } +#ifdef HAVE_CRL +void DoCrlCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, + ProcPeerCertArgs* args, int* outRet) +{ +#if defined(WOLFSSL_LOCAL_X509_STORE) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_QT)) + int ret = 0; + void* heap = (ssl != NULL) ? ssl->heap : cm->heap; + WOLFSSL_X509_STORE* cert_store = (ssl != NULL) ? SSL_STORE(ssl) : NULL; + + if (cert_store != NULL && cert_store->get_crl_cb != NULL) { + WOLFSSL_CRL* userCrl = NULL; + WOLFSSL_X509_STORE_CTX* store = NULL; + int x509Free = 0; + + ret = SetupStoreCtxCallback(&store, ssl, cm, args, 0, heap, + &x509Free); + if (ret != 0) { + *outRet = ret; + return; + } + + ret = cert_store->get_crl_cb(store, &userCrl, store->current_cert); + if (ret == 1 && userCrl != NULL) { + /* Point to current cm to be able to verify CRL */ + userCrl->cm = SSL_CM(ssl); + *outRet = CheckCertCRL(userCrl, args->dCert); + } + else + *outRet = CRL_MISSING; + + if (userCrl != NULL) + wolfSSL_X509_CRL_free(userCrl); + CleanupStoreCtxCallback(store, ssl, heap, x509Free); + } +#else + (void)cm; + (void)ssl; + (void)args; + (void)outRet; +#endif +} +#endif + static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) { ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs; @@ -13618,7 +13870,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type) #if defined(NO_SHA) && !defined(NO_SHA256) retHash = wc_Sha256Hash((const byte*)pbuf, len, dgt); #elif !defined(NO_SHA) - retHash = wc_ShaHash((const byte*)pbuf, len, dgt); + retHash = wc_ShaHash((const byte*)pbuf, (word32)len, dgt); #endif if (retHash == 0) { /* 4 bytes in little endian as unsigned long */ @@ -13688,7 +13940,7 @@ int LoadCertByIssuer(WOLFSSL_X509_STORE* store, X509_NAME* issuer, int type) for (; suffix < MAX_SUFFIX; suffix++) { /* /folder-path/.(r)N[0..9] */ - if (XSNPRINTF(filename, len, "%s/%08lx.%s%d", entry->dir_name, + if (XSNPRINTF(filename, (size_t)len, "%s/%08lx.%s%d", entry->dir_name, hash, post, suffix) >= len) { @@ -13783,6 +14035,7 @@ static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, buffer* cert; byte* subjectHash = NULL; int alreadySigner = 0; + Signer *extraSigners = NULL; #if defined(HAVE_RPK) int cType; #endif @@ -13813,7 +14066,7 @@ PRAGMA_GCC_DIAG_POP /* check if returning from non-blocking OCSP */ /* skip this section because cert is already initialized and parsed */ #ifdef WOLFSSL_NONBLOCK_OCSP - if (args->lastErr == OCSP_WANT_READ) { + if (args->lastErr == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { args->lastErr = 0; /* clear error */ return 0; } @@ -13843,7 +14096,7 @@ PRAGMA_GCC_DIAG_POP } /* perform cert parsing and signature check */ - sigRet = CheckCertSignature(cert->buffer, cert->length, + sigRet = wc_CheckCertSignature(cert->buffer, cert->length, ssl->heap, SSL_CM(ssl)); /* fail on errors here after the ParseCertRelative call, so dCert is populated */ @@ -13884,9 +14137,13 @@ PRAGMA_GCC_DIAG_POP return ret; #endif } - +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (verify != NO_VERIFY && TLSX_CSR2_IsMulti(ssl->extensions)) { + extraSigners = TLSX_CSR2_GetPendingSigners(ssl->extensions); + } +#endif /* Parse Certificate */ - ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl)); + ret = ParseCertRelative(args->dCert, certType, verify, SSL_CM(ssl), extraSigners); #if defined(HAVE_RPK) /* if cert type has negotiated with peer, confirm the cert received has @@ -13919,7 +14176,9 @@ PRAGMA_GCC_DIAG_POP #endif /* HAVE_RPK */ /* perform below checks for date failure cases */ - if (ret == 0 || ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { + if (ret == 0 || + ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) || + ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { /* get subject and determine if already loaded */ #ifndef NO_SKID if (args->dCert->extAuthKeyIdSet) @@ -13930,39 +14189,6 @@ PRAGMA_GCC_DIAG_POP alreadySigner = AlreadySigner(SSL_CM(ssl), subjectHash); } -#ifdef WOLFSSL_DUAL_ALG_CERTS - if ((ret == 0) && (args->dCert->sapkiDer != NULL)) { -#ifndef WOLFSSL_SMALL_STACK - byte der[MAX_CERT_VERIFY_SZ]; -#else - byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, ssl->heap, - DYNAMIC_TYPE_DCERT); - if (der == NULL) { - ret = MEMORY_E; - } -#endif /* ! WOLFSSL_SMALL_STACK */ - - if (ret == 0) { - ret = wc_GeneratePreTBS(args->dCert, der, MAX_CERT_VERIFY_SZ); - - if (ret > 0) { - ret = wc_ConfirmAltSignature(der, ret, - args->dCert->sapkiDer, args->dCert->sapkiLen, - args->dCert->sapkiOID, - args->dCert->altSigValDer, args->dCert->altSigValLen, - args->dCert->altSigAlgOID, ssl->heap); - } -#ifdef WOLFSSL_SMALL_STACK - XFREE(der, ssl->heap, DYNAMIC_TYPE_DCERT); -#endif /* WOLFSSL_SMALL_STACK */ - - if (ret == 0) { - WOLFSSL_MSG("Alternative signature has been verified!"); - } - } - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - #ifdef WOLFSSL_SMALL_CERT_VERIFY /* get signature check failures from above */ if (ret == 0) @@ -13975,7 +14201,7 @@ PRAGMA_GCC_DIAG_POP *pAlreadySigner = alreadySigner; #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, args->dCert->sigCtx.asyncDev); } @@ -13987,7 +14213,7 @@ PRAGMA_GCC_DIAG_POP * original return code is returned. */ if (ssl->ctx && ssl->ctx->ProcessPeerCertCb) { int new_ret = ssl->ctx->ProcessPeerCertCb(ssl, args->dCert); - if (new_ret != NOT_COMPILED_IN) { + if (new_ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { ret = new_ret; } } @@ -14056,7 +14282,6 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) } break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case FALCON_LEVEL1k: if (ssl->options.minFalconKeySz < 0 || @@ -14075,7 +14300,6 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) } break; #endif /* HAVE_FALCON */ - #endif /* HAVE_PQC */ #if defined(HAVE_DILITHIUM) case DILITHIUM_LEVEL2k: if (ssl->options.minDilithiumKeySz < 0 || @@ -14113,10 +14337,12 @@ static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) } #ifdef HAVE_CRL -static int ProcessPeerCertsChainCRLCheck(WOLFSSL_CERT_MANAGER* cm, Signer* ca) +static int ProcessPeerCertsChainCRLCheck(WOLFSSL* ssl, ProcPeerCertArgs* args) { Signer* prev = NULL; int ret = 0; + WOLFSSL_CERT_MANAGER* cm = SSL_CM(ssl); + Signer* ca = args->dCert->ca; /* End loop if no more issuers found or if we have * found a self signed cert (ca == prev) */ for (; ret == 0 && ca != NULL && ca != prev; @@ -14124,7 +14350,12 @@ static int ProcessPeerCertsChainCRLCheck(WOLFSSL_CERT_MANAGER* cm, Signer* ca) ret = CheckCertCRL_ex(cm->crl, ca->issuerNameHash, NULL, 0, ca->serialHash, NULL, 0, NULL); if (ret != 0) + DoCrlCallback(cm, ssl, args, &ret); + if (ret != 0){ + WOLFSSL_ERROR_VERBOSE(ret); + WOLFSSL_MSG("\tCRL check not ok"); break; + } } return ret; } @@ -14145,6 +14376,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, byte* subjectHash = NULL; int alreadySigner = 0; +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + int addToPendingCAs = 0; +#endif WOLFSSL_ENTER("ProcessPeerCerts"); #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) @@ -14158,7 +14392,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args = (ProcPeerCertArgs*)ssl->async->args; #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_ppc; @@ -14166,11 +14400,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, else #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_NONBLOCK_OCSP - if (ssl->error == OCSP_WANT_READ) { + if (ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { /* Re-entry after non-blocking OCSP */ #ifdef WOLFSSL_ASYNC_CRYPT /* if async operationg not pending, reset error code */ - if (ret == WC_NO_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_NO_PENDING_E)) ret = 0; #endif } @@ -14288,7 +14522,25 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_ppc); } c24to32(input + args->idx, &listSz); - args->idx += OPAQUE24_LEN; +#ifdef HAVE_RPK + /* + * If this is RPK from the peer, then single cert (if TLS1.2). + * So, ListSz location is same as CertSz location, so fake + * we have just seen this ListSz. + */ + if (!IsAtLeastTLSv1_3(ssl->version) && + ((ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.rpkState.received_ClientCertTypeCnt == 1 && + ssl->options.rpkState.received_ClientCertTypes[0] == WOLFSSL_CERT_TYPE_RPK) || + (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.rpkState.received_ServerCertTypeCnt == 1 && + ssl->options.rpkState.received_ServerCertTypes[0] == WOLFSSL_CERT_TYPE_RPK))) { + listSz += OPAQUE24_LEN; + } else +#endif /* HAVE_RPK */ + { + args->idx += OPAQUE24_LEN; + } if (listSz > MAX_CERTIFICATE_SZ) { ERROR_OUT(BUFFER_ERROR, exit_ppc); } @@ -14488,7 +14740,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ !defined(NO_STDIO_FILESYSTEM) - if (ret == ASN_NO_SIGNER_E || ret == ASN_SELF_SIGNED_E) { + if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || + ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) { WOLFSSL_MSG("try to load certificate if hash dir is set"); ret = LoadCertByIssuer(SSL_STORE(ssl), (WOLFSSL_X509_NAME*)args->dCert->issuerName, @@ -14508,14 +14761,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) goto exit_ppc; #endif if (ret == 0) { ret = ProcessPeerCertCheckKey(ssl, args); } - else if (ret == ASN_PARSE_E || ret == BUFFER_E || - ret == MEMORY_E) { + else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) || + ret == WC_NO_ERR_TRACE(BUFFER_E) || + ret == WC_NO_ERR_TRACE(MEMORY_E)) { WOLFSSL_MSG( "Got Peer cert ASN PARSE_E, BUFFER E, MEMORY_E"); ERROR_OUT(ret, exit_ppc); @@ -14550,9 +14804,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret == 0) { #ifdef HAVE_OCSP #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { + addToPendingCAs = 0; + if (ssl->status_request_v2 && TLSX_CSR2_IsMulti(ssl->extensions)) { ret = TLSX_CSR2_InitRequests(ssl->extensions, args->dCert, 0, ssl->heap); + addToPendingCAs = 1; } else /* skips OCSP and force CRL check */ #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ @@ -14562,7 +14818,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp, args->dCert, ssl); #ifdef WOLFSSL_NONBLOCK_OCSP - if (ret == OCSP_WANT_READ) { + if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { args->lastErr = ret; goto exit_ppc; } @@ -14586,7 +14842,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, responder, do a CRL lookup. If any other error, skip the CRL lookup and fail the certificate. */ - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); + doCrlLookup = (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN)); } #endif /* HAVE_OCSP */ @@ -14599,19 +14855,21 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, * same WOULD_BLOCK error code as OCSP's I/O * callback, and it is enabling it using the * same flag. */ - if (ret == OCSP_WANT_READ) { + if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { args->lastErr = ret; goto exit_ppc; } #endif + if (ret != 0) + DoCrlCallback(SSL_CM(ssl), ssl, args, &ret); if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); WOLFSSL_MSG("\tCRL check not ok"); } if (ret == 0 && args->certIdx == args->totalCerts-1) { - ret = ProcessPeerCertsChainCRLCheck( - SSL_CM(ssl), args->dCert->ca); + ret = ProcessPeerCertsChainCRLCheck(ssl, + args); if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); WOLFSSL_MSG("\tCRL chain check not ok"); @@ -14640,7 +14898,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, chain mode only requires that the peer certificate validate to a trusted CA */ if (ret != 0 && args->dCert->isCA) { - if (ret == ASN_NO_SIGNER_E || ret == ASN_SELF_SIGNED_E) { + if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || + ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) { if (!ssl->options.usingAltCertChain) { WOLFSSL_MSG("Trying alternate cert chain"); ssl->options.usingAltCertChain = 1; @@ -14663,7 +14922,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, * for a CA cert to fail validation here, as we will verify * the entire chain when we hit the peer (leaf) cert */ if ((ssl->ctx->doAppleNativeCertValidationFlag) - && (ret == ASN_NO_SIGNER_E)) { + && (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E))) { WOLFSSL_MSG("Bypassing errors to allow for Apple native" " CA validation"); @@ -14681,8 +14940,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* Do verify callback */ ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args); if (ssl->options.verifyNone && - (ret == CRL_MISSING || ret == CRL_CERT_REVOKED || - ret == CRL_CERT_DATE_ERR)) { + (ret == WC_NO_ERR_TRACE(CRL_MISSING) || + ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED) || + ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR))) { WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); ret = ssl->error = 0; } @@ -14693,6 +14953,67 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, skipAddCA = 1; } #endif +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ret == 0 && addToPendingCAs && !alreadySigner) { +#ifdef WOLFSSL_SMALL_STACK + DecodedCert *dCertAdd = NULL; +#else + DecodedCert dCertAdd[1]; +#endif + int dCertAdd_inited = 0; + DerBuffer *derBuffer = NULL; + buffer* cert = &args->certs[args->certIdx]; + Signer *s = NULL; + +#ifdef WOLFSSL_SMALL_STACK + dCertAdd = (DecodedCert *) + XMALLOC(sizeof(*dCertAdd), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (dCertAdd == NULL) { + ret = MEMORY_E; + goto exit_req_v2; + } +#endif + InitDecodedCert(dCertAdd, cert->buffer, cert->length, + ssl->heap); + dCertAdd_inited = 1; + ret = ParseCert(dCertAdd, CA_TYPE, NO_VERIFY, + SSL_CM(ssl)); + if (ret != 0) { + goto exit_req_v2; + } + ret = AllocDer(&derBuffer, cert->length, CA_TYPE, ssl->heap); + if (ret != 0 || derBuffer == NULL) { + goto exit_req_v2; + } + XMEMCPY(derBuffer->buffer, cert->buffer, cert->length); + s = MakeSigner(SSL_CM(ssl)->heap); + if (s == NULL) { + ret = MEMORY_E; + goto exit_req_v2; + } + ret = FillSigner(s, dCertAdd, CA_TYPE, derBuffer); + if (ret != 0) { + goto exit_req_v2; + } + skipAddCA = 1; + ret = TLSX_CSR2_AddPendingSigner(ssl->extensions, s); + + exit_req_v2: + if (s && (ret != 0)) + FreeSigner(s, SSL_CM(ssl)->heap); + if (derBuffer) + FreeDer(&derBuffer); + if (dCertAdd_inited) + FreeDecodedCert(dCertAdd); +#ifdef WOLFSSL_SMALL_STACK + if (dCertAdd) + XFREE(dCertAdd, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + if (ret != 0) + goto exit_ppc; + } +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ /* If valid CA then add to Certificate Manager */ if (ret == 0 && args->dCert->isCA && @@ -14775,7 +15096,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT)) && \ !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ !defined(NO_STDIO_FILESYSTEM) - if (ret == ASN_NO_SIGNER_E || ret == ASN_SELF_SIGNED_E) { + if (ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || + ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) { int lastErr = ret; /* save error from last time */ WOLFSSL_MSG("try to load certificate if hash dir is set"); ret = LoadCertByIssuer(SSL_STORE(ssl), @@ -14796,7 +15118,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) goto exit_ppc; #endif if (ret == 0) { @@ -14853,8 +15175,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, args->fatal = 0; } } - else if (ret == ASN_PARSE_E || ret == BUFFER_E || - ret == MEMORY_E || ret == BAD_FUNC_ARG) { + else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) || + ret == WC_NO_ERR_TRACE(BUFFER_E) || + ret == WC_NO_ERR_TRACE(MEMORY_E) || + ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) { WOLFSSL_MSG("Got Peer cert ASN_PARSE_E, BUFFER_E, MEMORY_E," " BAD_FUNC_ARG"); #if defined(WOLFSSL_EXTRA_ALERTS) || defined(OPENSSL_EXTRA) || \ @@ -14872,11 +15196,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) if (ssl->peerVerifyRet == 0) { /* Return first cert error here */ - if (ret == ASN_BEFORE_DATE_E) { + if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) { ssl->peerVerifyRet = (unsigned long)WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID; } - else if (ret == ASN_AFTER_DATE_E) { + else if (ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { ssl->peerVerifyRet = (unsigned long)WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED; } @@ -15014,11 +15338,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = CheckCertOCSP_ex(SSL_CM(ssl)->ocsp, args->dCert, ssl); #ifdef WOLFSSL_NONBLOCK_OCSP - if (ret == OCSP_WANT_READ) { + if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { goto exit_ppc; } #endif - doLookup = (ret == OCSP_CERT_UNKNOWN); + doLookup = (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN)); if (ret != 0) { WOLFSSL_MSG("\tOCSP Lookup not ok"); args->fatal = 0; @@ -15044,10 +15368,12 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, * same WOULD_BLOCK error code as OCSP's I/O * callback, and it is enabling it using the * same flag. */ - if (ret == OCSP_WANT_READ) { + if (ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { goto exit_ppc; } #endif + if (ret != 0) + DoCrlCallback(SSL_CM(ssl), ssl, args, &ret); if (ret != 0) { WOLFSSL_MSG("\tCRL check not ok"); args->fatal = 0; @@ -15066,8 +15392,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, SSL_CM(ssl)->crlCheckAll && args->totalCerts == 1) { /* Check the entire cert chain */ if (args->dCert->ca != NULL) { - ret = ProcessPeerCertsChainCRLCheck(SSL_CM(ssl), - args->dCert->ca); + ret = ProcessPeerCertsChainCRLCheck(ssl, args); if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); WOLFSSL_MSG("\tCRL chain check not ok"); @@ -15087,28 +15412,11 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (args->fatal == 0) { int copyRet = 0; - #ifdef WOLFSSL_POST_HANDSHAKE_AUTH - if (ssl->options.handShakeDone) { - FreeX509(&ssl->peerCert); - InitX509(&ssl->peerCert, 0, ssl->heap); - } - else - #endif - #ifdef HAVE_SECURE_RENEGOTIATION - if (ssl->secure_renegotiation && - ssl->secure_renegotiation->enabled) { - /* free old peer cert */ - FreeX509(&ssl->peerCert); - InitX509(&ssl->peerCert, 0, ssl->heap); - } - else - #endif - { - } - - /* set X509 format for peer cert */ + /* free old peer cert */ + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); copyRet = CopyDecodedToX509(&ssl->peerCert, args->dCert); - if (copyRet == MEMORY_E) { + if (copyRet == WC_NO_ERR_TRACE(MEMORY_E)) { args->fatal = 1; } } @@ -15209,6 +15517,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (args->dCert->altNames) { if (CheckForAltNames(args->dCert, (char*)ssl->buffers.domainName.buffer, + (ssl->buffers.domainName.buffer == NULL ? 0 : + (word32)XSTRLEN( + (const char *)ssl->buffers.domainName.buffer)), NULL) != 1) { WOLFSSL_MSG("DomainName match on alt names failed"); /* try to get peer key still */ @@ -15218,9 +15529,14 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, } else { if (MatchDomainName( - args->dCert->subjectCN, - args->dCert->subjectCNLen, - (char*)ssl->buffers.domainName.buffer) == 0) { + args->dCert->subjectCN, + args->dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer, + (ssl->buffers.domainName.buffer == NULL ? 0 : + (word32)XSTRLEN( + (const char *)ssl->buffers.domainName.buffer) + )) == 0) + { WOLFSSL_MSG("DomainName match on common name failed"); ret = DOMAIN_NAME_MISMATCH; WOLFSSL_ERROR_VERBOSE(ret); @@ -15230,10 +15546,15 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* Old behavior. */ if (MatchDomainName(args->dCert->subjectCN, args->dCert->subjectCNLen, - (char*)ssl->buffers.domainName.buffer) == 0) { + (char*)ssl->buffers.domainName.buffer, + (ssl->buffers.domainName.buffer == NULL ? 0 : + (word32)XSTRLEN(ssl->buffers.domainName.buffer))) == 0) + { WOLFSSL_MSG("DomainName match on common name failed"); if (CheckForAltNames(args->dCert, (char*)ssl->buffers.domainName.buffer, + (ssl->buffers.domainName.buffer == NULL ? 0 : + (word32)XSTRLEN(ssl->buffers.domainName.buffer)), NULL) != 1) { WOLFSSL_MSG( "DomainName match on alt names failed too"); @@ -15525,7 +15846,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: @@ -15575,7 +15895,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif /* HAVE_FALCON */ - #if defined(HAVE_DILITHIUM) + #if defined(HAVE_DILITHIUM) && \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) case DILITHIUM_LEVEL2k: case DILITHIUM_LEVEL3k: case DILITHIUM_LEVEL5k: @@ -15628,7 +15949,6 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ default: break; } @@ -15687,8 +16007,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DoVerifyCallback(SSL_CM(ssl), ssl, ret, args); if (ssl->options.verifyNone && - (ret == CRL_MISSING || ret == CRL_CERT_REVOKED || - ret == CRL_CERT_DATE_ERR)) { + (ret == WC_NO_ERR_TRACE(CRL_MISSING) || + ret == WC_NO_ERR_TRACE(CRL_CERT_REVOKED) || + ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR))) { WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); ret = ssl->error = 0; } @@ -15735,7 +16056,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) - if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) || + ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_certificate = 0; @@ -15781,7 +16103,8 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* Reset the session cert chain count in case the session resume failed, * do not reset if we are resuming after an async wait */ #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) - if (ssl->error != OCSP_WANT_READ && ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(OCSP_WANT_READ) && + ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { ssl->session->chain.count = 0; @@ -15810,6 +16133,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, int ret = 0; byte status_type; word32 status_length; + int endCertificateOK = 0; WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO); WOLFSSL_ENTER("DoCertificateStatus"); @@ -15833,6 +16157,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */ case WOLFSSL_CSR2_OCSP: ret = ProcessCSR(ssl, input, inOutIdx, status_length); + endCertificateOK = (ret == 0); break; #endif @@ -15843,6 +16168,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, OcspRequest* request; word32 list_length = status_length; byte idx = 0; + Signer *pendingCAs = NULL; #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -15854,14 +16180,12 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, OcspResponse response[1]; #endif - do { - if (ssl->status_request_v2) { - ssl->status_request_v2 = 0; - break; - } - + if (!ssl->status_request_v2) return BUFFER_ERROR; - } while(0); + + ssl->status_request_v2 = 0; + + pendingCAs = TLSX_CSR2_GetPendingSigners(ssl->extensions); #ifdef WOLFSSL_SMALL_STACK status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, @@ -15901,23 +16225,27 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (status_length) { InitOcspResponse(response, single, status, input +*inOutIdx, status_length, ssl->heap); - + response->pendingCAs = pendingCAs; if ((OcspResponseDecode(response, SSL_CM(ssl), ssl->heap, 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) || (response->single->status->status != CERT_GOOD)) ret = BAD_CERTIFICATE_STATUS_ERROR; - while (ret == 0) { + if (ret == 0) { request = (OcspRequest*)TLSX_CSR2_GetRequest( - ssl->extensions, status_type, idx++); + ssl->extensions, status_type, idx); - if (request == NULL) + if (request == NULL) { ret = BAD_CERTIFICATE_STATUS_ERROR; - else if (CompareOcspReqResp(request, response) == 0) - break; - else if (idx == 1) /* server cert must be OK */ + } + else if (CompareOcspReqResp(request, response) != 0) { ret = BAD_CERTIFICATE_STATUS_ERROR; + } + else { + if (idx == 0) /* server cert must be OK */ + endCertificateOK = 1; + } } /* only frees 'single' if single->isDynamic is set */ @@ -15926,6 +16254,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, *inOutIdx += status_length; list_length -= status_length; } + idx++; } ssl->status_request_v2 = 0; @@ -15945,6 +16274,20 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = BUFFER_ERROR; } + /* end certificate MUST be present */ + if (endCertificateOK == 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ret == 0) { + if (TLSX_CSR2_MergePendingCA(ssl) < 0) { + WOLFSSL_MSG("Failed to merge pending CAs"); + } + } + else { + TLSX_CSR2_ClearPendingCA(ssl); + } +#endif + if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); SendAlert(ssl, alert_fatal, bad_certificate_status_response); @@ -16348,44 +16691,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E); return OUT_OF_ORDER_E; } -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ - defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) - if (ssl->msgsReceived.got_certificate_status == 0) { - int csrRet = 0; -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (csrRet == 0 && ssl->status_request) { - WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); - csrRet = TLSX_CSR_ForceRequest(ssl); - } -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (csrRet == 0 && ssl->status_request_v2) { - WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); - csrRet = TLSX_CSR2_ForceRequest(ssl); - } -#endif - if (csrRet != 0) { - /* Error out if OCSP lookups are enabled and failed or if - * the user requires stapling. */ - if (SSL_CM(ssl)->ocspEnabled || SSL_CM(ssl)->ocspMustStaple) - return csrRet; - } - /* Check that a status request extension was seen as the - * CertificateStatus wasn't when an OCSP staple is required. - */ - if ( -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - !ssl->status_request && -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - !ssl->status_request_v2 && -#endif - SSL_CM(ssl)->ocspMustStaple) { - WOLFSSL_ERROR_VERBOSE(OCSP_CERT_UNKNOWN); - return OCSP_CERT_UNKNOWN; - } - } -#endif break; #endif @@ -16458,6 +16763,54 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) return OUT_OF_ORDER_E; } } +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ssl->msgsReceived.got_certificate_status == 0) { + int csrRet = 0; +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (csrRet == 0 && ssl->status_request) { + WOLFSSL_MSG("No CertificateStatus before ServerHelloDone"); + csrRet = TLSX_CSR_ForceRequest(ssl); + } +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (csrRet == 0 && ssl->status_request_v2) { + WOLFSSL_MSG("No CertificateStatus before ServerHelloDone"); + csrRet = TLSX_CSR2_ForceRequest(ssl); + } + if (ssl->status_request_v2) { + if (csrRet == 0) { + if (TLSX_CSR2_MergePendingCA(ssl) < 0) { + WOLFSSL_MSG("Failed to merge pending CAs"); + } + } + else { + TLSX_CSR2_ClearPendingCA(ssl); + } + } +#endif + if (csrRet != 0) { + /* Error out if OCSP lookups are enabled and failed or if + * the user requires stapling. */ + if (SSL_CM(ssl)->ocspEnabled || SSL_CM(ssl)->ocspMustStaple) + return csrRet; + } + /* Check that a status request extension was seen as the + * CertificateStatus wasn't when an OCSP staple is required. + */ + if ( +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + !ssl->status_request && +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + !ssl->status_request_v2 && +#endif + SSL_CM(ssl)->ocspMustStaple) { + WOLFSSL_ERROR_VERBOSE(OCSP_CERT_UNKNOWN); + return OCSP_CERT_UNKNOWN; + } + } +#endif break; #endif @@ -16734,7 +17087,7 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, && ssl->error != OCSP_WANT_READ #endif ) { - ret = HashInput(ssl, input + *inOutIdx, size); + ret = HashInput(ssl, input + *inOutIdx, (int)size); if (ret != 0) { WOLFSSL_MSG("Incomplete handshake hashes"); return ret; @@ -16827,7 +17180,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, IsAtLeastTLSv1_3(ssl->version)) { #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) - if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E) && + ret != WC_NO_ERR_TRACE(OCSP_WANT_READ)) #endif { ssl->options.cacheMessages = 0; @@ -16909,7 +17263,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ssl->options.resuming || !ssl->options.verifyPeer || \ !IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) { #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) - if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E) && + ret != WC_NO_ERR_TRACE(OCSP_WANT_READ)) #endif { ssl->options.cacheMessages = 0; @@ -16975,7 +17330,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) /* if async, offset index so this msg will be processed again */ - if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) { + if ((ret == WC_NO_ERR_TRACE(WC_PENDING_E) || + ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) && *inOutIdx > 0) { *inOutIdx -= HANDSHAKE_HEADER_SZ; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -16985,7 +17341,8 @@ int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } /* make sure async error is cleared */ - if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) { + if (ret == 0 && (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) || + ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ))) { ssl->error = 0; } #endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ @@ -17108,7 +17465,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* for async this copy was already done, do not replace, since @@ -17128,7 +17485,7 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->arrays->pendingMsgSz - idx, ssl->arrays->pendingMsgSz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* setup to process fragment again */ ssl->arrays->pendingMsgOffset -= inputLength; *inOutIdx -= inputLength; @@ -17160,43 +17517,41 @@ int SendFatalAlertOnly(WOLFSSL *ssl, int error) switch (error) { /* not fatal errors */ - case WANT_WRITE: - case WANT_READ: - case ZERO_RETURN: + case WC_NO_ERR_TRACE(WANT_WRITE): + case WC_NO_ERR_TRACE(WANT_READ): + case WC_NO_ERR_TRACE(ZERO_RETURN): #ifdef WOLFSSL_NONBLOCK_OCSP - case OCSP_WANT_READ: + case WC_NO_ERR_TRACE(OCSP_WANT_READ): #endif #ifdef WOLFSSL_ASYNC_CRYPT - case WC_PENDING_E: + case WC_NO_ERR_TRACE(WC_PENDING_E): #endif return 0; /* peer already disconnected and ssl is possibly in bad state * don't try to send an alert */ - case SOCKET_ERROR_E: + case WC_NO_ERR_TRACE(SOCKET_ERROR_E): return error; - case BUFFER_ERROR: - case ASN_PARSE_E: - case COMPRESSION_ERROR: + case WC_NO_ERR_TRACE(BUFFER_ERROR): + case WC_NO_ERR_TRACE(ASN_PARSE_E): + case WC_NO_ERR_TRACE(COMPRESSION_ERROR): why = decode_error; break; - case MATCH_SUITE_ERROR: - why = illegal_parameter; - break; - case VERIFY_FINISHED_ERROR: - case SIG_VERIFY_E: + case WC_NO_ERR_TRACE(VERIFY_FINISHED_ERROR): + case WC_NO_ERR_TRACE(SIG_VERIFY_E): why = decrypt_error; break; - case DUPLICATE_MSG_E: - case NO_CHANGE_CIPHER_E: - case OUT_OF_ORDER_E: + case WC_NO_ERR_TRACE(DUPLICATE_MSG_E): + case WC_NO_ERR_TRACE(NO_CHANGE_CIPHER_E): + case WC_NO_ERR_TRACE(OUT_OF_ORDER_E): why = unexpected_message; break; - case ECC_OUT_OF_RANGE_E: + case WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E): why = bad_record_mac; break; - case VERSION_ERROR: + case WC_NO_ERR_TRACE(MATCH_SUITE_ERROR): + case WC_NO_ERR_TRACE(VERSION_ERROR): default: why = handshake_failure; break; @@ -17680,12 +18035,12 @@ int DtlsMsgDrain(WOLFSSL* ssl) DtlsTxMsgListClean(ssl); } else if (!IsAtLeastTLSv1_3(ssl->version)) { - if (SendFatalAlertOnly(ssl, ret) == SOCKET_ERROR_E) { + if (SendFatalAlertOnly(ssl, ret) == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { ret = SOCKET_ERROR_E; } } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { break; } #endif @@ -18034,7 +18389,7 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, /* add cipher info and then its length */ XMEMSET(padding, 0, sizeof(padding)); - if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0) + if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, (word32)msglen)) != 0) return ret; /* 32 bit size of cipher to 64 bit endian */ @@ -18419,7 +18774,7 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, return ret; } if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, - sizeof(add), input, msgLen, tag, sizeof(tag))) != 0) { + sizeof(add), input, (word32)msgLen, tag, sizeof(tag))) != 0) { ForceZero(poly, sizeof(poly)); #ifdef WOLFSSL_CHECK_MEM_ZERO wc_MemZero_Check(poly, CHACHA20_256_KEY_SIZE); @@ -18443,7 +18798,7 @@ int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, /* if the tag was good decrypt message */ if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, - input, msgLen)) != 0) + input, (word32)msgLen)) != 0) return ret; #ifdef CHACHA_AEAD_TEST @@ -18542,7 +18897,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E && asyncOkay) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) { ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif @@ -18560,7 +18915,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, #endif ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E && asyncOkay) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) { ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif @@ -18631,7 +18986,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, ssl->encrypt.additional, AEAD_AUTH_DATA_SZ); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif /* HAVE_PK_CALLBACKS */ { ret = aes_auth_fn(ssl->encrypt.aes, @@ -18644,7 +18999,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E && asyncOkay) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) { ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif @@ -18734,7 +19089,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, #endif ret = wc_Sm4CbcEncrypt(ssl->encrypt.sm4, out, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E && asyncOkay) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) { ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif @@ -18798,7 +19153,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, ssl->encrypt.additional, AEAD_AUTH_DATA_SZ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E && asyncOkay) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && asyncOkay) { ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif @@ -18828,7 +19183,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, #ifdef WOLFSSL_ASYNC_CRYPT /* if async is not okay, then block */ - if (ret == WC_PENDING_E && !asyncOkay) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && !asyncOkay) { ret = wc_AsyncWait(ret, asyncDev, event_flags); } #endif @@ -18842,7 +19197,7 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, int ret = 0; #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->error == WC_PENDING_E) { + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { ssl->error = 0; /* clear async */ } #endif @@ -18935,7 +19290,7 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, #ifdef WOLFSSL_ASYNC_CRYPT /* If pending, then leave and return will resume below */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -19031,7 +19386,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev); } #endif @@ -19049,7 +19404,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, #endif ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } #endif @@ -19115,7 +19470,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, ssl->decrypt.additional, AEAD_AUTH_DATA_SZ); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif /* HAVE_PK_CALLBACKS */ { if ((ret = aes_auth_fn(ssl->decrypt.aes, @@ -19127,7 +19482,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, ssl->specs.aead_mac_size, ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } @@ -19213,7 +19568,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, #endif ret = wc_Sm4CbcDecrypt(ssl->decrypt.sm4, plain, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } #endif @@ -19274,7 +19629,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, ssl->specs.aead_mac_size, ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.sm4->asyncDev); } @@ -19314,9 +19669,9 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* check for still pending */ - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; ssl->error = 0; /* clear async */ @@ -19431,7 +19786,7 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) #ifdef WOLFSSL_ASYNC_CRYPT /* If pending, leave and return below */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -20076,7 +20431,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff) idx += rawSz; ssl->buffers.clearOutputBuffer.buffer = rawData; - ssl->buffers.clearOutputBuffer.length = dataSz; + ssl->buffers.clearOutputBuffer.length = (unsigned int)dataSz; } idx += ssl->keys.padSz; @@ -20445,14 +20800,14 @@ static int GetInputData(WOLFSSL *ssl, word32 size) /* remove processed data */ ssl->buffers.inputBuffer.idx = 0; - ssl->buffers.inputBuffer.length = usedLength; + ssl->buffers.inputBuffer.length = (word32)usedLength; /* read data from network */ do { int in = wolfSSLReceive(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.length, - inSz); + (word32)inSz); if (in == WANT_READ) return WANT_READ; @@ -20503,7 +20858,7 @@ static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz, } ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, PEER_ORDER); - ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz); + ret |= ConstantCompare(verify, input + msgSz - digestSz, (int)digestSz); if (ret != 0) { WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); return VERIFY_MAC_ERROR; @@ -20543,12 +20898,14 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, void* ctx = wolfSSL_GetVerifyMacCtx(ssl); ret = ssl->ctx->VerifyMacCb(ssl, input, (msgSz - ivExtra) - digestSz - pad - 1, - digestSz, content, ctx); - if (ret != 0 && ret != PROTOCOLCB_UNAVAILABLE) { + digestSz, (word32)content, ctx); + if (ret != 0 && + ret != WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) { return ret; } } - if (!ssl->ctx->VerifyMacCb || ret == PROTOCOLCB_UNAVAILABLE) + if (!ssl->ctx->VerifyMacCb || + ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) #endif ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra, content); @@ -20569,9 +20926,9 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, } (void)PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */ ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, - pad, content, 1, PEER_ORDER); + (int)pad, content, 1, PEER_ORDER); if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1, - digestSz) != 0) { + (int)digestSz) != 0) { WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); return VERIFY_MAC_ERROR; } @@ -20584,7 +20941,7 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, else if (ssl->specs.cipher_type == stream) { ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, PEER_ORDER); - if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0) { + if (ConstantCompare(verify, input + msgSz - digestSz, (int)digestSz) != 0) { WOLFSSL_ERROR_VERBOSE(VERIFY_MAC_ERROR); return VERIFY_MAC_ERROR; } @@ -20640,7 +20997,8 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode) } if ((ssl->options.handShakeDone && retcode != 0) - || retcode == SEQUENCE_ERROR || retcode == DTLS_CID_ERROR) { + || retcode == WC_NO_ERR_TRACE(SEQUENCE_ERROR) + || retcode == WC_NO_ERR_TRACE(DTLS_CID_ERROR)) { WOLFSSL_MSG_EX("Silently dropping DTLS message: %d", retcode); return 1; } @@ -20700,7 +21058,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #ifdef WOLFSSL_NONBLOCK_OCSP && ssl->error != OCSP_WANT_READ #endif - && (allowSocketErr != 1 || ssl->error != SOCKET_ERROR_E) + && (allowSocketErr != 1 || + ssl->error != WC_NO_ERR_TRACE(SOCKET_ERROR_E)) ) { WOLFSSL_MSG("ProcessReply retry in error state, not allowed"); return ssl->error; @@ -20711,7 +21070,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #if defined(WOLFSSL_CHECK_ALERT_ON_ERR) && \ (defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP)) if (allowSocketErr == 1 && \ - (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) { + (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) || + ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ))) { return ssl->error; } #endif @@ -20770,7 +21130,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* get header or return error */ if (!ssl->options.dtls) { - if ((ret = GetInputData(ssl, readSz)) < 0) + if ((ret = GetInputData(ssl, (word32)readSz)) < 0) return ret; } else { #ifdef WOLFSSL_DTLS @@ -20778,7 +21138,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; if (used < readSz) { - if ((ret = GetInputData(ssl, readSz)) < 0) + if ((ret = GetInputData(ssl, (word32)readSz)) < 0) return ret; } #endif @@ -20892,7 +21252,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #endif if (ret != 0) { switch (ret) { - case VERSION_ERROR: + case WC_NO_ERR_TRACE(VERSION_ERROR): /* send alert per RFC5246 Appendix E. Backward * Compatibility */ if (ssl->options.side == WOLFSSL_CLIENT_END) @@ -20900,7 +21260,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) wolfssl_alert_protocol_version); break; #ifdef HAVE_MAX_FRAGMENT - case LENGTH_ERROR: + case WC_NO_ERR_TRACE(LENGTH_ERROR): SendAlert(ssl, alert_fatal, record_overflow); break; #endif /* HAVE_MAX_FRAGMENT */ @@ -20987,7 +21347,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ssl->buffers.inputBuffer.idx, ssl->curSize, ssl->curRL.type); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif if (ret < 0) { @@ -21134,7 +21494,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif @@ -21218,7 +21578,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ssl->curSize, ssl->curRL.type, &ssl->keys.padSz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif if (ret < 0) { @@ -21369,14 +21729,15 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); - if (ret == 0 || ret == WC_PENDING_E) { + if (ret == 0 || + ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Reset timeout as we have received a valid * DTLS handshake message */ ssl->dtls_timeout = ssl->dtls_timeout_init; } else { if (SendFatalAlertOnly(ssl, ret) - == SOCKET_ERROR_E) { + == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { ret = SOCKET_ERROR_E; } } @@ -21417,7 +21778,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); if (ret != 0) { - if (SendFatalAlertOnly(ssl, ret) == SOCKET_ERROR_E) + if (SendFatalAlertOnly(ssl, ret) == + WC_NO_ERR_TRACE(SOCKET_ERROR_E)) ret = SOCKET_ERROR_E; } #else @@ -21457,7 +21819,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) * Current message should have been DtlsMsgStore'ed and * should be processed with DtlsMsgDrain */ && (!ssl->options.dtls - || ret != WC_PENDING_E) + || ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif ) { WOLFSSL_ERROR(ret); @@ -21570,7 +21932,8 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) /* Check for duplicate CCS message in DTLS mode. * DTLS allows for duplicate messages, and it should be * skipped. Also skip if out of order. */ - if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E) + if (ret != WC_NO_ERR_TRACE(DUPLICATE_MSG_E) && + ret != WC_NO_ERR_TRACE(OUT_OF_ORDER_E)) return ret; /* Reset error */ ret = 0; @@ -21665,7 +22028,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) defined(HAVE_SECURE_RENEGOTIATION) /* Not really an error. We will return after cleaning * up the processReply state. */ - if (ret != APP_DATA_READY) + if (ret != WC_NO_ERR_TRACE(APP_DATA_READY)) #endif return ret; } @@ -21794,7 +22157,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #endif #if defined(WOLFSSL_DTLS13) || defined(HAVE_SECURE_RENEGOTIATION) /* Signal to user that we have application data ready to read */ - if (ret == APP_DATA_READY) + if (ret == WC_NO_ERR_TRACE(APP_DATA_READY)) return ret; #endif /* It is safe to shrink the input buffer here now. local vars will @@ -21868,7 +22231,7 @@ int SendChangeCipher(WOLFSSL* ssl) input[0] = 1; /* turn it on */ #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, input, inputSz, change_cipher_hs)) != 0) { + (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, change_cipher_hs)) != 0) { return ret; } #endif @@ -21881,7 +22244,7 @@ int SendChangeCipher(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS else { if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, change_cipher_hs)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, change_cipher_hs)) != 0) return ret; DtlsSEQIncrement(ssl, CUR_ORDER); } @@ -21985,7 +22348,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, ret = wc_Md5Final(&md5, result); #ifdef WOLFSSL_ASYNC_CRYPT /* TODO: Make non-blocking */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); } #endif @@ -22005,7 +22368,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, ret = wc_Md5Final(&md5, digest); #ifdef WOLFSSL_ASYNC_CRYPT /* TODO: Make non-blocking */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); } #endif @@ -22035,7 +22398,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, ret = wc_ShaFinal(&sha, result); #ifdef WOLFSSL_ASYNC_CRYPT /* TODO: Make non-blocking */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); } #endif @@ -22055,7 +22418,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, ret = wc_ShaFinal(&sha, digest); #ifdef WOLFSSL_ASYNC_CRYPT /* TODO: Make non-blocking */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); } #endif @@ -22288,7 +22651,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, args = &ssl->async->buildArgs; ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_buildmsg; @@ -22302,7 +22665,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, /* Reset state */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_NO_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_NO_PENDING_E)) #endif { ret = 0; @@ -22531,7 +22894,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, { if (ssl->ctx->MacEncryptCb) { ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx, - output + args->headerSz + args->ivSz, inSz, + output + args->headerSz + args->ivSz, (unsigned int)inSz, type, 0, output + args->headerSz, output + args->headerSz, args->size, ssl->MacEncryptCtx); @@ -22563,7 +22926,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif ret = ssl->hmac(ssl, hmac, - output + args->headerSz + args->ivSz, inSz, + output + args->headerSz + args->ivSz, (word32)inSz, -1, type, 0, epochOrder); XMEMCPY(output + args->idx, hmac, args->digestSz); @@ -22575,7 +22938,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif { ret = ssl->hmac(ssl, output + args->idx, output + - args->headerSz + args->ivSz, inSz, -1, type, 0, epochOrder); + args->headerSz + args->ivSz, (word32)inSz, -1, type, 0, epochOrder); } } #endif /* WOLFSSL_AEAD_ONLY */ @@ -22636,7 +22999,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, if (ret != 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* Zeroize plaintext. */ @@ -22713,7 +23076,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, WOLFSSL_LEAVE("BuildMessage", ret); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -22728,7 +23091,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, /* return sz on success */ if (ret == 0) { - ret = args->sz; + ret = (int)args->sz; } else { WOLFSSL_ERROR_VERBOSE(ret); @@ -22925,7 +23288,7 @@ static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request, InitDecodedCert(cert, certData, length, ssl->heap); /* TODO: Setup async support here */ - ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, SSL_CM(ssl)); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, SSL_CM(ssl), NULL); if (ret != 0) { WOLFSSL_MSG("ParseCert failed"); } @@ -23022,9 +23385,9 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, ssl->heap); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED || - ret == OCSP_CERT_UNKNOWN || - ret == OCSP_LOOKUP_FAIL) { + if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) || + ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) || + ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) { ret = 0; } } @@ -23076,6 +23439,9 @@ int SendCertificate(WOLFSSL* ssl) int ret = 0; word32 certSz, certChainSz, headerSz, listSz, payloadSz; word32 length, maxFragment; +#ifdef HAVE_RPK + int usingRpkTls12 = 0; +#endif /* HAVE_RPK */ WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); WOLFSSL_ENTER("SendCertificate"); @@ -23085,6 +23451,21 @@ int SendCertificate(WOLFSSL* ssl) return 0; /* not needed */ } +#ifdef HAVE_RPK + if (!IsAtLeastTLSv1_3(ssl->version)) { + /* If this is (D)TLS1.2 and RPK, then single cert, not list. */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1 && + ssl->options.rpkState.sending_ServerCertTypes[0] == WOLFSSL_CERT_TYPE_RPK) + usingRpkTls12 = 1; + } else if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1 && + ssl->options.rpkState.sending_ClientCertTypes[0] == WOLFSSL_CERT_TYPE_RPK) + usingRpkTls12 = 1; + } + } +#endif /* HAVE_RPK */ + if (ssl->options.sendVerify == SEND_BLANK_CERT) { #ifdef OPENSSL_EXTRA if (ssl->version.major == SSLv3_MAJOR @@ -23107,10 +23488,19 @@ int SendCertificate(WOLFSSL* ssl) return BUFFER_ERROR; } certSz = ssl->buffers.certificate->length; - headerSz = 2 * CERT_HEADER_SZ; +#ifdef HAVE_RPK + if (usingRpkTls12) { + headerSz = 1 * CERT_HEADER_SZ; + listSz = certSz; + } else { +#endif /* HAVE_RPK */ + headerSz = 2 * CERT_HEADER_SZ; + listSz = certSz + CERT_HEADER_SZ; +#ifdef HAVE_RPK + } +#endif /* HAVE_RPK */ /* list + cert size */ length = certSz + headerSz; - listSz = certSz + CERT_HEADER_SZ; /* may need to send rest of chain, already has leading size(s) */ if (certSz && ssl->buffers.certChain) { @@ -23129,7 +23519,7 @@ int SendCertificate(WOLFSSL* ssl) maxFragment = MAX_RECORD_SIZE; - maxFragment = wolfSSL_GetMaxFragSize(ssl, maxFragment); + maxFragment = (word32)wolfSSL_GetMaxFragSize(ssl, (int)maxFragment); while (length > 0 && ret == 0) { byte* output = NULL; @@ -23203,12 +23593,18 @@ int SendCertificate(WOLFSSL* ssl) } /* list total */ - c32to24(listSz, output + i); - if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) - HashRaw(ssl, output + i, CERT_HEADER_SZ); - i += CERT_HEADER_SZ; - length -= CERT_HEADER_SZ; - fragSz -= CERT_HEADER_SZ; +#ifdef HAVE_RPK + if (!usingRpkTls12) { +#endif /* HAVE_RPK */ + c32to24(listSz, output + i); + if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) + HashRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; +#ifdef HAVE_RPK + } +#endif /* HAVE_RPK */ if (certSz) { c32to24(certSz, output + i); if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) @@ -23218,10 +23614,10 @@ int SendCertificate(WOLFSSL* ssl) fragSz -= CERT_HEADER_SZ; if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) { - HashRaw(ssl, ssl->buffers.certificate->buffer, certSz); + HashRaw(ssl, ssl->buffers.certificate->buffer, (int)certSz); if (certChainSz) HashRaw(ssl, ssl->buffers.certChain->buffer, - certChainSz); + (int)certChainSz); } } } @@ -23260,7 +23656,7 @@ int SendCertificate(WOLFSSL* ssl) if (IsEncryptionOn(ssl, 1)) { byte* input = NULL; - int inputSz = i; /* build msg adds rec hdr */ + int inputSz = (int)i; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; if (ssl->options.dtls) @@ -23289,7 +23685,7 @@ int SendCertificate(WOLFSSL* ssl) handshake, 1, 0, 0, CUR_ORDER); else /* DTLS 1.2 has to ignore fragmentation in hashing so we need to * calculate the hash ourselves above */ { - if ((ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, certificate)) != 0) { XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); return ret; } @@ -23304,10 +23700,10 @@ int SendCertificate(WOLFSSL* ssl) return sendSz; } else { - sendSz = i; + sendSz = (int)i; #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, certificate)) != 0) return ret; } if (ssl->options.dtls) @@ -23420,7 +23816,7 @@ int SendCertificateRequest(WOLFSSL* ssl) /* get output buffer */ output = GetOutputBuffer(ssl); - AddHeaders(output, reqSz, certificate_request, ssl); + AddHeaders(output, (word32)reqSz, certificate_request, ssl); /* write to output */ output[i++] = (byte)typeTotal; /* # of types */ @@ -23487,7 +23883,7 @@ int SendCertificateRequest(WOLFSSL* ssl) if (IsEncryptionOn(ssl, 1)) { byte* input = NULL; - int inputSz = i; /* build msg adds rec hdr */ + int inputSz = (int)i; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; if (ssl->options.dtls) @@ -23506,7 +23902,7 @@ int SendCertificateRequest(WOLFSSL* ssl) XMEMCPY(input, output + recordHeaderSz, inputSz); #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate_request)) != 0) { + (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, certificate_request)) != 0) { XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); return ret; } @@ -23518,10 +23914,10 @@ int SendCertificateRequest(WOLFSSL* ssl) if (sendSz < 0) return sendSz; } else { - sendSz = i; + sendSz = (int)i; #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate_request)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, certificate_request)) != 0) return ret; } if (ssl->options.dtls) @@ -23565,6 +23961,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, byte* output = NULL; word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; word32 length = ENUM_LEN; + word32 headerSz= idx; int sendSz = 0; int ret = 0; int i = 0; @@ -23584,88 +23981,42 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, default: return 0; } +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + headerSz = idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ; + sendSz = idx + length; - sendSz = idx + length; + } else +#endif + sendSz = (int)(idx + length); if (ssl->keys.encryptionOn) sendSz += MAX_MSG_EXTRA; - /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state - * is not advanced yet */ - ssl->options.buildingMsg = 1; - - if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) { - output = GetOutputBuffer(ssl); - - AddHeaders(output, length, certificate_status, ssl); - - output[idx++] = type; - - if (type == WOLFSSL_CSR2_OCSP_MULTI) { - c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx); - idx += OPAQUE24_LEN; - } + output =(byte*)XMALLOC(sendSz, ssl->heap, DYNAMIC_TYPE_OCSP); + if (output == NULL) + return MEMORY_E; - for (i = 0; i < count; i++) { - c32to24(status[i].length, output + idx); - idx += OPAQUE24_LEN; + AddHeaders(output, length, certificate_status, ssl); - XMEMCPY(output + idx, status[i].buffer, status[i].length); - idx += status[i].length; - } + output[idx++] = type; - if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = idx; /* build msg adds rec hdr */ - int recordHeaderSz = RECORD_HEADER_SZ; - - if (ssl->options.dtls) - recordHeaderSz += DTLS_RECORD_EXTRA; - inputSz -= recordHeaderSz; - input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); - if (input == NULL) - return MEMORY_E; - - XMEMCPY(input, output + recordHeaderSz, inputSz); - #ifdef WOLFSSL_DTLS - ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate_status); - #endif - if (ret == 0) - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0, CUR_ORDER); - XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); - - if (sendSz < 0) - ret = sendSz; - } - else { - #ifdef WOLFSSL_DTLS - if (ret == 0 && IsDtlsNotSctpMode(ssl)) - ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate_status); - if (ret == 0 && ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); - } + if (type == WOLFSSL_CSR2_OCSP_MULTI) { + c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx); + idx += OPAQUE24_LEN; + } - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) - if (ret == 0 && ssl->hsInfoOn) - AddPacketName(ssl, "CertificateStatus"); - if (ret == 0 && ssl->toInfoOn) { - ret = AddPacketInfo(ssl, "CertificateStatus", handshake, output, - sendSz, WRITE_PROTO, 0, ssl->heap); - if (ret != 0) - return ret; - } - #endif + for (i = 0; i < count; i++) { + c32to24(status[i].length, output + idx); + idx += OPAQUE24_LEN; - if (ret == 0) { - ssl->options.buildingMsg = 0; - ssl->buffers.outputBuffer.length += sendSz; - if (!ssl->options.groupMessages) - ret = SendBuffered(ssl); - } + XMEMCPY(output + idx, status[i].buffer, status[i].length); + idx += status[i].length; } + /* Send Message. Handled message fragmentation in the function if needed */ + ret = SendHandshakeMsg(ssl, output, (sendSz - headerSz), certificate_status, + "Certificate Status"); + XFREE(output, ssl->heap, DYNAMIC_TYPE_OCSP); WOLFSSL_LEAVE("BuildCertificateStatus", ret); return ret; @@ -23718,7 +24069,8 @@ int SendCertificateStatus(WOLFSSL* ssl) } /* Let's not error out the connection if we can't verify our cert */ - if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E) + if (ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) || + ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)) ret = 0; if (response.buffer) { @@ -23801,9 +24153,9 @@ int SendCertificateStatus(WOLFSSL* ssl) request, &responses[i + 1], ssl->heap); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED || - ret == OCSP_CERT_UNKNOWN || - ret == OCSP_LOOKUP_FAIL) { + if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) || + ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) || + ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) { ret = 0; } @@ -23827,9 +24179,9 @@ int SendCertificateStatus(WOLFSSL* ssl) request, &responses[++i], ssl->heap); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED || - ret == OCSP_CERT_UNKNOWN || - ret == OCSP_LOOKUP_FAIL) { + if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED) || + ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN) || + ret == WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL)) { ret = 0; } } @@ -23850,7 +24202,8 @@ int SendCertificateStatus(WOLFSSL* ssl) } /* Let's not error out the connection if we can't verify our cert */ - if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E) + if (ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) || + ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)) ret = 0; break; @@ -24104,7 +24457,8 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } /* don't allow write after decrypt or mac error */ - if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) { + if (ssl->error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) || + ssl->error == WC_NO_ERR_TRACE(DECRYPT_ERROR)) { /* For DTLS allow these possible errors and allow the session to continue despite them */ if (ssl->options.dtls) { @@ -24143,7 +24497,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { #ifdef WOLFSSL_ASYNC_CRYPT /* if async would block return WANT_WRITE */ - if (ssl->error == WC_PENDING_E) { + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { return WOLFSSL_CBIO_ERR_WANT_WRITE; } #endif @@ -24160,8 +24514,8 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) WOLFSSL_MSG("output buffer was full, trying to send again"); if ( (ssl->error = SendBuffered(ssl)) < 0) { WOLFSSL_ERROR(ssl->error); - if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || - ssl->options.isClosed)) { + if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) && + (ssl->options.connReset || ssl->options.isClosed)) { ssl->error = SOCKET_PEER_CLOSED_E; WOLFSSL_ERROR(ssl->error); return 0; /* peer reset or closed */ @@ -24307,7 +24661,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) } if (sendSz < 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (sendSz == WC_PENDING_E) + if (sendSz == WC_NO_ERR_TRACE(WC_PENDING_E)) ssl->error = sendSz; #endif return BUILD_MSG_ERROR; @@ -24324,8 +24678,8 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) doesn't present like WANT_WRITE */ ssl->buffers.plainSz = buffSz; ssl->buffers.prevSent = sent; - if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || - ssl->options.isClosed)) { + if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) && + (ssl->options.connReset || ssl->options.isClosed)) { ssl->error = SOCKET_PEER_CLOSED_E; WOLFSSL_ERROR(ssl->error); return 0; /* peer reset or closed */ @@ -24361,9 +24715,9 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) if (ssl->options.dtls) { /* In DTLS mode, we forgive some errors and allow the session * to continue despite them. */ - if (ssl->error == VERIFY_MAC_ERROR || - ssl->error == DECRYPT_ERROR || - ssl->error == DTLS_SIZE_ERROR) { + if (ssl->error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) || + ssl->error == WC_NO_ERR_TRACE(DECRYPT_ERROR) || + ssl->error == WC_NO_ERR_TRACE(DTLS_SIZE_ERROR)) { ssl->error = 0; } @@ -24395,7 +24749,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { #ifdef WOLFSSL_ASYNC_CRYPT /* if async would block return WANT_WRITE */ - if (ssl->error == WC_PENDING_E) { + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { return WOLFSSL_CBIO_ERR_WANT_READ; } #endif @@ -24422,7 +24776,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) WOLFSSL_MSG("Zero return, no more data coming"); return 0; /* no more data coming */ } - if (ssl->error == SOCKET_ERROR_E) { + if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { if (ssl->options.connReset || ssl->options.isClosed) { WOLFSSL_MSG("Peer reset or closed, connection done"); ssl->error = SOCKET_PEER_CLOSED_E; @@ -24458,7 +24812,7 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { #ifdef WOLFSSL_ASYNC_CRYPT /* if async would block return WANT_WRITE */ - if (ssl->error == WC_PENDING_E) { + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { return WOLFSSL_CBIO_ERR_WANT_READ; } #endif @@ -24633,6 +24987,11 @@ static int SendAlert_ex(WOLFSSL* ssl, int severity, int type) #endif /* WOLFSSL_DTLS13 */ { AddRecordHeader(output, ALERT_SIZE, alert, ssl, CUR_ORDER); +#ifdef WOLFSSL_DTLS + /* AddRecordHeader doesn't increment the seq number */ + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); +#endif } output += RECORD_HEADER_SZ; @@ -24723,6 +25082,10 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) return SendAlert_ex(ssl, severity, type); } +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES_H +#include +#endif + const char* wolfSSL_ERR_reason_error_string(unsigned long e) { #ifdef NO_ERROR_STRINGS @@ -25261,6 +25624,10 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) #endif /* NO_ERROR_STRINGS */ } +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES +#include +#endif + const char* wolfSSL_ERR_func_error_string(unsigned long e) { (void)e; @@ -25299,7 +25666,7 @@ const char* wolfSSL_ERR_lib_error_string(unsigned long e) void SetErrorString(int error, char* str) { - XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ); + XSTRNCPY(str, wolfSSL_ERR_reason_error_string((unsigned long)error), WOLFSSL_MAX_ERROR_SZ); str[WOLFSSL_MAX_ERROR_SZ-1] = 0; } @@ -26202,7 +26569,7 @@ const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl) int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, byte* cipherSuite, int* flags) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); int i; unsigned long len; const char* nameDelim; @@ -26273,8 +26640,11 @@ static int ParseCipherList(Suites* suites, return 0; } - if (next[0] == 0 || XSTRCMP(next, "ALL") == 0 || - XSTRCMP(next, "DEFAULT") == 0 || XSTRCMP(next, "HIGH") == 0) { + if (next[0] == '\0' || + XSTRCMP(next, "ALL") == 0 || + XSTRCMP(next, "DEFAULT") == 0 || + XSTRCMP(next, "HIGH") == 0) + { /* Add all ciphersuites except anonymous and null ciphers. Prefer RSA */ #ifndef NO_RSA haveRSA = 1; @@ -26286,7 +26656,8 @@ static int ParseCipherList(Suites* suites, 0, #endif haveRSA, 1, 1, !haveRSA, 1, haveRSA, !haveRSA, 1, 1, 0, 0, - side); + side + ); return 1; /* wolfSSL default */ } @@ -26306,6 +26677,8 @@ static int ParseCipherList(Suites* suites, if (length > currLen) { length = currLen; } + if (currLen == 0) + break; } #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) @@ -26336,7 +26709,7 @@ static int ParseCipherList(Suites* suites, substrCurrent[length] = '\0'; } else { - length = (int)XSTRLEN(substrCurrent); + length = (word32)XSTRLEN(substrCurrent); } /* check if is a public key type */ @@ -26559,14 +26932,12 @@ static int ParseCipherList(Suites* suites, defined(HAVE_ED448) haveSig |= SIG_ECDSA; #endif - #if defined(HAVE_PQC) #ifdef HAVE_FALCON haveSig |= SIG_FALCON; #endif /* HAVE_FALCON */ #ifdef HAVE_DILITHIUM haveSig |= SIG_DILITHIUM; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ } else #ifdef BUILD_TLS_SM4_GCM_SM3 @@ -26629,7 +27000,7 @@ static int ParseCipherList(Suites* suites, } } } - while (next++); /* ++ needed to skip ':' */ + while (next++); /* increment to skip ':' */ if (ret) { int keySz = 0; @@ -26659,7 +27030,7 @@ static int ParseCipherList(Suites* suites, #endif { suites->suiteSz = (word16)idx; - InitSuitesHashSigAlgo_ex2(suites->hashSigAlgo, haveSig, 1, keySz, + InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, keySz, &suites->hashSigAlgoSz); } @@ -26678,7 +27049,9 @@ static int ParseCipherList(Suites* suites, suites->setSuites = 1; } +#ifdef NO_CERTS (void)privateKeySz; +#endif return ret; } @@ -26796,14 +27169,12 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list, #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) haveECDSAsig = 1; #endif - #if defined(HAVE_PQC) #ifdef HAVE_FALCON haveFalconSig = 1; #endif /* HAVE_FALCON */ #ifdef HAVE_DILITHIUM haveDilithiumSig = 1; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ } else #endif /* WOLFSSL_TLS13 */ @@ -26843,7 +27214,7 @@ int SetCipherListFromBytes(WOLFSSL_CTX* ctx, Suites* suites, const byte* list, haveSig |= haveFalconSig ? SIG_FALCON : 0; haveSig |= haveDilithiumSig ? SIG_DILITHIUM : 0; haveSig |= haveAnon ? SIG_ANON : 0; - InitSuitesHashSigAlgo_ex2(suites->hashSigAlgo, haveSig, 1, keySz, + InitSuitesHashSigAlgo(suites->hashSigAlgo, haveSig, 1, keySz, &suites->hashSigAlgoSz); #ifdef HAVE_RENEGOTIATION_INDICATION if (ctx->method->side == WOLFSSL_CLIENT_END) { @@ -27044,7 +27415,6 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo) return sigAlgo == ed448_sa_algo; } #endif -#ifdef HAVE_PQC #ifdef HAVE_FALCON if (ssl->pkCurveOID == CTC_FALCON_LEVEL1) { /* Certificate has Falcon level 1 key, only match with Falcon level 1 @@ -27071,7 +27441,6 @@ static int MatchSigAlgo(WOLFSSL* ssl, int sigAlgo) return sigAlgo == dilithium_level5_sa_algo; } #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ #ifdef WC_RSA_PSS /* RSA certificate and PSS sig alg. */ if (ssl->options.sigAlgo == rsa_sa_algo) { @@ -27122,10 +27491,43 @@ static byte MinHashAlgo(WOLFSSL* ssl) return sha_mac; } -int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) +/* Check if a given peer hashSigAlgo is supported in our ssl->suites or + * ssl->ctx->suites. + * + * Returns 1 on match. + * Returns 0 otherwise. + * */ +static int SupportedHashSigAlgo(WOLFSSL* ssl, const byte * hashSigAlgo) +{ + const Suites * suites = NULL; + word32 i = 0; + + if (ssl == NULL || hashSigAlgo == NULL) { + return 0; + } + + suites = WOLFSSL_SUITES(ssl); + + if (suites == NULL || suites->hashSigAlgoSz == 0) { + return 0; + } + + for (i = 0; (i+1) < suites->hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { + if (XMEMCMP(&suites->hashSigAlgo[i], hashSigAlgo, + HELLO_EXT_SIGALGO_SZ) == 0) { + /* Match found. */ + return 1; + } + } + + return 0; +} + +int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz, + int matchSuites) { word32 i; - int ret = MATCH_SUITE_ERROR; + int ret = WC_NO_ERR_TRACE(MATCH_SUITE_ERROR); byte minHash; /* set defaults */ @@ -27163,6 +27565,14 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) if (!MatchSigAlgo(ssl, sigAlgo)) continue; + if (matchSuites) { + /* Keep looking if peer algorithm isn't supported in our ssl->suites + * or ssl->ctx->suites. */ + if (!SupportedHashSigAlgo(ssl, &hashSigAlgo[i])) { + continue; + } + } + #ifdef HAVE_ED25519 if (ssl->pkCurveOID == ECC_ED25519_OID) { /* Matched Ed25519 - set chosen and finished. */ @@ -27181,7 +27591,6 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) break; } #endif - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) if (ssl->pkCurveOID == CTC_FALCON_LEVEL1 || ssl->pkCurveOID == CTC_FALCON_LEVEL5 ) { @@ -27203,7 +27612,6 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) break; } #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ #if defined(WOLFSSL_ECDSA_MATCH_HASH) && defined(USE_ECDSA_KEYSZ_HASH_ALGO) #error "WOLFSSL_ECDSA_MATCH_HASH and USE_ECDSA_KEYSZ_HASH_ALGO cannot " @@ -27564,7 +27972,7 @@ int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, int label, int id, void* heap, int devId) { - int ret = NOT_COMPILED_IN; + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); if (hsType == DYNAMIC_TYPE_RSA) { #ifndef NO_RSA @@ -27579,7 +27987,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, ret = wc_InitRsaKey_Label(rsaKey, (char*)data, heap, devId); } else if (id) { - ret = wc_InitRsaKey_Id(rsaKey, data, length, heap, devId); + ret = wc_InitRsaKey_Id(rsaKey, data, (int)length, heap, devId); } if (ret == 0) { *pkey = (void*)rsaKey; @@ -27602,7 +28010,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, ret = wc_ecc_init_label(ecKey, (char*)data, heap, devId); } else if (id) { - ret = wc_ecc_init_id(ecKey, data, length, heap, devId); + ret = wc_ecc_init_id(ecKey, data, (int)length, heap, devId); } if (ret == 0) { *pkey = (void*)ecKey; @@ -27613,7 +28021,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, #endif } else if (hsType == DYNAMIC_TYPE_DILITHIUM) { -#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) dilithium_key* dilithiumKey; dilithiumKey = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap, @@ -27638,7 +28046,7 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, #endif } else if (hsType == DYNAMIC_TYPE_FALCON) { -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_FALCON) falcon_key* falconKey; falconKey = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, @@ -27676,9 +28084,9 @@ int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, * length The length of a signature. * returns 0 on success, otherwise failure. */ -int DecodePrivateKey(WOLFSSL *ssl, word16* length) +int DecodePrivateKey(WOLFSSL *ssl, word32* length) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); int keySz; word32 idx; @@ -27691,7 +28099,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) #endif ) { - *length = (word16)GetPrivateKeySigSize(ssl); + *length = (word32)GetPrivateKeySigSize(ssl); return 0; } else @@ -27709,9 +28117,12 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) ssl->hsType = DYNAMIC_TYPE_RSA; else if (ssl->buffers.keyType == ecc_dsa_sa_algo) ssl->hsType = DYNAMIC_TYPE_ECC; - else if (ssl->buffers.keyType == falcon_level5_sa_algo) + else if ((ssl->buffers.keyType == falcon_level1_sa_algo) || + (ssl->buffers.keyType == falcon_level5_sa_algo)) ssl->hsType = DYNAMIC_TYPE_FALCON; - else if (ssl->buffers.keyType == dilithium_level5_sa_algo) + else if ((ssl->buffers.keyType == dilithium_level2_sa_algo) || + (ssl->buffers.keyType == dilithium_level3_sa_algo) || + (ssl->buffers.keyType == dilithium_level5_sa_algo)) ssl->hsType = DYNAMIC_TYPE_DILITHIUM; ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { @@ -27738,7 +28149,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)ssl->buffers.keySz; + *length = (word32)ssl->buffers.keySz; } #else ret = NOT_COMPILED_IN; @@ -27764,14 +28175,15 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.keySz); + *length = (word32)wc_ecc_sig_size_calc(ssl->buffers.keySz); } #else ret = NOT_COMPILED_IN; #endif } - else if (ssl->buffers.keyType == falcon_level5_sa_algo) { - #if defined(HAVE_PQC) && defined(HAVE_FALCON) + else if ((ssl->buffers.keyType == falcon_level1_sa_algo) || + (ssl->buffers.keyType == falcon_level5_sa_algo)) { + #if defined(HAVE_FALCON) if (ssl->buffers.keyLabel) { ret = wc_falcon_init_label((falcon_key*)ssl->hsKey, (char*)ssl->buffers.key->buffer, @@ -27783,6 +28195,14 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) ssl->buffers.key->length, ssl->heap, ssl->buffers.keyDevId); } + if (ret == 0) { + if (ssl->buffers.keyType == falcon_level1_sa_algo) { + ret = wc_falcon_set_level((falcon_key*)ssl->hsKey, 1); + } + else if (ssl->buffers.keyType == falcon_level5_sa_algo) { + ret = wc_falcon_set_level((falcon_key*)ssl->hsKey, 5); + } + } if (ret == 0) { if (ssl->buffers.keySz < ssl->options.minFalconKeySz) { WOLFSSL_MSG("Falcon key size too small"); @@ -27790,14 +28210,16 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_falcon_sig_size((falcon_key*)ssl->hsKey); + *length = wc_falcon_sig_size((falcon_key*)ssl->hsKey); } #else ret = NOT_COMPILED_IN; #endif } - else if (ssl->buffers.keyType == dilithium_level5_sa_algo) { - #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + else if ((ssl->buffers.keyType == dilithium_level2_sa_algo) || + (ssl->buffers.keyType == dilithium_level3_sa_algo) || + (ssl->buffers.keyType == dilithium_level5_sa_algo)) { + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) if (ssl->buffers.keyLabel) { ret = wc_dilithium_init_label((dilithium_key*)ssl->hsKey, (char*)ssl->buffers.key->buffer, @@ -27809,6 +28231,17 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) ssl->buffers.key->length, ssl->heap, ssl->buffers.keyDevId); } + if (ret == 0) { + if (ssl->buffers.keyType == dilithium_level2_sa_algo) { + ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 2); + } + else if (ssl->buffers.keyType == dilithium_level3_sa_algo) { + ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 3); + } + else if (ssl->buffers.keyType == dilithium_level5_sa_algo) { + ret = wc_dilithium_set_level((dilithium_key*)ssl->hsKey, 5); + } + } if (ret == 0) { if (ssl->buffers.keySz < ssl->options.minDilithiumKeySz) { WOLFSSL_MSG("Dilithium key size too small"); @@ -27816,7 +28249,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_dilithium_sig_size( + *length = wc_dilithium_sig_size( (dilithium_key*)ssl->hsKey); } #else @@ -27870,7 +28303,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)keySz; + *length = (word32)keySz; goto exit_dpk; } @@ -27918,6 +28351,12 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) (ecc_key*)ssl->hsKey, ssl->buffers.key->length); } + #endif + #ifdef WOLFSSL_SM2 + if ((ret == 0) && (ssl->buffers.keyType == sm2_sa_algo)) { + ret = wc_ecc_set_curve((ecc_key*)ssl->hsKey, + WOLFSSL_SM2_KEY_BITS / 8, ECC_SM2P256V1); + } #endif if (ret == 0) { WOLFSSL_MSG("Using ECC private key"); @@ -27930,7 +28369,7 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } /* Return the maximum signature length. */ - *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey); + *length = (word32)wc_ecc_sig_size((ecc_key*)ssl->hsKey); goto exit_dpk; } @@ -28050,7 +28489,6 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) } } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ -#if defined(HAVE_PQC) #if defined(HAVE_FALCON) #if !defined(NO_RSA) || defined(HAVE_ECC) FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); @@ -28104,19 +28542,21 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) WOLFSSL_MSG("Using Falcon private key"); /* Check it meets the minimum Falcon key size requirements. */ - if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) { + keySz = wc_falcon_size((falcon_key*)ssl->hsKey); + if (keySz < ssl->options.minFalconKeySz) { WOLFSSL_MSG("Falcon key size too small"); ERROR_OUT(FALCON_KEY_SIZE_E, exit_dpk); } /* Return the maximum signature length. */ - *length = FALCON_MAX_SIG_SIZE; + *length = wc_falcon_sig_size((falcon_key*)ssl->hsKey); goto exit_dpk; } } #endif /* HAVE_FALCON */ -#if defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_ASN1) #if !defined(NO_RSA) || defined(HAVE_ECC) FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); #endif @@ -28168,26 +28608,27 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) /* Set start of data to beginning of buffer. */ idx = 0; /* Decode the key assuming it is a Dilithium private key. */ - ret = wc_dilithium_import_private_only(ssl->buffers.key->buffer, - ssl->buffers.key->length, - (dilithium_key*)ssl->hsKey); + ret = wc_Dilithium_PrivateKeyDecode(ssl->buffers.key->buffer, + &idx, + (dilithium_key*)ssl->hsKey, + ssl->buffers.key->length); if (ret == 0) { WOLFSSL_MSG("Using Dilithium private key"); /* Check it meets the minimum Dilithium key size requirements. */ - if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) { + keySz = wc_dilithium_size((dilithium_key*)ssl->hsKey); + if (keySz < ssl->options.minDilithiumKeySz) { WOLFSSL_MSG("Dilithium key size too small"); ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dpk); } /* Return the maximum signature length. */ - *length = DILITHIUM_MAX_SIG_SIZE; + *length = wc_dilithium_sig_size((dilithium_key*)ssl->hsKey); goto exit_dpk; } } #endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ (void)idx; (void)keySz; @@ -28201,12 +28642,15 @@ int DecodePrivateKey(WOLFSSL *ssl, word16* length) return ret; } -#if defined(HAVE_PQC) && defined(WOLFSSL_DUAL_ALG_CERTS) -/* This is just like the above, but only consider Falcon and Dilthium and - * only for the alternative key; not the native key. */ -int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) +#if defined(WOLFSSL_DUAL_ALG_CERTS) +/* This is just like the above, but only consider RSA, ECC, Falcon and + * Dilthium; Furthermore, use the alternative key, not the native key. + */ +int DecodeAltPrivateKey(WOLFSSL *ssl, word32* length) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); + int keySz; + word32 idx; /* make sure alt private key exists */ if (ssl->buffers.altKey == NULL || ssl->buffers.altKey->buffer == NULL) { @@ -28214,8 +28658,282 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) ERROR_OUT(NO_PRIVATE_KEY, exit_dapk); } +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.altKey, ssl->buffers.altKeyMask); +#endif + +#ifdef WOLF_PRIVATE_KEY_ID + if (ssl->buffers.altKeyDevId != INVALID_DEVID && + (ssl->buffers.altKeyId || ssl->buffers.altKeyLabel)) { + if (ssl->buffers.altKeyType == rsa_sa_algo) + ssl->hsAltType = DYNAMIC_TYPE_RSA; + else if (ssl->buffers.altKeyType == ecc_dsa_sa_algo) + ssl->hsAltType = DYNAMIC_TYPE_ECC; + else if ((ssl->buffers.altKeyType == falcon_level1_sa_algo) || + (ssl->buffers.altKeyType == falcon_level5_sa_algo)) + ssl->hsAltType = DYNAMIC_TYPE_FALCON; + else if ((ssl->buffers.altKeyType == dilithium_level2_sa_algo) || + (ssl->buffers.altKeyType == dilithium_level3_sa_algo) || + (ssl->buffers.altKeyType == dilithium_level5_sa_algo)) + ssl->hsAltType = DYNAMIC_TYPE_DILITHIUM; + ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey); + if (ret != 0) { + goto exit_dapk; + } + + if (ssl->buffers.altKeyType == rsa_sa_algo) { + #ifndef NO_RSA + if (ssl->buffers.altKeyLabel) { + ret = wc_InitRsaKey_Label((RsaKey*)ssl->hsAltKey, + (char*)ssl->buffers.altKey->buffer, + ssl->heap, ssl->buffers.altKeyDevId); + } + else if (ssl->buffers.altKeyId) { + ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsAltKey, + ssl->buffers.altKey->buffer, + ssl->buffers.altKey->length, ssl->heap, + ssl->buffers.altKeyDevId); + } + if (ret == 0) { + if (ssl->buffers.altKeySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dapk); + } + + /* Return the maximum signature length. */ + *length = ssl->buffers.altKeySz; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (ssl->buffers.altKeyType == ecc_dsa_sa_algo) { + #ifdef HAVE_ECC + if (ssl->buffers.altKeyLabel) { + ret = wc_ecc_init_label((ecc_key*)ssl->hsAltKey, + (char*)ssl->buffers.altKey->buffer, + ssl->heap, ssl->buffers.altKeyDevId); + } + else if (ssl->buffers.altKeyId) { + ret = wc_ecc_init_id((ecc_key*)ssl->hsAltKey, + ssl->buffers.altKey->buffer, + ssl->buffers.altKey->length, ssl->heap, + ssl->buffers.altKeyDevId); + } + if (ret == 0) { + if (ssl->buffers.altKeySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dapk); + } + + /* Return the maximum signature length. */ + *length = wc_ecc_sig_size_calc(ssl->buffers.altKeySz); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if ((ssl->buffers.altKeyType == falcon_level1_sa_algo) || + (ssl->buffers.altKeyType == falcon_level5_sa_algo)) { + #if defined(HAVE_FALCON) + if (ssl->buffers.altKeyLabel) { + ret = wc_falcon_init_label((falcon_key*)ssl->hsAltKey, + (char*)ssl->buffers.altKey->buffer, + ssl->heap, ssl->buffers.altKeyDevId); + } + else if (ssl->buffers.altKeyId) { + ret = wc_falcon_init_id((falcon_key*)ssl->hsAltKey, + ssl->buffers.altKey->buffer, + ssl->buffers.altKey->length, ssl->heap, + ssl->buffers.altKeyDevId); + } + if (ret == 0) { + if (ssl->buffers.altKeyType == falcon_level1_sa_algo) { + ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 1); + } + else if (ssl->buffers.altKeyType == falcon_level5_sa_algo) { + ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 5); + } + } + if (ret == 0) { + if (ssl->buffers.altKeySz < ssl->options.minFalconKeySz) { + WOLFSSL_MSG("Falcon key size too small"); + ERROR_OUT(FALCON_KEY_SIZE_E, exit_dapk); + } + + /* Return the maximum signature length. */ + *length = wc_falcon_sig_size((falcon_key*)ssl->hsAltKey); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if ((ssl->buffers.altKeyType == dilithium_level2_sa_algo) || + (ssl->buffers.altKeyType == dilithium_level3_sa_algo) || + (ssl->buffers.altKeyType == dilithium_level5_sa_algo)) { + #if defined(HAVE_DILITHIUM) + if (ssl->buffers.altKeyLabel) { + ret = wc_dilithium_init_label((dilithium_key*)ssl->hsAltKey, + (char*)ssl->buffers.altKey->buffer, + ssl->heap, ssl->buffers.altKeyDevId); + } + else if (ssl->buffers.altKeyId) { + ret = wc_dilithium_init_id((dilithium_key*)ssl->hsAltKey, + ssl->buffers.altKey->buffer, + ssl->buffers.altKey->length, ssl->heap, + ssl->buffers.altKeyDevId); + } + if (ret == 0) { + if (ssl->buffers.altKeyType == dilithium_level2_sa_algo) { + ret = wc_dilithium_set_level( + (dilithium_key*)ssl->hsAltKey, 2); + } + else if (ssl->buffers.altKeyType == dilithium_level3_sa_algo) { + ret = wc_dilithium_set_level( + (dilithium_key*)ssl->hsAltKey, 3); + } + else if (ssl->buffers.altKeyType == dilithium_level5_sa_algo) { + ret = wc_dilithium_set_level( + (dilithium_key*)ssl->hsAltKey, 5); + } + } + if (ret == 0) { + if (ssl->buffers.altKeySz < ssl->options.minDilithiumKeySz) { + WOLFSSL_MSG("Dilithium key size too small"); + ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk); + } + + /* Return the maximum signature length. */ + *length = wc_dilithium_sig_size( + (dilithium_key*)ssl->hsAltKey); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + goto exit_dapk; + } +#endif /* WOLF_PRIVATE_KEY_ID */ + +#ifndef NO_RSA + if (ssl->buffers.altKeyType == rsa_sa_algo || + ssl->buffers.altKeyType == 0) { + ssl->hsAltType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey); + if (ret != 0) { + goto exit_dapk; + } + + 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.altKey->buffer, &idx, + (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey->length); + #ifdef WOLF_PRIVATE_KEY_ID + /* if using external key then allow using a public key */ + if (ret != 0 && (ssl->devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) + #endif + )) { + WOLFSSL_MSG("Trying RSA public key with crypto callbacks"); + idx = 0; + ret = wc_RsaPublicKeyDecode(ssl->buffers.altKey->buffer, &idx, + (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey->length); + } + #endif + if (ret == 0) { + WOLFSSL_MSG("Using RSA private key"); + + /* It worked so check it meets minimum key size requirements. */ + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsAltKey); + if (keySz < 0) { /* check if keySz has error case */ + ERROR_OUT(keySz, exit_dapk); + } + + if (keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dapk); + } + + /* Return the maximum signature length. */ + *length = keySz; + + goto exit_dapk; + } + } +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +#ifndef NO_RSA + FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey); +#endif /* !NO_RSA */ + + if (ssl->buffers.altKeyType == ecc_dsa_sa_algo || + ssl->buffers.altKeyType == 0 + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) + || ssl->buffers.altKeyType == sm2_sa_algo + #endif + ) { + ssl->hsAltType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey); + if (ret != 0) { + goto exit_dapk; + } + + #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.altKey->buffer, &idx, + (ecc_key*)ssl->hsAltKey, + ssl->buffers.altKey->length); + #ifdef WOLF_PRIVATE_KEY_ID + /* if using external key then allow using a public key */ + if (ret != 0 && (ssl->devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) + #endif + )) { + WOLFSSL_MSG("Trying ECC public key with crypto callbacks"); + idx = 0; + ret = wc_EccPublicKeyDecode(ssl->buffers.altKey->buffer, &idx, + (ecc_key*)ssl->hsAltKey, + ssl->buffers.altKey->length); + } + #endif + if (ret == 0) { + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsAltKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dapk); + } + + /* Return the maximum signature length. */ + *length = wc_ecc_sig_size((ecc_key*)ssl->hsAltKey); + + goto exit_dapk; + } + } +#endif +#if defined(HAVE_FALCON) + #if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey); + #endif + if (ssl->buffers.altKeyType == falcon_level1_sa_algo || - ssl->buffers.altKeyType == falcon_level5_sa_algo) { + ssl->buffers.altKeyType == falcon_level5_sa_algo || + ssl->buffers.altKeyType == 0) { ssl->hsAltType = DYNAMIC_TYPE_FALCON; ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey); @@ -28230,14 +28948,25 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) ret = wc_falcon_set_level((falcon_key*)ssl->hsAltKey, 5); } else { + /* What if ssl->buffers.keyType is 0? We might want to do something + * more graceful here. */ ret = ALGO_ID_E; } if (ret != 0) { goto exit_dapk; } - WOLFSSL_MSG("Trying Falcon private key"); + #if defined(HAVE_ECC) + WOLFSSL_MSG("Trying Falcon private key, ECC didn't work"); + #elif !defined(NO_RSA) + WOLFSSL_MSG("Trying Falcon private key, RSA didn't work"); + #else + WOLFSSL_MSG("Trying Falcon private key"); + #endif + + /* Set start of data to beginning of buffer. */ + idx = 0; /* Decode the key assuming it is a Falcon private key. */ ret = wc_falcon_import_private_only(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length, @@ -28246,21 +28975,28 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) WOLFSSL_MSG("Using Falcon private key"); /* Check it meets the minimum Falcon key size requirements. */ - if (FALCON_MAX_KEY_SIZE < ssl->options.minFalconKeySz) { + keySz = wc_falcon_size((falcon_key*)ssl->hsAltKey); + if (keySz < ssl->options.minFalconKeySz) { WOLFSSL_MSG("Falcon key size too small"); ERROR_OUT(FALCON_KEY_SIZE_E, exit_dapk); } + /* Return the maximum signature length. */ *length = wc_falcon_sig_size((falcon_key*)ssl->hsAltKey); goto exit_dapk; } } - FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey); +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) + #if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsAltType, (void**)&ssl->hsAltKey); + #endif if (ssl->buffers.altKeyType == dilithium_level2_sa_algo || ssl->buffers.altKeyType == dilithium_level3_sa_algo || - ssl->buffers.altKeyType == dilithium_level5_sa_algo) { + ssl->buffers.altKeyType == dilithium_level5_sa_algo || + ssl->buffers.altKeyType == 0) { ssl->hsAltType = DYNAMIC_TYPE_DILITHIUM; ret = AllocKey(ssl, ssl->hsAltType, &ssl->hsAltKey); @@ -28278,6 +29014,8 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) ret = wc_dilithium_set_level((dilithium_key*)ssl->hsAltKey, 5); } else { + /* What if ssl->buffers.keyType is 0? We might want to do something + * more graceful here. */ ret = ALGO_ID_E; } @@ -28285,35 +29023,63 @@ int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length) goto exit_dapk; } - WOLFSSL_MSG("Trying Dilithium private key"); + #if defined(HAVE_FALCON) + WOLFSSL_MSG("Trying Dilithium private key, Falcon didn't work"); + #elif defined(HAVE_ECC) + WOLFSSL_MSG("Trying Dilithium private key, ECC didn't work"); + #elif !defined(NO_RSA) + WOLFSSL_MSG("Trying Dilithium private key, RSA didn't work"); + #else + WOLFSSL_MSG("Trying Dilithium private key"); + #endif + /* Set start of data to beginning of buffer. */ + idx = 0; /* Decode the key assuming it is a Dilithium private key. */ - ret = wc_dilithium_import_private_only(ssl->buffers.altKey->buffer, - ssl->buffers.altKey->length, - (dilithium_key*)ssl->hsAltKey); + ret = wc_Dilithium_PrivateKeyDecode(ssl->buffers.altKey->buffer, + &idx, + (dilithium_key*)ssl->hsAltKey, + ssl->buffers.altKey->length); if (ret == 0) { WOLFSSL_MSG("Using Dilithium private key"); /* Check it meets the minimum Dilithium key size requirements. */ - if (DILITHIUM_MAX_KEY_SIZE < ssl->options.minDilithiumKeySz) { + keySz = wc_dilithium_size((dilithium_key*)ssl->hsAltKey); + if (keySz < ssl->options.minDilithiumKeySz) { WOLFSSL_MSG("Dilithium key size too small"); ERROR_OUT(DILITHIUM_KEY_SIZE_E, exit_dapk); } + /* Return the maximum signature length. */ *length = wc_dilithium_sig_size((dilithium_key*)ssl->hsAltKey); goto exit_dapk; } } +#endif /* HAVE_DILITHIUM */ + + (void)idx; + (void)keySz; + (void)length; exit_dapk: +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } +#endif + if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); } return ret; } -#endif /* HAVE_PQC && WOLFSSL_DUAL_ALG_CERTS */ +#endif /* WOLFSSL_DUAL_ALG_CERTS */ #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_TLS12) @@ -28384,7 +29150,7 @@ static int SigAlgoCachesMsgs(int sigAlgo) } static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, - const byte* data, int sz, byte sigAlgo) + const byte* data, word32 sz, byte sigAlgo) { int ret = 0; int digest_sz = wc_HashGetDigestSize(hashType); @@ -28394,11 +29160,16 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } if (ret == 0) { + word32 new_size = SEED_LEN; /* buffer for signature */ - ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + sz, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); - if (ssl->buffers.sig.buffer == NULL) { + if (! WC_SAFE_SUM_WORD32(new_size, sz, new_size)) ret = MEMORY_E; + else { + ssl->buffers.sig.buffer = (byte*)XMALLOC(new_size, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ret = MEMORY_E; + } } } if (ret == 0) { @@ -28477,7 +29248,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, int sendSz; int idSz; int ret; - word16 extSz = 0; + word32 extSz = 0; const Suites* suites; if (ssl == NULL) { @@ -28526,7 +29297,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } #endif length = VERSION_SZ + RAN_LEN - + idSz + ENUM_LEN + + (word32)idSz + ENUM_LEN + SUITE_LEN + COMP_LEN + ENUM_LEN; #ifndef NO_FORCE_SCR_SAME_SUITE @@ -28556,7 +29327,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if (extSz != 0) length += extSz + HELLO_EXT_SZ_SZ; #endif - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + sendSz = (int)length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; if (ssl->arrays == NULL) { return BAD_FUNC_ARG; @@ -28566,7 +29337,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if (ssl->options.dtls) { length += ENUM_LEN; /* cookie */ if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz; - sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ; + sendSz = (int)length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ; idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; } #endif @@ -28697,7 +29468,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = idx; /* build msg adds rec hdr */ + int inputSz = (int)idx; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; if (ssl->options.dtls) @@ -28710,7 +29481,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, XMEMCPY(input, output + recordHeaderSz, inputSz); #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, input, inputSz, client_hello)) != 0) { + (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, client_hello)) != 0) { XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); return ret; } @@ -28724,7 +29495,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, } else { #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, client_hello)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, client_hello)) != 0) return ret; } if (ssl->options.dtls) @@ -28818,6 +29589,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if (!ssl->options.downgrade || ssl->options.minDowngrade <= DTLSv1_3_MINOR) return VERSION_ERROR; + + /* Cannot be DTLS1.3 as HELLO_VERIFY_REQUEST */ + ssl->options.tls1_3 = 0; } #endif /* defined(WOLFSSL_DTLS13) && defined(WOLFSSL_TLS13) */ @@ -29419,7 +30193,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, if ((len > size) || ((*inOutIdx - begin) + len > size)) return BUFFER_ERROR; - if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && + if (PickHashSigAlgo(ssl, input + *inOutIdx, len, 0) != 0 && ssl->buffers.certificate && ssl->buffers.certificate->buffer) { #ifdef HAVE_PK_CALLBACKS @@ -29592,7 +30366,7 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, static int CheckCurveId(int tlsCurveId) { - int ret = ECC_CURVE_ERROR; + int ret = WC_NO_ERR_TRACE(ECC_CURVE_ERROR); switch (tlsCurveId) { #if (defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 160 @@ -29660,7 +30434,9 @@ static int HashSkeData(WOLFSSL* ssl, enum wc_HashType hashType, case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID; #endif /* !NO_ECC_SECP */ #endif - default: break; + default: + ret = WC_NO_ERR_TRACE(ECC_CURVE_ERROR); + break; } return ret; @@ -29986,7 +30762,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, args = (DskeArgs*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_dske; @@ -30038,7 +30814,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN); + srvHintLen = (int)min(length, MAX_PSK_ID_LEN); XMEMCPY(ssl->arrays->server_hint, input + args->idx, srvHintLen); ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ @@ -30081,7 +30857,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } - ssl->ecdhCurveOID = curveOid; + ssl->ecdhCurveOID = (word32)curveOid; #if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) ssl->namedGroup = 0; #endif @@ -30112,9 +30888,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, input + args->idx, length, EC25519_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, illegal_parameter); @@ -30155,9 +30931,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, input + args->idx, length, EC448_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, illegal_parameter); @@ -30192,7 +30968,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } } - curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + curveId = wc_ecc_get_oid((word32)curveOid, NULL, NULL); if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS @@ -30225,7 +31001,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN); + srvHintLen = (int)min(length, MAX_PSK_ID_LEN); XMEMCPY(ssl->arrays->server_hint, input + args->idx, srvHintLen); ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ @@ -30258,7 +31034,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN); + srvHintLen = (int)min(length, MAX_PSK_ID_LEN); XMEMCPY(ssl->arrays->server_hint, input + args->idx, srvHintLen); ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ @@ -30281,7 +31057,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } - ssl->ecdhCurveOID = curveOid; + ssl->ecdhCurveOID = (word32)curveOid; length = input[args->idx++]; if ((args->idx - args->begin) + length > size) { @@ -30309,9 +31085,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, input + args->idx, length, EC25519_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, illegal_parameter); @@ -30352,9 +31128,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, input + args->idx, length, EC448_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, illegal_parameter); @@ -30389,7 +31165,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } } - curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + curveId = wc_ecc_get_oid((word32)curveOid, NULL, NULL); if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); @@ -30434,14 +31210,14 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(NOT_COMPILED_IN, exit_dske); #else enum wc_HashType hashType; - word16 verifySz; + word32 verifySz; byte sigAlgo; if (ssl->options.usingAnon_cipher) { break; } - verifySz = (word16)(args->idx - args->begin); + verifySz = (args->idx - args->begin); if (verifySz > MAX_DH_SZ) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -30452,6 +31228,15 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(BUFFER_ERROR, exit_dske); } + /* Check if hashSigAlgo in Server Key Exchange is supported + * in our ssl->suites or ssl->ctx->suites. */ + if (!SupportedHashSigAlgo(ssl, &input[args->idx])) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, handshake_failure); + #endif + ERROR_OUT(MATCH_SUITE_ERROR, exit_dske); + } + DecodeSigAlg(&input[args->idx], &ssl->options.peerHashAlgo, &sigAlgo); #ifndef NO_RSA @@ -30650,7 +31435,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ret = 0; } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* peerRsaKey */ @@ -30678,7 +31463,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, (ssl->buffers.sig.length - SEED_LEN)); } #endif /* HAVE_PK_CALLBACKS */ - if (ret == NOT_COMPILED_IN) { + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->options.peerSigAlgo == sm2_sa_algo) { ret = Sm2wSm3Verify(ssl, @@ -30712,7 +31497,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* peerEccDsaKey */ @@ -30742,7 +31527,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* peerEccDsaKey */ @@ -30772,7 +31557,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* peerEccDsaKey */ @@ -30989,7 +31774,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_server_key_exchange = 0; @@ -31070,7 +31855,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_scke; @@ -31370,11 +32155,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) void* ctx = wolfSSL_GetGenPreMasterCtx(ssl); ret = ssl->ctx->GenPreMasterCb(ssl, ssl->arrays->preMasterSecret, ENCRYPT_LEN, ctx); - if (ret != 0 && ret != PROTOCOLCB_UNAVAILABLE) { + if (ret != 0 && + ret != WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) { goto exit_scke; } } - if (!ssl->ctx->GenPreMasterCb || ret == PROTOCOLCB_UNAVAILABLE) + if (!ssl->ctx->GenPreMasterCb || + ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) #endif { /* build PreMasterSecret with RNG data */ @@ -31469,7 +32256,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } @@ -31514,7 +32301,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } @@ -31597,7 +32384,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } @@ -31872,7 +32659,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) WOLFSSL_CLIENT_END ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { FreeKey(ssl, DYNAMIC_TYPE_ECC, @@ -32104,7 +32891,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) } idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - args->sendSz = args->encSz + tlsSz + idx; + args->sendSz = (int)(args->encSz + tlsSz + idx); #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -32237,7 +33024,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef WOLFSSL_ASYNC_IO /* Handle async operation */ - if (ret == WC_PENDING_E || ret == WANT_WRITE) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) || ret == WANT_WRITE) { if (ssl->options.buildingMsg) return ret; /* If we have completed all states then we will not enter this function @@ -32285,7 +33072,7 @@ typedef struct ScvArgs { word32 sigSz; int sendSz; int inputSz; - word16 length; + word32 length; byte sigAlgo; } ScvArgs; @@ -32321,6 +33108,10 @@ int SendCertificateVerify(WOLFSSL* ssl) WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); WOLFSSL_ENTER("SendCertificateVerify"); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); +#endif + #ifdef WOLFSSL_ASYNC_IO if (ssl->async == NULL) { ssl->async = (struct WOLFSSL_ASYNC*) @@ -32333,10 +33124,10 @@ int SendCertificateVerify(WOLFSSL* ssl) args = (ScvArgs*)ssl->async->args; #ifdef WOLFSSL_ASYNC_CRYPT /* BuildMessage does its own Pop */ - if (ssl->error != WC_PENDING_E || + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E) || ssl->options.asyncState != TLS_ASYNC_END) ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_scv; @@ -32367,6 +33158,10 @@ int SendCertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, + ssl->buffers.keyMask); + #endif return 0; /* sent blank cert, can't verify */ } @@ -32504,7 +33299,7 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* prepend hdr */ - c16toa(args->length, args->verify + args->extraSz); + c16toa((word16)args->length, args->verify + args->extraSz); } #ifdef WC_RSA_PSS else if (args->sigAlgo == rsa_pss_sa_algo) { @@ -32514,7 +33309,7 @@ int SendCertificateVerify(WOLFSSL* ssl) args->sigSz = ENCRYPT_LEN; /* prepend hdr */ - c16toa(args->length, args->verify + args->extraSz); + c16toa((word16)args->length, args->verify + args->extraSz); } #endif #endif /* !NO_RSA */ @@ -32693,7 +33488,7 @@ int SendCertificateVerify(WOLFSSL* ssl) #endif args->length = (word16)ssl->buffers.sig.length; /* prepend hdr */ - c16toa(args->length, args->verify + args->extraSz); + c16toa((word16)args->length, args->verify + args->extraSz); XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, ssl->buffers.sig.buffer, ssl->buffers.sig.length); break; @@ -32722,7 +33517,7 @@ int SendCertificateVerify(WOLFSSL* ssl) ); /* free temporary buffer now */ - if (ret != WC_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) { XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); args->verifySig = NULL; } @@ -32771,6 +33566,15 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* switch(ssl->options.asyncState) */ exit_scv: +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } +#endif WOLFSSL_LEAVE("SendCertificateVerify", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); @@ -32934,7 +33738,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_CERTS -#ifdef WOLF_PRIVATE_KEY_ID +#if defined(WOLF_PRIVATE_KEY_ID) || defined(HAVE_PK_CALLBACKS) int GetPrivateKeySigSize(WOLFSSL* ssl) { int sigSz = 0; @@ -32975,7 +33779,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } return sigSz; } -#endif /* HAVE_PK_CALLBACKS */ +#endif /* WOLF_PRIVATE_KEY_ID || HAVE_PK_CALLBACKS */ #endif /* NO_CERTS */ @@ -33067,29 +33871,47 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int TranslateErrorToAlert(int err) { switch (err) { - case BUFFER_ERROR: + case WC_NO_ERR_TRACE(BUFFER_ERROR): return decode_error; - case EXT_NOT_ALLOWED: - case PEER_KEY_ERROR: - case ECC_PEERKEY_ERROR: - case BAD_KEY_SHARE_DATA: - case PSK_KEY_ERROR: - case INVALID_PARAMETER: - case HRR_COOKIE_ERROR: - case BAD_BINDER: + case WC_NO_ERR_TRACE(EXT_NOT_ALLOWED): + case WC_NO_ERR_TRACE(PEER_KEY_ERROR): + case WC_NO_ERR_TRACE(ECC_PEERKEY_ERROR): + case WC_NO_ERR_TRACE(BAD_KEY_SHARE_DATA): + case WC_NO_ERR_TRACE(PSK_KEY_ERROR): + case WC_NO_ERR_TRACE(INVALID_PARAMETER): + case WC_NO_ERR_TRACE(HRR_COOKIE_ERROR): + case WC_NO_ERR_TRACE(BAD_BINDER): return illegal_parameter; - case INCOMPLETE_DATA: + case WC_NO_ERR_TRACE(INCOMPLETE_DATA): return missing_extension; - case MATCH_SUITE_ERROR: - case MISSING_HANDSHAKE_DATA: + case WC_NO_ERR_TRACE(MATCH_SUITE_ERROR): + case WC_NO_ERR_TRACE(MISSING_HANDSHAKE_DATA): return handshake_failure; - case VERSION_ERROR: + case WC_NO_ERR_TRACE(VERSION_ERROR): return wolfssl_alert_protocol_version; default: return invalid_alert; } } + /* search suites for specific one, idx on success, negative on error */ + int FindSuite(const Suites* suites, byte first, byte second) + { + int i; + + if (suites == NULL || suites->suiteSz == 0) { + WOLFSSL_MSG("Suites pointer error or suiteSz 0"); + return SUITES_ERROR; + } + + for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) { + if (suites->suites[i] == first && + suites->suites[i+1] == second ) + return i; + } + + return MATCH_SUITE_ERROR; + } #ifndef NO_WOLFSSL_SERVER @@ -33278,7 +34100,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = idx; /* build msg adds rec hdr */ + int inputSz = (int)idx; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; if (ssl->options.dtls) @@ -33291,7 +34113,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(input, output + recordHeaderSz, inputSz); #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, input, inputSz, server_hello)) != 0) { + (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, server_hello)) != 0) { XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); return ret; } @@ -33305,7 +34127,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } else { #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, server_hello)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, server_hello)) != 0) return ret; } if (ssl->options.dtls) @@ -33377,7 +34199,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) word32 exportSz; #endif - int sendSz; + word32 sendSz; int inputSz; } SskeArgs; @@ -33416,6 +34238,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); WOLFSSL_ENTER("SendServerKeyExchange"); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + #endif + #ifdef WOLFSSL_ASYNC_IO if (ssl->async == NULL) { ssl->async = (struct WOLFSSL_ASYNC*) @@ -33428,7 +34254,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args = (SskeArgs*)ssl->async->args; #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_sske; @@ -33718,7 +34544,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->eccTempKeyPresent == 0) { ret = X25519MakeKey(ssl, (curve25519_key*)ssl->eccTempKey, NULL); - if (ret == 0 || ret == WC_PENDING_E) { + if (ret == 0 || + ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ssl->eccTempKeyPresent = DYNAMIC_TYPE_CURVE25519; } @@ -33745,7 +34572,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->eccTempKeyPresent == 0) { ret = X448MakeKey(ssl, (curve448_key*)ssl->eccTempKey, NULL); - if (ret == 0 || ret == WC_PENDING_E) { + if (ret == 0 || + ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ssl->eccTempKeyPresent = DYNAMIC_TYPE_CURVE448; } @@ -33770,7 +34598,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->eccTempKeyPresent == 0) { ret = EccMakeKey(ssl, ssl->eccTempKey, NULL); - if (ret == 0 || ret == WC_PENDING_E) { + if (ret == 0 || + ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC; } } @@ -34094,7 +34923,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.key == NULL) { #ifdef HAVE_PK_CALLBACKS if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { - args->tmpSigSz = GetPrivateKeySigSize(ssl); + args->tmpSigSz = (word32)GetPrivateKeySigSize(ssl); if (args->tmpSigSz == 0) { ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } @@ -34111,7 +34940,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif case rsa_sa_algo: { - word16 keySz; + word32 keySz; ssl->buffers.keyType = rsa_sa_algo; ret = DecodePrivateKey(ssl, &keySz); @@ -34129,9 +34958,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif case ecc_dsa_sa_algo: { - word16 keySz; + word32 keySz; - ssl->buffers.keyType = ecc_dsa_sa_algo; + ssl->buffers.keyType = ssl->options.sigAlgo; ret = DecodePrivateKey(ssl, &keySz); if (ret != 0) { goto exit_sske; @@ -34144,7 +34973,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ED25519 case ed25519_sa_algo: { - word16 keySz; + word32 keySz; ssl->buffers.keyType = ed25519_sa_algo; ret = DecodePrivateKey(ssl, &keySz); @@ -34160,7 +34989,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_ED448 case ed448_sa_algo: { - word16 keySz; + word32 keySz; ssl->buffers.keyType = ed448_sa_algo; ret = DecodePrivateKey(ssl, &keySz); @@ -34363,7 +35192,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, preSigSz = args->length; if (!ssl->options.usingAnon_cipher) { - word16 keySz = 0; + word32 keySz = 0; /* sig length */ args->length += LENGTH_SZ; @@ -34972,6 +35801,16 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, exit_sske: + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } + #endif + WOLFSSL_LEAVE("SendServerKeyExchange", ret); WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); @@ -35009,30 +35848,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return ret; } -#if defined(HAVE_SERVER_RENEGOTIATION_INFO) || defined(HAVE_FALLBACK_SCSV) || \ - defined(OPENSSL_ALL) - - /* search suites for specific one, idx on success, negative on error */ - static int FindSuite(Suites* suites, byte first, byte second) - { - int i; - - if (suites == NULL || suites->suiteSz == 0) { - WOLFSSL_MSG("Suites pointer error or suiteSz 0"); - return SUITES_ERROR; - } - - for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) { - if (suites->suites[i] == first && - suites->suites[i+1] == second ) - return i; - } - - return MATCH_SUITE_ERROR; - } - -#endif - #endif /* !WOLFSSL_NO_TLS12 */ /* Make sure server cert/key are valid for this suite, true on success @@ -35142,7 +35957,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int ret = TLSX_KeyShare_Choose(ssl, extensions, first, second, &cs->clientKSE, &searched); - if (ret == MEMORY_E) { + if (ret == WC_NO_ERR_TRACE(MEMORY_E)) { WOLFSSL_MSG("TLSX_KeyShare_Choose() failed in " "VerifyServerSuite() with MEMORY_E"); return 0; @@ -35157,7 +35972,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, cs->doHelloRetry = 1; } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif if (!cs->doHelloRetry && ret != 0) @@ -35224,7 +36039,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, for (i = 0; i < suites->suiteSz; i += 2) { for (j = 0; j < peerSuites->suiteSz; j += 2) { ret = CompareSuites(ssl, suites, peerSuites, i, j, cs, extensions); - if (ret != MATCH_SUITE_ERROR) + if (ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)) return ret; } } @@ -35234,7 +36049,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, for (j = 0; j < peerSuites->suiteSz; j += 2) { for (i = 0; i < suites->suiteSz; i += 2) { ret = CompareSuites(ssl, suites, peerSuites, i, j, cs, extensions); - if (ret != MATCH_SUITE_ERROR) + if (ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)) return ret; } } @@ -35273,7 +36088,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); + peerSuites->hashSigAlgoSz, 1); if (ret != 0) return ret; @@ -35525,6 +36340,47 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { int ret = 0; WOLFSSL_SESSION* session; + +#ifdef HAVE_SECRET_CALLBACK + if (ssl->sessionSecretCb != NULL +#ifdef HAVE_SESSION_TICKET + && ssl->session->ticketLen > 0 +#endif + ) { + int secretSz = SECRET_LEN; + WOLFSSL_MSG("Calling session secret callback"); + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, + RAN_LEN); + if (ret == 0) { + ret = ssl->sessionSecretCb(ssl, ssl->arrays->masterSecret, + &secretSz, ssl->sessionSecretCtx); + if (secretSz != SECRET_LEN) + ret = SESSION_SECRET_CB_E; + } + if (ret == 0) + ret = MatchSuite(ssl, clSuites); + if (ret == 0) { + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + #ifndef NO_TLS + if (ssl->options.tls) + ret = DeriveTlsKeys(ssl); + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif + /* SERVER: peer auth based on session secret. */ + ssl->options.peerAuthGood = (ret == 0); + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + if (ret != 0) + WOLFSSL_ERROR_VERBOSE(ret); + WOLFSSL_LEAVE("HandleTlsResumption", ret); + return ret; + } +#endif /* HAVE_SECRET_CALLBACK */ + #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket == 1) { session = ssl->session; @@ -35595,7 +36451,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = SetCipherSpecs(ssl); if (ret == 0) { ret = PickHashSigAlgo(ssl, clSuites->hashSigAlgo, - clSuites->hashSigAlgoSz); + clSuites->hashSigAlgoSz, 0); } } else if (ret == 0) { @@ -35671,7 +36527,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* propagate socket errors to avoid re-calling send alert */ err = SendAlert(ssl, alert_fatal, alertType); - if (err == SOCKET_ERROR_E) + if (err == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) ret = SOCKET_ERROR_E; } *inOutIdx += helloSz; @@ -35979,8 +36835,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); - if (ret != WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) { + ret = SECURE_RENEGOTIATION_E; goto out; + } else { + ret = 0; + } extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); if (extension) { @@ -36184,6 +37044,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.haveSessionId = 1; /* ProcessOld uses same resume code */ + WOLFSSL_MSG_EX("ssl->options.resuming %d", ssl->options.resuming); if (ssl->options.resuming) { ret = HandleTlsResumption(ssl, clSuites); if (ret != 0) @@ -36315,7 +37176,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args = (DcvArgs*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_dcv; @@ -36480,9 +37341,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ); if (ret >= 0) { if (ssl->options.peerSigAlgo == rsa_sa_algo) - args->sendSz = ret; + args->sendSz = (word32)ret; else { - args->sigSz = ret; + args->sigSz = (word32)ret; args->sendSz = ssl->buffers.digest.length; } ret = 0; @@ -36568,7 +37429,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_ASYNC_CRYPT /* handle async pending */ - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) goto exit_dcv; #endif @@ -36706,7 +37567,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_certificate_verify = 0; @@ -36714,9 +37575,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_ERROR) + if (ret == WC_NO_ERR_TRACE(BUFFER_ERROR)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == SIG_VERIFY_E) + else if (ret == WC_NO_ERR_TRACE(SIG_VERIFY_E)) SendAlert(ssl, alert_fatal, decrypt_error); else if (ret != 0) SendAlert(ssl, alert_fatal, bad_certificate); @@ -36798,7 +37659,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(input, output + recordHeaderSz, inputSz); #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && - (ret = DtlsMsgPoolSave(ssl, input, inputSz, server_hello_done)) != 0) { + (ret = DtlsMsgPoolSave(ssl, input, (word32)inputSz, server_hello_done)) != 0) { XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); return ret; } @@ -36812,7 +37673,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } else { #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, server_hello_done)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, server_hello_done)) != 0) return ret; } if (ssl->options.dtls) @@ -36929,7 +37790,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, it = (InternalTicket*)et->enc_ticket; #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { XMEMSET(et, 0, sizeof(*et)); @@ -37036,7 +37897,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (ret != WOLFSSL_TICKET_RET_OK) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -37157,7 +38018,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (ret != WOLFSSL_TICKET_RET_OK) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -37443,7 +38304,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif if (sess == NULL) { ret = TlsSessionCacheGetAndRdLock(id, &sess, &freeCtx->row, - ssl->options.side); + (byte)ssl->options.side); if (ret != 0) sess = NULL; } @@ -37565,6 +38426,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_START(WC_FUNC_TICKET_DO); WOLFSSL_ENTER("DoClientTicket"); +#ifdef HAVE_SECRET_CALLBACK + if (ssl->ticketParseCb != NULL) { + decryptRet = WOLFSSL_TICKET_RET_OK; + if (!ssl->ticketParseCb(ssl, input, len, ssl->ticketParseCtx)) { + /* Failure kills the connection */ + decryptRet = WOLFSSL_TICKET_RET_FATAL; + } + else { + if (wolfSSL_set_SessionTicket(ssl, input, len) != + WOLFSSL_SUCCESS) + decryptRet = WOLFSSL_TICKET_RET_REJECT; + } + goto cleanup; + } + else +#endif #ifdef WOLFSSL_TLS13 if (len == ID_LEN && IsAtLeastTLSv1_3(ssl->version)) { /* This is a stateful ticket. We can be sure about this because @@ -37579,7 +38456,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } else #endif + if (len >= sizeof(*it)) decryptRet = DoDecryptTicket(ssl, input, len, &it); + else + WOLFSSL_MSG("Ticket is smaller than InternalTicket. Rejecting."); + if (decryptRet != WOLFSSL_TICKET_RET_OK && decryptRet != WOLFSSL_TICKET_RET_CREATE) { @@ -37655,7 +38536,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } length += ssl->session->ticketLen; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + sendSz = (int)length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; if (!ssl->options.dtls) { if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) @@ -37697,7 +38578,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { byte* input; - int inputSz = idx; /* build msg adds rec hdr */ + int inputSz = (int)idx; /* build msg adds rec hdr */ int recordHeaderSz = RECORD_HEADER_SZ; if (ssl->options.dtls) @@ -37718,7 +38599,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, else { #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, session_ticket)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, (word32)sendSz, session_ticket)) != 0) return ret; DtlsSEQIncrement(ssl, CUR_ORDER); @@ -38135,6 +39016,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_ENTER("DefTicketEncCb"); + if ((!enc) && (inLen != sizeof(InternalTicket))) { + return BUFFER_E; + } + /* Check we have setup the RNG, name and primary key. */ if (keyCtx->expirary[0] == 0) { #ifndef SINGLE_THREADED @@ -38372,7 +39257,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; } - AddHeaders(output, length, hello_verify_request, ssl); + AddHeaders(output, (word32)length, hello_verify_request, ssl); output[idx++] = DTLS_MAJOR; output[idx++] = DTLS_MINOR; @@ -38456,6 +39341,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); WOLFSSL_ENTER("DoClientKeyExchange"); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + #endif + #ifdef WOLFSSL_ASYNC_CRYPT if (ssl->async == NULL) { ssl->async = (struct WOLFSSL_ASYNC*) @@ -38467,7 +39356,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], args = (DckeArgs*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_dcke; @@ -38611,7 +39500,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], #ifndef NO_RSA case rsa_kea: { - word16 keySz; + word32 keySz; ssl->buffers.keyType = rsa_sa_algo; ret = DecodePrivateKey(ssl, &keySz); @@ -38689,7 +39578,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { #if defined(WOLFSSL_EXTRA_ALERTS) || \ defined(WOLFSSL_PSK_IDENTITY_ALERT) SendAlert(ssl, alert_fatal, @@ -38731,7 +39620,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], if (ssl->specs.static_ecdh && ssl->ecdhCurveOID != ECC_X25519_OID && ssl->ecdhCurveOID != ECC_X448_OID) { - word16 keySz; + word32 keySz; ssl->buffers.keyType = ecc_dsa_sa_algo; ret = DecodePrivateKey(ssl, &keySz); @@ -38781,9 +39670,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, args->length, EC25519_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, @@ -38838,9 +39727,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, args->length, EC448_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, @@ -38906,7 +39795,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } - ssl->arrays->preMasterSz = private_key->dp->size; + ssl->arrays->preMasterSz = (word32)private_key->dp->size; ssl->peerEccKeyPresent = 1; @@ -39083,9 +39972,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, args->length, EC25519_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, @@ -39142,9 +40031,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, args->length, EC448_LITTLE_ENDIAN)) != 0) { #ifdef WOLFSSL_EXTRA_ALERTS - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) SendAlert(ssl, alert_fatal, decode_error); - else if (ret == ECC_OUT_OF_RANGE_E) + else if (ret == WC_NO_ERR_TRACE(ECC_OUT_OF_RANGE_E)) SendAlert(ssl, alert_fatal, bad_record_mac); else { SendAlert(ssl, alert_fatal, @@ -39245,10 +40134,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], * RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) goto exit_dcke; #endif - if (ret == BAD_FUNC_ARG) + if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) goto exit_dcke; lenErrMask = 0 - (SECRET_LEN != args->sigSz); @@ -39311,7 +40200,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_SERVER_END ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { FreeKey(ssl, DYNAMIC_TYPE_ECC, @@ -39367,7 +40256,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_SERVER_END ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, @@ -39388,7 +40277,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_SERVER_END ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { FreeKey(ssl, DYNAMIC_TYPE_CURVE448, @@ -39532,7 +40421,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { #if defined(WOLFSSL_EXTRA_ALERTS) || \ defined(WOLFSSL_PSK_IDENTITY_ALERT) SendAlert(ssl, alert_fatal, @@ -39578,7 +40467,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { ERROR_OUT(PSK_KEY_ERROR, exit_dcke); } /* SERVER: Pre-shared Key for peer authentication. */ @@ -39650,11 +40539,21 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], exit_dcke: + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } + #endif + WOLFSSL_LEAVE("DoClientKeyExchange", ret); WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_client_key_exchange = 0; @@ -39746,7 +40645,8 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) event = &asyncDev->event; ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL); - if (ret != WC_NO_PENDING_E && ret != WC_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E) && + ret != WC_NO_ERR_TRACE(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)++; @@ -39759,7 +40659,7 @@ int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) #if (defined(WOLF_CRYPTO_CB) || defined(HAVE_PK_CALLBACKS)) && \ !defined(WOLFSSL_ASYNC_CRYPT_SW) && !defined(HAVE_INTEL_QA) && \ !defined(HAVE_CAVIUM) - else if (ret == WC_PENDING_E) { + else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Allow the underlying crypto API to be called again to trigger the * crypto or PK callback. The actual callback must be called, since * the completion is not detected in the poll like Intel QAT or diff --git a/src/src/keys.c b/src/src/keys.c index fa04c4d..f9f9e85 100644 --- a/src/src/keys.c +++ b/src/src/keys.c @@ -105,7 +105,7 @@ int SetCipherSpecs(WOLFSSL* ssl) * @param cipherSuite [in] * @param specs [out] CipherSpecs * @param opts [in/out] Options can be NULL - * @return + * @return int (less than 0 on fail, 0 on success) */ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, CipherSpecs* specs, Options* opts) @@ -672,7 +672,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_16_AUTH_SZ; break; @@ -690,7 +690,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -708,7 +708,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_256_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -1069,7 +1069,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -1087,7 +1087,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_256_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -1105,7 +1105,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; if (opts != NULL) @@ -1125,7 +1125,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_256_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; if (opts != NULL) @@ -1145,7 +1145,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_16_AUTH_SZ; if (opts != NULL) @@ -1165,7 +1165,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_256_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_16_AUTH_SZ; if (opts != NULL) @@ -1185,7 +1185,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_16_AUTH_SZ; if (opts != NULL) @@ -1205,7 +1205,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_256_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_IMP_IV_SZ; + specs->iv_size = AESCCM_IMP_IV_SZ; specs->aead_mac_size = AES_CCM_16_AUTH_SZ; if (opts != NULL) @@ -1330,7 +1330,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_NONCE_SZ; + specs->iv_size = AESCCM_NONCE_SZ; specs->aead_mac_size = AES_CCM_16_AUTH_SZ; break; @@ -1348,7 +1348,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = AES_128_KEY_SIZE; specs->block_size = AES_BLOCK_SIZE; - specs->iv_size = AESGCM_NONCE_SZ; + specs->iv_size = AESCCM_NONCE_SZ; specs->aead_mac_size = AES_CCM_8_AUTH_SZ; break; @@ -1440,7 +1440,7 @@ int GetCipherSpec(word16 side, byte cipherSuite0, byte cipherSuite, specs->static_ecdh = 0; specs->key_size = SM4_KEY_SIZE; specs->block_size = SM4_BLOCK_SIZE; - specs->iv_size = GCM_IMP_IV_SZ; + specs->iv_size = CCM_IMP_IV_SZ; specs->aead_mac_size = SM4_CCM_AUTH_SZ; break; @@ -3561,7 +3561,8 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) void* ctx = wolfSSL_GetEncryptKeysCtx(ssl); ret = ssl->ctx->EncryptKeysCb(ssl, ctx); } - if (!ssl->ctx->EncryptKeysCb || ret == PROTOCOLCB_UNAVAILABLE) + if (!ssl->ctx->EncryptKeysCb || + ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) #endif { ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side, @@ -3668,7 +3669,8 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) /* TLS can call too */ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) { - int sz, i = 0; + size_t sz; + int i = 0; Keys* keys = &ssl->keys; #ifdef WOLFSSL_DTLS /* In case of DTLS, ssl->keys is updated here */ @@ -3712,7 +3714,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); #endif - i += sz; + i += (int)sz; } sz = ssl->specs.key_size; #ifdef WOLFSSL_DTLS @@ -3725,7 +3727,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #endif XMEMCPY(keys->client_write_key, &keyData[i], sz); XMEMCPY(keys->server_write_key, &keyData[i], sz); - i += sz; + i += (int)sz; sz = ssl->specs.iv_size; #ifdef WOLFSSL_DTLS @@ -3767,7 +3769,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #endif XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); #endif - i += sz; + i += (int)sz; } if (side & PROVISION_SERVER) { #ifndef WOLFSSL_AEAD_ONLY @@ -3778,7 +3780,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) #endif XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); #endif - i += sz; + i += (int)sz; } } sz = ssl->specs.key_size; @@ -3789,7 +3791,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) keys->client_write_key, sz); #endif XMEMCPY(keys->client_write_key, &keyData[i], sz); - i += sz; + i += (int)sz; } if (side & PROVISION_SERVER) { #ifdef WOLFSSL_DTLS @@ -3798,7 +3800,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) keys->server_write_key, sz); #endif XMEMCPY(keys->server_write_key, &keyData[i], sz); - i += sz; + i += (int)sz; } sz = ssl->specs.iv_size; @@ -3809,7 +3811,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) keys->client_write_IV, sz); #endif XMEMCPY(keys->client_write_IV, &keyData[i], sz); - i += sz; + i += (int)sz; } if (side & PROVISION_SERVER) { #ifdef WOLFSSL_DTLS diff --git a/src/src/ocsp.c b/src/src/ocsp.c index c56ec22..4760c50 100644 --- a/src/src/ocsp.c +++ b/src/src/ocsp.c @@ -144,7 +144,7 @@ static int xstat2err(int st) int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, WOLFSSL* ssl) { - int ret = OCSP_LOOKUP_FAIL; + int ret = WC_NO_ERR_TRACE(OCSP_LOOKUP_FAIL); #ifdef WOLFSSL_SMALL_STACK OcspRequest* ocspRequest; @@ -227,7 +227,7 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, OcspEntry* entry, CertStatus** status, buffer* responseBuffer, void* heap) { - int ret = OCSP_INVALID_STATUS; + int ret = WC_NO_ERR_TRACE(OCSP_INVALID_STATUS); WOLFSSL_ENTER("GetOcspStatus"); @@ -241,7 +241,7 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, for (*status = entry->status; *status; *status = (*status)->next) if ((*status)->serialSz == request->serialSz - && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz)) + && !XMEMCMP((*status)->serial, request->serial, (size_t)(*status)->serialSz)) break; if (responseBuffer && *status && !(*status)->rawOcspResponse) { @@ -326,9 +326,14 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, return MEMORY_E; } #endif - InitOcspResponse(ocspResponse, newSingle, newStatus, response, responseSz, - ocsp->cm->heap); - + InitOcspResponse(ocspResponse, newSingle, newStatus, response, + (word32)responseSz, ocsp->cm->heap); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ocspRequest != NULL && ocspRequest->ssl != NULL && + TLSX_CSR2_IsMulti(((WOLFSSL*)ocspRequest->ssl)->extensions)) { + ocspResponse->pendingCAs = TLSX_CSR2_GetPendingSigners(((WOLFSSL*)ocspRequest->ssl)->extensions); + } +#endif ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); if (ret != 0) { ocsp->error = ret; @@ -350,12 +355,12 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, } if (responseBuffer) { - responseBuffer->buffer = (byte*)XMALLOC(responseSz, heap, + responseBuffer->buffer = (byte*)XMALLOC((size_t)responseSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (responseBuffer->buffer) { - responseBuffer->length = responseSz; - XMEMCPY(responseBuffer->buffer, response, responseSz); + responseBuffer->length = (unsigned int)responseSz; + XMEMCPY(responseBuffer->buffer, response, (size_t)responseSz); } } @@ -410,10 +415,10 @@ int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, if (ret == 0 && validated == 1) { WOLFSSL_MSG("New OcspResponse validated"); } - else if (ret == OCSP_CERT_REVOKED) { + else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_REVOKED)) { WOLFSSL_MSG("OCSP revoked"); } - else if (ret == OCSP_CERT_UNKNOWN) { + else if (ret == WC_NO_ERR_TRACE(OCSP_CERT_UNKNOWN)) { WOLFSSL_MSG("OCSP unknown"); } else { @@ -466,7 +471,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer, heap); - if (ret != OCSP_INVALID_STATUS) + if (ret != WC_NO_ERR_TRACE(OCSP_INVALID_STATUS)) return ret; if (responseBuffer) { @@ -522,13 +527,13 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return 0; } - request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + request = (byte*)XMALLOC((size_t)requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); if (request == NULL) { WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_ERROR; } - requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); + requestSz = EncodeOcspRequest(ocspRequest, request, (word32)requestSz); if (requestSz > 0 && ocsp->cm->ocspIOCb) { responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz, request, requestSz, &response); @@ -555,7 +560,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, #ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, - void* vp) { + void* vp, Signer* pendingCAs) { /* Attempt to build a chain up to cert's issuer */ WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; Signer* ca = NULL; @@ -574,8 +579,16 @@ static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, /* End loop if no more issuers found or if we have found a self * signed cert (ca == prev) */ - for (ca = GetCAByName(cm, single->issuerHash); ca != NULL && ca != prev; - prev = ca, ca = GetCAByName(cm, ca->issuerNameHash)) { + ca = GetCAByName(cm, single->issuerHash); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ca == NULL && pendingCAs != NULL) { + ca = findSignerByName(pendingCAs, single->issuerHash); + } +#else + (void)pendingCAs; +#endif + for (; ca != NULL && ca != prev; + prev = ca) { if (XMEMCMP(cert->issuerHash, ca->issuerNameHash, OCSP_DIGEST_SIZE) == 0) { WOLFSSL_MSG("\tOCSP Response signed by authorized " @@ -584,6 +597,12 @@ static int CheckOcspResponderChain(OcspEntry* single, DecodedCert *cert, passed = 1; break; } + ca = GetCAByName(cm, ca->issuerNameHash); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ca == NULL && pendingCAs != NULL) { + ca = findSignerByName(pendingCAs, single->issuerHash); + } +#endif } return passed; } @@ -632,7 +651,7 @@ int CheckOcspResponder(OcspResponse *bs, DecodedCert *cert, void* vp) } #ifndef WOLFSSL_NO_OCSP_ISSUER_CHAIN_CHECK else if (vp != NULL) { - passed = CheckOcspResponderChain(single, cert, vp); + passed = CheckOcspResponderChain(single, cert, vp, bs->pendingCAs); } #endif } @@ -663,7 +682,7 @@ int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, single = bs->single; while (single != NULL) { - if ((XMEMCMP(single->status->serial, id->status->serial, single->status->serialSz) == 0) + if ((XMEMCMP(single->status->serial, id->status->serial, (size_t)single->status->serialSz) == 0) && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0) && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) { break; @@ -783,14 +802,14 @@ WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( InitDecodedCert(cert, subject->derCert->buffer, subject->derCert->length, NULL); - if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + if (ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL) != 0) { FreeDecodedCert(cert); goto out; } else { XMEMCPY(certId->issuerHash, cert->issuerHash, OCSP_DIGEST_SIZE); XMEMCPY(certId->issuerKeyHash, cert->issuerKeyHash, OCSP_DIGEST_SIZE); - XMEMCPY(certId->status->serial, cert->serial, cert->serialSz); + XMEMCPY(certId->status->serial, cert->serial, (size_t)cert->serialSz); certId->status->serialSz = cert->serialSz; FreeDecodedCert(cert); } @@ -864,7 +883,7 @@ int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, int derSz = 0; const byte* der = wolfSSL_X509_get_der(x, &derSz); if (der != NULL && derSz == (int)bs->certSz && - XMEMCMP(bs->cert, der, derSz) == 0) { + XMEMCMP(bs->cert, der, (size_t)derSz) == 0) { ret = WOLFSSL_SUCCESS; goto out; } @@ -873,7 +892,7 @@ int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, InitDecodedCert(cert, bs->cert, bs->certSz, NULL); certInit = 1; - if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm) < 0) + if (ParseCertRelative(cert, CERT_TYPE, VERIFY, st->cm, NULL) < 0) goto out; if (!(flags & OCSP_NOCHECKS)) { @@ -952,7 +971,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, if (fcur > MAX_WOLFSSL_FILE_SIZE || fcur <= 0) return NULL; - data = (byte*)XMALLOC(fcur, 0, DYNAMIC_TYPE_TMP_BUFFER); + data = (byte*)XMALLOC((size_t)fcur, 0, DYNAMIC_TYPE_TMP_BUFFER); if (data == NULL) return NULL; dataAlloced = 1; @@ -997,7 +1016,7 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, XMEMSET(resp, 0, sizeof(OcspResponse)); } - resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + resp->source = (byte*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (resp->source == NULL) { XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST); return NULL; @@ -1021,19 +1040,19 @@ OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, } XMEMSET(resp->single->status, 0, sizeof(CertStatus)); - XMEMCPY(resp->source, *data, len); - resp->maxIdx = len; + XMEMCPY(resp->source, *data, (size_t)len); + resp->maxIdx = (word32)len; ret = OcspResponseDecode(resp, NULL, NULL, 1); - if (ret != 0 && ret != ASN_OCSP_CONFIRM_E) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(ASN_OCSP_CONFIRM_E)) { /* for just converting from a DER to an internal structure the CA may * not yet be known to this function for signature verification */ wolfSSL_OCSP_RESPONSE_free(resp); return NULL; } - if (GetSequence(*data, &idx, &length, len) >= 0) - (*data) += idx + length; + if (GetSequence(*data, &idx, &length, (word32)len) >= 0) + (*data) += (unsigned char) ((int)idx + length); return resp; } @@ -1042,10 +1061,10 @@ int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, unsigned char** data) { if (data == NULL) - return response->maxIdx; + return (int)response->maxIdx; XMEMCPY(*data, response->source, response->maxIdx); - return response->maxIdx; + return (int)response->maxIdx; } int wolfSSL_OCSP_response_status(OcspResponse *response) @@ -1128,7 +1147,7 @@ int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) if (size <= 0 || data == NULL) return size; - return EncodeOcspRequest(request, *data, size); + return EncodeOcspRequest(request, *data, (word32) size); } WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, @@ -1147,12 +1166,12 @@ WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, if (cid->status->serialSz > req->serialSz) { if (req->serial != NULL) XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); - req->serial = (byte*)XMALLOC(cid->status->serialSz, + req->serial = (byte*)XMALLOC((size_t)cid->status->serialSz, req->heap, DYNAMIC_TYPE_OCSP_REQUEST); if (req->serial == NULL) return NULL; } - XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz); + XMEMCPY(req->serial, cid->status->serial, (size_t)cid->status->serialSz); req->serialSz = cid->status->serialSz; return req; @@ -1188,7 +1207,7 @@ int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out, size = wolfSSL_i2d_OCSP_REQUEST(req, NULL); if (size > 0) { - data = (unsigned char*) XMALLOC(size, out->heap, + data = (unsigned char*) XMALLOC((size_t)size, out->heap, DYNAMIC_TYPE_TMP_BUFFER); } @@ -1217,15 +1236,15 @@ int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data) return WOLFSSL_FAILURE; if (*data != NULL) { - XMEMCPY(*data, id->rawCertId, id->rawCertIdSize); + XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize); *data = *data + id->rawCertIdSize; } else { - *data = (unsigned char*)XMALLOC(id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL); + *data = (unsigned char*)XMALLOC((size_t)id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL); if (*data == NULL) { return WOLFSSL_FAILURE; } - XMEMCPY(*data, id->rawCertId, id->rawCertIdSize); + XMEMCPY(*data, id->rawCertId, (size_t)id->rawCertIdSize); } return id->rawCertIdSize; @@ -1254,9 +1273,9 @@ WOLFSSL_OCSP_CERTID* wolfSSL_d2i_OCSP_CERTID(WOLFSSL_OCSP_CERTID** cidOut, } if (cid != NULL) { - cid->rawCertId = (byte*)XMALLOC(length + 1, NULL, DYNAMIC_TYPE_OPENSSL); + cid->rawCertId = (byte*)XMALLOC((size_t)length + 1, NULL, DYNAMIC_TYPE_OPENSSL); if (cid->rawCertId != NULL) { - XMEMCPY(cid->rawCertId, *derIn, length); + XMEMCPY(cid->rawCertId, *derIn, (size_t)length); cid->rawCertIdSize = length; /* Per spec. advance past the data that is being returned @@ -1303,7 +1322,7 @@ int wolfSSL_OCSP_id_cmp(WOLFSSL_OCSP_CERTID *a, WOLFSSL_OCSP_CERTID *b) if (a->status != NULL && b->status != NULL) { if (a->status->serialSz == b->status->serialSz) ret = XMEMCMP(a->status->serial, b->status->serial, - a->status->serialSz); + (size_t)a->status->serialSz); else ret = -1; } @@ -1432,13 +1451,13 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { /* allocate data buffer, +2 for type and length */ - ser->data = (unsigned char*)XMALLOC(cid->status->serialSz + 2, NULL, + ser->data = (unsigned char*)XMALLOC((size_t)cid->status->serialSz + 2, NULL, DYNAMIC_TYPE_OPENSSL); if (ser->data == NULL) { wolfSSL_ASN1_INTEGER_free(ser); return 0; } - ser->dataMax = cid->status->serialSz + 2; + ser->dataMax = (unsigned int)cid->status->serialSz + 2; ser->isDynamic = 1; } else { /* Use array instead of dynamic memory */ @@ -1448,12 +1467,12 @@ int wolfSSL_OCSP_id_get0_info(WOLFSSL_ASN1_STRING **name, #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) /* Serial number starts at 0 index of ser->data */ - XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz); + XMEMCPY(&ser->data[i], cid->status->serial, (size_t)cid->status->serialSz); ser->length = cid->status->serialSz; #else ser->data[i++] = ASN_INTEGER; i += SetLength(cid->status->serialSz, ser->data + i); - XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz); + XMEMCPY(&ser->data[i], cid->status->serial, (size_t)cid->status->serialSz); ser->length = i + cid->status->serialSz; #endif @@ -1493,7 +1512,7 @@ int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val, sz = MAX_OCSP_NONCE_SZ; if (val != NULL) { - XMEMCPY(req->nonce, val, sz); + XMEMCPY(req->nonce, val, (size_t)sz); } else { if ( @@ -1506,7 +1525,7 @@ int wolfSSL_OCSP_request_add1_nonce(OcspRequest* req, unsigned char* val, WOLFSSL_MSG("RNG init failed"); return WOLFSSL_FAILURE; } - if (wc_RNG_GenerateBlock(&rng, req->nonce, sz) != 0) { + if (wc_RNG_GenerateBlock(&rng, req->nonce, (word32)sz) != 0) { WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); wc_FreeRng(&rng); return WOLFSSL_FAILURE; @@ -1559,7 +1578,7 @@ int wolfSSL_OCSP_check_nonce(OcspRequest* req, WOLFSSL_OCSP_BASICRESP* bs) /* nonces are present and equal, return 1. Extra NULL check for fixing scan-build warning. */ if (reqNonceSz == rspNonceSz && reqNonce && rspNonce) { - if (XMEMCMP(reqNonce, rspNonce, reqNonceSz) == 0) + if (XMEMCMP(reqNonce, rspNonce, (size_t)reqNonceSz) == 0) return 1; } diff --git a/src/src/pk.c b/src/src/pk.c index d7d32dd..db281f6 100644 --- a/src/src/pk.c +++ b/src/src/pk.c @@ -25,13 +25,19 @@ #include - #include +#include #ifndef WC_NO_RNG #include #endif #ifdef HAVE_ECC #include + #ifdef HAVE_SELFTEST + /* point compression types. */ + #define ECC_POINT_COMP_EVEN 0x02 + #define ECC_POINT_COMP_ODD 0x03 + #define ECC_POINT_UNCOMP 0x04 + #endif #endif #ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV /* FIPS build has replaced ecc.h. */ @@ -49,14 +55,6 @@ #include #endif -#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) && defined(WOLFSSL_KEY_GEN) && \ - (defined(HAVE_ECC) || (!defined(NO_DSA) && !defined(HAVE_SELFTEST))) -/* Forward declaration for wolfSSL_PEM_write_bio_DSA_PUBKEY. - * Implementation in ssl.c. - */ -static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key); -#endif - /******************************************************************************* * COMMON FUNCTIONS ******************************************************************************/ @@ -167,8 +165,7 @@ static int pem_read_bio_key(WOLFSSL_BIO* bio, wc_pem_password_cb* cb, /* Write left over data back to BIO if not a file BIO */ if ((ret > 0) && ((memSz - ret) > 0) && (bio->type != WOLFSSL_BIO_FILE)) { - int res; - res = wolfSSL_BIO_write(bio, mem + ret, memSz - ret); + int res = wolfSSL_BIO_write(bio, mem + ret, memSz - ret); if (res != memSz - ret) { WOLFSSL_ERROR_MSG("Unable to write back excess data"); if (res < 0) { @@ -180,7 +177,7 @@ static int pem_read_bio_key(WOLFSSL_BIO* bio, wc_pem_password_cb* cb, } } if (alloced) { - XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER); } } @@ -229,33 +226,36 @@ static int pem_read_file_key(XFILE fp, wc_pem_password_cb* cb, void* pass, * @param [in] heap Heap hint for dynamic memory allocation. * @param [out] out Allocated buffer containing PEM. * @param [out] outSz Size of PEM encoding. - * @return WOLFSSL_FAILURE on error. - * @return WOLFSSL_SUCCESS on success. + * @return 1 on success. + * @return 0 on error. */ static int der_to_pem_alloc(const unsigned char* der, int derSz, int type, void* heap, byte** out, int* outSz) { - int ret = WOLFSSL_SUCCESS; + int ret = 1; int pemSz; byte* pem = NULL; (void)heap; + /* Convert DER to PEM - to get size. */ pemSz = wc_DerToPem(der, (word32)derSz, NULL, 0, type); if (pemSz < 0) { - ret = WOLFSSL_FAILURE; + ret = 0; } - if (ret == WOLFSSL_SUCCESS) { + if (ret == 1) { + /* Allocate memory for PEM to be encoded into. */ pem = (byte*)XMALLOC((size_t)pemSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (pem == NULL) { - ret = WOLFSSL_FAILURE; + ret = 0; } } - if ((ret == WOLFSSL_SUCCESS) && (wc_DerToPem(der, (word32)derSz, pem, - (word32)pemSz, type) < 0)) { - ret = WOLFSSL_FAILURE; + /* Convert DER to PEM. */ + if ((ret == 1) && (wc_DerToPem(der, (word32)derSz, pem, (word32)pemSz, + type) < 0)) { + ret = 0; XFREE(pem, heap, DYNAMIC_TYPE_TMP_BUFFER); pem = NULL; } @@ -272,8 +272,8 @@ static int der_to_pem_alloc(const unsigned char* der, int derSz, int type, * @param [in] derSz Size of DER data in bytes. * @param [in, out] bio BIO object to write with. * @param [in] type Type of key being encoded. - * @return WOLFSSL_FAILURE on error. - * @return WOLFSSL_SUCCESS on success. + * @return 1 on success. + * @return 0 on error. */ static int der_write_to_bio_as_pem(const unsigned char* der, int derSz, WOLFSSL_BIO* bio, int type) @@ -283,11 +283,11 @@ static int der_write_to_bio_as_pem(const unsigned char* der, int derSz, byte* pem = NULL; ret = der_to_pem_alloc(der, derSz, type, bio->heap, &pem, &pemSz); - if (ret == WOLFSSL_SUCCESS) { + if (ret == 1) { int len = wolfSSL_BIO_write(bio, pem, pemSz); if (len != pemSz) { WOLFSSL_ERROR_MSG("Unable to write full PEM to BIO"); - ret = WOLFSSL_FAILURE; + ret = 0; } } @@ -308,8 +308,8 @@ static int der_write_to_bio_as_pem(const unsigned char* der, int derSz, * @param [in] fp File pointer to write with. * @param [in] type Type of key being encoded. * @param [in] heap Heap hint for dynamic memory allocation. - * @return WOLFSSL_FAILURE on error. - * @return WOLFSSL_SUCCESS on success. + * @return 1 on success. + * @return 0 on error. */ static int der_write_to_file_as_pem(const unsigned char* der, int derSz, XFILE fp, int type, void* heap) @@ -319,11 +319,11 @@ static int der_write_to_file_as_pem(const unsigned char* der, int derSz, byte* pem = NULL; ret = der_to_pem_alloc(der, derSz, type, heap, &pem, &pemSz); - if (ret == WOLFSSL_SUCCESS) { + if (ret == 1) { int len = (int)XFWRITE(pem, 1, (size_t)pemSz, fp); if (len != pemSz) { WOLFSSL_ERROR_MSG("Unable to write full PEM to BIO"); - ret = WOLFSSL_FAILURE; + ret = 0; } } @@ -333,9 +333,153 @@ static int der_write_to_file_as_pem(const unsigned char* der, int derSz, #endif #endif +#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER) +/* Encrypt private key into PEM format. + * + * DER is encrypted in place. + * + * @param [in] der DER encoding of private key. + * @param [in] derSz Size of DER in bytes. + * @param [in] cipher EVP cipher. + * @param [in] passwd Password to use with encryption. + * @param [in] passedSz Size of password in bytes. + * @param [out] cipherInfo PEM cipher information lines. + * @param [in] maxDerSz Maximum size of DER buffer. + * @return 1 on success. + * @return 0 on error. + */ +int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, byte **cipherInfo, int maxDerSz) +{ + int ret = 0; + int paddingSz = 0; + word32 idx; + word32 cipherInfoSz; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("EncryptDerKey"); + + /* Validate parameters. */ + if ((der == NULL) || (derSz == NULL) || (cipher == NULL) || + (passwd == NULL) || (cipherInfo == NULL)) { + ret = BAD_FUNC_ARG; + } + + #ifdef WOLFSSL_SMALL_STACK + if (ret == 0) { + /* Allocate encrypted info. */ + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + ret = 0; + } + } + #endif + if (ret == 0) { + /* Clear the encrypted info and set name. */ + XMEMSET(info, 0, sizeof(EncryptedInfo)); + XSTRNCPY(info->name, cipher, NAME_SZ - 1); + info->name[NAME_SZ - 1] = '\0'; /* null term */ + + /* Get encrypted info from name. */ + ret = wc_EncryptedInfoGet(info, info->name); + if (ret != 0) { + WOLFSSL_MSG("unsupported cipher"); + } + } + + if (ret == 0) { + /* Generate a random salt. */ + if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != 1) { + WOLFSSL_MSG("generate iv failed"); + ret = -1; + } + } + + if (ret == 0) { + /* Calculate padding size - always a padding block. */ + paddingSz = info->ivSz - ((*derSz) % info->ivSz); + /* Check der is big enough. */ + if (maxDerSz < (*derSz) + paddingSz) { + WOLFSSL_MSG("not enough DER buffer allocated"); + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + /* Set padding bytes to padding length. */ + XMEMSET(der + (*derSz), (byte)paddingSz, paddingSz); + /* Add padding to DER size. */ + (*derSz) += (int)paddingSz; + + /* Encrypt DER buffer. */ + ret = wc_BufferKeyEncrypt(info, der, (word32)*derSz, passwd, passwdSz, WC_MD5); + if (ret != 0) { + WOLFSSL_MSG("encrypt key failed"); + } + } + + if (ret == 0) { + /* Create cipher info : 'cipher_name,Salt(hex)' */ + cipherInfoSz = (word32)(2 * info->ivSz + XSTRLEN(info->name) + 2); + /* Allocate memory for PEM encryption lines. */ + *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, DYNAMIC_TYPE_STRING); + if (*cipherInfo == NULL) { + WOLFSSL_MSG("malloc failed"); + ret = MEMORY_E; + } + } + if (ret == 0) { + /* Copy in name and add on comma. */ + XSTRLCPY((char*)*cipherInfo, info->name, cipherInfoSz); + XSTRLCAT((char*)*cipherInfo, ",", cipherInfoSz); + + /* Find end of string. */ + idx = (word32)XSTRLEN((char*)*cipherInfo); + /* Calculate remaining bytes. */ + cipherInfoSz -= idx; + + /* Encode IV into PEM encryption lines. */ + ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo + idx, + &cipherInfoSz); + if (ret != 0) { + WOLFSSL_MSG("Base16_Encode failed"); + XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING); + *cipherInfo = NULL; + } + } + +#ifdef WOLFSSL_SMALL_STACK + /* Free dynamically allocated info. */ + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + return ret == 0; +} +#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */ + + #if defined(WOLFSSL_KEY_GEN) && \ (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) && \ (!defined(NO_RSA) || defined(HAVE_ECC)) +/* Encrypt the DER in PEM format. + * + * @param [in] der DER encoded private key. + * @param [in] derSz Size of DER in bytes. + * @param [in] cipher EVP cipher. + * @param [in] passwd Password to use in encryption. + * @param [in] passwdSz Size of password in bytes. + * @param [in] type PEM type of write out. + * @param [in] heap Dynamic memory hint. + * @param [out] out Allocated buffer containing PEM encoding. + * heap was NULL and dynamic type is DYNAMIC_TYPE_KEY. + * @param [out] outSz Size of PEM encoding in bytes. + * @return 1 on success. + * @return 0 on failure. + */ static int der_to_enc_pem_alloc(unsigned char* der, int derSz, const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz, int type, void* heap, byte** out, int* outSz) @@ -736,8 +880,11 @@ static int wolfssl_print_number(WOLFSSL_BIO* bio, mp_int* num, const char* name, #endif /* XSNPRINTF && !NO_BIO && !NO_RSA */ -#if !defined(NO_RSA) || (!defined(NO_DH) && !defined(NO_CERTS) && \ - defined(HAVE_FIPS) && !FIPS_VERSION_GT(2,0)) || defined(HAVE_ECC) +#endif /* OPENSSL_EXTRA */ + +#if !defined(NO_CERTS) || (defined(OPENSSL_EXTRA) && (!defined(NO_RSA) || \ + (!defined(NO_DH) && defined(HAVE_FIPS) && !FIPS_VERSION_GT(2,0)) || \ + defined(HAVE_ECC))) /* Uses the DER SEQUENCE to determine size of DER data. * @@ -765,9 +912,7 @@ static int wolfssl_der_length(const unsigned char* seq, int len) return ret; } -#endif /* !NO_RSA */ - -#endif /* OPENSSL_EXTRA */ +#endif /******************************************************************************* * START OF RSA API @@ -1659,7 +1804,7 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, rsa->pkcs8HeaderSz = (word16)idx; } /* When decoding and not PKCS#8, return will be ASN_PARSE_E. */ - else if (res != ASN_PARSE_E) { + else if (res != WC_NO_ERR_TRACE(ASN_PARSE_E)) { /* Something went wrong while decoding. */ WOLFSSL_ERROR_MSG("Unexpected error with trying to remove PKCS#8 " "header"); @@ -1787,7 +1932,7 @@ int wolfSSL_PEM_write_bio_RSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa) ret = 0; } if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio, - PUBLICKEY_TYPE) != WOLFSSL_SUCCESS)) { + PUBLICKEY_TYPE) != 1)) { ret = 0; } @@ -1832,7 +1977,7 @@ static int wolfssl_pem_write_rsa_public_key(XFILE fp, WOLFSSL_RSA* rsa, ret = 0; } if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, type, - rsa->heap) != WOLFSSL_SUCCESS)) { + rsa->heap) != 1)) { ret = 0; } @@ -2559,7 +2704,7 @@ int SetRsaInternal(WOLFSSL_RSA* rsa) } /* Copy down d mod q-1 if available. */ - if ((ret == 1) && (rsa->dmp1 != NULL) && + if ((ret == 1) && (rsa->dmq1 != NULL) && (wolfssl_bn_get_value(rsa->dmq1, &key->dQ) != 1)) { WOLFSSL_ERROR_MSG("rsa dQ key error"); ret = -1; @@ -3239,7 +3384,7 @@ WOLFSSL_RSA* wolfSSL_RSA_generate_key(int bits, unsigned long e, ret = wolfssl_rsa_generate_key_native(rsa, bits, bn, NULL); #ifdef HAVE_FIPS /* Keep trying if failed to find a prime. */ - if (ret == PRIME_GEN_E) { + if (ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) { continue; } #endif @@ -3290,7 +3435,7 @@ int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* e, int gen_ret = wolfssl_rsa_generate_key_native(rsa, bits, e, cb); #ifdef HAVE_FIPS /* Keep trying again if public key value didn't work. */ - if (gen_ret == PRIME_GEN_E) { + if (gen_ret == WC_NO_ERR_TRACE(PRIME_GEN_E)) { continue; } #endif @@ -3419,7 +3564,7 @@ int wolfSSL_RSA_padding_add_PKCS1_PSS(WOLFSSL_RSA *rsa, unsigned char *em, if (ret == 1) { /* Get length of RSA key - encrypted message length. */ emLen = wolfSSL_RSA_size(rsa); - if (ret <= 0) { + if (emLen <= 0) { WOLFSSL_ERROR_MSG("wolfSSL_RSA_size error"); ret = 0; } @@ -5468,7 +5613,7 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, } #endif /* !HAVE_SELFTEST */ -WOLFSSL_API int wolfSSL_i2d_DSAparams(const WOLFSSL_DSA* dsa, +int wolfSSL_i2d_DSAparams(const WOLFSSL_DSA* dsa, unsigned char** out) { int ret = 0; @@ -5485,7 +5630,7 @@ WOLFSSL_API int wolfSSL_i2d_DSAparams(const WOLFSSL_DSA* dsa, if (ret == 0) { key = (DsaKey*)dsa->internal; ret = wc_DsaKeyToParamsDer_ex(key, NULL, &derLen); - if (ret == LENGTH_ONLY_E) { + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { ret = 0; } } @@ -5577,99 +5722,115 @@ WOLFSSL_DSA* wolfSSL_d2i_DSAparams(WOLFSSL_DSA** dsa, const unsigned char** der, * Returns 1 or 0 */ int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - wc_pem_password_cb* cb, void* arg) + const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz, + wc_pem_password_cb* cb, void* arg) { - int ret = 0, der_max_len = 0, derSz = 0; - byte *derBuf; - WOLFSSL_EVP_PKEY* pkey; + int ret = 1; + byte *pem = NULL; + int pLen = 0; WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSAPrivateKey"); - if (bio == NULL || dsa == NULL) { + (void)cb; + (void)arg; + + /* Validate parameters. */ + if ((bio == NULL) || (dsa == NULL)) { WOLFSSL_MSG("Bad Function Arguments"); - return 0; + ret = 0; } - pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); - if (pkey == NULL) { - WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); - return 0; + if (ret == 1) { + ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, cipher, passwd, passwdSz, + &pem, &pLen); } - pkey->type = EVP_PKEY_DSA; - pkey->dsa = dsa; - pkey->ownDsa = 0; + /* Write PEM to BIO. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) { + WOLFSSL_ERROR_MSG("DSA private key BIO write failed"); + ret = 0; + } - /* 4 > size of pub, priv, p, q, g + ASN.1 additional information */ - der_max_len = MAX_DSA_PRIVKEY_SZ; + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return ret; +} - derBuf = (byte*)XMALLOC((size_t)der_max_len, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (derBuf == NULL) { - WOLFSSL_MSG("Malloc failed"); - wolfSSL_EVP_PKEY_free(pkey); - return 0; - } +#ifndef HAVE_SELFTEST +/* Encode the DSA public key as DER. + * + * @param [in] key DSA key to encode. + * @param [out] der Pointer through which buffer is returned. + * @param [in] heap Heap hint. + * @return Size of encoding on success. + * @return 0 on error. + */ +static int wolfssl_dsa_key_to_pubkey_der(WOLFSSL_DSA* key, unsigned char** der, + void* heap) +{ + int sz; + unsigned char* buf = NULL; - /* convert key to der format */ - derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, (word32)der_max_len); - if (derSz < 0) { - WOLFSSL_MSG("wc_DsaKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - wolfSSL_EVP_PKEY_free(pkey); - return 0; + /* Use maximum encoded size to allocate. */ + sz = MAX_DSA_PUBKEY_SZ; + /* Allocate memory to hold encoding. */ + buf = (byte*)XMALLOC((size_t)sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("malloc failed"); + sz = 0; } - - pkey->pkey.ptr = (char*)XMALLOC((size_t)derSz, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (pkey->pkey.ptr == NULL) { - WOLFSSL_MSG("key malloc failed"); - XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - wolfSSL_EVP_PKEY_free(pkey); - return 0; + if (sz > 0) { + /* Encode public key to DER using wolfSSL. */ + sz = wc_DsaKeyToPublicDer((DsaKey*)key->internal, buf, (word32)sz); + if (sz < 0) { + WOLFSSL_MSG("wc_DsaKeyToPublicDer failed"); + sz = 0; + } } - /* add der info to the evp key */ - pkey->pkey_sz = derSz; - XMEMCPY(pkey->pkey.ptr, derBuf, (size_t)derSz); - XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - - ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len, - cb, arg); - wolfSSL_EVP_PKEY_free(pkey); + /* Return buffer on success. */ + if (sz > 0) { + *der = buf; + } + else { + /* Dispose of any dynamically allocated data not returned. */ + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + } - return ret; + return sz; } -#ifndef HAVE_SELFTEST /* Takes a DSA public key and writes it out to a WOLFSSL_BIO * Returns 1 or 0 */ int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa) { - int ret = 0; - WOLFSSL_EVP_PKEY* pkey; + int ret = 1; + unsigned char* derBuf = NULL; + int derSz = 0; + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_DSA_PUBKEY"); - if (bio == NULL || dsa == NULL) { - WOLFSSL_MSG("Bad function arguments"); + /* Validate parameters. */ + if ((bio == NULL) || (dsa == NULL)) { + WOLFSSL_MSG("Bad Function Arguments"); return 0; } - pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); - if (pkey == NULL) { - WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); - return 0; + /* Encode public key in EC key as DER. */ + derSz = wolfssl_dsa_key_to_pubkey_der(dsa, &derBuf, bio->heap); + if (derSz == 0) { + ret = 0; } - pkey->type = EVP_PKEY_DSA; - pkey->dsa = dsa; - pkey->ownDsa = 0; + /* Write out to BIO the PEM encoding of the DSA public key. */ + if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio, + PUBLICKEY_TYPE) != 1)) { + ret = 0; + } + + /* Dispose of any dynamically allocated data. */ + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - ret = pem_write_bio_pubkey(bio, pkey); - wolfSSL_EVP_PKEY_free(pkey); return ret; } #endif /* HAVE_SELFTEST */ @@ -7305,7 +7466,7 @@ int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out) *out += len; } /* An error occurred unless only length returned. */ - else if (ret != LENGTH_ONLY_E) { + else if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { err = 1; } } @@ -7455,7 +7616,7 @@ static WOLFSSL_DH *wolfssl_dhparams_read_pem(WOLFSSL_DH **dh, } if (memAlloced) { /* PEM data no longer needed. */ - XFREE(pem, NULL, DYNAMIC_TYPE_PEM); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); } if (!err) { @@ -7610,7 +7771,7 @@ static int wolfssl_dhparams_to_der(WOLFSSL_DH* dh, unsigned char** out, /* Use wolfSSL API to get length of DER encode DH parameters. */ key = (DhKey*)dh->internal; ret = wc_DhParamsToDer(key, NULL, &derSz); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_ERROR_MSG("Failed to get size of DH params"); err = 1; } @@ -7681,7 +7842,7 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh) } } if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, - DH_PARAM_TYPE, NULL) != WOLFSSL_SUCCESS)) { + DH_PARAM_TYPE, NULL) != 1)) { ret = 0; } @@ -8569,7 +8730,7 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub, if (ret == 0) { /* Get the public key into the array. */ pubSz = wolfSSL_BN_bn2bin(otherPub, pub); - if (privSz <= 0) { + if (pubSz <= 0) { ret = -1; } } @@ -9715,7 +9876,6 @@ void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point) #endif } -#ifndef HAVE_SELFTEST /* Convert EC point to hex string that as either uncompressed or compressed. * * ECC point compression types were not included in selftest ecc.h @@ -9828,7 +9988,100 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, return hex; } -#endif /* HAVE_SELFTEST */ +static size_t hex_to_bytes(const char *hex, unsigned char *output, size_t sz) +{ + word32 i; + for (i = 0; i < sz; i++) { + signed char ch1, ch2; + ch1 = HexCharToByte(hex[i * 2]); + ch2 = HexCharToByte(hex[i * 2 + 1]); + if ((ch1 < 0) || (ch2 < 0)) { + WOLFSSL_MSG("hex_to_bytes: syntax error"); + return 0; + } + output[i] = (unsigned char)((ch1 << 4) + ch2); + } + return sz; +} + +WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const EC_GROUP *group, + const char *hex, WOLFSSL_EC_POINT*p, WOLFSSL_BN_CTX *ctx) +{ + /* for uncompressed mode */ + size_t str_sz; + BIGNUM *Gx = NULL; + BIGNUM *Gy = NULL; + char strGx[MAX_ECC_BYTES * 2 + 1]; + + /* for compressed mode */ + int key_sz; + byte *octGx = (byte *)strGx; /* octGx[MAX_ECC_BYTES] */ + + int p_alloc = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_hex2point"); + + if (group == NULL || hex == NULL || ctx == NULL) + return NULL; + + if (p == NULL) { + if ((p = wolfSSL_EC_POINT_new(group)) == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new"); + goto err; + } + p_alloc = 1; + } + + key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8; + if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */ + str_sz = key_sz * 2; + + XMEMSET(strGx, 0x0, str_sz + 1); + XMEMCPY(strGx, hex + 2, str_sz); + + if (wolfSSL_BN_hex2bn(&Gx, strGx) == 0) + goto err; + + if (wolfSSL_BN_hex2bn(&Gy, hex + 2 + str_sz) == 0) + goto err; + + ret = wolfSSL_EC_POINT_set_affine_coordinates_GFp + (group, p, Gx, Gy, ctx); + + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp"); + goto err; + } + } + else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) { + size_t sz = XSTRLEN(hex + 2) / 2; + /* compressed mode */ + octGx[0] = ECC_POINT_COMP_ODD; + if (hex_to_bytes(hex + 2, octGx + 1, sz) != sz) { + goto err; + } + if (wolfSSL_ECPoint_d2i(octGx, key_sz + 1, group, p) + != WOLFSSL_SUCCESS) { + goto err; + } + } + else + goto err; + + wolfSSL_BN_free(Gx); + wolfSSL_BN_free(Gy); + return p; + +err: + wolfSSL_BN_free(Gx); + wolfSSL_BN_free(Gy); + if (p_alloc) { + EC_POINT_free(p); + } + return NULL; + +} /* Encode the EC point as an uncompressed point in DER. * @@ -9871,7 +10124,8 @@ int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, int ret = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)point->internal, out, len); /* Check return. When out is NULL, return will be length only error. */ - if ((ret != MP_OKAY) && ((out != NULL) || (ret != LENGTH_ONLY_E))) { + if ((ret != MP_OKAY) && ((out != NULL) || + (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)))) { WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); res = 0; } @@ -11549,7 +11803,8 @@ static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src) if (ret == 0) { /* Copy private key. */ - ret = mp_copy(wc_ecc_key_get_priv(src), wc_ecc_key_get_priv(dst)); + ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src), + wc_ecc_key_get_priv(dst)); if (ret != MP_OKAY) { WOLFSSL_MSG("mp_copy error"); } @@ -12005,7 +12260,7 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, res = 1; } /* Error out on parsing error. */ - else if (ret != ASN_PARSE_E) { + else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) { WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); res = -1; } @@ -12076,12 +12331,9 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, * EC key PEM APIs */ -#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM)) || \ - (!defined(NO_BIO) && (defined(WOLFSSL_KEY_GEN) || \ - defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT))) +#ifdef HAVE_ECC_KEY_EXPORT +#if defined(WOLFSSL_KEY_GEN) && (!defined(NO_FILESYSTEM) || !defined(NO_BIO)) /* Encode the EC public key as DER. - * - * Also used by pem_write_pubkey(). * * @param [in] key EC key to encode. * @param [out] der Pointer through which buffer is returned. @@ -12176,6 +12428,7 @@ int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key) return ret; } #endif +#endif #ifndef NO_BIO /* Read a PEM encoded EC public key from a BIO. @@ -12302,7 +12555,7 @@ WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio, } #endif /* !NO_BIO */ -#if defined(WOLFSSL_KEY_GEN) +#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ECC_KEY_EXPORT) #ifndef NO_BIO /* Write out the EC public key as PEM to the BIO. * @@ -12331,7 +12584,7 @@ int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec) ret = 0; } - /* Write out to BIO the PEM encoding of the EC private key. */ + /* Write out to BIO the PEM encoding of the EC public key. */ if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio, ECC_PUBLICKEY_TYPE) != 1)) { ret = 0; @@ -12534,7 +12787,7 @@ int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec, } #endif /* NO_FILESYSTEM */ -#endif /* defined(WOLFSSL_KEY_GEN) */ +#endif /* WOLFSSL_KEY_GEN && HAVE_ECC_KEY_EXPORT */ /* * EC key print APIs @@ -13106,13 +13359,17 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) /* Check if we know which internal curve index to use. */ if (key->group->curve_idx < 0) { /* Generate key using the default curve. */ +#if FIPS_VERSION3_GE(6,0,0) + key->group->curve_idx = ECC_SECP256R1; /* FIPS default to 256 */ +#else key->group->curve_idx = ECC_CURVE_DEF; +#endif } /* Create a random number generator. */ rng = wolfssl_make_rng(tmpRng, &initTmpRng); if (rng == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG"); res = 0; } } @@ -13120,11 +13377,30 @@ int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid * is 0 then pass ECC_CURVE_DEF as arg */ int eccEnum = key->group->curve_nid ? +#if FIPS_VERSION3_GE(6,0,0) + NIDToEccEnum(key->group->curve_nid) : ECC_SECP256R1; +#else NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF; +#endif /* Get the internal EC key. */ ecc_key* ecKey = (ecc_key*)key->internal; /* Make the key using internal API. */ - int ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum); + int ret = 0; + +#if FIPS_VERSION3_GE(6,0,0) + /* In the case of FIPS only allow key generation with approved curves */ + if (eccEnum != ECC_SECP256R1 && eccEnum != ECC_SECP224R1 && + eccEnum != ECC_SECP384R1 && eccEnum != ECC_SECP521R1) { + WOLFSSL_MSG("Unsupported curve selected in FIPS mode"); + res = 0; + } + if (res == 1) { +#endif + ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum); +#if FIPS_VERSION3_GE(6,0,0) + } +#endif + #if defined(WOLFSSL_ASYNC_CRYPT) /* Wait on asynchronouse operation. */ ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE); @@ -13383,6 +13659,7 @@ WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig, int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) { word32 len = 0; + int update_p = 1; /* Validate parameter. */ if (sig != NULL) { @@ -13402,6 +13679,17 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) /* Add in the length of the SEQUENCE. */ len += (word32)1 + ASN_LEN_SIZE(len); + #ifdef WOLFSSL_I2D_ECDSA_SIG_ALLOC + if ((pp != NULL) && (*pp == NULL)) { + *pp = (unsigned char *)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (*pp != NULL) { + WOLFSSL_MSG("malloc error"); + return 0; + } + update_p = 0; + } + #endif + /* Encode only if there is a buffer to encode into. */ if ((pp != NULL) && (*pp != NULL)) { /* Encode using the internal representations of r and s. */ @@ -13410,7 +13698,7 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) /* No bytes encoded. */ len = 0; } - else { + else if (update_p) { /* Update pointer to after encoding. */ *pp += len; } @@ -13861,12 +14149,2311 @@ int wolfSSL_ECDH_compute_key(void *out, size_t outLen, /* End ECDH */ -#endif /* OPENSSL_EXTRA */ +#ifndef NO_WOLFSSL_STUB +const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_OpenSSL"); -#endif /* HAVE_ECC */ + return NULL; +} -/******************************************************************************* - * END OF EC API +WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new( + const WOLFSSL_EC_KEY_METHOD *meth) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_new"); + + (void)meth; + + return NULL; +} + +void wolfSSL_EC_KEY_METHOD_free(WOLFSSL_EC_KEY_METHOD *meth) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_free"); + + (void)meth; +} + +void wolfSSL_EC_KEY_METHOD_set_init(WOLFSSL_EC_KEY_METHOD *meth, + void* a1, void* a2, void* a3, void* a4, void* a5, void* a6) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_init"); + + (void)meth; + (void)a1; + (void)a2; + (void)a3; + (void)a4; + (void)a5; + (void)a6; +} + +void wolfSSL_EC_KEY_METHOD_set_sign(WOLFSSL_EC_KEY_METHOD *meth, + void* a1, void* a2, void* a3) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_METHOD_set_sign"); + + (void)meth; + (void)a1; + (void)a2; + (void)a3; +} + +const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_get_method( + const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_get_method"); + + (void)key; + + return NULL; +} + +int wolfSSL_EC_KEY_set_method(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_KEY_METHOD *meth) +{ + WOLFSSL_STUB("wolfSSL_EC_KEY_set_method"); + + (void)key; + (void)meth; + + return 0; +} + +#endif /* !NO_WOLFSSL_STUB */ + +#endif /* OPENSSL_EXTRA */ + +#endif /* HAVE_ECC */ + +/******************************************************************************* + * END OF EC API + ******************************************************************************/ + +/******************************************************************************* + * START OF EC25519 API + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519) + +/* Generate an EC25519 key pair. + * + * Output keys are in little endian format. + * + * @param [out] priv EC25519 private key data. + * @param [in, out] privSz On in, the size of priv in bytes. + * On out, the length of the private key data in bytes. + * @param [out] pub EC25519 public key data. + * @param [in, out] pubSz On in, the size of pub in bytes. + * On out, the length of the public key data in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifdef WOLFSSL_KEY_GEN + int res = 1; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + curve25519_key key; + + WOLFSSL_ENTER("wolfSSL_EC25519_generate_key"); + + /* Validate parameters. */ + if ((priv == NULL) || (privSz == NULL) || (*privSz < CURVE25519_KEYSIZE) || + (pub == NULL) || (pubSz == NULL) || (*pubSz < CURVE25519_KEYSIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + if (res) { + /* Create a random number generator. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG"); + res = 0; + } + } + + /* Initialize a Curve25519 key. */ + if (res && (wc_curve25519_init(&key) != 0)) { + WOLFSSL_MSG("wc_curve25519_init failed"); + res = 0; + } + if (res) { + /* Make a Curve25519 key pair. */ + int ret = wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_make_key failed"); + res = 0; + } + if (res) { + /* Export Curve25519 key pair to buffers. */ + ret = wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub, + pubSz, EC25519_LITTLE_ENDIAN); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed"); + res = 0; + } + } + + /* Dispose of key. */ + wc_curve25519_free(&key); + } + + if (initTmpRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + return res; +#else + WOLFSSL_MSG("No Key Gen built in"); + + (void)priv; + (void)privSz; + (void)pub; + (void)pubSz; + + return 0; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* Compute a shared secret from private and public EC25519 keys. + * + * Input and output keys are in little endian format + * + * @param [out] shared Shared secret buffer. + * @param [in, out] sharedSz On in, the size of shared in bytes. + * On out, the length of the secret in bytes. + * @param [in] priv EC25519 private key data. + * @param [in] privSz Length of the private key data in bytes. + * @param [in] pub EC25519 public key data. + * @param [in] pubSz Length of the public key data in bytes. + * @return 1 on success + * @return 0 on failure. + */ +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) +{ +#ifdef WOLFSSL_KEY_GEN + int res = 1; + curve25519_key privkey; + curve25519_key pubkey; + + WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); + + /* Validate parameters. */ + if ((shared == NULL) || (sharedSz == NULL) || + (*sharedSz < CURVE25519_KEYSIZE) || (priv == NULL) || + (privSz < CURVE25519_KEYSIZE) || (pub == NULL) || + (pubSz < CURVE25519_KEYSIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + /* Initialize private key object. */ + if (res && (wc_curve25519_init(&privkey) != 0)) { + WOLFSSL_MSG("wc_curve25519_init privkey failed"); + res = 0; + } + if (res) { + /* Initialize public key object. */ + if (wc_curve25519_init(&pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init pubkey failed"); + res = 0; + } + if (res) { + /* Import our private key. */ + int ret = wc_curve25519_import_private_ex(priv, privSz, &privkey, + EC25519_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve25519_import_private_ex failed"); + res = 0; + } + + if (res) { + /* Import peer's public key. */ + ret = wc_curve25519_import_public_ex(pub, pubSz, &pubkey, + EC25519_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve25519_import_public_ex failed"); + res = 0; + } + } + if (res) { + /* Compute shared secret. */ + ret = wc_curve25519_shared_secret_ex(&privkey, &pubkey, shared, + sharedSz, EC25519_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + res = 0; + } + } + + wc_curve25519_free(&pubkey); + } + wc_curve25519_free(&privkey); + } + + return res; +#else + WOLFSSL_MSG("No Key Gen built in"); + + (void)shared; + (void)sharedSz; + (void)priv; + (void)privSz; + (void)pub; + (void)pubSz; + + return 0; +#endif /* WOLFSSL_KEY_GEN */ +} +#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */ + +/******************************************************************************* + * END OF EC25519 API + ******************************************************************************/ + +/******************************************************************************* + * START OF ED25519 API + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519) +/* Generate an ED25519 key pair. + * + * Output keys are in little endian format. + * + * @param [out] priv ED25519 private key data. + * @param [in, out] privSz On in, the size of priv in bytes. + * On out, the length of the private key data in bytes. + * @param [out] pub ED25519 public key data. + * @param [in, out] pubSz On in, the size of pub in bytes. + * On out, the length of the public key data in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ED25519_KEY_EXPORT) + int res = 1; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + ed25519_key key; + + WOLFSSL_ENTER("wolfSSL_ED25519_generate_key"); + + /* Validate parameters. */ + if ((priv == NULL) || (privSz == NULL) || + (*privSz < ED25519_PRV_KEY_SIZE) || (pub == NULL) || + (pubSz == NULL) || (*pubSz < ED25519_PUB_KEY_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + if (res) { + /* Create a random number generator. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG"); + res = 0; + } + } + + /* Initialize an Ed25519 key. */ + if (res && (wc_ed25519_init(&key) != 0)) { + WOLFSSL_MSG("wc_ed25519_init failed"); + res = 0; + } + if (res) { + /* Make an Ed25519 key pair. */ + int ret = wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_ed25519_make_key failed"); + res = 0; + } + if (res) { + /* Export Curve25519 key pair to buffers. */ + ret = wc_ed25519_export_key(&key, priv, privSz, pub, pubSz); + if (ret != 0) { + WOLFSSL_MSG("wc_ed25519_export_key failed"); + res = 0; + } + } + + wc_ed25519_free(&key); + } + + if (initTmpRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + return res; +#else +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); +#else + WOLFSSL_MSG("No ED25519 key export built in"); +#endif + + (void)priv; + (void)privSz; + (void)pub; + (void)pubSz; + + return 0; +#endif /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */ +} + +/* Sign a message with Ed25519 using the private key. + * + * Input and output keys are in little endian format. + * Priv is a buffer containing private and public part of key. + * + * @param [in] msg Message to be signed. + * @param [in] msgSz Length of message in bytes. + * @param [in] priv ED25519 private key data. + * @param [in] privSz Length in bytes of private key data. + * @param [out] sig Signature buffer. + * @param [in, out] sigSz On in, the length of the signature buffer in bytes. + * On out, the length of the signature in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, unsigned char *sig, + unsigned int *sigSz) +{ +#if defined(HAVE_ED25519_SIGN) && defined(WOLFSSL_KEY_GEN) && \ + defined(HAVE_ED25519_KEY_IMPORT) + ed25519_key key; + int res = 1; + + WOLFSSL_ENTER("wolfSSL_ED25519_sign"); + + /* Validate parameters. */ + if ((priv == NULL) || (privSz != ED25519_PRV_KEY_SIZE) || + (msg == NULL) || (sig == NULL) || (sigSz == NULL) || + (*sigSz < ED25519_SIG_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + /* Initialize Ed25519 key. */ + if (res && (wc_ed25519_init(&key) != 0)) { + WOLFSSL_MSG("wc_curve25519_init failed"); + res = 0; + } + if (res) { + /* Import private and public key. */ + int ret = wc_ed25519_import_private_key(priv, privSz / 2, + priv + (privSz / 2), ED25519_PUB_KEY_SIZE, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_ed25519_import_private failed"); + res = 0; + } + + if (res) { + /* Sign message with Ed25519. */ + ret = wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + res = 0; + } + } + + wc_ed25519_free(&key); + } + + return res; +#else +#if !defined(HAVE_ED25519_SIGN) + WOLFSSL_MSG("No ED25519 sign built in"); +#elif !defined(WOLFSSL_KEY_GEN) + WOLFSSL_MSG("No Key Gen built in"); +#elif !defined(HAVE_ED25519_KEY_IMPORT) + WOLFSSL_MSG("No ED25519 Key import built in"); +#endif + + (void)msg; + (void)msgSz; + (void)priv; + (void)privSz; + (void)sig; + (void)sigSz; + + return 0; +#endif /* HAVE_ED25519_SIGN && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */ +} + +/* Verify a message with Ed25519 using the public key. + * + * Input keys are in little endian format. + * + * @param [in] msg Message to be verified. + * @param [in] msgSz Length of message in bytes. + * @param [in] pub ED25519 public key data. + * @param [in] privSz Length in bytes of public key data. + * @param [in] sig Signature buffer. + * @param [in] sigSz Length of the signature in bytes. + * @return 1 on success + * @return 0 on failure. + */ +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) +{ +#if defined(HAVE_ED25519_VERIFY) && defined(WOLFSSL_KEY_GEN) && \ + defined(HAVE_ED25519_KEY_IMPORT) + ed25519_key key; + int res = 1; + + WOLFSSL_ENTER("wolfSSL_ED25519_verify"); + + /* Validate parameters. */ + if ((pub == NULL) || (pubSz != ED25519_PUB_KEY_SIZE) || (msg == NULL) || + (sig == NULL) || (sigSz != ED25519_SIG_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + /* Initialize Ed25519 key. */ + if (res && (wc_ed25519_init(&key) != 0)) { + WOLFSSL_MSG("wc_curve25519_init failed"); + res = 0; + } + if (res) { + /* Import public key. */ + int ret = wc_ed25519_import_public(pub, pubSz, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_ed25519_import_public failed"); + res = 0; + } + + if (res) { + int check = 0; + + /* Verify signature with message and public key. */ + ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz, &check, + &key); + /* Check for errors in verification process. */ + if (ret != 0) { + WOLFSSL_MSG("wc_ed25519_verify_msg failed"); + res = 0; + } + /* Check signature is valid. */ + else if (!check) { + WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)"); + res = 0; + } + } + + wc_ed25519_free(&key); + } + + return res; +#else +#if !defined(HAVE_ED25519_VERIFY) + WOLFSSL_MSG("No ED25519 verify built in"); +#elif !defined(WOLFSSL_KEY_GEN) + WOLFSSL_MSG("No Key Gen built in"); +#elif !defined(HAVE_ED25519_KEY_IMPORT) + WOLFSSL_MSG("No ED25519 Key import built in"); +#endif + + (void)msg; + (void)msgSz; + (void)pub; + (void)pubSz; + (void)sig; + (void)sigSz; + + return 0; +#endif /* HAVE_ED25519_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */ +} + +#endif /* OPENSSL_EXTRA && HAVE_ED25519 */ + +/******************************************************************************* + * END OF ED25519 API + ******************************************************************************/ + +/******************************************************************************* + * START OF EC448 API + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448) +/* Generate an EC448 key pair. + * + * Output keys are in little endian format. + * + * @param [out] priv EC448 private key data. + * @param [in, out] privSz On in, the size of priv in bytes. + * On out, the length of the private key data in bytes. + * @param [out] pub EC448 public key data. + * @param [in, out] pubSz On in, the size of pub in bytes. + * On out, the length of the public key data in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC448_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifdef WOLFSSL_KEY_GEN + int res = 1; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + curve448_key key; + + WOLFSSL_ENTER("wolfSSL_EC448_generate_key"); + + /* Validate parameters. */ + if ((priv == NULL) || (privSz == NULL) || (*privSz < CURVE448_KEY_SIZE) || + (pub == NULL) || (pubSz == NULL) || (*pubSz < CURVE448_KEY_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + if (res) { + /* Create a random number generator. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG"); + res = 0; + } + } + + /* Initialize a Curve448 key. */ + if (res && (wc_curve448_init(&key) != 0)) { + WOLFSSL_MSG("wc_curve448_init failed"); + res = 0; + } + if (res) { + /* Make a Curve448 key pair. */ + int ret = wc_curve448_make_key(rng, CURVE448_KEY_SIZE, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_curve448_make_key failed"); + res = 0; + } + if (res) { + /* Export Curve448 key pair to buffers. */ + ret = wc_curve448_export_key_raw_ex(&key, priv, privSz, pub, pubSz, + EC448_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve448_export_key_raw_ex failed"); + res = 0; + } + } + + /* Dispose of key. */ + wc_curve448_free(&key); + } + + if (initTmpRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + return res; +#else + WOLFSSL_MSG("No Key Gen built in"); + + (void)priv; + (void)privSz; + (void)pub; + (void)pubSz; + + return 0; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* Compute a shared secret from private and public EC448 keys. + * + * Input and output keys are in little endian format + * + * @param [out] shared Shared secret buffer. + * @param [in, out] sharedSz On in, the size of shared in bytes. + * On out, the length of the secret in bytes. + * @param [in] priv EC448 private key data. + * @param [in] privSz Length of the private key data in bytes. + * @param [in] pub EC448 public key data. + * @param [in] pubSz Length of the public key data in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC448_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz) +{ +#ifdef WOLFSSL_KEY_GEN + int res = 1; + curve448_key privkey; + curve448_key pubkey; + + WOLFSSL_ENTER("wolfSSL_EC448_shared_key"); + + /* Validate parameters. */ + if ((shared == NULL) || (sharedSz == NULL) || + (*sharedSz < CURVE448_KEY_SIZE) || (priv == NULL) || + (privSz < CURVE448_KEY_SIZE) || (pub == NULL) || + (pubSz < CURVE448_KEY_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + /* Initialize private key object. */ + if (res && (wc_curve448_init(&privkey) != 0)) { + WOLFSSL_MSG("wc_curve448_init privkey failed"); + res = 0; + } + if (res) { + /* Initialize public key object. */ + if (wc_curve448_init(&pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve448_init pubkey failed"); + res = 0; + } + if (res) { + /* Import our private key. */ + int ret = wc_curve448_import_private_ex(priv, privSz, &privkey, + EC448_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve448_import_private_ex failed"); + res = 0; + } + + if (res) { + /* Import peer's public key. */ + ret = wc_curve448_import_public_ex(pub, pubSz, &pubkey, + EC448_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve448_import_public_ex failed"); + res = 0; + } + } + if (res) { + /* Compute shared secret. */ + ret = wc_curve448_shared_secret_ex(&privkey, &pubkey, shared, + sharedSz, EC448_LITTLE_ENDIAN); + if (ret != 0) { + WOLFSSL_MSG("wc_curve448_shared_secret_ex failed"); + res = 0; + } + } + + wc_curve448_free(&pubkey); + } + wc_curve448_free(&privkey); + } + + return res; +#else + WOLFSSL_MSG("No Key Gen built in"); + + (void)shared; + (void)sharedSz; + (void)priv; + (void)privSz; + (void)pub; + (void)pubSz; + + return 0; +#endif /* WOLFSSL_KEY_GEN */ +} +#endif /* OPENSSL_EXTRA && HAVE_CURVE448 */ + +/******************************************************************************* + * END OF EC448 API + ******************************************************************************/ + +/******************************************************************************* + * START OF ED448 API + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ED448) +/* Generate an ED448 key pair. + * + * Output keys are in little endian format. + * + * @param [out] priv ED448 private key data. + * @param [in, out] privSz On in, the size of priv in bytes. + * On out, the length of the private key data in bytes. + * @param [out] pub ED448 public key data. + * @param [in, out] pubSz On in, the size of pub in bytes. + * On out, the length of the public key data in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_ED448_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#if defined(WOLFSSL_KEY_GEN) && defined(HAVE_ED448_KEY_EXPORT) + int res = 1; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + ed448_key key; + + WOLFSSL_ENTER("wolfSSL_ED448_generate_key"); + + /* Validate parameters. */ + if ((priv == NULL) || (privSz == NULL) || + (*privSz < ED448_PRV_KEY_SIZE) || (pub == NULL) || + (pubSz == NULL) || (*pubSz < ED448_PUB_KEY_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + if (res) { + /* Create a random number generator. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to make RNG"); + res = 0; + } + } + + /* Initialize an Ed448 key. */ + if (res && (wc_ed448_init(&key) != 0)) { + WOLFSSL_MSG("wc_ed448_init failed"); + res = 0; + } + if (res) { + /* Make an Ed448 key pair. */ + int ret = wc_ed448_make_key(rng, ED448_KEY_SIZE, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_ed448_make_key failed"); + res = 0; + } + if (res) { + /* Export Curve448 key pair to buffers. */ + ret = wc_ed448_export_key(&key, priv, privSz, pub, pubSz); + if (ret != 0) { + WOLFSSL_MSG("wc_ed448_export_key failed"); + res = 0; + } + } + + wc_ed448_free(&key); + } + + if (initTmpRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + return res; +#else +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); +#else + WOLFSSL_MSG("No ED448 key export built in"); +#endif + + (void)priv; + (void)privSz; + (void)pub; + (void)pubSz; + + return 0; +#endif /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */ +} + +/* Sign a message with Ed448 using the private key. + * + * Input and output keys are in little endian format. + * Priv is a buffer containing private and public part of key. + * + * @param [in] msg Message to be signed. + * @param [in] msgSz Length of message in bytes. + * @param [in] priv ED448 private key data. + * @param [in] privSz Length in bytes of private key data. + * @param [out] sig Signature buffer. + * @param [in, out] sigSz On in, the length of the signature buffer in bytes. + * On out, the length of the signature in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_ED448_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, unsigned char *sig, + unsigned int *sigSz) +{ +#if defined(HAVE_ED448_SIGN) && defined(WOLFSSL_KEY_GEN) && \ + defined(HAVE_ED448_KEY_IMPORT) + ed448_key key; + int res = 1; + + WOLFSSL_ENTER("wolfSSL_ED448_sign"); + + /* Validate parameters. */ + if ((priv == NULL) || (privSz != ED448_PRV_KEY_SIZE) || + (msg == NULL) || (sig == NULL) || (sigSz == NULL) || + (*sigSz < ED448_SIG_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + /* Initialize Ed448 key. */ + if (res && (wc_ed448_init(&key) != 0)) { + WOLFSSL_MSG("wc_curve448_init failed"); + res = 0; + } + if (res) { + /* Import private and public key. */ + int ret = wc_ed448_import_private_key(priv, privSz / 2, + priv + (privSz / 2), ED448_PUB_KEY_SIZE, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_ed448_import_private failed"); + res = 0; + } + + if (res) { + /* Sign message with Ed448 - no context. */ + ret = wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("wc_curve448_shared_secret_ex failed"); + res = 0; + } + } + + wc_ed448_free(&key); + } + + return res; +#else +#if !defined(HAVE_ED448_SIGN) + WOLFSSL_MSG("No ED448 sign built in"); +#elif !defined(WOLFSSL_KEY_GEN) + WOLFSSL_MSG("No Key Gen built in"); +#elif !defined(HAVE_ED448_KEY_IMPORT) + WOLFSSL_MSG("No ED448 Key import built in"); +#endif + + (void)msg; + (void)msgSz; + (void)priv; + (void)privSz; + (void)sig; + (void)sigSz; + + return 0; +#endif /* HAVE_ED448_SIGN && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */ +} + +/* Verify a message with Ed448 using the public key. + * + * Input keys are in little endian format. + * + * @param [in] msg Message to be verified. + * @param [in] msgSz Length of message in bytes. + * @param [in] pub ED448 public key data. + * @param [in] privSz Length in bytes of public key data. + * @param [in] sig Signature buffer. + * @param [in] sigSz Length of the signature in bytes. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_ED448_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, const unsigned char *sig, + unsigned int sigSz) +{ +#if defined(HAVE_ED448_VERIFY) && defined(WOLFSSL_KEY_GEN) && \ + defined(HAVE_ED448_KEY_IMPORT) + ed448_key key; + int res = 1; + + WOLFSSL_ENTER("wolfSSL_ED448_verify"); + + /* Validate parameters. */ + if ((pub == NULL) || (pubSz != ED448_PUB_KEY_SIZE) || (msg == NULL) || + (sig == NULL) || (sigSz != ED448_SIG_SIZE)) { + WOLFSSL_MSG("Bad arguments"); + res = 0; + } + + /* Initialize Ed448 key. */ + if (res && (wc_ed448_init(&key) != 0)) { + WOLFSSL_MSG("wc_curve448_init failed"); + res = 0; + } + if (res) { + /* Import public key. */ + int ret = wc_ed448_import_public(pub, pubSz, &key); + if (ret != 0) { + WOLFSSL_MSG("wc_ed448_import_public failed"); + res = 0; + } + + if (res) { + int check = 0; + + /* Verify signature with message and public key - no context. */ + ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check, + &key, NULL, 0); + /* Check for errors in verification process. */ + if (ret != 0) { + WOLFSSL_MSG("wc_ed448_verify_msg failed"); + res = 0; + } + /* Check signature is valid. */ + else if (!check) { + WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)"); + res = 0; + } + } + + wc_ed448_free(&key); + } + + return res; +#else +#if !defined(HAVE_ED448_VERIFY) + WOLFSSL_MSG("No ED448 verify built in"); +#elif !defined(WOLFSSL_KEY_GEN) + WOLFSSL_MSG("No Key Gen built in"); +#elif !defined(HAVE_ED448_KEY_IMPORT) + WOLFSSL_MSG("No ED448 Key import built in"); +#endif + + (void)msg; + (void)msgSz; + (void)pub; + (void)pubSz; + (void)sig; + (void)sigSz; + + return 0; +#endif /* HAVE_ED448_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */ +} +#endif /* OPENSSL_EXTRA && HAVE_ED448 */ + +/******************************************************************************* + * END OF ED448 API + ******************************************************************************/ + +/******************************************************************************* + * START OF GENERIC PUBLIC KEY PEM APIs + ******************************************************************************/ + +#ifdef OPENSSL_EXTRA +/* Sets default callback password for PEM. + * + * @param [out] buf Buffer to hold password. + * @param [in] num Number of characters in buffer. + * @param [in] rwFlag Read/write flag. Ignored. + * @param [in] userData User data - assumed to be default password. + * @return Password size on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_def_callback(char* buf, int num, int rwFlag, void* userData) +{ + int sz = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_def_callback"); + + (void)rwFlag; + + /* We assume that the user passes a default password as userdata */ + if ((buf != NULL) && (userData != NULL)) { + sz = (int)XSTRLEN((const char*)userData); + sz = (int)min((word32)sz, (word32)num); + XMEMCPY(buf, userData, sz); + } + else { + WOLFSSL_MSG("Error, default password cannot be created."); + } + + return sz; +} + +#ifndef NO_BIO +/* Writes a public key to a WOLFSSL_BIO encoded in PEM format. + * + * @param [in] bio BIO to write to. + * @param [in] key Public key to write in PEM format. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY"); + + if ((bio != NULL) && (key != NULL)) { + switch (key->type) { +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) + case EVP_PKEY_RSA: + ret = wolfSSL_PEM_write_bio_RSA_PUBKEY(bio, key->rsa); + break; +#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ +#if !defined(NO_DSA) && !defined(HAVE_SELFTEST) && \ + (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) + case EVP_PKEY_DSA: + ret = wolfSSL_PEM_write_bio_DSA_PUBKEY(bio, key->dsa); + break; +#endif /* !NO_DSA && !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */ +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && \ + defined(WOLFSSL_KEY_GEN) + case EVP_PKEY_EC: + ret = wolfSSL_PEM_write_bio_EC_PUBKEY(bio, key->ecc); + break; +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + case EVP_PKEY_DH: + /* DH public key not supported. */ + WOLFSSL_MSG("Writing DH PUBKEY not supported!"); + break; +#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ + default: + /* Key type not supported. */ + WOLFSSL_MSG("Unknown Key type!"); + break; + } + } + + return ret; +} + +/* Writes a private key to a WOLFSSL_BIO encoded in PEM format. + * + * @param [in] bio BIO to write to. + * @param [in] key Public key to write in PEM format. + * @param [in] cipher Encryption cipher to use. + * @param [in] passwd Password to use when encrypting. + * @param [in] len Length of password. + * @param [in] cb Password callback. + * @param [in] arg Password callback argument. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, unsigned char* passwd, int len, + wc_pem_password_cb* cb, void* arg) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); + + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + /* Validate parameters. */ + if ((bio == NULL) || (key == NULL)) { + WOLFSSL_MSG("Bad Function Arguments"); + ret = 0; + } + + if (ret == 1) { + #ifdef WOLFSSL_KEY_GEN + switch (key->type) { + #ifndef NO_RSA + case EVP_PKEY_RSA: + /* Write using RSA specific API. */ + ret = wolfSSL_PEM_write_bio_RSAPrivateKey(bio, key->rsa, + cipher, passwd, len, cb, arg); + break; + #endif + #ifndef NO_DSA + case EVP_PKEY_DSA: + /* Write using DSA specific API. */ + ret = wolfSSL_PEM_write_bio_DSAPrivateKey(bio, key->dsa, + cipher, passwd, len, cb, arg); + break; + #endif + #ifdef HAVE_ECC + case EVP_PKEY_EC: + #if defined(HAVE_ECC_KEY_EXPORT) + /* Write using EC specific API. */ + ret = wolfSSL_PEM_write_bio_ECPrivateKey(bio, key->ecc, + cipher, passwd, len, cb, arg); + #else + ret = der_write_to_bio_as_pem((byte*)key->pkey.ptr, + key->pkey_sz, bio, EC_PRIVATEKEY_TYPE); + #endif + break; + #endif + #ifndef NO_DH + case EVP_PKEY_DH: + /* Write using generic API with DH type. */ + ret = der_write_to_bio_as_pem((byte*)key->pkey.ptr, + key->pkey_sz, bio, DH_PRIVATEKEY_TYPE); + break; + #endif + default: + WOLFSSL_MSG("Unknown Key type!"); + ret = 0; + break; + } + #else + int type = 0; + + switch (key->type) { + #ifndef NO_DSA + case EVP_PKEY_DSA: + type = DSA_PRIVATEKEY_TYPE; + break; + #endif + #ifdef HAVE_ECC + case EVP_PKEY_EC: + type = ECC_PRIVATEKEY_TYPE; + break; + #endif + #ifndef NO_DH + case EVP_PKEY_DH: + type = DH_PRIVATEKEY_TYPE; + break; + #endif + #ifndef NO_RSA + case EVP_PKEY_RSA: + type = PRIVATEKEY_TYPE; + break; + #endif + default: + ret = 0; + break; + } + if (ret == 1) { + /* Write using generic API with generic type. */ + ret = der_write_to_bio_as_pem((byte*)key->pkey.ptr, key->pkey_sz, + bio, type); + } + #endif + } + + return ret; +} +#endif /* !NO_BIO */ + +#ifndef NO_BIO +/* Create a private key object from the data in the BIO. + * + * @param [in] bio BIO to read from. + * @param [in, out] key Public key object. Object used if passed in. + * @param [in] cb Password callback. + * @param [in] arg Password callback argument. + * @return A WOLFSSL_EVP_PKEY object on success. + * @return NULL on failure. + */ +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY **key, wc_pem_password_cb *cb, void *arg) +{ + int err = 0; + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY"); + + if (bio == NULL) { + err = 1; + } + + /* Read the PEM public key from the BIO and convert to DER. */ + if ((!err) && (pem_read_bio_key(bio, cb, arg, PUBLICKEY_TYPE, NULL, + &der) < 0)) { + err = 1; + } + + if (!err) { + const unsigned char* ptr = der->buffer; + + /* Use key passed in if set. */ + if ((key != NULL) && (*key != NULL)) { + pkey = *key; + } + + /* Convert DER data to a public key object. */ + if (wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length) == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + pkey = NULL; + err = 1; + } + } + + /* Return the key if possible. */ + if ((!err) && (key != NULL) && (pkey != NULL)) { + *key = pkey; + } + /* Dispose of the DER encoding. */ + FreeDer(&der); + + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0); + + return pkey; +} + +/* Create a private key object from the data in the BIO. + * + * @param [in] bio BIO to read from. + * @param [in, out] key Private key object. Object used if passed in. + * @param [in] cb Password callback. + * @param [in] arg Password callback argument. + * @return A WOLFSSL_EVP_PKEY object on success. + * @return NULL on failure. + */ +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** key, wc_pem_password_cb* cb, void* arg) +{ + int err = 0; + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey"); + + /* Validate parameters. */ + if (bio == NULL) { + err = 1; + } + + /* Read the PEM private key from the BIO and convert to DER. */ + if ((!err) && (pem_read_bio_key(bio, cb, arg, PRIVATEKEY_TYPE, &keyFormat, + &der) < 0)) { + err = 1; + } + + if (!err) { + const unsigned char* ptr = der->buffer; + int type = -1; + + /* Set key type based on format returned. */ + switch (keyFormat) { + /* No key format set - default to RSA. */ + case 0: + case RSAk: + type = EVP_PKEY_RSA; + break; + case DSAk: + type = EVP_PKEY_DSA; + break; + case ECDSAk: + type = EVP_PKEY_EC; + break; + case DHk: + type = EVP_PKEY_DH; + break; + default: + break; + } + + /* Use key passed in if set. */ + if ((key != NULL) && (*key != NULL)) { + pkey = *key; + } + + /* Convert DER data to a private key object. */ + if (wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length) == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + pkey = NULL; + err = 1; + } + } + + /* Return the key if possible. */ + if ((!err) && (key != NULL) && (pkey != NULL)) { + *key = pkey; + } + /* Dispose of the DER encoding. */ + FreeDer(&der); + + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", err); + + return pkey; +} +#endif /* !NO_BIO */ + +#if !defined(NO_FILESYSTEM) +/* Create a private key object from the data in a file. + * + * @param [in] fp File pointer. + * @param [in, out] key Public key object. Object used if passed in. + * @param [in] cb Password callback. + * @param [in] arg Password callback argument. + * @return A WOLFSSL_EVP_PKEY object on success. + * @return NULL on failure. + */ +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY **key, + wc_pem_password_cb *cb, void *arg) +{ + int err = 0; + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_read_PUBKEY"); + + /* Validate parameters. */ + if (fp == XBADFILE) { + err = 1; + } + + /* Read the PEM public key from the file and convert to DER. */ + if ((!err) && ((pem_read_file_key(fp, cb, arg, PUBLICKEY_TYPE, NULL, + &der) < 0) || (der == NULL))) { + err = 1; + } + if (!err) { + const unsigned char* ptr = der->buffer; + + /* Use key passed in if set. */ + if ((key != NULL) && (*key != NULL)) { + pkey = *key; + } + + /* Convert DER data to a public key object. */ + if (wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length) == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + pkey = NULL; + err = 1; + } + } + + /* Return the key if possible. */ + if ((!err) && (key != NULL) && (pkey != NULL)) { + *key = pkey; + } + /* Dispose of the DER encoding. */ + FreeDer(&der); + + WOLFSSL_LEAVE("wolfSSL_PEM_read_PUBKEY", 0); + + return pkey; +} + +#ifndef NO_CERTS +/* Create a private key object from the data in a file. + * + * @param [in] fp File pointer. + * @param [in, out] key Private key object. Object used if passed in. + * @param [in] cb Password callback. + * @param [in] arg Password callback argument. + * @return A WOLFSSL_EVP_PKEY object on success. + * @return NULL on failure. + */ +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **key, + wc_pem_password_cb *cb, void *arg) +{ + int err = 0; + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_PrivateKey"); + + /* Validate parameters. */ + if (fp == XBADFILE) { + err = 1; + } + + /* Read the PEM private key from the file and convert to DER. */ + if ((!err) && (pem_read_file_key(fp, cb, arg, PRIVATEKEY_TYPE, &keyFormat, + &der)) < 0) { + err = 1; + } + + if (!err) { + const unsigned char* ptr = der->buffer; + int type = -1; + + /* Set key type based on format returned. */ + switch (keyFormat) { + /* No key format set - default to RSA. */ + case 0: + case RSAk: + type = EVP_PKEY_RSA; + break; + case DSAk: + type = EVP_PKEY_DSA; + break; + case ECDSAk: + type = EVP_PKEY_EC; + break; + case DHk: + type = EVP_PKEY_DH; + break; + default: + break; + } + + /* Use key passed in if set. */ + if ((key != NULL) && (*key != NULL)) { + pkey = *key; + } + + /* Convert DER data to a private key object. */ + if (wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length) == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + pkey = NULL; + err = 1; + } + } + + /* Return the key if possible. */ + if ((!err) && (key != NULL) && (pkey != NULL)) { + *key = pkey; + } + /* Dispose of the DER encoding. */ + FreeDer(&der); + + WOLFSSL_LEAVE("wolfSSL_PEM_read_PrivateKey", 0); + + return pkey; +} +#endif /* !NO_CERTS */ +#endif /* !NO_FILESYSTEM */ + +#ifndef NO_CERTS + +#if !defined(NO_BIO) || !defined(NO_FILESYSTEM) +#define PEM_BEGIN "-----BEGIN " +#define PEM_BEGIN_SZ 11 +#define PEM_END "-----END " +#define PEM_END_SZ 9 +#define PEM_HDR_FIN "-----" +#define PEM_HDR_FIN_SZ 5 +#define PEM_HDR_FIN_EOL_NEWLINE "-----\n" +#define PEM_HDR_FIN_EOL_NULL_TERM "-----\0" +#define PEM_HDR_FIN_EOL_SZ 6 + +/* Find strings and return middle offsets. + * + * Find first string in pem as a prefix and then locate second string as a + * postfix. + * len returning with 0 indicates not found. + * + * @param [in] pem PEM data. + * @param [in] pemLen Length of PEM data. + * @param [in] idx Current index. + * @param [in] prefix First string to find. + * @param [in] postfix Second string to find after first. + * @param [out] start Start index of data between strings. + * @param [out] len Length of data between strings. + */ +static void pem_find_pattern(char* pem, int pemLen, int idx, const char* prefix, + const char* postfix, int* start, int* len) +{ + int prefixLen = (int)XSTRLEN(prefix); + int postfixLen = (int)XSTRLEN(postfix); + + *start = *len = 0; + /* Find prefix part. */ + for (; idx < pemLen - prefixLen; idx++) { + if ((pem[idx] == prefix[0]) && + (XMEMCMP(pem + idx, prefix, prefixLen) == 0)) { + idx += prefixLen; + *start = idx; + break; + } + } + /* Find postfix part. */ + for (; idx < pemLen - postfixLen; idx++) { + if ((pem[idx] == postfix[0]) && + (XMEMCMP(pem + idx, postfix, postfixLen) == 0)) { + *len = idx - *start; + break; + } + } +} + +/* Parse out content type name, any encryption headers and DER encoding. + * + * @param [in] pem PEM data. + * @param [in] pemLen Length of PEM data. + * @param [out] name Name of content type. + * @param [out] header Encryption headers. + * @param [out] data DER encoding from PEM. + * @param [out] len Length of DER data. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return ASN_NO_PEM_HEADER when no header found or different names found. + */ +static int pem_read_data(char* pem, int pemLen, char **name, char **header, + unsigned char **data, long *len) +{ + int ret = 0; + int start; + int nameLen; + int startHdr = 0; + int hdrLen = 0; + int startEnd = 0; + int endLen; + + *name = NULL; + *header = NULL; + + /* Find header. */ + pem_find_pattern(pem, pemLen, 0, PEM_BEGIN, PEM_HDR_FIN, &start, &nameLen); + /* Allocate memory for header name. */ + *name = (char*)XMALLOC(nameLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (*name == NULL) { + ret = MEMORY_E; + } + if (ret == 0) { + /* Put in header name. */ + (*name)[nameLen] = '\0'; + if (nameLen == 0) { + ret = ASN_NO_PEM_HEADER; + } + else { + XMEMCPY(*name, pem + start, nameLen); + } + } + if (ret == 0) { + /* Find encryption headers after header. */ + start += nameLen + PEM_HDR_FIN_SZ; + pem_find_pattern(pem, pemLen, start, "\n", "\n\n", &startHdr, &hdrLen); + if (hdrLen > 0) { + /* Include first of two '\n' characters. */ + hdrLen++; + } + /* Allocate memory for encryption header string. */ + *header = (char*)XMALLOC(hdrLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (*header == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + /* Put in encryption header string. */ + (*header)[hdrLen] = '\0'; + if (hdrLen > 0) { + XMEMCPY(*header, pem + startHdr, hdrLen); + start = startHdr + hdrLen + 1; + } + + /* Find footer. */ + pem_find_pattern(pem, pemLen, start, PEM_END, PEM_HDR_FIN, &startEnd, + &endLen); + /* Validate header name and footer name are the same. */ + if ((endLen != nameLen) || + (XMEMCMP(*name, pem + startEnd, nameLen) != 0)) { + ret = ASN_NO_PEM_HEADER; + } + } + if (ret == 0) { + unsigned char* der = (unsigned char*)pem; + word32 derLen; + + /* Convert PEM body to DER. */ + derLen = (word32)(startEnd - PEM_END_SZ - start); + ret = Base64_Decode(der + start, derLen, der, &derLen); + if (ret == 0) { + /* Return the DER data. */ + *data = der; + *len = derLen; + } + } + + return ret; +} + +/* Encode the DER data in PEM format into a newly allocated buffer. + * + * @param [in] name Header/footer name. + * @param [in] header Encryption header. + * @param [in] data DER data. + * @param [in] len Length of DER data. + * @param [out] pemOut PEM encoded data. + * @param [out] pemOutLen Length of PEM encoded data. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int pem_write_data(const char *name, const char *header, + const unsigned char *data, long len, char** pemOut, word32* pemOutLen) +{ + int ret = 0; + int nameLen; + int headerLen; + char* pem = NULL; + word32 pemLen; + word32 derLen = (word32)len; + byte* p; + + nameLen = (int)XSTRLEN(name); + headerLen = (int)XSTRLEN(header); + + /* DER encode for PEM. */ + pemLen = (derLen + 2) / 3 * 4; + pemLen += (pemLen + 63) / 64; + /* Header */ + pemLen += PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ; + if (headerLen > 0) { + /* Encryption lines plus extra carriage return. */ + pemLen += headerLen + 1; + } + /* Trailer */ + pemLen += PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ; + + pem = (char*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ret = MEMORY_E; + } + p = (byte*)pem; + + if (ret == 0) { + /* Add header. */ + XMEMCPY(p, PEM_BEGIN, PEM_BEGIN_SZ); + p += PEM_BEGIN_SZ; + XMEMCPY(p, name, nameLen); + p += nameLen; + XMEMCPY(p, PEM_HDR_FIN_EOL_NEWLINE, PEM_HDR_FIN_EOL_SZ); + p += PEM_HDR_FIN_EOL_SZ; + + if (headerLen > 0) { + /* Add encryption header. */ + XMEMCPY(p, header, headerLen); + p += headerLen; + /* Blank line after a header and before body. */ + *(p++) = '\n'; + } + + /* Add DER data as PEM. */ + pemLen -= (word32)((size_t)p - (size_t)pem); + ret = Base64_Encode(data, derLen, p, &pemLen); + } + if (ret == 0) { + p += pemLen; + + /* Add trailer. */ + XMEMCPY(p, PEM_END, PEM_END_SZ); + p += PEM_END_SZ; + XMEMCPY(p, name, nameLen); + p += nameLen; + XMEMCPY(p, PEM_HDR_FIN_EOL_NEWLINE, PEM_HDR_FIN_EOL_SZ); + p += PEM_HDR_FIN_EOL_SZ; + + /* Return buffer and length of data. */ + *pemOut = pem; + *pemOutLen = (word32)((size_t)p - (size_t)pem); + } + + return ret; +} +#endif /* !NO_BIO || !NO_FILESYSTEM */ + +#ifndef NO_BIO +/* Read PEM encoded data from a BIO. + * + * Reads the entire contents in. + * + * @param [in] bio BIO to read from. + * @param [out] name Name of content type. + * @param [out] header Encryption headers. + * @param [out] data DER encoding from PEM. + * @param [out] len Length of DER data. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header, + unsigned char **data, long *len) +{ + int res = 1; + char* pem = NULL; + int pemLen = 0; + int memAlloced = 1; + + /* Validate parameters. */ + if ((bio == NULL) || (name == NULL) || (header == NULL) || (data == NULL) || + (len == NULL)) { + res = 0; + } + + /* Load all the data from the BIO. */ + if ((res == 1) && (wolfssl_read_bio(bio, &pem, &pemLen, &memAlloced) != + 0)) { + res = 0; + } + if ((res == 1) && (!memAlloced)) { + /* Need to return allocated memory - make sure it is allocated. */ + char* p = (char*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) { + res = 0; + } + else { + /* Copy the data into new buffer. */ + XMEMCPY(p, pem, pemLen); + pem = p; + } + } + + /* Read the PEM data. */ + if ((res == 1) && (pem_read_data(pem, pemLen, name, header, data, len) != + 0)) { + /* Dispose of any allocated memory. */ + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(*name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(*header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *name = NULL; + *header = NULL; + res = 0; + } + + return res; +} + +/* Encode the DER data in PEM format into a BIO. + * + * @param [in] bio BIO to write to. + * @param [in] name Header/footer name. + * @param [in] header Encryption header. + * @param [in] data DER data. + * @param [in] len Length of DER data. + * @return 0 on failure. + */ +int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name, + const char *header, const unsigned char *data, long len) +{ + int err = 0; + char* pem = NULL; + word32 pemLen = 0; + + /* Validate parameters. */ + if ((bio == NULL) || (name == NULL) || (header == NULL) || (data == NULL)) { + err = BAD_FUNC_ARG; + } + + /* Encode into a buffer. */ + if (!err) { + err = pem_write_data(name, header, data, len, &pem, &pemLen); + } + + /* Write PEM into BIO. */ + if ((!err) && (wolfSSL_BIO_write(bio, pem, (int)pemLen) != (int)pemLen)) { + err = IO_FAILED_E; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return (!err) ? pemLen : 0; +} +#endif /* !NO_BIO */ + +#if !defined(NO_FILESYSTEM) +/* Read PEM encoded data from a file. + * + * Reads the entire contents in. + * + * @param [in] bio BIO to read from. + * @param [out] name Name of content type. + * @param [out] header Encryption headers. + * @param [out] data DER encoding from PEM. + * @param [out] len Length of DER data. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_read(XFILE fp, char **name, char **header, unsigned char **data, + long *len) +{ + int res = 1; + char* pem = NULL; + int pemLen = 0; + + /* Validate parameters. */ + if ((fp == XBADFILE) || (name == NULL) || (header == NULL) || + (data == NULL) || (len == NULL)) { + res = 0; + } + + /* Load all the data from the file. */ + if ((res == 1) && (wolfssl_read_file(fp, &pem, &pemLen) != 0)) { + res = 0; + } + + /* Read the PEM data. */ + if ((res == 1) && (pem_read_data(pem, pemLen, name, header, data, len) != + 0)) { + /* Dispose of any allocated memory. */ + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(*name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(*header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *name = NULL; + *header = NULL; + res = 0; + } + + return res; +} + +/* Encode the DER data in PEM format into a file. + * + * @param [in] fp File pointer to write to. + * @param [in] name Header/footer name. + * @param [in] header Encryption header. + * @param [in] data DER data. + * @param [in] len Length of DER data. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header, + const unsigned char *data, long len) +{ + int err = 0; + char* pem = NULL; + word32 pemLen = 0; + + /* Validate parameters. */ + if ((fp == XBADFILE) || (name == NULL) || (header == NULL) || + (data == NULL)) { + err = 1; + } + + /* Encode into a buffer. */ + if ((!err) && (pem_write_data(name, header, data, len, &pem, &pemLen) != + 0)) { + pemLen = 0; + err = 1; + } + + /* Write PEM to a file. */ + if ((!err) && (XFWRITE(pem, 1, pemLen, fp) != pemLen)) { + pemLen = 0; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return (int)pemLen; +} +#endif + +/* Get EVP cipher info from encryption header string. + * + * @param [in] header Encryption header. + * @param [out] cipher EVP Cipher info. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_get_EVP_CIPHER_INFO(const char* header, EncryptedInfo* cipher) +{ + int res = 1; + + /* Validate parameters. */ + if ((header == NULL) || (cipher == NULL)) { + res = 0; + } + + if (res == 1) { + XMEMSET(cipher, 0, sizeof(*cipher)); + + if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0) { + res = 0; + } + } + + return res; +} + +/* Apply cipher to DER data. + * + * @param [in] cipher EVP cipher info. + * @param [in, out] data On in, encrypted DER data. + * On out, unencrypted DER data. + * @param [in, out] len On in, length of encrypted DER data. + * On out, length of unencrypted DER data. + * @param [in] cb Password callback. + * @param [in] ctx Context for password callback. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data, long* len, + wc_pem_password_cb* cb, void* ctx) +{ + int ret = 1; + char password[NAME_SZ]; + int passwordSz = 0; + + /* Validate parameters. */ + if ((cipher == NULL) || (data == NULL) || (len == NULL) || (cb == NULL)) { + ret = 0; + } + + if (ret == 1) { + /* Get password and length. */ + passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); + if (passwordSz < 0) { + ret = 0; + } + } + + if (ret == 1) { + /* Decrypt the data using password and MD5. */ + if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password, + passwordSz, WC_MD5) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + if (passwordSz > 0) { + /* Ensure password is erased from memory. */ + ForceZero(password, (word32)passwordSz); + } + + return ret; +} + +#endif /* !NO_CERTS */ +#endif /* OPENSSL_EXTRA */ + +#ifdef OPENSSL_ALL +#if !defined(NO_PWDBASED) && defined(HAVE_PKCS8) + +#if !defined(NO_BIO) || (!defined(NO_FILESYSTEM) && \ + !defined(NO_STDIO_FILESYSTEM)) +/* Encrypt the key into a buffer using PKCS$8 and a password. + * + * @param [in] pkey Private key to encrypt. + * @param [in] enc EVP cipher. + * @param [in] passwd Password to encrypt with. + * @param [in] passwdSz Number of bytes in password. + * @param [in] key Buffer to hold encrypted key. + * @param [in, out] keySz On in, size of buffer in bytes. + * On out, size of encrypted key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when EVP cipher not supported. + */ +static int pem_pkcs8_encrypt(WOLFSSL_EVP_PKEY* pkey, + const WOLFSSL_EVP_CIPHER* enc, char* passwd, int passwdSz, byte* key, + word32* keySz) +{ + int ret; + WC_RNG rng; + + /* Initialize a new random number generator. */ + ret = wc_InitRng(&rng); + if (ret == 0) { + int encAlgId = 0; + + /* Convert EVP cipher to a support encryption id. */ + #ifndef NO_DES3 + if (enc == EVP_DES_CBC) { + encAlgId = DESb; + } + else if (enc == EVP_DES_EDE3_CBC) { + encAlgId = DES3b; + } + else + #endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + if (enc == EVP_AES_128_CBC) { + encAlgId = AES128CBCb; + } + else + #endif + #ifdef WOLFSSL_AES_256 + if (enc == EVP_AES_256_CBC) { + encAlgId = AES256CBCb; + } + else + #endif +#endif + { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Encrypt private into buffer. */ + ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, + key, keySz, passwd, passwdSz, PKCS5, PBES2, encAlgId, + NULL, 0, WC_PKCS12_ITT_DEFAULT, &rng, NULL); + if (ret > 0) { + *keySz = (word32)ret; + } + } + /* Dispose of random number generator. */ + wc_FreeRng(&rng); + } + + return ret; +} + +/* Encode private key in PKCS#8 format. + * + * @param [in] pkey Private key. + * @param [out] key Buffer to hold encoding. + * @param [in, out] keySz On in, size of buffer in bytes. + * @param On out, size of encoded key in bytes. + * @return 0 on success. + */ +static int pem_pkcs8_encode(WOLFSSL_EVP_PKEY* pkey, byte* key, word32* keySz) +{ + int ret = 0; + int algId; + const byte* curveOid; + word32 oidSz; + + /* Get the details of the private key. */ +#ifdef HAVE_ECC + if (pkey->type == EVP_PKEY_EC) { + /* ECC private and get curve OID information. */ + algId = ECDSAk; + ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid, + &oidSz); + } + else +#endif + if (pkey->type == EVP_PKEY_RSA) { + /* RSA private has no curve information. */ + algId = RSAk; + curveOid = NULL; + oidSz = 0; + } + else { + ret = NOT_COMPILED_IN; + } + + if (ret >= 0) { + /* Encode private key in PKCS#8 format. */ + ret = wc_CreatePKCS8Key(key, keySz, (byte*)pkey->pkey.ptr, + pkey->pkey_sz, algId, curveOid, oidSz); + } + + return ret; +} + +/* Write PEM encoded, PKCS#8 formatted private key to BIO. + * + * @param [out] pem Buffer holding PEM encoding. + * @param [out] pemSz Size of data in buffer in bytes. + * @param [in] pkey Private key to write. + * @param [in] enc Encryption information to use. May be NULL. + * @param [in] passwd Password to use when encrypting. May be NULL. + * @param [in] passwdSz Size of password in bytes. + * @param [in] cb Password callback. Used when passwd is NULL. May be + * NULL. + * @param [in] ctx Context for password callback. + * @return Length of PEM encoding on success. + * @return 0 on failure. + */ +static int pem_write_mem_pkcs8privatekey(byte** pem, int* pemSz, + WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd, + int passwdSz, wc_pem_password_cb* cb, void* ctx) +{ + int res = 1; + int ret = 0; + char password[NAME_SZ]; + byte* key = NULL; + word32 keySz; + int type = PKCS8_PRIVATEKEY_TYPE; + + /* Validate parameters. */ + if (pkey == NULL) { + res = 0; + } + + if (res == 1) { + /* Guestimate key size and PEM size. */ + if (pem_pkcs8_encode(pkey, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { + res = 0; + } + } + if (res == 1) { + if (enc != NULL) { + /* Add on enough for extra DER data when encrypting. */ + keySz += 128; + } + /* PEM encoding size from DER size. */ + *pemSz = (int)(keySz + 2) / 3 * 4; + *pemSz += (*pemSz + 63) / 64; + /* Header and footer. */ + if (enc != NULL) { + /* Name is: 'ENCRYPTED PRIVATE KEY'. */ + *pemSz += 74; + } + else { + /* Name is: 'PRIVATE KEY'. */ + *pemSz += 54; + } + + /* Allocate enough memory to hold PEM encoded encrypted key. */ + *pem = (byte*)XMALLOC((size_t)*pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (*pem == NULL) { + res = 0; + } + else { + /* Use end of PEM buffer for key data. */ + key = *pem + *pemSz - keySz; + } + } + + if ((res == 1) && (enc != NULL)) { + /* Set type for PEM. */ + type = PKCS8_ENC_PRIVATEKEY_TYPE; + + if (passwd == NULL) { + /* Get the password by using callback. */ + passwdSz = cb(password, sizeof(password), 1, ctx); + if (passwdSz < 0) { + res = 0; + } + passwd = password; + } + + if (res == 1) { + /* Encrypt the private key. */ + ret = pem_pkcs8_encrypt(pkey, enc, passwd, passwdSz, key, &keySz); + if (ret <= 0) { + res = 0; + } + } + + /* Zeroize the password from memory. */ + if ((password == passwd) && (passwdSz > 0)) { + ForceZero(password, (word32)passwdSz); + } + } + else if ((res == 1) && (enc == NULL)) { + /* Set type for PEM. */ + type = PKCS8_PRIVATEKEY_TYPE; + + /* Encode private key in PKCS#8 format. */ + ret = pem_pkcs8_encode(pkey, key, &keySz); + if (ret < 0) { + res = 0; + } + } + + if (res == 1) { + /* Encode PKCS#8 formatted key to PEM. */ + ret = wc_DerToPemEx(key, keySz, *pem, (word32)*pemSz, NULL, type); + if (ret < 0) { + res = 0; + } + else { + *pemSz = ret; + } + } + + /* Return appropriate return code. */ + return (res == 0) ? 0 : ret; + +} +#endif /* !NO_BIO || (!NO_FILESYSTEM && !NO_STDIO_FILESYSTEM) */ + +#ifndef NO_BIO +/* Write PEM encoded, PKCS#8 formatted private key to BIO. + * + * TODO: OpenSSL returns 1 and 0 only. + * + * @param [in] bio BIO to write to. + * @param [in] pkey Private key to write. + * @param [in] enc Encryption information to use. May be NULL. + * @param [in] passwd Password to use when encrypting. May be NULL. + * @param [in] passwdSz Size of password in bytes. + * @param [in] cb Password callback. Used when passwd is NULL. May be + * NULL. + * @param [in] ctx Context for password callback. + * @return Length of PEM encoding on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd, + int passwdSz, wc_pem_password_cb* cb, void* ctx) +{ + byte* pem = NULL; + int pemSz = 0; + int res = 1; + + /* Validate parameters. */ + if (bio == NULL) { + res = 0; + } + if (res == 1) { + /* Write private key to memory. */ + res = pem_write_mem_pkcs8privatekey(&pem, &pemSz, pkey, enc, passwd, + passwdSz, cb, ctx); + } + + /* Write encoded key to BIO. */ + if ((res >= 1) && (wolfSSL_BIO_write(bio, pem, pemSz) != pemSz)) { + res = 0; + } + + /* Dispose of dynamically allocated memory (pem and key). */ + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return res; +} +#endif /* !NO_BIO */ + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* Write PEM encoded, PKCS#8 formatted private key to BIO. + * + * TODO: OpenSSL returns 1 and 0 only. + * + * @param [in] f File pointer. + * @param [in] pkey Private key to write. + * @param [in] enc Encryption information to use. May be NULL. + * @param [in] passwd Password to use when encrypting. May be NULL. + * @param [in] passwdSz Size of password in bytes. + * @param [in] cb Password callback. Used when passwd is NULL. May be + * NULL. + * @param [in] ctx Context for password callback. + * @return Length of PEM encoding on success. + * @return 0 on failure. + */ +int wolfSSL_PEM_write_PKCS8PrivateKey(XFILE f, WOLFSSL_EVP_PKEY* pkey, + const WOLFSSL_EVP_CIPHER* enc, char* passwd, int passwdSz, + wc_pem_password_cb* cb, void* ctx) +{ + byte* pem = NULL; + int pemSz = 0; + int res = 1; + + /* Validate parameters. */ + if (f == XBADFILE) { + res = 0; + } + if (res == 1) { + /* Write private key to memory. */ + res = pem_write_mem_pkcs8privatekey(&pem, &pemSz, pkey, enc, passwd, + passwdSz, cb, ctx); + } + + /* Write encoded key to file. */ + if ((res >= 1) && (XFWRITE(pem, 1, (size_t)pemSz, f) != (size_t)pemSz)) { + res = 0; + } + + /* Dispose of dynamically allocated memory (pem and key). */ + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return res; +} +#endif /* !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */ + +#endif /* !NO_PWDBASED && HAVE_PKCS8 */ +#endif /* OPENSSL_ALL */ + +/******************************************************************************* + * END OF GENERIC PUBLIC KEY PEM APIs ******************************************************************************/ #endif /* !WOLFSSL_PK_INCLUDED */ diff --git a/src/src/quic.c b/src/src/quic.c index 66f866a..117bb43 100644 --- a/src/src/quic.c +++ b/src/src/quic.c @@ -82,7 +82,7 @@ static QuicRecord *quic_record_make(WOLFSSL *ssl, qr->capacity = qr->len = (word32)len; } else { - qr->capacity = qr->len = qr_length(data, len); + qr->capacity = qr->len = (word32) qr_length(data, len); if (qr->capacity > WOLFSSL_QUIC_MAX_RECORD_CAPACITY) { WOLFSSL_MSG("QUIC length read larger than expected"); quic_record_free(ssl, qr); @@ -123,17 +123,17 @@ static int quic_record_append(WOLFSSL *ssl, QuicRecord *qr, const uint8_t *data, missing = 4 - qr->end; if (len < missing) { XMEMCPY(qr->data + qr->end, data, len); - qr->end += len; + qr->end += (word32)len; consumed = len; goto cleanup; /* len consumed, but qr->len still unknown */ } XMEMCPY(qr->data + qr->end, data, missing); - qr->end += missing; + qr->end += (word32)missing; len -= missing; data += missing; consumed = missing; - qr->len = qr_length(qr->data, qr->end); + qr->len = (word32)qr_length(qr->data, qr->end); /* sanity check on length read from wire before use */ if (qr->len > WOLFSSL_QUIC_MAX_RECORD_CAPACITY) { @@ -163,7 +163,7 @@ static int quic_record_append(WOLFSSL *ssl, QuicRecord *qr, const uint8_t *data, len = missing; } XMEMCPY(qr->data + qr->end, data, len); - qr->end += len; + qr->end += (word32)len; consumed += len; cleanup: @@ -172,7 +172,7 @@ static int quic_record_append(WOLFSSL *ssl, QuicRecord *qr, const uint8_t *data, } -static word32 add_rec_header(byte* output, word32 length, int type) +static word32 add_rec_header(byte* output, word32 length, byte type) { RecordLayerHeader* rl; @@ -188,15 +188,21 @@ static word32 add_rec_header(byte* output, word32 length, int type) return RECORD_HEADER_SZ; } -static word32 quic_record_transfer(QuicRecord* qr, byte* buf, word32 sz) +static sword32 quic_record_transfer(QuicRecord* qr, byte* buf, word32 sz) { word32 len = qr->end - qr->start; word32 offset = 0; - word16 rlen; + word32 rlen; if (len <= 0) { return 0; } + + /* We check if the buf is at least RECORD_HEADER_SZ */ + if (sz < RECORD_HEADER_SZ) { + return -1; + } + if (qr->rec_hdr_remain == 0) { /* start a new TLS record */ rlen = (qr->len <= (word32)MAX_RECORD_SIZE) ? @@ -218,7 +224,7 @@ static word32 quic_record_transfer(QuicRecord* qr, byte* buf, word32 sz) qr->start += len; qr->rec_hdr_remain -= len; } - return len + offset; + return (sword32)(len + offset); } @@ -236,7 +242,7 @@ const QuicTransportParam* QuicTransportParam_new(const uint8_t* data, return NULL; } XMEMCPY((uint8_t*)tp->data, data, len); - tp->len = len; + tp->len = (word16)len; return tp; } @@ -766,7 +772,7 @@ int wolfSSL_provide_quic_data(WOLFSSL* ssl, WOLFSSL_ENCRYPTION_LEVEL level, /* Called internally when SSL wants a certain amount of input. */ int wolfSSL_quic_receive(WOLFSSL* ssl, byte* buf, word32 sz) { - word32 n = 0; + sword32 n = 0; int transferred = 0; WOLFSSL_ENTER("wolfSSL_quic_receive"); @@ -774,6 +780,11 @@ int wolfSSL_quic_receive(WOLFSSL* ssl, byte* buf, word32 sz) n = 0; if (ssl->quic.input_head) { n = quic_record_transfer(ssl->quic.input_head, buf, sz); + + /* record too small to be fit into a RecordLayerHeader struct. */ + if (n == -1) { + return -1; + } if (quic_record_done(ssl->quic.input_head)) { QuicRecord* qr = ssl->quic.input_head; ssl->quic.input_head = qr->next; @@ -791,9 +802,9 @@ int wolfSSL_quic_receive(WOLFSSL* ssl, byte* buf, word32 sz) ssl->error = transferred = WANT_READ; goto cleanup; } - sz -= n; + sz -= (word32)n; buf += n; - transferred += n; + transferred += (int)n; } cleanup: WOLFSSL_LEAVE("wolfSSL_quic_receive", transferred); @@ -836,8 +847,8 @@ static int wolfSSL_quic_send_internal(WOLFSSL* ssl) goto cleanup; } output += len; - length -= len; - ssl->quic.output_rec_remain -= len; + length -= (word32)len; + ssl->quic.output_rec_remain -= (word32)len; } else { /* at start of a TLS Record */ @@ -990,11 +1001,13 @@ const WOLFSSL_EVP_CIPHER* wolfSSL_quic_get_aead(WOLFSSL* ssl) evp_cipher = wolfSSL_EVP_chacha20_poly1305(); break; #endif -#if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_128) +#if !defined(NO_AES) && defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) case TLS_AES_128_CCM_SHA256: - FALL_THROUGH; + evp_cipher = wolfSSL_EVP_aes_128_ccm(); + break; case TLS_AES_128_CCM_8_SHA256: - evp_cipher = wolfSSL_EVP_aes_128_ctr(); + WOLFSSL_MSG("wolfSSL_quic_get_aead: no CCM-8 support in EVP layer"); + evp_cipher = NULL; break; #endif @@ -1011,7 +1024,8 @@ const WOLFSSL_EVP_CIPHER* wolfSSL_quic_get_aead(WOLFSSL* ssl) return evp_cipher; } -static int evp_cipher_eq(const WOLFSSL_EVP_CIPHER* c1, +/* currently only used if HAVE_CHACHA && HAVE_POLY1305. */ +WC_MAYBE_UNUSED static int evp_cipher_eq(const WOLFSSL_EVP_CIPHER* c1, const WOLFSSL_EVP_CIPHER* c2) { /* We could check on nid equality, but we seem to have singulars */ @@ -1034,27 +1048,40 @@ const WOLFSSL_EVP_CIPHER* wolfSSL_quic_get_hp(WOLFSSL* ssl) } switch (cipher->cipherSuite) { -#if !defined(NO_AES) && defined(HAVE_AESGCM) +#if !defined(NO_AES) && defined(HAVE_AESGCM) && defined(WOLFSSL_AES_COUNTER) + /* This has to be CTR even though the spec says that ECB is used for + * mask generation. ngtcp2_crypto_hp_mask uses a hack where they pass + * in the "ECB" input as the IV for the CTR cipher and then the input + * is just a cleared buffer. They do this so that the EVP + * init-update-final cycle can be used without the padding that is added + * for EVP_aes_(128|256)_ecb. */ +#if defined(WOLFSSL_AES_128) case TLS_AES_128_GCM_SHA256: evp_cipher = wolfSSL_EVP_aes_128_ctr(); break; +#endif +#if defined(WOLFSSL_AES_256) case TLS_AES_256_GCM_SHA384: evp_cipher = wolfSSL_EVP_aes_256_ctr(); break; #endif +#endif #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) case TLS_CHACHA20_POLY1305_SHA256: evp_cipher = wolfSSL_EVP_chacha20(); break; #endif -#if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_128) +#if !defined(NO_AES) && defined(HAVE_AESCCM) && defined(WOLFSSL_AES_128) && \ + defined(WOLFSSL_AES_COUNTER) + /* This has to be CTR. See comment above. */ case TLS_AES_128_CCM_SHA256: - FALL_THROUGH; - case TLS_AES_128_CCM_8_SHA256: evp_cipher = wolfSSL_EVP_aes_128_ctr(); break; + case TLS_AES_128_CCM_8_SHA256: + WOLFSSL_MSG("wolfSSL_quic_get_hp: no CCM-8 support in EVP layer"); + evp_cipher = NULL; + break; #endif - default: evp_cipher = NULL; break; @@ -1072,8 +1099,7 @@ size_t wolfSSL_quic_get_aead_tag_len(const WOLFSSL_EVP_CIPHER* aead_cipher) { size_t ret; #ifdef WOLFSSL_SMALL_STACK - WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX *)XMALLOC( - sizeof(*ctx), NULL, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_EVP_CIPHER_CTX *ctx = wolfSSL_EVP_CIPHER_CTX_new(); if (ctx == NULL) return 0; #else @@ -1083,7 +1109,7 @@ size_t wolfSSL_quic_get_aead_tag_len(const WOLFSSL_EVP_CIPHER* aead_cipher) XMEMSET(ctx, 0, sizeof(*ctx)); if (wolfSSL_EVP_CipherInit(ctx, aead_cipher, NULL, NULL, 0) == WOLFSSL_SUCCESS) { - ret = ctx->authTagSz; + ret = (size_t)ctx->authTagSz; } else { ret = 0; } @@ -1098,30 +1124,12 @@ size_t wolfSSL_quic_get_aead_tag_len(const WOLFSSL_EVP_CIPHER* aead_cipher) int wolfSSL_quic_aead_is_gcm(const WOLFSSL_EVP_CIPHER* aead_cipher) { -#if !defined(NO_AES) && defined(HAVE_AESGCM) - if (evp_cipher_eq(aead_cipher, wolfSSL_EVP_aes_128_gcm()) -#ifdef WOLFSSL_AES_256 - || evp_cipher_eq(aead_cipher, wolfSSL_EVP_aes_256_gcm()) -#endif - ) { - return 1; - } -#else - (void)aead_cipher; -#endif - return 0; + return WOLFSSL_EVP_CIPHER_mode(aead_cipher) == WOLFSSL_EVP_CIPH_GCM_MODE; } int wolfSSL_quic_aead_is_ccm(const WOLFSSL_EVP_CIPHER* aead_cipher) { -#if defined(WOLFSSL_AES_COUNTER) && defined(WOLFSSL_AES_128) - if (evp_cipher_eq(aead_cipher, wolfSSL_EVP_aes_128_ctr())) { - return 1; - } -#else - (void)aead_cipher; -#endif - return 0; + return WOLFSSL_EVP_CIPHER_mode(aead_cipher) == WOLFSSL_EVP_CIPH_CCM_MODE; } int wolfSSL_quic_aead_is_chacha20(const WOLFSSL_EVP_CIPHER* aead_cipher) @@ -1358,7 +1366,7 @@ int wolfSSL_quic_aead_decrypt(uint8_t* dest, WOLFSSL_EVP_CIPHER_CTX* ctx, return WOLFSSL_FAILURE; } - enclen -= ctx->authTagSz; + enclen -= (size_t)ctx->authTagSz; tag = enc + enclen; if (wolfSSL_EVP_CipherInit(ctx, NULL, NULL, iv, 0) != WOLFSSL_SUCCESS diff --git a/src/src/sniffer.c b/src/src/sniffer.c index d5fc5c1..94b2a9f 100644 --- a/src/src/sniffer.c +++ b/src/src/sniffer.c @@ -2481,7 +2481,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, args = (SetupKeysArgs*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_sk; @@ -3089,7 +3089,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, #endif /* HAVE_CURVE448 */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Handle async pending response */ ret = wolfSSL_AsyncPush(ssl, asyncDev); break; @@ -3228,7 +3228,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, exit_sk: /* Handle async pending response */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3897,7 +3897,8 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, #endif #ifdef WOLFSSL_ASYNC_CRYPT - if (session->sslServer->error != WC_PENDING_E && session->pendSeq == 0) + if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) && + session->pendSeq == 0) #endif { /* hash server_hello */ @@ -3931,7 +3932,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, session, error, &session->cliKs); if (ret != 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -4578,7 +4579,8 @@ static int DoHandShake(const byte* input, int* sslBytes, #ifdef WOLFSSL_TLS13 if (type != client_hello && type != server_hello #ifdef WOLFSSL_ASYNC_CRYPT - && session->sslServer->error != WC_PENDING_E && session->pendSeq == 0 + && session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) + && session->pendSeq == 0 #endif ) { /* For resumption the hash is before / after client_hello PSK binder */ @@ -4696,7 +4698,7 @@ static int DoHandShake(const byte* input, int* sslBytes, if (ret == 0) { ret = ProcessClientKeyExchange(input, sslBytes, session, error); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif if (ret != 0) { @@ -4763,7 +4765,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev); } #endif @@ -4781,7 +4783,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, #endif ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } #endif @@ -4826,7 +4828,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, ssl->decrypt.additional, AEAD_AUTH_DATA_SZ, NULL, 0)) < 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } #endif @@ -4884,9 +4886,9 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, #ifdef WOLFSSL_ASYNC_CRYPT if (ssl->decrypt.state != CIPHER_STATE_BEGIN) { ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* check for still pending */ - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; ssl->error = 0; /* clear async */ @@ -4942,7 +4944,7 @@ static int DecryptTls(WOLFSSL* ssl, byte* plain, const byte* input, #ifdef WOLFSSL_ASYNC_CRYPT /* If pending, return now */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -4994,7 +4996,7 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, } #ifdef WOLFSSL_ASYNC_CRYPT /* for async the symmetric operations are blocking */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { do { ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); } while (ret == 0); @@ -5254,7 +5256,7 @@ static int DoOldHello(SnifferSession* session, const byte* sslFrame, ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes, (word16)*rhSize); - if (ret < 0 && ret != MATCH_SUITE_ERROR) { + if (ret < 0 && ret != WC_NO_ERR_TRACE(MATCH_SUITE_ERROR)) { SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE); return -1; } @@ -5679,7 +5681,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, if (real + *sslBytes > *expected) { #ifdef WOLFSSL_ASYNC_CRYPT - if (session->sslServer->error != WC_PENDING_E && + if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) && session->pendSeq != tcpInfo->sequence) #endif { @@ -5735,7 +5737,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, * already been ack'd during handshake */ if ( #ifdef WOLFSSL_ASYNC_CRYPT - session->sslServer->error != WC_PENDING_E && + session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E) && session->pendSeq != tcpInfo->sequence && #endif FindPrevAck(session, real)) { @@ -6039,7 +6041,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, #ifdef WOLFSSL_ASYNC_CRYPT /* if this is a pending async packet do not "grow" on partial (we already did) */ if (session->pendSeq == tcpInfo->sequence) { - if (session->sslServer->error == WC_PENDING_E) { + if (session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { return 0; /* don't check pre-record again */ } /* if record check already done then restore, otherwise process normal */ @@ -6371,7 +6373,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, Trace(GOT_HANDSHAKE_STR); ret = DoHandShake(sslFrame, &sslBytes, session, error, rhSize); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif if (ret != 0 || sslBytes > startIdx) { @@ -6655,7 +6657,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return WOLFSSL_SNIFFER_FATAL_ERROR; #ifdef WOLFSSL_ASYNC_CRYPT - else if (ret == WC_PENDING_E) return WC_PENDING_E; + else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return WC_PENDING_E; #endif else if (ret == -1) return WOLFSSL_SNIFFER_ERROR; else if (ret == 1) { @@ -6706,7 +6708,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, #ifdef WOLFSSL_ASYNC_CRYPT /* make sure this server was polled */ - if (asyncOkay && session->sslServer->error == WC_PENDING_E && + if (asyncOkay && + session->sslServer->error == WC_NO_ERR_TRACE(WC_PENDING_E) && !session->flags.wasPolled) { return WC_PENDING_E; } @@ -6714,7 +6717,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, #ifdef WOLFSSL_SNIFFER_STATS #ifdef WOLFSSL_ASYNC_CRYPT - if (session->sslServer->error != WC_PENDING_E) + if (session->sslServer->error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { if (sslBytes > 0) { @@ -6736,7 +6739,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, session->sslServer->error = ret; #ifdef WOLFSSL_ASYNC_CRYPT /* capture the seq pending for this session */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { session->flags.wasPolled = 0; session->pendSeq = tcpInfo.sequence; if (!asyncOkay || CryptoDeviceId == INVALID_DEVID) { @@ -6751,7 +6754,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, else { session->pendSeq = 0; } - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #else (void)asyncOkay; #endif diff --git a/src/src/ssl.c b/src/src/ssl.c index ea66e42..9ba891d 100644 --- a/src/src/ssl.c +++ b/src/src/ssl.c @@ -54,7 +54,8 @@ #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \ && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \ && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) - #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README" + #error "No cipher suites defined because DH disabled, ECC disabled, " + "and no static suites defined. Please see top of README" #endif #ifdef WOLFSSL_CERT_GEN /* need access to Cert struct for creating certificate */ @@ -115,14 +116,15 @@ #include #include #include - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) #include #endif /* HAVE_FALCON */ #if defined(HAVE_DILITHIUM) #include #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ + #if defined(HAVE_SPHINCS) + #include + #endif /* HAVE_SPHINCS */ #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) #ifdef HAVE_OCSP #include @@ -137,12 +139,6 @@ && !defined(WC_NO_RNG) #include #endif - #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) - #include - #endif - #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) - #include - #endif /* OPENSSL_ALL && HAVE_PKCS7 */ #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -160,25 +156,6 @@ #endif #endif /* !WOLFCRYPT_ONLY || OPENSSL_EXTRA */ -#ifdef WOLFSSL_SYS_CA_CERTS - -#ifdef _WIN32 - #include - #include - - /* mingw gcc does not support pragma comment, and the - * linking with crypt32 is handled in configure.ac */ - #if !defined(__MINGW32__) && !defined(__MINGW64__) - #pragma comment(lib, "crypt32") - #endif -#endif - -#if defined(__APPLE__) && defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) -#include -#endif - -#endif /* WOLFSSL_SYS_CA_CERTS */ - /* * OPENSSL_COMPATIBLE_DEFAULTS: * Enable default behaviour that is compatible with OpenSSL. For example @@ -215,6 +192,9 @@ #ifndef WOLFCRYPT_ONLY #define WOLFSSL_SSL_CERTMAN_INCLUDED #include "src/ssl_certman.c" + +#define WOLFSSL_SSL_SESS_INCLUDED +#include "src/ssl_sess.c" #endif #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ @@ -307,9 +287,10 @@ int wc_OBJ_sn2nid(const char *sn) #define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */ static WC_RNG globalRNG; -static int initGlobalRNG = 0; +static volatile int initGlobalRNG = 0; -static WC_MAYBE_UNUSED wolfSSL_Mutex globalRNGMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(globalRNGMutex); +static WC_MAYBE_UNUSED wolfSSL_Mutex globalRNGMutex + WOLFSSL_MUTEX_INITIALIZER_CLAUSE(globalRNGMutex); #ifndef WOLFSSL_MUTEX_INITIALIZER static int globalRNGMutex_valid = 0; #endif @@ -408,7 +389,8 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) * OPENSSL_EXTRA where RAND callbacks are not used */ #ifndef WOLFSSL_NO_OPENSSL_RAND_CB static const WOLFSSL_RAND_METHOD* gRandMethods = NULL; - static wolfSSL_Mutex gRandMethodMutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(gRandMethodMutex); + static wolfSSL_Mutex gRandMethodMutex + WOLFSSL_MUTEX_INITIALIZER_CLAUSE(gRandMethodMutex); #ifndef WOLFSSL_MUTEX_INITIALIZER static int gRandMethodsInit = 0; #endif @@ -428,47 +410,6 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) #include -#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) -const WOLF_EC_NIST_NAME kNistCurves[] = { - {XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1}, - {XSTR_SIZEOF("P-256"), "P-256", NID_X9_62_prime256v1}, - {XSTR_SIZEOF("P-112"), "P-112", NID_secp112r1}, - {XSTR_SIZEOF("P-112-2"), "P-112-2", NID_secp112r2}, - {XSTR_SIZEOF("P-128"), "P-128", NID_secp128r1}, - {XSTR_SIZEOF("P-128-2"), "P-128-2", NID_secp128r2}, - {XSTR_SIZEOF("P-160"), "P-160", NID_secp160r1}, - {XSTR_SIZEOF("P-160-2"), "P-160-2", NID_secp160r2}, - {XSTR_SIZEOF("P-224"), "P-224", NID_secp224r1}, - {XSTR_SIZEOF("P-384"), "P-384", NID_secp384r1}, - {XSTR_SIZEOF("P-521"), "P-521", NID_secp521r1}, - {XSTR_SIZEOF("K-160"), "K-160", NID_secp160k1}, - {XSTR_SIZEOF("K-192"), "K-192", NID_secp192k1}, - {XSTR_SIZEOF("K-224"), "K-224", NID_secp224k1}, - {XSTR_SIZEOF("K-256"), "K-256", NID_secp256k1}, - {XSTR_SIZEOF("B-160"), "B-160", NID_brainpoolP160r1}, - {XSTR_SIZEOF("B-192"), "B-192", NID_brainpoolP192r1}, - {XSTR_SIZEOF("B-224"), "B-224", NID_brainpoolP224r1}, - {XSTR_SIZEOF("B-256"), "B-256", NID_brainpoolP256r1}, - {XSTR_SIZEOF("B-320"), "B-320", NID_brainpoolP320r1}, - {XSTR_SIZEOF("B-384"), "B-384", NID_brainpoolP384r1}, - {XSTR_SIZEOF("B-512"), "B-512", NID_brainpoolP512r1}, -#ifdef HAVE_PQC - {XSTR_SIZEOF("KYBER_LEVEL1"), "KYBER_LEVEL1", WOLFSSL_KYBER_LEVEL1}, - {XSTR_SIZEOF("KYBER_LEVEL3"), "KYBER_LEVEL3", WOLFSSL_KYBER_LEVEL3}, - {XSTR_SIZEOF("KYBER_LEVEL5"), "KYBER_LEVEL5", WOLFSSL_KYBER_LEVEL5}, -#ifdef HAVE_LIBOQS - {XSTR_SIZEOF("P256_KYBER_LEVEL1"), "P256_KYBER_LEVEL1", WOLFSSL_P256_KYBER_LEVEL1}, - {XSTR_SIZEOF("P384_KYBER_LEVEL3"), "P384_KYBER_LEVEL3", WOLFSSL_P384_KYBER_LEVEL3}, - {XSTR_SIZEOF("P521_KYBER_LEVEL5"), "P521_KYBER_LEVEL5", WOLFSSL_P521_KYBER_LEVEL5}, -#endif -#endif -#ifdef WOLFSSL_SM2 - {XSTR_SIZEOF("SM2"), "SM2", NID_sm2}, -#endif - {0, NULL, 0}, -}; -#endif - #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) /* create the hpke key and ech config to send to clients */ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName, @@ -1037,7 +978,7 @@ int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen) workingOutputLen = *outputLen - totalLen; /* only error we break on, other 2 we need to keep finding length */ - if (ret == BAD_FUNC_ARG) + if (ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) return BAD_FUNC_ARG; workingConfig = workingConfig->next; @@ -1067,209 +1008,11 @@ int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen) #include #endif -#ifdef WOLFSSL_SESSION_EXPORT -/* Used to import a serialized TLS session. - * WARNING: buf contains sensitive information about the state and is best to be - * encrypted before storing if stored. - * - * @param ssl WOLFSSL structure to import the session into - * @param buf serialized session - * @param sz size of buffer 'buf' - * @return the number of bytes read from buffer 'buf' - */ -int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) -{ - if (ssl == NULL || buf == NULL) { - return BAD_FUNC_ARG; - } - return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS); -} - - -/* Used to export a serialized TLS session. - * WARNING: buf contains sensitive information about the state and is best to be - * encrypted before storing if stored. - * - * @param ssl WOLFSSL structure to export the session from - * @param buf output of serialized session - * @param sz size in bytes set in 'buf' - * @return the number of bytes written into buffer 'buf' - */ -int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) -{ - if (ssl == NULL || sz == NULL) { - return BAD_FUNC_ARG; - } - return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS); -} - -#ifdef WOLFSSL_DTLS -int wolfSSL_dtls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) -{ - WOLFSSL_ENTER("wolfSSL_session_import"); - - if (ssl == NULL || buf == NULL) { - return BAD_FUNC_ARG; - } - - /* sanity checks on buffer and protocol are done in internal function */ - return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS); -} - - -/* Sets the function to call for serializing the session. This function is - * called right after the handshake is completed. */ -int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func) -{ - - WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export"); - - /* purposefully allow func to be NULL */ - if (ctx == NULL) { - return BAD_FUNC_ARG; - } - - ctx->dtls_export = func; - - return WOLFSSL_SUCCESS; -} - - -/* Sets the function in WOLFSSL struct to call for serializing the session. This - * function is called right after the handshake is completed. */ -int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func) -{ - - WOLFSSL_ENTER("wolfSSL_dtls_set_export"); - - /* purposefully allow func to be NULL */ - if (ssl == NULL) { - return BAD_FUNC_ARG; - } - - ssl->dtls_export = func; - - return WOLFSSL_SUCCESS; -} - - -/* This function allows for directly serializing a session rather than using - * callbacks. It has less overhead by removing a temporary buffer and gives - * control over when the session gets serialized. When using callbacks the - * session is always serialized immediately after the handshake is finished. - * - * buf is the argument to contain the serialized session - * sz is the size of the buffer passed in - * ssl is the WOLFSSL struct to serialize - * returns the size of serialized session on success, 0 on no action, and - * negative value on error */ -int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) -{ - WOLFSSL_ENTER("wolfSSL_dtls_export"); - - if (ssl == NULL || sz == NULL) { - return BAD_FUNC_ARG; - } - - if (buf == NULL) { - *sz = MAX_EXPORT_BUFFER; - return 0; - } - - /* if not DTLS do nothing */ - if (!ssl->options.dtls) { - WOLFSSL_MSG("Currently only DTLS export is supported"); - return 0; - } - - /* copy over keys, options, and dtls state struct */ - return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS); -} - - -/* This function is similar to wolfSSL_dtls_export but only exports the portion - * of the WOLFSSL structure related to the state of the connection, i.e. peer - * sequence number, epoch, AEAD state etc. - * - * buf is the argument to contain the serialized state, if null then set "sz" to - * buffer size required - * sz is the size of the buffer passed in - * ssl is the WOLFSSL struct to serialize - * returns the size of serialized session on success, 0 on no action, and - * negative value on error */ -int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf, - unsigned int* sz) -{ - WOLFSSL_ENTER("wolfSSL_dtls_export_state_only"); - - if (ssl == NULL || sz == NULL) { - return BAD_FUNC_ARG; - } - - if (buf == NULL) { - *sz = MAX_EXPORT_STATE_BUFFER; - return 0; - } - - /* if not DTLS do nothing */ - if (!ssl->options.dtls) { - WOLFSSL_MSG("Currently only DTLS export state is supported"); - return 0; - } - - /* copy over keys, options, and dtls state struct */ - return wolfSSL_dtls_export_state_internal(ssl, buf, *sz); -} - - -/* returns 0 on success */ -int wolfSSL_send_session(WOLFSSL* ssl) -{ - int ret; - byte* buf; - word32 bufSz = MAX_EXPORT_BUFFER; - - WOLFSSL_ENTER("wolfSSL_send_session"); - - if (ssl == NULL) { - return BAD_FUNC_ARG; - } - - buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) { - return MEMORY_E; - } - - /* if not DTLS do nothing */ - if (!ssl->options.dtls) { - XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG("Currently only DTLS export is supported"); - return 0; - } - - /* copy over keys, options, and dtls state struct */ - ret = wolfSSL_session_export_internal(ssl, buf, &bufSz, WOLFSSL_EXPORT_DTLS); - if (ret < 0) { - XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } - - /* if no error ret has size of buffer */ - ret = ssl->dtls_export(ssl, buf, ret, NULL); - if (ret != WOLFSSL_SUCCESS) { - XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } - - XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; -} -#endif /* WOLFSSL_DTLS */ -#endif /* WOLFSSL_SESSION_EXPORT */ - /* prevent multiple mutex initializations */ static volatile WOLFSSL_GLOBAL int initRefCount = 0; -static WOLFSSL_GLOBAL wolfSSL_Mutex inits_count_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(inits_count_mutex); /* init ref count mutex */ +/* init ref count mutex */ +static WOLFSSL_GLOBAL wolfSSL_Mutex inits_count_mutex + WOLFSSL_MUTEX_INITIALIZER_CLAUSE(inits_count_mutex); #ifndef WOLFSSL_MUTEX_INITIALIZER static WOLFSSL_GLOBAL int inits_count_mutex_valid = 0; #endif @@ -1339,8 +1082,8 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); wolfSSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); if (wolfSSL_CTX_set_min_proto_version(ctx, - (method->version.major == DTLS_MAJOR) ? - DTLS1_VERSION : SSL3_VERSION) != WOLFSSL_SUCCESS || + (method->version.major == DTLS_MAJOR) ? + DTLS1_VERSION : SSL3_VERSION) != WOLFSSL_SUCCESS || #ifdef HAVE_ANON wolfSSL_CTX_allow_anon_cipher(ctx) != WOLFSSL_SUCCESS || #endif @@ -1610,8 +1353,8 @@ static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl) #ifdef HAVE_ONE_TIME_AUTH #ifdef HAVE_POLY1305 if (ssl->auth.setup && ssl->auth.poly1305 != NULL) { - dup->auth.poly1305 = - (Poly1305*)XMALLOC(sizeof(Poly1305), dup->heap, DYNAMIC_TYPE_CIPHER); + dup->auth.poly1305 = (Poly1305*)XMALLOC(sizeof(Poly1305), dup->heap, + DYNAMIC_TYPE_CIPHER); if (dup->auth.poly1305 == NULL) return MEMORY_E; dup->auth.setup = 1; @@ -1945,7 +1688,7 @@ const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len) return NULL; cipher = wolfSSL_get_cipher_name_iana(ssl); - len = min(len, (int)(XSTRLEN(cipher) + 1)); + len = (int)min((word32)len, (int)(XSTRLEN(cipher) + 1)); XMEMCPY(buf, cipher, len); return buf; } @@ -2218,10 +1961,12 @@ int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) static const WOLFSSL_SRTP_PROTECTION_PROFILE gSrtpProfiles[] = { /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 80-bits * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */ - {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80, (((128 + 112) * 2) / 8) }, + {"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80, + (((128 + 112) * 2) / 8) }, /* AES CCM 128, Salt:112-bits, Auth HMAC-SHA1 Tag: 32-bits * (master_key:128bits + master_salt:112bits) * 2 = 480 bits (60) */ - {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32, (((128 + 112) * 2) / 8) }, + {"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32, + (((128 + 112) * 2) / 8) }, /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 80-bits */ {"SRTP_NULL_SHA1_80", SRTP_NULL_SHA1_80, ((112 * 2) / 8)}, /* NULL Cipher, Salt:112-bits, Auth HMAC-SHA1 Tag 32-bits */ @@ -2348,7 +2093,7 @@ int wolfSSL_export_dtls_srtp_keying_material(WOLFSSL* ssl, return EXT_MISSING; } if (out == NULL) { - *olen = profile->kdfBits; + *olen = (size_t)profile->kdfBits; return LENGTH_ONLY_E; } @@ -2465,7 +2210,8 @@ int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, if (ret == 0) { XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz); - XMEMSET(ssl->arrays->preMasterSecret + preMasterSz, 0, ENCRYPT_LEN - preMasterSz); + XMEMSET(ssl->arrays->preMasterSecret + preMasterSz, 0, + ENCRYPT_LEN - preMasterSz); ssl->arrays->preMasterSz = preMasterSz; XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN); XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN); @@ -2716,7 +2462,8 @@ int wolfSSL_GetObjectSize(void) #ifdef WOLFSSL_SM4 printf("\tsizeof sm4 = %lu\n", (unsigned long)sizeof(Sm4)); #endif - printf("sizeof cipher specs = %lu\n", (unsigned long)sizeof(CipherSpecs)); + printf("sizeof cipher specs = %lu\n", (unsigned long) + sizeof(CipherSpecs)); printf("sizeof keys = %lu\n", (unsigned long)sizeof(Keys)); printf("sizeof Hashes(2) = %lu\n", (unsigned long)sizeof(Hashes)); #ifndef NO_MD5 @@ -2749,10 +2496,13 @@ int wolfSSL_GetObjectSize(void) #ifdef HAVE_ECC printf("sizeof ecc_key = %lu\n", (unsigned long)sizeof(ecc_key)); #endif - printf("sizeof WOLFSSL_CIPHER = %lu\n", (unsigned long)sizeof(WOLFSSL_CIPHER)); - printf("sizeof WOLFSSL_SESSION = %lu\n", (unsigned long)sizeof(WOLFSSL_SESSION)); + printf("sizeof WOLFSSL_CIPHER = %lu\n", (unsigned long) + sizeof(WOLFSSL_CIPHER)); + printf("sizeof WOLFSSL_SESSION = %lu\n", (unsigned long) + sizeof(WOLFSSL_SESSION)); printf("sizeof WOLFSSL = %lu\n", (unsigned long)sizeof(WOLFSSL)); - printf("sizeof WOLFSSL_CTX = %lu\n", (unsigned long)sizeof(WOLFSSL_CTX)); + printf("sizeof WOLFSSL_CTX = %lu\n", (unsigned long) + sizeof(WOLFSSL_CTX)); #endif return sizeof(WOLFSSL); @@ -2772,13 +2522,11 @@ int wolfSSL_METHOD_GetObjectSize(void) #ifdef WOLFSSL_STATIC_MEMORY -int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method, - unsigned char* buf, unsigned int sz, - int flag, int maxSz) +int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, + wolfSSL_method_func method, unsigned char* buf, unsigned int sz, int flag, + int maxSz) { - WOLFSSL_HEAP* heap; - WOLFSSL_HEAP_HINT* hint; - word32 idx = 0; + WOLFSSL_HEAP_HINT* hint = NULL; if (ctx == NULL || buf == NULL) { return BAD_FUNC_ARG; @@ -2788,42 +2536,23 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method return BAD_FUNC_ARG; } - if (*ctx == NULL || (*ctx)->heap == NULL) { - if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) { - return BUFFER_E; /* not enough memory for structures */ - } - heap = (WOLFSSL_HEAP*)buf; - idx += sizeof(WOLFSSL_HEAP); - if (wolfSSL_init_memory_heap(heap) != 0) { - return WOLFSSL_FAILURE; - } - hint = (WOLFSSL_HEAP_HINT*)(buf + idx); - idx += sizeof(WOLFSSL_HEAP_HINT); - XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); - hint->memory = heap; - - if (*ctx && (*ctx)->heap == NULL) { - (*ctx)->heap = (void*)hint; - } - } - else { -#ifdef WOLFSSL_HEAP_TEST - /* do not load in memory if test has been set */ - if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) { - return WOLFSSL_SUCCESS; - } -#endif - hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap); - heap = hint->memory; + /* If there is a heap already, capture it in hint. */ + if (*ctx && (*ctx)->heap != NULL) { + hint = (*ctx)->heap; } - if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) { - WOLFSSL_MSG("Error partitioning memory"); + if (wc_LoadStaticMemory(&hint, buf, sz, flag, maxSz)) { + WOLFSSL_MSG("Error loading static memory"); return WOLFSSL_FAILURE; } - /* create ctx if needed */ - if (*ctx == NULL) { + if (*ctx) { + if ((*ctx)->heap == NULL) { + (*ctx)->heap = (void*)hint; + } + } + else { + /* create ctx if needed */ *ctx = wolfSSL_CTX_new_ex(method(hint), hint); if (*ctx == NULL) { WOLFSSL_MSG("Error creating ctx"); @@ -2831,19 +2560,6 @@ int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method } } - /* determine what max applies too */ - if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { - heap->maxIO = maxSz; - } - else { /* general memory used in handshakes */ - heap->maxHa = maxSz; - } - - heap->flag |= flag; - - (void)maxSz; - (void)method; - return WOLFSSL_SUCCESS; } @@ -2855,6 +2571,7 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats) } WOLFSSL_ENTER("wolfSSL_is_static_memory"); +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */ if (mem_stats != NULL && ssl->heap != NULL) { WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); @@ -2863,7 +2580,9 @@ int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats) XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS)); } } +#endif + (void)mem_stats; return (ssl->heap) ? 1 : 0; } @@ -2875,6 +2594,7 @@ int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats) } WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory"); +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* fill out statistics if wanted */ if (mem_stats != NULL && ctx->heap != NULL) { WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory; @@ -2882,7 +2602,9 @@ int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats) return MEMORY_E; } } +#endif + (void)mem_stats; return (ctx->heap) ? 1 : 0; } @@ -2922,13 +2644,15 @@ 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, 0, CUR_ORDER); + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0, + CUR_ORDER); } #ifdef HAVE_ECC int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz) { + WOLFSSL_ENTER("wolfSSL_CTX_SetMinEccKey_Sz"); if (ctx == NULL || keySz < 0 || keySz % 8 != 0) { WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null"); return BAD_FUNC_ARG; @@ -2944,6 +2668,7 @@ int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz) int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz) { + WOLFSSL_ENTER("wolfSSL_SetMinEccKey_Sz"); if (ssl == NULL || keySz < 0 || keySz % 8 != 0) { WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null"); return BAD_FUNC_ARG; @@ -2983,138 +2708,6 @@ int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz) #ifndef NO_DH -#ifdef OPENSSL_EXTRA -long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) -{ - int pSz, gSz; - byte *p, *g; - int ret = 0; - - WOLFSSL_ENTER("wolfSSL_set_tmp_dh"); - - if (!ssl || !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 -1; - - p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (!p) - return MEMORY_E; - - g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (!g) { - XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - 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_SetTmpDH(ssl, p, pSz, g, gSz); - - XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - - return pSz > 0 && gSz > 0 ? ret : -1; -} -#endif /* OPENSSL_EXTRA */ - -/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ -int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, - const unsigned char* g, int gSz) -{ - WOLFSSL_ENTER("wolfSSL_SetTmpDH"); - - if (ssl == NULL || p == NULL || g == NULL) - return BAD_FUNC_ARG; - - if ((word16)pSz < ssl->options.minDhKeySz) - return DH_KEY_SIZE_E; - if ((word16)pSz > ssl->options.maxDhKeySz) - return DH_KEY_SIZE_E; - - /* this function is for server only */ - if (ssl->options.side == WOLFSSL_CLIENT_END) - return SIDE_ERROR; - - #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ - !defined(HAVE_SELFTEST) - ssl->options.dhKeyTested = 0; - ssl->options.dhDoKeyTest = 1; - #endif - - if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - 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_PUBLIC_KEY); - 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_PUBLIC_KEY); - if (ssl->buffers.serverDH_P.buffer == NULL) - return MEMORY_E; - - ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - if (ssl->buffers.serverDH_G.buffer == NULL) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - ssl->buffers.serverDH_P.buffer = NULL; - return MEMORY_E; - } - - ssl->buffers.serverDH_P.length = pSz; - ssl->buffers.serverDH_G.length = gSz; - - XMEMCPY(ssl->buffers.serverDH_P.buffer, p, pSz); - XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz); - - ssl->options.haveDH = 1; - - if (ssl->options.side != WOLFSSL_NEITHER_END) { - word16 havePSK; - word16 haveRSA; - int keySz = 0; - int ret; - - #ifndef NO_PSK - havePSK = ssl->options.havePSK; - #else - havePSK = 0; - #endif - #ifdef NO_RSA - haveRSA = 0; - #else - haveRSA = 1; - #endif - #ifndef NO_CERTS - keySz = ssl->buffers.keySz; - #endif - ret = AllocateSuites(ssl); - if (ret != 0) - return ret; - InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveECDSAsig, - ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, - ssl->options.useAnon, TRUE, ssl->options.side); - } - - WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0); - - return WOLFSSL_SUCCESS; -} - - #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ !defined(HAVE_SELFTEST) /* Enables or disables the session's DH key prime test. */ @@ -3135,82 +2728,6 @@ int wolfSSL_SetEnableDhKeyTest(WOLFSSL* ssl, int enable) } #endif - -/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ -int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, - const unsigned char* g, int gSz) -{ - WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH"); - if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG; - - if ((word16)pSz < ctx->minDhKeySz) - return DH_KEY_SIZE_E; - if ((word16)pSz > ctx->maxDhKeySz) - return DH_KEY_SIZE_E; - - #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ - !defined(HAVE_SELFTEST) - { - WC_RNG rng; - int error, freeKey = 0; - #ifdef WOLFSSL_SMALL_STACK - DhKey *checkKey = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); - if (checkKey == NULL) - return MEMORY_E; - #else - DhKey checkKey[1]; - #endif - - error = wc_InitRng(&rng); - if (!error) - error = wc_InitDhKey(checkKey); - if (!error) { - freeKey = 1; - error = wc_DhSetCheckKey(checkKey, - p, pSz, g, gSz, NULL, 0, 0, &rng); - } - if (freeKey) - wc_FreeDhKey(checkKey); - #ifdef WOLFSSL_SMALL_STACK - XFREE(checkKey, NULL, DYNAMIC_TYPE_DH); - #endif - wc_FreeRng(&rng); - if (error) - return error; - - ctx->dhKeyTested = 1; - } - #endif - - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - ctx->serverDH_P.buffer = NULL; - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - ctx->serverDH_G.buffer = NULL; - - ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (ctx->serverDH_P.buffer == NULL) - return MEMORY_E; - - ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (ctx->serverDH_G.buffer == NULL) { - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - ctx->serverDH_P.buffer = NULL; - return MEMORY_E; - } - - ctx->serverDH_P.length = pSz; - ctx->serverDH_G.length = gSz; - - XMEMCPY(ctx->serverDH_P.buffer, p, pSz); - XMEMCPY(ctx->serverDH_G.buffer, g, gSz); - - ctx->haveDH = 1; - - WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0); - return WOLFSSL_SUCCESS; -} - - int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz_bits) { if (ctx == NULL || keySz_bits > 16000 || keySz_bits % 8 != 0) @@ -3549,7 +3066,7 @@ word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) *data = NULL; if (ssl && ssl->extensions) - return TLSX_SNI_GetRequest(ssl->extensions, type, data); + return TLSX_SNI_GetRequest(ssl->extensions, type, data, 0); return 0; } @@ -3750,11 +3267,11 @@ static int isValidCurveGroup(word16 name) case WOLFSSL_FFDHE_6144: case WOLFSSL_FFDHE_8192: -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER case WOLFSSL_KYBER_LEVEL1: case WOLFSSL_KYBER_LEVEL3: case WOLFSSL_KYBER_LEVEL5: - #ifdef HAVE_LIBOQS + #if defined(WOLFSSL_WC_KYBER) || defined(HAVE_LIBOQS) case WOLFSSL_P256_KYBER_LEVEL1: case WOLFSSL_P384_KYBER_LEVEL3: case WOLFSSL_P521_KYBER_LEVEL5: @@ -3794,7 +3311,7 @@ int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) #endif /* NO_TLS */ } -#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) +#if defined(OPENSSL_EXTRA) int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, int count) { @@ -3812,7 +3329,7 @@ int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, #ifdef HAVE_ECC else { /* groups may be populated with curve NIDs */ - int oid = nid2oid(groups[i], oidCurveType); + int oid = (int)nid2oid(groups[i], oidCurveType); int name = (int)GetCurveByOID(oid); if (name == 0) { WOLFSSL_MSG("Invalid group name"); @@ -3847,7 +3364,7 @@ int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count) #ifdef HAVE_ECC else { /* groups may be populated with curve NIDs */ - int oid = nid2oid(groups[i], oidCurveType); + int oid = (int)nid2oid(groups[i], oidCurveType); int name = (int)GetCurveByOID(oid); if (name == 0) { WOLFSSL_MSG("Invalid group name"); @@ -3865,7 +3382,7 @@ int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count) return wolfSSL_set_groups(ssl, _groups, count) == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } -#endif /* OPENSSL_EXTRA && WOLFSSL_TLS13 */ +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SUPPORTED_CURVES */ /* Application-Layer Protocol Negotiation */ @@ -3906,7 +3423,8 @@ int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, return MEMORY_ERROR; } - token = (char **)XMALLOC(sizeof(char *) * (WOLFSSL_MAX_ALPN_NUMBER+1), ssl->heap, DYNAMIC_TYPE_ALPN); + token = (char **)XMALLOC(sizeof(char *) * (WOLFSSL_MAX_ALPN_NUMBER+1), + ssl->heap, DYNAMIC_TYPE_ALPN); if (token == NULL) { XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN); WOLFSSL_MSG("Memory failure"); @@ -4012,12 +3530,14 @@ int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list) /* user is forcing ability to use secure renegotiation, we discourage it */ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); #if defined(NO_TLS) (void)ssl; #else if (ssl) ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap); + else + ret = BAD_FUNC_ARG; if (ret == WOLFSSL_SUCCESS) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); @@ -4339,7 +3859,8 @@ int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, } } else { /* Ticket requires dynamic ticket storage */ - if (ssl->session->ticketLen < bufSz) { /* is dyn buffer big enough */ + /* is dyn buffer big enough */ + if (ssl->session->ticketLen < bufSz) { if (ssl->session->ticketLenAlloc > 0) { XFREE(ssl->session->ticket, ssl->session->heap, DYNAMIC_TYPE_SESSION_TICK); @@ -4452,10 +3973,29 @@ int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags) } #endif - -/* WOLFSSL_SUCCESS on ok */ -WOLFSSL_ABI -int wolfSSL_shutdown(WOLFSSL* ssl) +int wolfSSL_SendUserCanceled(WOLFSSL* ssl) +{ + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_recv"); + + if (ssl != NULL) { + ssl->error = SendAlert(ssl, alert_warning, user_canceled); + if (ssl->error < 0) { + WOLFSSL_ERROR(ssl->error); + } + else { + ret = wolfSSL_shutdown(ssl); + } + } + + WOLFSSL_LEAVE("wolfSSL_SendUserCanceled", ret); + + return ret; +} + +/* WOLFSSL_SUCCESS on ok */ +WOLFSSL_ABI +int wolfSSL_shutdown(WOLFSSL* ssl) { int ret = WOLFSSL_FATAL_ERROR; WOLFSSL_ENTER("wolfSSL_shutdown"); @@ -4499,13 +4039,14 @@ int wolfSSL_shutdown(WOLFSSL* ssl) /* call wolfSSL_shutdown again for bidirectional shutdown */ if (ssl->options.sentNotify && !ssl->options.closeNotify) { ret = ProcessReply(ssl); - if ((ret == ZERO_RETURN) || (ret == SOCKET_ERROR_E)) { + if ((ret == ZERO_RETURN) || + (ret == WC_NO_ERR_TRACE(SOCKET_ERROR_E))) { /* simulate OpenSSL behavior */ ssl->options.shutdownDone = 1; /* Clear error */ ssl->error = WOLFSSL_ERROR_NONE; ret = WOLFSSL_SUCCESS; - } else if (ret == MEMORY_E) { + } else if (ret == WC_NO_ERR_TRACE(MEMORY_E)) { ret = WOLFSSL_FATAL_ERROR; } else if (ssl->error == WOLFSSL_ERROR_NONE) { ret = WOLFSSL_SHUTDOWN_NOT_DONE; @@ -4563,14 +4104,10 @@ int wolfSSL_get_error(WOLFSSL* ssl, int ret) else if (ssl->error == ZERO_RETURN || ssl->options.shutdownDone) return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */ #ifdef OPENSSL_EXTRA - else if (ssl->error == SOCKET_PEER_CLOSED_E) + else if (ssl->error == WC_NO_ERR_TRACE(SOCKET_PEER_CLOSED_E)) return WOLFSSL_ERROR_SYSCALL; /* convert to OpenSSL type */ #endif -#if defined(WOLFSSL_HAPROXY) - return GetX509Error(ssl->error); -#else - return (ssl->error); -#endif + return ssl->error; } @@ -5709,14 +5246,15 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) #endif XMEMCPY(peerCert->subjectNameHash, cert->subjectHash, SIGNER_DIGEST_SIZE); - peerCert->next = NULL; /* If Key Usage not set, all uses valid. */ + /* If Key Usage not set, all uses valid. */ + peerCert->next = NULL; cert->subjectCN = 0; #ifndef IGNORE_NAME_CONSTRAINTS cert->permittedNames = NULL; cert->excludedNames = NULL; #endif - row = TrustedPeerHashSigner(peerCert->subjectNameHash); + row = (int)TrustedPeerHashSigner(peerCert->subjectNameHash); if (wc_LockMutex(&cm->tpLock) == 0) { peerCert->next = cm->tpTable[row]; @@ -5745,6 +5283,38 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) } #endif /* WOLFSSL_TRUST_PEER_CERT */ +int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s) +{ + byte* subjectHash; + Signer* signers; + word32 row; + + if (cm == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_SKID + subjectHash = s->subjectKeyIdHash; +#else + subjectHash = s->subjectNameHash; +#endif + + if (AlreadySigner(cm, subjectHash)) { + FreeSigner(s, cm->heap); + return 0; + } + + row = HashSigner(subjectHash); + + if (wc_LockMutex(&cm->caLock) != 0) + return BAD_MUTEX_E; + + signers = cm->caTable[row]; + s->next = signers; + cm->caTable[row] = s; + + wc_UnLockMutex(&cm->caLock); + return 0; +} /* owns der, internal now uses too */ /* type flag ids from user or from chain received during verify @@ -5830,7 +5400,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case FALCON_LEVEL1k: if (cm->minFalconKeySz < 0 || @@ -5870,7 +5439,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) } break; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ default: WOLFSSL_MSG("\tNo key size check done on CA"); @@ -5901,62 +5469,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (!signer) ret = MEMORY_ERROR; } -#if defined(WOLFSSL_AKID_NAME) || defined(HAVE_CRL) - if (ret == 0 && signer != NULL) - ret = CalcHashId(cert->serial, cert->serialSz, signer->serialHash); -#endif - if (ret == 0 && signer != NULL) { - #ifdef WOLFSSL_SIGNER_DER_CERT - ret = AllocDer(&signer->derCert, der->length, der->type, NULL); - } if (ret == 0 && signer != NULL) { - XMEMCPY(signer->derCert->buffer, der->buffer, der->length); - #endif - signer->keyOID = cert->keyOID; - if (cert->pubKeyStored) { - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - } - -#ifdef WOLFSSL_DUAL_ALG_CERTS - signer->sapkiDer = cert->sapkiDer; - signer->sapkiLen = cert->sapkiLen; -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - - if (cert->subjectCNStored) { - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; - } - signer->maxPathLen = cert->maxPathLen; - signer->selfSigned = cert->selfSigned; - #ifndef IGNORE_NAME_CONSTRAINTS - signer->permittedNames = cert->permittedNames; - signer->excludedNames = cert->excludedNames; - #endif - #ifndef NO_SKID - XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, - SIGNER_DIGEST_SIZE); - #endif - XMEMCPY(signer->subjectNameHash, cert->subjectHash, - SIGNER_DIGEST_SIZE); - #if defined(HAVE_OCSP) || defined(HAVE_CRL) - XMEMCPY(signer->issuerNameHash, cert->issuerHash, - SIGNER_DIGEST_SIZE); - #endif - #ifdef HAVE_OCSP - XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, - KEYID_SIZE); - #endif - signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage - : 0xFFFF; - signer->next = NULL; /* If Key Usage not set, all uses valid. */ - cert->publicKey = 0; /* in case lock fails don't free here. */ - cert->subjectCN = 0; - #ifndef IGNORE_NAME_CONSTRAINTS - cert->permittedNames = NULL; - cert->excludedNames = NULL; - #endif - signer->type = (byte)type; + ret = FillSigner(signer, cert, type, der); #ifndef NO_SKID row = HashSigner(signer->subjectKeyIdHash); @@ -5964,7 +5478,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) row = HashSigner(signer->subjectNameHash); #endif - if (wc_LockMutex(&cm->caLock) == 0) { + + if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) { signer->next = cm->caTable[row]; cm->caTable[row] = signer; /* takes ownership */ wc_UnLockMutex(&cm->caLock); @@ -6018,191 +5533,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) #endif /* !NO_CERTS */ -#ifndef NO_SESSION_CACHE - - /* basic config gives a cache with 33 sessions, adequate for clients and - embedded servers - - TITAN_SESSION_CACHE allows just over 2 million sessions, for servers - with titanic amounts of memory with long session ID timeouts and high - levels of traffic. - - ENABLE_SESSION_CACHE_ROW_LOCK: Allows row level locking for increased - performance with large session caches - - HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load, - allows over 13,000 new sessions per minute or over 200 new sessions per - second - - BIG_SESSION_CACHE yields 20,027 sessions - - MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that - aren't under heavy load, basically allows 200 new sessions per minute - - SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients - or systems where the default of is too much RAM. - SessionCache takes about 2K, ClientCache takes about 3Kbytes - - MICRO_SESSION_CACHE only stores 1 session, good for embedded clients - or systems where memory is at a premium. - SessionCache takes about 400 bytes, ClientCache takes 576 bytes - - default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined) - SessionCache takes about 13K bytes, ClientCache takes 17K bytes - */ - #if defined(TITAN_SESSION_CACHE) - #define SESSIONS_PER_ROW 31 - #define SESSION_ROWS 64937 - #ifndef ENABLE_SESSION_CACHE_ROW_LOCK - #define ENABLE_SESSION_CACHE_ROW_LOCK - #endif - #elif defined(HUGE_SESSION_CACHE) - #define SESSIONS_PER_ROW 11 - #define SESSION_ROWS 5981 - #elif defined(BIG_SESSION_CACHE) - #define SESSIONS_PER_ROW 7 - #define SESSION_ROWS 2861 - #elif defined(MEDIUM_SESSION_CACHE) - #define SESSIONS_PER_ROW 5 - #define SESSION_ROWS 211 - #elif defined(SMALL_SESSION_CACHE) - #define SESSIONS_PER_ROW 2 - #define SESSION_ROWS 3 - #elif defined(MICRO_SESSION_CACHE) - #define SESSIONS_PER_ROW 1 - #define SESSION_ROWS 1 - #else - #define SESSIONS_PER_ROW 3 - #define SESSION_ROWS 11 - #endif - #define INVALID_SESSION_ROW (-1) - - #ifdef NO_SESSION_CACHE_ROW_LOCK - #undef ENABLE_SESSION_CACHE_ROW_LOCK - #endif - - typedef struct SessionRow { - int nextIdx; /* where to place next one */ - int totalCount; /* sessions ever on this row */ -#ifdef SESSION_CACHE_DYNAMIC_MEM - WOLFSSL_SESSION* Sessions[SESSIONS_PER_ROW]; - void* heap; -#else - WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW]; -#endif - - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - /* not included in import/export */ - wolfSSL_RwLock row_lock; - int lock_valid; - #endif - } SessionRow; - #define SIZEOF_SESSION_ROW (sizeof(WOLFSSL_SESSION) + (sizeof(int) * 2)) - - static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS]; - - #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - static WOLFSSL_GLOBAL word32 PeakSessions; - #endif - - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - #define SESSION_ROW_RD_LOCK(row) wc_LockRwLock_Rd(&(row)->row_lock) - #define SESSION_ROW_WR_LOCK(row) wc_LockRwLock_Wr(&(row)->row_lock) - #define SESSION_ROW_UNLOCK(row) wc_UnLockRwLock(&(row)->row_lock); - #else - static WOLFSSL_GLOBAL wolfSSL_RwLock session_lock; /* SessionCache lock */ - static WOLFSSL_GLOBAL int session_lock_valid = 0; - #define SESSION_ROW_RD_LOCK(row) wc_LockRwLock_Rd(&session_lock) - #define SESSION_ROW_WR_LOCK(row) wc_LockRwLock_Wr(&session_lock) - #define SESSION_ROW_UNLOCK(row) wc_UnLockRwLock(&session_lock); - #endif - - #if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE) - #error ClientCache is required when not using NO_SESSION_CACHE_REF - #endif - - #ifndef NO_CLIENT_CACHE - - #ifndef CLIENT_SESSIONS_MULTIPLIER - #ifdef NO_SESSION_CACHE_REF - #define CLIENT_SESSIONS_MULTIPLIER 1 - #else - /* ClientSession objects are lightweight (compared to - * WOLFSSL_SESSION) so to decrease chance that user will reuse - * the wrong session, increase the ClientCache size. This will - * make the entire ClientCache about the size of one - * WOLFSSL_SESSION object. */ - #define CLIENT_SESSIONS_MULTIPLIER 8 - #endif - #endif - #define CLIENT_SESSIONS_PER_ROW \ - (SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER) - #define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER) - - #if CLIENT_SESSIONS_PER_ROW > 65535 - #error CLIENT_SESSIONS_PER_ROW too big - #endif - #if CLIENT_SESSION_ROWS > 65535 - #error CLIENT_SESSION_ROWS too big - #endif - - struct ClientSession { - word16 serverRow; /* SessionCache Row id */ - word16 serverIdx; /* SessionCache Idx (column) */ - word32 sessionIDHash; - }; - #ifndef WOLFSSL_CLIENT_SESSION_DEFINED - typedef struct ClientSession ClientSession; - #define WOLFSSL_CLIENT_SESSION_DEFINED - #endif - - typedef struct ClientRow { - int nextIdx; /* where to place next one */ - int totalCount; /* sessions ever on this row */ - ClientSession Clients[CLIENT_SESSIONS_PER_ROW]; - } ClientRow; - - static WOLFSSL_GLOBAL ClientRow ClientCache[CLIENT_SESSION_ROWS]; - /* Client Cache */ - /* uses session mutex */ - - static WOLFSSL_GLOBAL wolfSSL_Mutex clisession_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(clisession_mutex); /* ClientCache mutex */ - #ifndef WOLFSSL_MUTEX_INITIALIZER - static WOLFSSL_GLOBAL int clisession_mutex_valid = 0; - #endif - #endif /* !NO_CLIENT_CACHE */ - - void EvictSessionFromCache(WOLFSSL_SESSION* session) - { -#ifdef HAVE_EX_DATA - int save_ownExData = session->ownExData; - session->ownExData = 1; /* Make sure ex_data access doesn't lead back - * into the cache. */ -#endif -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - if (session->rem_sess_cb != NULL) { - session->rem_sess_cb(NULL, session); - session->rem_sess_cb = NULL; - } -#endif - ForceZero(session->masterSecret, SECRET_LEN); - XMEMSET(session->sessionID, 0, ID_LEN); - session->sessionIDSz = 0; -#ifdef HAVE_SESSION_TICKET - if (session->ticketLenAlloc > 0) { - XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); - session->ticket = session->staticTicket; - session->ticketLen = 0; - session->ticketLenAlloc = 0; - } -#endif -#ifdef HAVE_EX_DATA - session->ownExData = save_ownExData; -#endif - } - -#endif /* !NO_SESSION_CACHE */ - #if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) static int wolfSSL_RAND_InitMutex(void); #endif @@ -6244,13 +5574,13 @@ int wolfSSL_Init(void) return BAD_MUTEX_E; } - #if FIPS_VERSION_GE(5,1) +#if FIPS_VERSION_GE(5,1) if ((ret == WOLFSSL_SUCCESS) && (initRefCount == 0)) { ret = wolfCrypt_SetPrivateKeyReadEnable_fips(1, WC_KEYTYPE_ALL); if (ret == 0) ret = WOLFSSL_SUCCESS; } - #endif +#endif if ((ret == WOLFSSL_SUCCESS) && (initRefCount == 0)) { /* Initialize crypto for use with TLS connection */ @@ -6340,11 +5670,13 @@ int wolfSSL_Init(void) if (ret == WOLFSSL_SUCCESS) { initRefCount++; } + else { + initRefCount = 1; /* Force cleanup */ + } wc_UnLockMutex(&inits_count_mutex); if (ret != WOLFSSL_SUCCESS) { - initRefCount = 1; /* Force cleanup */ (void)wolfSSL_Cleanup(); /* Ignore any error from cleanup */ } @@ -6352,29677 +5684,18939 @@ int wolfSSL_Init(void) } +#define WOLFSSL_SSL_LOAD_INCLUDED +#include + #ifndef NO_CERTS -/* process user cert chain to pass during the handshake */ -static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, - long sz, int format, int type, WOLFSSL* ssl, - long* used, EncryptedInfo* info, int verify) +#ifdef HAVE_CRL + +int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int type) { - int ret = 0; - void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer"); - if ((type == CA_TYPE) && (ctx == NULL)) { - WOLFSSL_MSG("Need context for CA load"); + if (ctx == NULL) return BAD_FUNC_ARG; - } - /* we may have a user cert chain, try to consume */ - if ((type == CERT_TYPE || type == CHAIN_CERT_TYPE || type == CA_TYPE) && - (info->consumed < sz)) { - #ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ - #else - byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */ - #endif - byte* chainBuffer = staticBuffer; - int dynamicBuffer = 0; - word32 bufferSz; - long consumed = info->consumed; - word32 idx = 0; - int gotOne = 0; - #ifdef WOLFSSL_TLS13 - int cnt = 0; - #endif + return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type); +} - /* Calculate max possible size, including max headers */ - bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH); - if (bufferSz > sizeof(staticBuffer)) { - WOLFSSL_MSG("Growing Tmp Chain Buffer"); - /* will shrink to actual size */ - chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE); - if (chainBuffer == NULL) { - return MEMORY_E; - } - dynamicBuffer = 1; - } - WOLFSSL_MSG("Processing Cert Chain"); - while (consumed < sz) { - DerBuffer* part = NULL; - word32 remain = (word32)(sz - consumed); - info->consumed = 0; +int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, + long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer"); - if (format == WOLFSSL_FILETYPE_PEM) { - #ifdef WOLFSSL_PEM_TO_DER - ret = PemToDer(buff + consumed, remain, type, &part, - heap, info, NULL); - #else - ret = NOT_COMPILED_IN; - #endif - } - else { - int length = remain; - if (format == WOLFSSL_FILETYPE_ASN1) { - /* get length of der (read sequence) */ - word32 inOutIdx = 0; - if (GetSequence(buff + consumed, &inOutIdx, &length, - remain) < 0) { - ret = ASN_NO_PEM_HEADER; - } - length += inOutIdx; /* include leading sequence */ - } - info->consumed = length; - if (ret == 0) { - ret = AllocDer(&part, length, type, heap); - if (ret == 0) { - XMEMCPY(part->buffer, buff + consumed, length); - } - } - } - if (ret == 0) { - gotOne = 1; -#ifdef WOLFSSL_TLS13 - cnt++; -#endif - if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) { - WOLFSSL_MSG(" Cert Chain bigger than buffer. " - "Consider increasing MAX_CHAIN_DEPTH"); - ret = BUFFER_E; - } - else { - c32to24(part->length, &chainBuffer[idx]); - idx += CERT_HEADER_SZ; - XMEMCPY(&chainBuffer[idx], part->buffer, part->length); - idx += part->length; - consumed += info->consumed; - if (used) - *used += info->consumed; - } + if (ssl == NULL || ssl->ctx == NULL) + return BAD_FUNC_ARG; - /* add CA's to certificate manager */ - if (ret == 0 && type == CA_TYPE) { - /* verify CA unless user set to no verify */ - ret = AddCA(ctx->cm, &part, WOLFSSL_USER_CA, verify); - if (ret == WOLFSSL_SUCCESS) { - ret = 0; /* converted success case */ - } - gotOne = 0; /* don't exit loop for CA type */ - } - } + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type); +} - FreeDer(&part); +#endif /* HAVE_CRL */ - if (ret == ASN_NO_PEM_HEADER && gotOne) { - WOLFSSL_MSG("We got one good cert, so stuff at end ok"); - break; - } +#ifdef HAVE_OCSP +int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options) +{ + WOLFSSL_ENTER("wolfSSL_EnableOCSP"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options); + } + else + return BAD_FUNC_ARG; +} - if (ret < 0) { - WOLFSSL_MSG(" Error in Cert in Chain"); - if (dynamicBuffer) - XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); - return ret; - } - WOLFSSL_MSG(" Consumed another Cert in Chain"); - } - WOLFSSL_MSG("Finished Processing Cert Chain"); +int wolfSSL_DisableOCSP(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_DisableOCSP"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl)); + } + else + return BAD_FUNC_ARG; +} - /* only retain actual size used */ - ret = 0; - if (idx > 0) { - if (ssl) { - if (ssl->buffers.weOwnCertChain) { - FreeDer(&ssl->buffers.certChain); - } - ret = AllocDer(&ssl->buffers.certChain, idx, type, heap); - if (ret == 0) { - 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 - } - } - if (dynamicBuffer) - XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); +int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl)); } - - return ret; + else + return BAD_FUNC_ARG; } -#ifndef NO_RSA -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION > 2)) -static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - int devId) +int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl) { - int ret; + WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl)); + } + else + return BAD_FUNC_ARG; +} - (void)devId; +int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url) +{ + WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url); + } + else + return BAD_FUNC_ARG; +} - *idx = 0; - ret = wc_RsaPrivateKeyValidate(der->buffer, idx, keySz, der->length); -#ifdef WOLF_PRIVATE_KEY_ID - if ((ret != 0) && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || ((ssl == NULL) ? wolfSSL_CTX_IsPrivatePkSet(ctx) : - wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - #endif - )) { - word32 nSz; - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_RsaPublicKeyDecode_ex(der->buffer, idx, der->length, NULL, - &nSz, NULL, NULL); - if (ret == 0) { - *keySz = (int)nSz; - } - } -#endif - if (ret != 0) { - #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448) && !defined(HAVE_PQC) - WOLFSSL_MSG("RSA decode failed and other algorithms " - "not enabled to try"); - ret = WOLFSSL_BAD_FILE; - #else - if (*keyFormat == 0) { - /* Format unknown so keep trying. */ - ret = 0; /* continue trying other algorithms */ - } - #endif +int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl, + CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx) +{ + WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb"); + if (ssl) { + SSL_CM_WARNING(ssl); + ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */ + return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl), + ioCb, respFreeCb, NULL); } - else { - /* check that the size of the RSA key is enough */ - int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; - if (*keySz < minRsaSz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Private Key size too small"); - } + else + return BAD_FUNC_ARG; +} - if (ssl) { - ssl->buffers.keyType = rsa_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->privateKeyType = rsa_sa_algo; - ctx->privateKeySz = *keySz; - } +int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP"); + if (ctx) + return wolfSSL_CertManagerEnableOCSP(ctx->cm, options); + else + return BAD_FUNC_ARG; +} - *keyFormat = RSAk; - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - ssl->options.haveStaticECC = 0; - *resetSuites = 1; - } - } +int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP"); + if (ctx) + return wolfSSL_CertManagerDisableOCSP(ctx->cm); + else + return BAD_FUNC_ARG; +} - return ret; + +int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url) +{ + WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); + if (ctx) + return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url); + else + return BAD_FUNC_ARG; } -#else -static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int devId) + + +int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb, + CbOCSPRespFree respFreeCb, void* ioCbCtx) { - int ret; + WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb"); + if (ctx) + return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb, + respFreeCb, ioCbCtx); + else + return BAD_FUNC_ARG; +} - /* make sure RSA key can be used */ -#ifdef WOLFSSL_SMALL_STACK - RsaKey* key; -#else - RsaKey key[1]; -#endif +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm); + else + return BAD_FUNC_ARG; +} -#ifdef WOLFSSL_SMALL_STACK - key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); - if (key == NULL) - return MEMORY_E; -#endif +int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm); + else + return BAD_FUNC_ARG; +} - ret = wc_InitRsaKey_ex(key, heap, devId); - if (ret == 0) { - *idx = 0; - ret = wc_RsaPrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || ((ssl == NULL) ? wolfSSL_CTX_IsPrivatePkSet(ctx) : - wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_RsaPublicKeyDecode(der->buffer, idx, key, der->length); - } - #endif - if (ret != 0) { - #if !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448) && !defined(HAVE_PQC) - WOLFSSL_MSG("RSA decode failed and other algorithms " - "not enabled to try"); - ret = WOLFSSL_BAD_FILE; - #else - if (*keyFormat == 0) { - /* Format unknown so keep trying. */ - ret = 0; /* continue trying other algorithms */ - } - #endif - } - else { - /* check that the size of the RSA key is enough */ - int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; - *keySz = wc_RsaEncryptSize((RsaKey*)key); - if (*keySz < minRsaSz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Private Key size too small"); - } +int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple"); + if (ctx) + return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm); + else + return BAD_FUNC_ARG; +} - if (ssl) { - ssl->buffers.keyType = rsa_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->privateKeyType = rsa_sa_algo; - ctx->privateKeySz = *keySz; - } +int wolfSSL_CTX_DisableOCSPMustStaple(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPMustStaple"); + if (ctx) + return wolfSSL_CertManagerDisableOCSPMustStaple(ctx->cm); + else + return BAD_FUNC_ARG; +} +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || \ + * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ - *keyFormat = RSAk; +#endif /* HAVE_OCSP */ - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - ssl->options.haveStaticECC = 0; - *resetSuites = 1; - } - } +#ifdef HAVE_CRL - wc_FreeRsaKey(key); +int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) +{ + WOLFSSL_ENTER("wolfSSL_EnableCRL"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options); } + else + return BAD_FUNC_ARG; +} -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_RSA); -#endif - return ret; +int wolfSSL_DisableCRL(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_DisableCRL"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl)); + } + else + return BAD_FUNC_ARG; } -#endif -#endif /* !NO_RSA */ -#ifdef HAVE_ECC -static int ProcessBufferTryDecodeEcc(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int devId) +#ifndef NO_FILESYSTEM +int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) { - int ret = 0; - /* make sure ECC key can be used */ -#ifdef WOLFSSL_SMALL_STACK - ecc_key* key; -#else - ecc_key key[1]; -#endif + WOLFSSL_ENTER("wolfSSL_LoadCRL"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor); + } + else + return BAD_FUNC_ARG; +} -#ifdef WOLFSSL_SMALL_STACK - key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); - if (key == NULL) - return MEMORY_E; +int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRLFile"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type); + } + else + return BAD_FUNC_ARG; +} #endif - if (wc_ecc_init_ex(key, heap, devId) == 0) { - *idx = 0; - ret = wc_EccPrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || ((ssl == NULL) ? wolfSSL_CTX_IsPrivatePkSet(ctx) : - wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_EccPublicKeyDecode(der->buffer, idx, key, der->length); - } - #endif - if (ret == 0) { - /* check for minimum ECC key size and then free */ - int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; - *keySz = wc_ecc_size(key); - if (*keySz < minKeySz) { - WOLFSSL_MSG("ECC private key too small"); - ret = ECC_KEY_SIZE_E; - } - - *keyFormat = ECDSAk; - if (ssl) { - ssl->options.haveStaticECC = 1; - ssl->buffers.keyType = ecc_dsa_sa_algo; - #ifdef WOLFSSL_SM2 - if (key->dp->id == ECC_SM2P256V1) - ssl->buffers.keyType = sm2_sa_algo; - else - #endif - ssl->buffers.keyType = ecc_dsa_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->haveStaticECC = 1; - ctx->privateKeyType = ecc_dsa_sa_algo; - #ifdef WOLFSSL_SM2 - if (key->dp->id == ECC_SM2P256V1) - ctx->privateKeyType = sm2_sa_algo; - else - #endif - ctx->privateKeyType = ecc_dsa_sa_algo; - ctx->privateKeySz = *keySz; - } - - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } - - wc_ecc_free(key); +int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) +{ + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb); } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ECC); -#endif - return ret; + else + return BAD_FUNC_ARG; } -#endif /* HAVE_ECC */ -#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) -static int ProcessBufferTryDecodeEd25519(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int devId) +#ifdef HAVE_CRL_IO +int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) { - int ret; - /* make sure Ed25519 key can be used */ -#ifdef WOLFSSL_SMALL_STACK - ed25519_key* key; -#else - ed25519_key key[1]; + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) { + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerSetCRL_IOCb(SSL_CM(ssl), cb); + } + else + return BAD_FUNC_ARG; +} #endif -#ifdef WOLFSSL_SMALL_STACK - key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, - DYNAMIC_TYPE_ED25519); - if (key == NULL) - return MEMORY_E; -#endif +int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL"); + if (ctx) + return wolfSSL_CertManagerEnableCRL(ctx->cm, options); + else + return BAD_FUNC_ARG; +} - ret = wc_ed25519_init_ex(key, heap, devId); - if (ret == 0) { - *idx = 0; - ret = wc_Ed25519PrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || ((ssl == NULL) ? wolfSSL_CTX_IsPrivatePkSet(ctx) : - wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_Ed25519PublicKeyDecode(der->buffer, idx, key, der->length); - } - #endif - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; - *keySz = ED25519_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("ED25519 private key too small"); - ret = ECC_KEY_SIZE_E; - } - if (ret == 0) { - if (ssl) { - ssl->buffers.keyType = ed25519_sa_algo; - ssl->buffers.keySz = *keySz; - } - else { - ctx->privateKeyType = ed25519_sa_algo; - ctx->privateKeySz = *keySz; - } - *keyFormat = ED25519k; - if (ssl != NULL) { -#if !defined(WOLFSSL_NO_CLIENT_AUTH) && !defined(NO_ED25519_CLIENT_AUTH) - /* ED25519 requires caching enabled for tracking message - * hash used in EdDSA_Update for signing */ - ssl->options.cacheMessages = 1; -#endif - if (ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } +int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL"); + if (ctx) + return wolfSSL_CertManagerDisableCRL(ctx->cm); + else + return BAD_FUNC_ARG; +} - wc_ed25519_free(key); - } -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ED25519); -#endif - return ret; +#ifndef NO_FILESYSTEM +int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, + int type, int monitor) +{ + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); + if (ctx) + return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor); + else + return BAD_FUNC_ARG; } -#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ -#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) -static int ProcessBufferTryDecodeEd448(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int devId) +int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file, + int type) { - int ret; - /* make sure Ed448 key can be used */ -#ifdef WOLFSSL_SMALL_STACK - ed448_key* key = NULL; -#else - ed448_key key[1]; + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); + if (ctx) + return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type); + else + return BAD_FUNC_ARG; +} #endif -#ifdef WOLFSSL_SMALL_STACK - key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); - if (key == NULL) - return MEMORY_E; + +int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb); + else + 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 - ret = wc_ed448_init_ex(key, heap, devId); - if (ret == 0) { - *idx = 0; - ret = wc_Ed448PrivateKeyDecode(der->buffer, idx, key, der->length); - #ifdef WOLF_PRIVATE_KEY_ID - if (ret != 0 && (devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || ((ssl == NULL) ? wolfSSL_CTX_IsPrivatePkSet(ctx) : - wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) - #endif - )) { - /* if using crypto or PK callbacks, try public key decode */ - *idx = 0; - ret = wc_Ed448PublicKeyDecode(der->buffer, idx, key, der->length); - } - #endif - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; - *keySz = ED448_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("ED448 private key too small"); - ret = ECC_KEY_SIZE_E; - } - } - if (ret == 0) { - if (ssl) { - ssl->buffers.keyType = ed448_sa_algo; - ssl->buffers.keySz = *keySz; - } - else if (ctx) { - ctx->privateKeyType = ed448_sa_algo; - ctx->privateKeySz = *keySz; - } - - *keyFormat = ED448k; - if (ssl != NULL) { - /* ED448 requires caching enabled for tracking message - * hash used in EdDSA_Update for signing */ - ssl->options.cacheMessages = 1; - if (ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } - wc_ed448_free(key); +#endif /* HAVE_CRL */ + + +/* Sets the max chain depth when verifying a certificate chain. Default depth + * is set to MAX_CHAIN_DEPTH. + * + * ctx WOLFSSL_CTX structure to set depth in + * depth max depth + */ +void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { + WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); + + if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) { + WOLFSSL_MSG("Bad depth argument, too large or less than 0"); + return; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(key, heap, DYNAMIC_TYPE_ED448); -#endif - return ret; + ctx->verifyDepth = (byte)depth; } -#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ -#if defined(HAVE_PQC) -#if defined(HAVE_FALCON) -static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int type) + +/* get cert chaining depth using ssl struct */ +long wolfSSL_get_verify_depth(WOLFSSL* ssl) { - int ret; - /* make sure Falcon key can be used */ - falcon_key* key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, - DYNAMIC_TYPE_FALCON); - (void) type; - if (key == NULL) { - return MEMORY_E; + if(ssl == NULL) { + return BAD_FUNC_ARG; } - ret = wc_falcon_init(key); - if (ret == 0) { - if (*keyFormat == FALCON_LEVEL1k) { - ret = wc_falcon_set_level(key, 1); - } - else if (*keyFormat == FALCON_LEVEL5k) { - ret = wc_falcon_set_level(key, 5); - } - else { - /* What if *keyformat is 0? We might want to do something more - * graceful here. */ - wc_falcon_free(key); - ret = ALGO_ID_E; - } +#ifndef OPENSSL_EXTRA + return MAX_CHAIN_DEPTH; +#else + return ssl->options.verifyDepth; +#endif +} + + +/* get cert chaining depth using ctx struct */ +long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; } +#ifndef OPENSSL_EXTRA + return MAX_CHAIN_DEPTH; +#else + return ctx->verifyDepth; +#endif +} - if (ret == 0) { - *idx = 0; - ret = wc_falcon_import_private_only(der->buffer, der->length, key); - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minFalconKeySz : - ctx->minFalconKeySz; - *keySz = FALCON_MAX_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("Falcon private key too small"); - ret = FALCON_KEY_SIZE_E; - } - if (ssl) { -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (type == ALT_PRIVATEKEY_TYPE) { - if (*keyFormat == FALCON_LEVEL1k) { - ssl->buffers.altKeyType = falcon_level1_sa_algo; - } - else { - ssl->buffers.altKeyType = falcon_level5_sa_algo; - } - ssl->buffers.altKeySz = *keySz; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - { - if (*keyFormat == FALCON_LEVEL1k) { - ssl->buffers.keyType = falcon_level1_sa_algo; - } - else { - ssl->buffers.keyType = falcon_level5_sa_algo; - } - ssl->buffers.keySz = *keySz; - } - } - else { -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (type == ALT_PRIVATEKEY_TYPE) { - if (*keyFormat == FALCON_LEVEL1k) { - ctx->altPrivateKeyType = falcon_level1_sa_algo; - } - else { - ctx->altPrivateKeyType = falcon_level5_sa_algo; - } - ctx->altPrivateKeySz = *keySz; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - { - if (*keyFormat == FALCON_LEVEL1k) { - ctx->privateKeyType = falcon_level1_sa_algo; - } - else { - ctx->privateKeyType = falcon_level5_sa_algo; - } - ctx->privateKeySz = *keySz; - } - } +#ifndef NO_CHECK_PRIVATE_KEY - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } - } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ - } +#ifdef WOLF_PRIVATE_KEY_ID +/* Check private against public in certificate for match using external + * device with given devId */ +static int check_cert_key_dev(word32 keyOID, byte* privKey, word32 privSz, + const byte* pubKey, word32 pubSz, int label, int id, void* heap, int devId) +{ + int ret = 0; + int type = 0; + void *pkey = NULL; - wc_falcon_free(key); + if (privKey == NULL) { + return MISSING_KEY; } - XFREE(key, heap, DYNAMIC_TYPE_FALCON); - return ret; -} -#endif +#ifndef NO_RSA + if (keyOID == RSAk) { + type = DYNAMIC_TYPE_RSA; + } +#ifdef WC_RSA_PSS + if (keyOID == RSAPSSk) { + type = DYNAMIC_TYPE_RSA; + } +#endif +#endif +#ifdef HAVE_ECC + if (keyOID == ECDSAk) { + type = DYNAMIC_TYPE_ECC; + } +#endif #if defined(HAVE_DILITHIUM) -static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int type) -{ - int ret; - /* make sure Dilithium key can be used */ - dilithium_key* key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap, - DYNAMIC_TYPE_DILITHIUM); - (void) type; - if (key == NULL) { - return MEMORY_E; + if ((keyOID == DILITHIUM_LEVEL2k) || + (keyOID == DILITHIUM_LEVEL3k) || + (keyOID == DILITHIUM_LEVEL5k)) { + type = DYNAMIC_TYPE_DILITHIUM; + } +#endif +#if defined(HAVE_FALCON) + if ((keyOID == FALCON_LEVEL1k) || + (keyOID == FALCON_LEVEL5k)) { + type = DYNAMIC_TYPE_FALCON; } - ret = wc_dilithium_init(key); +#endif + + ret = CreateDevPrivateKey(&pkey, privKey, privSz, type, label, id, + heap, devId); + #ifdef WOLF_CRYPTO_CB if (ret == 0) { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ret = wc_dilithium_set_level(key, 2); + #ifndef NO_RSA + if (keyOID == RSAk + #ifdef WC_RSA_PSS + || keyOID == RSAPSSk + #endif + ) { + ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, pubKey, pubSz); } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ret = wc_dilithium_set_level(key, 3); + #endif + #ifdef HAVE_ECC + if (keyOID == ECDSAk) { + ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, pubKey, pubSz); } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ret = wc_dilithium_set_level(key, 5); + #endif + #if defined(HAVE_DILITHIUM) + if ((keyOID == DILITHIUM_LEVEL2k) || + (keyOID == DILITHIUM_LEVEL3k) || + (keyOID == DILITHIUM_LEVEL5k)) { + ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, + WC_PQC_SIG_TYPE_DILITHIUM, + pubKey, pubSz); } - else { - /* What if *keyformat is 0? We might want to do something more - * graceful here. */ - wc_dilithium_free(key); - ret = ALGO_ID_E; + #endif + #if defined(HAVE_FALCON) + if ((keyOID == FALCON_LEVEL1k) || + (keyOID == FALCON_LEVEL5k)) { + ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, + WC_PQC_SIG_TYPE_FALCON, + pubKey, pubSz); } + #endif } - - if (ret == 0) { - *idx = 0; - ret = wc_dilithium_import_private_only(der->buffer, der->length, key); - if (ret == 0) { - /* check for minimum key size and then free */ - int minKeySz = ssl ? ssl->options.minDilithiumKeySz : - ctx->minDilithiumKeySz; - *keySz = DILITHIUM_MAX_KEY_SIZE; - if (*keySz < minKeySz) { - WOLFSSL_MSG("Dilithium private key too small"); - ret = DILITHIUM_KEY_SIZE_E; - } - if (ssl) { -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (type == ALT_PRIVATEKEY_TYPE) { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ssl->buffers.altKeyType = dilithium_level2_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ssl->buffers.altKeyType = dilithium_level3_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ssl->buffers.altKeyType = dilithium_level5_sa_algo; - } - ssl->buffers.altKeySz = *keySz; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ssl->buffers.keyType = dilithium_level2_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ssl->buffers.keyType = dilithium_level3_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ssl->buffers.keyType = dilithium_level5_sa_algo; - } - ssl->buffers.keySz = *keySz; - } - } - else { -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (type == ALT_PRIVATEKEY_TYPE) { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ctx->altPrivateKeyType = dilithium_level2_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ctx->altPrivateKeyType = dilithium_level3_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ctx->altPrivateKeyType = dilithium_level5_sa_algo; - } - ctx->altPrivateKeySz = *keySz; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - { - if (*keyFormat == DILITHIUM_LEVEL2k) { - ctx->privateKeyType = dilithium_level2_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL3k) { - ctx->privateKeyType = dilithium_level3_sa_algo; - } - else if (*keyFormat == DILITHIUM_LEVEL5k) { - ctx->privateKeyType = dilithium_level5_sa_algo; - } - ctx->privateKeySz = *keySz; - } - } - - if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { - *resetSuites = 1; - } + #else + /* devId was set, don't check, for now */ + /* TODO: Add callback for private key check? */ + (void) pubKey; + (void) pubSz; + #endif + if (pkey != NULL) { + #ifndef NO_RSA + if (keyOID == RSAk + #ifdef WC_RSA_PSS + || keyOID == RSAPSSk + #endif + ) { + wc_FreeRsaKey((RsaKey*)pkey); } - else if (*keyFormat == 0) { - ret = 0; /* continue trying other algorithms */ + #endif + #ifdef HAVE_ECC + if (keyOID == ECDSAk) { + wc_ecc_free((ecc_key*)pkey); } - - wc_dilithium_free(key); + #endif + #if defined(HAVE_DILITHIUM) + if ((keyOID == DILITHIUM_LEVEL2k) || + (keyOID == DILITHIUM_LEVEL3k) || + (keyOID == DILITHIUM_LEVEL5k)) { + wc_dilithium_free((dilithium_key*)pkey); + } + #endif + #if defined(HAVE_FALCON) + if ((keyOID == FALCON_LEVEL1k) || + (keyOID == FALCON_LEVEL5k)) { + wc_falcon_free((falcon_key*)pkey); + } + #endif + XFREE(pkey, heap, type); } - XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); return ret; } -#endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ +#endif /* WOLF_PRIVATE_KEY_ID */ -static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - DerBuffer* der, int* keySz, word32* idx, int* resetSuites, int* keyFormat, - void* heap, int devId, int type) +/* Check private against public in certificate for match + * + * Returns WOLFSSL_SUCCESS on good private key + * WOLFSSL_FAILURE if mismatched */ +static int check_cert_key(DerBuffer* cert, DerBuffer* key, DerBuffer* altKey, + void* heap, int devId, int isKeyLabel, int isKeyId, int altDevId, + int isAltKeyLabel, int isAltKeyId) { - int ret = 0; - - (void)heap; - (void)devId; - (void)type; - - if (ctx == NULL && ssl == NULL) - return BAD_FUNC_ARG; - if (!der || !keySz || !idx || !resetSuites || !keyFormat) - return BAD_FUNC_ARG; - -#ifndef NO_RSA - if ((*keyFormat == 0 || *keyFormat == RSAk)) { -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION > 2)) - ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keySz, idx, resetSuites, - keyFormat, devId); +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* der = NULL; #else - ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keySz, idx, resetSuites, - keyFormat, heap, devId); + DecodedCert der[1]; #endif - if (ret != 0) - return ret; + word32 size; + byte* buff; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("check_cert_key"); + + if (cert == NULL || key == NULL) { + return WOLFSSL_FAILURE; } + +#ifdef WOLFSSL_SMALL_STACK + der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, DYNAMIC_TYPE_DCERT); + if (der == NULL) + return MEMORY_E; #endif -#ifdef HAVE_ECC - if ((*keyFormat == 0) || (*keyFormat == ECDSAk) - #ifdef WOLFSSL_SM2 - || (*keyFormat == SM2k) + + size = cert->length; + buff = cert->buffer; + InitDecodedCert_ex(der, buff, size, heap, devId); + if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) { + FreeDecodedCert(der); + #ifdef WOLFSSL_SMALL_STACK + XFREE(der, heap, DYNAMIC_TYPE_DCERT); #endif - ) { - ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keySz, idx, resetSuites, - keyFormat, heap, devId); - if (ret != 0) - return ret; + return WOLFSSL_FAILURE; } -#endif /* HAVE_ECC */ -#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) - if ((*keyFormat == 0 || *keyFormat == ED25519k)) { - ret = ProcessBufferTryDecodeEd25519(ctx, ssl, der, keySz, idx, - resetSuites, keyFormat, heap, devId); - if (ret != 0) - return ret; + + size = key->length; + buff = key->buffer; +#ifdef WOLF_PRIVATE_KEY_ID + if (devId != INVALID_DEVID) { + ret = check_cert_key_dev(der->keyOID, buff, size, der->publicKey, + der->pubKeySize, isKeyLabel, isKeyId, heap, + devId); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; + } } -#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ -#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) - if ((*keyFormat == 0 || *keyFormat == ED448k)) { - ret = ProcessBufferTryDecodeEd448(ctx, ssl, der, keySz, idx, - resetSuites, keyFormat, heap, devId); - if (ret != 0) - return ret; + else { + /* fall through if unavailable */ + ret = CRYPTOCB_UNAVAILABLE; } -#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ -#if defined(HAVE_PQC) -#if defined(HAVE_FALCON) - if (((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) || - (*keyFormat == FALCON_LEVEL5k))) { - ret = ProcessBufferTryDecodeFalcon(ctx, ssl, der, keySz, idx, - resetSuites, keyFormat, heap, type); - if (ret != 0) - return ret; + + if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) +#endif /* WOLF_PRIVATE_KEY_ID */ + { + ret = wc_CheckPrivateKeyCert(buff, size, der, 0); + ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; } -#endif /* HAVE_FALCON */ -#if defined(HAVE_DILITHIUM) - if ((*keyFormat == 0) || - (*keyFormat == DILITHIUM_LEVEL2k) || - (*keyFormat == DILITHIUM_LEVEL3k) || - (*keyFormat == DILITHIUM_LEVEL5k)) { - ret = ProcessBufferTryDecodeDilithium(ctx, ssl, der, keySz, idx, - resetSuites, keyFormat, heap, type); - if (ret != 0) { - return ret; + +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (ret == WOLFSSL_SUCCESS && der->extSapkiSet && der->sapkiDer != NULL) { + /* Certificate contains an alternative public key. Hence, we also + * need an alternative private key. */ + if (altKey == NULL) { + ret = MISSING_KEY; + buff = NULL; + size = 0; + } + else { + size = altKey->length; + buff = altKey->buffer; + } +#ifdef WOLF_PRIVATE_KEY_ID + if (ret == WOLFSSL_SUCCESS && altDevId != INVALID_DEVID) { + /* We have to decode the public key first */ + word32 idx = 0; + /* Dilithium has the largest public key at the moment */ + word32 pubKeyLen = DILITHIUM_MAX_PUB_KEY_SIZE; + byte* decodedPubKey = (byte*)XMALLOC(pubKeyLen, heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (decodedPubKey == NULL) { + ret = MEMORY_E; + } + if (ret == WOLFSSL_SUCCESS) { + if (der->sapkiOID == RSAk || der->sapkiOID == ECDSAk) { + /* Simply copy the data */ + XMEMCPY(decodedPubKey, der->sapkiDer, der->sapkiLen); + pubKeyLen = der->sapkiLen; + ret = 0; + } + else { + ret = DecodeAsymKeyPublic(der->sapkiDer, &idx, + der->sapkiLen, decodedPubKey, + &pubKeyLen, der->sapkiOID); + } + } + if (ret == 0) { + ret = check_cert_key_dev(der->sapkiOID, buff, size, + decodedPubKey, pubKeyLen, + isAltKeyLabel, isAltKeyId, + heap, altDevId); + } + XFREE(decodedPubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { + ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; + } + } + else { + /* fall through if unavailable */ + ret = CRYPTOCB_UNAVAILABLE; + } + + if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) +#endif /* WOLF_PRIVATE_KEY_ID */ + { + ret = wc_CheckPrivateKeyCert(buff, size, der, 1); + ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; } } -#endif /* HAVE_DILITHIUM */ -#endif /* HAVE_PQC */ +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + FreeDecodedCert(der); +#ifdef WOLFSSL_SMALL_STACK + XFREE(der, heap, DYNAMIC_TYPE_DCERT); +#endif + + (void)devId; + (void)isKeyLabel; + (void)isKeyId; + (void)altKey; + (void)altDevId; + (void)isAltKeyLabel; + (void)isAltKeyId; + return ret; } -/* process the buffer buff, length sz, into ctx of format and type - used tracks bytes consumed, userChain specifies a user cert chain - to pass during the handshake */ -int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, - long sz, int format, int type, WOLFSSL* ssl, - long* used, int userChain, int verify) -{ - DerBuffer* der = NULL; - int ret = 0; - int done = 0; - int keyFormat = 0; - int resetSuites = 0; - void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); - int devId = wolfSSL_CTX_GetDevId(ctx, ssl); - word32 idx = 0; - int keySz = 0; -#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \ - defined(HAVE_PKCS8) - word32 algId = 0; +/* Check private against public in certificate for match + * + * ctx WOLFSSL_CTX structure to check private key in + * + * Returns WOLFSSL_SUCCESS on good private key + * WOLFSSL_FAILURE if mismatched. */ +int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) +{ + int res; + + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_DUAL_ALG_CERTS +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); + wolfssl_priv_der_unblind(ctx->altPrivateKey, ctx->altPrivateKeyMask); +#endif + res = check_cert_key(ctx->certificate, ctx->privateKey, ctx->altPrivateKey, + ctx->heap, ctx->privateKeyDevId, ctx->privateKeyLabel, + ctx->privateKeyId, ctx->altPrivateKeyDevId, ctx->altPrivateKeyLabel, + ctx->altPrivateKeyId) != 0; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + { + int ret; + ret = wolfssl_priv_der_blind(NULL, ctx->privateKey, + (DerBuffer**)&ctx->privateKeyMask); + if (ret == 0) { + ret = wolfssl_priv_der_blind(NULL, ctx->altPrivateKey, + (DerBuffer**)&ctx->altPrivateKeyMask); + } + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } #endif -#ifdef WOLFSSL_SMALL_STACK - EncryptedInfo* info = NULL; #else - EncryptedInfo info[1]; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); +#endif + res = check_cert_key(ctx->certificate, ctx->privateKey, NULL, ctx->heap, + ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId, + INVALID_DEVID, 0, 0); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + { + int ret = wolfssl_priv_der_blind(NULL, ctx->privateKey, + (DerBuffer**)&ctx->privateKeyMask); + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } +#endif #endif - (void)devId; - (void)idx; - (void)keySz; - - if (used) - *used = sz; /* used bytes default to sz, PEM chain may shorten*/ + return res; +} +#endif /* !NO_CHECK_PRIVATE_KEY */ - /* check args */ - if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM) - return WOLFSSL_BAD_FILETYPE; +#ifdef OPENSSL_ALL +/** + * Return the private key of the WOLFSSL_CTX struct + * @return WOLFSSL_EVP_PKEY* The caller doesn *NOT*` free the returned object. + */ +WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx) +{ + WOLFSSL_EVP_PKEY* res; + const unsigned char *key; + int type; - if (ctx == NULL && ssl == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey"); - /* This API does not handle CHAIN_CERT_TYPE */ - if (type == CHAIN_CERT_TYPE) - return BAD_FUNC_ARG; + if (ctx == NULL || ctx->privateKey == NULL || + ctx->privateKey->buffer == NULL) { + WOLFSSL_MSG("Bad parameter or key not set"); + return NULL; + } -#ifdef WOLFSSL_SMALL_STACK - info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, - DYNAMIC_TYPE_ENCRYPTEDINFO); - if (info == NULL) - return MEMORY_E; + switch (ctx->privateKeyType) { +#ifndef NO_RSA + case rsa_sa_algo: + type = EVP_PKEY_RSA; + break; +#endif +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + type = EVP_PKEY_EC; + break; +#endif +#ifdef WOLFSSL_SM2 + case sm2_sa_algo: + type = EVP_PKEY_EC; + break; #endif + default: + /* Other key types not supported either as ssl private keys + * or in the EVP layer */ + WOLFSSL_MSG("Unsupported key type"); + return NULL; + } - XMEMSET(info, 0, sizeof(EncryptedInfo)); -#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) - if (ctx) { - info->passwd_cb = ctx->passwd_cb; - info->passwd_userdata = ctx->passwd_userdata; + key = ctx->privateKey->buffer; + + if (ctx->privateKeyPKey != NULL) { + res = ctx->privateKeyPKey; + } + else { + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); + #endif + res = wolfSSL_d2i_PrivateKey(type, + (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key, + (long)ctx->privateKey->length); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ctx->privateKey, ctx->privateKeyMask); + #endif } + + return res; +} #endif - if (format == WOLFSSL_FILETYPE_PEM) { - #ifdef WOLFSSL_PEM_TO_DER - ret = PemToDer(buff, sz, type, &der, heap, info, &keyFormat); - #else - ret = NOT_COMPILED_IN; +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + +#if !defined(NO_RSA) +static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) +{ + WOLFSSL_EVP_PKEY* pkey; + word32 keyIdx = 0; + int isRsaKey; + int ret = 1; +#ifndef WOLFSSL_SMALL_STACK + RsaKey rsa[1]; +#else + RsaKey *rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (rsa == NULL) + return 0; +#endif + + XMEMSET(rsa, 0, sizeof(RsaKey)); + + if (wc_InitRsaKey(rsa, NULL) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); #endif + return 0; + } + /* test if RSA key */ + if (priv) { + isRsaKey = + (wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); } else { - /* ASN1 (DER) */ - int length = (int)sz; - word32 inOutIdx = 0; - /* get length of der (read sequence or octet string) */ - if (GetSequence(buff, &inOutIdx, &length, (word32)sz) >= 0) { - length += inOutIdx; /* include leading sequence */ - } - /* get length using octet string (allowed for private key types) */ - else if (type == PRIVATEKEY_TYPE && - GetOctetString(buff, &inOutIdx, &length, (word32)sz) >= 0) { - length += inOutIdx; /* include leading oct string */ - } - else { - ret = ASN_PARSE_E; - } + isRsaKey = + (wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); + } + wc_FreeRsaKey(rsa); +#ifdef WOLFSSL_SMALL_STACK + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); +#endif - info->consumed = length; + if (!isRsaKey) { + return -1; + } - if (ret == 0) { - ret = AllocDer(&der, (word32)length, type, heap); - if (ret == 0) { - XMEMCPY(der->buffer, buff, length); - } - - #ifdef HAVE_PKCS8 - /* if private key try and remove PKCS8 header */ - if (ret == 0 && type == PRIVATEKEY_TYPE) { - if ((ret = ToTraditional_ex(der->buffer, der->length, - &algId)) > 0) { - /* Found PKCS8 header */ - /* ToTraditional_ex moves buff and returns adjusted length */ - der->length = ret; - keyFormat = algId; - } - ret = 0; /* failures should be ignored */ - } - #endif + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error"); + return 0; } } - if (used) { - *used = info->consumed; + pkey->pkey_sz = (int)keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + priv ? DYNAMIC_TYPE_PRIVATE_KEY : + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + ret = 0; } + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; - /* process user chain */ - if (ret >= 0) { - /* Chain should have server cert first, then intermediates, then root. - * First certificate in chain is processed below after ProcessUserChain - * and is loaded into ssl->buffers.certificate. - * Remainder are processed using ProcessUserChain and are loaded into - * ssl->buffers.certChain. */ - if (userChain) { - ret = ProcessUserChain(ctx, buff, sz, format, CHAIN_CERT_TYPE, ssl, - used, info, verify); - if (ret == ASN_NO_PEM_HEADER) { /* Additional chain is optional */ - unsigned long pemErr = 0; - CLEAR_ASN_NO_PEM_HEADER_ERROR(pemErr); - ret = 0; - } + pkey->ownRsa = 1; + pkey->rsa = wolfssl_rsa_d2i(NULL, mem, memSz, + priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC); + if (pkey->rsa == NULL) { + ret = 0; } } - /* info is only used for private key with DER or PEM, so free now */ - if (ret < 0 || type != PRIVATEKEY_TYPE) { + if (ret == 1) { + *out = pkey; + } + + if ((ret == 0) && (*out == NULL)) { + wolfSSL_EVP_PKEY_free(pkey); + } + return ret; +} +#endif /* !NO_RSA */ + +#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) +static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) +{ + WOLFSSL_EVP_PKEY* pkey; + word32 keyIdx = 0; + int isEccKey; + int ret = 1; +#ifndef WOLFSSL_SMALL_STACK + ecc_key ecc[1]; +#else + ecc_key *ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, + DYNAMIC_TYPE_ECC); + if (ecc == NULL) + return 0; +#endif + + XMEMSET(ecc, 0, sizeof(ecc_key)); + + if (wc_ecc_init(ecc) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + XFREE(ecc, NULL, DYNAMIC_TYPE_ECC); #endif + return 0; } - /* check for error */ - if (ret < 0) { - FreeDer(&der); - done = 1; + if (priv) { + isEccKey = + (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); + } + else { + isEccKey = + (wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); } + wc_ecc_free(ecc); +#ifdef WOLFSSL_SMALL_STACK + XFREE(ecc, NULL, DYNAMIC_TYPE_ECC); +#endif - if (done == 1) { - /* No operation, just skip the next section */ + if (!isEccKey) { + return -1; } - /* Handle DER owner */ - else if (type == CA_TYPE) { - if (ctx == NULL) { - WOLFSSL_MSG("Need context for CA load"); - FreeDer(&der); - return BAD_FUNC_ARG; - } - /* verify CA unless user set to no verify */ - ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify); - done = 1; + + if (*out != NULL) { + pkey = *out; } -#ifdef WOLFSSL_TRUST_PEER_CERT - else if (type == TRUSTED_PEER_TYPE) { - /* add trusted peer cert. der is freed within */ - if (ctx != NULL) - ret = AddTrustedPeer(ctx->cm, &der, verify); - else { - SSL_CM_WARNING(ssl); - ret = AddTrustedPeer(SSL_CM(ssl), &der, verify); - } - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error adding trusted peer"); + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error"); + return 0; } - done = 1; } -#endif /* WOLFSSL_TRUST_PEER_CERT */ - else if (type == CERT_TYPE) { - if (ssl != NULL) { - /* Make sure previous is free'd */ - if (ssl->buffers.weOwnCert) { - FreeDer(&ssl->buffers.certificate); - #ifdef KEEP_OUR_CERT - wolfSSL_X509_free(ssl->ourCert); - ssl->ourCert = NULL; - #endif - } - ssl->buffers.certificate = der; - #ifdef KEEP_OUR_CERT - ssl->keepCert = 1; /* hold cert for ssl lifetime */ - #endif - ssl->buffers.weOwnCert = 1; - } - else if (ctx != NULL) { - FreeDer(&ctx->certificate); /* Make sure previous is free'd */ - #ifdef KEEP_OUR_CERT - if (ctx->ourCert) { - if (ctx->ownOurCert) - wolfSSL_X509_free(ctx->ourCert); - ctx->ourCert = NULL; - } - #endif - ctx->certificate = der; - } + + pkey->pkey_sz = (int)keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, + priv ? DYNAMIC_TYPE_PRIVATE_KEY : + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + ret = 0; } - else if (type == PRIVATEKEY_TYPE) { - if (ssl != NULL) { - /* Make sure previous is free'd */ - if (ssl->buffers.weOwnKey) { - ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); - FreeDer(&ssl->buffers.key); - } - ssl->buffers.key = der; -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("SSL Buffers key", der->buffer, der->length); -#endif - ssl->buffers.weOwnKey = 1; - } - else if (ctx != NULL) { - if (ctx->privateKey != NULL && ctx->privateKey->buffer != NULL) { - ForceZero(ctx->privateKey->buffer, ctx->privateKey->length); - } - FreeDer(&ctx->privateKey); - ctx->privateKey = der; -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("CTX private key", der->buffer, der->length); -#endif + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; + + pkey->ownEcc = 1; + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc == NULL) { + ret = 0; } } -#ifdef WOLFSSL_DUAL_ALG_CERTS - else if (type == ALT_PRIVATEKEY_TYPE) { - if (ssl != NULL) { - /* Make sure previous is free'd */ - if (ssl->buffers.weOwnAltKey) { - ForceZero(ssl->buffers.altKey->buffer, - ssl->buffers.altKey->length); - FreeDer(&ssl->buffers.altKey); - } - ssl->buffers.altKey = der; -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("SSL Buffers key", der->buffer, der->length); -#endif - ssl->buffers.weOwnAltKey = 1; - } - else if (ctx != NULL) { - if (ctx->altPrivateKey != NULL && - ctx->altPrivateKey->buffer != NULL) { - ForceZero(ctx->altPrivateKey->buffer, - ctx->altPrivateKey->length); - } - FreeDer(&ctx->altPrivateKey); - ctx->altPrivateKey = der; -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("CTX private key", der->buffer, der->length); + if ((ret == 1) && (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE + : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) { + ret = 0; + } + if (ret == 1) { + *out = pkey; + } + + if ((ret == 0) && (*out == NULL)) { + wolfSSL_EVP_PKEY_free(pkey); + } + return ret; +} +#endif /* HAVE_ECC && OPENSSL_EXTRA */ + +#if !defined(NO_DSA) +static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) +{ + WOLFSSL_EVP_PKEY* pkey; + word32 keyIdx = 0; + int isDsaKey; + int ret = 1; +#ifndef WOLFSSL_SMALL_STACK + DsaKey dsa[1]; +#else + DsaKey *dsa = (DsaKey*)XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA); + if (dsa == NULL) + return 0; #endif - } + + XMEMSET(dsa, 0, sizeof(DsaKey)); + + if (wc_InitDsaKey(dsa) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); + #endif + return 0; + } + + if (priv) { + isDsaKey = + (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ else { - FreeDer(&der); - return WOLFSSL_BAD_CERTTYPE; + isDsaKey = + (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); } + wc_FreeDsaKey(dsa); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); +#endif - if (done == 1) { - /* No operation, just skip the next section */ + /* test if DSA key */ + if (!isDsaKey) { + return -1; } - else if (type == PRIVATEKEY_TYPE -#ifdef WOLFSSL_DUAL_ALG_CERTS - || type == ALT_PRIVATEKEY_TYPE -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - ) { - ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites, - &keyFormat, heap, devId, type); - - #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) - /* for WOLFSSL_FILETYPE_PEM, PemToDer manages the decryption */ - /* If private key type PKCS8 header wasn't already removed (algoId == 0) */ - if ((ret != 0 || keyFormat == 0) - && format != WOLFSSL_FILETYPE_PEM && info->passwd_cb && algId == 0) - { - int passwordSz = NAME_SZ; - #ifndef WOLFSSL_SMALL_STACK - char password[NAME_SZ]; - #else - char* password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING); - if (password == NULL) { - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); - FreeDer(&der); - return MEMORY_E; - } - #endif - /* get password */ - ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ, - info->passwd_userdata); - if (ret >= 0) { - passwordSz = ret; - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("ProcessBuffer password", password, passwordSz); - #endif - /* PKCS8 decrypt */ - ret = ToTraditionalEnc(der->buffer, der->length, - password, passwordSz, &algId); - if (ret >= 0) { - ForceZero(der->buffer + ret, der->length - ret); - der->length = ret; - } - /* ignore failures and try parsing as unencrypted */ + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error"); + return 0; + } + } - ForceZero(password, passwordSz); - } + pkey->pkey_sz = (int)keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + priv ? DYNAMIC_TYPE_PRIVATE_KEY : + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + ret = 0; + } + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_DSA; - #ifdef WOLFSSL_SMALL_STACK - XFREE(password, heap, DYNAMIC_TYPE_STRING); - #elif defined(WOLFSSL_CHECK_MEM_ZERO) - wc_MemZero_Check(password, NAME_SZ); - #endif - ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, - &resetSuites, &keyFormat, heap, devId, type); + pkey->ownDsa = 1; + pkey->dsa = wolfSSL_DSA_new(); + if (pkey->dsa == NULL) { + ret = 0; } - #endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + } - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); - #endif - return ret; - } - if (keyFormat == 0) { -#ifdef OPENSSL_EXTRA - /* Reaching this point probably means that the - * decryption password is wrong */ - if (info->passwd_cb) - EVPerr(0, EVP_R_BAD_DECRYPT); + if ((ret == 1) && (wolfSSL_DSA_LoadDer_ex(pkey->dsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE + : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) { + ret = 0; + } + if (ret == 1) { + *out = pkey; + } + + if ((ret == 0) && (*out == NULL)) { + wolfSSL_EVP_PKEY_free(pkey); + } + return ret; +} +#endif /* NO_DSA */ + +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) +static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) +{ + WOLFSSL_EVP_PKEY* pkey; + int isDhKey; + word32 keyIdx = 0; + int ret = 1; +#ifndef WOLFSSL_SMALL_STACK + DhKey dh[1]; +#else + DhKey *dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); + if (dh == NULL) + return 0; #endif - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); - #endif - WOLFSSL_ERROR(WOLFSSL_BAD_FILE); - return WOLFSSL_BAD_FILE; - } + XMEMSET(dh, 0, sizeof(DhKey)); + + if (wc_InitDhKey(dh) != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + XFREE(dh, NULL, DYNAMIC_TYPE_DH); #endif + return 0; + } + + isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0); + wc_FreeDhKey(dh); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dh, NULL, DYNAMIC_TYPE_DH); +#endif - (void)devId; + /* test if DH key */ + if (!isDhKey) { + return -1; } - else if (type == CERT_TYPE) { - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert; - #else - DecodedCert cert[1]; - #endif - #ifdef WOLF_PRIVATE_KEY_ID - int keyType = 0; - #endif - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, - DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return MEMORY_E; - #endif + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("DH wolfSSL_EVP_PKEY_new error"); + return 0; + } + } - WOLFSSL_MSG("Checking cert signature type"); - InitDecodedCert_ex(cert, der->buffer, der->length, heap, devId); + pkey->pkey_sz = (int)memSz; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + priv ? DYNAMIC_TYPE_PRIVATE_KEY : + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + ret = 0; + } + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, memSz); + pkey->type = EVP_PKEY_DH; - if (DecodeToKey(cert, 0) < 0) { - WOLFSSL_MSG("Decode to key failed"); - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, heap, DYNAMIC_TYPE_DCERT); - #endif - return WOLFSSL_BAD_FILE; + pkey->ownDh = 1; + pkey->dh = wolfSSL_DH_new(); + if (pkey->dh == NULL) { + ret = 0; } -#if defined(HAVE_RPK) - if (ssl) { - ssl->options.rpkState.isRPKLoaded = 0; - if (cert->isRPK) { - ssl->options.rpkState.isRPKLoaded = 1; - } + } + + if ((ret == 1) && (wolfSSL_DH_LoadDer(pkey->dh, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz) != WOLFSSL_SUCCESS)) { + ret = 0; + } + if (ret == 1) { + *out = pkey; + } + + if ((ret == 0) && (*out == NULL)) { + wolfSSL_EVP_PKEY_free(pkey); + } + return ret; +} +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ + +#if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) +static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) +{ + WOLFSSL_EVP_PKEY* pkey; + word32 keyIdx = 0; + DhKey* key = NULL; + int elements; + int ret; +#ifndef WOLFSSL_SMALL_STACK + DhKey dh[1]; +#else + DhKey* dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); + if (dh == NULL) + return 0; +#endif + XMEMSET(dh, 0, sizeof(DhKey)); + + /* test if DH-public key */ + if (wc_InitDhKey(dh) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dh, NULL, DYNAMIC_TYPE_DH); +#endif + return 0; + } + + ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz); + wc_FreeDhKey(dh); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dh, NULL, DYNAMIC_TYPE_DH); +#endif + + if (ret != 0) { + return -1; + } + + if (*out != NULL) { + pkey = *out; + } + else { + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + return 0; } - else if (ctx) { - ctx->rpkState.isRPKLoaded = 0; - if (cert->isRPK) { - ctx->rpkState.isRPKLoaded = 1; - } + } + + ret = 1; + pkey->type = EVP_PKEY_DH; + pkey->pkey_sz = (int)memSz; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + priv ? DYNAMIC_TYPE_PRIVATE_KEY : + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + ret = 0; + } + if (ret == 1) { + XMEMCPY(pkey->pkey.ptr, mem, memSz); + pkey->ownDh = 1; + pkey->dh = wolfSSL_DH_new(); + if (pkey->dh == NULL) { + ret = 0; } -#endif /* HAVE_RPK */ + } + + if (ret == 1) { + key = (DhKey*)pkey->dh->internal; - if (ssl) { - if (ssl->options.side == WOLFSSL_SERVER_END) - resetSuites = 1; + keyIdx = 0; + if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) { + ret = 0; } - else if (ctx && ctx->method->side == WOLFSSL_SERVER_END) { - resetSuites = 1; + } + + if (ret == 1) { + elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; + if (priv) { + elements |= ELEMENT_PRV; } - 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 */ + if (SetDhExternal_ex(pkey->dh, elements) != WOLFSSL_SUCCESS ) { + ret = 0; } + } + if (ret == 1) { + *out = pkey; + } - switch (cert->signatureOID) { - case CTC_SHAwECDSA: - case CTC_SHA256wECDSA: - case CTC_SHA384wECDSA: - case CTC_SHA512wECDSA: - case CTC_ED25519: - case CTC_ED448: - #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - case CTC_SM3wSM2: - #endif - WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature"); - if (ssl) - ssl->options.haveECDSAsig = 1; - else if (ctx) - ctx->haveECDSAsig = 1; - break; - case CTC_FALCON_LEVEL1: - case CTC_FALCON_LEVEL5: - WOLFSSL_MSG("Falcon cert signature"); - if (ssl) - ssl->options.haveFalconSig = 1; - else if (ctx) - ctx->haveFalconSig = 1; - break; - case CTC_DILITHIUM_LEVEL2: - case CTC_DILITHIUM_LEVEL3: - case CTC_DILITHIUM_LEVEL5: - WOLFSSL_MSG("Dilithium cert signature"); - if (ssl) - ssl->options.haveDilithiumSig = 1; - else if (ctx) - ctx->haveDilithiumSig = 1; - break; - default: - WOLFSSL_MSG("Not ECDSA cert signature"); - break; - } + if ((ret == 0) && (*out == NULL)) { + wolfSSL_EVP_PKEY_free(pkey); + } + return ret; +} +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ - #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ - (defined(HAVE_PQC) && defined(HAVE_LIBOQS)) || !defined(NO_RSA) - if (ssl) { - #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - (defined(HAVE_CURVE448) && defined(HAVE_ED448)) - ssl->pkCurveOID = cert->pkCurveOID; - #endif - #ifndef WC_STRICT_SIG - if (cert->keyOID == ECDSAk) { - ssl->options.haveECC = 1; - } - #ifndef NO_RSA - else if (cert->keyOID == RSAk) { - ssl->options.haveRSA = 1; - } - #ifdef WC_RSA_PSS - else if (cert->keyOID == RSAPSSk) { - ssl->options.haveRSA = 1; - } - #endif - #endif - #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - else if (cert->keyOID == SM2k) { - ssl->options.haveECC = 1; - } - #endif - #ifdef HAVE_ED25519 - else if (cert->keyOID == ED25519k) { - ssl->options.haveECC = 1; - } - #endif - #ifdef HAVE_ED448 - else if (cert->keyOID == ED448k) { - ssl->options.haveECC = 1; - } - #endif - #ifdef HAVE_PQC - #ifdef HAVE_FALCON - else if (cert->keyOID == FALCON_LEVEL1k || - cert->keyOID == FALCON_LEVEL5k) { - ssl->options.haveFalconSig = 1; - } - #endif /* HAVE_FALCON */ - #ifdef HAVE_DILITHIUM - else if (cert->keyOID == DILITHIUM_LEVEL2k || - cert->keyOID == DILITHIUM_LEVEL3k || - cert->keyOID == DILITHIUM_LEVEL5k) { - ssl->options.haveDilithiumSig = 1; - } - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ - #else - ssl->options.haveECC = ssl->options.haveECDSAsig; - #endif +#ifdef HAVE_FALCON +static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) +{ + WOLFSSL_EVP_PKEY* pkey; + int isFalcon = 0; +#ifndef WOLFSSL_SMALL_STACK + falcon_key falcon[1]; +#else + falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(falcon_key), NULL, + DYNAMIC_TYPE_FALCON); + if (falcon == NULL) { + return 0; + } +#endif + + if (wc_falcon_init(falcon) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); + #endif + return 0; + } + + /* test if Falcon key */ + if (priv) { + /* Try level 1 */ + isFalcon = ((wc_falcon_set_level(falcon, 1) == 0) && + (wc_falcon_import_private_only(mem, (word32)memSz, + falcon) == 0)); + if (!isFalcon) { + /* Try level 5 */ + isFalcon = ((wc_falcon_set_level(falcon, 5) == 0) && + (wc_falcon_import_private_only(mem, (word32)memSz, + falcon) == 0)); } - else if (ctx) { - #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) - ctx->pkCurveOID = cert->pkCurveOID; - #endif - #ifndef WC_STRICT_SIG - if (cert->keyOID == ECDSAk) { - ctx->haveECC = 1; - } - #ifndef NO_RSA - else if (cert->keyOID == RSAk) { - ctx->haveRSA = 1; - } - #ifdef WC_RSA_PSS - else if (cert->keyOID == RSAPSSk) { - ctx->haveRSA = 1; - } - #endif - #endif - #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - else if (cert->keyOID == SM2k) { - ctx->haveECC = 1; - } - #endif - #ifdef HAVE_ED25519 - else if (cert->keyOID == ED25519k) { - ctx->haveECC = 1; - } - #endif - #ifdef HAVE_ED448 - else if (cert->keyOID == ED448k) { - ctx->haveECC = 1; - } - #endif - #ifdef HAVE_PQC - #ifdef HAVE_FALCON - else if (cert->keyOID == FALCON_LEVEL1k || - cert->keyOID == FALCON_LEVEL5k) { - ctx->haveFalconSig = 1; - } - #endif /* HAVE_FALCON */ - #ifdef HAVE_DILITHIUM - else if (cert->keyOID == DILITHIUM_LEVEL2k || - cert->keyOID == DILITHIUM_LEVEL3k || - cert->keyOID == DILITHIUM_LEVEL5k) { - ctx->haveDilithiumSig = 1; - } - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ - #else - ctx->haveECC = ctx->haveECDSAsig; - #endif + } + else { + /* Try level 1 */ + isFalcon = ((wc_falcon_set_level(falcon, 1) == 0) && + (wc_falcon_import_public(mem, (word32)memSz, falcon) == 0)); + + if (!isFalcon) { + /* Try level 5 */ + isFalcon = ((wc_falcon_set_level(falcon, 5) == 0) && + (wc_falcon_import_public(mem, (word32)memSz, + falcon) == 0)); } - #endif + } + wc_falcon_free(falcon); +#ifdef WOLFSSL_SMALL_STACK + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); +#endif - /* check key size of cert unless specified not to */ - switch (cert->keyOID) { - #ifndef NO_RSA - #ifdef WC_RSA_PSS - case RSAPSSk: - #endif - case RSAk: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = rsa_sa_algo; - #endif - /* Determine RSA key size by parsing public key */ - idx = 0; - ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx, - cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL); - if (ret < 0) - break; - - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minRsaKeySz < 0 || - keySz < (int)ssl->options.minRsaKeySz || - keySz > (RSA_MAX_SIZE / 8)) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Certificate RSA key size too small"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minRsaKeySz < 0 || - keySz < (int)ctx->minRsaKeySz || - keySz > (RSA_MAX_SIZE / 8)) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Certificate RSA key size too small"); - } - } - break; - #endif /* !NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = ecc_dsa_sa_algo; - #endif - /* Determine ECC key size based on curve */ - #ifdef WOLFSSL_CUSTOM_CURVES - if (cert->pkCurveOID == 0 && cert->pkCurveSize != 0) { - keySz = cert->pkCurveSize * 8; - } - else - #endif - { - keySz = wc_ecc_get_curve_size_from_id( - wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL)); - } - - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minEccKeySz < 0 || - keySz < (int)ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate ECC key size error"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minEccKeySz < 0 || - keySz < (int)ctx->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate ECC key size error"); - } - } - break; - #endif /* HAVE_ECC */ - #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - case SM2k: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = sm2_sa_algo; - #endif - /* Determine ECC key size based on curve */ - keySz = wc_ecc_get_curve_size_from_id( - wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL)); - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minEccKeySz < 0 || - keySz < (int)ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Ed key size error"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minEccKeySz < 0 || - keySz < (int)ctx->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate ECC key size error"); - } - } - break; - #endif /* HAVE_ED25519 */ - #ifdef HAVE_ED25519 - case ED25519k: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = ed25519_sa_algo; - #endif - /* ED25519 is fixed key size */ - keySz = ED25519_KEY_SIZE; - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minEccKeySz < 0 || - keySz < (int)ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Ed key size error"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minEccKeySz < 0 || - keySz < (int)ctx->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate ECC key size error"); - } - } - break; - #endif /* HAVE_ED25519 */ - #ifdef HAVE_ED448 - case ED448k: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = ed448_sa_algo; - #endif - /* ED448 is fixed key size */ - keySz = ED448_KEY_SIZE; - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minEccKeySz < 0 || - keySz < (int)ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Ed key size error"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minEccKeySz < 0 || - keySz < (int)ctx->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Certificate ECC key size error"); - } - } - break; - #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) - #if defined(HAVE_FALCON) - case FALCON_LEVEL1k: - case FALCON_LEVEL5k: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = falcon_level5_sa_algo; - #endif - /* Falcon is fixed key size */ - keySz = FALCON_MAX_KEY_SIZE; - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minFalconKeySz < 0 || - keySz < (int)ssl->options.minFalconKeySz) { - ret = FALCON_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Falcon key size error"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minFalconKeySz < 0 || - keySz < (int)ctx->minFalconKeySz) { - ret = FALCON_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Falcon key size error"); - } - } - break; - #endif /* HAVE_FALCON */ - #if defined(HAVE_DILITHIUM) - case DILITHIUM_LEVEL2k: - case DILITHIUM_LEVEL3k: - case DILITHIUM_LEVEL5k: - #ifdef WOLF_PRIVATE_KEY_ID - keyType = dilithium_level5_sa_algo; - #endif - /* Dilithium is fixed key size */ - keySz = DILITHIUM_MAX_KEY_SIZE; - if (ssl && !ssl->options.verifyNone) { - if (ssl->options.minDilithiumKeySz < 0 || - keySz < (int)ssl->options.minDilithiumKeySz) { - ret = DILITHIUM_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Dilithium key size error"); - } - } - else if (ctx && !ctx->verifyNone) { - if (ctx->minDilithiumKeySz < 0 || - keySz < (int)ctx->minDilithiumKeySz) { - ret = DILITHIUM_KEY_SIZE_E; - WOLFSSL_MSG("Certificate Dilithium key size error"); - } - } - break; - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ - - default: - WOLFSSL_MSG("No key size check done on certificate"); - break; /* do no check if not a case for the key */ - } - - #ifdef WOLF_PRIVATE_KEY_ID - if (ssl != NULL) { - ssl->buffers.keyType = (byte)keyType; - ssl->buffers.keySz = keySz; - } - else if (ctx != NULL) { - ctx->privateKeyType = (byte)keyType; - ctx->privateKeySz = keySz; - } - #endif - - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, heap, DYNAMIC_TYPE_DCERT); - #endif - - if (ret != 0) { - done = 1; - } + if (!isFalcon) { + return -1; } - if (done == 1) { - #if !defined(NO_WOLFSSL_CM_VERIFY) && (!defined(NO_WOLFSSL_CLIENT) || \ - !defined(WOLFSSL_NO_CLIENT_AUTH)) - if ((type == CA_TYPE) || (type == CERT_TYPE)) { - /* Call to over-ride status */ - if ((ctx != NULL) && (ctx->cm != NULL) && - (ctx->cm->verifyCallback != NULL)) { - ret = CM_VerifyBuffer_ex(ctx->cm, buff, - sz, format, (ret == WOLFSSL_SUCCESS ? 0 : ret)); - } - } - #endif /* NO_WOLFSSL_CM_VERIFY */ - - return ret; + if (*out != NULL) { + pkey = *out; } - - - if (ssl && resetSuites) { - word16 havePSK = 0; - word16 haveRSA = 0; - - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ssl->options.havePSK) { - havePSK = 1; + else { + /* Create a fake Falcon EVP_PKEY. In the future, we might integrate + * Falcon into the compatibility layer. */ + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("Falcon wolfSSL_EVP_PKEY_new error"); + return 0; } - #endif - #ifndef NO_RSA - haveRSA = 1; - #endif - keySz = ssl->buffers.keySz; - - if (AllocateSuites(ssl) != 0) - return WOLFSSL_FAILURE; - /* let's reset suites */ - InitSuites(ssl->suites, ssl->version, keySz, haveRSA, - havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, - ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, - ssl->options.useAnon, TRUE, ssl->options.side); } - else if (ctx && resetSuites) { - word16 havePSK = 0; - word16 haveRSA = 0; - - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (ctx->havePSK) { - havePSK = 1; - } - #endif - #ifndef NO_RSA - haveRSA = 1; - #endif - keySz = ctx->privateKeySz; + pkey->type = EVP_PKEY_FALCON; + pkey->pkey.ptr = NULL; + pkey->pkey_sz = 0; - if (AllocateCtxSuites(ctx) != 0) - return WOLFSSL_FAILURE; - /* let's reset suites */ - InitSuites(ctx->suites, ctx->method->version, keySz, haveRSA, - havePSK, ctx->haveDH, ctx->haveECDSAsig, - ctx->haveECC, TRUE, ctx->haveStaticECC, - ctx->haveFalconSig, ctx->haveDilithiumSig, -#ifdef HAVE_ANON - ctx->useAnon, -#else - FALSE, -#endif - TRUE, ctx->method->side); - } + *out = pkey; + return 1; - return WOLFSSL_SUCCESS; } +#endif /* HAVE_FALCON */ - -/* CA PEM file for verification, may have multiple/chain certs to process */ -static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, - long sz, int format, int type, WOLFSSL* ssl, int verify) +#ifdef HAVE_DILITHIUM +static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, + long memSz, int priv) { - long used = 0; - int ret = 0; - int gotOne = 0; - - WOLFSSL_MSG("Processing CA PEM file"); - while (used < sz) { - long consumed = 0; + WOLFSSL_EVP_PKEY* pkey; + int isDilithium = 0; +#ifndef WOLFSSL_SMALL_STACK + dilithium_key dilithium[1]; +#else + dilithium_key *dilithium = (dilithium_key *) + XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM); + if (dilithium == NULL) { + return 0; + } +#endif - ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, - &consumed, 0, verify); + if (wc_dilithium_init(dilithium) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); + #endif + return 0; + } - if (ret == MEMORY_E) { - return ret; + /* Test if Dilithium key. Try all levels. */ + if (priv) { + isDilithium = ((wc_dilithium_set_level(dilithium, 2) == 0) && + (wc_dilithium_import_private(mem, + (word32)memSz, dilithium) == 0)); + if (!isDilithium) { + isDilithium = ((wc_dilithium_set_level(dilithium, 3) == 0) && + (wc_dilithium_import_private(mem, + (word32)memSz, dilithium) == 0)); } - else if (ret < 0) { -#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL) - 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(" Processed a CRL"); - wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, - der->length, WOLFSSL_FILETYPE_ASN1); - FreeDer(&der); - used += info.consumed; - continue; - } -#endif - - if (consumed > 0) { /* Made progress in file */ - WOLFSSL_ERROR(ret); - WOLFSSL_MSG("CA Parse failed, with progress in file."); - WOLFSSL_MSG("Search for other certs in file"); - } - else { - WOLFSSL_MSG("CA Parse failed, no progress in file."); - WOLFSSL_MSG("Do not continue search for other certs in file"); - break; - } + if (!isDilithium) { + isDilithium = ((wc_dilithium_set_level(dilithium, 5) == 0) && + (wc_dilithium_import_private(mem, + (word32)memSz, dilithium) == 0)); } - else { - WOLFSSL_MSG(" Processed a CA"); - gotOne = 1; + } + else { + isDilithium = ((wc_dilithium_set_level(dilithium, 2) == 0) && + (wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0)); + if (!isDilithium) { + isDilithium = ((wc_dilithium_set_level(dilithium, 3) == 0) && + (wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0)); + } + if (!isDilithium) { + isDilithium = ((wc_dilithium_set_level(dilithium, 5) == 0) && + (wc_dilithium_import_public(mem, (word32)memSz, + dilithium) == 0)); } - used += consumed; } + wc_dilithium_free(dilithium); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); +#endif - if (gotOne) { - WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK"); - return WOLFSSL_SUCCESS; + if (!isDilithium) { + return -1; } - return ret; -} - - -#ifdef HAVE_CRL - -int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, - long sz, int type) -{ - WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer"); - if (ctx == NULL) - return BAD_FUNC_ARG; + if (*out != NULL) { + pkey = *out; + } + else { + /* Create a fake Dilithium EVP_PKEY. In the future, we might + * integrate Dilithium into the compatibility layer. */ + pkey = wolfSSL_EVP_PKEY_new(); + if (pkey == NULL) { + WOLFSSL_MSG("Dilithium wolfSSL_EVP_PKEY_new error"); + return 0; + } + } + pkey->type = EVP_PKEY_DILITHIUM; + pkey->pkey.ptr = NULL; + pkey->pkey_sz = 0; - return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type); + *out = pkey; + return 1; } +#endif /* HAVE_DILITHIUM */ - -int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, - long sz, int type) +static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out, + const unsigned char** in, long inSz, int priv) { - WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer"); + WOLFSSL_EVP_PKEY* pkey = NULL; - if (ssl == NULL || ssl->ctx == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("d2iGenericKey"); - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerLoadCRLBuffer(SSL_CM(ssl), buff, sz, type); -} + if (in == NULL || *in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } -#endif /* HAVE_CRL */ + if ((out != NULL) && (*out != NULL)) { + pkey = *out; + } -#ifdef HAVE_OCSP -int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options) -{ - WOLFSSL_ENTER("wolfSSL_EnableOCSP"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerEnableOCSP(SSL_CM(ssl), options); +#if !defined(NO_RSA) + if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) { + ; } else - return BAD_FUNC_ARG; -} - -int wolfSSL_DisableOCSP(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_DisableOCSP"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerDisableOCSP(SSL_CM(ssl)); +#endif /* NO_RSA */ +#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) + if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) { + ; } else - return BAD_FUNC_ARG; -} - - -int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerEnableOCSPStapling(SSL_CM(ssl)); +#endif /* HAVE_ECC && OPENSSL_EXTRA */ +#if !defined(NO_DSA) + if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) { + ; } else - return BAD_FUNC_ARG; -} - -int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerDisableOCSPStapling(SSL_CM(ssl)); +#endif /* NO_DSA */ +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) + if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) { + ; } else - return BAD_FUNC_ARG; -} +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ -int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url) -{ - WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerSetOCSPOverrideURL(SSL_CM(ssl), url); +#if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) + if (d2iTryAltDhKey(&pkey, *in, inSz, priv) >= 0) { + ; } else - return BAD_FUNC_ARG; -} - +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ -int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl, - CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx) -{ - WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb"); - if (ssl) { - SSL_CM_WARNING(ssl); - ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */ - return wolfSSL_CertManagerSetOCSP_Cb(SSL_CM(ssl), - ioCb, respFreeCb, NULL); +#ifdef HAVE_FALCON + if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) { + ; } else - return BAD_FUNC_ARG; +#endif /* HAVE_FALCON */ +#ifdef HAVE_DILITHIUM + if (d2iTryDilithiumKey(&pkey, *in, inSz, priv) >= 0) { + ; + } + else +#endif /* HAVE_DILITHIUM */ + { + WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type"); + } + + if ((pkey != NULL) && (out != NULL)) { + *out = pkey; + } + return pkey; } +#endif /* OPENSSL_EXTRA || WPA_SMALL */ +#ifdef OPENSSL_EXTRA -int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options) +WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY( + WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, + long keyLen) { - WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP"); - if (ctx) - return wolfSSL_CertManagerEnableOCSP(ctx->cm, options); - else - return BAD_FUNC_ARG; -} + WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; +#ifdef WOLFSSL_PEM_TO_DER + int ret; + DerBuffer* der = NULL; + if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) { + WOLFSSL_MSG("Bad key PEM/DER args"); + return NULL; + } -int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP"); - if (ctx) - return wolfSSL_CertManagerDisableOCSP(ctx->cm); - else - return BAD_FUNC_ARG; -} + ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &der, NULL, NULL, NULL); + if (ret < 0) { + WOLFSSL_MSG("Not PEM format"); + ret = AllocDer(&der, (word32)keyLen, PRIVATEKEY_TYPE, NULL); + if (ret == 0) { + XMEMCPY(der->buffer, *keyBuf, keyLen); + } + } + if (ret == 0) { + /* Verify this is PKCS8 Key */ + word32 inOutIdx = 0; + word32 algId; + ret = ToTraditionalInline_ex(der->buffer, &inOutIdx, der->length, + &algId); + if (ret >= 0) { + ret = 0; /* good DER */ + } + } -int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url) -{ - WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); - if (ctx) - return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url); - else - return BAD_FUNC_ARG; -} + if (ret == 0) { + pkcs8 = wolfSSL_EVP_PKEY_new(); + if (pkcs8 == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + pkcs8->pkey.ptr = (char*)XMALLOC(der->length, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkcs8->pkey.ptr == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + XMEMCPY(pkcs8->pkey.ptr, der->buffer, der->length); + pkcs8->pkey_sz = (int)der->length; + } + FreeDer(&der); + if (ret != 0) { + wolfSSL_EVP_PKEY_free(pkcs8); + pkcs8 = NULL; + } + if (pkey != NULL) { + *pkey = pkcs8; + } -int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb, - CbOCSPRespFree respFreeCb, void* ioCbCtx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb"); - if (ctx) - return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb, - respFreeCb, ioCbCtx); - else - return BAD_FUNC_ARG; -} +#else + (void)bio; + (void)pkey; +#endif /* WOLFSSL_PEM_TO_DER */ -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) -int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling"); - if (ctx) - return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm); - else - return BAD_FUNC_ARG; + return pkcs8; } -int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling"); - if (ctx) - return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm); - else - return BAD_FUNC_ARG; -} -int wolfSSL_CTX_EnableOCSPMustStaple(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPMustStaple"); - if (ctx) - return wolfSSL_CertManagerEnableOCSPMustStaple(ctx->cm); - else - return BAD_FUNC_ARG; -} +#ifndef NO_BIO +/* put SSL type in extra for now, not very common */ -int wolfSSL_CTX_DisableOCSPMustStaple(WOLFSSL_CTX* ctx) +/* Converts a DER format key read from "bio" to a PKCS8 structure. + * + * bio input bio to read DER from + * pkey If not NULL then this pointer will be overwritten with a new PKCS8 + * structure. + * + * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail + * case. + */ +WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey) { - WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPMustStaple"); - if (ctx) - return wolfSSL_CertManagerDisableOCSPMustStaple(ctx->cm); - else - return BAD_FUNC_ARG; -} -#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; +#ifdef WOLFSSL_PEM_TO_DER + unsigned char* mem = NULL; + int memSz; -#endif /* HAVE_OCSP */ + WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio"); -/* macro to get verify settings for AddCA */ -#define GET_VERIFY_SETTING_CTX(ctx) \ - ((ctx) && (ctx)->verifyNone ? NO_VERIFY : VERIFY) -#define GET_VERIFY_SETTING_SSL(ssl) \ - ((ssl)->options.verifyNone ? NO_VERIFY : VERIFY) + if (bio == NULL) { + return NULL; + } -#ifndef NO_FILESYSTEM + if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { + return NULL; + } -/* process a file with name fname into ctx of format and type - userChain specifies a user certificate chain to pass during handshake */ -int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, - WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify) -{ -#ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ + pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz); #else - byte staticBuffer[FILE_BUFFER_SIZE]; -#endif - byte* myBuffer = staticBuffer; - int dynamic = 0; - int ret; - long sz = 0; - XFILE file; - void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl); -#ifndef NO_CODING - const char* header = NULL; - const char* footer = NULL; -#endif + (void)bio; + (void)pkey; +#endif /* WOLFSSL_PEM_TO_DER */ - (void)crl; - (void)heapHint; + return pkcs8; +} - if (fname == NULL) return WOLFSSL_BAD_FILE; - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) return WOLFSSL_BAD_FILE; - if (XFSEEK(file, 0, XSEEK_END) != 0) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - sz = XFTELL(file); - if (XFSEEK(file, 0, XSEEK_SET) != 0) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; +/* expecting DER format public key + * + * bio input bio to read DER from + * out If not NULL then this pointer will be overwritten with a new + * WOLFSSL_EVP_PKEY pointer + * + * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case. + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) +{ + unsigned char* mem; + long memSz; + WOLFSSL_EVP_PKEY* pkey = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio"); + + if (bio == NULL) { + return NULL; } + (void)out; - if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { - WOLFSSL_MSG("ProcessFile file size error"); - XFCLOSE(file); - return WOLFSSL_BAD_FILE; + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + return NULL; } - if (sz > (long)sizeof(staticBuffer)) { - WOLFSSL_MSG("Getting dynamic buffer"); - myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE); - if (myBuffer == NULL) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - dynamic = 1; + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + return NULL; } - if ((size_t)XFREAD(myBuffer, 1, sz, file) != (size_t)sz) - ret = WOLFSSL_BAD_FILE; - else { - /* Try to detect type by parsing cert header and footer */ - if (type == DETECT_CERT_TYPE) { -#ifndef NO_CODING - if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 && - (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) { - type = CA_TYPE; - } -#ifdef HAVE_CRL - else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && - (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) { - type = CRL_TYPE; - } -#endif - else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && - (XSTRNSTR((char*)myBuffer, header, (int)sz) != NULL)) { - type = CERT_TYPE; - } - else -#endif - { - WOLFSSL_MSG("Failed to detect certificate type"); - if (dynamic) - XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE); - XFCLOSE(file); - return WOLFSSL_BAD_CERTTYPE; - } - } - if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) - && format == WOLFSSL_FILETYPE_PEM) { - ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl, - verify); + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz); + if (out != NULL && pkey != NULL) { + *out = pkey; } -#ifdef HAVE_CRL - else if (type == CRL_TYPE) - ret = BufferLoadCRL(crl, myBuffer, sz, format, verify); -#endif - else - ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL, - userChain, verify); } - XFCLOSE(file); - if (dynamic) - XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE); - - return ret; + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return pkey; } -/* loads file then loads each file in path, no c_rehash */ -int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, - const char* path, word32 flags) -{ - int ret = WOLFSSL_SUCCESS; -#ifndef NO_WOLFSSL_DIR - int successCount = 0; -#endif - int verify; +#endif /* !NO_BIO */ - WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex"); - if (ctx == NULL || (file == NULL && path == NULL)) { - return WOLFSSL_FAILURE; - } +/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. + * + * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL + * in DER buffer to convert + * inSz size of in buffer + * + * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL + * on fail + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, + const unsigned char** in, long inSz) +{ + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); + return d2iGenericKey(out, in, inSz, 0); +} - verify = GET_VERIFY_SETTING_CTX(ctx); - if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) - verify = VERIFY_SKIP_DATE; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \ + !defined(NO_PWDBASED) - if (file) { - ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, - NULL, verify); -#ifndef NO_WOLFSSL_DIR - if (ret == WOLFSSL_SUCCESS) - successCount++; -#endif -#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) - ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error"); - } -#endif - } +/* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */ +static int wolfSSL_EVP_PKEY_get_der(const WOLFSSL_EVP_PKEY* key, + unsigned char** der) +{ + int sz; + word16 pkcs8HeaderSz; - if (ret == WOLFSSL_SUCCESS && path) { -#ifndef NO_WOLFSSL_DIR - char* name = NULL; - int fileRet; - int failCount = 0; - #ifdef WOLFSSL_SMALL_STACK - ReadDirCtx* readCtx; - readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, - DYNAMIC_TYPE_DIRCTX); - if (readCtx == NULL) - return MEMORY_E; - #else - ReadDirCtx readCtx[1]; - #endif - - /* try to load each regular file in path */ - fileRet = wc_ReadDirFirst(readCtx, path, &name); - while (fileRet == 0 && name) { - WOLFSSL_MSG(name); /* log file name */ - ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL, verify); - if (ret != WOLFSSL_SUCCESS) { - /* handle flags for ignoring errors, skipping expired certs or - by PEM certificate header error */ - if ( (flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) || - ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) && - (ret == ASN_NO_PEM_HEADER))) { - /* Do not fail here if a certificate fails to load, - continue to next file */ - unsigned long err = 0; - CLEAR_ASN_NO_PEM_HEADER_ERROR(err); - #if defined(WOLFSSL_QT) - ret = WOLFSSL_SUCCESS; - #endif - } - else { - WOLFSSL_ERROR(ret); - WOLFSSL_MSG("Load CA file failed, continuing"); - failCount++; - } - } - else { - #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) - ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error. Ignoring" - "this error."); - } - #endif - successCount++; - } - fileRet = wc_ReadDirNext(readCtx, path, &name); - } - wc_ReadDirClose(readCtx); + if (!key || !key->pkey_sz) + return WOLFSSL_FATAL_ERROR; - /* pass directory read failure to response code */ - if (fileRet != WC_READDIR_NOFILE) { - ret = fileRet; - #if defined(WOLFSSL_QT) || defined(WOLFSSL_IGNORE_BAD_CERT_PATH) - if (ret == BAD_PATH_ERROR && - flags & WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR) { - /* QSslSocket always loads certs in system folder - * when it is initialized. - * Compliant with OpenSSL when flag sets. - */ - ret = WOLFSSL_SUCCESS; - } - else { - /* qssl socket wants to know errors. */ - WOLFSSL_ERROR(ret); - } - #endif - } - /* report failure if no files were loaded or there were failures */ - else if (successCount == 0 || failCount > 0) { - /* use existing error code if exists */ - #if defined(WOLFSSL_QT) - /* compliant with OpenSSL when flag sets*/ - if (!(flags & WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE)) - #endif - { - ret = WOLFSSL_FAILURE; - } + /* return the key without PKCS8 for compatibility */ + /* if pkcs8HeaderSz is invalid, use 0 and return all of pkey */ + pkcs8HeaderSz = 0; + if (key->pkey_sz > key->pkcs8HeaderSz) + pkcs8HeaderSz = key->pkcs8HeaderSz; + sz = key->pkey_sz - pkcs8HeaderSz; + if (der) { + unsigned char* pt = (unsigned char*)key->pkey.ptr; + if (*der) { + /* since this function signature has no size value passed in it is + * assumed that the user has allocated a large enough buffer */ + XMEMCPY(*der, pt + pkcs8HeaderSz, sz); + *der += sz; } else { - ret = WOLFSSL_SUCCESS; + *der = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*der == NULL) { + return WOLFSSL_FATAL_ERROR; + } + XMEMCPY(*der, pt + pkcs8HeaderSz, sz); } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX); - #endif -#else - ret = NOT_COMPILED_IN; - (void)flags; -#endif } - - return ret; + return sz; } -WOLFSSL_ABI -int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, - const char* path) +int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der) { - int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, - WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); - - return WS_RETURN_CODE(ret,WOLFSSL_FAILURE); + return wolfSSL_i2d_PublicKey(key, der); } -#ifdef WOLFSSL_SYS_CA_CERTS - -#ifdef USE_WINDOWS_API +#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */ -static int LoadSystemCaCertsWindows(WOLFSSL_CTX* ctx, byte* loaded) +static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz, int priv) { - int ret = WOLFSSL_SUCCESS; - word32 i; - HANDLE handle = NULL; - PCCERT_CONTEXT certCtx = NULL; - LPCSTR storeNames[2] = {"ROOT", "CA"}; - HCRYPTPROV_LEGACY hProv = (HCRYPTPROV_LEGACY)NULL; - - if (ctx == NULL || loaded == NULL) { - ret = WOLFSSL_FAILURE; - } - - for (i = 0; ret == WOLFSSL_SUCCESS && - i < sizeof(storeNames)/sizeof(*storeNames); ++i) { - handle = CertOpenSystemStoreA(hProv, storeNames[i]); - if (handle != NULL) { - while ((certCtx = CertEnumCertificatesInStore(handle, certCtx)) - != NULL) { - if (certCtx->dwCertEncodingType == X509_ASN_ENCODING) { - if (ProcessBuffer(ctx, certCtx->pbCertEncoded, - certCtx->cbCertEncoded, WOLFSSL_FILETYPE_ASN1, - CA_TYPE, NULL, NULL, 0, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - /* - * Set "loaded" as long as we've loaded one CA - * cert. - */ - *loaded = 1; - } - } - } - } - else { - WOLFSSL_MSG_EX("Failed to open cert store %s.", storeNames[i]); - } - - if (handle != NULL && !CertCloseStore(handle, 0)) { - WOLFSSL_MSG_EX("Failed to close cert store %s.", storeNames[i]); - ret = WOLFSSL_FAILURE; - } - } - - return ret; -} - -#elif defined(__APPLE__) + int ret = 0; + word32 idx = 0, algId; + word16 pkcs8HeaderSz = 0; + WOLFSSL_EVP_PKEY* local; + int opt = 0; -#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \ - && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) -/* - * Manually obtains certificates from the system trust store and loads them - * directly into wolfSSL "the old way". - * - * As of MacOS 14.0 we are still able to use this method to access system - * certificates. Accessibility of this API is indicated by the presence of the - * Security/SecTrustSettings.h header. In the likely event that Apple removes - * access to this API on Macs, this function should be removed and the - * DoAppleNativeCertValidation() routine should be used for all devices. - */ -static int LoadSystemCaCertsMac(WOLFSSL_CTX* ctx, byte* loaded) -{ - int ret = WOLFSSL_SUCCESS; - word32 i; - const unsigned int trustDomains[] = { - kSecTrustSettingsDomainUser, - kSecTrustSettingsDomainAdmin, - kSecTrustSettingsDomainSystem - }; - CFArrayRef certs; - OSStatus stat; - CFIndex numCerts; - CFDataRef der; - CFIndex j; + (void)opt; - if (ctx == NULL || loaded == NULL) { - ret = WOLFSSL_FAILURE; + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; } - for (i = 0; ret == WOLFSSL_SUCCESS && - i < sizeof(trustDomains)/sizeof(*trustDomains); ++i) { - stat = SecTrustSettingsCopyCertificates( - (SecTrustSettingsDomain)trustDomains[i], &certs); - if (stat == errSecSuccess) { - numCerts = CFArrayGetCount(certs); - for (j = 0; j < numCerts; ++j) { - der = SecCertificateCopyData((SecCertificateRef) - CFArrayGetValueAtIndex(certs, j)); - if (der != NULL) { - if (ProcessBuffer(ctx, CFDataGetBytePtr(der), - CFDataGetLength(der), WOLFSSL_FILETYPE_ASN1, - CA_TYPE, NULL, NULL, 0, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - /* - * Set "loaded" as long as we've loaded one CA - * cert. - */ - *loaded = 1; - } + if (priv == 1) { + /* Check if input buffer has PKCS8 header. In the case that it does not + * have a PKCS8 header then do not error out. */ + if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, + (word32)inSz, &algId)) > 0) { + WOLFSSL_MSG("Found PKCS8 header"); + pkcs8HeaderSz = (word16)idx; - CFRelease(der); - } + if ((type == EVP_PKEY_RSA && algId != RSAk + #ifdef WC_RSA_PSS + && algId != RSAPSSk + #endif + ) || + (type == EVP_PKEY_EC && algId != ECDSAk) || + (type == EVP_PKEY_DSA && algId != DSAk) || + (type == EVP_PKEY_DH && algId != DHk)) { + WOLFSSL_MSG("PKCS8 does not match EVP key type"); + return NULL; } - CFRelease(certs); - } - else if (stat == errSecNoTrustSettings) { - WOLFSSL_MSG_EX("No trust settings for domain %d, moving to next " - "domain.", trustDomains[i]); + (void)idx; /* not used */ } else { - WOLFSSL_MSG_EX("SecTrustSettingsCopyCertificates failed with" - " status %d.", stat); - ret = WOLFSSL_FAILURE; - break; + if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 " + "header"); + return NULL; + } } } - return ret; -} -#endif /* defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) */ - -#else - -/* Potential system CA certs directories on Linux/Unix distros. */ -static const char* systemCaDirs[] = { -#if defined(__ANDROID__) || defined(ANDROID) - "/system/etc/security/cacerts" /* Android */ -#else - "/etc/ssl/certs", /* Debian, Ubuntu, Gentoo, others */ - "/etc/pki/ca-trust/source/anchors", /* Fedora, RHEL */ - "/etc/pki/tls/certs" /* Older RHEL */ -#endif -}; - -const char** wolfSSL_get_system_CA_dirs(word32* num) -{ - const char** ret; + if (out != NULL && *out != NULL) { + wolfSSL_EVP_PKEY_free(*out); + *out = NULL; + } + local = wolfSSL_EVP_PKEY_new(); + if (local == NULL) { + return NULL; + } - if (num == NULL) { - ret = NULL; + local->type = type; + local->pkey_sz = (int)inSz; + local->pkcs8HeaderSz = pkcs8HeaderSz; + local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (local->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(local); + local = NULL; + return NULL; } else { - ret = systemCaDirs; - *num = sizeof(systemCaDirs)/sizeof(*systemCaDirs); + XMEMCPY(local->pkey.ptr, *in, inSz); } - return ret; -} - -static int LoadSystemCaCertsNix(WOLFSSL_CTX* ctx, byte* loaded) { - int ret = WOLFSSL_SUCCESS; - word32 i; - - if (ctx == NULL || loaded == NULL) { - ret = WOLFSSL_FAILURE; + switch (type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC; + local->ownRsa = 1; + local->rsa = wolfssl_rsa_d2i(NULL, + (const unsigned char*)local->pkey.ptr, local->pkey_sz, opt); + if (local->rsa == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* NO_RSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + local->ownEcc = 1; + local->ecc = wolfSSL_EC_KEY_new(); + if (local->ecc == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE : + WOLFSSL_EC_KEY_LOAD_PUBLIC; + if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc, + (const unsigned char*)local->pkey.ptr, local->pkey_sz, + opt) + != WOLFSSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* HAVE_ECC */ +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) +#ifndef NO_DSA + case EVP_PKEY_DSA: + local->ownDsa = 1; + local->dsa = wolfSSL_DSA_new(); + if (local->dsa == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC; + if (wolfSSL_DSA_LoadDer_ex(local->dsa, + (const unsigned char*)local->pkey.ptr, local->pkey_sz, + opt) + != WOLFSSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* NO_DSA */ +#ifndef NO_DH +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) + case EVP_PKEY_DH: + local->ownDh = 1; + local->dh = wolfSSL_DH_new(); + if (local->dh == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_DH_LoadDer(local->dh, + (const unsigned char*)local->pkey.ptr, local->pkey_sz) + != WOLFSSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* HAVE_DH */ +#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */ + default: + WOLFSSL_MSG("Unsupported key type"); + wolfSSL_EVP_PKEY_free(local); + return NULL; } - for (i = 0; ret == WOLFSSL_SUCCESS && - i < sizeof(systemCaDirs)/sizeof(*systemCaDirs); ++i) { - WOLFSSL_MSG_EX("Attempting to load system CA certs from %s.", - systemCaDirs[i]); - /* - * We want to keep trying to load more CAs even if one cert in - * the directory is bad and can't be used (e.g. if one is expired), - * so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR. - */ - if (wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, systemCaDirs[i], - WOLFSSL_LOAD_FLAG_IGNORE_ERR) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG_EX("Failed to load CA certs from %s, trying " - "next possible location.", systemCaDirs[i]); + /* advance pointer with success */ + if (local != NULL) { + if (local->pkey_sz <= (int)inSz) { + *in += local->pkey_sz; } - else { - WOLFSSL_MSG_EX("Loaded CA certs from %s.", - systemCaDirs[i]); - *loaded = 1; - /* Stop searching after we've loaded one directory. */ - break; + + if (out != NULL) { + *out = local; } } - return ret; + return local; } -#endif - -int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx) +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) { - int ret; - byte loaded = 0; - - WOLFSSL_ENTER("wolfSSL_CTX_load_system_CA_certs"); - -#ifdef USE_WINDOWS_API - - ret = LoadSystemCaCertsWindows(ctx, &loaded); - -#elif defined(__APPLE__) - -#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \ - && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) - /* As of MacOS 14.0 we are still able to access system certificates and - * load them manually into wolfSSL "the old way". Accessibility of this API - * is indicated by the presence of the Security/SecTrustSettings.h header */ - ret = LoadSystemCaCertsMac(ctx, &loaded); -#elif defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) - /* For other Apple devices, Apple has removed the ability to obtain - * certificates from the trust store, so we can't use wolfSSL's built-in - * certificate validation mechanisms anymore. We instead must call into the - * Security Framework APIs to authenticate peer certificates when received. - * (see src/internal.c:DoAppleNativeCertValidation()). - * Thus, there is no CA "loading" required, but to keep behavior consistent - * with the current API (not using system CA certs unless this function has - * been called), we simply set a flag indicating that the new apple trust - * verification routine should be used later */ - ctx->doAppleNativeCertValidationFlag = 1; - ret = WOLFSSL_SUCCESS; - loaded = 1; - -#if FIPS_VERSION_GE(2,0) /* Gate back to cert 3389 FIPS modules */ -#warning "Cryptographic operations may occur outside the FIPS module boundary" \ - "Please review FIPS claims for cryptography on this Apple device" -#endif /* FIPS_VERSION_GE(2,0) */ + WOLFSSL_ENTER("wolfSSL_d2i_PublicKey"); -#else -/* HAVE_SECURITY_SECXXX_H macros are set by autotools or CMake when searching - * system for the required SDK headers. If building with user_settings.h, you - * will need to manually define WOLFSSL_APPLE_NATIVE_CERT_VALIDATION - * and ensure the appropriate Security.framework headers and libraries are - * visible to your compiler */ -#error "WOLFSSL_SYS_CA_CERTS on Apple devices requires Security.framework" \ - " header files to be detected, or a manual override with" \ - " WOLFSSL_APPLE_NATIVE_CERT_VALIDATION" -#endif - -#else + return _d2i_PublicKey(type, out, in, inSz, 0); +} +/* Reads in a DER format key. If PKCS8 headers are found they are stripped off. + * + * type type of key + * out newly created WOLFSSL_EVP_PKEY structure + * in pointer to input key DER + * inSz size of in buffer + * + * On success a non null pointer is returned and the pointer in is advanced the + * same number of bytes read. + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) +{ + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); - ret = LoadSystemCaCertsNix(ctx, &loaded); + return _d2i_PublicKey(type, out, in, inSz, 1); +} -#endif +#ifdef WOLF_PRIVATE_KEY_ID +/* Create an EVP structure for use with crypto callbacks */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out, + void* heap, int devId) +{ + WOLFSSL_EVP_PKEY* local; - if (ret == WOLFSSL_SUCCESS && !loaded) { - ret = WOLFSSL_BAD_PATH; + if (out != NULL && *out != NULL) { + wolfSSL_EVP_PKEY_free(*out); + *out = NULL; } - WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret); + local = wolfSSL_EVP_PKEY_new_ex(heap); + if (local == NULL) { + return NULL; + } - return ret; -} + local->type = type; + local->pkey_sz = 0; + local->pkcs8HeaderSz = 0; -#endif /* WOLFSSL_SYS_CA_CERTS */ + switch (type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + { + RsaKey* key; + local->ownRsa = 1; + local->rsa = wolfSSL_RSA_new_ex(heap, devId); + if (local->rsa == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + key = (RsaKey*)local->rsa->internal; + #ifdef WOLF_CRYPTO_CB + key->devId = devId; + #endif + (void)key; + local->rsa->inSet = 1; + break; + } +#endif /* !NO_RSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + { + ecc_key* key; + local->ownEcc = 1; + local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId); + if (local->ecc == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + key = (ecc_key*)local->ecc->internal; + #ifdef WOLF_CRYPTO_CB + key->devId = devId; + #endif + key->type = ECC_PRIVATEKEY; + /* key is required to have a key size / curve set, although + * actual one used is determined by devId callback function */ + wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF); -#ifdef WOLFSSL_TRUST_PEER_CERT -/* Used to specify a peer cert to match when connecting - ctx : the ctx structure to load in peer cert - file: the string name of cert file - type: type of format such as PEM/DER - */ -int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) -{ - WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert"); + local->ecc->inSet = 1; + break; + } +#endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Unsupported private key id type"); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } - if (ctx == NULL || file == NULL) { - return WOLFSSL_FAILURE; + if (local != NULL && out != NULL) { + *out = local; } - return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)); + return local; } +#endif /* WOLF_PRIVATE_KEY_ID */ + +#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */ -int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int type) +#ifndef NO_CHECK_PRIVATE_KEY +/* Check private against public in certificate for match + * + * ssl WOLFSSL structure to check private key in + * + * Returns WOLFSSL_SUCCESS on good private key + * WOLFSSL_FAILURE if mismatched. */ +int wolfSSL_check_private_key(const WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_trust_peer_cert"); + int res = WOLFSSL_SUCCESS; - if (ssl == NULL || file == NULL) { + if (ssl == NULL) { return WOLFSSL_FAILURE; } +#ifdef WOLFSSL_DUAL_ALG_CERTS +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + wolfssl_priv_der_unblind(ssl->buffers.altKey, ssl->buffers.altKeyMask); +#endif + res = check_cert_key(ssl->buffers.certificate, ssl->buffers.key, + ssl->buffers.altKey, ssl->heap, ssl->buffers.keyDevId, + ssl->buffers.keyLabel, ssl->buffers.keyId, ssl->buffers.altKeyDevId, + ssl->buffers.altKeyLabel, ssl->buffers.altKeyId); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (res == WOLFSSL_SUCCESS) { + int ret; + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + (DerBuffer**)&ssl->buffers.keyMask); + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + (DerBuffer**)&ssl->buffers.altKeyMask); + } + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } +#endif +#else +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); +#endif + res = check_cert_key(ssl->buffers.certificate, ssl->buffers.key, NULL, + ssl->heap, ssl->buffers.keyDevId, ssl->buffers.keyLabel, + ssl->buffers.keyId, INVALID_DEVID, 0, 0); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (res == WOLFSSL_SUCCESS) { + int ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + (DerBuffer**)&ssl->buffers.keyMask); + if (ret != 0) { + res = WOLFSSL_FAILURE; + } + } +#endif +#endif - return ProcessFile(NULL, file, type, TRUSTED_PEER_TYPE, ssl, 0, NULL, - GET_VERIFY_SETTING_SSL(ssl)); + return res; } -#endif /* WOLFSSL_TRUST_PEER_CERT */ +#endif /* !NO_CHECK_PRIVATE_KEY */ -#endif /* NO_FILESYSTEM */ +#endif /* !NO_CERTS */ -#ifdef HAVE_CRL +#endif /* OPENSSL_EXTRA */ -int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) +#if defined(HAVE_RPK) +/* Confirm that all the byte data in the buffer is unique. + * return 1 if all the byte data in the buffer is unique, otherwise 0. + */ +static int isArrayUnique(const char* buf, size_t len) { - WOLFSSL_ENTER("wolfSSL_EnableCRL"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerEnableCRL(SSL_CM(ssl), options); + size_t i, j; + /* check the array is unique */ + for (i = 0; i < len -1; ++i) { + for (j = i+ 1; j < len; ++j) { + if (buf[i] == buf[j]) { + return 0; + } + } } - else - return BAD_FUNC_ARG; + return 1; } - -int wolfSSL_DisableCRL(WOLFSSL* ssl) +/* Set user preference for the client_cert_type exetnsion. + * Takes byte array containing cert types the caller can provide to its peer. + * Cert types are in preferred order in the array. + */ +WOLFSSL_API int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, + const char* buf, int bufLen) { - WOLFSSL_ENTER("wolfSSL_DisableCRL"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerDisableCRL(SSL_CM(ssl)); - } - else - return BAD_FUNC_ARG; -} + int i; -#ifndef NO_FILESYSTEM -int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) -{ - WOLFSSL_ENTER("wolfSSL_LoadCRL"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerLoadCRL(SSL_CM(ssl), path, type, monitor); - } - else + if (ctx == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { return BAD_FUNC_ARG; -} + } -int wolfSSL_LoadCRLFile(WOLFSSL* ssl, const char* file, int type) -{ - WOLFSSL_ENTER("wolfSSL_LoadCRLFile"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerLoadCRLFile(SSL_CM(ssl), file, type); + /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ + if (buf == NULL || bufLen == 0) { + ctx->rpkConfig.preferred_ClientCertTypeCnt = 1; + ctx->rpkConfig.preferred_ClientCertTypes[0]= WOLFSSL_CERT_TYPE_X509; + ctx->rpkConfig.preferred_ClientCertTypes[1]= WOLFSSL_CERT_TYPE_X509; + return WOLFSSL_SUCCESS; } - else + + if (!isArrayUnique(buf, (size_t)bufLen)) return BAD_FUNC_ARG; -} -#endif + for (i = 0; i < bufLen; i++){ + if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) + return BAD_FUNC_ARG; -int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) -{ - WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerSetCRL_Cb(SSL_CM(ssl), cb); + ctx->rpkConfig.preferred_ClientCertTypes[i] = (byte)buf[i]; } - else - return BAD_FUNC_ARG; -} + ctx->rpkConfig.preferred_ClientCertTypeCnt = bufLen; -#ifdef HAVE_CRL_IO -int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) -{ - WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); - if (ssl) { - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerSetCRL_IOCb(SSL_CM(ssl), cb); - } - else - return BAD_FUNC_ARG; + return WOLFSSL_SUCCESS; } -#endif -int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options) +/* Set user preference for the server_cert_type exetnsion. + * Takes byte array containing cert types the caller can provide to its peer. + * Cert types are in preferred order in the array. + */ +WOLFSSL_API int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, + const char* buf, int bufLen) { - WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL"); - if (ctx) - return wolfSSL_CertManagerEnableCRL(ctx->cm, options); - else + int i; + + if (ctx == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { return BAD_FUNC_ARG; -} + } + /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ + if (buf == NULL || bufLen == 0) { + ctx->rpkConfig.preferred_ServerCertTypeCnt = 1; + ctx->rpkConfig.preferred_ServerCertTypes[0]= WOLFSSL_CERT_TYPE_X509; + ctx->rpkConfig.preferred_ServerCertTypes[1]= WOLFSSL_CERT_TYPE_X509; + return WOLFSSL_SUCCESS; + } -int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL"); - if (ctx) - return wolfSSL_CertManagerDisableCRL(ctx->cm); - else + if (!isArrayUnique(buf, (size_t)bufLen)) return BAD_FUNC_ARG; -} + for (i = 0; i < bufLen; i++){ + if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) + return BAD_FUNC_ARG; -#ifndef NO_FILESYSTEM -int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, - int type, int monitor) -{ - WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); - if (ctx) - return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor); - else - return BAD_FUNC_ARG; -} + ctx->rpkConfig.preferred_ServerCertTypes[i] = (byte)buf[i]; + } + ctx->rpkConfig.preferred_ServerCertTypeCnt = bufLen; -int wolfSSL_CTX_LoadCRLFile(WOLFSSL_CTX* ctx, const char* file, - int type) -{ - WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); - if (ctx) - return wolfSSL_CertManagerLoadCRLFile(ctx->cm, file, type); - else - return BAD_FUNC_ARG; + return WOLFSSL_SUCCESS; } -#endif - -int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) +/* Set user preference for the client_cert_type exetnsion. + * Takes byte array containing cert types the caller can provide to its peer. + * Cert types are in preferred order in the array. + */ +WOLFSSL_API int wolfSSL_set_client_cert_type(WOLFSSL* ssl, + const char* buf, int bufLen) { - WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb"); - if (ctx) - return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb); - else - return BAD_FUNC_ARG; -} + int i; -#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 + if (ssl == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { return BAD_FUNC_ARG; -} -#endif - - -#endif /* HAVE_CRL */ - - -#ifndef NO_FILESYSTEM - - -#ifdef WOLFSSL_DER_LOAD - -/* Add format parameter to allow DER load of CA files */ -int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, - int format) -{ - WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations"); - if (ctx == NULL || file == NULL) - return WOLFSSL_FAILURE; + } - if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ + if (buf == NULL || bufLen == 0) { + ssl->options.rpkConfig.preferred_ClientCertTypeCnt = 1; + ssl->options.rpkConfig.preferred_ClientCertTypes[0] + = WOLFSSL_CERT_TYPE_X509; + ssl->options.rpkConfig.preferred_ClientCertTypes[1] + = WOLFSSL_CERT_TYPE_X509; return WOLFSSL_SUCCESS; } - return WOLFSSL_FAILURE; -} - -#endif /* WOLFSSL_DER_LOAD */ - - + if (!isArrayUnique(buf, (size_t)bufLen)) + return BAD_FUNC_ARG; -WOLFSSL_ABI -int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file, - int format) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file"); + for (i = 0; i < bufLen; i++){ + if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) + return BAD_FUNC_ARG; - if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + ssl->options.rpkConfig.preferred_ClientCertTypes[i] = (byte)buf[i]; } + ssl->options.rpkConfig.preferred_ClientCertTypeCnt = bufLen; - return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; } - -WOLFSSL_ABI -int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, - int format) +/* Set user preference for the server_cert_type exetnsion. + * Takes byte array containing cert types the caller can provide to its peer. + * Cert types are in preferred order in the array. + */ +WOLFSSL_API int wolfSSL_set_server_cert_type(WOLFSSL* ssl, + const char* buf, int bufLen) { - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file"); + int i; - if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + if (ssl == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { + return BAD_FUNC_ARG; } - return WOLFSSL_FAILURE; -} - -#ifdef WOLFSSL_DUAL_ALG_CERTS -int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file, - int format) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file"); - - if (ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { + /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ + if (buf == NULL || bufLen == 0) { + ssl->options.rpkConfig.preferred_ServerCertTypeCnt = 1; + ssl->options.rpkConfig.preferred_ServerCertTypes[0] + = WOLFSSL_CERT_TYPE_X509; + ssl->options.rpkConfig.preferred_ServerCertTypes[1] + = WOLFSSL_CERT_TYPE_X509; return WOLFSSL_SUCCESS; } - return WOLFSSL_FAILURE; -} -#endif /* WOLFSSL_DUAL_ALG_CERTS */ -#endif /* NO_FILESYSTEM */ - + if (!isArrayUnique(buf, (size_t)bufLen)) + return BAD_FUNC_ARG; -/* Sets the max chain depth when verifying a certificate chain. Default depth - * is set to MAX_CHAIN_DEPTH. - * - * ctx WOLFSSL_CTX structure to set depth in - * depth max depth - */ -void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { - WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); + for (i = 0; i < bufLen; i++){ + if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) + return BAD_FUNC_ARG; - if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) { - WOLFSSL_MSG("Bad depth argument, too large or less than 0"); - return; + ssl->options.rpkConfig.preferred_ServerCertTypes[i] = (byte)buf[i]; } + ssl->options.rpkConfig.preferred_ServerCertTypeCnt = bufLen; - ctx->verifyDepth = (byte)depth; + return WOLFSSL_SUCCESS; } - -/* get cert chaining depth using ssl struct */ -long wolfSSL_get_verify_depth(WOLFSSL* ssl) +/* get negotiated certificate type value and return it to the second parameter. + * cert type value: + * -1: WOLFSSL_CERT_TYPE_UNKNOWN + * 0: WOLFSSL_CERT_TYPE_X509 + * 2: WOLFSSL_CERT_TYPE_RPK + * return WOLFSSL_SUCCESS on success, otherwise negative value. + * in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for + * cert type. + */ +WOLFSSL_API int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp) { - if(ssl == NULL) { - return BAD_FUNC_ARG; - } -#ifndef OPENSSL_EXTRA - return MAX_CHAIN_DEPTH; -#else - return ssl->options.verifyDepth; -#endif -} - + int ret = WOLFSSL_SUCCESS; -/* get cert chaining depth using ctx struct */ -long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) -{ - if (ctx == NULL) { + if (ssl == NULL || tp == NULL) return BAD_FUNC_ARG; - } -#ifndef OPENSSL_EXTRA - return MAX_CHAIN_DEPTH; -#else - return ctx->verifyDepth; -#endif -} - -#ifndef NO_FILESYSTEM - - -WOLFSSL_ABI -int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file) -{ - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file"); - - if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) + *tp = ssl->options.rpkState.received_ClientCertTypes[0]; + else + *tp = WOLFSSL_CERT_TYPE_UNKNOWN; } - - return WOLFSSL_FAILURE; + else { + if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1) + *tp = ssl->options.rpkState.sending_ClientCertTypes[0]; + else + *tp = WOLFSSL_CERT_TYPE_UNKNOWN; + } + return ret; } - -int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx, - const char* file, int format) +/* get negotiated certificate type value and return it to the second parameter. + * cert type value: + * -1: WOLFSSL_CERT_TYPE_UNKNOWN + * 0: WOLFSSL_CERT_TYPE_X509 + * 2: WOLFSSL_CERT_TYPE_RPK + * return WOLFSSL_SUCCESS on success, otherwise negative value. + * in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for + * cert type. + */ +WOLFSSL_API int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp) { - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format"); + int ret = WOLFSSL_SUCCESS; - if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL, - GET_VERIFY_SETTING_CTX(ctx)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } + if (ssl == NULL || tp == NULL) + return BAD_FUNC_ARG; - return WOLFSSL_FAILURE; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) + *tp = ssl->options.rpkState.received_ServerCertTypes[0]; + else + *tp = WOLFSSL_CERT_TYPE_UNKNOWN; + } + else { + if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1) + *tp = ssl->options.rpkState.sending_ServerCertTypes[0]; + else + *tp = WOLFSSL_CERT_TYPE_UNKNOWN; + } + return ret; } +#endif /* HAVE_RPK */ -#ifndef NO_DH +#ifdef HAVE_ECC -/* server Diffie-Hellman parameters */ -static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - const char* fname, int format) +/* Set Temp CTX EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */ +int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) { -#ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ -#else - byte staticBuffer[FILE_BUFFER_SIZE]; -#endif - byte* myBuffer = staticBuffer; - int dynamic = 0; - int ret; - long sz = 0; - XFILE file; + WOLFSSL_ENTER("wolfSSL_CTX_SetTmpEC_DHE_Sz"); - if (ctx == NULL || fname == NULL) + if (ctx == NULL) return BAD_FUNC_ARG; - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) return WOLFSSL_BAD_FILE; - if(XFSEEK(file, 0, XSEEK_END) != 0) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - sz = XFTELL(file); - if(XFSEEK(file, 0, XSEEK_SET) != 0) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - - if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { - WOLFSSL_MSG("SetTmpDH file size error"); - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } + /* if 0 then get from loaded private key */ + if (sz == 0) { + /* applies only to ECDSA */ + if (ctx->privateKeyType != ecc_dsa_sa_algo) + return WOLFSSL_SUCCESS; - if (sz > (long)sizeof(staticBuffer)) { - WOLFSSL_MSG("Getting dynamic buffer"); - myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); - if (myBuffer == NULL) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; + if (ctx->privateKeySz == 0) { + WOLFSSL_MSG("Must set private key/cert first"); + return BAD_FUNC_ARG; } - dynamic = 1; - } - if ((size_t)XFREAD(myBuffer, 1, sz, file) != (size_t)sz) - ret = WOLFSSL_BAD_FILE; - else { - if (ssl) - ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format); - else - ret = wolfSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format); + sz = (word16)ctx->privateKeySz; } - XFCLOSE(file); - if (dynamic) - XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + /* check size */ +#if ECC_MIN_KEY_SZ > 0 + if (sz < ECC_MINSIZE) + return BAD_FUNC_ARG; +#endif + if (sz > ECC_MAXSIZE) + return BAD_FUNC_ARG; + + ctx->eccTempKeySz = sz; - return ret; + return WOLFSSL_SUCCESS; } -/* server Diffie-Hellman parameters */ -int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format) + +/* Set Temp SSL EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */ +int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) { + WOLFSSL_ENTER("wolfSSL_SetTmpEC_DHE_Sz"); + if (ssl == NULL) return BAD_FUNC_ARG; - return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format); -} + /* check size */ +#if ECC_MIN_KEY_SZ > 0 + if (sz < ECC_MINSIZE) + return BAD_FUNC_ARG; +#endif + if (sz > ECC_MAXSIZE) + return BAD_FUNC_ARG; + ssl->eccTempKeySz = sz; -/* server Diffie-Hellman parameters */ -int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) -{ - return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format); + return WOLFSSL_SUCCESS; } -#endif /* NO_DH */ - -#endif /* NO_FILESYSTEM */ +#endif /* HAVE_ECC */ -#ifndef NO_CHECK_PRIVATE_KEY -/* Check private against public in certificate for match - * - * Returns WOLFSSL_SUCCESS on good private key - * WOLFSSL_FAILURE if mismatched */ -static int check_cert_key(DerBuffer* cert, DerBuffer* key, void* heap, - int devId, int isKeyLabel, int isKeyId) -{ -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* der = NULL; -#else - DecodedCert der[1]; -#endif - word32 size; - byte* buff; - int ret = WOLFSSL_FAILURE; - WOLFSSL_ENTER("check_cert_key"); +typedef struct { + byte verifyPeer:1; + byte verifyNone:1; + byte failNoCert:1; + byte failNoCertxPSK:1; + byte verifyPostHandshake:1; +} SetVerifyOptions; - if (cert == NULL || key == NULL) { - return WOLFSSL_FAILURE; - } +static SetVerifyOptions ModeToVerifyOptions(int mode) +{ + SetVerifyOptions opts; + XMEMSET(&opts, 0, sizeof(SetVerifyOptions)); -#ifdef WOLFSSL_SMALL_STACK - der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); - if (der == NULL) - return MEMORY_E; + if (mode != WOLFSSL_VERIFY_DEFAULT) { + opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE); + if (!opts.verifyNone) { + opts.verifyPeer = + (mode & WOLFSSL_VERIFY_PEER) != 0; + opts.failNoCertxPSK = + (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0; + opts.failNoCert = + (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + opts.verifyPostHandshake = + (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0; #endif - - size = cert->length; - buff = cert->buffer; - InitDecodedCert_ex(der, buff, size, heap, devId); - if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) { - FreeDecodedCert(der); - #ifdef WOLFSSL_SMALL_STACK - XFREE(der, NULL, DYNAMIC_TYPE_DCERT); - #endif - return WOLFSSL_FAILURE; - } - - size = key->length; - buff = key->buffer; -#ifdef WOLF_PRIVATE_KEY_ID - if (devId != INVALID_DEVID) { - int type = 0; - void *pkey = NULL; - - #ifndef NO_RSA - if (der->keyOID == RSAk) { - type = DYNAMIC_TYPE_RSA; - } - #ifdef WC_RSA_PSS - if (der->keyOID == RSAPSSk) { - type = DYNAMIC_TYPE_RSA; - } - #endif - #endif - #ifdef HAVE_ECC - if (der->keyOID == ECDSAk) { - type = DYNAMIC_TYPE_ECC; - } - #endif - #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) - if ((der->keyOID == DILITHIUM_LEVEL2k) || - (der->keyOID == DILITHIUM_LEVEL3k) || - (der->keyOID == DILITHIUM_LEVEL5k)) { - type = DYNAMIC_TYPE_DILITHIUM; - } - #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) - if ((der->keyOID == FALCON_LEVEL1k) || - (der->keyOID == FALCON_LEVEL5k)) { - type = DYNAMIC_TYPE_FALCON; - } - #endif - - ret = CreateDevPrivateKey(&pkey, buff, size, type, - isKeyLabel, isKeyId, heap, devId); - #ifdef WOLF_CRYPTO_CB - if (ret == 0) { - #ifndef NO_RSA - if (der->keyOID == RSAk - #ifdef WC_RSA_PSS - || der->keyOID == RSAPSSk - #endif - ) { - ret = wc_CryptoCb_RsaCheckPrivKey((RsaKey*)pkey, - der->publicKey, der->pubKeySize); - } - #endif - #ifdef HAVE_ECC - if (der->keyOID == ECDSAk) { - ret = wc_CryptoCb_EccCheckPrivKey((ecc_key*)pkey, - der->publicKey, der->pubKeySize); - } - #endif - #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) - if ((der->keyOID == DILITHIUM_LEVEL2k) || - (der->keyOID == DILITHIUM_LEVEL3k) || - (der->keyOID == DILITHIUM_LEVEL5k)) { - ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, - WC_PQC_SIG_TYPE_DILITHIUM, - der->publicKey, der->pubKeySize); - } - #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) - if ((der->keyOID == FALCON_LEVEL1k) || - (der->keyOID == FALCON_LEVEL5k)) { - ret = wc_CryptoCb_PqcSignatureCheckPrivKey(pkey, - WC_PQC_SIG_TYPE_FALCON, - der->publicKey, der->pubKeySize); - } - #endif - } - #else - /* devId was set, don't check, for now */ - /* TODO: Add callback for private key check? */ - #endif - if (pkey != NULL) { - #ifndef NO_RSA - if (der->keyOID == RSAk - #ifdef WC_RSA_PSS - || der->keyOID == RSAPSSk - #endif - ) { - wc_FreeRsaKey((RsaKey*)pkey); - } - #endif - #ifdef HAVE_ECC - if (der->keyOID == ECDSAk) { - wc_ecc_free((ecc_key*)pkey); - } - #endif - #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) - if ((der->keyOID == DILITHIUM_LEVEL2k) || - (der->keyOID == DILITHIUM_LEVEL3k) || - (der->keyOID == DILITHIUM_LEVEL5k)) { - wc_dilithium_free((dilithium_key*)pkey); - } - #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) - if ((der->keyOID == FALCON_LEVEL1k) || - (der->keyOID == FALCON_LEVEL5k)) { - wc_falcon_free((falcon_key*)pkey); - } - #endif - XFREE(pkey, heap, type); } - if (ret != CRYPTOCB_UNAVAILABLE) { - ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; - } - } - else { - /* fall through if unavailable */ - ret = CRYPTOCB_UNAVAILABLE; - } - - if (ret == CRYPTOCB_UNAVAILABLE) -#endif /* WOLF_PRIVATE_KEY_ID */ - { - ret = wc_CheckPrivateKeyCert(buff, size, der); - ret = (ret == 1) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; } - FreeDecodedCert(der); -#ifdef WOLFSSL_SMALL_STACK - XFREE(der, NULL, DYNAMIC_TYPE_DCERT); -#endif - - (void)devId; - (void)isKeyLabel; - (void)isKeyId; - - return ret; -} -/* Check private against public in certificate for match - * - * ctx WOLFSSL_CTX structure to check private key in - * - * Returns WOLFSSL_SUCCESS on good private key - * WOLFSSL_FAILURE if mismatched. */ -int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) -{ - if (ctx == NULL) { - return WOLFSSL_FAILURE; - } - return check_cert_key(ctx->certificate, ctx->privateKey, ctx->heap, - ctx->privateKeyDevId, ctx->privateKeyLabel, ctx->privateKeyId); + return opts; } -#endif /* !NO_CHECK_PRIVATE_KEY */ -#ifdef OPENSSL_ALL -/** - * Return the private key of the WOLFSSL_CTX struct - * @return WOLFSSL_EVP_PKEY* The caller doesn *NOT*` free the returned object. - */ -WOLFSSL_EVP_PKEY* wolfSSL_CTX_get0_privatekey(const WOLFSSL_CTX* ctx) +WOLFSSL_ABI +void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) { - const unsigned char *key; - int type; + SetVerifyOptions opts; - WOLFSSL_ENTER("wolfSSL_CTX_get0_privatekey"); + WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); + if (ctx == NULL) + return; - if (ctx == NULL || ctx->privateKey == NULL || - ctx->privateKey->buffer == NULL) { - WOLFSSL_MSG("Bad parameter or key not set"); - return NULL; - } + opts = ModeToVerifyOptions(mode); - switch (ctx->privateKeyType) { -#ifndef NO_RSA - case rsa_sa_algo: - type = EVP_PKEY_RSA; - break; -#endif -#ifdef HAVE_ECC - case ecc_dsa_sa_algo: - type = EVP_PKEY_EC; - break; -#endif -#ifdef WOLFSSL_SM2 - case sm2_sa_algo: - type = EVP_PKEY_EC; - break; + ctx->verifyNone = opts.verifyNone; + ctx->verifyPeer = opts.verifyPeer; + ctx->failNoCert = opts.failNoCert; + ctx->failNoCertxPSK = opts.failNoCertxPSK; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + ctx->verifyPostHandshake = opts.verifyPostHandshake; #endif - default: - /* Other key types not supported either as ssl private keys - * or in the EVP layer */ - WOLFSSL_MSG("Unsupported key type"); - return NULL; - } - key = ctx->privateKey->buffer; + ctx->verifyCallback = vc; +} - if (ctx->privateKeyPKey != NULL) - return ctx->privateKeyPKey; - else - return wolfSSL_d2i_PrivateKey(type, - (WOLFSSL_EVP_PKEY**)&ctx->privateKeyPKey, &key, - (long)ctx->privateKey->length); +#ifdef OPENSSL_ALL +void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx, + CertVerifyCallback cb, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback"); + if (ctx == NULL) + return; + + ctx->verifyCertCb = cb; + ctx->verifyCertCbArg = arg; } #endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -static WOLFSSL_EVP_PKEY* d2iGenericKey(WOLFSSL_EVP_PKEY** out, - const unsigned char** in, long inSz, int priv) +void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) { + SetVerifyOptions opts; - WOLFSSL_EVP_PKEY* pkey = NULL; - const unsigned char* mem; - long memSz = inSz; + WOLFSSL_ENTER("wolfSSL_set_verify"); + if (ssl == NULL) + return; - WOLFSSL_ENTER("d2iGenericKey"); + opts = ModeToVerifyOptions(mode); - if (in == NULL || *in == NULL || inSz < 0) { - WOLFSSL_MSG("Bad argument"); - return NULL; - } - mem = *in; + ssl->options.verifyNone = opts.verifyNone; + ssl->options.verifyPeer = opts.verifyPeer; + ssl->options.failNoCert = opts.failNoCert; + ssl->options.failNoCertxPSK = opts.failNoCertxPSK; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + ssl->options.verifyPostHandshake = opts.verifyPostHandshake; +#endif - #if !defined(NO_RSA) - { - word32 keyIdx = 0; - int isRsaKey; - #ifdef WOLFSSL_SMALL_STACK - RsaKey *rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); - if (rsa == NULL) - return NULL; - #else - RsaKey rsa[1]; - #endif - XMEMSET(rsa, 0, sizeof(RsaKey)); + ssl->verifyCallback = vc; +} - /* test if RSA key */ - if (priv) - isRsaKey = wc_InitRsaKey(rsa, NULL) == 0 && - wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0; - else - isRsaKey = wc_InitRsaKey(rsa, NULL) == 0 && - wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0; - wc_FreeRsaKey(rsa); - #ifdef WOLFSSL_SMALL_STACK - XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); - #endif +void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) +{ + WOLFSSL_ENTER("wolfSSL_set_verify_result"); - if (isRsaKey) { - pkey = wolfSSL_EVP_PKEY_new(); - if (pkey != NULL) { - pkey->pkey_sz = keyIdx; - pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, - priv ? DYNAMIC_TYPE_PRIVATE_KEY : - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, keyIdx); - pkey->type = EVP_PKEY_RSA; - if (out != NULL) { - *out = pkey; - } + if (ssl == NULL) + return; - pkey->ownRsa = 1; - pkey->rsa = wolfssl_rsa_d2i(NULL, mem, inSz, - priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC); - if (pkey->rsa == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(OPENSSL_ALL) + ssl->peerVerifyRet = (unsigned long)v; +#else + (void)v; + WOLFSSL_STUB("wolfSSL_set_verify_result"); +#endif +} - return pkey; - } - else { - WOLFSSL_MSG("RSA wolfSSL_EVP_PKEY_new error"); - } +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +/* For TLS v1.3 send handshake messages after handshake completes. */ +/* Returns 1=WOLFSSL_SUCCESS or 0=WOLFSSL_FAILURE */ +int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl) +{ + int ret = wolfSSL_request_certificate(ssl); + if (ret != WOLFSSL_SUCCESS) { + if (!IsAtLeastTLSv1_3(ssl->version)) { + /* specific error of wrong version expected */ + WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION); + + } + else { + WOLFSSL_ERROR(ret); /* log the error in the error queue */ } } - #endif /* NO_RSA */ - - #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) - { - word32 keyIdx = 0; - int isEccKey; - #ifdef WOLFSSL_SMALL_STACK - ecc_key *ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); - if (ecc == NULL) - return NULL; - #else - ecc_key ecc[1]; - #endif - XMEMSET(ecc, 0, sizeof(ecc_key)); - - if (priv) - isEccKey = wc_ecc_init(ecc) == 0 && - wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0; - else - isEccKey = wc_ecc_init(ecc) == 0 && - wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0; - wc_ecc_free(ecc); - #ifdef WOLFSSL_SMALL_STACK - XFREE(ecc, NULL, DYNAMIC_TYPE_ECC); - #endif + return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} - if (isEccKey) { - pkey = wolfSSL_EVP_PKEY_new(); - if (pkey != NULL) { - pkey->pkey_sz = keyIdx; - pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, - priv ? DYNAMIC_TYPE_PRIVATE_KEY : - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, keyIdx); - pkey->type = EVP_PKEY_EC; - if (out != NULL) { - *out = pkey; - } +int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val) +{ + int ret = wolfSSL_CTX_allow_post_handshake_auth(ctx); + if (ret == 0) { + ctx->postHandshakeAuth = (val != 0); + } + return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val) +{ + int ret = wolfSSL_allow_post_handshake_auth(ssl); + if (ret == 0) { + ssl->options.postHandshakeAuth = (val != 0); + } + return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_TLS13 && + * WOLFSSL_POST_HANDSHAKE_AUTH */ - pkey->ownEcc = 1; - pkey->ecc = wolfSSL_EC_KEY_new(); - if (pkey->ecc == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } +/* store user ctx for verify callback */ +void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); + if (ssl) + ssl->verifyCbCtx = ctx; +} - if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc, - (const unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE - : WOLFSSL_RSA_LOAD_PUBLIC) != 1) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - return pkey; - } - else { - WOLFSSL_MSG("ECC wolfSSL_EVP_PKEY_new error"); - } - } - } - #endif /* HAVE_ECC && OPENSSL_EXTRA */ +/* store user ctx for verify callback */ +void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx"); + if (ctx) + ctx->verifyCbCtx = userCtx; +} - #if !defined(NO_DSA) - { - word32 keyIdx = 0; - int isDsaKey; - #ifdef WOLFSSL_SMALL_STACK - DsaKey *dsa = (DsaKey*)XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA); - if (dsa == NULL) - return NULL; - #else - DsaKey dsa[1]; - #endif - XMEMSET(dsa, 0, sizeof(DsaKey)); - if (priv) - isDsaKey = wc_InitDsaKey(dsa) == 0 && - wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0; - else - isDsaKey = wc_InitDsaKey(dsa) == 0 && - wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0; - wc_FreeDsaKey(dsa); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); - #endif +/* store context CA Cache addition callback */ +void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) +{ + if (ctx && ctx->cm) + ctx->cm->caCacheCallback = cb; +} - /* test if DSA key */ - if (isDsaKey) { - pkey = wolfSSL_EVP_PKEY_new(); - - if (pkey != NULL) { - pkey->pkey_sz = keyIdx; - pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, - priv ? DYNAMIC_TYPE_PRIVATE_KEY : - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, keyIdx); - pkey->type = EVP_PKEY_DSA; - if (out != NULL) { - *out = pkey; - } - pkey->ownDsa = 1; - pkey->dsa = wolfSSL_DSA_new(); - if (pkey->dsa == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } +#if defined(PERSIST_CERT_CACHE) - if (wolfSSL_DSA_LoadDer_ex(pkey->dsa, - (const unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, priv ? WOLFSSL_RSA_LOAD_PRIVATE - : WOLFSSL_RSA_LOAD_PUBLIC) != 1) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } +#if !defined(NO_FILESYSTEM) - return pkey; - } - else { - WOLFSSL_MSG("DSA wolfSSL_EVP_PKEY_new error"); - } - } - } - #endif /* NO_DSA */ +/* 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 !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) - #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION > 2)) - { - int isDhKey; - word32 keyIdx = 0; - #ifdef WOLFSSL_SMALL_STACK - DhKey *dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); - if (dh == NULL) - return NULL; - #else - DhKey dh[1]; - #endif - XMEMSET(dh, 0, sizeof(DhKey)); + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; - isDhKey = wc_InitDhKey(dh) == 0 && - wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0; - wc_FreeDhKey(dh); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dh, NULL, DYNAMIC_TYPE_DH); - #endif + return CM_SaveCertCache(ctx->cm, fname); +} - /* test if DH key */ - if (isDhKey) { - pkey = wolfSSL_EVP_PKEY_new(); - - if (pkey != NULL) { - pkey->pkey_sz = (int)memSz; - pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, - priv ? DYNAMIC_TYPE_PRIVATE_KEY : - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, memSz); - pkey->type = EVP_PKEY_DH; - if (out != NULL) { - *out = pkey; - } - pkey->ownDh = 1; - pkey->dh = wolfSSL_DH_new(); - if (pkey->dh == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } +/* Persist cert cache from file */ +int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) +{ + WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache"); - if (wolfSSL_DH_LoadDer(pkey->dh, - (const unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz) != WOLFSSL_SUCCESS) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; - return pkey; - } - else { - WOLFSSL_MSG("DH wolfSSL_EVP_PKEY_new error"); - } - } - } - #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ - #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ + return CM_RestoreCertCache(ctx->cm, fname); +} - #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) - #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ - (HAVE_FIPS_VERSION > 2)) - { - word32 keyIdx = 0; - DhKey* key = NULL; - int ret; - #ifdef WOLFSSL_SMALL_STACK - DhKey* dh = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); - if (dh == NULL) - return NULL; - #else - DhKey dh[1]; - #endif - XMEMSET(dh, 0, sizeof(DhKey)); +#endif /* NO_FILESYSTEM */ - /* test if DH-public key */ - if (wc_InitDhKey(dh) != 0) - return NULL; +/* Persist cert cache to memory */ +int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, + int sz, int* used) +{ + WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache"); - ret = wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz); - wc_FreeDhKey(dh); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dh, NULL, DYNAMIC_TYPE_DH); - #endif + if (ctx == NULL || mem == NULL || used == NULL || sz <= 0) + return BAD_FUNC_ARG; - if (ret == 0) { - pkey = wolfSSL_EVP_PKEY_new(); - if (pkey != NULL) { - pkey->type = EVP_PKEY_DH; - pkey->pkey_sz = (int)memSz; - pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, - priv ? DYNAMIC_TYPE_PRIVATE_KEY : - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkey->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - XMEMCPY(pkey->pkey.ptr, mem, memSz); - if (out != NULL) { - *out = pkey; - } - pkey->ownDh = 1; - pkey->dh = wolfSSL_DH_new(); - if (pkey->dh == NULL) { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } + return CM_MemSaveCertCache(ctx->cm, mem, sz, used); +} - key = (DhKey*)pkey->dh->internal; - - keyIdx = 0; - if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) == 0) - { - int elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | - ELEMENT_PUB; - if (priv) - elements |= ELEMENT_PRV; - if(SetDhExternal_ex(pkey->dh, elements) - == WOLFSSL_SUCCESS ) { - return pkey; - } - } - else { - wolfSSL_EVP_PKEY_free(pkey); - return NULL; - } - } - } - } - #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ - #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ - #ifdef HAVE_PQC - #ifdef HAVE_FALCON - { - int isFalcon = 0; - #ifdef WOLFSSL_SMALL_STACK - falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(falcon_key), NULL, - DYNAMIC_TYPE_FALCON); - if (falcon == NULL) { - return NULL; - } - #else - falcon_key falcon[1]; - #endif +/* Restore cert cache from memory */ +int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz) +{ + WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache"); - if (wc_falcon_init(falcon) == 0) { - /* test if Falcon key */ - if (priv) { - /* Try level 1 */ - isFalcon = wc_falcon_set_level(falcon, 1) == 0 && - wc_falcon_import_private_only(mem, (word32)memSz, - falcon) == 0; - if (!isFalcon) { - /* Try level 5 */ - isFalcon = wc_falcon_set_level(falcon, 5) == 0 && - wc_falcon_import_private_only(mem, (word32)memSz, - falcon) == 0; - } - } else { - /* Try level 1 */ - isFalcon = wc_falcon_set_level(falcon, 1) == 0 && - wc_falcon_import_public(mem, (word32)memSz, falcon) - == 0; - - if (!isFalcon) { - /* Try level 5 */ - isFalcon = wc_falcon_set_level(falcon, 5) == 0 && - wc_falcon_import_public(mem, (word32)memSz, - falcon) == 0; - } - } - wc_falcon_free(falcon); - } + if (ctx == NULL || mem == NULL || sz <= 0) + return BAD_FUNC_ARG; - #ifdef WOLFSSL_SMALL_STACK - XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); - #endif - if (isFalcon) { - /* Create a fake Falcon EVP_PKEY. In the future, we might integrate - * Falcon into the compatibility layer. */ - pkey = wolfSSL_EVP_PKEY_new(); - if (pkey == NULL) { - WOLFSSL_MSG("Falcon wolfSSL_EVP_PKEY_new error"); - return NULL; - } - pkey->type = EVP_PKEY_FALCON; - pkey->pkey.ptr = NULL; - pkey->pkey_sz = 0; - return pkey; - } + return CM_MemRestoreCertCache(ctx->cm, mem, sz); +} - } - #endif /* HAVE_FALCON */ - #ifdef HAVE_DILITHIUM - { - int isDilithium = 0; - #ifdef WOLFSSL_SMALL_STACK - dilithium_key *dilithium = (dilithium_key *) - XMALLOC(sizeof(dilithium_key), NULL, DYNAMIC_TYPE_DILITHIUM); - if (dilithium == NULL) { - return NULL; - } - #else - dilithium_key dilithium[1]; - #endif - if (wc_dilithium_init(dilithium) == 0) { - /* Test if Dilithium key. Try all levels. */ - if (priv) { - isDilithium = wc_dilithium_set_level(dilithium, 2) == 0 && - wc_dilithium_import_private_only(mem, - (word32)memSz, dilithium) == 0; - if (!isDilithium) { - isDilithium = wc_dilithium_set_level(dilithium, 3) == 0 && - wc_dilithium_import_private_only(mem, - (word32)memSz, dilithium) == 0; - } - if (!isDilithium) { - isDilithium = wc_dilithium_set_level(dilithium, 5) == 0 && - wc_dilithium_import_private_only(mem, - (word32)memSz, dilithium) == 0; - } - } else { - isDilithium = wc_dilithium_set_level(dilithium, 2) == 0 && - wc_dilithium_import_public(mem, (word32)memSz, - dilithium) == 0; - if (!isDilithium) { - isDilithium = wc_dilithium_set_level(dilithium, 3) == 0 && - wc_dilithium_import_public(mem, (word32)memSz, - dilithium) == 0; - } - if (!isDilithium) { - isDilithium = wc_dilithium_set_level(dilithium, 5) == 0 && - wc_dilithium_import_public(mem, (word32)memSz, - dilithium) == 0; - } - } - wc_dilithium_free(dilithium); - } +/* get how big the the cert cache save buffer needs to be */ +int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); - #endif - if (isDilithium) { - /* Create a fake Dilithium EVP_PKEY. In the future, we might - * integrate Dilithium into the compatibility layer. */ - pkey = wolfSSL_EVP_PKEY_new(); - if (pkey == NULL) { - WOLFSSL_MSG("Dilithium wolfSSL_EVP_PKEY_new error"); - return NULL; - } - pkey->type = EVP_PKEY_DILITHIUM; - pkey->pkey.ptr = NULL; - pkey->pkey_sz = 0; - return pkey; - } + if (ctx == NULL) + return BAD_FUNC_ARG; - } - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ + return CM_GetCertCacheMemSize(ctx->cm); +} - if (pkey == NULL) { - WOLFSSL_MSG("wolfSSL_d2i_PUBKEY couldn't determine key type"); - } +#endif /* PERSIST_CERT_CACHE */ +#endif /* !NO_CERTS */ - return pkey; +void wolfSSL_load_error_strings(void) +{ + /* compatibility only */ } -#endif /* OPENSSL_EXTRA || WPA_SMALL */ -#ifdef OPENSSL_EXTRA -WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY( - WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, long keyLen) +int wolfSSL_library_init(void) { - WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; -#ifdef WOLFSSL_PEM_TO_DER - int ret; - DerBuffer* der = NULL; - - if (keyBuf == NULL || *keyBuf == NULL || keyLen <= 0) { - WOLFSSL_MSG("Bad key PEM/DER args"); - return NULL; - } + WOLFSSL_ENTER("wolfSSL_library_init"); + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; +} - ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &der, NULL, NULL, NULL); - if (ret < 0) { - WOLFSSL_MSG("Not PEM format"); - ret = AllocDer(&der, (word32)keyLen, PRIVATEKEY_TYPE, NULL); - if (ret == 0) { - XMEMCPY(der->buffer, *keyBuf, keyLen); - } - } - if (ret == 0) { - /* Verify this is PKCS8 Key */ - word32 inOutIdx = 0; - word32 algId; - ret = ToTraditionalInline_ex(der->buffer, &inOutIdx, der->length, &algId); - if (ret >= 0) { - ret = 0; /* good DER */ - } - } +#ifdef HAVE_SECRET_CALLBACK - if (ret == 0) { - pkcs8 = wolfSSL_EVP_PKEY_new(); - if (pkcs8 == NULL) - ret = MEMORY_E; - } - if (ret == 0) { - pkcs8->pkey.ptr = (char*)XMALLOC(der->length, NULL, - DYNAMIC_TYPE_PUBLIC_KEY); - if (pkcs8->pkey.ptr == NULL) - ret = MEMORY_E; - } - if (ret == 0) { - XMEMCPY(pkcs8->pkey.ptr, der->buffer, der->length); - pkcs8->pkey_sz = der->length; - } +int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_set_session_secret_cb"); + if (ssl == NULL) + return WOLFSSL_FAILURE; - FreeDer(&der); - if (ret != 0) { - wolfSSL_EVP_PKEY_free(pkcs8); - pkcs8 = NULL; - } - if (pkey != NULL) { - *pkey = pkcs8; + ssl->sessionSecretCb = cb; + ssl->sessionSecretCtx = ctx; + if (cb != NULL) { + /* If using a pre-set key, assume session resumption. */ + ssl->session->sessionIDSz = 0; + ssl->options.resuming = 1; } -#else - (void)bio; - (void)pkey; -#endif /* WOLFSSL_PEM_TO_DER */ - - return pkcs8; + return WOLFSSL_SUCCESS; } - -#ifndef NO_BIO -/* put SSL type in extra for now, not very common */ - -/* Converts a DER format key read from "bio" to a PKCS8 structure. - * - * bio input bio to read DER from - * pkey If not NULL then this pointer will be overwritten with a new PKCS8 - * structure. - * - * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail - * case. - */ -WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, - WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey) +int wolfSSL_set_session_ticket_ext_cb(WOLFSSL* ssl, TicketParseCb cb, + void *ctx) { - WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; -#ifdef WOLFSSL_PEM_TO_DER - unsigned char* mem = NULL; - int memSz; + WOLFSSL_ENTER("wolfSSL_set_session_ticket_ext_cb"); + if (ssl == NULL) + return WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio"); + ssl->ticketParseCb = cb; + ssl->ticketParseCtx = ctx; - if (bio == NULL) { - return NULL; - } + return WOLFSSL_SUCCESS; +} - if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { - return NULL; - } +int wolfSSL_set_secret_cb(WOLFSSL* ssl, TlsSecretCb cb, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_set_secret_cb"); + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; - pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz); -#else - (void)bio; - (void)pkey; -#endif /* WOLFSSL_PEM_TO_DER */ + ssl->tlsSecretCb = cb; + ssl->tlsSecretCtx = ctx; - return pkcs8; + return WOLFSSL_SUCCESS; } - -/* expecting DER format public key - * - * bio input bio to read DER from - * out If not NULL then this pointer will be overwritten with a new - * WOLFSSL_EVP_PKEY pointer - * - * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case. - */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** out) +#ifdef SHOW_SECRETS +int tlsShowSecrets(WOLFSSL* ssl, void* secret, int secretSz, + void* ctx) { - unsigned char* mem; - long memSz; - WOLFSSL_EVP_PKEY* pkey = NULL; + /* Wireshark Pre-Master-Secret Format: + * CLIENT_RANDOM + */ + const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM"; + int i, pmsPos = 0; + char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1]; + byte clientRandom[RAN_LEN]; + int clientRandomSz; - WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio"); + (void)ctx; - if (bio == NULL) { - return NULL; - } - (void)out; + clientRandomSz = (int)wolfSSL_get_client_random(ssl, clientRandom, + sizeof(clientRandom)); - memSz = wolfSSL_BIO_get_len(bio); - if (memSz <= 0) { - return NULL; + if (clientRandomSz <= 0) { + printf("Error getting server random %d\n", clientRandomSz); + return BAD_FUNC_ARG; } - mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (mem == NULL) { - return NULL; + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ", + CLIENT_RANDOM_LABEL); + pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1; + for (i = 0; i < clientRandomSz; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + clientRandom[i]); + pmsPos += 2; } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " "); + pmsPos += 1; + for (i = 0; i < secretSz; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ((byte*)secret)[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n"); + pmsPos += 1; - if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { - pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz); - if (out != NULL && pkey != NULL) { - *out = pkey; + /* print master secret */ + puts(pmsBuf); + + #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) + { + FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a"); + if (f != XBADFILE) { + XFWRITE(pmsBuf, 1, pmsPos, f); + XFCLOSE(f); } } - - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return pkey; + #endif + return 0; } +#endif /* SHOW_SECRETS */ -#endif /* !NO_BIO */ +#endif -/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. - * - * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL - * in DER buffer to convert - * inSz size of in buffer - * - * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL - * on fail +#ifdef OPENSSL_EXTRA + +/* + * check if the list has TLS13 and pre-TLS13 suites + * @param list cipher suite list that user want to set + * (caller required to check for NULL) + * @return mixed: 0, only pre-TLS13: 1, only TLS13: 2 */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, - const unsigned char** in, long inSz) +static int CheckcipherList(const char* list) { - WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); - return d2iGenericKey(out, in, inSz, 0); -} + int ret; + int findTLSv13Suites = 0; + int findbeforeSuites = 0; + byte cipherSuite0; + byte cipherSuite1; + int flags; + char* next = (char*)list; -#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN) && \ - !defined(NO_PWDBASED) + do { + char* current = next; + char name[MAX_SUITE_NAME + 1]; + word32 length = MAX_SUITE_NAME; + word32 current_length; -/* helper function to get raw pointer to DER buffer from WOLFSSL_EVP_PKEY */ -static int wolfSSL_EVP_PKEY_get_der(const WOLFSSL_EVP_PKEY* key, unsigned char** der) -{ - int sz; - word16 pkcs8HeaderSz; + next = XSTRSTR(next, ":"); - if (!key || !key->pkey_sz) - return WOLFSSL_FATAL_ERROR; + current_length = (!next) ? (word32)XSTRLEN(current) + : (word32)(next - current); + if (current_length == 0) { + break; + } - /* return the key without PKCS8 for compatibility */ - /* if pkcs8HeaderSz is invalid, use 0 and return all of pkey */ - pkcs8HeaderSz = 0; - if (key->pkey_sz > key->pkcs8HeaderSz) - pkcs8HeaderSz = key->pkcs8HeaderSz; - sz = key->pkey_sz - pkcs8HeaderSz; - if (der) { - unsigned char* pt = (unsigned char*)key->pkey.ptr; - if (*der) { - /* since this function signature has no size value passed in it is - * assumed that the user has allocated a large enough buffer */ - XMEMCPY(*der, pt + pkcs8HeaderSz, sz); - *der += sz; + if (current_length < length) { + length = current_length; } - else { - *der = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); - if (*der == NULL) { - return WOLFSSL_FATAL_ERROR; + XMEMCPY(name, current, length); + name[length] = 0; + + if (XSTRCMP(name, "ALL") == 0 || + XSTRCMP(name, "DEFAULT") == 0 || + XSTRCMP(name, "HIGH") == 0) + { + findTLSv13Suites = 1; + findbeforeSuites = 1; + break; + } + + ret = wolfSSL_get_cipher_suite_from_name(name, &cipherSuite0, + &cipherSuite1, &flags); + if (ret == 0) { + if (cipherSuite0 == TLS13_BYTE) { + /* TLSv13 suite */ + findTLSv13Suites = 1; + } + else { + findbeforeSuites = 1; } - XMEMCPY(*der, pt + pkcs8HeaderSz, sz); } - } - return sz; -} -int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der) -{ - return wolfSSL_i2d_PublicKey(key, der); -} + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + /* check if mixed due to names like RSA:ECDHE+AESGCM etc. */ + if (ret != 0) { + char* subStr = name; + char* subStrNext; -#endif /* OPENSSL_EXTRA && !NO_CERTS && !NO_ASN && !NO_PWDBASED */ + do { + subStrNext = XSTRSTR(subStr, "+"); -static WOLFSSL_EVP_PKEY* _d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, - const unsigned char **in, long inSz, int priv) -{ - int ret = 0; - word32 idx = 0, algId; - word16 pkcs8HeaderSz = 0; - WOLFSSL_EVP_PKEY* local; - int opt = 0; - - (void)opt; - - if (in == NULL || inSz < 0) { - WOLFSSL_MSG("Bad argument"); - return NULL; - } - - if (priv == 1) { - /* Check if input buffer has PKCS8 header. In the case that it does not - * have a PKCS8 header then do not error out. */ - if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, - (word32)inSz, &algId)) > 0) { - WOLFSSL_MSG("Found PKCS8 header"); - pkcs8HeaderSz = (word16)idx; - - if ((type == EVP_PKEY_RSA && algId != RSAk - #ifdef WC_RSA_PSS - && algId != RSAPSSk - #endif - ) || - (type == EVP_PKEY_EC && algId != ECDSAk) || - (type == EVP_PKEY_DSA && algId != DSAk) || - (type == EVP_PKEY_DH && algId != DHk)) { - WOLFSSL_MSG("PKCS8 does not match EVP key type"); - return NULL; - } + if ((XSTRCMP(subStr, "ECDHE") == 0) || + (XSTRCMP(subStr, "RSA") == 0)) { + return 0; + } - (void)idx; /* not used */ + if (subStrNext && (XSTRLEN(subStrNext) > 0)) { + subStr = subStrNext + 1; /* +1 to skip past '+' */ + } + } while (subStrNext != NULL); } - else { - if (ret != ASN_PARSE_E) { - WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 " - "header"); - return NULL; - } + #endif + + if (findTLSv13Suites == 1 && findbeforeSuites == 1) { + /* list has mixed suites */ + return 0; } } + while (next++); /* increment to skip ':' */ - if (out != NULL && *out != NULL) { - wolfSSL_EVP_PKEY_free(*out); - *out = NULL; - } - local = wolfSSL_EVP_PKEY_new(); - if (local == NULL) { - return NULL; + if (findTLSv13Suites == 0 && findbeforeSuites == 1) { + ret = 1;/* only before TLSv13 suites */ } - - local->type = type; - local->pkey_sz = (int)inSz; - local->pkcs8HeaderSz = pkcs8HeaderSz; - local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (local->pkey.ptr == NULL) { - wolfSSL_EVP_PKEY_free(local); - local = NULL; - return NULL; + else if (findTLSv13Suites == 1 && findbeforeSuites == 0) { + ret = 2;/* only TLSv13 suties */ } else { - XMEMCPY(local->pkey.ptr, *in, inSz); - } - - switch (type) { -#ifndef NO_RSA - case EVP_PKEY_RSA: - opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC; - local->ownRsa = 1; - local->rsa = wolfssl_rsa_d2i(NULL, - (const unsigned char*)local->pkey.ptr, local->pkey_sz, opt); - if (local->rsa == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - break; -#endif /* NO_RSA */ -#ifdef HAVE_ECC - case EVP_PKEY_EC: - local->ownEcc = 1; - local->ecc = wolfSSL_EC_KEY_new(); - if (local->ecc == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE : - WOLFSSL_EC_KEY_LOAD_PUBLIC; - if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc, - (const unsigned char*)local->pkey.ptr, local->pkey_sz, - opt) - != WOLFSSL_SUCCESS) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - break; -#endif /* HAVE_ECC */ -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) -#ifndef NO_DSA - case EVP_PKEY_DSA: - local->ownDsa = 1; - local->dsa = wolfSSL_DSA_new(); - if (local->dsa == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC; - if (wolfSSL_DSA_LoadDer_ex(local->dsa, - (const unsigned char*)local->pkey.ptr, local->pkey_sz, - opt) - != WOLFSSL_SUCCESS) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - break; -#endif /* NO_DSA */ -#ifndef NO_DH -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) - case EVP_PKEY_DH: - local->ownDh = 1; - local->dh = wolfSSL_DH_new(); - if (local->dh == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - if (wolfSSL_DH_LoadDer(local->dh, - (const unsigned char*)local->pkey.ptr, local->pkey_sz) - != WOLFSSL_SUCCESS) { - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - break; -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* HAVE_DH */ -#endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */ - default: - WOLFSSL_MSG("Unsupported key type"); - wolfSSL_EVP_PKEY_free(local); - return NULL; - } - - /* advance pointer with success */ - if (local != NULL) { - if (local->pkey_sz <= (int)inSz) { - *in += local->pkey_sz; - } - - if (out != NULL) { - *out = local; - } + ret = 0;/* handle as mixed */ } - - return local; + return ret; } -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, - const unsigned char **in, long inSz) -{ - WOLFSSL_ENTER("wolfSSL_d2i_PublicKey"); - - return _d2i_PublicKey(type, out, in, inSz, 0); -} -/* Reads in a DER format key. If PKCS8 headers are found they are stripped off. - * - * type type of key - * out newly created WOLFSSL_EVP_PKEY structure - * in pointer to input key DER - * inSz size of in buffer +/* parse some bulk lists like !eNULL / !aNULL * - * On success a non null pointer is returned and the pointer in is advanced the - * same number of bytes read. + * returns WOLFSSL_SUCCESS on success and sets the cipher suite list */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, - const unsigned char **in, long inSz) +static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + Suites* suites, const char* list) { - WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); + int ret = 0; + int listattribute = 0; + int tls13Only = 0; +#ifndef WOLFSSL_SMALL_STACK + byte suitesCpy[WOLFSSL_MAX_SUITE_SZ]; +#else + byte* suitesCpy = NULL; +#endif + word16 suitesCpySz = 0; + word16 i = 0; + word16 j = 0; - return _d2i_PublicKey(type, out, in, inSz, 1); -} + if (suites == NULL || list == NULL) { + WOLFSSL_MSG("NULL argument"); + return WOLFSSL_FAILURE; + } -#ifdef WOLF_PRIVATE_KEY_ID -/* Create an EVP structure for use with crypto callbacks */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out, - void* heap, int devId) -{ - WOLFSSL_EVP_PKEY* local; + listattribute = CheckcipherList(list); - if (out != NULL && *out != NULL) { - wolfSSL_EVP_PKEY_free(*out); - *out = NULL; + if (listattribute == 0) { + /* list has mixed(pre-TLSv13 and TLSv13) suites + * update cipher suites the same as before + */ + return (SetCipherList_ex(ctx, ssl, suites, list)) ? WOLFSSL_SUCCESS : + WOLFSSL_FAILURE; + } + else if (listattribute == 1) { + /* list has only pre-TLSv13 suites. + * Only update before TLSv13 suites. + */ + tls13Only = 0; + } + else if (listattribute == 2) { + /* list has only TLSv13 suites. Only update TLv13 suites + * simulate set_ciphersuites() compatibility layer API + */ + tls13Only = 1; + if ((ctx != NULL && !IsAtLeastTLSv1_3(ctx->method->version)) || + (ssl != NULL && !IsAtLeastTLSv1_3(ssl->version))) { + /* Silently ignore TLS 1.3 ciphers if we don't support it. */ + return WOLFSSL_SUCCESS; + } } - local = wolfSSL_EVP_PKEY_new_ex(heap); - if (local == NULL) { - return NULL; + /* list contains ciphers either only for TLS 1.3 or <= TLS 1.2 */ + if (suites->suiteSz == 0) { + WOLFSSL_MSG("Warning suites->suiteSz = 0 set to WOLFSSL_MAX_SUITE_SZ"); + suites->suiteSz = WOLFSSL_MAX_SUITE_SZ; } +#ifdef WOLFSSL_SMALL_STACK + if (suites->suiteSz > 0) { + suitesCpy = (byte*)XMALLOC(suites->suiteSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (suitesCpy == NULL) { + return WOLFSSL_FAILURE; + } - local->type = type; - local->pkey_sz = 0; - local->pkcs8HeaderSz = 0; + XMEMSET(suitesCpy, 0, suites->suiteSz); + } +#else + XMEMSET(suitesCpy, 0, sizeof(suitesCpy)); +#endif - switch (type) { -#ifndef NO_RSA - case EVP_PKEY_RSA: - { - RsaKey* key; - local->ownRsa = 1; - local->rsa = wolfSSL_RSA_new_ex(heap, devId); - if (local->rsa == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; + if (suites->suiteSz > 0) + XMEMCPY(suitesCpy, suites->suites, suites->suiteSz); + suitesCpySz = suites->suiteSz; + + ret = SetCipherList_ex(ctx, ssl, suites, list); + if (ret != 1) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return WOLFSSL_FAILURE; + } + + for (i = 0; i < suitesCpySz && + suites->suiteSz <= (WOLFSSL_MAX_SUITE_SZ - SUITE_LEN); i += 2) { + /* Check for duplicates */ + int duplicate = 0; + for (j = 0; j < suites->suiteSz; j += 2) { + if (suitesCpy[i] == suites->suites[j] && + suitesCpy[i+1] == suites->suites[j+1]) { + duplicate = 1; + break; } - key = (RsaKey*)local->rsa->internal; - #ifdef WOLF_CRYPTO_CB - key->devId = devId; - #endif - (void)key; - local->rsa->inSet = 1; - break; } -#endif /* !NO_RSA */ -#ifdef HAVE_ECC - case EVP_PKEY_EC: - { - ecc_key* key; - local->ownEcc = 1; - local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId); - if (local->ecc == NULL) { - wolfSSL_EVP_PKEY_free(local); - return NULL; + if (!duplicate) { + if (tls13Only) { + /* Updating TLS 1.3 ciphers */ + if (suitesCpy[i] != TLS13_BYTE) { + /* Only copy over <= TLS 1.2 ciphers */ + /* TLS 1.3 ciphers take precedence */ + suites->suites[suites->suiteSz++] = suitesCpy[i]; + suites->suites[suites->suiteSz++] = suitesCpy[i+1]; + } + } + else { + /* Updating <= TLS 1.2 ciphers */ + if (suitesCpy[i] == TLS13_BYTE) { + /* Only copy over TLS 1.3 ciphers */ + /* TLS 1.3 ciphers take precedence */ + XMEMMOVE(suites->suites + SUITE_LEN, suites->suites, + suites->suiteSz); + suites->suites[0] = suitesCpy[i]; + suites->suites[1] = suitesCpy[i+1]; + suites->suiteSz += 2; + } } - key = (ecc_key*)local->ecc->internal; - #ifdef WOLF_CRYPTO_CB - key->devId = devId; - #endif - key->type = ECC_PRIVATEKEY; - /* key is required to have a key size / curve set, although - * actual one used is determined by devId callback function */ - wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF); - - local->ecc->inSet = 1; - break; } -#endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Unsupported private key id type"); - wolfSSL_EVP_PKEY_free(local); - return NULL; } - if (local != NULL && out != NULL) { - *out = local; - } - - return local; +#ifdef WOLFSSL_SMALL_STACK + XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } -#endif /* WOLF_PRIVATE_KEY_ID */ -#ifndef NO_CERTS /* // NOLINT(readability-redundant-preprocessor) */ +#endif -#ifndef NO_CHECK_PRIVATE_KEY -/* Check private against public in certificate for match - * - * ssl WOLFSSL structure to check private key in - * - * Returns WOLFSSL_SUCCESS on good private key - * WOLFSSL_FAILURE if mismatched. */ -int wolfSSL_check_private_key(const WOLFSSL* ssl) + +int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } - return check_cert_key(ssl->buffers.certificate, ssl->buffers.key, ssl->heap, - ssl->buffers.keyDevId, ssl->buffers.keyLabel, ssl->buffers.keyId); -} -#endif /* !NO_CHECK_PRIVATE_KEY */ + WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list"); -#endif /* !NO_CERTS */ + if (ctx == NULL) + return WOLFSSL_FAILURE; -int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) -{ - WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); - if (ssl == NULL || pkey == NULL ) { + if (AllocateCtxSuites(ctx) != 0) return WOLFSSL_FAILURE; - } - return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1); +#ifdef OPENSSL_EXTRA + return wolfSSL_parse_cipher_list(ctx, NULL, ctx->suites, list); +#else + return (SetCipherList(ctx, ctx->suites, list)) ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +#endif } - -int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der, - long derSz) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES) +int wolfSSL_CTX_set_cipher_list_bytes(WOLFSSL_CTX* ctx, const byte* list, + const int listSz) { - WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); - if (ssl == NULL || der == NULL ) { + WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list_bytes"); + + if (ctx == NULL) return WOLFSSL_FAILURE; - } - (void)pri; /* type of private key */ - return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); + if (AllocateCtxSuites(ctx) != 0) + return WOLFSSL_FAILURE; + + return (SetCipherListFromBytes(ctx, ctx->suites, list, listSz)) ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } -/****************************************************************************** -* wolfSSL_CTX_use_PrivateKey_ASN1 - loads a private key buffer into the SSL ctx -* -* RETURNS: -* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE -*/ +#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ -int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, - unsigned char* der, long derSz) +int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) { - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1"); - if (ctx == NULL || der == NULL ) { + WOLFSSL_ENTER("wolfSSL_set_cipher_list"); + + if (ssl == NULL || ssl->ctx == NULL) { return WOLFSSL_FAILURE; } - (void)pri; /* type of private key */ - return wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1); -} + if (AllocateSuites(ssl) != 0) + return WOLFSSL_FAILURE; +#ifdef OPENSSL_EXTRA + return wolfSSL_parse_cipher_list(NULL, ssl, ssl->suites, list); +#else + return (SetCipherList_ex(NULL, ssl, ssl->suites, list)) ? + WOLFSSL_SUCCESS : + WOLFSSL_FAILURE; +#endif +} -#ifndef NO_RSA -int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES) +int wolfSSL_set_cipher_list_bytes(WOLFSSL* ssl, const byte* list, + const int listSz) { - WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); - if (ssl == NULL || der == NULL ) { + WOLFSSL_ENTER("wolfSSL_set_cipher_list_bytes"); + + if (ssl == NULL || ssl->ctx == NULL) { return WOLFSSL_FAILURE; } - return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); + if (AllocateSuites(ssl) != 0) + return WOLFSSL_FAILURE; + + return (SetCipherListFromBytes(ssl->ctx, ssl->suites, list, listSz)) + ? WOLFSSL_SUCCESS + : WOLFSSL_FAILURE; } -#endif +#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ -int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) -{ - long idx = 0; - WOLFSSL_ENTER("wolfSSL_use_certificate"); - if (x509 != NULL && ssl != NULL && x509->derCert != NULL) { - if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, - WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0, - GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } - } +#ifdef HAVE_KEYING_MATERIAL - (void)idx; - return WOLFSSL_FAILURE; -} +#define TLS_PRF_LABEL_CLIENT_FINISHED "client finished" +#define TLS_PRF_LABEL_SERVER_FINISHED "server finished" +#define TLS_PRF_LABEL_MASTER_SECRET "master secret" +#define TLS_PRF_LABEL_EXT_MASTER_SECRET "extended master secret" +#define TLS_PRF_LABEL_KEY_EXPANSION "key expansion" -#endif /* OPENSSL_EXTRA */ +static const struct ForbiddenLabels { + const char* label; + size_t labelLen; +} forbiddenLabels[] = { + {TLS_PRF_LABEL_CLIENT_FINISHED, XSTR_SIZEOF(TLS_PRF_LABEL_CLIENT_FINISHED)}, + {TLS_PRF_LABEL_SERVER_FINISHED, XSTR_SIZEOF(TLS_PRF_LABEL_SERVER_FINISHED)}, + {TLS_PRF_LABEL_MASTER_SECRET, XSTR_SIZEOF(TLS_PRF_LABEL_MASTER_SECRET)}, + {TLS_PRF_LABEL_EXT_MASTER_SECRET, + XSTR_SIZEOF(TLS_PRF_LABEL_EXT_MASTER_SECRET)}, + {TLS_PRF_LABEL_KEY_EXPANSION, XSTR_SIZEOF(TLS_PRF_LABEL_KEY_EXPANSION)}, + {NULL, 0}, +}; -#if defined(HAVE_RPK) -/* Confirm that all the byte data in the buffer is unique. - * return 1 if all the byte data in the buffer is unique, otherwise 0. +/** + * Implement RFC 5705 + * TLS 1.3 uses a different exporter definition (section 7.5 of RFC 8446) + * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ -static int isArrayUnique(const char* buf, size_t len) +int wolfSSL_export_keying_material(WOLFSSL *ssl, + unsigned char *out, size_t outLen, + const char *label, size_t labelLen, + const unsigned char *context, size_t contextLen, + int use_context) { - size_t i, j; - /* check the array is unique */ - for (i = 0; i < len -1; ++i) { - for (j = i+ 1; j < len; ++j) { - if (buf[i] == buf[j]) { - return 0; - } - } - } - return 1; -} + byte* seed = NULL; + word32 seedLen; + const struct ForbiddenLabels* fl; -/* Set user preference for the client_cert_type exetnsion. - * Takes byte array containing cert types the caller can provide to its peer. - * Cert types are in preferred order in the array. - */ -WOLFSSL_API int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, - const char* buf, int bufLen) -{ - int i; + WOLFSSL_ENTER("wolfSSL_export_keying_material"); - if (ctx == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { - return BAD_FUNC_ARG; + if (ssl == NULL || out == NULL || label == NULL || + (use_context && contextLen && context == NULL)) { + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; } - /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ - if (buf == NULL || bufLen == 0) { - ctx->rpkConfig.preferred_ClientCertTypeCnt = 1; - ctx->rpkConfig.preferred_ClientCertTypes[0]= WOLFSSL_CERT_TYPE_X509; - ctx->rpkConfig.preferred_ClientCertTypes[1]= WOLFSSL_CERT_TYPE_X509; - return WOLFSSL_SUCCESS; - } + /* clientRandom + serverRandom + * OR + * clientRandom + serverRandom + ctx len encoding + ctx */ + seedLen = !use_context ? (word32)SEED_LEN : + (word32)SEED_LEN + 2 + (word32)contextLen; - if (!isArrayUnique(buf, bufLen)) - return BAD_FUNC_ARG; + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("To export keying material wolfSSL needs to keep handshake " + "data. Call wolfSSL_KeepArrays before attempting to " + "export keyid material."); + return WOLFSSL_FAILURE; + } - for (i = 0; i < bufLen; i++){ - if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) - return BAD_FUNC_ARG; - - ctx->rpkConfig.preferred_ClientCertTypes[i] = buf[i]; + /* check forbidden labels */ + for (fl = &forbiddenLabels[0]; fl->label != NULL; fl++) { + if (labelLen >= fl->labelLen && + XMEMCMP(label, fl->label, fl->labelLen) == 0) { + WOLFSSL_MSG("Forbidden label"); + return WOLFSSL_FAILURE; + } } - ctx->rpkConfig.preferred_ClientCertTypeCnt = bufLen; - - return WOLFSSL_SUCCESS; -} -/* Set user preference for the server_cert_type exetnsion. - * Takes byte array containing cert types the caller can provide to its peer. - * Cert types are in preferred order in the array. - */ -WOLFSSL_API int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, - const char* buf, int bufLen) -{ - int i; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + /* Path for TLS 1.3 */ + if (!use_context) { + contextLen = 0; + context = (byte*)""; /* Give valid pointer for 0 length memcpy */ + } - if (ctx == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { - return BAD_FUNC_ARG; + if (Tls13_Exporter(ssl, out, (word32)outLen, label, labelLen, + context, contextLen) != 0) { + WOLFSSL_MSG("Tls13_Exporter error"); + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; } +#endif - /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ - if (buf == NULL || bufLen == 0) { - ctx->rpkConfig.preferred_ServerCertTypeCnt = 1; - ctx->rpkConfig.preferred_ServerCertTypes[0]= WOLFSSL_CERT_TYPE_X509; - ctx->rpkConfig.preferred_ServerCertTypes[1]= WOLFSSL_CERT_TYPE_X509; - return WOLFSSL_SUCCESS; + /* Path for <=TLS 1.2 */ + seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (seed == NULL) { + WOLFSSL_MSG("malloc error"); + return WOLFSSL_FAILURE; } - if (!isArrayUnique(buf, bufLen)) - return BAD_FUNC_ARG; + XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - for (i = 0; i < bufLen; i++){ - if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) - return BAD_FUNC_ARG; + if (use_context) { + /* Encode len in big endian */ + seed[SEED_LEN ] = (contextLen >> 8) & 0xFF; + seed[SEED_LEN + 1] = (contextLen) & 0xFF; + if (contextLen) { + /* 0 length context is allowed */ + XMEMCPY(seed + SEED_LEN + 2, context, contextLen); + } + } - ctx->rpkConfig.preferred_ServerCertTypes[i] = buf[i]; + PRIVATE_KEY_UNLOCK(); + if (wc_PRF_TLS(out, (word32)outLen, ssl->arrays->masterSecret, SECRET_LEN, + (byte*)label, (word32)labelLen, seed, seedLen, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, + ssl->devId) != 0) { + WOLFSSL_MSG("wc_PRF_TLS error"); + PRIVATE_KEY_LOCK(); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; } - ctx->rpkConfig.preferred_ServerCertTypeCnt = bufLen; + PRIVATE_KEY_LOCK(); + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); return WOLFSSL_SUCCESS; } +#endif /* HAVE_KEYING_MATERIAL */ -/* Set user preference for the client_cert_type exetnsion. - * Takes byte array containing cert types the caller can provide to its peer. - * Cert types are in preferred order in the array. - */ -WOLFSSL_API int wolfSSL_set_client_cert_type(WOLFSSL* ssl, - const char* buf, int bufLen) +int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) { - int i; + int useNb = 0; - if (ssl == NULL || bufLen > MAX_CLIENT_CERT_TYPE_CNT) { - return BAD_FUNC_ARG; - } + if (ssl == NULL) + return WOLFSSL_FAILURE; - /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ - if (buf == NULL || bufLen == 0) { - ssl->options.rpkConfig.preferred_ClientCertTypeCnt = 1; - ssl->options.rpkConfig.preferred_ClientCertTypes[0] - = WOLFSSL_CERT_TYPE_X509; - ssl->options.rpkConfig.preferred_ClientCertTypes[1] - = WOLFSSL_CERT_TYPE_X509; - return WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock"); + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + useNb = ssl->options.dtlsUseNonblock; +#endif + } + else { + WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is " + "DEPRECATED for non-DTLS use."); } + return useNb; +} - if (!isArrayUnique(buf, bufLen)) - return BAD_FUNC_ARG; - for (i = 0; i < bufLen; i++){ - if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) - return BAD_FUNC_ARG; +#ifndef WOLFSSL_LEANPSK - ssl->options.rpkConfig.preferred_ClientCertTypes[i] = buf[i]; - } - ssl->options.rpkConfig.preferred_ClientCertTypeCnt = bufLen; +void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) +{ + (void)nonblock; - return WOLFSSL_SUCCESS; -} + WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock"); -/* Set user preference for the server_cert_type exetnsion. - * Takes byte array containing cert types the caller can provide to its peer. - * Cert types are in preferred order in the array. - */ -WOLFSSL_API int wolfSSL_set_server_cert_type(WOLFSSL* ssl, - const char* buf, int bufLen) -{ - int i; + if (ssl == NULL) + return; - if (ssl == NULL || bufLen > MAX_SERVER_CERT_TYPE_CNT) { - return BAD_FUNC_ARG; + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ssl->options.dtlsUseNonblock = (nonblock != 0); +#endif } - - /* if buf is set to NULL or bufLen is set to zero, it defaults the setting*/ - if (buf == NULL || bufLen == 0) { - ssl->options.rpkConfig.preferred_ServerCertTypeCnt = 1; - ssl->options.rpkConfig.preferred_ServerCertTypes[0] - = WOLFSSL_CERT_TYPE_X509; - ssl->options.rpkConfig.preferred_ServerCertTypes[1] - = WOLFSSL_CERT_TYPE_X509; - return WOLFSSL_SUCCESS; + else { + WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is " + "DEPRECATED for non-DTLS use."); } +} - if (!isArrayUnique(buf, bufLen)) - return BAD_FUNC_ARG; - for (i = 0; i < bufLen; i++){ - if (buf[i] != WOLFSSL_CERT_TYPE_RPK && buf[i] != WOLFSSL_CERT_TYPE_X509) - return BAD_FUNC_ARG; +#ifdef WOLFSSL_DTLS - ssl->options.rpkConfig.preferred_ServerCertTypes[i] = buf[i]; - } - ssl->options.rpkConfig.preferred_ServerCertTypeCnt = bufLen; +int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) +{ + int timeout = 0; + if (ssl) + timeout = ssl->dtls_timeout; - return WOLFSSL_SUCCESS; + WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout", timeout); + return timeout; } -/* get negotiated certificate type value and return it to the second parameter. - * cert type value: - * -1: WOLFSSL_CERT_TYPE_UNKNOWN - * 0: WOLFSSL_CERT_TYPE_X509 - * 2: WOLFSSL_CERT_TYPE_RPK - * return WOLFSSL_SUCCESS on success, otherwise negative value. - * in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for - * cert type. +#ifdef WOLFSSL_DTLS13 + +/* + * This API returns 1 when the user should set a short timeout for receiving + * data. It is recommended that it is at most 1/4 the value returned by + * wolfSSL_dtls_get_current_timeout(). */ -WOLFSSL_API int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp) +int wolfSSL_dtls13_use_quick_timeout(WOLFSSL* ssl) { - int ret = WOLFSSL_SUCCESS; - - if (ssl == NULL || tp == NULL) - return BAD_FUNC_ARG; - - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) - *tp = ssl->options.rpkState.received_ClientCertTypes[0]; - else - *tp = WOLFSSL_CERT_TYPE_UNKNOWN; - } - else { - if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1) - *tp = ssl->options.rpkState.sending_ClientCertTypes[0]; - else - *tp = WOLFSSL_CERT_TYPE_UNKNOWN; - } - return ret; + return ssl->dtls13FastTimeout; } -/* get negotiated certificate type value and return it to the second parameter. - * cert type value: - * -1: WOLFSSL_CERT_TYPE_UNKNOWN - * 0: WOLFSSL_CERT_TYPE_X509 - * 2: WOLFSSL_CERT_TYPE_RPK - * return WOLFSSL_SUCCESS on success, otherwise negative value. - * in case no negotiation performed, it returns WOLFSSL_SUCCESS and -1 is for - * cert type. +/* + * When this is set, a DTLS 1.3 connection will send acks immediately when a + * disruption is detected to shortcut timeouts. This results in potentially + * more traffic but may make the handshake quicker. */ -WOLFSSL_API int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp) +void wolfSSL_dtls13_set_send_more_acks(WOLFSSL* ssl, int value) { - int ret = WOLFSSL_SUCCESS; - - if (ssl == NULL || tp == NULL) - return BAD_FUNC_ARG; - - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) - *tp = ssl->options.rpkState.received_ServerCertTypes[0]; - else - *tp = WOLFSSL_CERT_TYPE_UNKNOWN; - } - else { - if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1) - *tp = ssl->options.rpkState.sending_ServerCertTypes[0]; - else - *tp = WOLFSSL_CERT_TYPE_UNKNOWN; - } - return ret; + if (ssl != NULL) + ssl->options.dtls13SendMoreAcks = !!value; } +#endif /* WOLFSSL_DTLS13 */ -#endif /* HAVE_RPK */ - -int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der, - int derSz) +int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft) { - long idx = 0; - - WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); - if (der != NULL && ssl != NULL) { - if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, - ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } + if (ssl && timeleft) { + XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL)); + timeleft->tv_sec = ssl->dtls_timeout; } - - (void)idx; - return WOLFSSL_FAILURE; + return 0; } -#ifndef NO_FILESYSTEM - -WOLFSSL_ABI -int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) +#ifndef NO_WOLFSSL_STUB +int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_use_certificate_file"); + WOLFSSL_STUB("SSL_DTLSv1_handle_timeout"); + (void)ssl; + return 0; +} +#endif - if (ssl == NULL) { - return BAD_FUNC_ARG; - } - - if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, - ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } - - return WOLFSSL_FAILURE; +#ifndef NO_WOLFSSL_STUB +void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, + word32 duration_ms) +{ + WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration"); + (void)ssl; + (void)duration_ms; } +#endif - -WOLFSSL_ABI -int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) +/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout) { - WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); + if (ssl == NULL || timeout < 0) + return BAD_FUNC_ARG; - if (ssl == NULL) { + if (timeout > ssl->dtls_timeout_max) { + WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout " + "max"); return BAD_FUNC_ARG; } - if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, - ssl, 0, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } + ssl->dtls_timeout_init = timeout; + ssl->dtls_timeout = timeout; - return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; } -WOLFSSL_ABI -int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) +/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout) { - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); + if (ssl == NULL || timeout < 0) + return BAD_FUNC_ARG; - if (ssl == NULL) { + if (timeout < ssl->dtls_timeout_init) { + WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init"); return BAD_FUNC_ARG; } - if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, - ssl, 1, NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } + ssl->dtls_timeout_max = timeout; - return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; } -int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file, - int format) + +int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) { - /* process up to MAX_CHAIN_DEPTH plus subject cert */ - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format"); + int result = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_dtls_got_timeout"); - if (ssl == NULL) { - return BAD_FUNC_ARG; - } + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) { + result = Dtls13RtxTimeout(ssl); + if (result < 0) { + if (result == WANT_WRITE) + ssl->dtls13SendingAckOrRtx = 1; + ssl->error = result; + WOLFSSL_ERROR(result); + return WOLFSSL_FATAL_ERROR; + } - if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, - NULL, GET_VERIFY_SETTING_SSL(ssl)) == WOLFSSL_SUCCESS) { return WOLFSSL_SUCCESS; } - return WOLFSSL_FAILURE; -} +#endif /* WOLFSSL_DTLS13 */ -#endif /* !NO_FILESYSTEM */ + if ((IsSCR(ssl) || !ssl->options.handShakeDone)) { + if (DtlsMsgPoolTimeout(ssl) < 0){ + ssl->error = SOCKET_ERROR_E; + WOLFSSL_ERROR(ssl->error); + result = WOLFSSL_FATAL_ERROR; + } + else if ((result = DtlsMsgPoolSend(ssl, 0)) < 0) { + ssl->error = result; + WOLFSSL_ERROR(result); + result = WOLFSSL_FATAL_ERROR; + } + else { + /* Reset return value to success */ + result = WOLFSSL_SUCCESS; + } + } -#ifdef HAVE_ECC + WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout", result); + return result; +} -/* Set Temp CTX EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */ -int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) + +/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_retransmit(WOLFSSL* ssl) { - if (ctx == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_dtls_retransmit"); - /* if 0 then get from loaded private key */ - if (sz == 0) { - /* applies only to ECDSA */ - if (ctx->privateKeyType != ecc_dsa_sa_algo) - return WOLFSSL_SUCCESS; + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; - if (ctx->privateKeySz == 0) { - WOLFSSL_MSG("Must set private key/cert first"); - return BAD_FUNC_ARG; + if (!ssl->options.handShakeDone) { + int result = DtlsMsgPoolSend(ssl, 0); + if (result < 0) { + ssl->error = result; + WOLFSSL_ERROR(result); + return WOLFSSL_FATAL_ERROR; } - - sz = (word16)ctx->privateKeySz; } - /* check size */ -#if ECC_MIN_KEY_SZ > 0 - if (sz < ECC_MINSIZE) - return BAD_FUNC_ARG; -#endif - if (sz > ECC_MAXSIZE) - return BAD_FUNC_ARG; - - ctx->eccTempKeySz = sz; - - return WOLFSSL_SUCCESS; + return 0; } +#endif /* DTLS */ +#endif /* LEANPSK */ -/* Set Temp SSL EC-DHE size in octets, can be 14 - 66 (112 - 521 bit) */ -int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) -{ - if (ssl == NULL) - return BAD_FUNC_ARG; - /* check size */ -#if ECC_MIN_KEY_SZ > 0 - if (sz < ECC_MINSIZE) - return BAD_FUNC_ARG; -#endif - if (sz > ECC_MAXSIZE) - return BAD_FUNC_ARG; +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) - ssl->eccTempKeySz = sz; +/* Not an SSL function, return 0 for success, error code otherwise */ +/* Prereq: ssl's RNG needs to be initialized. */ +int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, + const byte* secret, word32 secretSz) +{ + int ret = 0; - return WOLFSSL_SUCCESS; -} + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); -#endif /* HAVE_ECC */ + if (ssl == NULL) { + WOLFSSL_MSG("need a SSL object"); + return BAD_FUNC_ARG; + } + if (secret != NULL && secretSz == 0) { + WOLFSSL_MSG("can't have a new secret without a size"); + return BAD_FUNC_ARG; + } -#ifdef OPENSSL_EXTRA + /* If secretSz is 0, use the default size. */ + if (secretSz == 0) + secretSz = COOKIE_SECRET_SZ; -#ifndef NO_FILESYSTEM -int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file, - int format) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey_file"); + if (secretSz != ssl->buffers.dtlsCookieSecret.length) { + byte* newSecret; - return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format); -} + if (ssl->buffers.dtlsCookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + XFREE(ssl->buffers.dtlsCookieSecret.buffer, + ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); + } + newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD); + if (newSecret == NULL) { + ssl->buffers.dtlsCookieSecret.buffer = NULL; + ssl->buffers.dtlsCookieSecret.length = 0; + WOLFSSL_MSG("couldn't allocate new cookie secret"); + return MEMORY_ERROR; + } + ssl->buffers.dtlsCookieSecret.buffer = newSecret; + ssl->buffers.dtlsCookieSecret.length = secretSz; + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecret secret", + ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + #endif + } -int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) -{ - WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file"); + /* If the supplied secret is NULL, randomly generate a new secret. */ + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->buffers.dtlsCookieSecret.buffer, secretSz); + } + else + XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); - return wolfSSL_use_PrivateKey_file(ssl, file, format); + WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); + return ret; } -#endif /* NO_FILESYSTEM */ +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ -/* 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; - - ses = ClientSessionToSession(ses); - if (outSz == 0) { - return SECRET_LEN; +/* EITHER SIDE METHODS */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + WOLFSSL_METHOD* wolfSSLv23_method(void) + { + return wolfSSLv23_method_ex(NULL); } + WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap) + { + WOLFSSL_METHOD* m = NULL; + WOLFSSL_ENTER("wolfSSLv23_method"); + #if !defined(NO_WOLFSSL_CLIENT) + m = wolfSSLv23_client_method_ex(heap); + #elif !defined(NO_WOLFSSL_SERVER) + m = wolfSSLv23_server_method_ex(heap); + #else + (void)heap; + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } - if (ses == NULL || out == NULL || outSz < 0) { - return 0; + return m; } - if (outSz > SECRET_LEN) { - size = SECRET_LEN; - } - else { - size = outSz; + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + WOLFSSL_METHOD* wolfSSLv3_method(void) + { + return wolfSSLv3_method_ex(NULL); } + WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap) + { + WOLFSSL_METHOD* m = NULL; + WOLFSSL_ENTER("wolfSSLv3_method_ex"); + #if !defined(NO_WOLFSSL_CLIENT) + m = wolfSSLv3_client_method_ex(heap); + #elif !defined(NO_WOLFSSL_SERVER) + m = wolfSSLv3_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } - XMEMCPY(out, ses->masterSecret, size); - return size; -} - + return m; + } + #endif + #endif +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ -int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses) -{ - (void)ses; - return SECRET_LEN; -} +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT -#ifdef WOLFSSL_EARLY_DATA -unsigned int wolfSSL_SESSION_get_max_early_data(const WOLFSSL_SESSION *session) -{ - return session->maxEarlyDataSz; -} -#endif /* WOLFSSL_EARLY_DATA */ - -#endif /* OPENSSL_EXTRA */ + #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv2_client_method(void) + { + WOLFSSL_STUB("wolfSSLv2_client_method"); + return NULL; + } + #endif -typedef struct { - byte verifyPeer:1; - byte verifyNone:1; - byte failNoCert:1; - byte failNoCertxPSK:1; - byte verifyPostHandshake:1; -} SetVerifyOptions; + #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv3_client_method(void) + { + return wolfSSLv3_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("wolfSSLv3_client_method_ex"); + if (method) + InitSSL_Method(method, MakeSSLv3()); + return method; + } + #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ -static SetVerifyOptions ModeToVerifyOptions(int mode) -{ - SetVerifyOptions opts; - XMEMSET(&opts, 0, sizeof(SetVerifyOptions)); - if (mode != WOLFSSL_VERIFY_DEFAULT) { - opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE); - if (!opts.verifyNone) { - opts.verifyPeer = - (mode & WOLFSSL_VERIFY_PEER) != 0; - opts.failNoCertxPSK = - (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0; - opts.failNoCert = - (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0; -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - opts.verifyPostHandshake = - (mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0; -#endif + WOLFSSL_METHOD* wolfSSLv23_client_method(void) + { + return wolfSSLv23_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("wolfSSLv23_client_method_ex"); + if (method) { + #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || \ + defined(WOLFSSL_SHA512) + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #else + #ifndef NO_OLD_TLS + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #endif + #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + method->downgrade = 1; + #endif } + return method; } - return opts; -} + /* please see note at top of README if you get an error from connect */ + WOLFSSL_ABI + int wolfSSL_connect(WOLFSSL* ssl) + { + #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && \ + defined(WOLFSSL_TLS13)) + int neededState; + byte advanceState; + #endif + int ret = 0; -WOLFSSL_ABI -void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) -{ - SetVerifyOptions opts; + (void)ret; - WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); - if (ctx == NULL) - return; + #ifdef HAVE_ERRNO_H + errno = 0; + #endif - opts = ModeToVerifyOptions(mode); + if (ssl == NULL) + return BAD_FUNC_ARG; - ctx->verifyNone = opts.verifyNone; - ctx->verifyPeer = opts.verifyPeer; - ctx->failNoCert = opts.failNoCert; - ctx->failNoCertxPSK = opts.failNoCertxPSK; -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - ctx->verifyPostHandshake = opts.verifyPostHandshake; -#endif + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (ssl->options.side == WOLFSSL_NEITHER_END) { + ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END); + if (ssl->error != WOLFSSL_SUCCESS) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->error = 0; /* expected to be zero here */ + } - ctx->verifyCallback = vc; -} + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_ST_CONNECT, WOLFSSL_SUCCESS); + ssl->cbmode = SSL_CB_WRITE; + } + #endif + #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ -#ifdef OPENSSL_ALL -void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx, - CertVerifyCallback cb, void* arg) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback"); - if (ctx == NULL) - return; + #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && \ + defined(WOLFSSL_TLS13) + return wolfSSL_connect_TLSv13(ssl); + #else + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + WOLFSSL_MSG("TLS 1.3"); + return wolfSSL_connect_TLSv13(ssl); + } + #endif - ctx->verifyCertCb = cb; - ctx->verifyCertCbArg = arg; -} -#endif + WOLFSSL_MSG("TLS 1.2 or lower"); + WOLFSSL_ENTER("wolfSSL_connect"); + /* make sure this wolfSSL object has arrays and rng setup. Protects + * case where the WOLFSSL object is reused via wolfSSL_clear() */ + if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) { + return ret; + } -void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) -{ - SetVerifyOptions opts; +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + if ((ssl->ConnectFilter != NULL) && + (ssl->options.connectState == CONNECT_BEGIN)) { + wolfSSL_netfilter_decision_t res; + if ((ssl->ConnectFilter(ssl, ssl->ConnectFilter_arg, &res) == + WOLFSSL_SUCCESS) && + (res == WOLFSSL_NETFILTER_REJECT)) { + ssl->error = SOCKET_FILTERED_E; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ - WOLFSSL_ENTER("wolfSSL_set_verify"); - if (ssl == NULL) - return; + if (ssl->options.side != WOLFSSL_CLIENT_END) { + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } - opts = ModeToVerifyOptions(mode); + #ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + ssl->options.dtlsStateful = 1; + } + #endif - ssl->options.verifyNone = opts.verifyNone; - ssl->options.verifyPeer = opts.verifyPeer; - ssl->options.failNoCert = opts.failNoCert; - ssl->options.failNoCertxPSK = opts.failNoCertxPSK; -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - ssl->options.verifyPostHandshake = opts.verifyPostHandshake; -#endif + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + advanceState = ssl->fragOffset == 0 && + (ssl->options.connectState == CONNECT_BEGIN || + ssl->options.connectState == HELLO_AGAIN || + (ssl->options.connectState >= FIRST_REPLY_DONE && + ssl->options.connectState <= FIRST_REPLY_FOURTH)); - ssl->verifyCallback = vc; -} +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) + advanceState = advanceState && !ssl->dtls13SendingAckOrRtx; +#endif /* WOLFSSL_DTLS13 */ -void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) -{ - WOLFSSL_ENTER("wolfSSL_set_verify_result"); + if (ssl->buffers.outputBuffer.length > 0 + #ifdef WOLFSSL_ASYNC_CRYPT + /* do not send buffered or advance state if last error was an + async pending operation */ + && ssl->error != WC_PENDING_E + #endif + ) { + ret = SendBuffered(ssl); + if (ret == 0) { + if (ssl->fragOffset == 0 && !ssl->options.buildingMsg) { + if (advanceState) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: Advanced from last " + "buffered fragment send"); + #ifdef WOLFSSL_ASYNC_IO + /* Cleanup async */ + FreeAsyncCtx(ssl, 0); + #endif + } + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + ssl->dtls13SendingAckOrRtx = 0; +#endif /* WOLFSSL_DTLS13 */ + } - if (ssl == NULL) - return; + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(OPENSSL_ALL) - ssl->peerVerifyRet = v; -#else - (void)v; - WOLFSSL_STUB("wolfSSL_set_verify_result"); -#endif -} + switch (ssl->options.connectState) { -#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) -/* For TLS v1.3 send handshake messages after handshake completes. */ -/* Returns 1=WOLFSSL_SUCCESS or 0=WOLFSSL_FAILURE */ -int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl) -{ - int ret = wolfSSL_request_certificate(ssl); - if (ret != WOLFSSL_SUCCESS) { - if (!IsAtLeastTLSv1_3(ssl->version)) { - /* specific error of wrong version expected */ - WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION); + case CONNECT_BEGIN : + /* always send client hello first */ + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; - } - else { - WOLFSSL_ERROR(ret); /* log the error in the error queue */ - } - } - return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} + case CLIENT_HELLO_SENT : + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + #ifdef WOLFSSL_DTLS + /* In DTLS, when resuming, we can go straight to FINISHED, + * or do a cookie exchange and then skip to FINISHED, assume + * we need the cookie exchange first. */ + if (IsDtlsNotSctpMode(ssl)) + neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + #endif + /* get response */ + WOLFSSL_MSG("Server state up to needed state."); + while (ssl->options.serverState < neededState) { + WOLFSSL_MSG("Progressing server state..."); + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + WOLFSSL_MSG("ProcessReply..."); + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) + neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + else + #endif + neededState = SERVER_HELLODONE_COMPLETE; + } + } + WOLFSSL_MSG("ProcessReply done."); -int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val) -{ - int ret = wolfSSL_CTX_allow_post_handshake_auth(ctx); - if (ret == 0) { - ctx->postHandshakeAuth = (val != 0); - } - return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} -int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val) -{ - int ret = wolfSSL_allow_post_handshake_auth(ssl); - if (ret == 0) { - ssl->options.postHandshakeAuth = (val != 0); - } - return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} -#endif /* OPENSSL_EXTRA && !NO_CERTS && WOLFSSL_TLS13 && WOLFSSL_POST_HANDSHAKE_AUTH */ +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version) + && ssl->dtls13Rtx.sendAcks == 1 + && ssl->options.seenUnifiedHdr) { + /* we aren't negotiated the version yet, so we aren't sure + * the other end can speak v1.3. On the other side we have + * received a unified records, assuming that the + * ServerHello got lost, we will send an empty ACK. In case + * the server is a DTLS with version less than 1.3, it + * should just ignore the message */ + ssl->dtls13Rtx.sendAcks = 0; + if ((ssl->error = SendDtls13Ack(ssl)) < 0) { + if (ssl->error == WANT_WRITE) + ssl->dtls13SendingAckOrRtx = 1; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* WOLFSSL_DTLS13 */ + } -/* store user ctx for verify callback */ -void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) -{ - WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); - if (ssl) - ssl->verifyCbCtx = ctx; -} + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + case HELLO_AGAIN : -/* store user ctx for verify callback */ -void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx"); - if (ctx) - ctx->verifyCbCtx = userCtx; -} + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.serverState == + SERVER_HELLOVERIFYREQUEST_COMPLETE) { + if (IsDtlsNotSctpMode(ssl)) { + /* re-init hashes, exclude first hello and verify request */ + if ((ssl->error = InitHandshakeHashes(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } + #endif -/* store context CA Cache addition callback */ -void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) -{ - if (ctx && ctx->cm) - ctx->cm->caCacheCallback = cb; -} + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + case HELLO_AGAIN_REPLY : + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + neededState = ssl->options.resuming ? + SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; -#if defined(PERSIST_CERT_CACHE) + /* get response */ + while (ssl->options.serverState < neededState) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) + neededState = SERVER_HELLODONE_COMPLETE; + } + } + } + #endif -#if !defined(NO_FILESYSTEM) + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; -/* Persist cert cache to file */ -int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) -{ - WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); + case FIRST_REPLY_DONE : + if (ssl->options.certOnly) + return WOLFSSL_SUCCESS; + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificate(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } - if (ctx == NULL || fname == NULL) - return BAD_FUNC_ARG; + #endif + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; - return CM_SaveCertCache(ctx->cm, fname); -} + case FIRST_REPLY_FIRST : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + if (!ssl->options.resuming) { + if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif +#ifdef WOLFSSL_EXTRA_ALERTS + if (ssl->error == NO_PEER_KEY || + ssl->error == WC_NO_ERR_TRACE(PSK_KEY_ERROR)) { + SendAlert(ssl, alert_fatal, handshake_failure); + } +#endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: client key exchange"); + } + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; -/* Persist cert cache from file */ -int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) -{ - WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache"); + #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) + case FIRST_REPLY_SECOND : + /* CLIENT: Fail-safe for Server Authentication. */ + if (!ssl->options.peerAuthGood) { + WOLFSSL_MSG("Server authentication did not happen"); + ssl->error = NO_PEER_VERIFY; + return WOLFSSL_FATAL_ERROR; + } - if (ctx == NULL || fname == NULL) - return BAD_FUNC_ARG; + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */ + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; - return CM_RestoreCertCache(ctx->cm, fname); -} - -#endif /* NO_FILESYSTEM */ - -/* Persist cert cache to memory */ -int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, - int sz, int* used) -{ - WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache"); - - if (ctx == NULL || mem == NULL || used == NULL || sz <= 0) - return BAD_FUNC_ARG; - - return CM_MemSaveCertCache(ctx->cm, mem, sz, used); -} - - -/* Restore cert cache from memory */ -int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz) -{ - WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache"); - - if (ctx == NULL || mem == NULL || sz <= 0) - return BAD_FUNC_ARG; - - return CM_MemRestoreCertCache(ctx->cm, mem, sz); -} - - -/* get how big the the cert cache save buffer needs to be */ -int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize"); + case FIRST_REPLY_THIRD : + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: change cipher spec"); + ssl->options.connectState = FIRST_REPLY_FOURTH; + WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; - if (ctx == NULL) - return BAD_FUNC_ARG; + case FIRST_REPLY_FOURTH : + if ( (ssl->error = SendFinished(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; - return CM_GetCertCacheMemSize(ctx->cm); -} +#ifdef WOLFSSL_DTLS13 + case WAIT_FINISHED_ACK: + ssl->options.connectState = FINISHED_DONE; + FALL_THROUGH; +#endif /* WOLFSSL_DTLS13 */ -#endif /* PERSIST_CERT_CACHE */ -#endif /* !NO_CERTS */ + case FINISHED_DONE : + /* get response */ + while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.connectState = SECOND_REPLY_DONE; + WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + FALL_THROUGH; -#ifndef NO_SESSION_CACHE + case SECOND_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 WOLFSSL_FATAL_ERROR; + } + } + #endif /* NO_HANDSHAKE_DONE_CB */ -WOLFSSL_ABI -WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_session"); - if (ssl) { -#ifdef NO_SESSION_CACHE_REF - return ssl->session; -#else - if (ssl->options.side == WOLFSSL_CLIENT_END) { - /* On the client side we want to return a persistent reference for - * backwards compatibility. */ -#ifndef NO_CLIENT_CACHE - if (ssl->clientSession) { - return (WOLFSSL_SESSION*)ssl->clientSession; + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } + #ifdef WOLFSSL_DTLS else { - /* Try to add a ClientCache entry to associate with the current - * session. Ignore any session cache options. */ - int err; - const byte* id = ssl->session->sessionID; - byte idSz = ssl->session->sessionIDSz; - if (ssl->session->haveAltSessionID) { - id = ssl->session->altSessionID; - idSz = ID_LEN; - } - err = AddSessionToCache(ssl->ctx, ssl->session, id, idSz, - NULL, ssl->session->side, - #ifdef HAVE_SESSION_TICKET - ssl->session->ticketLen > 0, - #else - 0, - #endif - &ssl->clientSession); - if (err == 0) { - return (WOLFSSL_SESSION*)ssl->clientSession; - } + ssl->options.dtlsHsRetain = 1; } -#endif - } - else { - return ssl->session; - } -#endif - } - - return NULL; -} + #endif /* WOLFSSL_DTLS */ -/* The get1 version requires caller to call SSL_SESSION_free */ -WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) -{ - WOLFSSL_SESSION* sess = NULL; - WOLFSSL_ENTER("wolfSSL_get1_session"); - if (ssl != NULL) { - sess = ssl->session; - if (sess != NULL) { - /* increase reference count if allocated session */ - if (sess->type == WOLFSSL_SESSION_TYPE_HEAP) { - if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS) - sess = NULL; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION) + /* This may be necessary in async so that we don't try to + * renegotiate again */ + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->startScr) { + ssl->secure_renegotiation->startScr = 0; } - } - } - return sess; -} + #endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */ + #if defined(WOLFSSL_ASYNC_IO) && !defined(WOLFSSL_ASYNC_CRYPT) + /* Free the remaining async context if not using it for crypto */ + FreeAsyncCtx(ssl, 1); + #endif + ssl->error = 0; /* clear the error */ -/* - * Sets the session object to use when establishing a TLS/SSL session using - * the ssl object. Therefore, this function must be called before - * wolfSSL_connect. The session object to use can be obtained in a previous - * TLS/SSL connection using wolfSSL_get_session. - * - * This function rejects the session if it has been expired when this function - * is called. Note that this expiration check is wolfSSL specific and differs - * from OpenSSL return code behavior. - * - * By default, wolfSSL_set_session returns WOLFSSL_SUCCESS on successfully - * setting the session, WOLFSSL_FAILURE on failure due to the session cache - * being disabled, or the session has expired. - * - * To match OpenSSL return code behavior when session is expired, define - * OPENSSL_EXTRA and WOLFSSL_ERROR_CODE_OPENSSL. This behavior will return - * WOLFSSL_SUCCESS even when the session is expired and rejected. - */ -WOLFSSL_ABI -int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) -{ - WOLFSSL_ENTER("wolfSSL_set_session"); - if (session) - return wolfSSL_SetSession(ssl, session); + WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ - return WOLFSSL_FAILURE; -} + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } + #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */ + } +#endif /* NO_WOLFSSL_CLIENT */ -#ifndef NO_CLIENT_CACHE -/* Associate client session with serverID, find existing or store for saving - if newSession flag on, don't reuse existing session - WOLFSSL_SUCCESS on ok */ -int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) -{ - WOLFSSL_SESSION* session = NULL; - byte idHash[SERVER_ID_LEN]; +/* server only parts */ +#ifndef NO_WOLFSSL_SERVER - WOLFSSL_ENTER("wolfSSL_SetServerID"); + #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv2_server_method(void) + { + WOLFSSL_STUB("wolfSSLv2_server_method"); + return 0; + } + #endif - if (ssl == NULL || id == NULL || len <= 0) - return BAD_FUNC_ARG; + #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + WOLFSSL_METHOD* wolfSSLv3_server_method(void) + { + return wolfSSLv3_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("wolfSSLv3_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeSSLv3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ - if (len > SERVER_ID_LEN) { -#if defined(NO_SHA) && !defined(NO_SHA256) - if (wc_Sha256Hash(id, len, idHash) != 0) - return WOLFSSL_FAILURE; -#else - if (wc_ShaHash(id, len, idHash) != 0) - return WOLFSSL_FAILURE; -#endif - id = idHash; - len = SERVER_ID_LEN; + WOLFSSL_METHOD* wolfSSLv23_server_method(void) + { + return wolfSSLv23_server_method_ex(NULL); } - if (newSession == 0) { - session = wolfSSL_GetSessionClient(ssl, id, len); - if (session) { - if (wolfSSL_SetSession(ssl, session) != WOLFSSL_SUCCESS) { - #ifdef HAVE_EXT_CACHE - wolfSSL_FreeSession(ssl->ctx, session); - #endif - WOLFSSL_MSG("wolfSSL_SetSession failed"); - session = NULL; - } + WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("wolfSSLv23_server_method_ex"); + if (method) { + #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || \ + defined(WOLFSSL_SHA512) + #ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #else + #ifndef NO_OLD_TLS + InitSSL_Method(method, MakeTLSv1_1()); + #else + #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 + #endif + #endif + #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + method->downgrade = 1; + #endif + method->side = WOLFSSL_SERVER_END; } + return method; } - if (session == NULL) { - WOLFSSL_MSG("Valid ServerID not cached already"); - ssl->session->idLen = (word16)len; - XMEMCPY(ssl->session->serverID, id, len); - } -#ifdef HAVE_EXT_CACHE - else { - wolfSSL_FreeSession(ssl->ctx, session); - } + WOLFSSL_ABI + int wolfSSL_accept(WOLFSSL* ssl) + { +#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && \ + defined(WOLFSSL_TLS13)) + word16 havePSK = 0; + word16 haveAnon = 0; + word16 haveMcast = 0; #endif + int ret = 0; - return WOLFSSL_SUCCESS; -} - -#endif /* !NO_CLIENT_CACHE */ + (void)ret; -/* TODO: Add SESSION_CACHE_DYNAMIC_MEM support for PERSIST_SESSION_CACHE. - * Need a count of current sessions to get an accurate memsize (totalCount is - * not decremented when sessions are removed). - * Need to determine ideal layout for mem/filesave. - * Also need mem/filesave checking to ensure not restoring non DYNAMIC_MEM cache. - */ -#if defined(PERSIST_SESSION_CACHE) && !defined(SESSION_CACHE_DYNAMIC_MEM) + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; -/* for persistence, if changes to layout need to increment and modify - save_session_cache() and restore_session_cache and memory versions too */ -#define WOLFSSL_CACHE_VERSION 2 + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (ssl->options.side == WOLFSSL_NEITHER_END) { + WOLFSSL_MSG("Setting WOLFSSL_SSL to be server side"); + ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END); + if (ssl->error != WOLFSSL_SUCCESS) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->error = 0; /* expected to be zero here */ + } + #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ -/* Session Cache Header information */ -typedef struct { - int version; /* cache layout version id */ - int rows; /* session rows */ - int columns; /* session columns */ - int sessionSz; /* sizeof WOLFSSL_SESSION */ -} cache_header_t; +#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) + return wolfSSL_accept_TLSv13(ssl); +#else + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_accept_TLSv13(ssl); + #endif + WOLFSSL_ENTER("wolfSSL_accept"); -/* current persistence layout is: + /* make sure this wolfSSL object has arrays and rng setup. Protects + * case where the WOLFSSL object is reused via wolfSSL_clear() */ + if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) { + return ret; + } - 1) cache_header_t - 2) SessionCache - 3) ClientCache - - update WOLFSSL_CACHE_VERSION if change layout for the following - PERSISTENT_SESSION_CACHE functions -*/ - -/* get how big the the session cache save buffer needs to be */ -int wolfSSL_get_session_cache_memsize(void) -{ - int sz = (int)(sizeof(SessionCache) + sizeof(cache_header_t)); -#ifndef NO_CLIENT_CACHE - sz += (int)(sizeof(ClientCache)); -#endif - return sz; -} - - -/* Persist session cache to memory */ -int wolfSSL_memsave_session_cache(void* mem, int sz) -{ - int i; - cache_header_t cache_header; - SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); - - WOLFSSL_ENTER("wolfSSL_memsave_session_cache"); - - if (sz < wolfSSL_get_session_cache_memsize()) { - WOLFSSL_MSG("Memory buffer too small"); - return BUFFER_E; - } - - cache_header.version = WOLFSSL_CACHE_VERSION; - cache_header.rows = SESSION_ROWS; - cache_header.columns = SESSIONS_PER_ROW; - cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); - XMEMCPY(mem, &cache_header, sizeof(cache_header)); - -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_RD_LOCK(row) != 0) { - WOLFSSL_MSG("Session cache mutex lock failed"); - return BAD_MUTEX_E; - } +#ifdef WOLFSSL_WOLFSENTRY_HOOKS + if ((ssl->AcceptFilter != NULL) && + ((ssl->options.acceptState == ACCEPT_BEGIN) +#ifdef HAVE_SECURE_RENEGOTIATION + || (ssl->options.acceptState == ACCEPT_BEGIN_RENEG) #endif - for (i = 0; i < cache_header.rows; ++i) { - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_RD_LOCK(&SessionCache[i]) != 0) { - WOLFSSL_MSG("Session row cache mutex lock failed"); - return BAD_MUTEX_E; + )) + { + wolfSSL_netfilter_decision_t res; + if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) == + WOLFSSL_SUCCESS) && + (res == WOLFSSL_NETFILTER_REJECT)) { + ssl->error = SOCKET_FILTERED_E; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } } - #endif - - XMEMCPY(row++, &SessionCache[i], SIZEOF_SESSION_ROW); - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[i]); - #endif - } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(row); -#endif - -#ifndef NO_CLIENT_CACHE - if (wc_LockMutex(&clisession_mutex) != 0) { - WOLFSSL_MSG("Client cache mutex lock failed"); - return BAD_MUTEX_E; - } - XMEMCPY(row, ClientCache, sizeof(ClientCache)); - wc_UnLockMutex(&clisession_mutex); -#endif - - WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS); +#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ - return WOLFSSL_SUCCESS; -} + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + (void)havePSK; -/* Restore the persistent session cache from memory */ -int wolfSSL_memrestore_session_cache(const void* mem, int sz) -{ - int i; - cache_header_t cache_header; - SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); + #ifdef HAVE_ANON + haveAnon = ssl->options.useAnon; + #endif + (void)haveAnon; - WOLFSSL_ENTER("wolfSSL_memrestore_session_cache"); + #ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; + #endif + (void)haveMcast; - if (sz < wolfSSL_get_session_cache_memsize()) { - WOLFSSL_MSG("Memory buffer too small"); - return BUFFER_E; - } + if (ssl->options.side != WOLFSSL_SERVER_END) { + ssl->error = SIDE_ERROR; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } - XMEMCPY(&cache_header, mem, sizeof(cache_header)); - if (cache_header.version != WOLFSSL_CACHE_VERSION || - cache_header.rows != SESSION_ROWS || - cache_header.columns != SESSIONS_PER_ROW || - cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) { + #ifndef NO_CERTS + /* in case used set_accept_state after init */ + if (!havePSK && !haveAnon && !haveMcast) { + #ifdef OPENSSL_EXTRA + if (ssl->ctx->certSetupCb != NULL) { + WOLFSSL_MSG("CertSetupCb set. server cert and " + "key not checked"); + } + else + #endif + { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { - WOLFSSL_MSG("Session cache header match failed"); - return CACHE_MATCH_ERROR; - } + WOLFSSL_MSG("accept error: server cert required"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_WR_LOCK(&SessionCache[0]) != 0) { - WOLFSSL_MSG("Session cache mutex lock failed"); - return BAD_MUTEX_E; - } -#endif - for (i = 0; i < cache_header.rows; ++i) { - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) { - WOLFSSL_MSG("Session row cache mutex lock failed"); - return BAD_MUTEX_E; + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + /* allow no private key if using existing key */ + #ifdef WOLF_PRIVATE_KEY_ID + if (ssl->devId != INVALID_DEVID + #ifdef HAVE_PK_CALLBACKS + || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) + #endif + ) { + WOLFSSL_MSG("Allowing no server private key " + "(external)"); + } + else + #endif + { + WOLFSSL_MSG("accept error: server key required"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } } #endif - XMEMCPY(&SessionCache[i], row++, SIZEOF_SESSION_ROW); - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[i]); - #endif - } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[0]); -#endif - -#ifndef NO_CLIENT_CACHE - if (wc_LockMutex(&clisession_mutex) != 0) { - WOLFSSL_MSG("Client cache mutex lock failed"); - return BAD_MUTEX_E; - } - XMEMCPY(ClientCache, row, sizeof(ClientCache)); - wc_UnLockMutex(&clisession_mutex); -#endif - - WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS); - - return WOLFSSL_SUCCESS; -} - -#if !defined(NO_FILESYSTEM) - -/* Persist session cache to file */ -/* doesn't use memsave because of additional memory use */ -int wolfSSL_save_session_cache(const char *fname) -{ - XFILE file; - int ret; - int rc = WOLFSSL_SUCCESS; - int i; - cache_header_t cache_header; - - WOLFSSL_ENTER("wolfSSL_save_session_cache"); - - file = XFOPEN(fname, "w+b"); - if (file == XBADFILE) { - WOLFSSL_MSG("Couldn't open session cache save file"); - return WOLFSSL_BAD_FILE; - } - cache_header.version = WOLFSSL_CACHE_VERSION; - cache_header.rows = SESSION_ROWS; - cache_header.columns = SESSIONS_PER_ROW; - cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); - - /* cache header */ - ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file); - if (ret != 1) { - WOLFSSL_MSG("Session cache header file write failed"); - XFCLOSE(file); - return FWRITE_ERROR; - } - -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_RD_LOCK(&SessionCache[0]) != 0) { - WOLFSSL_MSG("Session cache mutex lock failed"); - XFCLOSE(file); - return BAD_MUTEX_E; - } -#endif - /* session cache */ - for (i = 0; i < cache_header.rows; ++i) { - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_RD_LOCK(&SessionCache[i]) != 0) { - WOLFSSL_MSG("Session row cache mutex lock failed"); - XFCLOSE(file); - return BAD_MUTEX_E; + #ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + if (!IsDtlsNotSctpMode(ssl) || !IsDtlsNotSrtpMode(ssl) || + IsSCR(ssl)) + ssl->options.dtlsStateful = 1; } #endif - ret = (int)XFWRITE(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file); - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[i]); - #endif - if (ret != 1) { - WOLFSSL_MSG("Session cache member file write failed"); - rc = FWRITE_ERROR; - break; + if (ssl->buffers.outputBuffer.length > 0 + #ifdef WOLFSSL_ASYNC_CRYPT + /* do not send buffered or advance state if last error was an + async pending operation */ + && ssl->error != WC_PENDING_E + #endif + ) { + ret = SendBuffered(ssl); + if (ret == 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.buildingMsg) { + if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE || + ssl->options.acceptState == SERVER_HELLO_SENT || + ssl->options.acceptState == CERT_SENT || + ssl->options.acceptState == CERT_STATUS_SENT || + ssl->options.acceptState == KEY_EXCHANGE_SENT || + ssl->options.acceptState == CERT_REQ_SENT || + ssl->options.acceptState == ACCEPT_SECOND_REPLY_DONE || + ssl->options.acceptState == TICKET_SENT || + ssl->options.acceptState == CHANGE_CIPHER_SENT) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: Advanced from last " + "buffered fragment send"); + #ifdef WOLFSSL_ASYNC_IO + /* Cleanup async */ + FreeAsyncCtx(ssl, 0); + #endif + } + } + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); + } + } + else { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) + ssl->dtls13SendingAckOrRtx = 0; +#endif /* WOLFSSL_DTLS13 */ } - } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[0]); -#endif -#ifndef NO_CLIENT_CACHE - /* client cache */ - if (wc_LockMutex(&clisession_mutex) != 0) { - WOLFSSL_MSG("Client cache mutex lock failed"); - XFCLOSE(file); - return BAD_MUTEX_E; - } - ret = (int)XFWRITE(ClientCache, sizeof(ClientCache), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Client cache member file write failed"); - rc = FWRITE_ERROR; - } - wc_UnLockMutex(&clisession_mutex); -#endif /* !NO_CLIENT_CACHE */ + ret = RetrySendAlert(ssl); + if (ret != 0) { + ssl->error = ret; + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } - XFCLOSE(file); - WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc); + switch (ssl->options.acceptState) { - return rc; -} + case ACCEPT_BEGIN : +#ifdef HAVE_SECURE_RENEGOTIATION + case ACCEPT_BEGIN_RENEG: +#endif + /* get response */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_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 : + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } +#endif -/* Restore the persistent session cache from file */ -/* doesn't use memstore because of additional memory use */ -int wolfSSL_restore_session_cache(const char *fname) -{ - XFILE file; - int rc = WOLFSSL_SUCCESS; - int ret; - int i; - cache_header_t cache_header; + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; - WOLFSSL_ENTER("wolfSSL_restore_session_cache"); + case ACCEPT_FIRST_REPLY_DONE : + if ( (ssl->error = SendServerHello(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) { - WOLFSSL_MSG("Couldn't open session cache save file"); - return WOLFSSL_BAD_FILE; - } - /* cache header */ - ret = (int)XFREAD(&cache_header, sizeof(cache_header), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Session cache header file read failed"); - XFCLOSE(file); - return FREAD_ERROR; - } - if (cache_header.version != WOLFSSL_CACHE_VERSION || - cache_header.rows != SESSION_ROWS || - cache_header.columns != SESSIONS_PER_ROW || - cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) { - - WOLFSSL_MSG("Session cache header match failed"); - XFCLOSE(file); - return CACHE_MATCH_ERROR; - } + case SERVER_HELLO_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif + #ifndef NO_CERTS + if (!ssl->options.resuming) + if ( (ssl->error = SendCertificate(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_WR_LOCK(&SessionCache[0]) != 0) { - WOLFSSL_MSG("Session cache mutex lock failed"); - XFCLOSE(file); - return BAD_MUTEX_E; - } -#endif - /* session cache */ - for (i = 0; i < cache_header.rows; ++i) { - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) { - WOLFSSL_MSG("Session row cache mutex lock failed"); - XFCLOSE(file); - return BAD_MUTEX_E; - } - #endif + case CERT_SENT : + #ifndef NO_CERTS + if (!ssl->options.resuming) + if ( (ssl->error = SendCertificateStatus(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_STATUS_SENT; + WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; - ret = (int)XFREAD(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file); - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[i]); - #endif - if (ret != 1) { - WOLFSSL_MSG("Session cache member file read failed"); - XMEMSET(SessionCache, 0, sizeof SessionCache); - rc = FREAD_ERROR; - break; - } - } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[0]); -#endif + case CERT_STATUS_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif + if (!ssl->options.resuming) + if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = KEY_EXCHANGE_SENT; + WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); + FALL_THROUGH; -#ifndef NO_CLIENT_CACHE - /* client cache */ - if (wc_LockMutex(&clisession_mutex) != 0) { - WOLFSSL_MSG("Client cache mutex lock failed"); - XFCLOSE(file); - return BAD_MUTEX_E; - } - ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file); - if (ret != 1) { - WOLFSSL_MSG("Client cache member file read failed"); - XMEMSET(ClientCache, 0, sizeof ClientCache); - rc = FREAD_ERROR; - } - wc_UnLockMutex(&clisession_mutex); -#endif /* !NO_CLIENT_CACHE */ + case KEY_EXCHANGE_SENT : + #ifndef NO_CERTS + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { + if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + /* See if an alert was sent. */ + ProcessReplyEx(ssl, 1); + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + else { + /* SERVER: Peer auth good if not verifying client. */ + ssl->options.peerAuthGood = 1; + } + } + #endif + ssl->options.acceptState = CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; - XFCLOSE(file); - WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc); + case CERT_REQ_SENT : + if (!ssl->options.resuming) + if ( (ssl->error = SendServerHelloDone(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_DONE; + WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); + FALL_THROUGH; - return rc; -} + case SERVER_HELLO_DONE : + if (!ssl->options.resuming) { + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; -#endif /* !NO_FILESYSTEM */ -#endif /* PERSIST_SESSION_CACHE && !SESSION_CACHE_DYNAMIC_MEM */ -#endif /* NO_SESSION_CACHE */ + case ACCEPT_SECOND_REPLY_DONE : + #ifndef NO_CERTS + /* SERVER: When not resuming and verifying peer but no certificate + * received and not failing when not received then peer auth good. + */ + if (!ssl->options.resuming && ssl->options.verifyPeer && + !ssl->options.havePeerCert && !ssl->options.failNoCert) { + ssl->options.peerAuthGood = 1; + } + #endif /* !NO_CERTS */ + #ifdef WOLFSSL_NO_CLIENT_AUTH + if (!ssl->options.resuming) { + ssl->options.peerAuthGood = 1; + } + #endif +#ifdef HAVE_SESSION_TICKET + if (ssl->options.createTicket && !ssl->options.noTicketTls12) { + if ( (ssl->error = SendTicket(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_MSG("Thought we need ticket but failed"); + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; -void wolfSSL_load_error_strings(void) -{ - /* compatibility only */ -} + case TICKET_SENT: + /* SERVER: Fail-safe for CLient Authentication. */ + if (!ssl->options.peerAuthGood) { + WOLFSSL_MSG("Client authentication did not happen"); + return WOLFSSL_FATAL_ERROR; + } + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = CHANGE_CIPHER_SENT; + WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); + FALL_THROUGH; -int wolfSSL_library_init(void) -{ - WOLFSSL_ENTER("wolfSSL_library_init"); - if (wolfSSL_Init() == WOLFSSL_SUCCESS) - return WOLFSSL_SUCCESS; - else - return WOLFSSL_FATAL_ERROR; -} + case CHANGE_CIPHER_SENT : + if ( (ssl->error = SendFinished(ssl)) != 0) { + #ifdef WOLFSSL_CHECK_ALERT_ON_ERR + ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ + #endif + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; -#ifdef HAVE_SECRET_CALLBACK + case ACCEPT_FINISHED_DONE : + if (ssl->options.resuming) { + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; -int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) -{ - WOLFSSL_ENTER("wolfSSL_set_session_secret_cb"); - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + 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 WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ - ssl->sessionSecretCb = cb; - ssl->sessionSecretCtx = ctx; - if (cb != NULL) { - /* If using a pre-set key, assume session resumption. */ - ssl->session->sessionIDSz = 0; - ssl->options.resuming = 1; - } + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ - return WOLFSSL_SUCCESS; -} +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION) + /* This may be necessary in async so that we don't try to + * renegotiate again */ + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->startScr) { + ssl->secure_renegotiation->startScr = 0; + } +#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */ +#if defined(WOLFSSL_ASYNC_IO) && !defined(WOLFSSL_ASYNC_CRYPT) + /* Free the remaining async context if not using it for crypto */ + FreeAsyncCtx(ssl, 1); +#endif +#if defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS) + if (ssl->dtls_export) { + if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { + WOLFSSL_MSG("Export DTLS session error"); + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } #endif + ssl->error = 0; /* clear the error */ + WOLFSSL_LEAVE("wolfSSL_accept", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; -#ifndef NO_SESSION_CACHE + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return WOLFSSL_FATAL_ERROR; + } +#endif /* !WOLFSSL_NO_TLS12 */ + } -/* on by default if built in but allow user to turn off */ -WOLFSSL_ABI -long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) +#endif /* NO_WOLFSSL_SERVER */ + +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) +int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx) { - WOLFSSL_ENTER("wolfSSL_CTX_set_session_cache_mode"); + WOLFSSL_ENTER("wolfDTLS_SetChGoodCb"); - if (ctx == NULL) - return WOLFSSL_FAILURE; + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->chGoodCb = cb; + ssl->chGoodCtx = user_ctx; - if (mode == WOLFSSL_SESS_CACHE_OFF) { - ctx->sessionCacheOff = 1; -#ifdef HAVE_EXT_CACHE - ctx->internalCacheOff = 1; - ctx->internalCacheLookupOff = 1; + return WOLFSSL_SUCCESS; +} #endif - } - if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) - ctx->sessionCacheFlushOff = 1; +#ifndef NO_HANDSHAKE_DONE_CB + +int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetHsDoneCb"); + + if (ssl == NULL) + return BAD_FUNC_ARG; -#ifdef HAVE_EXT_CACHE - /* WOLFSSL_SESS_CACHE_NO_INTERNAL activates both if's */ - if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) - ctx->internalCacheOff = 1; - if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP) != 0) - ctx->internalCacheLookupOff = 1; -#endif + ssl->hsDoneCb = cb; + ssl->hsDoneCtx = user_ctx; return WOLFSSL_SUCCESS; } -#ifdef OPENSSL_EXTRA -/* Get the session cache mode for CTX - * - * ctx WOLFSSL_CTX struct to get cache mode from - * - * Returns a bit mask that has the session cache mode */ -long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) +#endif /* NO_HANDSHAKE_DONE_CB */ + +WOLFSSL_ABI +int wolfSSL_Cleanup(void) { - long m = 0; + int ret = WOLFSSL_SUCCESS; /* Only the first error will be returned */ + int release = 0; +#if !defined(NO_SESSION_CACHE) + int i; + int j; +#endif - WOLFSSL_ENTER("wolfSSL_CTX_get_session_cache_mode"); + WOLFSSL_ENTER("wolfSSL_Cleanup"); - if (ctx == NULL) { - return m; +#ifndef WOLFSSL_MUTEX_INITIALIZER + if (inits_count_mutex_valid == 1) { +#endif + if (wc_LockMutex(&inits_count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); + return BAD_MUTEX_E; + } +#ifndef WOLFSSL_MUTEX_INITIALIZER } +#endif - if (ctx->sessionCacheOff != 1) { - m |= WOLFSSL_SESS_CACHE_SERVER; + if (initRefCount > 0) { + --initRefCount; + if (initRefCount == 0) + release = 1; } - if (ctx->sessionCacheFlushOff == 1) { - m |= WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR; +#ifndef WOLFSSL_MUTEX_INITIALIZER + if (inits_count_mutex_valid == 1) { +#endif + wc_UnLockMutex(&inits_count_mutex); +#ifndef WOLFSSL_MUTEX_INITIALIZER } +#endif -#ifdef HAVE_EXT_CACHE - if (ctx->internalCacheOff == 1) { - m |= WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE; - } - if (ctx->internalCacheLookupOff == 1) { - m |= WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP; - } + if (!release) + return ret; + +#ifdef OPENSSL_EXTRA + wolfSSL_BN_free_one(); #endif - return m; -} -#endif /* OPENSSL_EXTRA */ +#ifndef NO_SESSION_CACHE + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + for (i = 0; i < SESSION_ROWS; ++i) { + if ((SessionCache[i].lock_valid == 1) && + (wc_FreeRwLock(&SessionCache[i].row_lock) != 0)) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + SessionCache[i].lock_valid = 0; + } + #else + if ((session_lock_valid == 1) && (wc_FreeRwLock(&session_lock) != 0)) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + session_lock_valid = 0; + #endif + for (i = 0; i < SESSION_ROWS; i++) { + for (j = 0; j < SESSIONS_PER_ROW; j++) { + #ifdef SESSION_CACHE_DYNAMIC_MEM + if (SessionCache[i].Sessions[j]) { + EvictSessionFromCache(SessionCache[i].Sessions[j]); + XFREE(SessionCache[i].Sessions[j], SessionCache[i].heap, + DYNAMIC_TYPE_SESSION); + SessionCache[i].Sessions[j] = NULL; + } + #else + EvictSessionFromCache(&SessionCache[i].Sessions[j]); + #endif + } + } + #ifndef NO_CLIENT_CACHE + #ifndef WOLFSSL_MUTEX_INITIALIZER + if ((clisession_mutex_valid == 1) && + (wc_FreeMutex(&clisession_mutex) != 0)) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + clisession_mutex_valid = 0; + #endif + #endif +#endif /* !NO_SESSION_CACHE */ -#endif /* NO_SESSION_CACHE */ +#ifndef WOLFSSL_MUTEX_INITIALIZER + if ((inits_count_mutex_valid == 1) && + (wc_FreeMutex(&inits_count_mutex) != 0)) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + inits_count_mutex_valid = 0; +#endif #ifdef OPENSSL_EXTRA + wolfSSL_RAND_Cleanup(); +#endif -/* - * check if the list has TLS13 and pre-TLS13 suites - * @param list cipher suite list that user want to set - * @return mixed: 0, only pre-TLS13: 1, only TLS13: 2 - */ -static int CheckcipherList(const char* list) -{ - int ret; - int findTLSv13Suites = 0; - int findbeforeSuites = 0; - byte cipherSuite0; - byte cipherSuite1; - int flags; - char* next = (char*)list; + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + if (ret == WOLFSSL_SUCCESS) + ret = WC_CLEANUP_E; + } - do { - char* current = next; - char name[MAX_SUITE_NAME + 1]; - word32 length = MAX_SUITE_NAME; - word32 current_length; +#if FIPS_VERSION_GE(5,1) + if (wolfCrypt_SetPrivateKeyReadEnable_fips(0, WC_KEYTYPE_ALL) < 0) { + if (ret == WOLFSSL_SUCCESS) + ret = WC_CLEANUP_E; + } +#endif - next = XSTRSTR(next, ":"); +#ifdef HAVE_GLOBAL_RNG +#ifndef WOLFSSL_MUTEX_INITIALIZER + if ((globalRNGMutex_valid == 1) && (wc_FreeMutex(&globalRNGMutex) != 0)) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + globalRNGMutex_valid = 0; +#endif /* !WOLFSSL_MUTEX_INITIALIZER */ - current_length = (!next) ? (word32)XSTRLEN(current) - : (word32)(next - current); + #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG) + wolfSSL_FIPS_drbg_free(gDrbgDefCtx); + gDrbgDefCtx = NULL; + #endif +#endif - if (current_length < length) { - length = current_length; - } - XMEMCPY(name, current, length); - name[length] = 0; +#if defined(HAVE_EX_DATA) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ + defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || \ + defined(WOLFSSL_WPAS_SMALL) + crypto_ex_cb_free(crypto_ex_cb_ctx_session); + crypto_ex_cb_ctx_session = NULL; +#endif - if (XSTRCMP(name, "ALL") == 0 || XSTRCMP(name, "DEFAULT") == 0 || - XSTRCMP(name, "HIGH") == 0) { - findTLSv13Suites = 1; - findbeforeSuites = 1; - break; - } +#ifdef WOLFSSL_MEM_FAIL_COUNT + wc_MemFailCount_Free(); +#endif - ret = wolfSSL_get_cipher_suite_from_name(name, &cipherSuite0, - &cipherSuite1, &flags); - if (ret == 0) { - if (cipherSuite0 == TLS13_BYTE) { - /* TLSv13 suite */ - findTLSv13Suites = 1; - } - else { - findbeforeSuites = 1; - } - } + return ret; +} - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) - /* check if mixed due to names like RSA:ECDHE+AESGCM etc. */ - if (ret != 0) { - char* subStr = name; - char* subStrNext; - do { - subStrNext = XSTRSTR(subStr, "+"); +/* call before SSL_connect, if verifying will add name check to + date check and signature check */ +WOLFSSL_ABI +int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn) +{ + WOLFSSL_ENTER("wolfSSL_check_domain_name"); - if ((XSTRCMP(subStr, "ECDHE") == 0) || - (XSTRCMP(subStr, "RSA") == 0)) { - return 0; - } + if (ssl == NULL || dn == NULL) { + WOLFSSL_MSG("Bad function argument: NULL"); + return WOLFSSL_FAILURE; + } - if (subStrNext && (XSTRLEN(subStrNext) > 0)) { - subStr = subStrNext + 1; /* +1 to skip past '+' */ - } - } while (subStrNext != NULL); - } - #endif + if (ssl->buffers.domainName.buffer) + XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); - if (findTLSv13Suites == 1 && findbeforeSuites == 1) { - /* list has mixed suites */ - return 0; - } - } - while (next++); /* ++ needed to skip ':' */ + ssl->buffers.domainName.length = (word32)XSTRLEN(dn); + ssl->buffers.domainName.buffer = (byte*)XMALLOC( + ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN); - if (findTLSv13Suites == 0 && findbeforeSuites == 1) { - ret = 1;/* only before TLSv13 suites */ - } - else if (findTLSv13Suites == 1 && findbeforeSuites == 0) { - ret = 2;/* only TLSv13 suties */ + if (ssl->buffers.domainName.buffer) { + unsigned char* domainName = ssl->buffers.domainName.buffer; + XMEMCPY(domainName, dn, ssl->buffers.domainName.length); + domainName[ssl->buffers.domainName.length] = '\0'; + return WOLFSSL_SUCCESS; } else { - ret = 0;/* handle as mixed */ + ssl->error = MEMORY_ERROR; + return WOLFSSL_FAILURE; } - return ret; } -/* parse some bulk lists like !eNULL / !aNULL - * - * returns WOLFSSL_SUCCESS on success and sets the cipher suite list - */ -static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - Suites* suites, const char* list) + +/* turn on wolfSSL zlib compression + returns WOLFSSL_SUCCESS for success, else error (not built in) +*/ +int wolfSSL_set_compression(WOLFSSL* ssl) { - int ret = 0; - int listattribute = 0; - int tls13Only = 0; -#ifndef WOLFSSL_SMALL_STACK - byte suitesCpy[WOLFSSL_MAX_SUITE_SZ]; + WOLFSSL_ENTER("wolfSSL_set_compression"); + (void)ssl; +#ifdef HAVE_LIBZ + ssl->options.usingCompression = 1; + return WOLFSSL_SUCCESS; #else - byte* suitesCpy = NULL; + return NOT_COMPILED_IN; #endif - word16 suitesCpySz = 0; - word16 i = 0; - word16 j = 0; - - if (suites == NULL || list == NULL) { - WOLFSSL_MSG("NULL argument"); - return WOLFSSL_FAILURE; - } +} - listattribute = CheckcipherList(list); - if (listattribute == 0) { - /* list has mixed(pre-TLSv13 and TLSv13) suites - * update cipher suites the same as before - */ - return (SetCipherList_ex(ctx, ssl, suites, list)) ? WOLFSSL_SUCCESS : - WOLFSSL_FAILURE; - } - else if (listattribute == 1) { - /* list has only pre-TLSv13 suites. - * Only update before TLSv13 suites. - */ - tls13Only = 0; - } - else if (listattribute == 2) { - /* list has only TLSv13 suites. Only update TLv13 suites - * simulate set_ciphersuites() compatibility layer API - */ - tls13Only = 1; - if ((ctx != NULL && !IsAtLeastTLSv1_3(ctx->method->version)) || - (ssl != NULL && !IsAtLeastTLSv1_3(ssl->version))) { - /* Silently ignore TLS 1.3 ciphers if we don't support it. */ - return WOLFSSL_SUCCESS; - } - } +#ifndef USE_WINDOWS_API + #ifndef NO_WRITEV - /* list contains ciphers either only for TLS 1.3 or <= TLS 1.2 */ - if (suites->suiteSz == 0) { - WOLFSSL_MSG("Warning suites->suiteSz = 0 set to WOLFSSL_MAX_SUITE_SZ"); - suites->suiteSz = WOLFSSL_MAX_SUITE_SZ; - } -#ifdef WOLFSSL_SMALL_STACK - if (suites->suiteSz > 0) { - suitesCpy = (byte*)XMALLOC(suites->suiteSz, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (suitesCpy == NULL) { - return WOLFSSL_FAILURE; - } + /* simulate writev semantics, doesn't actually do block at a time though + because of SSL_write behavior and because front adds may be small */ + int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt) + { + #ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ + #else + byte staticBuffer[FILE_BUFFER_SIZE]; + #endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + int sending = 0; + int idx = 0; + int i; + int ret; - XMEMSET(suitesCpy, 0, suites->suiteSz); - } -#else - XMEMSET(suitesCpy, 0, sizeof(suitesCpy)); -#endif + WOLFSSL_ENTER("wolfSSL_writev"); - if (suites->suiteSz > 0) - XMEMCPY(suitesCpy, suites->suites, suites->suiteSz); - suitesCpySz = suites->suiteSz; + for (i = 0; i < iovcnt; i++) + sending += (int)iov[i].iov_len; - ret = SetCipherList_ex(ctx, ssl, suites, list); - if (ret != 1) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return WOLFSSL_FAILURE; - } + if (sending > (int)sizeof(staticBuffer)) { + myBuffer = (byte*)XMALLOC(sending, ssl->heap, + DYNAMIC_TYPE_WRITEV); + if (!myBuffer) + return MEMORY_ERROR; - for (i = 0; i < suitesCpySz && - suites->suiteSz <= (WOLFSSL_MAX_SUITE_SZ - SUITE_LEN); i += 2) { - /* Check for duplicates */ - int duplicate = 0; - for (j = 0; j < suites->suiteSz; j += 2) { - if (suitesCpy[i] == suites->suites[j] && - suitesCpy[i+1] == suites->suites[j+1]) { - duplicate = 1; - break; - } - } - if (!duplicate) { - if (tls13Only) { - /* Updating TLS 1.3 ciphers */ - if (suitesCpy[i] != TLS13_BYTE) { - /* Only copy over <= TLS 1.2 ciphers */ - /* TLS 1.3 ciphers take precedence */ - suites->suites[suites->suiteSz++] = suitesCpy[i]; - suites->suites[suites->suiteSz++] = suitesCpy[i+1]; - } - } - else { - /* Updating <= TLS 1.2 ciphers */ - if (suitesCpy[i] == TLS13_BYTE) { - /* Only copy over TLS 1.3 ciphers */ - /* TLS 1.3 ciphers take precedence */ - XMEMMOVE(suites->suites + SUITE_LEN, suites->suites, - suites->suiteSz); - suites->suites[0] = suitesCpy[i]; - suites->suites[1] = suitesCpy[i+1]; - suites->suiteSz += 2; - } + dynamic = 1; } - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(suitesCpy, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; -} - -#endif - -int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list"); + for (i = 0; i < iovcnt; i++) { + XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len); + idx += (int)iov[i].iov_len; + } - if (ctx == NULL) - return WOLFSSL_FAILURE; + /* myBuffer may not be initialized fully, but the span up to the + * sending length will be. + */ + PRAGMA_GCC_DIAG_PUSH + PRAGMA_GCC("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") + ret = wolfSSL_write(ssl, myBuffer, sending); + PRAGMA_GCC_DIAG_POP - if (AllocateCtxSuites(ctx) != 0) - return WOLFSSL_FAILURE; + if (dynamic) + XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); -#ifdef OPENSSL_EXTRA - return wolfSSL_parse_cipher_list(ctx, NULL, ctx->suites, list); -#else - return (SetCipherList(ctx, ctx->suites, list)) ? - WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + return ret; + } + #endif #endif -} -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES) -int wolfSSL_CTX_set_cipher_list_bytes(WOLFSSL_CTX* ctx, const byte* list, - const int listSz) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list_bytes"); - if (ctx == NULL) - return WOLFSSL_FAILURE; +#ifdef WOLFSSL_CALLBACKS - if (AllocateCtxSuites(ctx) != 0) - return WOLFSSL_FAILURE; + typedef struct itimerval Itimerval; - return (SetCipherListFromBytes(ctx, ctx->suites, list, listSz)) ? - WOLFSSL_SUCCESS : WOLFSSL_FAILURE; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ + /* don't keep calling simple functions while setting up timer and signals + if no inlining these are the next best */ -int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) -{ - WOLFSSL_ENTER("wolfSSL_set_cipher_list"); + #define AddTimes(a, b, c) \ + do { \ + (c).tv_sec = (a).tv_sec + (b).tv_sec; \ + (c).tv_usec = (a).tv_usec + (b).tv_usec;\ + if ((c).tv_usec >= 1000000) { \ + (c).tv_sec++; \ + (c).tv_usec -= 1000000; \ + } \ + } while (0) - if (ssl == NULL || ssl->ctx == NULL) { - return WOLFSSL_FAILURE; - } - if (AllocateSuites(ssl) != 0) - return WOLFSSL_FAILURE; + #define SubtractTimes(a, b, c) \ + do { \ + (c).tv_sec = (a).tv_sec - (b).tv_sec; \ + (c).tv_usec = (a).tv_usec - (b).tv_usec;\ + if ((c).tv_usec < 0) { \ + (c).tv_sec--; \ + (c).tv_usec += 1000000; \ + } \ + } while (0) -#ifdef OPENSSL_EXTRA - return wolfSSL_parse_cipher_list(NULL, ssl, ssl->suites, list); -#else - return (SetCipherList_ex(NULL, ssl, ssl->suites, list)) ? - WOLFSSL_SUCCESS : - WOLFSSL_FAILURE; -#endif -} + #define CmpTimes(a, b, cmp) \ + (((a).tv_sec == (b).tv_sec) ? \ + ((a).tv_usec cmp (b).tv_usec) : \ + ((a).tv_sec cmp (b).tv_sec)) \ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SET_CIPHER_BYTES) -int wolfSSL_set_cipher_list_bytes(WOLFSSL* ssl, const byte* list, - const int listSz) -{ - WOLFSSL_ENTER("wolfSSL_set_cipher_list_bytes"); - if (ssl == NULL || ssl->ctx == NULL) { - return WOLFSSL_FAILURE; + /* do nothing handler */ + static void myHandler(int signo) + { + (void)signo; + return; } - if (AllocateSuites(ssl) != 0) - return WOLFSSL_FAILURE; - return (SetCipherListFromBytes(ssl->ctx, ssl->suites, list, listSz)) - ? WOLFSSL_SUCCESS - : WOLFSSL_FAILURE; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_SET_CIPHER_BYTES */ + static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb, + TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) + { + int ret = WOLFSSL_FATAL_ERROR; + int oldTimerOn = 0; /* was timer already on */ + WOLFSSL_TIMEVAL startTime; + WOLFSSL_TIMEVAL endTime; + WOLFSSL_TIMEVAL totalTime; + Itimerval myTimeout; + Itimerval oldTimeout; /* if old timer adjust from total time to reset */ + struct sigaction act, oact; + #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; } -#ifdef HAVE_KEYING_MATERIAL + if (hsCb) { + ssl->hsInfoOn = 1; + InitHandShakeInfo(&ssl->handShakeInfo, ssl); + } + if (toCb) { + ssl->toInfoOn = 1; + InitTimeoutInfo(&ssl->timeoutInfo); -#define TLS_PRF_LABEL_CLIENT_FINISHED "client finished" -#define TLS_PRF_LABEL_SERVER_FINISHED "server finished" -#define TLS_PRF_LABEL_MASTER_SECRET "master secret" -#define TLS_PRF_LABEL_EXT_MASTER_SECRET "extended master secret" -#define TLS_PRF_LABEL_KEY_EXPANSION "key expansion" + if (gettimeofday(&startTime, 0) < 0) + ERR_OUT(GETTIME_ERROR); -static const struct ForbiddenLabels { - const char* label; - size_t labelLen; -} forbiddenLabels[] = { - {TLS_PRF_LABEL_CLIENT_FINISHED, XSTR_SIZEOF(TLS_PRF_LABEL_CLIENT_FINISHED)}, - {TLS_PRF_LABEL_SERVER_FINISHED, XSTR_SIZEOF(TLS_PRF_LABEL_SERVER_FINISHED)}, - {TLS_PRF_LABEL_MASTER_SECRET, XSTR_SIZEOF(TLS_PRF_LABEL_MASTER_SECRET)}, - {TLS_PRF_LABEL_EXT_MASTER_SECRET, XSTR_SIZEOF(TLS_PRF_LABEL_EXT_MASTER_SECRET)}, - {TLS_PRF_LABEL_KEY_EXPANSION, XSTR_SIZEOF(TLS_PRF_LABEL_KEY_EXPANSION)}, - {NULL, 0}, -}; + /* use setitimer to simulate getitimer, init 0 myTimeout */ + myTimeout.it_interval.tv_sec = 0; + myTimeout.it_interval.tv_usec = 0; + myTimeout.it_value.tv_sec = 0; + myTimeout.it_value.tv_usec = 0; + if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0) + ERR_OUT(SETITIMER_ERROR); -/** - * Implement RFC 5705 - * TLS 1.3 uses a different exporter definition (section 7.5 of RFC 8446) - * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error - */ -int wolfSSL_export_keying_material(WOLFSSL *ssl, - unsigned char *out, size_t outLen, - const char *label, size_t labelLen, - const unsigned char *context, size_t contextLen, - int use_context) -{ - byte* seed = NULL; - word32 seedLen; - const struct ForbiddenLabels* fl; + if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) { + oldTimerOn = 1; - WOLFSSL_ENTER("wolfSSL_export_keying_material"); + /* is old timer going to expire before ours */ + if (CmpTimes(oldTimeout.it_value, timeout, <)) { + timeout.tv_sec = oldTimeout.it_value.tv_sec; + timeout.tv_usec = oldTimeout.it_value.tv_usec; + } + } + myTimeout.it_value.tv_sec = timeout.tv_sec; + myTimeout.it_value.tv_usec = timeout.tv_usec; - if (ssl == NULL || out == NULL || label == NULL || - (use_context && contextLen && context == NULL)) { - WOLFSSL_MSG("Bad argument"); - return WOLFSSL_FAILURE; - } + /* set up signal handler, don't restart socket send/recv */ + act.sa_handler = myHandler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; +#ifdef SA_INTERRUPT + act.sa_flags |= SA_INTERRUPT; +#endif + if (sigaction(SIGALRM, &act, &oact) < 0) + ERR_OUT(SIGACT_ERROR); - /* clientRandom + serverRandom - * OR - * clientRandom + serverRandom + ctx len encoding + ctx */ - seedLen = !use_context ? (word32)SEED_LEN : - (word32)SEED_LEN + 2 + (word32)contextLen; + if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0) + ERR_OUT(SETITIMER_ERROR); + } - if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { - WOLFSSL_MSG("To export keying material wolfSSL needs to keep handshake " - "data. Call wolfSSL_KeepArrays before attempting to " - "export keyid material."); - return WOLFSSL_FAILURE; - } + /* do main work */ +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) + ret = wolfSSL_connect(ssl); +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) + ret = wolfSSL_accept(ssl); +#endif - /* check forbidden labels */ - for (fl = &forbiddenLabels[0]; fl->label != NULL; fl++) { - if (labelLen >= fl->labelLen && - XMEMCMP(label, fl->label, fl->labelLen) == 0) { - WOLFSSL_MSG("Forbidden label"); - return WOLFSSL_FAILURE; - } - } + /* do callbacks */ + if (toCb) { + if (oldTimerOn) { + if (gettimeofday(&endTime, 0) < 0) + ERR_OUT(SYSLIB_FAILED_E); + SubtractTimes(endTime, startTime, totalTime); + /* adjust old timer for elapsed time */ + if (CmpTimes(totalTime, oldTimeout.it_value, <)) + SubtractTimes(oldTimeout.it_value, totalTime, + oldTimeout.it_value); + else { + /* reset value to interval, may be off */ + oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec; + oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec; + } + /* keep iter the same whether there or not */ + } + /* restore old handler */ + if (sigaction(SIGALRM, &oact, 0) < 0) + ret = SIGACT_ERROR; /* more pressing error, stomp */ + else + /* use old settings which may turn off (expired or not there) */ + if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0) + ret = SETITIMER_ERROR; -#ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version)) { - /* Path for TLS 1.3 */ - if (!use_context) { - contextLen = 0; - context = (byte*)""; /* Give valid pointer for 0 length memcpy */ + /* if we had a timeout call callback */ + if (ssl->timeoutInfo.timeoutName[0]) { + ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec; + ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec; + (toCb)(&ssl->timeoutInfo); + } + ssl->toInfoOn = 0; } - if (Tls13_Exporter(ssl, out, (word32)outLen, label, labelLen, - context, contextLen) != 0) { - WOLFSSL_MSG("Tls13_Exporter error"); - return WOLFSSL_FAILURE; + /* clean up buffers allocated by AddPacketInfo */ + FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap); + + if (hsCb) { + FinishHandShakeInfo(&ssl->handShakeInfo); + (hsCb)(&ssl->handShakeInfo); + ssl->hsInfoOn = 0; } - return WOLFSSL_SUCCESS; + return ret; } -#endif - /* Path for <=TLS 1.2 */ - seed = (byte*)XMALLOC(seedLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (seed == NULL) { - WOLFSSL_MSG("malloc error"); - return WOLFSSL_FAILURE; - } - XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); +#ifndef NO_WOLFSSL_CLIENT - if (use_context) { - /* Encode len in big endian */ - seed[SEED_LEN ] = (contextLen >> 8) & 0xFF; - seed[SEED_LEN + 1] = (contextLen) & 0xFF; - if (contextLen) { - /* 0 length context is allowed */ - XMEMCPY(seed + SEED_LEN + 2, context, contextLen); - } + int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, + TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) + { + WOLFSSL_ENTER("wolfSSL_connect_ex"); + return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); } - PRIVATE_KEY_UNLOCK(); - if (wc_PRF_TLS(out, (word32)outLen, ssl->arrays->masterSecret, SECRET_LEN, - (byte*)label, (word32)labelLen, seed, seedLen, IsAtLeastTLSv1_2(ssl), - ssl->specs.mac_algorithm, ssl->heap, ssl->devId) != 0) { - WOLFSSL_MSG("wc_PRF_TLS error"); - PRIVATE_KEY_LOCK(); - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; - } - PRIVATE_KEY_LOCK(); +#endif - XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_KEYING_MATERIAL */ -int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) -{ - int useNb = 0; +#ifndef NO_WOLFSSL_SERVER - if (ssl == NULL) - return WOLFSSL_FAILURE; + int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, + TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) + { + WOLFSSL_ENTER("wolfSSL_accept_ex"); + return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); + } - WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock"); - if (ssl->options.dtls) { -#ifdef WOLFSSL_DTLS - useNb = ssl->options.dtlsUseNonblock; #endif - } - else { - WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is " - "DEPRECATED for non-DTLS use."); - } - return useNb; -} +#endif /* WOLFSSL_CALLBACKS */ -#ifndef WOLFSSL_LEANPSK -void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) -{ - (void)nonblock; +#ifndef NO_PSK - WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock"); + void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx, + wc_psk_client_callback cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_psk_client_callback"); - if (ssl == NULL) - return; + if (ctx == NULL) + return; - if (ssl->options.dtls) { -#ifdef WOLFSSL_DTLS - ssl->options.dtlsUseNonblock = (nonblock != 0); -#endif - } - else { - WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is " - "DEPRECATED for non-DTLS use."); + ctx->havePSK = 1; + ctx->client_psk_cb = cb; } -} + void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) + { + byte haveRSA = 1; + int keySz = 0; -#ifdef WOLFSSL_DTLS + WOLFSSL_ENTER("wolfSSL_set_psk_client_callback"); -int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) -{ - int timeout = 0; - if (ssl) - timeout = ssl->dtls_timeout; - - WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout", timeout); - return timeout; -} - -#ifdef WOLFSSL_DTLS13 - -/* - * This API returns 1 when the user should set a short timeout for receiving - * data. It is recommended that it is at most 1/4 the value returned by - * wolfSSL_dtls_get_current_timeout(). - */ -int wolfSSL_dtls13_use_quick_timeout(WOLFSSL* ssl) -{ - return ssl->dtls13FastTimeout; -} + if (ssl == NULL) + return; -/* - * When this is set, a DTLS 1.3 connection will send acks immediately when a - * disruption is detected to shortcut timeouts. This results in potentially - * more traffic but may make the handshake quicker. - */ -void wolfSSL_dtls13_set_send_more_acks(WOLFSSL* ssl, int value) -{ - if (ssl != NULL) - ssl->options.dtls13SendMoreAcks = !!value; -} -#endif /* WOLFSSL_DTLS13 */ + ssl->options.havePSK = 1; + ssl->options.client_psk_cb = cb; -int wolfSSL_DTLSv1_get_timeout(WOLFSSL* ssl, WOLFSSL_TIMEVAL* timeleft) -{ - if (ssl && timeleft) { - XMEMSET(timeleft, 0, sizeof(WOLFSSL_TIMEVAL)); - timeleft->tv_sec = ssl->dtls_timeout; + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + if (AllocateSuites(ssl) != 0) + return; + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveECDSAsig, + ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.useAnon, TRUE, ssl->options.side); } - return 0; -} - -#ifndef NO_WOLFSSL_STUB -int wolfSSL_DTLSv1_handle_timeout(WOLFSSL* ssl) -{ - WOLFSSL_STUB("SSL_DTLSv1_handle_timeout"); - (void)ssl; - return 0; -} -#endif - -#ifndef NO_WOLFSSL_STUB -void wolfSSL_DTLSv1_set_initial_timeout_duration(WOLFSSL* ssl, word32 duration_ms) -{ - WOLFSSL_STUB("SSL_DTLSv1_set_initial_timeout_duration"); - (void)ssl; - (void)duration_ms; -} -#endif + #ifdef OPENSSL_EXTRA + /** + * set call back function for psk session use + * @param ssl a pointer to WOLFSSL structure + * @param cb a function pointer to wc_psk_use_session_cb + * @return none + */ + void wolfSSL_set_psk_use_session_callback(WOLFSSL* ssl, + wc_psk_use_session_cb_func cb) + { + WOLFSSL_ENTER("wolfSSL_set_psk_use_session_callback"); -/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */ -int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout) -{ - if (ssl == NULL || timeout < 0) - return BAD_FUNC_ARG; + if (ssl != NULL) { + ssl->options.havePSK = 1; + ssl->options.session_psk_cb = cb; + } - if (timeout > ssl->dtls_timeout_max) { - WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max"); - return BAD_FUNC_ARG; + WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS); } + #endif - ssl->dtls_timeout_init = timeout; - ssl->dtls_timeout = timeout; + void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx, + wc_psk_server_callback cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_psk_server_callback"); + if (ctx == NULL) + return; + ctx->havePSK = 1; + ctx->server_psk_cb = cb; + } - return WOLFSSL_SUCCESS; -} + void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb) + { + byte haveRSA = 1; + int keySz = 0; + WOLFSSL_ENTER("wolfSSL_set_psk_server_callback"); + if (ssl == NULL) + return; -/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */ -int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout) -{ - if (ssl == NULL || timeout < 0) - return BAD_FUNC_ARG; + ssl->options.havePSK = 1; + ssl->options.server_psk_cb = cb; - if (timeout < ssl->dtls_timeout_init) { - WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init"); - return BAD_FUNC_ARG; + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + if (AllocateSuites(ssl) != 0) + return; + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveECDSAsig, + ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, + ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, + ssl->options.useAnon, TRUE, ssl->options.side); } - ssl->dtls_timeout_max = timeout; + const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get_psk_identity_hint"); - return WOLFSSL_SUCCESS; -} + if (ssl == NULL || ssl->arrays == NULL) + return NULL; + return ssl->arrays->server_hint; + } -int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) -{ - int result = WOLFSSL_SUCCESS; - WOLFSSL_ENTER("wolfSSL_dtls_got_timeout"); - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get_psk_identity"); -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) { - result = Dtls13RtxTimeout(ssl); - if (result < 0) { - if (result == WANT_WRITE) - ssl->dtls13SendingAckOrRtx = 1; - ssl->error = result; - WOLFSSL_ERROR(result); - return WOLFSSL_FATAL_ERROR; - } + if (ssl == NULL || ssl->arrays == NULL) + return NULL; - return WOLFSSL_SUCCESS; + return ssl->arrays->client_identity; } -#endif /* WOLFSSL_DTLS13 */ - if ((IsSCR(ssl) || !ssl->options.handShakeDone)) { - if (DtlsMsgPoolTimeout(ssl) < 0){ - ssl->error = SOCKET_ERROR_E; - WOLFSSL_ERROR(ssl->error); - result = WOLFSSL_FATAL_ERROR; - } - else if ((result = DtlsMsgPoolSend(ssl, 0)) < 0) { - ssl->error = result; - WOLFSSL_ERROR(result); - result = WOLFSSL_FATAL_ERROR; - } + int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint) + { + WOLFSSL_ENTER("wolfSSL_CTX_use_psk_identity_hint"); + if (hint == 0) + ctx->server_hint[0] = '\0'; else { - /* Reset return value to success */ - result = WOLFSSL_SUCCESS; + /* Qt does not call CTX_set_*_psk_callbacks where havePSK is set */ + #ifdef WOLFSSL_QT + ctx->havePSK=1; + #endif + XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN); + ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } + return WOLFSSL_SUCCESS; } - WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout", result); - return result; -} - - -/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */ -int wolfSSL_dtls_retransmit(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_dtls_retransmit"); + int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint) + { + WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint"); - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; + if (ssl == NULL || ssl->arrays == NULL) + return WOLFSSL_FAILURE; - if (!ssl->options.handShakeDone) { - int result = DtlsMsgPoolSend(ssl, 0); - if (result < 0) { - ssl->error = result; - WOLFSSL_ERROR(result); - return WOLFSSL_FATAL_ERROR; + if (hint == 0) + ssl->arrays->server_hint[0] = 0; + else { + XSTRNCPY(ssl->arrays->server_hint, hint, + sizeof(ssl->arrays->server_hint)-1); + ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0'; } + return WOLFSSL_SUCCESS; } - return 0; -} + void* wolfSSL_get_psk_callback_ctx(WOLFSSL* ssl) + { + return ssl ? ssl->options.psk_ctx : NULL; + } + void* wolfSSL_CTX_get_psk_callback_ctx(WOLFSSL_CTX* ctx) + { + return ctx ? ctx->psk_ctx : NULL; + } + int wolfSSL_set_psk_callback_ctx(WOLFSSL* ssl, void* psk_ctx) + { + if (ssl == NULL) + return WOLFSSL_FAILURE; + ssl->options.psk_ctx = psk_ctx; + return WOLFSSL_SUCCESS; + } + int wolfSSL_CTX_set_psk_callback_ctx(WOLFSSL_CTX* ctx, void* psk_ctx) + { + if (ctx == NULL) + return WOLFSSL_FAILURE; + ctx->psk_ctx = psk_ctx; + return WOLFSSL_SUCCESS; + } +#endif /* NO_PSK */ -#endif /* DTLS */ -#endif /* LEANPSK */ +#ifdef HAVE_ANON -#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) + int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher"); -/* Not an SSL function, return 0 for success, error code otherwise */ -/* Prereq: ssl's RNG needs to be initialized. */ -int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, - const byte* secret, word32 secretSz) -{ - int ret = 0; + if (ctx == NULL) + return WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); + ctx->useAnon = 1; - if (ssl == NULL) { - WOLFSSL_MSG("need a SSL object"); - return BAD_FUNC_ARG; + return WOLFSSL_SUCCESS; } - if (secret != NULL && secretSz == 0) { - WOLFSSL_MSG("can't have a new secret without a size"); - return BAD_FUNC_ARG; - } +#endif /* HAVE_ANON */ - /* If secretSz is 0, use the default size. */ - if (secretSz == 0) - secretSz = COOKIE_SECRET_SZ; +#ifndef NO_CERTS - if (secretSz != ssl->buffers.dtlsCookieSecret.length) { - byte* newSecret; + /* unload any certs or keys that SSL owns, leave CTX as is + WOLFSSL_SUCCESS on ok */ + int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl) + { + if (ssl == NULL) { + WOLFSSL_MSG("Null function arg"); + return BAD_FUNC_ARG; + } - if (ssl->buffers.dtlsCookieSecret.buffer != NULL) { - ForceZero(ssl->buffers.dtlsCookieSecret.buffer, - ssl->buffers.dtlsCookieSecret.length); - XFREE(ssl->buffers.dtlsCookieSecret.buffer, - ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); + if (ssl->buffers.weOwnCert && !ssl->keepCert) { + WOLFSSL_MSG("Unloading cert"); + FreeDer(&ssl->buffers.certificate); + #ifdef KEEP_OUR_CERT + wolfSSL_X509_free(ssl->ourCert); + ssl->ourCert = NULL; + #endif + ssl->buffers.weOwnCert = 0; } - newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD); - if (newSecret == NULL) { - ssl->buffers.dtlsCookieSecret.buffer = NULL; - ssl->buffers.dtlsCookieSecret.length = 0; - WOLFSSL_MSG("couldn't allocate new cookie secret"); - return MEMORY_ERROR; + if (ssl->buffers.weOwnCertChain) { + WOLFSSL_MSG("Unloading cert chain"); + FreeDer(&ssl->buffers.certChain); + ssl->buffers.weOwnCertChain = 0; } - ssl->buffers.dtlsCookieSecret.buffer = newSecret; - ssl->buffers.dtlsCookieSecret.length = secretSz; - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("wolfSSL_DTLS_SetCookieSecret secret", - ssl->buffers.dtlsCookieSecret.buffer, - ssl->buffers.dtlsCookieSecret.length); - #endif - } - /* If the supplied secret is NULL, randomly generate a new secret. */ - if (secret == NULL) { - ret = wc_RNG_GenerateBlock(ssl->rng, - ssl->buffers.dtlsCookieSecret.buffer, secretSz); - } - else - XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); + if (ssl->buffers.weOwnKey) { + WOLFSSL_MSG("Unloading key"); + ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); + FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif + ssl->buffers.weOwnKey = 0; + } - WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); - return ret; -} +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->buffers.weOwnAltKey) { + WOLFSSL_MSG("Unloading alt key"); + ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length); + FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif + ssl->buffers.weOwnAltKey = 0; + } +#endif /* WOLFSSL_DUAL_ALG_CERTS */ -#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + return WOLFSSL_SUCCESS; + } -/* EITHER SIDE METHODS */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - WOLFSSL_METHOD* wolfSSLv23_method(void) + int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx) { - return wolfSSLv23_method_ex(NULL); + WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnloadCAs(ctx->cm); } - WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap) + + int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx) { - WOLFSSL_METHOD* m = NULL; - WOLFSSL_ENTER("wolfSSLv23_method"); - #if !defined(NO_WOLFSSL_CLIENT) - m = wolfSSLv23_client_method_ex(heap); - #elif !defined(NO_WOLFSSL_SERVER) - m = wolfSSLv23_server_method_ex(heap); - #else - (void)heap; - #endif - if (m != NULL) { - m->side = WOLFSSL_NEITHER_END; + WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (ctx->ref.count > 1) { + WOLFSSL_MSG("ctx object must have a ref count of 1 before " + "unloading intermediate certs"); + return BAD_STATE_E; } - return m; + return wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); } - #ifdef WOLFSSL_ALLOW_SSLV3 - WOLFSSL_METHOD* wolfSSLv3_method(void) + +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) { - return wolfSSLv3_method_ex(NULL); + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); } - WOLFSSL_METHOD* wolfSSLv3_method_ex(void* heap) + +#ifdef WOLFSSL_LOCAL_X509_STORE + int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) { - WOLFSSL_METHOD* m = NULL; - WOLFSSL_ENTER("wolfSSLv3_method_ex"); - #if !defined(NO_WOLFSSL_CLIENT) - m = wolfSSLv3_client_method_ex(heap); - #elif !defined(NO_WOLFSSL_SERVER) - m = wolfSSLv3_server_method_ex(heap); - #endif - if (m != NULL) { - m->side = WOLFSSL_NEITHER_END; - } + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); - return m; + if (ssl == NULL) + return BAD_FUNC_ARG; + + SSL_CM_WARNING(ssl); + return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl)); } - #endif -#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ +#endif /* WOLFSSL_LOCAL_X509_STORE */ +#endif /* WOLFSSL_TRUST_PEER_CERT */ +/* old NO_FILESYSTEM end */ +#endif /* !NO_CERTS */ -/* client only parts */ -#ifndef NO_WOLFSSL_CLIENT - #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) - WOLFSSL_METHOD* wolfSSLv2_client_method(void) - { - WOLFSSL_STUB("wolfSSLv2_client_method"); - return NULL; - } - #endif +#ifdef OPENSSL_EXTRA - #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) - WOLFSSL_METHOD* wolfSSLv3_client_method(void) + int wolfSSL_add_all_algorithms(void) { - return wolfSSLv3_client_method_ex(NULL); + WOLFSSL_ENTER("wolfSSL_add_all_algorithms"); + if (initRefCount != 0 || wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; } - WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap) + + int wolfSSL_OpenSSL_add_all_algorithms_noconf(void) { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), - heap, DYNAMIC_TYPE_METHOD); - (void)heap; - WOLFSSL_ENTER("wolfSSLv3_client_method_ex"); - if (method) - InitSSL_Method(method, MakeSSLv3()); - return method; - } - #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ + WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf"); + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) + return WOLFSSL_FATAL_ERROR; - WOLFSSL_METHOD* wolfSSLv23_client_method(void) - { - return wolfSSLv23_client_method_ex(NULL); + return WOLFSSL_SUCCESS; } - WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap) + + int wolfSSL_OpenSSL_add_all_algorithms_conf(void) { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), - heap, DYNAMIC_TYPE_METHOD); - (void)heap; - WOLFSSL_ENTER("wolfSSLv23_client_method_ex"); - if (method) { - #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) - #if defined(WOLFSSL_TLS13) - InitSSL_Method(method, MakeTLSv1_3()); - #elif !defined(WOLFSSL_NO_TLS12) - InitSSL_Method(method, MakeTLSv1_2()); - #elif !defined(NO_OLD_TLS) - InitSSL_Method(method, MakeTLSv1_1()); - #endif - #else - #ifndef NO_OLD_TLS - InitSSL_Method(method, MakeTLSv1_1()); - #endif - #endif - #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) - method->downgrade = 1; - #endif + WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_conf"); + /* This function is currently the same as + wolfSSL_OpenSSL_add_all_algorithms_noconf since we do not employ + the use of a wolfssl.cnf type configuration file and is only used for + OpenSSL compatibility. */ + + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) { + return WOLFSSL_FATAL_ERROR; } - return method; + return WOLFSSL_SUCCESS; } - /* please see note at top of README if you get an error from connect */ - WOLFSSL_ABI - int wolfSSL_connect(WOLFSSL* ssl) - { - #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) - int neededState; - byte advanceState; - #endif - int ret = 0; - - (void)ret; +#endif - #ifdef HAVE_ERRNO_H - errno = 0; - #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown"); + if (mode) + ctx->quietShutdown = 1; + } - if (ssl == NULL) - return BAD_FUNC_ARG; - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - if (ssl->options.side == WOLFSSL_NEITHER_END) { - ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END); - if (ssl->error != WOLFSSL_SUCCESS) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - ssl->error = 0; /* expected to be zero here */ - } + void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode) + { + WOLFSSL_ENTER("wolfSSL_set_quiet_shutdown"); + if (mode) + ssl->options.quietShutdown = 1; + } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || + WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - #ifdef OPENSSL_EXTRA - if (ssl->CBIS != NULL) { - ssl->CBIS(ssl, SSL_ST_CONNECT, WOLFSSL_SUCCESS); - ssl->cbmode = SSL_CB_WRITE; +#ifdef OPENSSL_EXTRA +#ifndef NO_BIO + void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) + { + WOLFSSL_ENTER("wolfSSL_set_bio"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument, ssl was NULL"); + return; } - #endif - #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ - #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) - return wolfSSL_connect_TLSv13(ssl); - #else - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { - WOLFSSL_MSG("TLS 1.3"); - return wolfSSL_connect_TLSv13(ssl); + /* free any existing WOLFSSL_BIOs in use but don't free those in + * a chain */ + if (ssl->biord != NULL) { + if (ssl->biord != ssl->biowr) { + if (ssl->biowr != NULL && ssl->biowr->prev != NULL) + wolfSSL_BIO_free(ssl->biowr); + ssl->biowr = NULL; + } + if (ssl->biord->prev != NULL) + wolfSSL_BIO_free(ssl->biord); + ssl->biord = NULL; } - #endif + /* set flag obviously */ + if (rd && !(rd->flags & WOLFSSL_BIO_FLAG_READ)) + rd->flags |= WOLFSSL_BIO_FLAG_READ; + if (wr && !(wr->flags & WOLFSSL_BIO_FLAG_WRITE)) + wr->flags |= WOLFSSL_BIO_FLAG_WRITE; - WOLFSSL_MSG("TLS 1.2 or lower"); - WOLFSSL_ENTER("wolfSSL_connect"); + ssl->biord = rd; + ssl->biowr = wr; - /* make sure this wolfSSL object has arrays and rng setup. Protects - * case where the WOLFSSL object is reused via wolfSSL_clear() */ - if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) { - return ret; + /* set SSL to use BIO callbacks instead */ + if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)) { + ssl->CBIORecv = BioReceive; } - -#ifdef WOLFSSL_WOLFSENTRY_HOOKS - if ((ssl->ConnectFilter != NULL) && - (ssl->options.connectState == CONNECT_BEGIN)) { - wolfSSL_netfilter_decision_t res; - if ((ssl->ConnectFilter(ssl, ssl->ConnectFilter_arg, &res) == - WOLFSSL_SUCCESS) && - (res == WOLFSSL_NETFILTER_REJECT)) { - ssl->error = SOCKET_FILTERED_E; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)) { + ssl->CBIOSend = BioSend; } -#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ - if (ssl->options.side != WOLFSSL_CLIENT_END) { - ssl->error = SIDE_ERROR; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + /* User programs should always retry reading from these BIOs */ + if (rd) { + /* User writes to rd */ + BIO_set_retry_write(rd); + } + if (wr) { + /* User reads from wr */ + BIO_set_retry_read(wr); } + } +#endif /* !NO_BIO */ +#endif /* OPENSSL_EXTRA */ - #ifdef WOLFSSL_DTLS - if (ssl->version.major == DTLS_MAJOR) { - ssl->options.dtls = 1; - ssl->options.tls = 1; - ssl->options.tls1_1 = 1; - ssl->options.dtlsStateful = 1; +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list"); + if (ctx != NULL) { + wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL); + ctx->client_ca_names = names; } - #endif + } - /* fragOffset is non-zero when sending fragments. On the last - * fragment, fragOffset is zero again, and the state can be - * advanced. */ - advanceState = ssl->fragOffset == 0 && - (ssl->options.connectState == CONNECT_BEGIN || - ssl->options.connectState == HELLO_AGAIN || - (ssl->options.connectState >= FIRST_REPLY_DONE && - ssl->options.connectState <= FIRST_REPLY_FOURTH)); + void wolfSSL_set_client_CA_list(WOLFSSL* ssl, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) + { + WOLFSSL_ENTER("wolfSSL_set_client_CA_list"); + if (ssl != NULL) { + if (ssl->client_ca_names != ssl->ctx->client_ca_names) + wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL); + ssl->client_ca_names = names; + } + } -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) - advanceState = advanceState && !ssl->dtls13SendingAckOrRtx; -#endif /* WOLFSSL_DTLS13 */ + #ifdef OPENSSL_EXTRA + /* registers client cert callback, called during handshake if server + requests client auth but user has not loaded client cert/key */ + void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb"); - if (ssl->buffers.outputBuffer.length > 0 - #ifdef WOLFSSL_ASYNC_CRYPT - /* do not send buffered or advance state if last error was an - async pending operation */ - && ssl->error != WC_PENDING_E - #endif - ) { - ret = SendBuffered(ssl); - if (ret == 0) { - if (ssl->fragOffset == 0 && !ssl->options.buildingMsg) { - if (advanceState) { - ssl->options.connectState++; - WOLFSSL_MSG("connect state: " - "Advanced from last buffered fragment send"); - #ifdef WOLFSSL_ASYNC_IO - /* Cleanup async */ - FreeAsyncCtx(ssl, 0); - #endif - } - } - else { - WOLFSSL_MSG("connect state: " - "Not advanced, more fragments to send"); - } - } - else { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls) - ssl->dtls13SendingAckOrRtx = 0; -#endif /* WOLFSSL_DTLS13 */ + if (ctx != NULL) { + ctx->CBClientCert = cb; } + } - ret = RetrySendAlert(ssl); - if (ret != 0) { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, + CertSetupCallback cb, void *arg) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb"); + if (ctx == NULL) + return; - switch (ssl->options.connectState) { + ctx->certSetupCb = cb; + ctx->certSetupCbArg = arg; + } - case CONNECT_BEGIN : - /* always send client hello first */ - if ( (ssl->error = SendClientHello(ssl)) != 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl, + const byte** suites, word16* suiteSz, + const byte** hashSigAlgo, word16* hashSigAlgoSz) + { + WOLFSSL_ENTER("wolfSSL_get_client_suites_sigalgs"); + + if (suites != NULL) + *suites = NULL; + if (suiteSz != NULL) + *suiteSz = 0; + if (hashSigAlgo != NULL) + *hashSigAlgo = NULL; + if (hashSigAlgoSz != NULL) + *hashSigAlgoSz = 0; + + if (ssl != NULL && ssl->clSuites != NULL) { + if (suites != NULL && suiteSz != NULL) { + *suites = ssl->clSuites->suites; + *suiteSz = ssl->clSuites->suiteSz; } - ssl->options.connectState = CLIENT_HELLO_SENT; - WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); - FALL_THROUGH; + if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) { + *hashSigAlgo = ssl->clSuites->hashSigAlgo; + *hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz; + } + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; + } + WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first, + byte second) + { + WOLFSSL_CIPHERSUITE_INFO info; + info.rsaAuth = (byte)(CipherRequires(first, second, REQUIRES_RSA) || + CipherRequires(first, second, REQUIRES_RSA_SIG)); + info.eccAuth = (byte)(CipherRequires(first, second, REQUIRES_ECC) || + /* Static ECC ciphers may require RSA for authentication */ + (CipherRequires(first, second, REQUIRES_ECC_STATIC) && + !CipherRequires(first, second, REQUIRES_RSA_SIG))); + info.eccStatic = + (byte)CipherRequires(first, second, REQUIRES_ECC_STATIC); + info.psk = (byte)CipherRequires(first, second, REQUIRES_PSK); + return info; + } - case CLIENT_HELLO_SENT : - neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : - SERVER_HELLODONE_COMPLETE; - #ifdef WOLFSSL_DTLS - /* In DTLS, when resuming, we can go straight to FINISHED, - * or do a cookie exchange and then skip to FINISHED, assume - * we need the cookie exchange first. */ - if (IsDtlsNotSctpMode(ssl)) - neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; - #endif - /* get response */ - WOLFSSL_MSG("Server state up to needed state."); - while (ssl->options.serverState < neededState) { - WOLFSSL_MSG("Progressing server state..."); - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) - return wolfSSL_connect_TLSv13(ssl); - #endif - WOLFSSL_MSG("ProcessReply..."); - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - /* if resumption failed, reset needed state */ - else if (neededState == SERVER_FINISHED_COMPLETE) { - if (!ssl->options.resuming) { - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) - neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; - else - #endif - neededState = SERVER_HELLODONE_COMPLETE; - } - } - WOLFSSL_MSG("ProcessReply done."); + /** + * @param first First byte of the hash and signature algorithm + * @param second Second byte of the hash and signature algorithm + * @param hashAlgo The enum wc_HashType of the MAC algorithm + * @param sigAlgo The enum Key_Sum of the authentication algorithm + */ + int wolfSSL_get_sigalg_info(byte first, byte second, + int* hashAlgo, int* sigAlgo) + { + byte input[2]; + byte hashType; + byte sigType; -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version) - && ssl->dtls13Rtx.sendAcks == 1 - && ssl->options.seenUnifiedHdr) { - /* we aren't negotiated the version yet, so we aren't sure - * the other end can speak v1.3. On the other side we have - * received a unified records, assuming that the - * ServerHello got lost, we will send an empty ACK. In case - * the server is a DTLS with version less than 1.3, it - * should just ignore the message */ - ssl->dtls13Rtx.sendAcks = 0; - if ((ssl->error = SendDtls13Ack(ssl)) < 0) { - if (ssl->error == WANT_WRITE) - ssl->dtls13SendingAckOrRtx = 1; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } -#endif /* WOLFSSL_DTLS13 */ - } + if (hashAlgo == NULL || sigAlgo == NULL) + return BAD_FUNC_ARG; - ssl->options.connectState = HELLO_AGAIN; - WOLFSSL_MSG("connect state: HELLO_AGAIN"); - FALL_THROUGH; + input[0] = first; + input[1] = second; + DecodeSigAlg(input, &hashType, &sigType); - case HELLO_AGAIN : + /* cast so that compiler reminds us of unimplemented values */ + switch ((enum SignatureAlgorithm)sigType) { + case anonymous_sa_algo: + *sigAlgo = ANONk; + break; + case rsa_sa_algo: + *sigAlgo = RSAk; + break; + case dsa_sa_algo: + *sigAlgo = DSAk; + break; + case ecc_dsa_sa_algo: + *sigAlgo = ECDSAk; + break; + case rsa_pss_sa_algo: + *sigAlgo = RSAPSSk; + break; + case ed25519_sa_algo: + *sigAlgo = ED25519k; + break; + case rsa_pss_pss_algo: + *sigAlgo = RSAPSSk; + break; + case ed448_sa_algo: + *sigAlgo = ED448k; + break; + case falcon_level1_sa_algo: + *sigAlgo = FALCON_LEVEL1k; + break; + case falcon_level5_sa_algo: + *sigAlgo = FALCON_LEVEL5k; + break; + case dilithium_level2_sa_algo: + *sigAlgo = DILITHIUM_LEVEL2k; + break; + case dilithium_level3_sa_algo: + *sigAlgo = DILITHIUM_LEVEL3k; + break; + case dilithium_level5_sa_algo: + *sigAlgo = DILITHIUM_LEVEL5k; + break; + case sm2_sa_algo: + *sigAlgo = SM2k; + break; + case invalid_sa_algo: + default: + *hashAlgo = WC_HASH_TYPE_NONE; + *sigAlgo = 0; + return BAD_FUNC_ARG; + } - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) - return wolfSSL_connect_TLSv13(ssl); - #endif + /* cast so that compiler reminds us of unimplemented values */ + switch((enum wc_MACAlgorithm)hashType) { + case no_mac: + case rmd_mac: /* Don't have a RIPEMD type in wc_HashType */ + *hashAlgo = WC_HASH_TYPE_NONE; + break; + case md5_mac: + *hashAlgo = WC_HASH_TYPE_MD5; + break; + case sha_mac: + *hashAlgo = WC_HASH_TYPE_SHA; + break; + case sha224_mac: + *hashAlgo = WC_HASH_TYPE_SHA224; + break; + case sha256_mac: + *hashAlgo = WC_HASH_TYPE_SHA256; + break; + case sha384_mac: + *hashAlgo = WC_HASH_TYPE_SHA384; + break; + case sha512_mac: + *hashAlgo = WC_HASH_TYPE_SHA512; + break; + case blake2b_mac: + *hashAlgo = WC_HASH_TYPE_BLAKE2B; + break; + case sm3_mac: +#ifdef WOLFSSL_SM3 + *hashAlgo = WC_HASH_TYPE_SM3; +#else + *hashAlgo = WC_HASH_TYPE_NONE; +#endif + break; + default: + *hashAlgo = WC_HASH_TYPE_NONE; + *sigAlgo = 0; + return BAD_FUNC_ARG; + } + return 0; + } - #ifdef WOLFSSL_DTLS - if (ssl->options.serverState == - SERVER_HELLOVERIFYREQUEST_COMPLETE) { - if (IsDtlsNotSctpMode(ssl)) { - /* re-init hashes, exclude first hello and verify request */ - if ((ssl->error = InitHandshakeHashes(ssl)) != 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - if ( (ssl->error = SendClientHello(ssl)) != 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } + /** + * Internal wrapper for calling certSetupCb + * @param ssl The SSL/TLS Object + * @return 0 on success + */ + int CertSetupCbWrapper(WOLFSSL* ssl) + { + int ret = 0; + if (ssl->ctx->certSetupCb != NULL) { + WOLFSSL_MSG("Calling user cert setup callback"); + ret = ssl->ctx->certSetupCb(ssl, ssl->ctx->certSetupCbArg); + if (ret == 1) { + WOLFSSL_MSG("User cert callback returned success"); + ret = 0; } - #endif + else if (ret == 0) { + SendAlert(ssl, alert_fatal, internal_error); + ret = CLIENT_CERT_CB_ERROR; + } + else if (ret < 0) { + ret = WOLFSSL_ERROR_WANT_X509_LOOKUP; + } + else { + WOLFSSL_MSG("Unexpected user callback return"); + ret = CLIENT_CERT_CB_ERROR; + } + } + return ret; + } + #endif /* OPENSSL_EXTRA */ - ssl->options.connectState = HELLO_AGAIN_REPLY; - WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); - FALL_THROUGH; +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ - case HELLO_AGAIN_REPLY : - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - neededState = ssl->options.resuming ? - SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; +#ifndef WOLFSSL_NO_CA_NAMES + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list"); - /* get response */ - while (ssl->options.serverState < neededState) { - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - /* if resumption failed, reset needed state */ - if (neededState == SERVER_FINISHED_COMPLETE) { - if (!ssl->options.resuming) - neededState = SERVER_HELLODONE_COMPLETE; - } - } - } - #endif + if (ctx == NULL) { + WOLFSSL_MSG("Bad argument passed to " + "wolfSSL_CTX_get_client_CA_list"); + return NULL; + } - ssl->options.connectState = FIRST_REPLY_DONE; - WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); - FALL_THROUGH; + return ctx->client_ca_names; + } - case FIRST_REPLY_DONE : - if (ssl->options.certOnly) - return WOLFSSL_SUCCESS; - #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) - return wolfSSL_connect_TLSv13(ssl); - #endif - if (ssl->options.sendVerify) { - if ( (ssl->error = SendCertificate(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - WOLFSSL_MSG("sent: certificate"); - } + /* returns the CA's set on server side or the CA's sent from server when + * on client side */ + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( + const WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_get_client_CA_list"); - #endif - ssl->options.connectState = FIRST_REPLY_FIRST; - WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); - FALL_THROUGH; + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); + return NULL; + } - case FIRST_REPLY_FIRST : - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) - return wolfSSL_connect_TLSv13(ssl); - #endif - if (!ssl->options.resuming) { - if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif -#ifdef WOLFSSL_EXTRA_ALERTS - if (ssl->error == NO_PEER_KEY || - ssl->error == PSK_KEY_ERROR) { - SendAlert(ssl, alert_fatal, handshake_failure); - } -#endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - WOLFSSL_MSG("sent: client key exchange"); - } + return SSL_CA_NAMES(ssl); + } - ssl->options.connectState = FIRST_REPLY_SECOND; - WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); - FALL_THROUGH; + #if !defined(NO_CERTS) + int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_X509_NAME *nameCopy = NULL; - #if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) - case FIRST_REPLY_SECOND : - /* CLIENT: Fail-safe for Server Authentication. */ - if (!ssl->options.peerAuthGood) { - WOLFSSL_MSG("Server authentication did not happen"); - ssl->error = NO_PEER_VERIFY; - return WOLFSSL_FATAL_ERROR; - } + WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); - #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) - if (ssl->options.sendVerify) { - if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - WOLFSSL_MSG("sent: certificate verify"); - } - #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */ - ssl->options.connectState = FIRST_REPLY_THIRD; - WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); - FALL_THROUGH; + if (ctx == NULL || x509 == NULL){ + WOLFSSL_MSG("Bad argument"); + return WOLFSSL_FAILURE; + } - case FIRST_REPLY_THIRD : - if ( (ssl->error = SendChangeCipher(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + if (ctx->client_ca_names == NULL) { + ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); + if (ctx->client_ca_names == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + return WOLFSSL_FAILURE; } - 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) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - WOLFSSL_MSG("sent: finished"); - ssl->options.connectState = FINISHED_DONE; - WOLFSSL_MSG("connect state: FINISHED_DONE"); - FALL_THROUGH; + nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); + if (nameCopy == NULL) { + WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); + return WOLFSSL_FAILURE; + } -#ifdef WOLFSSL_DTLS13 - case WAIT_FINISHED_ACK: - ssl->options.connectState = FINISHED_DONE; - FALL_THROUGH; -#endif /* WOLFSSL_DTLS13 */ + if (wolfSSL_sk_X509_NAME_push(ctx->client_ca_names, nameCopy) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); + wolfSSL_X509_NAME_free(nameCopy); + return WOLFSSL_FAILURE; + } - case FINISHED_DONE : - /* get response */ - while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + return WOLFSSL_SUCCESS; + } + #endif - ssl->options.connectState = SECOND_REPLY_DONE; - WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); - FALL_THROUGH; + #ifndef NO_BIO + #if !defined(NO_RSA) && !defined(NO_CERTS) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file( + const char* fname) + { + /* The webserver build is using this to load a CA into the server + * for client authentication as an option. Have this return NULL in + * that case. If OPENSSL_EXTRA is enabled, go ahead and include + * the function. */ + #ifdef OPENSSL_EXTRA + WOLFSSL_STACK *list = NULL; + WOLFSSL_BIO* bio = NULL; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *nameCopy = NULL; + unsigned long err = WOLFSSL_FAILURE; - case SECOND_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 WOLFSSL_FATAL_ERROR; - } - } - #endif /* NO_HANDSHAKE_DONE_CB */ + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); - if (!ssl->options.dtls) { - if (!ssl->options.keepResources) { - FreeHandshakeResources(ssl); - } - } - #ifdef WOLFSSL_DTLS - else { - ssl->options.dtlsHsRetain = 1; + bio = wolfSSL_BIO_new_file(fname, "rb"); + if (bio == NULL) { + WOLFSSL_MSG("wolfSSL_BIO_new_file error"); + goto cleanup; } - #endif /* WOLFSSL_DTLS */ - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION) - /* This may be necessary in async so that we don't try to - * renegotiate again */ - if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { - ssl->secure_renegotiation->startScr = 0; + list = wolfSSL_sk_X509_NAME_new(NULL); + if (list == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); + goto cleanup; } - #endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */ - #if defined(WOLFSSL_ASYNC_IO) && !defined(WOLFSSL_ASYNC_CRYPT) - /* Free the remaining async context if not using it for crypto */ - FreeAsyncCtx(ssl, 1); - #endif - - ssl->error = 0; /* clear the error */ - WOLFSSL_LEAVE("wolfSSL_connect", WOLFSSL_SUCCESS); - return WOLFSSL_SUCCESS; - #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + /* Need a persistent copy of the subject name. */ + nameCopy = wolfSSL_X509_NAME_dup( + wolfSSL_X509_get_subject_name(cert)); + if (nameCopy == NULL) { + WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); + goto cleanup; + } + /* + * Original cert will be freed so make sure not to try to access + * it in the future. + */ + nameCopy->x509 = NULL; - default: - WOLFSSL_MSG("Unknown connect state ERROR"); - return WOLFSSL_FATAL_ERROR; /* unknown connect state */ - } - #endif /* !WOLFSSL_NO_TLS12 || !NO_OLD_TLS || !WOLFSSL_TLS13 */ - } + if (wolfSSL_sk_X509_NAME_push(list, nameCopy) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); + /* Do free in loop because nameCopy is now responsibility + * of list to free and adding jumps to cleanup after this + * might result in a double free. */ + wolfSSL_X509_NAME_free(nameCopy); + goto cleanup; + } -#endif /* NO_WOLFSSL_CLIENT */ + wolfSSL_X509_free(cert); + cert = NULL; + } + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); -/* server only parts */ -#ifndef NO_WOLFSSL_SERVER + err = WOLFSSL_SUCCESS; +cleanup: + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + if (err != WOLFSSL_SUCCESS) { + /* We failed so return NULL */ + wolfSSL_sk_X509_NAME_pop_free(list, NULL); + list = NULL; + } + return list; + #else + (void)fname; + return NULL; + #endif + } + #endif + #endif /* !NO_BIO */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */ - #if defined(OPENSSL_EXTRA) && !defined(NO_OLD_TLS) - WOLFSSL_METHOD* wolfSSLv2_server_method(void) - { - WOLFSSL_STUB("wolfSSLv2_server_method"); - return 0; - } - #endif +#ifdef OPENSSL_EXTRA - #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) - WOLFSSL_METHOD* wolfSSLv3_server_method(void) + #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ + && !defined(WC_NO_RNG) + static const byte srp_N[] = { + 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8, + 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, + 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6, + 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13, + 0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, + 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7, + 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69, + 0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85, + 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC, + 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, + 0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F, + 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3 + }; + static const byte srp_g[] = { + 0x02 + }; + + int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username) { - return wolfSSLv3_server_method_ex(NULL); + int r = 0; + SrpSide srp_side = SRP_CLIENT_SIDE; + byte salt[SRP_SALT_SIZE]; + + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username"); + if (ctx == NULL || ctx->srp == NULL || username==NULL) + return WOLFSSL_FAILURE; + + if (ctx->method->side == WOLFSSL_SERVER_END){ + srp_side = SRP_SERVER_SIDE; + } else if (ctx->method->side == WOLFSSL_CLIENT_END){ + srp_side = SRP_CLIENT_SIDE; + } else { + WOLFSSL_MSG("Init CTX failed"); + return WOLFSSL_FAILURE; + } + + if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0) { + WOLFSSL_MSG("Init SRP CTX failed"); + XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp = NULL; + return WOLFSSL_FAILURE; + } + r = wc_SrpSetUsername(ctx->srp, (const byte*)username, + (word32)XSTRLEN(username)); + if (r < 0) { + WOLFSSL_MSG("fail to set srp username."); + return WOLFSSL_FAILURE; + } + + /* if wolfSSL_CTX_set_srp_password has already been called, */ + /* execute wc_SrpSetPassword here */ + if (ctx->srp_password != NULL) { + WC_RNG rng; + if (wc_InitRng(&rng) < 0){ + WOLFSSL_MSG("wc_InitRng failed"); + return WOLFSSL_FAILURE; + } + XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); + r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0])); + wc_FreeRng(&rng); + if (r < 0) { + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + return WOLFSSL_FAILURE; + } + + if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), + srp_g, sizeof(srp_g)/sizeof(srp_g[0]), + salt, sizeof(salt)/sizeof(salt[0])) < 0) { + WOLFSSL_MSG("wc_SrpSetParam failed"); + return WOLFSSL_FAILURE; + } + r = wc_SrpSetPassword(ctx->srp, + (const byte*)ctx->srp_password, + (word32)XSTRLEN((char *)ctx->srp_password)); + if (r < 0) { + WOLFSSL_MSG("fail to set srp password."); + return WOLFSSL_FAILURE; + } + + XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + + return WOLFSSL_SUCCESS; } - WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap) + + int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password) { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), - heap, DYNAMIC_TYPE_METHOD); - (void)heap; - WOLFSSL_ENTER("wolfSSLv3_server_method_ex"); - if (method) { - InitSSL_Method(method, MakeSSLv3()); - method->side = WOLFSSL_SERVER_END; + int r; + byte salt[SRP_SALT_SIZE]; + + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password"); + if (ctx == NULL || ctx->srp == NULL || password == NULL) + return WOLFSSL_FAILURE; + + if (ctx->srp->user != NULL) { + WC_RNG rng; + if (wc_InitRng(&rng) < 0) { + WOLFSSL_MSG("wc_InitRng failed"); + return WOLFSSL_FAILURE; + } + XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); + r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0])); + wc_FreeRng(&rng); + if (r < 0) { + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + return WOLFSSL_FAILURE; + } + if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), + srp_g, sizeof(srp_g)/sizeof(srp_g[0]), + salt, sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_SrpSetParam failed"); + wc_FreeRng(&rng); + return WOLFSSL_FAILURE; + } + r = wc_SrpSetPassword(ctx->srp, (const byte*)password, + (word32)XSTRLEN(password)); + if (r < 0) { + WOLFSSL_MSG("wc_SrpSetPassword failed."); + wc_FreeRng(&rng); + return WOLFSSL_FAILURE; + } + if (ctx->srp_password != NULL){ + XFREE(ctx->srp_password,NULL, + DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + wc_FreeRng(&rng); + } else { + /* save password for wolfSSL_set_srp_username */ + if (ctx->srp_password != NULL) + XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP); + + ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap, + DYNAMIC_TYPE_SRP); + if (ctx->srp_password == NULL){ + WOLFSSL_MSG("memory allocation error"); + return WOLFSSL_FAILURE; + } + XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1); } - return method; + return WOLFSSL_SUCCESS; } - #endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ - WOLFSSL_METHOD* wolfSSLv23_server_method(void) + /** + * The modulus passed to wc_SrpSetParams in ssl.c is constant so check + * that the requested strength is less than or equal to the size of the + * static modulus size. + * @param ctx Not used + * @param strength Minimum number of bits for the modulus + * @return 1 if strength is less than or equal to static modulus + * 0 if strength is greater than static modulus + */ + int wolfSSL_CTX_set_srp_strength(WOLFSSL_CTX *ctx, int strength) { - return wolfSSLv23_server_method_ex(NULL); + (void)ctx; + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_strength"); + if (strength > (int)(sizeof(srp_N)*8)) { + WOLFSSL_MSG("Bad Parameter"); + return WOLFSSL_FAILURE; + } + return WOLFSSL_SUCCESS; } - WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap) + char* wolfSSL_get_srp_username(WOLFSSL *ssl) { - WOLFSSL_METHOD* method = - (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), - heap, DYNAMIC_TYPE_METHOD); - (void)heap; - WOLFSSL_ENTER("wolfSSLv23_server_method_ex"); - if (method) { - #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) - #ifdef WOLFSSL_TLS13 - InitSSL_Method(method, MakeTLSv1_3()); - #elif !defined(WOLFSSL_NO_TLS12) - InitSSL_Method(method, MakeTLSv1_2()); - #elif !defined(NO_OLD_TLS) - InitSSL_Method(method, MakeTLSv1_1()); - #endif - #else - #ifndef NO_OLD_TLS - InitSSL_Method(method, MakeTLSv1_1()); - #else - #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 - #endif - #endif - #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) - method->downgrade = 1; - #endif - method->side = WOLFSSL_SERVER_END; + if (ssl && ssl->ctx && ssl->ctx->srp) { + return (char*) ssl->ctx->srp->user; } - return method; + return NULL; } + #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */ - - WOLFSSL_ABI - int wolfSSL_accept(WOLFSSL* ssl) + /* keyblock size in bytes or -1 */ + int wolfSSL_get_keyblock_size(WOLFSSL* ssl) { -#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) - word16 havePSK = 0; - word16 haveAnon = 0; - word16 haveMcast = 0; -#endif - int ret = 0; - - (void)ret; - if (ssl == NULL) return WOLFSSL_FATAL_ERROR; - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) - if (ssl->options.side == WOLFSSL_NEITHER_END) { - WOLFSSL_MSG("Setting WOLFSSL_SSL to be server side"); - ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END); - if (ssl->error != WOLFSSL_SUCCESS) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - ssl->error = 0; /* expected to be zero here */ - } - #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + return 2 * (ssl->specs.key_size + ssl->specs.iv_size + + ssl->specs.hash_size); + } -#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) - return wolfSSL_accept_TLSv13(ssl); -#else - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) - return wolfSSL_accept_TLSv13(ssl); - #endif - WOLFSSL_ENTER("wolfSSL_accept"); +#endif /* OPENSSL_EXTRA */ - /* make sure this wolfSSL object has arrays and rng setup. Protects - * case where the WOLFSSL object is reused via wolfSSL_clear() */ - if ((ret = ReinitSSL(ssl, ssl->ctx, 0)) != 0) { - return ret; - } +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || \ + defined(WOLFSSL_WPAS_SMALL) -#ifdef WOLFSSL_WOLFSENTRY_HOOKS - if ((ssl->AcceptFilter != NULL) && - ((ssl->options.acceptState == ACCEPT_BEGIN) -#ifdef HAVE_SECURE_RENEGOTIATION - || (ssl->options.acceptState == ACCEPT_BEGIN_RENEG) -#endif - )) - { - wolfSSL_netfilter_decision_t res; - if ((ssl->AcceptFilter(ssl, ssl->AcceptFilter_arg, &res) == - WOLFSSL_SUCCESS) && - (res == WOLFSSL_NETFILTER_REJECT)) { - ssl->error = SOCKET_FILTERED_E; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } -#endif /* WOLFSSL_WOLFSENTRY_HOOKS */ + /* store keys returns WOLFSSL_SUCCESS or -1 on error */ + int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen, + unsigned char** sr, unsigned int* srLen, + unsigned char** cr, unsigned int* crLen) + { + if (ssl == NULL || ssl->arrays == NULL) + return WOLFSSL_FATAL_ERROR; - #ifdef HAVE_ERRNO_H - errno = 0; - #endif + *ms = ssl->arrays->masterSecret; + *sr = ssl->arrays->serverRandom; + *cr = ssl->arrays->clientRandom; - #ifndef NO_PSK - havePSK = ssl->options.havePSK; - #endif - (void)havePSK; + *msLen = SECRET_LEN; + *srLen = RAN_LEN; + *crLen = RAN_LEN; - #ifdef HAVE_ANON - haveAnon = ssl->options.useAnon; - #endif - (void)haveAnon; + return WOLFSSL_SUCCESS; + } - #ifdef WOLFSSL_MULTICAST - haveMcast = ssl->options.haveMcast; - #endif - (void)haveMcast; + void wolfSSL_set_accept_state(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_set_accept_state"); - if (ssl->options.side != WOLFSSL_SERVER_END) { - ssl->error = SIDE_ERROR; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + if (ssl == NULL) + return; - #ifndef NO_CERTS - /* in case used set_accept_state after init */ - if (!havePSK && !haveAnon && !haveMcast) { - #ifdef OPENSSL_EXTRA - if (ssl->ctx->certSetupCb != NULL) { - WOLFSSL_MSG("CertSetupCb set. server cert and " - "key not checked"); - } - else + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key = NULL; + #else + ecc_key key[1]; #endif - { - if (!ssl->buffers.certificate || - !ssl->buffers.certificate->buffer) { - - WOLFSSL_MSG("accept error: server cert required"); - ssl->error = NO_PRIVATE_KEY; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } + word32 idx = 0; - if (!ssl->buffers.key || !ssl->buffers.key->buffer) { - /* allow no private key if using existing key */ - #ifdef WOLF_PRIVATE_KEY_ID - if (ssl->devId != INVALID_DEVID - #ifdef HAVE_PK_CALLBACKS - || wolfSSL_CTX_IsPrivatePkSet(ssl->ctx) - #endif - ) { - WOLFSSL_MSG("Allowing no server private key " - "(external)"); - } - else - #endif - { - WOLFSSL_MSG("accept error: server key required"); - ssl->error = NO_PRIVATE_KEY; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } + #ifdef WOLFSSL_SMALL_STACK + key = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_ECC); + if (key == NULL) { + WOLFSSL_MSG("Error allocating memory for ecc_key"); } - } - #endif - - #ifdef WOLFSSL_DTLS - if (ssl->version.major == DTLS_MAJOR) { - ssl->options.dtls = 1; - ssl->options.tls = 1; - ssl->options.tls1_1 = 1; - if (!IsDtlsNotSctpMode(ssl) || !IsDtlsNotSrtpMode(ssl) || - IsSCR(ssl)) - ssl->options.dtlsStateful = 1; - } - #endif - - if (ssl->buffers.outputBuffer.length > 0 - #ifdef WOLFSSL_ASYNC_CRYPT - /* do not send buffered or advance state if last error was an - async pending operation */ - && ssl->error != WC_PENDING_E #endif - ) { - ret = SendBuffered(ssl); - if (ret == 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.buildingMsg) { - if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE || - ssl->options.acceptState == SERVER_HELLO_SENT || - ssl->options.acceptState == CERT_SENT || - ssl->options.acceptState == CERT_STATUS_SENT || - ssl->options.acceptState == KEY_EXCHANGE_SENT || - ssl->options.acceptState == CERT_REQ_SENT || - ssl->options.acceptState == ACCEPT_SECOND_REPLY_DONE || - ssl->options.acceptState == TICKET_SENT || - ssl->options.acceptState == CHANGE_CIPHER_SENT) { - ssl->options.acceptState++; - WOLFSSL_MSG("accept state: " - "Advanced from last buffered fragment send"); - #ifdef WOLFSSL_ASYNC_IO - /* Cleanup async */ - FreeAsyncCtx(ssl, 0); - #endif + if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { + if (wc_ecc_init(key) >= 0) { + 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; } - } - else { - WOLFSSL_MSG("accept state: " - "Not advanced, more fragments to send"); + wc_ecc_free(key); } } - else { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, ssl->heap, DYNAMIC_TYPE_ECC); + #endif + #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; } -#ifdef WOLFSSL_DTLS13 - if (ssl->options.dtls) - ssl->dtls13SendingAckOrRtx = 0; -#endif /* WOLFSSL_DTLS13 */ + #endif } - ret = RetrySendAlert(ssl); - if (ret != 0) { - ssl->error = ret; - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; + if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error initializing server side"); } + } - switch (ssl->options.acceptState) { +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - case ACCEPT_BEGIN : -#ifdef HAVE_SECURE_RENEGOTIATION - case ACCEPT_BEGIN_RENEG: -#endif - /* get response */ - while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } -#ifdef WOLFSSL_TLS13 - ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; - WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); - FALL_THROUGH; + /* return true if connection established */ + int wolfSSL_is_init_finished(const WOLFSSL* ssl) + { + if (ssl == NULL) + return 0; - case ACCEPT_CLIENT_HELLO_DONE : - if (ssl->options.tls1_3) { - return wolfSSL_accept_TLSv13(ssl); - } -#endif + /* Can't use ssl->options.connectState and ssl->options.acceptState + * because they differ in meaning for TLS <=1.2 and 1.3 */ + if (ssl->options.handShakeState == HANDSHAKE_DONE) + return 1; - ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; - WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); - FALL_THROUGH; + return 0; + } - case ACCEPT_FIRST_REPLY_DONE : - if ( (ssl->error = SendServerHello(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - ssl->options.acceptState = SERVER_HELLO_SENT; - WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); - FALL_THROUGH; +#ifdef OPENSSL_EXTRA + void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx, + WOLFSSL_RSA*(*f)(WOLFSSL*, int, int)) + { + /* wolfSSL verifies all these internally */ + (void)ctx; + (void)f; + } - case SERVER_HELLO_SENT : - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { - return wolfSSL_accept_TLSv13(ssl); - } - #endif - #ifndef NO_CERTS - if (!ssl->options.resuming) - if ( (ssl->error = SendCertificate(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_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 = SendCertificateStatus(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - #endif - ssl->options.acceptState = CERT_STATUS_SENT; - WOLFSSL_MSG("accept state CERT_STATUS_SENT"); - FALL_THROUGH; - - case CERT_STATUS_SENT : - #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { - return wolfSSL_accept_TLSv13(ssl); - } - #endif - if (!ssl->options.resuming) - if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - ssl->options.acceptState = KEY_EXCHANGE_SENT; - WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); - FALL_THROUGH; + void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt) + { + WOLFSSL_ENTER("wolfSSL_set_shutdown"); + if(ssl==NULL) { + WOLFSSL_MSG("Shutdown not set. ssl is null"); + return; + } - case KEY_EXCHANGE_SENT : - #ifndef NO_CERTS - if (!ssl->options.resuming) { - if (ssl->options.verifyPeer) { - if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } - else { - /* SERVER: Peer auth good if not verifying client. */ - ssl->options.peerAuthGood = 1; - } - } - #endif - ssl->options.acceptState = CERT_REQ_SENT; - WOLFSSL_MSG("accept state CERT_REQ_SENT"); - FALL_THROUGH; + ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0; + ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0; + } +#endif - case CERT_REQ_SENT : - if (!ssl->options.resuming) - if ( (ssl->error = SendServerHelloDone(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - ssl->options.acceptState = SERVER_HELLO_DONE; - WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); - FALL_THROUGH; + long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_get_options"); + WOLFSSL_MSG("wolfSSL options are set through API calls and macros"); + if(ctx == NULL) + return BAD_FUNC_ARG; + return ctx->mask; + } - case SERVER_HELLO_DONE : - if (!ssl->options.resuming) { - while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } - ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; - WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); - FALL_THROUGH; + /* forward declaration */ + static long wolf_set_options(long old_op, long op); - case ACCEPT_SECOND_REPLY_DONE : - #ifndef NO_CERTS - /* SERVER: When not resuming and verifying peer but no certificate - * received and not failing when not received then peer auth good. - */ - if (!ssl->options.resuming && ssl->options.verifyPeer && - !ssl->options.havePeerCert && !ssl->options.failNoCert) { - ssl->options.peerAuthGood = 1; - } - #endif /* !NO_CERTS */ - #ifdef WOLFSSL_NO_CLIENT_AUTH - if (!ssl->options.resuming) { - ssl->options.peerAuthGood = 1; - } - #endif + long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_options"); -#ifdef HAVE_SESSION_TICKET - if (ssl->options.createTicket && !ssl->options.noTicketTls12) { - if ( (ssl->error = SendTicket(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_MSG("Thought we need ticket but failed"); - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } -#endif /* HAVE_SESSION_TICKET */ - ssl->options.acceptState = TICKET_SENT; - WOLFSSL_MSG("accept state TICKET_SENT"); - FALL_THROUGH; + if (ctx == NULL) + return BAD_FUNC_ARG; - case TICKET_SENT: - /* SERVER: Fail-safe for CLient Authentication. */ - if (!ssl->options.peerAuthGood) { - WOLFSSL_MSG("Client authentication did not happen"); - return WOLFSSL_FATAL_ERROR; + ctx->mask = wolf_set_options(ctx->mask, opt); +#if defined(HAVE_SESSION_TICKET) && (defined(OPENSSL_EXTRA) \ + || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)) + if ((ctx->mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) { + ctx->noTicketTls12 = 1; + } + /* This code is here for documentation purpose. You must not turn off + * session tickets with the WOLFSSL_OP_NO_TICKET option for TLSv1.3. + * Because we need to support both stateful and stateless tickets. + #ifdef WOLFSSL_TLS13 + if ((ctx->mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) { + ctx->noTicketTls13 = 1; } + #endif + */ +#endif + return ctx->mask; + } - if ( (ssl->error = SendChangeCipher(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - ssl->options.acceptState = CHANGE_CIPHER_SENT; - WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); - FALL_THROUGH; + long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) + { + WOLFSSL_ENTER("wolfSSL_CTX_clear_options"); + if(ctx == NULL) + return BAD_FUNC_ARG; + ctx->mask &= ~opt; + return ctx->mask; + } - case CHANGE_CIPHER_SENT : - if ( (ssl->error = SendFinished(ssl)) != 0) { - #ifdef WOLFSSL_CHECK_ALERT_ON_ERR - ProcessReplyEx(ssl, 1); /* See if an alert was sent. */ - #endif - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } +#ifdef OPENSSL_EXTRA - ssl->options.acceptState = ACCEPT_FINISHED_DONE; - WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); - FALL_THROUGH; + int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd) + { + WOLFSSL_ENTER("wolfSSL_set_rfd"); + ssl->rfd = rfd; /* not used directly to allow IO callbacks */ - case ACCEPT_FINISHED_DONE : - if (ssl->options.resuming) { - while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) { - if ( (ssl->error = ProcessReply(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } - } - ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; - WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); - FALL_THROUGH; + ssl->IOCB_ReadCtx = &ssl->rfd; - 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 WOLFSSL_FATAL_ERROR; - } - } -#endif /* NO_HANDSHAKE_DONE_CB */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; + ssl->buffers.dtlsCtx.rfd = rfd; + } + #endif - if (!ssl->options.dtls) { - if (!ssl->options.keepResources) { - FreeHandshakeResources(ssl); - } - } -#ifdef WOLFSSL_DTLS - else { - ssl->options.dtlsHsRetain = 1; - } -#endif /* WOLFSSL_DTLS */ + return WOLFSSL_SUCCESS; + } -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION) - /* This may be necessary in async so that we don't try to - * renegotiate again */ - if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { - ssl->secure_renegotiation->startScr = 0; - } -#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */ -#if defined(WOLFSSL_ASYNC_IO) && !defined(WOLFSSL_ASYNC_CRYPT) - /* Free the remaining async context if not using it for crypto */ - FreeAsyncCtx(ssl, 1); -#endif -#if defined(WOLFSSL_SESSION_EXPORT) && defined(WOLFSSL_DTLS) - if (ssl->dtls_export) { - if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { - WOLFSSL_MSG("Export DTLS session error"); - WOLFSSL_ERROR(ssl->error); - return WOLFSSL_FATAL_ERROR; - } - } -#endif - ssl->error = 0; /* clear the error */ + int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd) + { + WOLFSSL_ENTER("wolfSSL_set_wfd"); + ssl->wfd = wfd; /* not used directly to allow IO callbacks */ - WOLFSSL_LEAVE("wolfSSL_accept", WOLFSSL_SUCCESS); - return WOLFSSL_SUCCESS; + ssl->IOCB_WriteCtx = &ssl->wfd; - default : - WOLFSSL_MSG("Unknown accept state ERROR"); - return WOLFSSL_FATAL_ERROR; - } -#endif /* !WOLFSSL_NO_TLS12 */ + return WOLFSSL_SUCCESS; } +#endif /* OPENSSL_EXTRA */ -#endif /* NO_WOLFSSL_SERVER */ +#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_WPAS_SMALL)) -#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) -int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx) -{ - WOLFSSL_ENTER("wolfDTLS_SetChGoodCb"); +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /** + * Implemented in a similar way that ngx_ssl_ocsp_validate does it when + * SSL_get0_verified_chain is not available. + * @param ssl WOLFSSL object to extract certs from + * @return Stack of verified certs + */ + WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) + { + WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; + WOLFSSL_X509_STORE_CTX* storeCtx = NULL; + WOLFSSL_X509* peerCert = NULL; - if (ssl == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); - ssl->chGoodCb = cb; - ssl->chGoodCtx = user_ctx; + if (ssl == NULL || ssl->ctx == NULL) { + WOLFSSL_MSG("Bad parameter"); + return NULL; + } - return WOLFSSL_SUCCESS; -} -#endif + peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl); + if (peerCert == NULL) { + WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); + return NULL; + } + /* wolfSSL_get_peer_certificate returns a copy. We want the internal + * member so that we don't have to worry about free'ing it. We call + * wolfSSL_get_peer_certificate so that we don't have to worry about + * setting up the internal pointer. */ + wolfSSL_X509_free(peerCert); + peerCert = (WOLFSSL_X509*)&ssl->peerCert; + chain = wolfSSL_get_peer_cert_chain(ssl); + if (chain == NULL) { + WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); + return NULL; + } + storeCtx = wolfSSL_X509_STORE_CTX_new(); + if (storeCtx == NULL) { + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error"); + return NULL; + } + if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), + peerCert, chain) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); + wolfSSL_X509_STORE_CTX_free(storeCtx); + return NULL; + } + if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { + WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); + wolfSSL_X509_STORE_CTX_free(storeCtx); + return NULL; + } + wolfSSL_X509_STORE_CTX_free(storeCtx); + return chain; + } +#endif /* SESSION_CERTS && OPENSSL_EXTRA */ -#ifndef NO_HANDSHAKE_DONE_CB + WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx) + { + if (ctx == NULL) { + return NULL; + } -int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) -{ - WOLFSSL_ENTER("wolfSSL_SetHsDoneCb"); + if (ctx->x509_store_pt != NULL) + return ctx->x509_store_pt; + return &((WOLFSSL_CTX*)ctx)->x509_store; + } - if (ssl == NULL) - return BAD_FUNC_ARG; + void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store"); + if (ctx == NULL || str == NULL || ctx->cm == str->cm) { + return; + } - ssl->hsDoneCb = cb; - ssl->hsDoneCtx = user_ctx; + if (wolfSSL_CertManager_up_ref(str->cm) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_CertManager_up_ref error"); + return; + } + /* free cert manager if have one */ + if (ctx->cm != NULL) { + wolfSSL_CertManagerFree(ctx->cm); + } + ctx->cm = str->cm; + ctx->x509_store.cm = str->cm; - return WOLFSSL_SUCCESS; -} + /* free existing store if it exists */ + wolfSSL_X509_STORE_free(ctx->x509_store_pt); + ctx->x509_store.cache = str->cache; + ctx->x509_store_pt = str; /* take ownership of store and free it + with CTX free */ + ctx->cm->x509_store_p = ctx->x509_store_pt;/* CTX has ownership + and free it with CTX free*/ + } -#endif /* NO_HANDSHAKE_DONE_CB */ +#ifdef OPENSSL_ALL + int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx, + WOLFSSL_X509_STORE* str) + { + WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store"); -WOLFSSL_ABI -int wolfSSL_Cleanup(void) -{ - int ret = WOLFSSL_SUCCESS; /* Only the first error will be returned */ - int release = 0; -#if !defined(NO_SESSION_CACHE) - int i; - int j; -#endif + if (ctx == NULL || str == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } - WOLFSSL_ENTER("wolfSSL_Cleanup"); + /* NO-OP when setting existing store */ + if (str == CTX_STORE(ctx)) + return WOLFSSL_SUCCESS; -#ifndef WOLFSSL_MUTEX_INITIALIZER - if (inits_count_mutex_valid == 1) { -#endif - if (wc_LockMutex(&inits_count_mutex) != 0) { - WOLFSSL_MSG("Bad Lock Mutex count"); - return BAD_MUTEX_E; + if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); + return WOLFSSL_FAILURE; } -#ifndef WOLFSSL_MUTEX_INITIALIZER + + /* free existing store if it exists */ + wolfSSL_X509_STORE_free(ctx->x509_store_pt); + ctx->x509_store_pt = str; /* take ownership of store and free it + with CTX free */ + return WOLFSSL_SUCCESS; } #endif - if (initRefCount > 0) { - --initRefCount; - if (initRefCount == 0) - release = 1; - } + int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) + { + WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store"); -#ifndef WOLFSSL_MUTEX_INITIALIZER - if (inits_count_mutex_valid == 1) { -#endif - wc_UnLockMutex(&inits_count_mutex); -#ifndef WOLFSSL_MUTEX_INITIALIZER + if (ssl == NULL || str == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + /* NO-OP when setting existing store */ + if (str == SSL_STORE(ssl)) + return WOLFSSL_SUCCESS; + + /* free existing store if it exists */ + wolfSSL_X509_STORE_free(ssl->x509_store_pt); + if (str == ssl->ctx->x509_store_pt) + ssl->x509_store_pt = NULL; /* if setting ctx store then just revert + to using that instead */ + else + ssl->x509_store_pt = str; /* take ownership of store and free it + with SSL free */ + return WOLFSSL_SUCCESS; } -#endif - if (!release) - return ret; -#ifdef OPENSSL_EXTRA - wolfSSL_BN_free_one(); -#endif + int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) + { + WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store"); -#ifndef NO_SESSION_CACHE - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - for (i = 0; i < SESSION_ROWS; ++i) { - if ((SessionCache[i].lock_valid == 1) && - (wc_FreeRwLock(&SessionCache[i].row_lock) != 0)) { - if (ret == WOLFSSL_SUCCESS) - ret = BAD_MUTEX_E; + if (ssl == NULL || str == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } - SessionCache[i].lock_valid = 0; - } - #else - if ((session_lock_valid == 1) && (wc_FreeRwLock(&session_lock) != 0)) { - if (ret == WOLFSSL_SUCCESS) - ret = BAD_MUTEX_E; - } - session_lock_valid = 0; - #endif - for (i = 0; i < SESSION_ROWS; i++) { - for (j = 0; j < SESSIONS_PER_ROW; j++) { - #ifdef SESSION_CACHE_DYNAMIC_MEM - if (SessionCache[i].Sessions[j]) { - EvictSessionFromCache(SessionCache[i].Sessions[j]); - XFREE(SessionCache[i].Sessions[j], SessionCache[i].heap, - DYNAMIC_TYPE_SESSION); - SessionCache[i].Sessions[j] = NULL; - } - #else - EvictSessionFromCache(&SessionCache[i].Sessions[j]); - #endif + + /* NO-OP when setting existing store */ + if (str == SSL_STORE(ssl)) + return WOLFSSL_SUCCESS; + + if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); + return WOLFSSL_FAILURE; } - } - #ifndef NO_CLIENT_CACHE - #ifndef WOLFSSL_MUTEX_INITIALIZER - if ((clisession_mutex_valid == 1) && - (wc_FreeMutex(&clisession_mutex) != 0)) { - if (ret == WOLFSSL_SUCCESS) - ret = BAD_MUTEX_E; - } - clisession_mutex_valid = 0; - #endif - #endif -#endif /* !NO_SESSION_CACHE */ -#ifndef WOLFSSL_MUTEX_INITIALIZER - if ((inits_count_mutex_valid == 1) && (wc_FreeMutex(&inits_count_mutex) != 0)) { - if (ret == WOLFSSL_SUCCESS) - ret = BAD_MUTEX_E; + /* free existing store if it exists */ + wolfSSL_X509_STORE_free(ssl->x509_store_pt); + if (str == ssl->ctx->x509_store_pt) + ssl->x509_store_pt = NULL; /* if setting ctx store then just revert + to using that instead */ + else + ssl->x509_store_pt = str; /* take ownership of store and free it + with SSL free */ + return WOLFSSL_SUCCESS; } - inits_count_mutex_valid = 0; -#endif +#endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */ -#ifdef OPENSSL_EXTRA - wolfSSL_RAND_Cleanup(); -#endif +#ifdef WOLFSSL_ENCRYPTED_KEYS - if (wolfCrypt_Cleanup() != 0) { - WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); - if (ret == WOLFSSL_SUCCESS) - ret = WC_CLEANUP_E; + void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx, + void* userdata) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_default_passwd_cb_userdata"); + if (ctx) + ctx->passwd_userdata = userdata; } -#if FIPS_VERSION_GE(5,1) - if (wolfCrypt_SetPrivateKeyReadEnable_fips(0, WC_KEYTYPE_ALL) < 0) { - if (ret == WOLFSSL_SUCCESS) - ret = WC_CLEANUP_E; - } -#endif -#ifdef HAVE_GLOBAL_RNG -#ifndef WOLFSSL_MUTEX_INITIALIZER - if ((globalRNGMutex_valid == 1) && (wc_FreeMutex(&globalRNGMutex) != 0)) { - if (ret == WOLFSSL_SUCCESS) - ret = BAD_MUTEX_E; + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, wc_pem_password_cb* + cb) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_default_passwd_cb"); + if (ctx) + ctx->passwd_cb = cb; } - globalRNGMutex_valid = 0; -#endif /* !WOLFSSL_MUTEX_INITIALIZER */ - - #if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG) - wolfSSL_FIPS_drbg_free(gDrbgDefCtx); - gDrbgDefCtx = NULL; - #endif -#endif -#if defined(HAVE_EX_DATA) && \ - (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ - defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || \ - defined(WOLFSSL_WPAS_SMALL) - crypto_ex_cb_free(crypto_ex_cb_ctx_session); - crypto_ex_cb_ctx_session = NULL; -#endif - -#ifdef WOLFSSL_MEM_FAIL_COUNT - wc_MemFailCount_Free(); -#endif - - return ret; -} + wc_pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx) + { + if (ctx == NULL || ctx->passwd_cb == NULL) { + return NULL; + } -void SetupSession(WOLFSSL* ssl) -{ - WOLFSSL_SESSION* session = ssl->session; + return ctx->passwd_cb; + } - WOLFSSL_ENTER("SetupSession"); - if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { - /* Make sure the session ID is available when the user calls any - * get_session API */ - if (!session->haveAltSessionID) { - XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); - session->sessionIDSz = ssl->arrays->sessionIDSz; - } - else { - XMEMCPY(session->sessionID, session->altSessionID, ID_LEN); - session->sessionIDSz = ID_LEN; + void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx) + { + if (ctx == NULL) { + return NULL; } - } - session->side = (byte)ssl->options.side; - if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) - XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); - session->haveEMS = ssl->options.haveEMS; -#ifdef WOLFSSL_SESSION_ID_CTX - /* If using compatibility layer then check for and copy over session context - * id. */ - if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { - XMEMCPY(ssl->session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); - session->sessionCtxSz = ssl->sessionCtxSz; - } -#endif - session->timeout = ssl->timeout; -#ifndef NO_ASN_TIME - session->bornOn = LowResTimer(); -#endif -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - session->version = ssl->version; -#endif -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - session->cipherSuite0 = ssl->options.cipherSuite0; - session->cipherSuite = ssl->options.cipherSuite; -#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - session->peerVerifyRet = (byte)ssl->peerVerifyRet; -#endif - session->isSetup = 1; -} -#ifndef NO_SESSION_CACHE + return ctx->passwd_userdata; + } -WOLFSSL_ABI -void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm) -{ - /* static table now, no flushing needed */ - (void)ctx; - (void)tm; -} +#endif /* WOLFSSL_ENCRYPTED_KEYS */ -void wolfSSL_CTX_flush_sessions(WOLFSSL_CTX* ctx, long tm) -{ - int i, j; - byte id[ID_LEN]; - (void)ctx; - XMEMSET(id, 0, ID_LEN); - WOLFSSL_ENTER("wolfSSL_flush_sessions"); - for (i = 0; i < SESSION_ROWS; ++i) { - if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) { - WOLFSSL_MSG("Session cache mutex lock failed"); - return; - } - for (j = 0; j < SESSIONS_PER_ROW; j++) { -#ifdef SESSION_CACHE_DYNAMIC_MEM - WOLFSSL_SESSION* s = SessionCache[i].Sessions[j]; +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED) + unsigned long wolfSSL_ERR_get_error(void) + { + WOLFSSL_ENTER("wolfSSL_ERR_get_error"); +#ifdef WOLFSSL_HAVE_ERROR_QUEUE + return wc_GetErrorNodeErr(); #else - WOLFSSL_SESSION* s = &SessionCache[i].Sessions[j]; -#endif - if ( -#ifdef SESSION_CACHE_DYNAMIC_MEM - s != NULL && -#endif - XMEMCMP(s->sessionID, id, ID_LEN) != 0 && - s->bornOn + s->timeout < (word32)tm - ) - { - EvictSessionFromCache(s); -#ifdef SESSION_CACHE_DYNAMIC_MEM - XFREE(s, s->heap, DYNAMIC_TYPE_SESSION); - SessionCache[i].Sessions[j] = NULL; + return (unsigned long)(0 - NOT_COMPILED_IN); #endif - } - } - SESSION_ROW_UNLOCK(&SessionCache[i]); } -} - - -/* set ssl session timeout in seconds */ -WOLFSSL_ABI -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 WOLFSSL_SUCCESS; -} - +#endif -/** - * Sets ctx session timeout in seconds. - * The timeout value set here should be reflected in the - * "session ticket lifetime hint" if this API works in the openssl compat-layer. - * Therefore wolfSSL_CTX_set_TicketHint is called internally. - * Arguments: - * - ctx WOLFSSL_CTX object which the timeout is set to - * - to timeout value in second - * Returns: - * WOLFSSL_SUCCESS on success, BAD_FUNC_ARG on failure. - * When WOLFSSL_ERROR_CODE_OPENSSL is defined, returns previous timeout value - * on success, BAD_FUNC_ARG on failure. - */ -WOLFSSL_ABI -int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) -{ - #if defined(WOLFSSL_ERROR_CODE_OPENSSL) - word32 prev_timeout = 0; - #endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - int ret = WOLFSSL_SUCCESS; - (void)ret; + int wolfSSL_num_locks(void) + { + return 0; + } - if (ctx == NULL) - ret = BAD_FUNC_ARG; + void wolfSSL_set_locking_callback(mutex_cb* f) + { + WOLFSSL_ENTER("wolfSSL_set_locking_callback"); - if (ret == WOLFSSL_SUCCESS) { - #if defined(WOLFSSL_ERROR_CODE_OPENSSL) - prev_timeout = ctx->timeout; - #endif - if (to == 0) { - ctx->timeout = WOLFSSL_SESSION_TIMEOUT; - } - else { - ctx->timeout = to; - } - } -#if defined(OPENSSL_EXTRA) && defined(HAVE_SESSION_TICKET) && \ - !defined(NO_WOLFSSL_SERVER) - if (ret == WOLFSSL_SUCCESS) { - if (to == 0) { - ret = wolfSSL_CTX_set_TicketHint(ctx, SESSION_TICKET_HINT_DEFAULT); - } - else { - ret = wolfSSL_CTX_set_TicketHint(ctx, to); + if (wc_SetMutexCb(f) != 0) { + WOLFSSL_MSG("Error when setting mutex call back"); } } -#endif /* OPENSSL_EXTRA && HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER */ - -#if defined(WOLFSSL_ERROR_CODE_OPENSSL) - if (ret == WOLFSSL_SUCCESS) { - return prev_timeout; - } - else { - return ret; - } -#else - return ret; -#endif /* WOLFSSL_ERROR_CODE_OPENSSL */ -} - -#ifndef NO_CLIENT_CACHE - -/* Get Session from Client cache based on id/len, return NULL on failure */ -WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) -{ - WOLFSSL_SESSION* ret = NULL; - word32 row; - int idx; - int count; - int error = 0; - ClientSession* clSess; - - WOLFSSL_ENTER("wolfSSL_GetSessionClient"); + mutex_cb* wolfSSL_get_locking_callback(void) + { + WOLFSSL_ENTER("wolfSSL_get_locking_callback"); - if (ssl->ctx->sessionCacheOff) { - WOLFSSL_MSG("Session Cache off"); - return NULL; + return wc_GetMutexCb(); } - if (ssl->options.side == WOLFSSL_SERVER_END) - return NULL; - len = min(SERVER_ID_LEN, (word32)len); - - /* Do not access ssl->ctx->get_sess_cb from here. It is using a different - * set of ID's */ + typedef unsigned long (idCb)(void); + static idCb* inner_idCb = NULL; - row = HashObject(id, len, &error) % CLIENT_SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return NULL; + unsigned long wolfSSL_thread_id(void) + { + if (inner_idCb != NULL) { + return inner_idCb(); + } + else { + return 0; + } } - if (wc_LockMutex(&clisession_mutex) != 0) { - WOLFSSL_MSG("Client cache mutex lock failed"); - return NULL; - } - /* start from most recently used */ - count = min((word32)ClientCache[row].totalCount, CLIENT_SESSIONS_PER_ROW); - idx = ClientCache[row].nextIdx - 1; - if (idx < 0 || idx >= CLIENT_SESSIONS_PER_ROW) { - idx = CLIENT_SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ + void wolfSSL_set_id_callback(unsigned long (*f)(void)) + { + inner_idCb = f; } - clSess = ClientCache[row].Clients; - for (; count > 0; --count) { - WOLFSSL_SESSION* current; - SessionRow* sessRow; +#ifdef WOLFSSL_HAVE_ERROR_QUEUE +#ifndef NO_BIO + /* print out and clear all errors */ + void wolfSSL_ERR_print_errors(WOLFSSL_BIO* bio) + { + const char* file = NULL; + const char* reason = NULL; + int ret; + int line = 0; + char buf[WOLFSSL_MAX_ERROR_SZ * 2]; - if (clSess[idx].serverRow >= SESSION_ROWS) { - WOLFSSL_MSG("Client cache serverRow invalid"); - break; - } + WOLFSSL_ENTER("wolfSSL_ERR_print_errors"); - /* lock row */ - sessRow = &SessionCache[clSess[idx].serverRow]; - if (SESSION_ROW_RD_LOCK(sessRow) != 0) { - WOLFSSL_MSG("Session cache row lock failure"); - break; + if (bio == NULL) { + WOLFSSL_MSG("BIO passed in was null"); + return; } -#ifdef SESSION_CACHE_DYNAMIC_MEM - current = sessRow->Sessions[clSess[idx].serverIdx]; -#else - current = &sessRow->Sessions[clSess[idx].serverIdx]; -#endif - if (current && XMEMCMP(current->serverID, id, len) == 0) { - WOLFSSL_MSG("Found a serverid match for client"); - if (LowResTimer() < (current->bornOn + current->timeout)) { - WOLFSSL_MSG("Session valid"); - ret = current; - SESSION_ROW_UNLOCK(sessRow); - break; - } else { - WOLFSSL_MSG("Session timed out"); /* could have more for id */ + do { + ret = wc_PeekErrorNode(0, &file, &reason, &line); + if (ret >= 0) { + const char* r = wolfSSL_ERR_reason_error_string(0 - ret); + if (XSNPRINTF(buf, sizeof(buf), + "error:%d:wolfSSL library:%s:%s:%d\n", + ret, r, file, line) + >= (int)sizeof(buf)) + { + WOLFSSL_MSG("Buffer overrun formatting error message"); } - } else { - WOLFSSL_MSG("ServerID not a match from client table"); + wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)); + wc_RemoveErrorNode(0); + } + } while (ret >= 0); + if (wolfSSL_BIO_write(bio, "", 1) != 1) { + WOLFSSL_MSG("Issue writing final string terminator"); } - SESSION_ROW_UNLOCK(sessRow); - - idx = idx > 0 ? idx - 1 : CLIENT_SESSIONS_PER_ROW - 1; } +#endif /* !NO_BIO */ +#endif /* WOLFSSL_HAVE_ERROR_QUEUE */ - wc_UnLockMutex(&clisession_mutex); - - return ret; -} - -#endif /* !NO_CLIENT_CACHE */ - -static int SslSessionCacheOff(const WOLFSSL* ssl, const WOLFSSL_SESSION* session) -{ - (void)session; - return ssl->options.sessionCacheOff - #if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_FORCE_CACHE_ON_TICKET) - && session->ticketLen == 0 - #endif - ; -} +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ - defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) -/** - * SessionTicketNoncePrealloc() - prealloc a buffer for ticket nonces - * @output: [in] pointer to WOLFSSL_SESSION object that will soon be a - * destination of a session duplication - * @buf: [out] address of the preallocated buf - * @len: [out] len of the preallocated buf - * - * prealloc a buffer that will likely suffice to contain a ticket nonce. It's - * used when copying session under lock, when syscalls need to be avoided. If - * output already has a dynamic buffer, it's reused. +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_SECRET_CALLBACK) +#if !defined(NO_WOLFSSL_SERVER) +/* 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 */ -static int SessionTicketNoncePrealloc(byte** buf, byte* len, void *heap) +size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, + size_t outSz) { - (void)heap; + size_t size; - *buf = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_NONCE_LEN, heap, - DYNAMIC_TYPE_SESSION_TICK); - if (*buf == NULL) { - WOLFSSL_MSG("Failed to preallocate ticket nonce buffer"); - *len = 0; - return 1; + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; } - *len = PREALLOC_SESSION_TICKET_NONCE_LEN; - return 0; -} -#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 */ - -static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input, - WOLFSSL_SESSION* output, int avoidSysCalls, byte* ticketNonceBuf, - byte* ticketNonceLen, byte* preallocUsed); + if (ssl == NULL || out == NULL) { + return 0; + } -void TlsSessionCacheUnlockRow(word32 row) -{ - SessionRow* sessRow; + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } - sessRow = &SessionCache[row]; - (void)sessRow; - SESSION_ROW_UNLOCK(sessRow); -} - -/* Don't use this function directly. Use TlsSessionCacheGetAndRdLock and - * TlsSessionCacheGetAndWrLock to fully utilize compiler const support. */ -static int TlsSessionCacheGetAndLock(const byte *id, - const WOLFSSL_SESSION **sess, word32 *lockedRow, byte readOnly, byte side) -{ - SessionRow *sessRow; - const WOLFSSL_SESSION *s; - word32 row; - int count; - int error; - int idx; - - *sess = NULL; - row = HashObject(id, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) - return error; - sessRow = &SessionCache[row]; - if (readOnly) - error = SESSION_ROW_RD_LOCK(sessRow); - else - error = SESSION_ROW_WR_LOCK(sessRow); - if (error != 0) - return FATAL_ERROR; - - /* start from most recently used */ - count = min((word32)sessRow->totalCount, SESSIONS_PER_ROW); - idx = sessRow->nextIdx - 1; - if (idx < 0 || idx >= SESSIONS_PER_ROW) { - idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ - } - for (; count > 0; --count) { -#ifdef SESSION_CACHE_DYNAMIC_MEM - s = sessRow->Sessions[idx]; -#else - s = &sessRow->Sessions[idx]; -#endif - if (s && XMEMCMP(s->sessionID, id, ID_LEN) == 0 && s->side == side) { - *sess = s; - break; - } - idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; - } - if (*sess == NULL) { - SESSION_ROW_UNLOCK(sessRow); + if (outSz > RAN_LEN) { + size = RAN_LEN; } else { - *lockedRow = row; + size = outSz; } - return 0; + XMEMCPY(out, ssl->arrays->serverRandom, size); + return size; } +#endif /* !NO_WOLFSSL_SERVER */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ -static int CheckSessionMatch(const WOLFSSL* ssl, const WOLFSSL_SESSION* sess) -{ - if (ssl == NULL || sess == NULL) - return 0; #ifdef OPENSSL_EXTRA - if (ssl->sessionCtxSz > 0 && (ssl->sessionCtxSz != sess->sessionCtxSz || - XMEMCMP(ssl->sessionCtx, sess->sessionCtx, sess->sessionCtxSz) != 0)) - return 0; -#endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - if (IsAtLeastTLSv1_3(ssl->version) != IsAtLeastTLSv1_3(sess->version)) - return 0; -#endif - return 1; -} - -int TlsSessionCacheGetAndRdLock(const byte *id, const WOLFSSL_SESSION **sess, - word32 *lockedRow, byte side) -{ - return TlsSessionCacheGetAndLock(id, sess, lockedRow, 1, side); -} - -int TlsSessionCacheGetAndWrLock(const byte *id, WOLFSSL_SESSION **sess, - word32 *lockedRow, byte side) -{ - return TlsSessionCacheGetAndLock(id, (const WOLFSSL_SESSION**)sess, - lockedRow, 0, side); -} - -int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) +#if !defined(NO_WOLFSSL_SERVER) +/* Used to get the peer ephemeral public key sent during the connection + * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called + * before the ephemeral key is stored. + * return WOLFSSL_SUCCESS on success */ +int wolfSSL_get_peer_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey) { - const WOLFSSL_SESSION* sess = NULL; - const byte* id = NULL; - word32 row; - int error = 0; -#ifdef HAVE_SESSION_TICKET -#ifndef WOLFSSL_SMALL_STACK - byte tmpTicket[PREALLOC_SESSION_TICKET_LEN]; -#else - byte* tmpTicket = NULL; -#endif -#ifdef WOLFSSL_TLS13 - byte *preallocNonce = NULL; - byte preallocNonceLen = 0; - byte preallocNonceUsed = 0; -#endif /* WOLFSSL_TLS13 */ - byte tmpBufSet = 0; -#endif -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - WOLFSSL_X509* peer = NULL; -#endif - byte bogusID[ID_LEN]; - byte bogusIDSz = 0; + WOLFSSL_EVP_PKEY* ret = NULL; - WOLFSSL_ENTER("wolfSSL_GetSessionFromCache"); + WOLFSSL_ENTER("wolfSSL_get_server_tmp_key"); - if (output == NULL) { - WOLFSSL_MSG("NULL output"); + if (ssl == NULL || pkey == NULL) { + WOLFSSL_MSG("Bad argument passed in"); return WOLFSSL_FAILURE; } - if (SslSessionCacheOff(ssl, ssl->session)) - return WOLFSSL_FAILURE; - - if (ssl->options.haveSessionId == 0 && !ssl->session->haveAltSessionID) - return WOLFSSL_FAILURE; - -#ifdef HAVE_SESSION_TICKET - if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) - return WOLFSSL_FAILURE; -#endif +#ifdef HAVE_ECC + if (ssl->peerEccKey != NULL) { + unsigned char* der; + const unsigned char* pt; + unsigned int derSz = 0; + int sz; - XMEMSET(bogusID, 0, sizeof(bogusID)); - if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL - && !ssl->session->haveAltSessionID) - id = ssl->arrays->sessionID; - else if (ssl->session->haveAltSessionID) { - id = ssl->session->altSessionID; - /* We want to restore the bogus ID for TLS compatibility */ - if (output == ssl->session) { - XMEMCPY(bogusID, ssl->session->sessionID, ID_LEN); - bogusIDSz = ssl->session->sessionIDSz; + PRIVATE_KEY_UNLOCK(); + if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("get ecc der size failed"); + PRIVATE_KEY_LOCK(); + return WOLFSSL_FAILURE; } - } - else - id = ssl->session->sessionID; - - -#ifdef HAVE_EXT_CACHE - if (ssl->ctx->get_sess_cb != NULL) { - int copy = 0; - int found = 0; - WOLFSSL_SESSION* extSess; - /* Attempt to retrieve the session from the external cache. */ - WOLFSSL_MSG("Calling external session cache"); - extSess = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); - if ((extSess != NULL) - && CheckSessionMatch(ssl, extSess) - ) { - WOLFSSL_MSG("Session found in external cache"); - found = 1; + PRIVATE_KEY_LOCK(); - error = wolfSSL_DupSession(extSess, output, 0); -#ifdef HAVE_EX_DATA - extSess->ownExData = 1; - output->ownExData = 0; -#endif - /* We want to restore the bogus ID for TLS compatibility */ - if (ssl->session->haveAltSessionID && - output == ssl->session) { - XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); - ssl->session->sessionIDSz = bogusIDSz; - } + derSz += MAX_SEQ_SZ + (2 * MAX_ALGO_SZ) + MAX_SEQ_SZ + TRAILING_ZERO; + der = (unsigned char*)XMALLOC(derSz, ssl->heap, DYNAMIC_TYPE_KEY); + if (der == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; } - /* If copy not set then free immediately */ - if (extSess != NULL && !copy) - wolfSSL_FreeSession(ssl->ctx, extSess); - if (found) - return error; - WOLFSSL_MSG("Session not found in external cache"); - } - - if (ssl->options.internalCacheLookupOff) { - WOLFSSL_MSG("Internal cache lookup turned off"); - return WOLFSSL_FAILURE; - } -#endif -#ifdef HAVE_SESSION_TICKET - if (output->ticket == NULL || - output->ticketLenAlloc < PREALLOC_SESSION_TICKET_LEN) { -#ifdef WOLFSSL_SMALL_STACK - tmpTicket = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_LEN, output->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (tmpTicket == NULL) { - WOLFSSL_MSG("tmpTicket malloc failed"); + if ((sz = wc_EccPublicKeyToDer(ssl->peerEccKey, der, derSz, 1)) <= 0) { + WOLFSSL_MSG("get ecc der failed"); + XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); return WOLFSSL_FAILURE; } -#endif - if (output->ticketLenAlloc) - XFREE(output->ticket, output->heap, DYNAMIC_TYPE_SESSION_TICK); - output->ticket = tmpTicket; /* cppcheck-suppress autoVariables - */ - output->ticketLenAlloc = PREALLOC_SESSION_TICKET_LEN; - output->ticketLen = 0; - tmpBufSet = 1; - } -#endif - -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (output->peer != NULL) { - wolfSSL_X509_free(output->peer); - output->peer = NULL; + pt = der; /* in case pointer gets advanced */ + ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz); + XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); } #endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \ - defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (output->ticketNonce.data != output->ticketNonce.dataStatic) { - XFREE(output->ticketNonce.data, output->heap, - DYNAMIC_TYPE_SESSION_TICK); - output->ticketNonce.data = output->ticketNonce.dataStatic; - output->ticketNonce.len = 0; - } - error = SessionTicketNoncePrealloc(&preallocNonce, &preallocNonceLen, - output->heap); - if (error != 0) { - if (tmpBufSet) { - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - } -#ifdef WOLFSSL_SMALL_STACK - if (tmpTicket != NULL) - XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); + *pkey = ret; +#ifdef HAVE_ECC + if (ret != NULL) + return WOLFSSL_SUCCESS; + else #endif return WOLFSSL_FAILURE; - } -#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET*/ - - /* init to avoid clang static analyzer false positive */ - row = 0; - error = TlsSessionCacheGetAndRdLock(id, &sess, &row, (byte)ssl->options.side); - error = (error == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; - if (error != WOLFSSL_SUCCESS || sess == NULL) { - WOLFSSL_MSG("Get Session from cache failed"); - error = WOLFSSL_FAILURE; -#ifdef HAVE_SESSION_TICKET - if (tmpBufSet) { - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - } -#ifdef WOLFSSL_TLS13 - if (preallocNonce != NULL) { - XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK); - preallocNonce = NULL; - } -#endif /* WOLFSSL_TLS13 */ -#ifdef WOLFSSL_SMALL_STACK - if (tmpTicket != NULL) { - XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); - tmpTicket = NULL; - } -#endif -#endif - } - else { - if (!CheckSessionMatch(ssl, sess)) { - WOLFSSL_MSG("Invalid session: can't be used in this context"); - TlsSessionCacheUnlockRow(row); - error = WOLFSSL_FAILURE; - } - else if (LowResTimer() >= (sess->bornOn + sess->timeout)) { - WOLFSSL_SESSION* wrSess = NULL; - WOLFSSL_MSG("Invalid session: timed out"); - sess = NULL; - TlsSessionCacheUnlockRow(row); - /* Attempt to get a write lock */ - error = TlsSessionCacheGetAndWrLock(id, &wrSess, &row, - (byte)ssl->options.side); - if (error == 0 && wrSess != NULL) { - EvictSessionFromCache(wrSess); - TlsSessionCacheUnlockRow(row); - } - error = WOLFSSL_FAILURE; - } - } - - /* mollify confused cppcheck nullPointer warning. */ - if (sess == NULL) - error = WOLFSSL_FAILURE; - - if (error == WOLFSSL_SUCCESS) { -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) - error = wolfSSL_DupSessionEx(sess, output, 1, - preallocNonce, &preallocNonceLen, &preallocNonceUsed); -#else - error = wolfSSL_DupSession(sess, output, 1); -#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 */ -#ifdef HAVE_EX_DATA - output->ownExData = !sess->ownExData; /* Session may own ex_data */ -#endif - TlsSessionCacheUnlockRow(row); - } - - /* We want to restore the bogus ID for TLS compatibility */ - if (ssl->session->haveAltSessionID && - output == ssl->session) { - XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); - ssl->session->sessionIDSz = bogusIDSz; - } - -#ifdef HAVE_SESSION_TICKET - if (tmpBufSet) { - if (error == WOLFSSL_SUCCESS) { - if (output->ticketLen > SESSION_TICKET_LEN) { - output->ticket = (byte*)XMALLOC(output->ticketLen, output->heap, - DYNAMIC_TYPE_SESSION_TICK); - if (output->ticket == NULL) { - error = WOLFSSL_FAILURE; - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - output->ticketLen = 0; - } - } - else { - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - } - } - else { - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - output->ticketLen = 0; - } - if (error == WOLFSSL_SUCCESS) { - XMEMCPY(output->ticket, tmpTicket, output->ticketLen); - } - } -#ifdef WOLFSSL_SMALL_STACK - if (tmpTicket != NULL) - XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (error == WOLFSSL_SUCCESS && preallocNonceUsed) { - if (preallocNonceLen < PREALLOC_SESSION_TICKET_NONCE_LEN) { - /* buffer bigger than needed */ -#ifndef XREALLOC - output->ticketNonce.data = (byte*)XMALLOC(preallocNonceLen, - output->heap, DYNAMIC_TYPE_SESSION_TICK); - if (output->ticketNonce.data != NULL) - XMEMCPY(output->ticketNonce.data, preallocNonce, - preallocNonceLen); - XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK); - preallocNonce = NULL; -#else - output->ticketNonce.data = XREALLOC(preallocNonce, - preallocNonceLen, output->heap, DYNAMIC_TYPE_SESSION_TICK); - if (output->ticketNonce.data != NULL) { - /* don't free the reallocated pointer */ - preallocNonce = NULL; - } -#endif /* !XREALLOC */ - if (output->ticketNonce.data == NULL) { - output->ticketNonce.data = output->ticketNonce.dataStatic; - output->ticketNonce.len = 0; - error = WOLFSSL_FAILURE; - /* preallocNonce will be free'd after the if */ - } - } - else { - output->ticketNonce.data = preallocNonce; - output->ticketNonce.len = preallocNonceLen; - preallocNonce = NULL; - } - } - if (preallocNonce != NULL) - XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK); -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ - -#endif - -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (peer != NULL) { - wolfSSL_X509_free(peer); - } -#endif - - return error; } -WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, - byte restoreSessionCerts) +#endif /* !NO_WOLFSSL_SERVER */ + +/** + * This function checks if any compiled in protocol versions are + * left enabled after calls to set_min or set_max API. + * @param major The SSL/TLS major version + * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no + * protocol versions are left enabled. + */ +static int CheckSslMethodVersion(byte major, unsigned long options) { - WOLFSSL_SESSION* ret = NULL; + int sanityConfirmed = 0; - (void)restoreSessionCerts; /* Kept for compatibility */ + (void)options; - if (wolfSSL_GetSessionFromCache(ssl, ssl->session) == WOLFSSL_SUCCESS) { - ret = ssl->session; + switch (major) { + #ifndef NO_TLS + case SSLv3_MAJOR: + #ifdef WOLFSSL_ALLOW_SSLV3 + if (!(options & WOLFSSL_OP_NO_SSLv3)) { + sanityConfirmed = 1; + } + #endif + #ifndef NO_OLD_TLS + if (!(options & WOLFSSL_OP_NO_TLSv1)) + sanityConfirmed = 1; + if (!(options & WOLFSSL_OP_NO_TLSv1_1)) + sanityConfirmed = 1; + #endif + #ifndef WOLFSSL_NO_TLS12 + if (!(options & WOLFSSL_OP_NO_TLSv1_2)) + sanityConfirmed = 1; + #endif + #ifdef WOLFSSL_TLS13 + if (!(options & WOLFSSL_OP_NO_TLSv1_3)) + sanityConfirmed = 1; + #endif + break; + #endif + #ifdef WOLFSSL_DTLS + case DTLS_MAJOR: + sanityConfirmed = 1; + break; + #endif + default: + WOLFSSL_MSG("Invalid major version"); + return WOLFSSL_FAILURE; } - else { - WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session"); + if (!sanityConfirmed) { + WOLFSSL_MSG("All compiled in TLS versions disabled"); + return WOLFSSL_FAILURE; } - - if (ret != NULL && masterSecret != NULL) - XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN); - - return ret; + return WOLFSSL_SUCCESS; } -int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) -{ - SessionRow* sessRow = NULL; - int ret = WOLFSSL_SUCCESS; +/** + * protoVerTbl holds (D)TLS version numbers in ascending order. + * Except DTLS versions, the newer version is located in the latter part of + * the table. This table is referred by wolfSSL_CTX_set_min_proto_version and + * wolfSSL_CTX_set_max_proto_version. + */ +static const int protoVerTbl[] = { + SSL3_VERSION, + TLS1_VERSION, + TLS1_1_VERSION, + TLS1_2_VERSION, + TLS1_3_VERSION, + DTLS1_VERSION, + DTLS1_2_VERSION +}; +/* number of protocol versions listed in protoVerTbl */ +#define NUMBER_OF_PROTOCOLS (sizeof(protoVerTbl)/sizeof(int)) - session = ClientSessionToSession(session); +/** + * wolfSSL_CTX_set_min_proto_version attempts to set the minimum protocol + * version to use by SSL objects created from this WOLFSSL_CTX. + * This API guarantees that a version of SSL/TLS lower than specified + * here will not be allowed. If the version specified is not compiled in + * then this API sets the lowest compiled in protocol version. + * This API also accept 0 as version, to set the minimum version automatically. + * CheckSslMethodVersion() is called to check if any remaining protocol versions + * are enabled. + * @param ctx The wolfSSL CONTEXT factory for spawning SSL/TLS objects + * @param version Any of the following + * * 0 + * * SSL3_VERSION + * * TLS1_VERSION + * * TLS1_1_VERSION + * * TLS1_2_VERSION + * * TLS1_3_VERSION + * * DTLS1_VERSION + * * DTLS1_2_VERSION + * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no + * protocol versions are left enabled. + */ +static int Set_CTX_min_proto_version(WOLFSSL_CTX* ctx, int version) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version_ex"); - if (ssl == NULL || session == NULL || !session->isSetup) { - WOLFSSL_MSG("ssl or session NULL or not set up"); + if (ctx == NULL) { return WOLFSSL_FAILURE; } - /* We need to lock the session as the first step if its in the cache */ - if (session->type == WOLFSSL_SESSION_TYPE_CACHE) { - if (session->cacheRow < SESSION_ROWS) { - sessRow = &SessionCache[session->cacheRow]; - if (SESSION_ROW_RD_LOCK(sessRow) != 0) { - WOLFSSL_MSG("Session row lock failed"); - return WOLFSSL_FAILURE; - } - } - } - - if (ret == WOLFSSL_SUCCESS && ssl->options.side != WOLFSSL_NEITHER_END && - (byte)ssl->options.side != session->side) { - WOLFSSL_MSG("Setting session for wrong role"); - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - if (ssl->session == session) { - WOLFSSL_MSG("ssl->session and session same"); - } - else if (session->type != WOLFSSL_SESSION_TYPE_CACHE) { - if (wolfSSL_SESSION_up_ref(session) == WOLFSSL_SUCCESS) { - wolfSSL_FreeSession(ssl->ctx, ssl->session); - ssl->session = session; - } - else - ret = WOLFSSL_FAILURE; - } - else { - ret = wolfSSL_DupSession(session, ssl->session, 0); - if (ret != WOLFSSL_SUCCESS) - WOLFSSL_MSG("Session duplicate failed"); - } - } - - /* Let's copy over the altSessionID for local cache purposes */ - if (ret == WOLFSSL_SUCCESS && session->haveAltSessionID && - ssl->session != session) { - ssl->session->haveAltSessionID = 1; - XMEMCPY(ssl->session->altSessionID, session->altSessionID, ID_LEN); - } - - if (sessRow != NULL) { - SESSION_ROW_UNLOCK(sessRow); - sessRow = NULL; - } - - /* Note: the `session` variable cannot be used below, since the row is - * un-locked */ - - if (ret != WOLFSSL_SUCCESS) - return ret; - -#ifdef WOLFSSL_SESSION_ID_CTX - /* check for application context id */ - if (ssl->sessionCtxSz > 0) { - if (XMEMCMP(ssl->sessionCtx, ssl->session->sessionCtx, ssl->sessionCtxSz)) { - /* context id did not match! */ - WOLFSSL_MSG("Session context did not match"); - return WOLFSSL_FAILURE; - } - } -#endif /* WOLFSSL_SESSION_ID_CTX */ - - if (LowResTimer() >= (ssl->session->bornOn + ssl->session->timeout)) { -#if !defined(OPENSSL_EXTRA) || !defined(WOLFSSL_ERROR_CODE_OPENSSL) - return WOLFSSL_FAILURE; /* session timed out */ -#else /* defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) */ - WOLFSSL_MSG("Session is expired but return success for " - "OpenSSL compatibility"); + switch (version) { +#ifndef NO_TLS + case SSL3_VERSION: +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + ctx->minDowngrade = SSLv3_MINOR; + break; #endif + case TLS1_VERSION: + #ifdef WOLFSSL_ALLOW_TLSV10 + ctx->minDowngrade = TLSv1_MINOR; + break; + #endif + case TLS1_1_VERSION: + #ifndef NO_OLD_TLS + ctx->minDowngrade = TLSv1_1_MINOR; + break; + #endif + case TLS1_2_VERSION: + #ifndef WOLFSSL_NO_TLS12 + ctx->minDowngrade = TLSv1_2_MINOR; + break; + #endif + case TLS1_3_VERSION: + #ifdef WOLFSSL_TLS13 + ctx->minDowngrade = TLSv1_3_MINOR; + break; + #endif +#endif +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + #ifndef NO_OLD_TLS + ctx->minDowngrade = DTLS_MINOR; + break; + #endif + case DTLS1_2_VERSION: + ctx->minDowngrade = DTLSv1_2_MINOR; + break; +#endif + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; } - ssl->options.resuming = 1; - ssl->options.haveEMS = ssl->session->haveEMS; -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - ssl->version = ssl->session->version; - if (IsAtLeastTLSv1_3(ssl->version)) - ssl->options.tls1_3 = 1; -#endif -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - ssl->options.cipherSuite0 = ssl->session->cipherSuite0; - ssl->options.cipherSuite = ssl->session->cipherSuite; + switch (version) { +#ifndef NO_TLS + case TLS1_3_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2); + FALL_THROUGH; + case TLS1_2_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_1); + FALL_THROUGH; + case TLS1_1_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1); + FALL_THROUGH; + case TLS1_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_SSLv3); + break; + case SSL3_VERSION: + case SSL2_VERSION: + /* Nothing to do here */ + break; #endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - ssl->peerVerifyRet = (unsigned long)ssl->session->peerVerifyRet; +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + case DTLS1_2_VERSION: + break; #endif + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; + } - return WOLFSSL_SUCCESS; + return CheckSslMethodVersion(ctx->method->version.major, ctx->mask); } - -#ifdef WOLFSSL_SESSION_STATS -static int get_locked_session_stats(word32* active, word32* total, - word32* peak); -#endif - -#ifndef NO_CLIENT_CACHE -ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverID, - word16 idLen, const byte* sessionID, - word16 useTicket) +/* Sets the min protocol version allowed with WOLFSSL_CTX + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) { - int error = -1; - word32 clientRow = 0, clientIdx = 0; - ClientSession* ret = NULL; - - (void)useTicket; - if (side == WOLFSSL_CLIENT_END - && row != INVALID_SESSION_ROW - && (idLen -#ifdef HAVE_SESSION_TICKET - || useTicket == 1 -#endif - || serverID != NULL - )) { + int ret; + int proto = 0; + int maxProto = 0; + int i; + int idx = 0; - WOLFSSL_MSG("Trying to add client cache entry"); + WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version"); - if (idLen) { - clientRow = HashObject(serverID, - idLen, &error) % CLIENT_SESSION_ROWS; - } - else if (serverID != NULL) { - clientRow = HashObject(sessionID, - ID_LEN, &error) % CLIENT_SESSION_ROWS; - } - else { - error = -1; - } - if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { - clientIdx = ClientCache[clientRow].nextIdx; - if (clientIdx < CLIENT_SESSIONS_PER_ROW) { - ClientCache[clientRow].Clients[clientIdx].serverRow = - (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = - (word16)idx; - if (sessionID != NULL) { - word32 sessionIDHash = HashObject(sessionID, ID_LEN, - &error); - if (error == 0) { - ClientCache[clientRow].Clients[clientIdx].sessionIDHash - = sessionIDHash; - } - } - } - else { - error = -1; - ClientCache[clientRow].nextIdx = 0; /* reset index as safety */ - WOLFSSL_MSG("Invalid client cache index! " - "Possible corrupted memory"); + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + if (version != 0) { + proto = version; + ctx->minProto = 0; /* turn min proto flag off */ + for (i = 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) { + if (protoVerTbl[i] == version) { + break; } - if (error == 0) { - WOLFSSL_MSG("Adding client cache entry"); - - ret = &ClientCache[clientRow].Clients[clientIdx]; - - if (ClientCache[clientRow].totalCount < CLIENT_SESSIONS_PER_ROW) - ClientCache[clientRow].totalCount++; - ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].nextIdx %= CLIENT_SESSIONS_PER_ROW; + } + } + else { + /* when 0 is specified as version, try to find out the min version */ + for (i = 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) { + ret = Set_CTX_min_proto_version(ctx, protoVerTbl[i]); + if (ret == WOLFSSL_SUCCESS) { + proto = protoVerTbl[i]; + ctx->minProto = 1; /* turn min proto flag on */ + break; } - - wc_UnLockMutex(&clisession_mutex); } - else { - WOLFSSL_MSG("Hash session or lock failed"); + } + + /* check case where max > min , if so then clear the NO_* options + * i is the index into the table for proto version used, see if the max + * proto version index found is smaller */ + maxProto = wolfSSL_CTX_get_max_proto_version(ctx); + for (idx = 0; (unsigned)idx < NUMBER_OF_PROTOCOLS; idx++) { + if (protoVerTbl[idx] == maxProto) { + break; } } - else { - WOLFSSL_MSG("Skipping client cache"); + if (idx < i) { + wolfSSL_CTX_clear_options(ctx, WOLFSSL_OP_NO_TLSv1 | + WOLFSSL_OP_NO_TLSv1_1 | WOLFSSL_OP_NO_TLSv1_2 | + WOLFSSL_OP_NO_TLSv1_3); } + ret = Set_CTX_min_proto_version(ctx, proto); return ret; } -#endif /* !NO_CLIENT_CACHE */ /** - * For backwards compatibility, this API needs to be used in *ALL* functions - * that access the WOLFSSL_SESSION members directly. - * - * This API checks if the passed in session is actually a ClientSession object - * and returns the matching session cache object. Otherwise just return the - * input. ClientSession objects only occur in the ClientCache. They are not - * allocated anywhere else. + * wolfSSL_CTX_set_max_proto_version attempts to set the maximum protocol + * version to use by SSL objects created from this WOLFSSL_CTX. + * This API guarantees that a version of SSL/TLS higher than specified + * here will not be allowed. If the version specified is not compiled in + * then this API sets the highest compiled in protocol version. + * This API also accept 0 as version, to set the maximum version automatically. + * CheckSslMethodVersion() is called to check if any remaining protocol versions + * are enabled. + * @param ctx The wolfSSL CONTEXT factory for spawning SSL/TLS objects + * @param ver Any of the following + * * 0 + * * SSL3_VERSION + * * TLS1_VERSION + * * TLS1_1_VERSION + * * TLS1_2_VERSION + * * TLS1_3_VERSION + * * DTLS1_VERSION + * * DTLS1_2_VERSION + * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no + * protocol versions are left enabled. */ -WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) -{ - WOLFSSL_ENTER("ClientSessionToSession"); -#ifdef NO_SESSION_CACHE_REF - return (WOLFSSL_SESSION*)session; -#else -#ifndef NO_CLIENT_CACHE - if (session == NULL) - return NULL; - /* Check if session points into ClientCache */ - if ((byte*)session >= (byte*)ClientCache && - /* Cast to byte* to make pointer arithmetic work per byte */ - (byte*)session < ((byte*)ClientCache) + sizeof(ClientCache)) { - ClientSession* clientSession = (ClientSession*)session; - SessionRow* sessRow = NULL; - WOLFSSL_SESSION* cacheSession = NULL; - word32 sessionIDHash = 0; - int error = 0; - session = NULL; /* Default to NULL for failure case */ - if (wc_LockMutex(&clisession_mutex) != 0) { - WOLFSSL_MSG("Client cache mutex lock failed"); - return NULL; - } - if (clientSession->serverRow >= SESSION_ROWS || - clientSession->serverIdx >= SESSIONS_PER_ROW) { - WOLFSSL_MSG("Client cache serverRow or serverIdx invalid"); - error = -1; - } - /* Prevent memory access before clientSession->serverRow and - * clientSession->serverIdx are sanitized. */ - XFENCE(); - if (error == 0) { - /* Lock row */ - sessRow = &SessionCache[clientSession->serverRow]; - error = SESSION_ROW_RD_LOCK(sessRow); - if (error != 0) { - WOLFSSL_MSG("Session cache row lock failure"); - sessRow = NULL; - } - } - if (error == 0) { -#ifdef SESSION_CACHE_DYNAMIC_MEM - cacheSession = sessRow->Sessions[clientSession->serverIdx]; -#else - cacheSession = &sessRow->Sessions[clientSession->serverIdx]; -#endif - if (cacheSession && cacheSession->sessionIDSz == 0) { - cacheSession = NULL; - WOLFSSL_MSG("Session cache entry not set"); - error = -1; - } - } - if (error == 0) { - /* Calculate the hash of the session ID */ - sessionIDHash = HashObject(cacheSession->sessionID, ID_LEN, - &error); - } - if (error == 0) { - /* Check the session ID hash matches */ - error = clientSession->sessionIDHash != sessionIDHash; - if (error != 0) - WOLFSSL_MSG("session ID hash don't match"); - } - if (error == 0) { - /* Hashes match */ - session = cacheSession; - WOLFSSL_MSG("Found session cache matching client session object"); - } - if (sessRow != NULL) { - SESSION_ROW_UNLOCK(sessRow); - } - wc_UnLockMutex(&clisession_mutex); - return (WOLFSSL_SESSION*)session; - } - else { - /* Plain WOLFSSL_SESSION object */ - return (WOLFSSL_SESSION*)session; - } -#else - return (WOLFSSL_SESSION*)session; -#endif -#endif -} - -int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession, - const byte* id, byte idSz, int* sessionIndex, int side, - word16 useTicket, ClientSession** clientCacheEntry) +static int Set_CTX_max_proto_version(WOLFSSL_CTX* ctx, int ver) { - WOLFSSL_SESSION* cacheSession = NULL; - SessionRow* sessRow = NULL; - word32 idx = 0; -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - WOLFSSL_X509* cachePeer = NULL; - WOLFSSL_X509* addPeer = NULL; -#endif -#ifdef HAVE_SESSION_TICKET - byte* cacheTicBuff = NULL; - byte ticBuffUsed = 0; - byte* ticBuff = NULL; - int ticLen = 0; -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - byte *preallocNonce = NULL; - byte preallocNonceLen = 0; - byte preallocNonceUsed = 0; - byte *toFree = NULL; -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC */ -#endif /* HAVE_SESSION_TICKET */ - int ret = 0; - int row; - int i; - int overwrite = 0; - (void)ctx; - (void)sessionIndex; - (void)useTicket; - (void)clientCacheEntry; - - WOLFSSL_ENTER("AddSessionToCache"); - - if (idSz == 0) { - WOLFSSL_MSG("AddSessionToCache idSz == 0"); - return BAD_FUNC_ARG; - } + int ret; + WOLFSSL_ENTER("Set_CTX_max_proto_version"); - addSession = ClientSessionToSession(addSession); - if (addSession == NULL) { - WOLFSSL_MSG("AddSessionToCache is NULL"); - return MEMORY_E; + if (!ctx || !ctx->method) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } -#ifdef HAVE_SESSION_TICKET - ticLen = addSession->ticketLen; - /* Alloc Memory here to avoid syscalls during lock */ - if (ticLen > SESSION_TICKET_LEN) { - ticBuff = (byte*)XMALLOC(ticLen, NULL, - DYNAMIC_TYPE_SESSION_TICK); - if (ticBuff == NULL) { - return MEMORY_E; - } - } -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (addSession->ticketNonce.data != addSession->ticketNonce.dataStatic) { - /* use the AddSession->heap even if the buffer maybe saved in - * CachedSession objects. CachedSession heap and AddSession heap should - * be the same */ - preallocNonce = (byte*)XMALLOC(addSession->ticketNonce.len, - addSession->heap, DYNAMIC_TYPE_SESSION_TICK); - if (preallocNonce == NULL) { - if (ticBuff != NULL) - XFREE(ticBuff, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); - return MEMORY_E; - } - preallocNonceLen = addSession->ticketNonce.len; + switch (ver) { + case SSL2_VERSION: + WOLFSSL_MSG("wolfSSL does not support SSLv2"); + return WOLFSSL_FAILURE; +#ifndef NO_TLS + case SSL3_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1); + FALL_THROUGH; + case TLS1_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_1); + FALL_THROUGH; + case TLS1_1_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2); + FALL_THROUGH; + case TLS1_2_VERSION: + wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_3); + FALL_THROUGH; + case TLS1_3_VERSION: + /* Nothing to do here */ + break; +#endif +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + case DTLS1_2_VERSION: + break; +#endif + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; } -#endif /* WOLFSSL_TLS13 && WOLFSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3) */ -#endif /* HAVE_SESSION_TICKET */ - /* Find a position for the new session in cache and use that */ - /* Use the session object in the cache for external cache if required */ - row = (int)(HashObject(id, ID_LEN, &ret) % SESSION_ROWS); - if (ret != 0) { - WOLFSSL_MSG("Hash session failed"); - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); - #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) - XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif + ret = CheckSslMethodVersion(ctx->method->version.major, ctx->mask); + if (ret == WOLFSSL_SUCCESS) { + /* Check the major */ + switch (ver) { + #ifndef NO_TLS + case SSL3_VERSION: + case TLS1_VERSION: + case TLS1_1_VERSION: + case TLS1_2_VERSION: + case TLS1_3_VERSION: + if (ctx->method->version.major != SSLv3_MAJOR) { + WOLFSSL_MSG("Mismatched protocol version"); + return WOLFSSL_FAILURE; + } + break; #endif - return ret; - } - - sessRow = &SessionCache[row]; - if (SESSION_ROW_WR_LOCK(sessRow) != 0) { - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); - #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) - XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + #ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + case DTLS1_2_VERSION: + if (ctx->method->version.major != DTLS_MAJOR) { + WOLFSSL_MSG("Mismatched protocol version"); + return WOLFSSL_FAILURE; + } + break; #endif + } + /* Update the method */ + switch (ver) { + case SSL2_VERSION: + WOLFSSL_MSG("wolfSSL does not support SSLv2"); + return WOLFSSL_FAILURE; + #ifndef NO_TLS + case SSL3_VERSION: + ctx->method->version.minor = SSLv3_MINOR; + break; + case TLS1_VERSION: + ctx->method->version.minor = TLSv1_MINOR; + break; + case TLS1_1_VERSION: + ctx->method->version.minor = TLSv1_1_MINOR; + break; + case TLS1_2_VERSION: + ctx->method->version.minor = TLSv1_2_MINOR; + break; + case TLS1_3_VERSION: + ctx->method->version.minor = TLSv1_3_MINOR; + break; #endif - WOLFSSL_MSG("Session row lock failed"); - return BAD_MUTEX_E; - } - - for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { -#ifdef SESSION_CACHE_DYNAMIC_MEM - cacheSession = sessRow->Sessions[i]; -#else - cacheSession = &sessRow->Sessions[i]; -#endif - if (cacheSession && XMEMCMP(id, - cacheSession->sessionID, ID_LEN) == 0 && - cacheSession->side == side) { - WOLFSSL_MSG("Session already exists. Overwriting."); - overwrite = 1; - idx = i; + #ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + ctx->method->version.minor = DTLS_MINOR; break; + case DTLS1_2_VERSION: + ctx->method->version.minor = DTLSv1_2_MINOR; + break; + #endif + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; } } + return ret; +} - if (!overwrite) - idx = sessRow->nextIdx; -#ifdef SESSION_INDEX - if (sessionIndex != NULL) - *sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; -#endif - -#ifdef SESSION_CACHE_DYNAMIC_MEM - cacheSession = sessRow->Sessions[idx]; - if (cacheSession == NULL) { - cacheSession = (WOLFSSL_SESSION*) XMALLOC(sizeof(WOLFSSL_SESSION), - sessRow->heap, DYNAMIC_TYPE_SESSION); - if (cacheSession == NULL) { - #ifdef HAVE_SESSION_TICKET - XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); - #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) - XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); - #endif - #endif - SESSION_ROW_UNLOCK(sessRow); - return MEMORY_E; - } - XMEMSET(cacheSession, 0, sizeof(WOLFSSL_SESSION)); - sessRow->Sessions[idx] = cacheSession; - } -#else - cacheSession = &sessRow->Sessions[idx]; -#endif - -#ifdef HAVE_EX_DATA - if (overwrite) { - /* Figure out who owns the ex_data */ - if (cacheSession->ownExData) { - /* Prioritize cacheSession copy */ - XMEMCPY(&addSession->ex_data, &cacheSession->ex_data, - sizeof(WOLFSSL_CRYPTO_EX_DATA)); - } - /* else will be copied in wolfSSL_DupSession call */ - } - else if (cacheSession->ownExData) { - crypto_ex_cb_free_data(cacheSession, crypto_ex_cb_ctx_session, - &cacheSession->ex_data); - cacheSession->ownExData = 0; - } -#endif - - if (!overwrite) - EvictSessionFromCache(cacheSession); - cacheSession->type = WOLFSSL_SESSION_TYPE_CACHE; - cacheSession->cacheRow = row; +/* Sets the max protocol version allowed with WOLFSSL_CTX + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version) +{ + int i; + int ret = WOLFSSL_FAILURE; + int minProto; -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - /* Save the peer field to free after unlocking the row */ - if (cacheSession->peer != NULL) - cachePeer = cacheSession->peer; - cacheSession->peer = NULL; -#endif -#ifdef HAVE_SESSION_TICKET - /* If we can reuse the existing buffer in cacheSession then we won't touch - * ticBuff at all making it a very cheap malloc/free. The page on a modern - * OS will most likely not even be allocated to the process. */ - if (ticBuff != NULL && cacheSession->ticketLenAlloc < ticLen) { - /* Save pointer only if separately allocated */ - if (cacheSession->ticket != cacheSession->staticTicket) - cacheTicBuff = cacheSession->ticket; - ticBuffUsed = 1; - cacheSession->ticket = ticBuff; - cacheSession->ticketLenAlloc = (word16) ticLen; - } -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - /* cache entry never used */ - if (cacheSession->ticketNonce.data == NULL) - cacheSession->ticketNonce.data = cacheSession->ticketNonce.dataStatic; - - if (cacheSession->ticketNonce.data != - cacheSession->ticketNonce.dataStatic) { - toFree = cacheSession->ticketNonce.data; - cacheSession->ticketNonce.data = cacheSession->ticketNonce.dataStatic; - cacheSession->ticketNonce.len = 0; - } -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ -#endif -#ifdef SESSION_CERTS - if (overwrite && - addSession->chain.count == 0 && - cacheSession->chain.count > 0) { - /* Copy in the certs from the session */ - addSession->chain.count = cacheSession->chain.count; - XMEMCPY(addSession->chain.certs, cacheSession->chain.certs, - sizeof(x509_buffer) * cacheSession->chain.count); - } -#endif /* SESSION_CERTS */ -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - /* Don't copy the peer cert into cache */ - addPeer = addSession->peer; - addSession->peer = NULL; -#endif - cacheSession->heap = NULL; - /* Copy data into the cache object */ -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ - defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - ret = wolfSSL_DupSessionEx(addSession, cacheSession, 1, preallocNonce, - &preallocNonceLen, &preallocNonceUsed) == WOLFSSL_FAILURE; -#else - ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE; -#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC - && FIPS_VERSION_GE(5,3)*/ -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - addSession->peer = addPeer; -#endif + WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version"); - if (ret == 0) { - if (!overwrite) { - /* Increment the totalCount and the nextIdx */ - if (sessRow->totalCount < SESSIONS_PER_ROW) - sessRow->totalCount++; - sessRow->nextIdx = (sessRow->nextIdx + 1) % SESSIONS_PER_ROW; - } - if (id != addSession->sessionID) { - /* ssl->session->sessionID may contain the bogus ID or we want the - * ID from the arrays object */ - XMEMCPY(cacheSession->sessionID, id, ID_LEN); - cacheSession->sessionIDSz = ID_LEN; - } -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - if (ctx->rem_sess_cb != NULL) - cacheSession->rem_sess_cb = ctx->rem_sess_cb; -#endif -#ifdef HAVE_EX_DATA - /* The session in cache now owns the ex_data */ - addSession->ownExData = 0; - cacheSession->ownExData = 1; -#endif -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ - defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (preallocNonce != NULL && preallocNonceUsed) { - cacheSession->ticketNonce.data = preallocNonce; - cacheSession->ticketNonce.len = preallocNonceLen; - preallocNonce = NULL; - preallocNonceLen = 0; - } -#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC - * && FIPS_VERSION_GE(5,3)*/ - } -#ifdef HAVE_SESSION_TICKET - else if (ticBuffUsed) { - /* Error occurred. Need to clean up the ticket buffer. */ - cacheSession->ticket = cacheSession->staticTicket; - cacheSession->ticketLenAlloc = 0; - cacheSession->ticketLen = 0; + if (ctx == NULL) { + return ret; } -#endif - SESSION_ROW_UNLOCK(sessRow); - cacheSession = NULL; /* Can't access after unlocked */ -#ifndef NO_CLIENT_CACHE - if (ret == 0 && clientCacheEntry != NULL) { - ClientSession* clientCache = AddSessionToClientCache(side, row, idx, - addSession->serverID, addSession->idLen, id, useTicket); - if (clientCache != NULL) - *clientCacheEntry = clientCache; + /* clear out flags and reset min protocol version */ + minProto = wolfSSL_CTX_get_min_proto_version(ctx); + wolfSSL_CTX_clear_options(ctx, + WOLFSSL_OP_NO_TLSv1 | WOLFSSL_OP_NO_TLSv1_1 | + WOLFSSL_OP_NO_TLSv1_2 | WOLFSSL_OP_NO_TLSv1_3); + wolfSSL_CTX_set_min_proto_version(ctx, minProto); + if (version != 0) { + ctx->maxProto = 0; /* turn max proto flag off */ + return Set_CTX_max_proto_version(ctx, version); } -#endif - -#ifdef HAVE_SESSION_TICKET - if (ticBuff != NULL && !ticBuffUsed) - XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); - XFREE(cacheTicBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); - XFREE(toFree, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ -#endif -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (cachePeer != NULL) { - wolfSSL_X509_free(cachePeer); - cachePeer = NULL; /* Make sure not use after this point */ + /* when 0 is specified as version, try to find out the min version from + * the bottom to top of the protoverTbl. + */ + for (i = NUMBER_OF_PROTOCOLS -1; i >= 0; i--) { + ret = Set_CTX_max_proto_version(ctx, protoVerTbl[i]); + if (ret == WOLFSSL_SUCCESS) { + ctx->maxProto = 1; /* turn max proto flag on */ + break; + } } -#endif return ret; } -void AddSession(WOLFSSL* ssl) -{ - int error = 0; - const byte* id = NULL; - byte idSz = 0; - WOLFSSL_SESSION* session = ssl->session; - - (void)error; - WOLFSSL_ENTER("AddSession"); - - if (SslSessionCacheOff(ssl, session)) { - WOLFSSL_MSG("Cache off"); - return; - } +static int Set_SSL_min_proto_version(WOLFSSL* ssl, int ver) +{ + WOLFSSL_ENTER("Set_SSL_min_proto_version"); - if (session->haveAltSessionID) { - id = session->altSessionID; - idSz = ID_LEN; - } - else { - id = session->sessionID; - idSz = session->sessionIDSz; - } - - /* Do this only for the client because if the server doesn't have an ID at - * this point, it won't on resumption. */ - if (idSz == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { - WC_RNG* rng = NULL; - if (ssl->rng != NULL) - rng = ssl->rng; -#if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) - else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) { - rng = &globalRNG; - } -#endif - if (wc_RNG_GenerateBlock(rng, ssl->session->altSessionID, - ID_LEN) != 0) - return; - ssl->session->haveAltSessionID = 1; - id = ssl->session->altSessionID; - idSz = ID_LEN; + if (ssl == NULL) { + return WOLFSSL_FAILURE; } -#ifdef HAVE_EXT_CACHE - if (!ssl->options.internalCacheOff) -#endif - { - /* Try to add the session to internal cache or external cache - if a new_sess_cb is set. Its ok if we don't succeed. */ - (void)AddSessionToCache(ssl->ctx, session, id, idSz, -#ifdef SESSION_INDEX - &ssl->sessionIndex, -#else - NULL, + switch (ver) { +#ifndef NO_TLS + case SSL3_VERSION: +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + ssl->options.minDowngrade = SSLv3_MINOR; + break; #endif - ssl->options.side, -#ifdef HAVE_SESSION_TICKET - ssl->options.useTicket, -#else - 0, + case TLS1_VERSION: + #ifdef WOLFSSL_ALLOW_TLSV10 + ssl->options.minDowngrade = TLSv1_MINOR; + break; + #endif + case TLS1_1_VERSION: + #ifndef NO_OLD_TLS + ssl->options.minDowngrade = TLSv1_1_MINOR; + break; + #endif + case TLS1_2_VERSION: + #ifndef WOLFSSL_NO_TLS12 + ssl->options.minDowngrade = TLSv1_2_MINOR; + break; + #endif + case TLS1_3_VERSION: + #ifdef WOLFSSL_TLS13 + ssl->options.minDowngrade = TLSv1_3_MINOR; + break; + #endif #endif -#ifdef NO_SESSION_CACHE_REF - NULL -#else - (ssl->options.side == WOLFSSL_CLIENT_END) ? - &ssl->clientSession : NULL +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + #ifndef NO_OLD_TLS + ssl->options.minDowngrade = DTLS_MINOR; + break; + #endif + case DTLS1_2_VERSION: + ssl->options.minDowngrade = DTLSv1_2_MINOR; + break; #endif - ); + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; } -#ifdef HAVE_EXT_CACHE - if (error == 0 && ssl->ctx->new_sess_cb != NULL) { - int cbRet = 0; - wolfSSL_SESSION_up_ref(session); - cbRet = ssl->ctx->new_sess_cb(ssl, session); - if (cbRet == 0) - wolfSSL_FreeSession(ssl->ctx, session); - } + switch (ver) { +#ifndef NO_TLS + case TLS1_3_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_2; + FALL_THROUGH; + case TLS1_2_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_1; + FALL_THROUGH; + case TLS1_1_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1; + FALL_THROUGH; + case TLS1_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_SSLv3; + break; + case SSL3_VERSION: + case SSL2_VERSION: + /* Nothing to do here */ + break; #endif - -#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - if (error == 0) { - word32 active = 0; - - error = get_locked_session_stats(&active, NULL, NULL); - if (error == WOLFSSL_SUCCESS) { - error = 0; /* back to this function ok */ - - if (PeakSessions < active) { - PeakSessions = active; - } - } +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + case DTLS1_2_VERSION: + break; +#endif + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; } -#endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */ - (void)error; -} - -#ifdef SESSION_INDEX - -int wolfSSL_GetSessionIndex(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_GetSessionIndex"); - WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex); - return ssl->sessionIndex; + return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); } - -int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) +int wolfSSL_set_min_proto_version(WOLFSSL* ssl, int version) { - int row, col, result = WOLFSSL_FAILURE; - SessionRow* sessRow; - WOLFSSL_SESSION* cacheSession; - - WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); - - session = ClientSessionToSession(session); + int i; + int ret = WOLFSSL_FAILURE;; - row = idx >> SESSIDX_ROW_SHIFT; - col = idx & SESSIDX_IDX_MASK; + WOLFSSL_ENTER("wolfSSL_set_min_proto_version"); - if (session == NULL || - row < 0 || row >= SESSION_ROWS || col >= SESSIONS_PER_ROW) { + if (ssl == NULL) { return WOLFSSL_FAILURE; } - - sessRow = &SessionCache[row]; - if (SESSION_ROW_RD_LOCK(sessRow) != 0) { - return BAD_MUTEX_E; + if (version != 0) { + return Set_SSL_min_proto_version(ssl, version); } -#ifdef SESSION_CACHE_DYNAMIC_MEM - cacheSession = sessRow->Sessions[col]; -#else - cacheSession = &sessRow->Sessions[col]; -#endif - if (cacheSession) { - XMEMCPY(session, cacheSession, sizeof(WOLFSSL_SESSION)); - result = WOLFSSL_SUCCESS; - } - else { - result = WOLFSSL_FAILURE; + /* when 0 is specified as version, try to find out the min version */ + for (i= 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) { + ret = Set_SSL_min_proto_version(ssl, protoVerTbl[i]); + if (ret == WOLFSSL_SUCCESS) + break; } - SESSION_ROW_UNLOCK(sessRow); - - WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result); - return result; + return ret; } -#endif /* SESSION_INDEX */ - -#if defined(SESSION_CERTS) - -WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) +static int Set_SSL_max_proto_version(WOLFSSL* ssl, int ver) { - WOLFSSL_X509_CHAIN* chain = NULL; - WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + WOLFSSL_ENTER("Set_SSL_max_proto_version"); - session = ClientSessionToSession(session); + if (!ssl) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } - if (session) - chain = &session->chain; + switch (ver) { + case SSL2_VERSION: + WOLFSSL_MSG("wolfSSL does not support SSLv2"); + return WOLFSSL_FAILURE; +#ifndef NO_TLS + case SSL3_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1; + FALL_THROUGH; + case TLS1_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_1; + FALL_THROUGH; + case TLS1_1_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_2; + FALL_THROUGH; + case TLS1_2_VERSION: + ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_3; + FALL_THROUGH; + case TLS1_3_VERSION: + /* Nothing to do here */ + break; +#endif +#ifdef WOLFSSL_DTLS + case DTLS1_VERSION: + case DTLS1_2_VERSION: + break; +#endif + default: + WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + return WOLFSSL_FAILURE; + } - WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0); - return chain; + return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); } - -#ifdef OPENSSL_EXTRA -/* gets the peer certificate associated with the session passed in - * returns null on failure, the caller should not free the returned pointer */ -WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) +int wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version) { - WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + int i; + int ret = WOLFSSL_FAILURE;; - session = ClientSessionToSession(session); - if (session) { - int count; + WOLFSSL_ENTER("wolfSSL_set_max_proto_version"); - count = wolfSSL_get_chain_count(&session->chain); - if (count < 1 || count >= MAX_CHAIN_DEPTH) { - WOLFSSL_MSG("bad count found"); - return NULL; - } + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + if (version != 0) { + return Set_SSL_max_proto_version(ssl, version); + } - if (session->peer == NULL) { - session->peer = wolfSSL_get_chain_X509(&session->chain, 0); - } - return session->peer; + /* when 0 is specified as version, try to find out the min version from + * the bottom to top of the protoverTbl. + */ + for (i = NUMBER_OF_PROTOCOLS -1; i >= 0; i--) { + ret = Set_SSL_max_proto_version(ssl, protoVerTbl[i]); + if (ret == WOLFSSL_SUCCESS) + break; } - WOLFSSL_MSG("No session passed in"); - return NULL; + return ret; } -#endif /* OPENSSL_EXTRA */ -#endif /* SESSION_INDEX && SESSION_CERTS */ +static int GetMinProtoVersion(int minDowngrade) +{ + int ret; + + switch (minDowngrade) { +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + case SSLv3_MINOR: + ret = SSL3_VERSION; + break; + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + case TLSv1_MINOR: + ret = TLS1_VERSION; + break; + #endif + case TLSv1_1_MINOR: + ret = TLS1_1_VERSION; + break; +#endif +#ifndef WOLFSSL_NO_TLS12 + case TLSv1_2_MINOR: + ret = TLS1_2_VERSION; + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSv1_3_MINOR: + ret = TLS1_3_VERSION; + break; +#endif + default: + ret = 0; + break; + } -#ifdef WOLFSSL_SESSION_STATS + return ret; +} -static int get_locked_session_stats(word32* active, word32* total, word32* peak) +int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx) { - int result = WOLFSSL_SUCCESS; - int i; - int count; - int idx; - word32 now = 0; - word32 seen = 0; - word32 ticks = LowResTimer(); + int ret = 0; - WOLFSSL_ENTER("get_locked_session_stats"); + WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version"); -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_RD_LOCK(&SessionCache[0]); -#endif - for (i = 0; i < SESSION_ROWS; i++) { - SessionRow* row = &SessionCache[i]; - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - if (SESSION_ROW_RD_LOCK(row) != 0) { - WOLFSSL_MSG("Session row cache mutex lock failed"); - return BAD_MUTEX_E; + if (ctx != NULL) { + if (ctx->minProto) { + ret = 0; } - #endif - - seen += row->totalCount; - - if (active == NULL) { - SESSION_ROW_UNLOCK(row); - continue; + else { + ret = GetMinProtoVersion(ctx->minDowngrade); } + } + else { + ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE); + } - count = min((word32)row->totalCount, SESSIONS_PER_ROW); - idx = row->nextIdx - 1; - if (idx < 0 || idx >= SESSIONS_PER_ROW) { - idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */ - } + WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret); - for (; count > 0; --count) { - /* if not expired then good */ -#ifdef SESSION_CACHE_DYNAMIC_MEM - if (row->Sessions[idx] && - ticks < (row->Sessions[idx]->bornOn + - row->Sessions[idx]->timeout) ) -#else - if (ticks < (row->Sessions[idx].bornOn + - row->Sessions[idx].timeout) ) -#endif - { - now++; - } + return ret; +} - idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; - } - #ifdef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(row); +/* returns the maximum allowed protocol version given the 'options' used + * returns WOLFSSL_FATAL_ERROR on no match */ +static int GetMaxProtoVersion(long options) +{ +#ifndef NO_TLS +#ifdef WOLFSSL_TLS13 + if (!(options & WOLFSSL_OP_NO_TLSv1_3)) + return TLS1_3_VERSION; +#endif +#ifndef WOLFSSL_NO_TLS12 + if (!(options & WOLFSSL_OP_NO_TLSv1_2)) + return TLS1_2_VERSION; +#endif +#ifndef NO_OLD_TLS + if (!(options & WOLFSSL_OP_NO_TLSv1_1)) + return TLS1_1_VERSION; + #ifdef WOLFSSL_ALLOW_TLSV10 + if (!(options & WOLFSSL_OP_NO_TLSv1)) + return TLS1_VERSION; + #endif + #ifdef WOLFSSL_ALLOW_SSLV3 + if (!(options & WOLFSSL_OP_NO_SSLv3)) + return SSL3_VERSION; #endif - } -#ifndef ENABLE_SESSION_CACHE_ROW_LOCK - SESSION_ROW_UNLOCK(&SessionCache[0]); #endif +#else + (void)options; +#endif /* NO_TLS */ + return WOLFSSL_FATAL_ERROR; +} - if (active) { - *active = now; - } - if (total) { - *total = seen; + +/* returns the maximum protocol version for 'ctx' */ +int wolfSSL_CTX_get_max_proto_version(WOLFSSL_CTX* ctx) +{ + int ret = 0; + long options = 0; /* default to nothing set */ + + WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version"); + + if (ctx != NULL) { + options = wolfSSL_CTX_get_options(ctx); } -#ifdef WOLFSSL_PEAK_SESSIONS - if (peak) { - *peak = PeakSessions; + if ((ctx != NULL) && ctx->maxProto) { + ret = 0; + } + else { + ret = GetMaxProtoVersion(options); } -#else - (void)peak; -#endif - WOLFSSL_LEAVE("get_locked_session_stats", result); + WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret); - return result; + if (ret == WOLFSSL_FATAL_ERROR) { + WOLFSSL_MSG("Error getting max proto version"); + ret = 0; /* setting ret to 0 to match compat return */ + } + return ret; } +#endif /* OPENSSL_EXTRA */ - -/* return WOLFSSL_SUCCESS on ok */ -int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, - word32* maxSessions) +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_SECRET_CALLBACK) +#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 + */ +size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, + size_t outSz) { - int result = WOLFSSL_SUCCESS; - - WOLFSSL_ENTER("wolfSSL_get_session_stats"); - - if (maxSessions) { - *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS; + size_t size; - if (active == NULL && total == NULL && peak == NULL) - return result; /* we're done */ + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; } - /* user must provide at least one query value */ - if (active == NULL && total == NULL && peak == NULL) { - return BAD_FUNC_ARG; + if (ssl == NULL || out == NULL) { + return 0; } - result = get_locked_session_stats(active, total, peak); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } - WOLFSSL_LEAVE("wolfSSL_get_session_stats", result); + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } - return result; + XMEMCPY(out, ssl->arrays->clientRandom, size); + return size; } +#endif /* !NO_WOLFSSL_CLIENT */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ -#endif /* WOLFSSL_SESSION_STATS */ - +#ifdef OPENSSL_EXTRA - #ifdef PRINT_SESSION_STATS + unsigned long wolfSSLeay(void) + { + return SSLEAY_VERSION_NUMBER; + } - /* WOLFSSL_SUCCESS on ok */ - int wolfSSL_PrintSessionStats(void) + unsigned long wolfSSL_OpenSSL_version_num(void) { - word32 totalSessionsSeen = 0; - word32 totalSessionsNow = 0; - word32 peak = 0; - word32 maxSessions = 0; - int i; - int ret; - double E; /* expected freq */ - double chiSquare = 0; - - ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen, - &peak, &maxSessions); - if (ret != WOLFSSL_SUCCESS) - return ret; - printf("Total Sessions Seen = %u\n", totalSessionsSeen); - printf("Total Sessions Now = %u\n", totalSessionsNow); -#ifdef WOLFSSL_PEAK_SESSIONS - printf("Peak Sessions = %u\n", peak); -#endif - printf("Max Sessions = %u\n", maxSessions); - - E = (double)totalSessionsSeen / SESSION_ROWS; - - for (i = 0; i < SESSION_ROWS; i++) { - double diff = SessionCache[i].totalCount - E; - diff *= diff; /* square */ - diff /= E; /* normalize */ - - chiSquare += diff; - } - printf(" chi-square = %5.1f, d.f. = %d\n", chiSquare, - SESSION_ROWS - 1); - #if (SESSION_ROWS == 11) - printf(" .05 p value = 18.3, chi-square should be less\n"); - #elif (SESSION_ROWS == 211) - printf(".05 p value = 244.8, chi-square should be less\n"); - #elif (SESSION_ROWS == 5981) - printf(".05 p value = 6161.0, chi-square should be less\n"); - #elif (SESSION_ROWS == 3) - printf(".05 p value = 6.0, chi-square should be less\n"); - #elif (SESSION_ROWS == 2861) - printf(".05 p value = 2985.5, chi-square should be less\n"); - #endif - printf("\n"); + return OPENSSL_VERSION_NUMBER; + } - return ret; + const char* wolfSSLeay_version(int type) + { + (void)type; +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + return wolfSSL_OpenSSL_version(type); +#else + return wolfSSL_OpenSSL_version(); +#endif } +#endif /* OPENSSL_EXTRA */ - #endif /* SESSION_STATS */ +#ifdef OPENSSL_EXTRA + void wolfSSL_ERR_free_strings(void) + { + /* handled internally */ + } -#else /* NO_SESSION_CACHE */ + void wolfSSL_cleanup_all_ex_data(void) + { + /* nothing to do here */ + } -WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) -{ - return (WOLFSSL_SESSION*)session; -} +#endif /* OPENSSL_EXTRA */ -/* No session cache version */ -WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, - byte restoreSessionCerts) -{ - (void)ssl; - (void)masterSecret; - (void)restoreSessionCerts; +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) || \ + defined(HAVE_CURL) + void wolfSSL_ERR_clear_error(void) + { + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + wc_ClearErrorNodes(); + #endif + } +#endif - return NULL; -} +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + int wolfSSL_clear(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_clear"); -#endif /* NO_SESSION_CACHE */ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + if (!ssl->options.handShakeDone) { + /* Only reset the session if we didn't complete a handshake */ + wolfSSL_FreeSession(ssl->ctx, ssl->session); + ssl->session = wolfSSL_NewSession(ssl->heap); + if (ssl->session == NULL) { + return WOLFSSL_FAILURE; + } + } -/* call before SSL_connect, if verifying will add name check to - date check and signature check */ -WOLFSSL_ABI -int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn) -{ - WOLFSSL_ENTER("wolfSSL_check_domain_name"); + /* reset error */ + ssl->error = 0; - if (ssl == NULL || dn == NULL) { - WOLFSSL_MSG("Bad function argument: NULL"); - return WOLFSSL_FAILURE; - } + /* reset option bits */ + ssl->options.isClosed = 0; + ssl->options.connReset = 0; + ssl->options.sentNotify = 0; + ssl->options.closeNotify = 0; + ssl->options.sendVerify = 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 = 0; /* doProcessInit */ + ssl->options.havePeerVerify = 0; + ssl->options.havePeerCert = 0; + ssl->options.peerAuthGood = 0; + ssl->options.tls1_3 = 0; + ssl->options.haveSessionId = 0; + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + #ifdef WOLFSSL_DTLS + ssl->options.dtlsStateful = 0; + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ssl->options.noPskDheKe = 0; + #ifdef HAVE_SUPPORTED_CURVES + ssl->options.onlyPskDheKe = 0; + #endif + #endif + #ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13 + ssl->options.ticketsSent = 0; + #endif + ssl->options.rejectTicket = 0; + #endif + #ifdef WOLFSSL_EARLY_DATA + ssl->earlyData = no_early_data; + ssl->earlyDataSz = 0; + #endif - if (ssl->buffers.domainName.buffer) - XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); + #if defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS) + TLSX_FreeAll(ssl->extensions, ssl->heap); + ssl->extensions = NULL; + #endif - ssl->buffers.domainName.length = (word32)XSTRLEN(dn); - ssl->buffers.domainName.buffer = (byte*)XMALLOC( - ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN); + if (ssl->keys.encryptionOn) { + ForceZero(ssl->buffers.inputBuffer.buffer - + ssl->buffers.inputBuffer.offset, + ssl->buffers.inputBuffer.bufferSize); + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(ssl->buffers.inputBuffer.buffer - + ssl->buffers.inputBuffer.offset, + ssl->buffers.inputBuffer.bufferSize); + #endif + } + ssl->keys.encryptionOn = 0; + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); - if (ssl->buffers.domainName.buffer) { - unsigned char* domainName = ssl->buffers.domainName.buffer; - XMEMCPY(domainName, dn, ssl->buffers.domainName.length); - domainName[ssl->buffers.domainName.length] = '\0'; - return WOLFSSL_SUCCESS; - } - else { - ssl->error = MEMORY_ERROR; - return WOLFSSL_FAILURE; - } -} + if (InitSSL_Suites(ssl) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + if (InitHandshakeHashes(ssl) != 0) + return WOLFSSL_FAILURE; -/* turn on wolfSSL zlib compression - returns WOLFSSL_SUCCESS for success, else error (not built in) -*/ -int wolfSSL_set_compression(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_set_compression"); - (void)ssl; -#ifdef HAVE_LIBZ - ssl->options.usingCompression = 1; - return WOLFSSL_SUCCESS; -#else - return NOT_COMPILED_IN; +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); #endif -} +#ifdef WOLFSSL_QUIC + wolfSSL_quic_clear(ssl); +#endif -#ifndef USE_WINDOWS_API - #ifndef NO_WRITEV + return WOLFSSL_SUCCESS; + } - /* simulate writev semantics, doesn't actually do block at a time though - because of SSL_write behavior and because front adds may be small */ - int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt) - { - #ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ - #else - byte staticBuffer[FILE_BUFFER_SIZE]; - #endif - byte* myBuffer = staticBuffer; - int dynamic = 0; - int sending = 0; - int idx = 0; - int i; - int ret; +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - WOLFSSL_ENTER("wolfSSL_writev"); +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED) + long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode) + { + /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ - for (i = 0; i < iovcnt; i++) - sending += (int)iov[i].iov_len; + WOLFSSL_ENTER("wolfSSL_CTX_set_mode"); + switch(mode) { + case SSL_MODE_ENABLE_PARTIAL_WRITE: + ctx->partialWrite = 1; + break; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + case SSL_MODE_RELEASE_BUFFERS: + WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented."); + break; + #endif + case SSL_MODE_AUTO_RETRY: + ctx->autoRetry = 1; + break; + default: + WOLFSSL_MSG("Mode Not Implemented"); + } - if (sending > (int)sizeof(staticBuffer)) { - myBuffer = (byte*)XMALLOC(sending, ssl->heap, - DYNAMIC_TYPE_WRITEV); - if (!myBuffer) - return MEMORY_ERROR; + /* SSL_MODE_AUTO_RETRY + * Should not return -1 with renegotiation on read/write */ - dynamic = 1; - } + return mode; + } - for (i = 0; i < iovcnt; i++) { - XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len); - idx += (int)iov[i].iov_len; - } + long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode) + { + /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ - /* myBuffer may not be initialized fully, but the span up to the - * sending length will be. - */ - PRAGMA_GCC_DIAG_PUSH - PRAGMA_GCC("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") - ret = wolfSSL_write(ssl, myBuffer, sending); - PRAGMA_GCC_DIAG_POP + WOLFSSL_ENTER("wolfSSL_CTX_clear_mode"); + switch(mode) { + case SSL_MODE_ENABLE_PARTIAL_WRITE: + ctx->partialWrite = 0; + break; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + case SSL_MODE_RELEASE_BUFFERS: + WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented."); + break; + #endif + case SSL_MODE_AUTO_RETRY: + ctx->autoRetry = 0; + break; + default: + WOLFSSL_MSG("Mode Not Implemented"); + } - if (dynamic) - XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); + /* SSL_MODE_AUTO_RETRY + * Should not return -1 with renegotiation on read/write */ - return ret; - } - #endif + return 0; + } #endif +#ifdef OPENSSL_EXTRA -#ifdef WOLFSSL_CALLBACKS - - typedef struct itimerval Itimerval; + #ifndef NO_WOLFSSL_STUB + long wolfSSL_SSL_get_mode(WOLFSSL* ssl) + { + /* TODO: */ + (void)ssl; + WOLFSSL_STUB("SSL_get_mode"); + return 0; + } + #endif - /* don't keep calling simple functions while setting up timer and signals - if no inlining these are the next best */ - - #define AddTimes(a, b, c) \ - do { \ - (c).tv_sec = (a).tv_sec + (b).tv_sec; \ - (c).tv_usec = (a).tv_usec + (b).tv_usec;\ - if ((c).tv_usec >= 1000000) { \ - (c).tv_sec++; \ - (c).tv_usec -= 1000000; \ - } \ - } while (0) + #ifndef NO_WOLFSSL_STUB + long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx) + { + /* TODO: */ + (void)ctx; + WOLFSSL_STUB("SSL_CTX_get_mode"); + return 0; + } + #endif + #ifndef NO_WOLFSSL_STUB + void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m) + { + /* TODO: maybe? */ + (void)ctx; + (void)m; + WOLFSSL_STUB("SSL_CTX_set_default_read_ahead"); + } + #endif - #define SubtractTimes(a, b, c) \ - do { \ - (c).tv_sec = (a).tv_sec - (b).tv_sec; \ - (c).tv_usec = (a).tv_usec - (b).tv_usec;\ - if ((c).tv_usec < 0) { \ - (c).tv_sec--; \ - (c).tv_usec += 1000000; \ - } \ - } while (0) - #define CmpTimes(a, b, cmp) \ - (((a).tv_sec == (b).tv_sec) ? \ - ((a).tv_usec cmp (b).tv_usec) : \ - ((a).tv_sec cmp (b).tv_sec)) \ + /* returns the unsigned error value and increments the pointer into the + * error queue. + * + * file pointer to file name + * line gets set to line number of error when not NULL + */ + unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line) + { + #ifdef WOLFSSL_HAVE_ERROR_QUEUE + int ret = wc_PullErrorNode(file, NULL, line); + if (ret < 0) { + if (ret == WC_NO_ERR_TRACE(BAD_STATE_E)) + return 0; /* no errors in queue */ + WOLFSSL_MSG("Issue getting error node"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret); + ret = 0 - ret; /* return absolute value of error */ + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + return (unsigned long)ret; + #else + (void)file; + (void)line; - /* do nothing handler */ - static void myHandler(int signo) - { - (void)signo; - return; + return 0; + #endif } - static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) - { - int ret = WOLFSSL_FATAL_ERROR; - int oldTimerOn = 0; /* was timer already on */ - WOLFSSL_TIMEVAL startTime; - WOLFSSL_TIMEVAL endTime; - WOLFSSL_TIMEVAL totalTime; - Itimerval myTimeout; - Itimerval oldTimeout; /* if old timer adjust from total time to reset */ - struct sigaction act, oact; - - #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; } +#if (defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)) && \ + (!defined(_WIN32) && !defined(NO_ERROR_QUEUE)) + static const char WOLFSSL_SYS_ACCEPT_T[] = "accept"; + static const char WOLFSSL_SYS_BIND_T[] = "bind"; + static const char WOLFSSL_SYS_CONNECT_T[] = "connect"; + static const char WOLFSSL_SYS_FOPEN_T[] = "fopen"; + static const char WOLFSSL_SYS_FREAD_T[] = "fread"; + static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo"; + static const char WOLFSSL_SYS_GETSOCKOPT_T[] = "getsockopt"; + static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname"; + static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname"; + static const char WOLFSSL_SYS_GETNAMEINFO_T[] = "getnameinfo"; + static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname"; + static const char WOLFSSL_SYS_IOCTLSOCKET_T[] = "ioctlsocket"; + static const char WOLFSSL_SYS_LISTEN_T[] = "listen"; + static const char WOLFSSL_SYS_OPENDIR_T[] = "opendir"; + static const char WOLFSSL_SYS_SETSOCKOPT_T[] = "setsockopt"; + static const char WOLFSSL_SYS_SOCKET_T[] = "socket"; - if (hsCb) { - ssl->hsInfoOn = 1; - InitHandShakeInfo(&ssl->handShakeInfo, ssl); + /* switch with int mapped to function name for compatibility */ + static const char* wolfSSL_ERR_sys_func(int fun) + { + switch (fun) { + case WOLFSSL_SYS_ACCEPT: return WOLFSSL_SYS_ACCEPT_T; + case WOLFSSL_SYS_BIND: return WOLFSSL_SYS_BIND_T; + case WOLFSSL_SYS_CONNECT: return WOLFSSL_SYS_CONNECT_T; + case WOLFSSL_SYS_FOPEN: return WOLFSSL_SYS_FOPEN_T; + case WOLFSSL_SYS_FREAD: return WOLFSSL_SYS_FREAD_T; + case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T; + case WOLFSSL_SYS_GETSOCKOPT: return WOLFSSL_SYS_GETSOCKOPT_T; + case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T; + case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T; + case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T; + case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T; + case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T; + case WOLFSSL_SYS_LISTEN: return WOLFSSL_SYS_LISTEN_T; + case WOLFSSL_SYS_OPENDIR: return WOLFSSL_SYS_OPENDIR_T; + case WOLFSSL_SYS_SETSOCKOPT: return WOLFSSL_SYS_SETSOCKOPT_T; + case WOLFSSL_SYS_SOCKET: return WOLFSSL_SYS_SOCKET_T; + default: + return "NULL"; } - if (toCb) { - ssl->toInfoOn = 1; - InitTimeoutInfo(&ssl->timeoutInfo); + } +#endif /* DEBUG_WOLFSSL */ - if (gettimeofday(&startTime, 0) < 0) - ERR_OUT(GETTIME_ERROR); - /* use setitimer to simulate getitimer, init 0 myTimeout */ - myTimeout.it_interval.tv_sec = 0; - myTimeout.it_interval.tv_usec = 0; - myTimeout.it_value.tv_sec = 0; - myTimeout.it_value.tv_usec = 0; - if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0) - ERR_OUT(SETITIMER_ERROR); + void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file, + int line) + { + WOLFSSL_ENTER("wolfSSL_ERR_put_error"); - if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) { - oldTimerOn = 1; + #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA) + (void)fun; + (void)err; + (void)file; + (void)line; + WOLFSSL_MSG("Not compiled in debug mode"); + #elif defined(OPENSSL_EXTRA) && \ + (defined(_WIN32) || defined(NO_ERROR_QUEUE)) + (void)fun; + (void)file; + (void)line; + WOLFSSL_ERROR(err); + #else + WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line, + file, NULL); + #endif + (void)lib; + } - /* is old timer going to expire before ours */ - if (CmpTimes(oldTimeout.it_value, timeout, <)) { - timeout.tv_sec = oldTimeout.it_value.tv_sec; - timeout.tv_usec = oldTimeout.it_value.tv_usec; - } - } - myTimeout.it_value.tv_sec = timeout.tv_sec; - myTimeout.it_value.tv_usec = timeout.tv_usec; - /* set up signal handler, don't restart socket send/recv */ - act.sa_handler = myHandler; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; -#ifdef SA_INTERRUPT - act.sa_flags |= SA_INTERRUPT; -#endif - if (sigaction(SIGALRM, &act, &oact) < 0) - ERR_OUT(SIGACT_ERROR); + /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for + * more flexibility. + * + * file output pointer to file where error happened + * line output to line number of error + * data output data. Is a string if ERR_TXT_STRING flag is used + * flags output format of output + * + * Returns the error value or 0 if no errors are in the queue + */ + unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, + const char** data, int *flags) + { +#ifdef WOLFSSL_HAVE_ERROR_QUEUE + int ret; - if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0) - ERR_OUT(SETITIMER_ERROR); - } + WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data"); - /* do main work */ -#ifndef NO_WOLFSSL_CLIENT - if (ssl->options.side == WOLFSSL_CLIENT_END) - ret = wolfSSL_connect(ssl); -#endif -#ifndef NO_WOLFSSL_SERVER - if (ssl->options.side == WOLFSSL_SERVER_END) - ret = wolfSSL_accept(ssl); -#endif + if (flags != NULL) + *flags = ERR_TXT_STRING; /* Clear the flags */ - /* do callbacks */ - if (toCb) { - if (oldTimerOn) { - if (gettimeofday(&endTime, 0) < 0) - ERR_OUT(SYSLIB_FAILED_E); - SubtractTimes(endTime, startTime, totalTime); - /* adjust old timer for elapsed time */ - if (CmpTimes(totalTime, oldTimeout.it_value, <)) - SubtractTimes(oldTimeout.it_value, totalTime, - oldTimeout.it_value); - else { - /* reset value to interval, may be off */ - oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec; - oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec; - } - /* keep iter the same whether there or not */ - } - /* restore old handler */ - if (sigaction(SIGALRM, &oact, 0) < 0) - ret = SIGACT_ERROR; /* more pressing error, stomp */ - else - /* use old settings which may turn off (expired or not there) */ - if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0) - ret = SETITIMER_ERROR; + ret = wc_PullErrorNode(file, data, line); + if (ret < 0) { + if (ret == WC_NO_ERR_TRACE(BAD_STATE_E)) + return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret); + ret = 0 - ret; /* return absolute value of error */ - /* if we had a timeout call callback */ - if (ssl->timeoutInfo.timeoutName[0]) { - ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec; - ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec; - (toCb)(&ssl->timeoutInfo); - } - ssl->toInfoOn = 0; + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); } - /* clean up buffers allocated by AddPacketInfo */ - FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap); - - if (hsCb) { - FinishHandShakeInfo(&ssl->handShakeInfo); - (hsCb)(&ssl->handShakeInfo); - ssl->hsInfoOn = 0; - } - return ret; + return (unsigned long)ret; +#else + WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data"); + WOLFSSL_MSG("Error queue turned off, can not get error line"); + (void)file; + (void)line; + (void)data; + (void)flags; + return 0; +#endif } +#endif /* OPENSSL_EXTRA */ -#ifndef NO_WOLFSSL_CLIENT - int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) +#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \ + (defined(OPENSSL_EXTRA) && defined(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) { - WOLFSSL_ENTER("wolfSSL_connect_ex"); - return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); - } - -#endif + int ret; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; + #else + DecodedCert cert[1]; + #endif + if (x509 == NULL || in == NULL || len <= 0) + return BAD_FUNC_ARG; + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif -#ifndef NO_WOLFSSL_SERVER + /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. + */ + InitDecodedCert(cert, (byte*)in, (word32)len, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL, NULL)) == 0) { + /* Check if x509 was not previously initialized by wolfSSL_X509_new() */ + if (x509->dynamicMemory != TRUE) + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + } + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif - int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, - TimeoutCallBack toCb, WOLFSSL_TIMEVAL timeout) - { - WOLFSSL_ENTER("wolfSSL_accept_ex"); - return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); + return ret; } +#endif /* (KEEP_PEER_CERT & SESSION_CERTS) || (OPENSSL_EXTRA & SESSION_CERTS) */ + +#ifdef KEEP_PEER_CERT + WOLFSSL_ABI + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) + { + WOLFSSL_X509* ret = NULL; + WOLFSSL_ENTER("wolfSSL_get_peer_certificate"); + if (ssl != NULL) { + if (ssl->peerCert.issuer.sz) + ret = wolfSSL_X509_dup(&ssl->peerCert); +#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) { + ret = wolfSSL_X509_dup(&ssl->peerCert); + } + } #endif + } + WOLFSSL_LEAVE("wolfSSL_get_peer_certificate", ret != NULL); + return ret; + } -#endif /* WOLFSSL_CALLBACKS */ +#endif /* KEEP_PEER_CERT */ +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) +/* Return stack of peer certs. + * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl + * is. + */ +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); -#ifndef NO_PSK + if (ssl == NULL) + return NULL; - void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx, - wc_psk_client_callback cb) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_psk_client_callback"); + /* Try to populate if NULL or empty */ + if (ssl->peerCertChain == NULL || + wolfSSL_sk_X509_num(ssl->peerCertChain) == 0) + wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); + return ssl->peerCertChain; +} - if (ctx == NULL) - return; +#ifndef WOLFSSL_QT +static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, + WOLFSSL_X509 *x); +/** + * Recursively push the issuer CA chain onto the stack + * @param cm The cert manager that is queried for the issuer + * @param x This cert's issuer will be queried in cm + * @param sk The issuer is pushed onto this stack + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on no issuer found + * WOLFSSL_FATAL_ERROR on a fatal error + */ +static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, + WOLFSSL_X509 *x, WOLFSSL_STACK* sk) +{ + WOLFSSL_X509* issuer[MAX_CHAIN_DEPTH]; + int i; + int push = 1; + int ret = WOLFSSL_SUCCESS; - ctx->havePSK = 1; - ctx->client_psk_cb = cb; + for (i = 0; i < MAX_CHAIN_DEPTH; i++) { + if (x509GetIssuerFromCM(&issuer[i], cm, x) + != WOLFSSL_SUCCESS) + break; + x = issuer[i]; + } + if (i == 0) /* No further chain found */ + return WOLFSSL_FAILURE; + i--; + for (; i >= 0; i--) { + if (push) { + if (wolfSSL_sk_X509_push(sk, issuer[i]) != WOLFSSL_SUCCESS) { + wolfSSL_X509_free(issuer[i]); + ret = WOLFSSL_FATAL_ERROR; + push = 0; /* Free the rest of the unpushed certs */ + } + } + else { + wolfSSL_X509_free(issuer[i]); + } } + return ret; +} +#endif /* !WOLFSSL_QT */ - void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) - { - byte haveRSA = 1; - int keySz = 0; +/* Builds up and creates a stack of peer certificates for ssl->peerCertChain + based off of the ssl session chain. Attempts to place CA certificates + at the bottom of the stack. Returns stack of WOLFSSL_X509 certs or + NULL on failure */ +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) +{ + WOLFSSL_STACK* sk; + WOLFSSL_X509* x509; + int i = 0; + int ret; - WOLFSSL_ENTER("wolfSSL_set_psk_client_callback"); + WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); + if ((ssl == NULL) || (ssl->session->chain.count == 0)) + return NULL; - if (ssl == NULL) - return; + sk = wolfSSL_sk_X509_new_null(); + i = ssl->session->chain.count-1; + for (; i >= 0; i--) { + x509 = wolfSSL_X509_new_ex(ssl->heap); + if (x509 == NULL) { + WOLFSSL_MSG("Error Creating X509"); + wolfSSL_sk_X509_pop_free(sk, NULL); + return NULL; + } + ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer, + ssl->session->chain.certs[i].length); +#if !defined(WOLFSSL_QT) + if (ret == 0 && i == ssl->session->chain.count-1) { + /* On the last element in the chain try to add the CA chain + * first if we have one for this cert */ + SSL_CM_WARNING(ssl); + if (PushCAx509Chain(SSL_CM(ssl), x509, sk) + == WOLFSSL_FATAL_ERROR) { + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif - ssl->options.havePSK = 1; - ssl->options.client_psk_cb = cb; + if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error decoding cert"); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_pop_free(sk, NULL); + return NULL; + } + } - #ifdef NO_RSA - haveRSA = 0; - #endif - #ifndef NO_CERTS - keySz = ssl->buffers.keySz; - #endif - if (AllocateSuites(ssl) != 0) - return; - InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, - ssl->options.haveDH, ssl->options.haveECDSAsig, - ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, - ssl->options.useAnon, TRUE, ssl->options.side); + if (sk == NULL) { + WOLFSSL_MSG("Null session chain"); } - #ifdef OPENSSL_EXTRA - /** - * set call back function for psk session use - * @param ssl a pointer to WOLFSSL structure - * @param cb a function pointer to wc_psk_use_session_cb - * @return none - */ - void wolfSSL_set_psk_use_session_callback(WOLFSSL* ssl, - wc_psk_use_session_cb_func cb) - { - WOLFSSL_ENTER("wolfSSL_set_psk_use_session_callback"); +#if defined(OPENSSL_ALL) + else if (ssl->options.side == WOLFSSL_SERVER_END) { + /* to be compliant with openssl + first element is kept as peer cert on server side.*/ + wolfSSL_sk_X509_pop(sk); + } +#endif + if (ssl->peerCertChain != NULL) + wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); + /* This is Free'd when ssl is Free'd */ + ssl->peerCertChain = sk; + return sk; +} +#endif /* SESSION_CERTS && OPENSSL_EXTRA */ - if (ssl != NULL) { - ssl->options.havePSK = 1; - ssl->options.session_psk_cb = cb; - } +#ifndef NO_CERTS +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) - WOLFSSL_LEAVE("wolfSSL_set_psk_use_session_callback", WOLFSSL_SUCCESS); - } - #endif +/* create a generic wolfSSL stack node + * returns a new WOLFSSL_STACK structure on success */ +WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_node"); - void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx, - wc_psk_server_callback cb) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_psk_server_callback"); - if (ctx == NULL) - return; - ctx->havePSK = 1; - ctx->server_psk_cb = cb; + sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap, + DYNAMIC_TYPE_OPENSSL); + if (sk != NULL) { + XMEMSET(sk, 0, sizeof(*sk)); + sk->heap = heap; } - void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb) - { - byte haveRSA = 1; - int keySz = 0; - - WOLFSSL_ENTER("wolfSSL_set_psk_server_callback"); - if (ssl == NULL) - return; - - ssl->options.havePSK = 1; - ssl->options.server_psk_cb = cb; + return sk; +} - #ifdef NO_RSA - haveRSA = 0; - #endif - #ifndef NO_CERTS - keySz = ssl->buffers.keySz; - #endif - if (AllocateSuites(ssl) != 0) - return; - InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, - ssl->options.haveDH, ssl->options.haveECDSAsig, - ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, - ssl->options.useAnon, TRUE, ssl->options.side); +/* free's node but does not free internal data such as in->data.x509 */ +void wolfSSL_sk_free_node(WOLFSSL_STACK* in) +{ + if (in != NULL) { + XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL); } +} - const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_get_psk_identity_hint"); - - if (ssl == NULL || ssl->arrays == NULL) - return NULL; +/* pushes node "in" onto "stack" and returns pointer to the new stack on success + * also handles internal "num" for number of nodes on stack + * return WOLFSSL_SUCCESS on success + */ +int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in) +{ + if (stack == NULL || in == NULL) { + return WOLFSSL_FAILURE; + } - return ssl->arrays->server_hint; + if (*stack == NULL) { + in->num = 1; + *stack = in; + return WOLFSSL_SUCCESS; } + in->num = (*stack)->num + 1; + in->next = *stack; + *stack = in; + return WOLFSSL_SUCCESS; +} - const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_get_psk_identity"); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +static WC_INLINE int compare_WOLFSSL_CIPHER( + WOLFSSL_CIPHER *a, + WOLFSSL_CIPHER *b) +{ + if ((a->cipherSuite0 == b->cipherSuite0) && + (a->cipherSuite == b->cipherSuite) && + (a->ssl == b->ssl) && + (XMEMCMP(a->description, b->description, sizeof a->description) == 0) && + (a->offset == b->offset) && + (a->in_stack == b->in_stack) && + (a->bits == b->bits)) + return 0; + else + return -1; +} +#endif /* OPENSSL_ALL || WOLFSSL_QT */ - if (ssl == NULL || ssl->arrays == NULL) - return NULL; - return ssl->arrays->client_identity; - } +/* return 1 on success 0 on fail */ +int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data) +{ + WOLFSSL_STACK* node; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + WOLFSSL_CIPHER ciph; +#endif + WOLFSSL_ENTER("wolfSSL_sk_push"); - int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint) - { - WOLFSSL_ENTER("wolfSSL_CTX_use_psk_identity_hint"); - if (hint == 0) - ctx->server_hint[0] = '\0'; - else { - /* Qt does not call CTX_set_*_psk_callbacks where havePSK is set */ - #ifdef WOLFSSL_QT - ctx->havePSK=1; - #endif - XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN); - ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ - } - return WOLFSSL_SUCCESS; + if (!sk) { + return WOLFSSL_FAILURE; } - int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint) - { - WOLFSSL_ENTER("wolfSSL_use_psk_identity_hint"); - - if (ssl == NULL || ssl->arrays == NULL) - return WOLFSSL_FAILURE; - - if (hint == 0) - ssl->arrays->server_hint[0] = 0; - else { - XSTRNCPY(ssl->arrays->server_hint, hint, - sizeof(ssl->arrays->server_hint)-1); - ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0'; - } - return WOLFSSL_SUCCESS; + /* Check if empty data */ + switch (sk->type) { + case STACK_TYPE_CIPHER: +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + /* check if entire struct is zero */ + XMEMSET(&ciph, 0, sizeof(WOLFSSL_CIPHER)); + if (compare_WOLFSSL_CIPHER(&sk->data.cipher, &ciph) == 0) { + sk->data.cipher = *(WOLFSSL_CIPHER*)data; + sk->num = 1; + if (sk->hash_fn) { + sk->hash = sk->hash_fn(&sk->data.cipher); + } + return WOLFSSL_SUCCESS; + } + break; +#endif + case STACK_TYPE_X509: + case STACK_TYPE_GEN_NAME: + case STACK_TYPE_BIO: + case STACK_TYPE_OBJ: + case STACK_TYPE_STRING: + case STACK_TYPE_ACCESS_DESCRIPTION: + case STACK_TYPE_X509_EXT: + case STACK_TYPE_X509_REQ_ATTR: + case STACK_TYPE_NULL: + case STACK_TYPE_X509_NAME: + case STACK_TYPE_X509_NAME_ENTRY: + case STACK_TYPE_CONF_VALUE: + case STACK_TYPE_X509_INFO: + case STACK_TYPE_BY_DIR_entry: + case STACK_TYPE_BY_DIR_hash: + case STACK_TYPE_X509_OBJ: + case STACK_TYPE_DIST_POINT: + case STACK_TYPE_X509_CRL: + default: + /* All other types are pointers */ + if (!sk->data.generic) { + sk->data.generic = (void*)data; + sk->num = 1; +#ifdef OPENSSL_ALL + if (sk->hash_fn) { + sk->hash = sk->hash_fn(sk->data.generic); + } +#endif + return WOLFSSL_SUCCESS; + } + break; } - void* wolfSSL_get_psk_callback_ctx(WOLFSSL* ssl) - { - return ssl ? ssl->options.psk_ctx : NULL; - } - void* wolfSSL_CTX_get_psk_callback_ctx(WOLFSSL_CTX* ctx) - { - return ctx ? ctx->psk_ctx : NULL; - } - int wolfSSL_set_psk_callback_ctx(WOLFSSL* ssl, void* psk_ctx) - { - if (ssl == NULL) - return WOLFSSL_FAILURE; - ssl->options.psk_ctx = psk_ctx; - return WOLFSSL_SUCCESS; - } - int wolfSSL_CTX_set_psk_callback_ctx(WOLFSSL_CTX* ctx, void* psk_ctx) - { - if (ctx == NULL) - return WOLFSSL_FAILURE; - ctx->psk_ctx = psk_ctx; - return WOLFSSL_SUCCESS; + /* stack already has value(s) create a new node and add more */ + node = wolfSSL_sk_new_node(sk->heap); + if (!node) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; } -#endif /* NO_PSK */ + /* push new x509 onto head of stack */ + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->num += 1; -#ifdef HAVE_ANON +#ifdef OPENSSL_ALL + node->hash_fn = sk->hash_fn; + node->hash = sk->hash; + sk->hash = 0; +#endif + switch (sk->type) { + case STACK_TYPE_CIPHER: +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + node->data.cipher = sk->data.cipher; + sk->data.cipher = *(WOLFSSL_CIPHER*)data; + if (sk->hash_fn) { + sk->hash = sk->hash_fn(&sk->data.cipher); + } + break; +#endif + case STACK_TYPE_X509: + case STACK_TYPE_GEN_NAME: + case STACK_TYPE_BIO: + case STACK_TYPE_OBJ: + case STACK_TYPE_STRING: + case STACK_TYPE_ACCESS_DESCRIPTION: + case STACK_TYPE_X509_EXT: + case STACK_TYPE_X509_REQ_ATTR: + case STACK_TYPE_NULL: + case STACK_TYPE_X509_NAME: + case STACK_TYPE_X509_NAME_ENTRY: + case STACK_TYPE_CONF_VALUE: + case STACK_TYPE_X509_INFO: + case STACK_TYPE_BY_DIR_entry: + case STACK_TYPE_BY_DIR_hash: + case STACK_TYPE_X509_OBJ: + case STACK_TYPE_DIST_POINT: + case STACK_TYPE_X509_CRL: + default: + /* All other types are pointers */ + node->data.generic = sk->data.generic; + sk->data.generic = (void*)data; +#ifdef OPENSSL_ALL + if (sk->hash_fn) { + sk->hash = sk->hash_fn(sk->data.generic); + } +#endif + break; + } - int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher"); + return WOLFSSL_SUCCESS; +} - if (ctx == NULL) - return WOLFSSL_FAILURE; +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - ctx->useAnon = 1; +#ifdef OPENSSL_EXTRA - return WOLFSSL_SUCCESS; - } - -#endif /* HAVE_ANON */ +/* returns the node at index "idx", NULL if not found */ +WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx) +{ + int i; + WOLFSSL_STACK* ret = NULL; + WOLFSSL_STACK* current; + current = sk; + for (i = 0; i <= idx && current != NULL; i++) { + if (i == idx) { + ret = current; + break; + } + current = current->next; + } + return ret; +} -#ifndef NO_CERTS -/* used to be defined on NO_FILESYSTEM only, but are generally useful */ - int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx, - const unsigned char* in, - long sz, int format, int userChain, - word32 flags) - { - int verify; - int ret = WOLFSSL_FAILURE; +#endif /* OPENSSL_EXTRA */ - WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex"); +#ifdef OPENSSL_EXTRA - verify = GET_VERIFY_SETTING_CTX(ctx); - if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) - verify = VERIFY_SKIP_DATE; +#if defined(OPENSSL_ALL) - if (format == WOLFSSL_FILETYPE_PEM) - ret = ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL, - verify); - else - ret = ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL, - userChain, verify); -#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) - if (ret == WOLFSSL_SUCCESS) - ret = wolfSSL_CTX_trust_peer_buffer(ctx, in, sz, format); -#endif +void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data) +{ + unsigned long hash; - WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret); - return ret; - } + WOLFSSL_ENTER("wolfSSL_lh_retrieve"); - /* wolfSSL extension allows DER files to be loaded from buffers as well */ - int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, - const unsigned char* in, - long sz, int format) - { - return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0, - WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); + if (!sk || !data) { + WOLFSSL_MSG("Bad parameters"); + return NULL; } - int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx, - const unsigned char* in, - long sz, int format) - { - return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1, - WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); + if (!sk->hash_fn) { + WOLFSSL_MSG("No hash function defined"); + return NULL; } + hash = sk->hash_fn(data); -#ifdef WOLFSSL_TRUST_PEER_CERT - int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, - const unsigned char* in, - long sz, int format) - { - int verify; - WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer"); - - /* sanity check on arguments */ - if (sz < 0 || in == NULL || ctx == NULL) { - return BAD_FUNC_ARG; + while (sk) { + /* Calc hash if not done so yet */ + if (!sk->hash) { + switch (sk->type) { + case STACK_TYPE_CIPHER: + sk->hash = sk->hash_fn(&sk->data.cipher); + break; + case STACK_TYPE_X509: + case STACK_TYPE_GEN_NAME: + case STACK_TYPE_BIO: + case STACK_TYPE_OBJ: + case STACK_TYPE_STRING: + case STACK_TYPE_ACCESS_DESCRIPTION: + case STACK_TYPE_X509_EXT: + case STACK_TYPE_X509_REQ_ATTR: + case STACK_TYPE_NULL: + case STACK_TYPE_X509_NAME: + case STACK_TYPE_X509_NAME_ENTRY: + case STACK_TYPE_CONF_VALUE: + case STACK_TYPE_X509_INFO: + case STACK_TYPE_BY_DIR_entry: + case STACK_TYPE_BY_DIR_hash: + case STACK_TYPE_X509_OBJ: + case STACK_TYPE_DIST_POINT: + case STACK_TYPE_X509_CRL: + default: + sk->hash = sk->hash_fn(sk->data.generic); + break; + } } - - #if (WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) - verify = VERIFY_SKIP_DATE; - #else - verify = GET_VERIFY_SETTING_CTX(ctx); - #endif - - if (format == WOLFSSL_FILETYPE_PEM) - return ProcessChainBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, - NULL, verify); - else - return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL, - NULL, 0, verify); + if (sk->hash == hash) { + switch (sk->type) { + case STACK_TYPE_CIPHER: + return &sk->data.cipher; + case STACK_TYPE_X509: + case STACK_TYPE_GEN_NAME: + case STACK_TYPE_BIO: + case STACK_TYPE_OBJ: + case STACK_TYPE_STRING: + case STACK_TYPE_ACCESS_DESCRIPTION: + case STACK_TYPE_X509_EXT: + case STACK_TYPE_X509_REQ_ATTR: + case STACK_TYPE_NULL: + case STACK_TYPE_X509_NAME: + case STACK_TYPE_X509_NAME_ENTRY: + case STACK_TYPE_CONF_VALUE: + case STACK_TYPE_X509_INFO: + case STACK_TYPE_BY_DIR_entry: + case STACK_TYPE_BY_DIR_hash: + case STACK_TYPE_X509_OBJ: + case STACK_TYPE_DIST_POINT: + case STACK_TYPE_X509_CRL: + default: + return sk->data.generic; + } + } + sk = sk->next; } -#endif /* WOLFSSL_TRUST_PEER_CERT */ - - int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx, - const unsigned char* in, long sz, int format) - { - int ret = WOLFSSL_FAILURE; - - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer"); - ret = ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0, - GET_VERIFY_SETTING_CTX(ctx)); - WOLFSSL_LEAVE("wolfSSL_CTX_use_certificate_buffer", ret); - return ret; - } + return NULL; +} +#endif /* OPENSSL_ALL */ - int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx, - const unsigned char* in, long sz, int format) - { - int ret = WOLFSSL_FAILURE; +#endif /* OPENSSL_EXTRA */ - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer"); - ret = ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, NULL, - 0, GET_VERIFY_SETTING_CTX(ctx)); - WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_buffer", ret); - return ret; +/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function + KEEP_OUR_CERT is to insure ability for returning ssl certificate */ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(KEEP_OUR_CERT) +WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; } -#ifdef WOLF_PRIVATE_KEY_ID - int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id, - long sz, int devId, long keySz) - { - int ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId); - - if (ret == WOLFSSL_SUCCESS) - ctx->privateKeySz = (word32)keySz; - - return ret; + if (ssl->buffers.weOwnCert) { + if (ssl->ourCert == NULL) { + if (ssl->buffers.certificate == NULL) { + WOLFSSL_MSG("Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ssl->ourCert = wolfSSL_X509_d2i_ex(NULL, + ssl->buffers.certificate->buffer, + ssl->buffers.certificate->length, + ssl->heap); + #endif + } + return ssl->ourCert; } - - int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id, - long sz, int devId) - { - int ret = WOLFSSL_FAILURE; - - FreeDer(&ctx->privateKey); - if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE, - ctx->heap) == 0) { - XMEMCPY(ctx->privateKey->buffer, id, sz); - ctx->privateKeyId = 1; - if (devId != INVALID_DEVID) - ctx->privateKeyDevId = devId; - else - ctx->privateKeyDevId = ctx->devId; - - ret = WOLFSSL_SUCCESS; + else { /* if cert not owned get parent ctx cert or return null */ + if (ssl->ctx) { + if (ssl->ctx->ourCert == NULL) { + if (ssl->ctx->certificate == NULL) { + WOLFSSL_MSG("Ctx Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ssl->ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, + ssl->ctx->certificate->buffer, + ssl->ctx->certificate->length, + ssl->heap); + #endif + ssl->ctx->ownOurCert = 1; + } + return ssl->ctx->ourCert; } - - return ret; } - int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label, - int devId) - { - int ret = WOLFSSL_FAILURE; - word32 sz = (word32)XSTRLEN(label) + 1; - - FreeDer(&ctx->privateKey); - if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE, - ctx->heap) == 0) { - XMEMCPY(ctx->privateKey->buffer, label, sz); - ctx->privateKeyLabel = 1; - if (devId != INVALID_DEVID) - ctx->privateKeyDevId = devId; - else - ctx->privateKeyDevId = ctx->devId; + return NULL; +} - ret = WOLFSSL_SUCCESS; +WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx) +{ + if (ctx) { + if (ctx->ourCert == NULL) { + if (ctx->certificate == NULL) { + WOLFSSL_MSG("Ctx Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, + ctx->certificate->buffer, + ctx->certificate->length, ctx->heap); + #endif + ctx->ownOurCert = 1; } - - return ret; + return ctx->ourCert; } -#endif /* WOLF_PRIVATE_KEY_ID */ + return NULL; +} +#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ +#endif /* NO_CERTS */ - int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx, - const unsigned char* in, long sz, int format) - { - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format"); - return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1, - GET_VERIFY_SETTING_CTX(ctx)); +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +void wolfSSL_set_connect_state(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_set_connect_state"); + if (ssl == NULL) { + WOLFSSL_MSG("WOLFSSL struct pointer passed in was null"); + return; } - int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx, - const unsigned char* in, long sz) - { - return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz, - WOLFSSL_FILETYPE_PEM); + #ifndef NO_DH + /* client creates its own DH parameters on handshake */ + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + 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_PUBLIC_KEY); } + ssl->buffers.serverDH_G.buffer = NULL; + #endif + if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error initializing client side"); + } +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ -#ifndef NO_DH - /* server wrapper for ctx or ssl Diffie-Hellman parameters */ - static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - const unsigned char* buf, - long sz, int format) - { - DerBuffer* der = NULL; - int ret = 0; - word32 pSz = MAX_DH_SIZE; - word32 gSz = MAX_DH_SIZE; - #ifdef WOLFSSL_SMALL_STACK - byte* p = NULL; - byte* g = NULL; - #else - byte p[MAX_DH_SIZE]; - byte g[MAX_DH_SIZE]; - #endif +int wolfSSL_get_shutdown(const WOLFSSL* ssl) +{ + int isShutdown = 0; - if (ctx == NULL || buf == NULL) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_get_shutdown"); - ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap); - if (ret != 0) { - return ret; + if (ssl) { +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + if (ssl->options.shutdownDone) { + /* The SSL object was possibly cleared with wolfSSL_clear after + * a successful shutdown. Simulate a response for a full + * bidirectional shutdown. */ + isShutdown = WOLFSSL_SENT_SHUTDOWN | WOLFSSL_RECEIVED_SHUTDOWN; } - der->buffer = (byte*)buf; - der->length = (word32)sz; - - #ifdef WOLFSSL_SMALL_STACK - p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - - if (p == NULL || g == NULL) { - XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - return MEMORY_E; + else +#endif + { + /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * + * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ + if (ssl->options.sentNotify) + isShutdown |= WOLFSSL_SENT_SHUTDOWN; + if (ssl->options.closeNotify||ssl->options.connReset) + isShutdown |= WOLFSSL_RECEIVED_SHUTDOWN; } - #endif - if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM) - ret = WOLFSSL_BAD_FILETYPE; - else { - if (format == WOLFSSL_FILETYPE_PEM) { -#ifdef WOLFSSL_PEM_TO_DER - FreeDer(&der); - ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, - NULL, NULL); - if (ret < 0) { - /* Also try X9.42 format */ - ret = PemToDer(buf, sz, X942_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 /* WOLFSSL_WPAS */ -#else - ret = NOT_COMPILED_IN; -#endif /* WOLFSSL_PEM_TO_DER */ - } - - if (ret == 0) { - if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) - ret = WOLFSSL_BAD_FILETYPE; - else if (ssl) - ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); - else - ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); - } - } - - FreeDer(&der); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - #endif - - return ret; } + WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown); + return isShutdown; +} - /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ - int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz, - int format) - { - if (ssl == NULL) - return BAD_FUNC_ARG; - return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format); +int wolfSSL_session_reused(WOLFSSL* ssl) +{ + int resuming = 0; + WOLFSSL_ENTER("wolfSSL_session_reused"); + if (ssl) { +#ifndef HAVE_SECURE_RENEGOTIATION + resuming = ssl->options.resuming; +#else + resuming = ssl->options.resuming || ssl->options.resumed; +#endif } + WOLFSSL_LEAVE("wolfSSL_session_reused", resuming); + return resuming; +} +/* helper function that takes in a protocol version struct and returns string */ +static const char* wolfSSL_internal_get_version(const ProtocolVersion* version) +{ + WOLFSSL_ENTER("wolfSSL_get_version"); - /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ - int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf, - long sz, int format) - { - return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format); + if (version == NULL) { + return "Bad arg"; } -#endif /* NO_DH */ - + if (version->major == SSLv3_MAJOR) { + switch (version->minor) { + case SSLv3_MINOR : + return "SSLv3"; + case TLSv1_MINOR : + return "TLSv1"; + case TLSv1_1_MINOR : + return "TLSv1.1"; + case TLSv1_2_MINOR : + return "TLSv1.2"; + case TLSv1_3_MINOR : + return "TLSv1.3"; + default: + return "unknown"; + } + } +#ifdef WOLFSSL_DTLS + else if (version->major == DTLS_MAJOR) { + switch (version->minor) { + case DTLS_MINOR : + return "DTLS"; + case DTLSv1_2_MINOR : + return "DTLSv1.2"; + case DTLSv1_3_MINOR : + return "DTLSv1.3"; + default: + return "unknown"; + } + } +#endif /* WOLFSSL_DTLS */ + return "unknown"; +} - int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, - const unsigned char* in, long sz, int format) - { - WOLFSSL_ENTER("wolfSSL_use_certificate_buffer"); - if (ssl == NULL) - return BAD_FUNC_ARG; - return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0, - GET_VERIFY_SETTING_SSL(ssl)); +const char* wolfSSL_get_version(const WOLFSSL* ssl) +{ + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument"); + return "unknown"; } + return wolfSSL_internal_get_version(&ssl->version); +} - int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl, - const unsigned char* in, long sz, int format) - { - WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer"); - if (ssl == NULL) - return BAD_FUNC_ARG; - - return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, - ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl)); - } -#ifdef WOLF_PRIVATE_KEY_ID - int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id, - long sz, int devId, long keySz) - { - int ret = wolfSSL_use_PrivateKey_Id(ssl, id, sz, devId); +/* current library version */ +const char* wolfSSL_lib_version(void) +{ + return LIBWOLFSSL_VERSION_STRING; +} - if (ret == WOLFSSL_SUCCESS) - ssl->buffers.keySz = (word32)keySz; +#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +const char* wolfSSL_OpenSSL_version(int a) +{ + (void)a; + return "wolfSSL " LIBWOLFSSL_VERSION_STRING; +} +#else +const char* wolfSSL_OpenSSL_version(void) +{ + return "wolfSSL " LIBWOLFSSL_VERSION_STRING; +} +#endif /* WOLFSSL_QT */ +#endif - return ret; - } - int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, - long sz, int devId) - { - int ret = WOLFSSL_FAILURE; +/* current library version in hex */ +word32 wolfSSL_lib_version_hex(void) +{ + return LIBWOLFSSL_VERSION_HEX; +} - if (ssl->buffers.weOwnKey) - FreeDer(&ssl->buffers.key); - if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE, - ssl->heap) == 0) { - XMEMCPY(ssl->buffers.key->buffer, id, sz); - ssl->buffers.weOwnKey = 1; - ssl->buffers.keyId = 1; - if (devId != INVALID_DEVID) - ssl->buffers.keyDevId = devId; - else - ssl->buffers.keyDevId = ssl->devId; - ret = WOLFSSL_SUCCESS; - } +int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_current_cipher_suite"); + if (ssl) + return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite; + return 0; +} - return ret; +WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_current_cipher"); + if (ssl) { + ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0; + ssl->cipher.cipherSuite = ssl->options.cipherSuite; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + ssl->cipher.bits = ssl->specs.key_size * 8; +#endif + return &ssl->cipher; } + else + return NULL; +} - int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId) - { - int ret = WOLFSSL_FAILURE; - word32 sz = (word32)XSTRLEN(label) + 1; - - if (ssl->buffers.weOwnKey) - FreeDer(&ssl->buffers.key); - if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE, - ssl->heap) == 0) { - XMEMCPY(ssl->buffers.key->buffer, label, sz); - ssl->buffers.weOwnKey = 1; - ssl->buffers.keyLabel = 1; - if (devId != INVALID_DEVID) - ssl->buffers.keyDevId = devId; - else - ssl->buffers.keyDevId = ssl->devId; - ret = WOLFSSL_SUCCESS; - } +const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_CIPHER_get_name"); - return ret; + if (cipher == NULL) { + return NULL; } -#endif /* WOLF_PRIVATE_KEY_ID */ - int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl, - const unsigned char* in, long sz, int format) - { - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); - if (ssl == NULL) - return BAD_FUNC_ARG; + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ + !defined(WOLFSSL_QT) + return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite); + #else + return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0, + cipher->cipherSuite); + #endif +} - return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, - ssl, NULL, 1, GET_VERIFY_SETTING_SSL(ssl)); - } +const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_CIPHER_get_version"); - int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, - const unsigned char* in, long sz) - { - return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz, - WOLFSSL_FILETYPE_PEM); + if (cipher == NULL || cipher->ssl == NULL) { + return NULL; } + return wolfSSL_get_version(cipher->ssl); +} - /* unload any certs or keys that SSL owns, leave CTX as is - WOLFSSL_SUCCESS on ok */ - int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl) - { - if (ssl == NULL) { - WOLFSSL_MSG("Null function arg"); - return BAD_FUNC_ARG; - } +const char* wolfSSL_get_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_cipher"); + return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); +} - if (ssl->buffers.weOwnCert && !ssl->keepCert) { - WOLFSSL_MSG("Unloading cert"); - FreeDer(&ssl->buffers.certificate); - #ifdef KEEP_OUR_CERT - wolfSSL_X509_free(ssl->ourCert); - ssl->ourCert = NULL; - #endif - ssl->buffers.weOwnCert = 0; - } +/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */ +const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) +{ + /* get access to cipher_name_idx in internal.c */ + return wolfSSL_get_cipher_name_internal(ssl); +} - if (ssl->buffers.weOwnCertChain) { - WOLFSSL_MSG("Unloading cert chain"); - FreeDer(&ssl->buffers.certChain); - ssl->buffers.weOwnCertChain = 0; - } +const char* wolfSSL_get_cipher_name_from_suite(byte cipherSuite0, + byte cipherSuite) +{ + return GetCipherNameInternal(cipherSuite0, cipherSuite); +} - if (ssl->buffers.weOwnKey) { - WOLFSSL_MSG("Unloading key"); - ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); - FreeDer(&ssl->buffers.key); - ssl->buffers.weOwnKey = 0; - } +const char* wolfSSL_get_cipher_name_iana_from_suite(byte cipherSuite0, + byte cipherSuite) +{ + return GetCipherNameIana(cipherSuite0, cipherSuite); +} -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (ssl->buffers.weOwnAltKey) { - WOLFSSL_MSG("Unloading alt key"); - ForceZero(ssl->buffers.altKey->buffer, ssl->buffers.altKey->length); - FreeDer(&ssl->buffers.altKey); - ssl->buffers.weOwnAltKey = 0; - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ +int wolfSSL_get_cipher_suite_from_name(const char* name, byte* cipherSuite0, + byte* cipherSuite, int *flags) { + if ((name == NULL) || + (cipherSuite0 == NULL) || + (cipherSuite == NULL) || + (flags == NULL)) + return BAD_FUNC_ARG; + return GetCipherSuiteFromName(name, cipherSuite0, cipherSuite, flags); +} - return WOLFSSL_SUCCESS; - } +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +/* Creates and returns a new WOLFSSL_CIPHER stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_cipher(void) +{ + WOLFSSL_STACK* sk; + WOLFSSL_ENTER("wolfSSL_sk_new_cipher"); - int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs"); + sk = wolfSSL_sk_new_null(); + if (sk == NULL) + return NULL; + sk->type = STACK_TYPE_CIPHER; - if (ctx == NULL) - return BAD_FUNC_ARG; + return sk; +} - return wolfSSL_CertManagerUnloadCAs(ctx->cm); - } +/* return 1 on success 0 on fail */ +int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, + WOLFSSL_CIPHER* cipher) +{ + return wolfSSL_sk_push(sk, cipher); +} - int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts"); +#ifndef NO_WOLFSSL_STUB +WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +{ + WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop"); + (void)sk; + return NULL; +} +#endif /* NO_WOLFSSL_STUB */ +#endif /* WOLFSSL_QT || OPENSSL_ALL */ - if (ctx == NULL) - return BAD_FUNC_ARG; +word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher) +{ + word16 cipher_id = 0; - if (ctx->ref.count > 1) { - WOLFSSL_MSG("ctx object must have a ref count of 1 before " - "unloading intermediate certs"); - return BAD_STATE_E; - } + WOLFSSL_ENTER("wolfSSL_CIPHER_get_id"); - return wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm); + if (cipher && cipher->ssl) { + cipher_id = (cipher->ssl->options.cipherSuite0 << 8) | + cipher->ssl->options.cipherSuite; } + return cipher_id; +} -#ifdef WOLFSSL_TRUST_PEER_CERT - int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); - - if (ctx == NULL) - return BAD_FUNC_ARG; +const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value) +{ + const WOLFSSL_CIPHER* cipher = NULL; + byte cipherSuite0, cipherSuite; + WOLFSSL_ENTER("wolfSSL_get_cipher_by_value"); - return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); - } + /* extract cipher id information */ + cipherSuite = (value & 0xFF); + cipherSuite0 = ((value >> 8) & 0xFF); -#ifdef WOLFSSL_LOCAL_X509_STORE - int wolfSSL_Unload_trust_peers(WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + /* TODO: lookup by cipherSuite0 / cipherSuite */ + (void)cipherSuite0; + (void)cipherSuite; - if (ssl == NULL) - return BAD_FUNC_ARG; + return cipher; +} - SSL_CM_WARNING(ssl); - return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl)); - } -#endif /* WOLFSSL_LOCAL_X509_STORE */ -#endif /* WOLFSSL_TRUST_PEER_CERT */ -/* old NO_FILESYSTEM end */ -#endif /* !NO_CERTS */ +#if defined(OPENSSL_EXTRA) +/* Free the structure for WOLFSSL_CIPHER stack + * + * sk stack to free nodes in + */ +void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free"); -#ifdef OPENSSL_EXTRA + wolfSSL_sk_free(sk); +} +#endif /* OPENSSL_ALL */ - int wolfSSL_add_all_algorithms(void) - { - WOLFSSL_ENTER("wolfSSL_add_all_algorithms"); - if (initRefCount != 0 || wolfSSL_Init() == WOLFSSL_SUCCESS) - return WOLFSSL_SUCCESS; - else - return WOLFSSL_FATAL_ERROR; +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ + !defined(NO_DH) +#ifdef HAVE_FFDHE +static const char* wolfssl_ffdhe_name(word16 group) +{ + const char* str = NULL; + switch (group) { + case WOLFSSL_FFDHE_2048: + str = "FFDHE_2048"; + break; + case WOLFSSL_FFDHE_3072: + str = "FFDHE_3072"; + break; + case WOLFSSL_FFDHE_4096: + str = "FFDHE_4096"; + break; + case WOLFSSL_FFDHE_6144: + str = "FFDHE_6144"; + break; + case WOLFSSL_FFDHE_8192: + str = "FFDHE_8192"; + break; + default: + break; } + return str; +} +#endif +/* 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) +{ + const char* cName = NULL; - int wolfSSL_OpenSSL_add_all_algorithms_noconf(void) - { - WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf"); - - if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) - return WOLFSSL_FATAL_ERROR; - - return WOLFSSL_SUCCESS; - } + WOLFSSL_ENTER("wolfSSL_get_curve_name"); - int wolfSSL_OpenSSL_add_all_algorithms_conf(void) - { - WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_conf"); - /* This function is currently the same as - wolfSSL_OpenSSL_add_all_algorithms_noconf since we do not employ - the use of a wolfssl.cnf type configuration file and is only used for - OpenSSL compatibility. */ + if (ssl == NULL) + return NULL; - if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) { - return WOLFSSL_FATAL_ERROR; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_KYBER) + /* Check for post-quantum groups. Return now because we do not want the ECC + * check to override this result in the case of a hybrid. */ + if (IsAtLeastTLSv1_3(ssl->version)) { + switch (ssl->namedGroup) { +#ifdef HAVE_LIBOQS + case WOLFSSL_KYBER_LEVEL1: + return "KYBER_LEVEL1"; + case WOLFSSL_KYBER_LEVEL3: + return "KYBER_LEVEL3"; + case WOLFSSL_KYBER_LEVEL5: + return "KYBER_LEVEL5"; + case WOLFSSL_P256_KYBER_LEVEL1: + return "P256_KYBER_LEVEL1"; + case WOLFSSL_P384_KYBER_LEVEL3: + return "P384_KYBER_LEVEL3"; + case WOLFSSL_P521_KYBER_LEVEL5: + return "P521_KYBER_LEVEL5"; +#elif defined(HAVE_PQM4) + case WOLFSSL_KYBER_LEVEL1: + return "KYBER_LEVEL1"; +#elif defined(WOLFSSL_WC_KYBER) + #ifdef WOLFSSL_KYBER512 + case WOLFSSL_KYBER_LEVEL1: + return "KYBER_LEVEL1"; + case WOLFSSL_P256_KYBER_LEVEL1: + return "P256_KYBER_LEVEL1"; + #endif + #ifdef WOLFSSL_KYBER768 + case WOLFSSL_KYBER_LEVEL3: + return "KYBER_LEVEL3"; + case WOLFSSL_P384_KYBER_LEVEL3: + return "P384_KYBER_LEVEL3"; + #endif + #ifdef WOLFSSL_KYBER1024 + case WOLFSSL_KYBER_LEVEL5: + return "KYBER_LEVEL5"; + case WOLFSSL_P521_KYBER_LEVEL5: + return "P521_KYBER_LEVEL5"; + #endif +#endif } - return WOLFSSL_SUCCESS; } +#endif /* WOLFSSL_TLS13 && WOLFSSL_HAVE_KYBER */ - /* 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; - WOLFSSL_MSG("session cache is set at compile time"); - #ifndef NO_SESSION_CACHE - return (long)(SESSIONS_PER_ROW * SESSION_ROWS); - #else - return 0; - #endif +#ifdef HAVE_FFDHE + if (ssl->namedGroup != 0) { + cName = wolfssl_ffdhe_name(ssl->namedGroup); } - #endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) - void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown"); - if (mode) - ctx->quietShutdown = 1; +#ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) { + cName = "X25519"; } +#endif - - void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode) - { - WOLFSSL_ENTER("wolfSSL_set_quiet_shutdown"); - if (mode) - ssl->options.quietShutdown = 1; +#ifdef HAVE_CURVE448 + if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) { + cName = "X448"; } -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || - WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#endif -#ifdef OPENSSL_EXTRA -#ifndef NO_BIO - void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) - { - WOLFSSL_ENTER("wolfSSL_set_bio"); +#ifdef HAVE_ECC + if (ssl->ecdhCurveOID != 0 && cName == NULL) { + cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, + NULL)); + } +#endif - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument, ssl was NULL"); - return; - } + return cName; +} +#endif - /* free any existing WOLFSSL_BIOs in use but don't free those in - * a chain */ - if (ssl->biord != NULL) { - if (ssl->biord != ssl->biowr) { - if (ssl->biowr != NULL && ssl->biowr->prev != NULL) - wolfSSL_BIO_free(ssl->biowr); - ssl->biowr = NULL; - } - if (ssl->biord->prev != NULL) - wolfSSL_BIO_free(ssl->biord); - ssl->biord = NULL; - } - /* set flag obviously */ - if (rd && !(rd->flags & WOLFSSL_BIO_FLAG_READ)) - rd->flags |= WOLFSSL_BIO_FLAG_READ; - if (wr && !(wr->flags & WOLFSSL_BIO_FLAG_WRITE)) - wr->flags |= WOLFSSL_BIO_FLAG_WRITE; - - ssl->biord = rd; - ssl->biowr = wr; +#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +/* return authentication NID corresponding to cipher suite + * @param cipher a pointer to WOLFSSL_CIPHER + * return NID if found, NID_undef if not found + */ +int wolfSSL_CIPHER_get_auth_nid(const WOLFSSL_CIPHER* cipher) +{ + static const struct authnid { + const char* alg_name; + const int nid; + } authnid_tbl[] = { + {"RSA", NID_auth_rsa}, + {"PSK", NID_auth_psk}, + {"SRP", NID_auth_srp}, + {"ECDSA", NID_auth_ecdsa}, + {"None", NID_auth_null}, + {NULL, NID_undef} + }; - /* set SSL to use BIO callbacks instead */ - if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0)) { - ssl->CBIORecv = BioReceive; - } - if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0)) { - ssl->CBIOSend = BioSend; - } + const char* authStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - /* User programs should always retry reading from these BIOs */ - if (rd) { - /* User writes to rd */ - BIO_set_retry_write(rd); - } - if (wr) { - /* User reads from wr */ - BIO_set_retry_read(wr); - } + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } -#endif /* !NO_BIO */ -#endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) - void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, - WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list"); - if (ctx != NULL) { - wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL); - ctx->client_ca_names = names; + authStr = GetCipherAuthStr(n); + + if (authStr != NULL) { + const struct authnid* sa; + for(sa = authnid_tbl; sa->alg_name != NULL; sa++) { + if (XSTRCMP(sa->alg_name, authStr) == 0) { + return sa->nid; + } } } - void wolfSSL_set_client_CA_list(WOLFSSL* ssl, - WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) - { - WOLFSSL_ENTER("wolfSSL_set_client_CA_list"); - if (ssl != NULL) { - if (ssl->client_ca_names != ssl->ctx->client_ca_names) - wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL); - ssl->client_ca_names = names; - } + return NID_undef; +} +/* return cipher NID corresponding to cipher suite + * @param cipher a pointer to WOLFSSL_CIPHER + * return NID if found, NID_undef if not found + */ +int wolfSSL_CIPHER_get_cipher_nid(const WOLFSSL_CIPHER* cipher) +{ + static const struct ciphernid { + const char* alg_name; + const int nid; + } ciphernid_tbl[] = { + {"AESGCM(256)", NID_aes_256_gcm}, + {"AESGCM(128)", NID_aes_128_gcm}, + {"AESCCM(128)", NID_aes_128_ccm}, + {"AES(128)", NID_aes_128_cbc}, + {"AES(256)", NID_aes_256_cbc}, + {"CAMELLIA(256)", NID_camellia_256_cbc}, + {"CAMELLIA(128)", NID_camellia_128_cbc}, + {"RC4", NID_rc4}, + {"3DES", NID_des_ede3_cbc}, + {"CHACHA20/POLY1305(256)", NID_chacha20_poly1305}, + {"None", NID_undef}, + {NULL, NID_undef} + }; + + const char* encStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + + WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid"); + + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } - #ifdef OPENSSL_EXTRA - /* registers client cert callback, called during handshake if server - requests client auth but user has not loaded client cert/key */ - void wolfSSL_CTX_set_client_cert_cb(WOLFSSL_CTX *ctx, client_cert_cb cb) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_client_cert_cb"); + encStr = GetCipherEncStr(n); - if (ctx != NULL) { - ctx->CBClientCert = cb; + if (encStr != NULL) { + const struct ciphernid* c; + for(c = ciphernid_tbl; c->alg_name != NULL; c++) { + if (XSTRCMP(c->alg_name, encStr) == 0) { + return c->nid; + } } } - void wolfSSL_CTX_set_cert_cb(WOLFSSL_CTX* ctx, - CertSetupCallback cb, void *arg) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_cert_cb"); - if (ctx == NULL) - return; + return NID_undef; +} +/* return digest NID corresponding to cipher suite + * @param cipher a pointer to WOLFSSL_CIPHER + * return NID if found, NID_undef if not found + */ +int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher) +{ + static const struct macnid { + const char* alg_name; + const int nid; + } macnid_tbl[] = { + {"SHA1", NID_sha1}, + {"SHA256", NID_sha256}, + {"SHA384", NID_sha384}, + {NULL, NID_undef} + }; - ctx->certSetupCb = cb; - ctx->certSetupCbArg = arg; + const char* name; + const char* macStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + (void)name; + + WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid"); + + if ((name = GetCipherSegment(cipher, n)) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } - int wolfSSL_get_client_suites_sigalgs(const WOLFSSL* ssl, - const byte** suites, word16* suiteSz, - const byte** hashSigAlgo, word16* hashSigAlgoSz) - { - WOLFSSL_ENTER("wolfSSL_get_client_suites_sigalgs"); + /* in MD5 case, NID will be NID_md5 */ + if (XSTRSTR(name, "MD5") != NULL) { + return NID_md5; + } - if (suites != NULL) - *suites = NULL; - if (suiteSz != NULL) - *suiteSz = 0; - if (hashSigAlgo != NULL) - *hashSigAlgo = NULL; - if (hashSigAlgoSz != NULL) - *hashSigAlgoSz = 0; + macStr = GetCipherMacStr(n); - if (ssl != NULL && ssl->clSuites != NULL) { - if (suites != NULL && suiteSz != NULL) { - *suites = ssl->clSuites->suites; - *suiteSz = ssl->clSuites->suiteSz; - } - if (hashSigAlgo != NULL && hashSigAlgoSz != NULL) { - *hashSigAlgo = ssl->clSuites->hashSigAlgo; - *hashSigAlgoSz = ssl->clSuites->hashSigAlgoSz; + if (macStr != NULL) { + const struct macnid* mc; + for(mc = macnid_tbl; mc->alg_name != NULL; mc++) { + if (XSTRCMP(mc->alg_name, macStr) == 0) { + return mc->nid; } - return WOLFSSL_SUCCESS; } - return WOLFSSL_FAILURE; - } - WOLFSSL_CIPHERSUITE_INFO wolfSSL_get_ciphersuite_info(byte first, - byte second) - { - WOLFSSL_CIPHERSUITE_INFO info; - info.rsaAuth = (byte)(CipherRequires(first, second, REQUIRES_RSA) || - CipherRequires(first, second, REQUIRES_RSA_SIG)); - info.eccAuth = (byte)(CipherRequires(first, second, REQUIRES_ECC) || - /* Static ECC ciphers may require RSA for authentication */ - (CipherRequires(first, second, REQUIRES_ECC_STATIC) && - !CipherRequires(first, second, REQUIRES_RSA_SIG))); - info.eccStatic = - (byte)CipherRequires(first, second, REQUIRES_ECC_STATIC); - info.psk = (byte)CipherRequires(first, second, REQUIRES_PSK); - return info; } - /** - * @param first First byte of the hash and signature algorithm - * @param second Second byte of the hash and signature algorithm - * @param hashAlgo The enum wc_HashType of the MAC algorithm - * @param sigAlgo The enum Key_Sum of the authentication algorithm - */ - int wolfSSL_get_sigalg_info(byte first, byte second, - int* hashAlgo, int* sigAlgo) - { - byte input[2]; - byte hashType; - byte sigType; + return NID_undef; +} +/* return key exchange NID corresponding to cipher suite + * @param cipher a pointer to WOLFSSL_CIPHER + * return NID if found, NID_undef if not found + */ +int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher) +{ + static const struct kxnid { + const char* name; + const int nid; + } kxnid_table[] = { + {"ECDHEPSK", NID_kx_ecdhe_psk}, + {"ECDH", NID_kx_ecdhe}, + {"DHEPSK", NID_kx_dhe_psk}, + {"DH", NID_kx_dhe}, + {"RSAPSK", NID_kx_rsa_psk}, + {"SRP", NID_kx_srp}, + {"EDH", NID_kx_dhe}, + {"RSA", NID_kx_rsa}, + {NULL, NID_undef} + }; - if (hashAlgo == NULL || sigAlgo == NULL) - return BAD_FUNC_ARG; + const char* keaStr; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - input[0] = first; - input[1] = second; - DecodeSigAlg(input, &hashType, &sigType); + WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid"); - /* cast so that compiler reminds us of unimplemented values */ - switch ((enum SignatureAlgorithm)sigType) { - case anonymous_sa_algo: - *sigAlgo = ANONk; - break; - case rsa_sa_algo: - *sigAlgo = RSAk; - break; - case dsa_sa_algo: - *sigAlgo = DSAk; - break; - case ecc_dsa_sa_algo: - *sigAlgo = ECDSAk; - break; - case rsa_pss_sa_algo: - *sigAlgo = RSAPSSk; - break; - case ed25519_sa_algo: - *sigAlgo = ED25519k; - break; - case rsa_pss_pss_algo: - *sigAlgo = RSAPSSk; - break; - case ed448_sa_algo: - *sigAlgo = ED448k; - break; - case falcon_level1_sa_algo: - *sigAlgo = FALCON_LEVEL1k; - break; - case falcon_level5_sa_algo: - *sigAlgo = FALCON_LEVEL5k; - break; - case dilithium_level2_sa_algo: - *sigAlgo = DILITHIUM_LEVEL2k; - break; - case dilithium_level3_sa_algo: - *sigAlgo = DILITHIUM_LEVEL3k; - break; - case dilithium_level5_sa_algo: - *sigAlgo = DILITHIUM_LEVEL5k; - break; - case sm2_sa_algo: - *sigAlgo = SM2k; - break; - case invalid_sa_algo: - default: - *hashAlgo = WC_HASH_TYPE_NONE; - *sigAlgo = 0; - return BAD_FUNC_ARG; - } - - /* cast so that compiler reminds us of unimplemented values */ - switch((enum wc_MACAlgorithm)hashType) { - case no_mac: - case rmd_mac: /* Don't have a RIPEMD type in wc_HashType */ - *hashAlgo = WC_HASH_TYPE_NONE; - break; - case md5_mac: - *hashAlgo = WC_HASH_TYPE_MD5; - break; - case sha_mac: - *hashAlgo = WC_HASH_TYPE_SHA; - break; - case sha224_mac: - *hashAlgo = WC_HASH_TYPE_SHA224; - break; - case sha256_mac: - *hashAlgo = WC_HASH_TYPE_SHA256; - break; - case sha384_mac: - *hashAlgo = WC_HASH_TYPE_SHA384; - break; - case sha512_mac: - *hashAlgo = WC_HASH_TYPE_SHA512; - break; - case blake2b_mac: - *hashAlgo = WC_HASH_TYPE_BLAKE2B; - break; - case sm3_mac: -#ifdef WOLFSSL_SM3 - *hashAlgo = WC_HASH_TYPE_SM3; -#else - *hashAlgo = WC_HASH_TYPE_NONE; -#endif - break; - default: - *hashAlgo = WC_HASH_TYPE_NONE; - *sigAlgo = 0; - return BAD_FUNC_ARG; - } - return 0; + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } - /** - * Internal wrapper for calling certSetupCb - * @param ssl The SSL/TLS Object - * @return 0 on success - */ - int CertSetupCbWrapper(WOLFSSL* ssl) - { - int ret = 0; - if (ssl->ctx->certSetupCb != NULL) { - WOLFSSL_MSG("Calling user cert setup callback"); - ret = ssl->ctx->certSetupCb(ssl, ssl->ctx->certSetupCbArg); - if (ret == 1) { - WOLFSSL_MSG("User cert callback returned success"); - ret = 0; - } - else if (ret == 0) { - SendAlert(ssl, alert_fatal, internal_error); - ret = CLIENT_CERT_CB_ERROR; - } - else if (ret < 0) { - ret = WOLFSSL_ERROR_WANT_X509_LOOKUP; - } - else { - WOLFSSL_MSG("Unexpected user callback return"); - ret = CLIENT_CERT_CB_ERROR; - } - } - return ret; + /* in TLS 1.3 case, NID will be NID_kx_any */ + if (XSTRCMP(n[0], "TLS13") == 0) { + return NID_kx_any; } - #endif /* OPENSSL_EXTRA */ - -#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || HAVE_WEBSERVER */ -#ifndef WOLFSSL_NO_CA_NAMES - WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list( - const WOLFSSL_CTX *ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list"); + keaStr = GetCipherKeaStr(n); - if (ctx == NULL) { - WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list"); - return NULL; + if (keaStr != NULL) { + const struct kxnid* k; + for(k = kxnid_table; k->name != NULL; k++) { + if (XSTRCMP(k->name, keaStr) == 0) { + return k->nid; + } } - - return ctx->client_ca_names; } - /* returns the CA's set on server side or the CA's sent from server when - * on client side */ - WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list( - const WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_get_client_CA_list"); + return NID_undef; +} +/* check if cipher suite is AEAD + * @param cipher a pointer to WOLFSSL_CIPHER + * return 1 if cipher is AEAD, 0 otherwise + */ +int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher) +{ + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list"); - return NULL; - } + WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead"); - return SSL_CA_NAMES(ssl); + if (GetCipherSegment(cipher, n) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return NID_undef; } - #if !defined(NO_CERTS) - int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) - { - WOLFSSL_X509_NAME *nameCopy = NULL; + return IsCipherAEAD(n); +} +/* Creates cipher->description based on cipher->offset + * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added + * to a stack of ciphers. + * @param [in] cipher: A cipher from a stack of ciphers. + * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE + */ +int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher) +{ + int strLen; + unsigned long offset; + char* dp; + const char* name; + const char *keaStr, *authStr, *encStr, *macStr, *protocol; + char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + int len = MAX_DESCRIPTION_SZ-1; + const CipherSuiteInfo* cipher_names; + ProtocolVersion pv; + WOLFSSL_ENTER("wolfSSL_sk_CIPHER_description"); - WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); + if (cipher == NULL) + return WOLFSSL_FAILURE; - if (ctx == NULL || x509 == NULL){ - WOLFSSL_MSG("Bad argument"); - return WOLFSSL_FAILURE; - } + dp = cipher->description; + if (dp == NULL) + return WOLFSSL_FAILURE; - if (ctx->client_ca_names == NULL) { - ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL); - if (ctx->client_ca_names == NULL) { - WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); - return WOLFSSL_FAILURE; - } - } + cipher_names = GetCipherNames(); - nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509)); - if (nameCopy == NULL) { - WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); - return WOLFSSL_FAILURE; - } + offset = cipher->offset; + if (offset >= (unsigned long)GetCipherNamesSize()) + return WOLFSSL_FAILURE; + pv.major = cipher_names[offset].major; + pv.minor = cipher_names[offset].minor; + protocol = wolfSSL_internal_get_version(&pv); - if (wolfSSL_sk_X509_NAME_push(ctx->client_ca_names, nameCopy) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); - wolfSSL_X509_NAME_free(nameCopy); - return WOLFSSL_FAILURE; - } + if ((name = GetCipherSegment(cipher, n)) == NULL) { + WOLFSSL_MSG("no suitable cipher name found"); + return WOLFSSL_FAILURE; + } - return WOLFSSL_SUCCESS; + /* keaStr */ + keaStr = GetCipherKeaStr(n); + /* authStr */ + authStr = GetCipherAuthStr(n); + /* encStr */ + encStr = GetCipherEncStr(n); + if ((cipher->bits = SetCipherBits(encStr)) == WOLFSSL_FAILURE) { + WOLFSSL_MSG("Cipher Bits Not Set."); } - #endif + /* macStr */ + macStr = GetCipherMacStr(n); - #ifndef NO_BIO - #if !defined(NO_RSA) && !defined(NO_CERTS) - WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) - { - /* The webserver build is using this to load a CA into the server - * for client authentication as an option. Have this return NULL in - * that case. If OPENSSL_EXTRA is enabled, go ahead and include - * the function. */ - #ifdef OPENSSL_EXTRA - WOLFSSL_STACK *list = NULL; - WOLFSSL_BIO* bio = NULL; - WOLFSSL_X509 *cert = NULL; - WOLFSSL_X509_NAME *nameCopy = NULL; - unsigned long err = WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + /* Build up the string by copying onto the end. */ + XSTRNCPY(dp, name, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; - bio = wolfSSL_BIO_new_file(fname, "rb"); - if (bio == NULL) { - WOLFSSL_MSG("wolfSSL_BIO_new_file error"); - goto cleanup; - } - - list = wolfSSL_sk_X509_NAME_new(NULL); - if (list == NULL) { - WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error"); - goto cleanup; - } + XSTRNCPY(dp, " ", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; + XSTRNCPY(dp, protocol, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; - /* Read each certificate in the chain out of the file. */ - while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { - /* Need a persistent copy of the subject name. */ - nameCopy = wolfSSL_X509_NAME_dup( - wolfSSL_X509_get_subject_name(cert)); - if (nameCopy == NULL) { - WOLFSSL_MSG("wolfSSL_X509_NAME_dup error"); - goto cleanup; - } - /* - * Original cert will be freed so make sure not to try to access - * it in the future. - */ - nameCopy->x509 = NULL; + XSTRNCPY(dp, " Kx=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; + XSTRNCPY(dp, keaStr, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; - if (wolfSSL_sk_X509_NAME_push(list, nameCopy) != - WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error"); - /* Do free in loop because nameCopy is now responsibility - * of list to free and adding jumps to cleanup after this - * might result in a double free. */ - wolfSSL_X509_NAME_free(nameCopy); - goto cleanup; - } + XSTRNCPY(dp, " Au=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; + XSTRNCPY(dp, authStr, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; - wolfSSL_X509_free(cert); - cert = NULL; - } + XSTRNCPY(dp, " Enc=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; + XSTRNCPY(dp, encStr, len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; - CLEAR_ASN_NO_PEM_HEADER_ERROR(err); + XSTRNCPY(dp, " Mac=", len); + dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); + len -= strLen; dp += strLen; + XSTRNCPY(dp, macStr, len); + dp[len-1] = '\0'; - err = WOLFSSL_SUCCESS; -cleanup: - wolfSSL_X509_free(cert); - wolfSSL_BIO_free(bio); - if (err != WOLFSSL_SUCCESS) { - /* We failed so return NULL */ - wolfSSL_sk_X509_NAME_pop_free(list, NULL); - list = NULL; - } - return list; - #else - (void)fname; - return NULL; - #endif - } - #endif - #endif /* !NO_BIO */ -#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */ + return WOLFSSL_SUCCESS; +} +#endif /* OPENSSL_ALL || WOLFSSL_QT */ -#ifdef OPENSSL_EXTRA +static WC_INLINE const char* wolfssl_kea_to_string(int kea) +{ + const char* keaStr; - #ifdef WOLFSSL_SYS_CA_CERTS - /* - * This is an OpenSSL compatibility layer function, but it doesn't mirror - * the exact functionality of its OpenSSL counterpart. We don't support the - * notion of an "OpenSSL directory". This function will attempt to load the - * environment variables SSL_CERT_DIR and SSL_CERT_FILE, if either are found, - * they will be loaded. Otherwise, it will act as a wrapper around our - * native wolfSSL_CTX_load_system_CA_certs function. This function does - * conform to OpenSSL's return value conventions. - */ - int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) - { - int ret; -#ifdef XGETENV - char* certDir; - char* certFile; - word32 flags; + switch (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_ECC + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; +#endif + default: + keaStr = "unknown"; + break; + } - WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths"); - -#ifdef XGETENV - certDir = XGETENV("SSL_CERT_DIR"); - certFile = XGETENV("SSL_CERT_FILE"); - flags = WOLFSSL_LOAD_FLAG_PEM_CA_ONLY; + return keaStr; +} - if (certDir || certFile) { - if (certDir) { - /* - * We want to keep trying to load more CAs even if one cert in - * the directory is bad and can't be used (e.g. if one is expired), - * so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR. - */ - flags |= WOLFSSL_LOAD_FLAG_IGNORE_ERR; - } +static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo) +{ + const char* authStr; - ret = wolfSSL_CTX_load_verify_locations_ex(ctx, certFile, certDir, - flags); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG_EX("Failed to load CA certs from SSL_CERT_FILE: %s" - " SSL_CERT_DIR: %s. Error: %d", certFile, - certDir, ret); - return WOLFSSL_FAILURE; - } - return ret; - } + switch (sig_algo) { + case anonymous_sa_algo: + authStr = "None"; + break; +#ifndef NO_RSA + case rsa_sa_algo: + authStr = "RSA"; + break; + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + authStr = "RSA-PSS"; + break; + #endif #endif - -#ifdef NO_FILESYSTEM - WOLFSSL_MSG("wolfSSL_CTX_set_default_verify_paths not supported" - " with NO_FILESYSTEM enabled"); - ret = WOLFSSL_FATAL_ERROR; -#else - ret = wolfSSL_CTX_load_system_CA_certs(ctx); - if (ret == WOLFSSL_BAD_PATH) { - /* - * OpenSSL doesn't treat the lack of a system CA cert directory as a - * failure. We do the same here. - */ - ret = WOLFSSL_SUCCESS; - } +#ifndef NO_DSA + case dsa_sa_algo: + authStr = "DSA"; + break; #endif - - WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret); - - return ret; +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + authStr = "ECDSA"; + break; +#endif +#ifdef WOLFSSL_SM2 + case sm2_sa_algo: + authStr = "SM2"; + break; +#endif +#ifdef HAVE_ED25519 + case ed25519_sa_algo: + authStr = "Ed25519"; + break; +#endif +#ifdef HAVE_ED448 + case ed448_sa_algo: + authStr = "Ed448"; + break; +#endif + default: + authStr = "unknown"; + break; } - #endif /* WOLFSSL_SYS_CA_CERTS */ - - #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ - && !defined(WC_NO_RNG) - static const byte srp_N[] = { - 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8, - 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, - 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6, - 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13, - 0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, - 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7, - 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69, - 0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85, - 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC, - 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, - 0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F, - 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3 - }; - static const byte srp_g[] = { - 0x02 - }; - - int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username) - { - int r = 0; - SrpSide srp_side = SRP_CLIENT_SIDE; - byte salt[SRP_SALT_SIZE]; - WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username"); - if (ctx == NULL || ctx->srp == NULL || username==NULL) - return WOLFSSL_FAILURE; + return authStr; +} - if (ctx->method->side == WOLFSSL_SERVER_END){ - srp_side = SRP_SERVER_SIDE; - } else if (ctx->method->side == WOLFSSL_CLIENT_END){ - srp_side = SRP_CLIENT_SIDE; - } else { - WOLFSSL_MSG("Init CTX failed"); - return WOLFSSL_FAILURE; - } +static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size) +{ + const char* encStr; - if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0) { - WOLFSSL_MSG("Init SRP CTX failed"); - XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); - ctx->srp = NULL; - return WOLFSSL_FAILURE; - } - r = wc_SrpSetUsername(ctx->srp, (const byte*)username, - (word32)XSTRLEN(username)); - if (r < 0) { - WOLFSSL_MSG("fail to set srp username."); - return WOLFSSL_FAILURE; - } + (void)key_size; - /* if wolfSSL_CTX_set_srp_password has already been called, */ - /* execute wc_SrpSetPassword here */ - if (ctx->srp_password != NULL) { - WC_RNG rng; - if (wc_InitRng(&rng) < 0){ - WOLFSSL_MSG("wc_InitRng failed"); - return WOLFSSL_FAILURE; - } - XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); - r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0])); - wc_FreeRng(&rng); - if (r < 0) { - WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); - return WOLFSSL_FAILURE; - } + switch (cipher) { + 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 +#ifndef NO_AES + case wolfssl_aes: + if (key_size == 128) + encStr = "AES(128)"; + else if (key_size == 256) + encStr = "AES(256)"; + else + encStr = "AES(?)"; + break; + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (key_size == 128) + encStr = "AESGCM(128)"; + else if (key_size == 256) + encStr = "AESGCM(256)"; + else + encStr = "AESGCM(?)"; + break; + #endif + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + if (key_size == 128) + encStr = "AESCCM(128)"; + else if (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_ARIA + case wolfssl_aria_gcm: + if (key_size == 128) + encStr = "Aria(128)"; + else if (key_size == 192) + encStr = "Aria(192)"; + else if (key_size == 256) + encStr = "Aria(256)"; + else + encStr = "Aria(?)"; + break; +#endif +#ifdef HAVE_CAMELLIA + case wolfssl_camellia: + if (key_size == 128) + encStr = "Camellia(128)"; + else if (key_size == 256) + encStr = "Camellia(256)"; + else + encStr = "Camellia(?)"; + break; +#endif + default: + encStr = "unknown"; + break; + } - if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), - srp_g, sizeof(srp_g)/sizeof(srp_g[0]), - salt, sizeof(salt)/sizeof(salt[0])) < 0) { - WOLFSSL_MSG("wc_SrpSetParam failed"); - return WOLFSSL_FAILURE; - } - r = wc_SrpSetPassword(ctx->srp, - (const byte*)ctx->srp_password, - (word32)XSTRLEN((char *)ctx->srp_password)); - if (r < 0) { - WOLFSSL_MSG("fail to set srp password."); - return WOLFSSL_FAILURE; - } + return encStr; +} - XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP); - ctx->srp_password = NULL; - } +static WC_INLINE const char* wolfssl_mac_to_string(int mac) +{ + const char* macStr; - return WOLFSSL_SUCCESS; + switch (mac) { + 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 + default: + macStr = "unknown"; + break; } - int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password) - { - int r; - byte salt[SRP_SALT_SIZE]; - - WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password"); - if (ctx == NULL || ctx->srp == NULL || password == NULL) - return WOLFSSL_FAILURE; + return macStr; +} - if (ctx->srp->user != NULL) { - WC_RNG rng; - if (wc_InitRng(&rng) < 0) { - WOLFSSL_MSG("wc_InitRng failed"); - return WOLFSSL_FAILURE; - } - XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); - r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0])); - wc_FreeRng(&rng); - if (r < 0) { - WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); - return WOLFSSL_FAILURE; - } - if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), - srp_g, sizeof(srp_g)/sizeof(srp_g[0]), - salt, sizeof(salt)/sizeof(salt[0])) < 0){ - WOLFSSL_MSG("wc_SrpSetParam failed"); - wc_FreeRng(&rng); - return WOLFSSL_FAILURE; - } - r = wc_SrpSetPassword(ctx->srp, (const byte*)password, - (word32)XSTRLEN(password)); - if (r < 0) { - WOLFSSL_MSG("wc_SrpSetPassword failed."); - wc_FreeRng(&rng); - return WOLFSSL_FAILURE; - } - if (ctx->srp_password != NULL){ - XFREE(ctx->srp_password,NULL, - DYNAMIC_TYPE_SRP); - ctx->srp_password = NULL; - } - wc_FreeRng(&rng); - } else { - /* save password for wolfSSL_set_srp_username */ - if (ctx->srp_password != NULL) - XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP); +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) +{ + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + WOLFSSL_ENTER("wolfSSL_CIPHER_description"); - ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap, - DYNAMIC_TYPE_SRP); - if (ctx->srp_password == NULL){ - WOLFSSL_MSG("memory allocation error"); - return WOLFSSL_FAILURE; - } - XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1); - } - return WOLFSSL_SUCCESS; - } + if (cipher == NULL || in == NULL) + return NULL; - /** - * The modulus passed to wc_SrpSetParams in ssl.c is constant so check - * that the requested strength is less than or equal to the size of the - * static modulus size. - * @param ctx Not used - * @param strength Minimum number of bits for the modulus - * @return 1 if strength is less than or equal to static modulus - * 0 if strength is greater than static modulus +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + /* if cipher is in the stack from wolfSSL_get_ciphers_compat then + * Return the description based on cipher_names[cipher->offset] */ - int wolfSSL_CTX_set_srp_strength(WOLFSSL_CTX *ctx, int strength) - { - (void)ctx; - WOLFSSL_ENTER("wolfSSL_CTX_set_srp_strength"); - if (strength > (int)(sizeof(srp_N)*8)) { - WOLFSSL_MSG("Bad Parameter"); - return WOLFSSL_FAILURE; - } - return WOLFSSL_SUCCESS; + if (cipher->in_stack == TRUE) { + wolfSSL_sk_CIPHER_description((WOLFSSL_CIPHER*)cipher); + XSTRNCPY(in,cipher->description,len); + return ret; } +#endif - char* wolfSSL_get_srp_username(WOLFSSL *ssl) - { - if (ssl && ssl->ctx && ssl->ctx->srp) { - return (char*) ssl->ctx->srp->user; - } - return NULL; - } - #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */ + /* Get the cipher description based on the SSL session cipher */ + keaStr = wolfssl_kea_to_string(cipher->ssl->specs.kea); + authStr = wolfssl_sigalg_to_string(cipher->ssl->specs.sig_algo); + encStr = wolfssl_cipher_to_string(cipher->ssl->specs.bulk_cipher_algorithm, + cipher->ssl->specs.key_size); + macStr = wolfssl_mac_to_string(cipher->ssl->specs.mac_algorithm); - /* keyblock size in bytes or -1 */ - int wolfSSL_get_keyblock_size(WOLFSSL* ssl) - { - if (ssl == NULL) - return WOLFSSL_FATAL_ERROR; - - return 2 * (ssl->specs.key_size + ssl->specs.iv_size + - ssl->specs.hash_size); - } + /* 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; -#endif /* OPENSSL_EXTRA */ + 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; -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + 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; - /* store keys returns WOLFSSL_SUCCESS or -1 on error */ - int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen, - unsigned char** sr, unsigned int* srLen, - unsigned char** cr, unsigned int* crLen) - { - if (ssl == NULL || ssl->arrays == NULL) - return WOLFSSL_FATAL_ERROR; + 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; - *ms = ssl->arrays->masterSecret; - *sr = ssl->arrays->serverRandom; - *cr = ssl->arrays->clientRandom; + 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; - *msLen = SECRET_LEN; - *srLen = RAN_LEN; - *crLen = RAN_LEN; + 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 WOLFSSL_SUCCESS; - } + return ret; +} - void wolfSSL_set_accept_state(WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_set_accept_state"); - if (ssl == NULL) - return; +#ifndef NO_WOLFSSL_STUB +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; + WOLFSSL_STUB("OCSP_parse_url"); + return 0; +} +#endif - if (ssl->options.side == WOLFSSL_CLIENT_END) { - #ifdef HAVE_ECC - #ifdef WOLFSSL_SMALL_STACK - ecc_key* key = NULL; - #else - ecc_key key[1]; - #endif - word32 idx = 0; +#ifndef NO_WOLFSSL_STUB +WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) +{ + WOLFSSL_STUB("COMP_zlib"); + return 0; +} +#endif - #ifdef WOLFSSL_SMALL_STACK - key = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (key == NULL) { - WOLFSSL_MSG("Error allocating memory for ecc_key"); - } - #endif - if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { - if (wc_ecc_init(key) >= 0) { - 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); - } - } - #ifdef WOLFSSL_SMALL_STACK - XFREE(key, ssl->heap, DYNAMIC_TYPE_ECC); - #endif - #endif +#ifndef NO_WOLFSSL_STUB +WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) +{ + WOLFSSL_STUB("COMP_rle"); + return 0; +} +#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 - } +#ifndef NO_WOLFSSL_STUB +int wolfSSL_COMP_add_compression_method(int method, void* data) +{ + (void)method; + (void)data; + WOLFSSL_STUB("COMP_add_compression_method"); + return 0; +} +#endif - if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error initializing server side"); - } - } +#ifndef NO_WOLFSSL_STUB +const char* wolfSSL_COMP_get_name(const void* comp) +{ + static const char ret[] = "not supported"; -#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + (void)comp; + WOLFSSL_STUB("wolfSSL_COMP_get_name"); + return ret; +} +#endif - /* return true if connection established */ - int wolfSSL_is_init_finished(const WOLFSSL* ssl) - { - if (ssl == NULL) - return 0; +/* wolfSSL_set_dynlock_create_callback + * CRYPTO_set_dynlock_create_callback has been deprecated since openSSL 1.0.1. + * This function exists for compatibility purposes because wolfSSL satisfies + * thread safety without relying on the callback. + */ +void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)( + const char*, int)) +{ + WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback"); + (void)f; +} +/* wolfSSL_set_dynlock_lock_callback + * CRYPTO_set_dynlock_lock_callback has been deprecated since openSSL 1.0.1. + * This function exists for compatibility purposes because wolfSSL satisfies + * thread safety without relying on the callback. + */ +void wolfSSL_set_dynlock_lock_callback( + void (*f)(int, WOLFSSL_dynlock_value*, const char*, int)) +{ + WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback"); + (void)f; +} +/* wolfSSL_set_dynlock_destroy_callback + * CRYPTO_set_dynlock_destroy_callback has been deprecated since openSSL 1.0.1. + * This function exists for compatibility purposes because wolfSSL satisfies + * thread safety without relying on the callback. + */ +void wolfSSL_set_dynlock_destroy_callback( + void (*f)(WOLFSSL_dynlock_value*, const char*, int)) +{ + WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback"); + (void)f; +} - /* Can't use ssl->options.connectState and ssl->options.acceptState because - * they differ in meaning for TLS <=1.2 and 1.3 */ - if (ssl->options.handShakeState == HANDSHAKE_DONE) - return 1; - return 0; - } +#endif /* OPENSSL_EXTRA */ #ifdef OPENSSL_EXTRA - void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx, - WOLFSSL_RSA*(*f)(WOLFSSL*, int, int)) - { - /* wolfSSL verifies all these internally */ - (void)ctx; - (void)f; - } +#ifndef NO_CERTS +#if !defined(NO_ASN) && !defined(NO_PWDBASED) +/* Copies unencrypted DER key buffer into "der". If "der" is null then the size + * of buffer needed is returned. If *der == NULL then it allocates a buffer. + * NOTE: This also advances the "der" pointer to be at the end of buffer. + * + * Returns size of key buffer on success + */ +int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der) +{ + return wolfSSL_EVP_PKEY_get_der(key, der); +} - void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt) - { - WOLFSSL_ENTER("wolfSSL_set_shutdown"); - if(ssl==NULL) { - WOLFSSL_MSG("Shutdown not set. ssl is null"); - return; - } +int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) +{ +#if !defined(NO_RSA) || defined(HAVE_ECC) +#ifdef HAVE_ECC + unsigned char *local_der = NULL; + word32 local_derSz = 0; + unsigned char *pub_der = NULL; + ecc_key *eccKey = NULL; + word32 inOutIdx = 0; +#endif + word32 pub_derSz = 0; + int ret; + int key_type = 0; - ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0; - ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0; + if (key == NULL) { + return WOLFSSL_FATAL_ERROR; } -#endif - long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_CTX_get_options"); - WOLFSSL_MSG("wolfSSL options are set through API calls and macros"); - if(ctx == NULL) - return BAD_FUNC_ARG; - return ctx->mask; + key_type = key->type; + if ((key_type != EVP_PKEY_EC) && (key_type != EVP_PKEY_RSA)) { + return WOLFSSL_FATAL_ERROR; } - /* forward declaration */ - static long wolf_set_options(long old_op, long op); +#ifndef NO_RSA + if (key_type == EVP_PKEY_RSA) { + return wolfSSL_i2d_RSAPublicKey(key->rsa, der); + } +#endif - long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_options"); + /* Now that RSA is taken care of, we only need to consider the ECC case. */ - if (ctx == NULL) - return BAD_FUNC_ARG; +#ifdef HAVE_ECC - ctx->mask = wolf_set_options(ctx->mask, opt); -#if defined(HAVE_SESSION_TICKET) && (defined(OPENSSL_EXTRA) \ - || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)) - if ((ctx->mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) { - ctx->noTicketTls12 = 1; - } - /* This code is here for documentation purpose. You must not turn off - * session tickets with the WOLFSSL_OP_NO_TICKET option for TLSv1.3. - * Because we need to support both stateful and stateless tickets. - #ifdef WOLFSSL_TLS13 - if ((ctx->mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) { - ctx->noTicketTls13 = 1; - } - #endif - */ -#endif - return ctx->mask; - } - - long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) - { - WOLFSSL_ENTER("wolfSSL_CTX_clear_options"); - if(ctx == NULL) - return BAD_FUNC_ARG; - ctx->mask &= ~opt; - return ctx->mask; + /* We need to get the DER, then convert it to a public key. But what we get + * might be a buffered private key so we need to decode it and then encode + * the public part. */ + ret = wolfSSL_EVP_PKEY_get_der(key, &local_der); + if (ret <= 0) { + /* In this case, there was no buffered DER at all. This could be the + * case where the key that was passed in was generated. So now we + * have to create the local DER. */ + local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(key->ecc, &local_der); + if (local_derSz == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } else { + local_derSz = (word32)ret; + ret = 0; } -#ifdef OPENSSL_EXTRA - - int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd) - { - WOLFSSL_ENTER("wolfSSL_set_rfd"); - ssl->rfd = rfd; /* not used directly to allow IO callbacks */ - - ssl->IOCB_ReadCtx = &ssl->rfd; - - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; - ssl->buffers.dtlsCtx.rfd = rfd; + if (ret == 0) { + eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC); + if (eccKey == NULL) { + WOLFSSL_MSG("Failed to allocate key buffer."); + ret = WOLFSSL_FATAL_ERROR; } - #endif - - return WOLFSSL_SUCCESS; } - - int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd) - { - WOLFSSL_ENTER("wolfSSL_set_wfd"); - ssl->wfd = wfd; /* not used directly to allow IO callbacks */ - - ssl->IOCB_WriteCtx = &ssl->wfd; - - return WOLFSSL_SUCCESS; + if (ret == 0) { + ret = wc_ecc_init(eccKey); } -#endif /* OPENSSL_EXTRA */ - -#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) - -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - /** - * Implemented in a similar way that ngx_ssl_ocsp_validate does it when - * SSL_get0_verified_chain is not available. - * @param ssl WOLFSSL object to extract certs from - * @return Stack of verified certs - */ - WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) - { - WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; - WOLFSSL_X509_STORE_CTX* storeCtx = NULL; - WOLFSSL_X509* peerCert = NULL; - - WOLFSSL_ENTER("wolfSSL_get0_verified_chain"); - - if (ssl == NULL || ssl->ctx == NULL) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - peerCert = wolfSSL_get_peer_certificate((WOLFSSL*)ssl); - if (peerCert == NULL) { - WOLFSSL_MSG("wolfSSL_get_peer_certificate error"); - return NULL; - } - /* wolfSSL_get_peer_certificate returns a copy. We want the internal - * member so that we don't have to worry about free'ing it. We call - * wolfSSL_get_peer_certificate so that we don't have to worry about - * setting up the internal pointer. */ - wolfSSL_X509_free(peerCert); - peerCert = (WOLFSSL_X509*)&ssl->peerCert; - chain = wolfSSL_get_peer_cert_chain(ssl); - if (chain == NULL) { - WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); - return NULL; - } - storeCtx = wolfSSL_X509_STORE_CTX_new(); - if (storeCtx == NULL) { - WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_new error"); - return NULL; - } - if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), - peerCert, chain) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); - wolfSSL_X509_STORE_CTX_free(storeCtx); - return NULL; - } - if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { - WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); - wolfSSL_X509_STORE_CTX_free(storeCtx); - return NULL; + if (ret == 0) { + ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz); + if (ret < 0) { + /* We now try again as x.963 [point type][x][opt y]. */ + ret = wc_ecc_import_x963(local_der, local_derSz, eccKey); } - wolfSSL_X509_STORE_CTX_free(storeCtx); - return chain; } -#endif /* SESSION_CERTS && OPENSSL_EXTRA */ - WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) - { - if (ctx == NULL) { - return NULL; + if (ret == 0) { + pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 0); + if ((int)pub_derSz <= 0) { + ret = WOLFSSL_FAILURE; } - - if (ctx->x509_store_pt != NULL) - return ctx->x509_store_pt; - return &ctx->x509_store; } - void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store"); - if (ctx == NULL || str == NULL || ctx->cm == str->cm) { - return; + if (ret == 0) { + pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pub_der == NULL) { + WOLFSSL_MSG("Failed to allocate output buffer."); + ret = WOLFSSL_FATAL_ERROR; } + } - if (wolfSSL_CertManager_up_ref(str->cm) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_CertManager_up_ref error"); - return; - } - /* free cert manager if have one */ - if (ctx->cm != NULL) { - wolfSSL_CertManagerFree(ctx->cm); + if (ret == 0) { + pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 0); + if ((int)pub_derSz <= 0) { + ret = WOLFSSL_FATAL_ERROR; } - ctx->cm = str->cm; - ctx->x509_store.cm = str->cm; - - /* free existing store if it exists */ - wolfSSL_X509_STORE_free(ctx->x509_store_pt); - ctx->x509_store.cache = str->cache; - ctx->x509_store_pt = str; /* take ownership of store and free it - with CTX free */ - ctx->cm->x509_store_p = ctx->x509_store_pt;/* CTX has ownership - and free it with CTX free*/ } -#ifdef OPENSSL_ALL - int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) - { - WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store"); + /* This block is for actually returning the DER of the public key */ + if ((ret == 0) && (der != NULL)) { + if (*der == NULL) { + *der = (unsigned char*)XMALLOC(pub_derSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (*der == NULL) { + WOLFSSL_MSG("Failed to allocate output buffer."); + ret = WOLFSSL_FATAL_ERROR; + } - if (ctx == NULL || str == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; + if (ret == 0) { + XMEMCPY(*der, pub_der, pub_derSz); + } } - - /* NO-OP when setting existing store */ - if (str == CTX_STORE(ctx)) - return WOLFSSL_SUCCESS; - - if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); - return WOLFSSL_FAILURE; + else { + XMEMCPY(*der, pub_der, pub_derSz); + *der += pub_derSz; } - - /* free existing store if it exists */ - wolfSSL_X509_STORE_free(ctx->x509_store_pt); - ctx->x509_store_pt = str; /* take ownership of store and free it - with CTX free */ - return WOLFSSL_SUCCESS; } -#endif - int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) - { - WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store"); + XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(local_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (ssl == NULL || str == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } + wc_ecc_free(eccKey); + XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); - /* NO-OP when setting existing store */ - if (str == SSL_STORE(ssl)) - return WOLFSSL_SUCCESS; +#else + ret = WOLFSSL_FATAL_ERROR; +#endif /* HAVE_ECC */ - /* free existing store if it exists */ - wolfSSL_X509_STORE_free(ssl->x509_store_pt); - if (str == ssl->ctx->x509_store_pt) - ssl->x509_store_pt = NULL; /* if setting ctx store then just revert - to using that instead */ - else - ssl->x509_store_pt = str; /* take ownership of store and free it - with SSL free */ - return WOLFSSL_SUCCESS; + if (ret == 0) { + return (int)pub_derSz; } + return ret; +#else + return WOLFSSL_FATAL_ERROR; +#endif /* !NO_RSA || HAVE_ECC */ +} +#endif /* !NO_ASN && !NO_PWDBASED */ - int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str) - { - WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store"); +#endif /* !NO_CERTS */ +#endif /* OPENSSL_EXTRA */ - if (ssl == NULL || str == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } +#ifdef OPENSSL_EXTRA - /* NO-OP when setting existing store */ - if (str == SSL_STORE(ssl)) - return WOLFSSL_SUCCESS; +/* Sets the DNS hostname to name. + * Hostname is cleared if name is NULL or empty. */ +int wolfSSL_set1_host(WOLFSSL * ssl, const char* name) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } - if (wolfSSL_X509_STORE_up_ref(str) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error"); - return WOLFSSL_FAILURE; - } + return wolfSSL_X509_VERIFY_PARAM_set1_host(ssl->param, name, 0); +} - /* free existing store if it exists */ - wolfSSL_X509_STORE_free(ssl->x509_store_pt); - if (str == ssl->ctx->x509_store_pt) - ssl->x509_store_pt = NULL; /* if setting ctx store then just revert - to using that instead */ - else - ssl->x509_store_pt = str; /* take ownership of store and free it - with SSL free */ +/****************************************************************************** +* wolfSSL_CTX_set1_param - set a pointer to the SSL verification parameters +* +* RETURNS: +* WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +* Note: Returns WOLFSSL_SUCCESS, in case either parameter is NULL, +* same as openssl. +*/ +int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm) +{ + if (ctx == NULL || vpm == NULL) return WOLFSSL_SUCCESS; - } -#endif /* !NO_CERTS && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */ -#ifdef WOLFSSL_ENCRYPTED_KEYS + return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm); +} - void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx, - void* userdata) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_default_passwd_cb_userdata"); - if (ctx) - ctx->passwd_userdata = userdata; +/****************************************************************************** +* wolfSSL_CTX/_get0_param - return a pointer to the SSL verification parameters +* +* RETURNS: +* returns pointer to the SSL verification parameters on success, +* otherwise returns NULL +*/ +WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return NULL; } + return ctx->param; +} - void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, wc_pem_password_cb* - cb) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_default_passwd_cb"); - if (ctx) - ctx->passwd_cb = cb; +WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; } + return ssl->param; +} - wc_pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx) - { - if (ctx == NULL || ctx->passwd_cb == NULL) { - return NULL; - } +#endif /* OPENSSL_EXTRA */ - return ctx->passwd_cb; - } +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +/* Gets an index to store SSL structure at. + * + * Returns positive index on success and negative values on failure + */ +int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); + /* store SSL at index 0 */ + return 0; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx) - { - if (ctx == NULL) { - return NULL; - } +#ifdef OPENSSL_EXTRA +/* Sets a function callback that will send information about the state of all + * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed + * in. + * + * ctx WOLFSSL_CTX structure to set callback function in + * f callback function to use + */ +void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, + void (*f)(const WOLFSSL* ssl, int type, int val)) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback"); + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + } + else { + ctx->CBIS = f; + } +} - return ctx->passwd_userdata; +void wolfSSL_set_info_callback(WOLFSSL* ssl, + void (*f)(const WOLFSSL* ssl, int type, int val)) +{ + WOLFSSL_ENTER("wolfSSL_set_info_callback"); + if (ssl == NULL) { + WOLFSSL_MSG("Bad function argument"); } + else { + ssl->CBIS = f; + } +} -#endif /* WOLFSSL_ENCRYPTED_KEYS */ +unsigned long wolfSSL_ERR_peek_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED) - unsigned long wolfSSL_ERR_get_error(void) - { - WOLFSSL_ENTER("wolfSSL_ERR_get_error"); -#ifdef WOLFSSL_HAVE_ERROR_QUEUE - return wc_GetErrorNodeErr(); -#else - return (unsigned long)(0 - NOT_COMPILED_IN); -#endif - } -#endif + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); +} -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +int wolfSSL_ERR_GET_LIB(unsigned long err) +{ + unsigned long value; - int wolfSSL_num_locks(void) - { + value = (err & 0xFFFFFFL); + switch (value) { + case -WC_NO_ERR_TRACE(PARSE_ERROR): + return ERR_LIB_SSL; + case -WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER): + case PEM_R_NO_START_LINE: + case PEM_R_PROBLEMS_GETTING_PASSWORD: + case PEM_R_BAD_PASSWORD_READ: + case PEM_R_BAD_DECRYPT: + return ERR_LIB_PEM; + case EVP_R_BAD_DECRYPT: + case EVP_R_BN_DECODE_ERROR: + case EVP_R_DECODE_ERROR: + case EVP_R_PRIVATE_KEY_DECODE_ERROR: + return ERR_LIB_EVP; + case ASN1_R_HEADER_TOO_LONG: + return ERR_LIB_ASN1; + default: return 0; } +} - void wolfSSL_set_locking_callback(mutex_cb* f) - { - WOLFSSL_ENTER("wolfSSL_set_locking_callback"); +/* This function is to find global error values that are the same through out + * all library version. With wolfSSL having only one set of error codes the + * return value is pretty straight forward. The only thing needed is all wolfSSL + * error values are typically negative. + * + * Returns the error reason + */ +int wolfSSL_ERR_GET_REASON(unsigned long err) +{ + int ret = (int)err; - if (wc_SetMutexCb(f) != 0) { - WOLFSSL_MSG("Error when setting mutex call back"); - } - } + WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON"); - mutex_cb* wolfSSL_get_locking_callback(void) - { - WOLFSSL_ENTER("wolfSSL_get_locking_callback"); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + /* Nginx looks for this error to know to stop parsing certificates. + * Same for HAProxy. */ + if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE) || + ((err & 0xFFFFFFL) == -ASN_NO_PEM_HEADER) || + ((err & 0xFFFL) == PEM_R_NO_START_LINE )) + return PEM_R_NO_START_LINE; + if (err == ((ERR_LIB_SSL << 24) | -SSL_R_HTTP_REQUEST)) + return SSL_R_HTTP_REQUEST; +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) + if (err == ((ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG)) + return ASN1_R_HEADER_TOO_LONG; +#endif - return wc_GetMutexCb(); + /* check if error value is in range of wolfSSL errors */ + ret = 0 - ret; /* setting as negative value */ + /* wolfCrypt range is less than MAX (-100) + wolfSSL range is MIN (-300) and lower */ + if (ret < MAX_CODE_E && ret > MIN_CODE_E) { + return ret; } - - - typedef unsigned long (idCb)(void); - static idCb* inner_idCb = NULL; - - unsigned long wolfSSL_thread_id(void) - { - if (inner_idCb != NULL) { - return inner_idCb(); - } - else { - return 0; - } + else { + WOLFSSL_MSG("Not in range of typical error values"); + ret = (int)err; } + return ret; +} - void wolfSSL_set_id_callback(unsigned long (*f)(void)) - { - inner_idCb = f; - } +/* returns a string that describes the alert + * + * alertID the alert value to look up + */ +const char* wolfSSL_alert_type_string_long(int alertID) +{ + WOLFSSL_ENTER("wolfSSL_alert_type_string_long"); -#ifdef WOLFSSL_HAVE_ERROR_QUEUE -#ifndef NO_BIO - /* print out and clear all errors */ - void wolfSSL_ERR_print_errors(WOLFSSL_BIO* bio) - { - const char* file = NULL; - const char* reason = NULL; - int ret; - int line = 0; - char buf[WOLFSSL_MAX_ERROR_SZ * 2]; + return AlertTypeToString(alertID); +} - WOLFSSL_ENTER("wolfSSL_ERR_print_errors"); - if (bio == NULL) { - WOLFSSL_MSG("BIO passed in was null"); - return; - } +const char* wolfSSL_alert_desc_string_long(int alertID) +{ + WOLFSSL_ENTER("wolfSSL_alert_desc_string_long"); - do { - ret = wc_PeekErrorNode(0, &file, &reason, &line); - if (ret >= 0) { - const char* r = wolfSSL_ERR_reason_error_string(0 - ret); - if (XSNPRINTF(buf, sizeof(buf), - "error:%d:wolfSSL library:%s:%s:%d\n", - ret, r, file, line) - >= (int)sizeof(buf)) - { - WOLFSSL_MSG("Buffer overrun formatting error message"); - } - wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)); - wc_RemoveErrorNode(0); - } - } while (ret >= 0); - if (wolfSSL_BIO_write(bio, "", 1) != 1) { - WOLFSSL_MSG("Issue writing final string terminator"); - } + return AlertTypeToString(alertID); +} + +#define STATE_STRINGS_PROTO(s) \ + { \ + {"SSLv3 " s, \ + "SSLv3 " s, \ + "SSLv3 " s}, \ + {"TLSv1 " s, \ + "TLSv1 " s, \ + "TLSv1 " s}, \ + {"TLSv1_1 " s, \ + "TLSv1_1 " s, \ + "TLSv1_1 " s}, \ + {"TLSv1_2 " s, \ + "TLSv1_2 " s, \ + "TLSv1_2 " s}, \ + {"TLSv1_3 " s, \ + "TLSv1_3 " s, \ + "TLSv1_3 " s}, \ + {"DTLSv1 " s, \ + "DTLSv1 " s, \ + "DTLSv1 " s}, \ + {"DTLSv1_2 " s, \ + "DTLSv1_2 " s, \ + "DTLSv1_2 " s}, \ + {"DTLSv1_3 " s, \ + "DTLSv1_3 " s, \ + "DTLSv1_3 " s}, \ } -#endif /* !NO_BIO */ -#endif /* WOLFSSL_HAVE_ERROR_QUEUE */ -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ +#define STATE_STRINGS_PROTO_RW(s) \ + { \ + {"SSLv3 read " s, \ + "SSLv3 write " s, \ + "SSLv3 " s}, \ + {"TLSv1 read " s, \ + "TLSv1 write " s, \ + "TLSv1 " s}, \ + {"TLSv1_1 read " s, \ + "TLSv1_1 write " s, \ + "TLSv1_1 " s}, \ + {"TLSv1_2 read " s, \ + "TLSv1_2 write " s, \ + "TLSv1_2 " s}, \ + {"TLSv1_3 read " s, \ + "TLSv1_3 write " s, \ + "TLSv1_3 " s}, \ + {"DTLSv1 read " s, \ + "DTLSv1 write " s, \ + "DTLSv1 " s}, \ + {"DTLSv1_2 read " s, \ + "DTLSv1_2 write " s, \ + "DTLSv1_2 " s}, \ + {"DTLSv1_3 read " s, \ + "DTLSv1_3 write " s, \ + "DTLSv1_3 " s}, \ + } -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ - defined(HAVE_SECRET_CALLBACK) -#if !defined(NO_WOLFSSL_SERVER) -/* 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 +/* Gets the current state of the WOLFSSL structure + * + * ssl WOLFSSL structure to get state of + * + * Returns a human readable string of the WOLFSSL structure state */ -size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, - size_t outSz) +const char* wolfSSL_state_string_long(const WOLFSSL* ssl) { - size_t size; - /* return max size of buffer */ - if (outSz == 0) { - return RAN_LEN; - } + static const char* OUTPUT_STR[24][8][3] = { + STATE_STRINGS_PROTO("Initialization"), + STATE_STRINGS_PROTO_RW("Server Hello Request"), + STATE_STRINGS_PROTO_RW("Server Hello Verify Request"), + STATE_STRINGS_PROTO_RW("Server Hello Retry Request"), + STATE_STRINGS_PROTO_RW("Server Hello"), + STATE_STRINGS_PROTO_RW("Server Certificate Status"), + STATE_STRINGS_PROTO_RW("Server Encrypted Extensions"), + STATE_STRINGS_PROTO_RW("Server Session Ticket"), + STATE_STRINGS_PROTO_RW("Server Certificate Request"), + STATE_STRINGS_PROTO_RW("Server Cert"), + STATE_STRINGS_PROTO_RW("Server Key Exchange"), + STATE_STRINGS_PROTO_RW("Server Hello Done"), + STATE_STRINGS_PROTO_RW("Server Change CipherSpec"), + STATE_STRINGS_PROTO_RW("Server Finished"), + STATE_STRINGS_PROTO_RW("server Key Update"), + STATE_STRINGS_PROTO_RW("Client Hello"), + STATE_STRINGS_PROTO_RW("Client Key Exchange"), + STATE_STRINGS_PROTO_RW("Client Cert"), + STATE_STRINGS_PROTO_RW("Client Change CipherSpec"), + STATE_STRINGS_PROTO_RW("Client Certificate Verify"), + STATE_STRINGS_PROTO_RW("Client End Of Early Data"), + STATE_STRINGS_PROTO_RW("Client Finished"), + STATE_STRINGS_PROTO_RW("Client Key Update"), + STATE_STRINGS_PROTO("Handshake Done"), + }; + enum ProtocolVer { + SSL_V3 = 0, + TLS_V1, + TLS_V1_1, + TLS_V1_2, + TLS_V1_3, + DTLS_V1, + DTLS_V1_2, + DTLS_V1_3, + UNKNOWN = 100 + }; - if (ssl == NULL || out == NULL) { - return 0; - } + enum IOMode { + SS_READ = 0, + SS_WRITE, + SS_NEITHER + }; - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays struct not saved after handshake"); - return 0; + enum SslState { + ss_null_state = 0, + ss_server_hellorequest, + ss_server_helloverify, + ss_server_helloretryrequest, + ss_server_hello, + ss_server_certificatestatus, + ss_server_encryptedextensions, + ss_server_sessionticket, + ss_server_certrequest, + ss_server_cert, + ss_server_keyexchange, + ss_server_hellodone, + ss_server_changecipherspec, + ss_server_finished, + ss_server_keyupdate, + ss_client_hello, + ss_client_keyexchange, + ss_client_cert, + ss_client_changecipherspec, + ss_client_certverify, + ss_client_endofearlydata, + ss_client_finished, + ss_client_keyupdate, + ss_handshake_done + }; + + int protocol = 0; + int cbmode = 0; + int state = 0; + + WOLFSSL_ENTER("wolfSSL_state_string_long"); + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return NULL; } - if (outSz > RAN_LEN) { - size = RAN_LEN; + /* Get state of callback */ + if (ssl->cbmode == SSL_CB_MODE_WRITE) { + cbmode = SS_WRITE; + } + else if (ssl->cbmode == SSL_CB_MODE_READ) { + cbmode = SS_READ; } else { - size = outSz; + cbmode = SS_NEITHER; } - XMEMCPY(out, ssl->arrays->serverRandom, size); - return size; -} -#endif /* !NO_WOLFSSL_SERVER */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ - -#ifdef OPENSSL_EXTRA -#if !defined(NO_WOLFSSL_SERVER) -/* Used to get the peer ephemeral public key sent during the connection - * NOTE: currently wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) must be called - * before the ephemeral key is stored. - * return WOLFSSL_SUCCESS on success */ -int wolfSSL_get_peer_tmp_key(const WOLFSSL* ssl, WOLFSSL_EVP_PKEY** pkey) -{ - WOLFSSL_EVP_PKEY* ret = NULL; - - WOLFSSL_ENTER("wolfSSL_get_server_tmp_key"); - - if (ssl == NULL || pkey == NULL) { - WOLFSSL_MSG("Bad argument passed in"); - return WOLFSSL_FAILURE; + /* Get protocol version */ + switch (ssl->version.major) { + case SSLv3_MAJOR: + switch (ssl->version.minor) { + case SSLv3_MINOR: + protocol = SSL_V3; + break; + case TLSv1_MINOR: + protocol = TLS_V1; + break; + case TLSv1_1_MINOR: + protocol = TLS_V1_1; + break; + case TLSv1_2_MINOR: + protocol = TLS_V1_2; + break; + case TLSv1_3_MINOR: + protocol = TLS_V1_3; + break; + default: + protocol = UNKNOWN; + } + break; + case DTLS_MAJOR: + switch (ssl->version.minor) { + case DTLS_MINOR: + protocol = DTLS_V1; + break; + case DTLSv1_2_MINOR: + protocol = DTLS_V1_2; + break; + case DTLSv1_3_MINOR: + protocol = DTLS_V1_3; + break; + default: + protocol = UNKNOWN; + } + break; + default: + protocol = UNKNOWN; } -#ifdef HAVE_ECC - if (ssl->peerEccKey != NULL) { - unsigned char* der; - const unsigned char* pt; - unsigned int derSz = 0; - int sz; - - PRIVATE_KEY_UNLOCK(); - if (wc_ecc_export_x963(ssl->peerEccKey, NULL, &derSz) != - LENGTH_ONLY_E) { - WOLFSSL_MSG("get ecc der size failed"); - PRIVATE_KEY_LOCK(); - return WOLFSSL_FAILURE; - } - PRIVATE_KEY_LOCK(); - - derSz += MAX_SEQ_SZ + (2 * MAX_ALGO_SZ) + MAX_SEQ_SZ + TRAILING_ZERO; - der = (unsigned char*)XMALLOC(derSz, ssl->heap, DYNAMIC_TYPE_KEY); - if (der == NULL) { - WOLFSSL_MSG("Memory error"); - return WOLFSSL_FAILURE; + /* accept process */ + if (ssl->cbmode == SSL_CB_MODE_READ) { + state = ssl->cbtype; + switch (state) { + case hello_request: + state = ss_server_hellorequest; + break; + case client_hello: + state = ss_client_hello; + break; + case server_hello: + state = ss_server_hello; + break; + case hello_verify_request: + state = ss_server_helloverify; + break; + case session_ticket: + state = ss_server_sessionticket; + break; + case end_of_early_data: + state = ss_client_endofearlydata; + break; + case hello_retry_request: + state = ss_server_helloretryrequest; + break; + case encrypted_extensions: + state = ss_server_encryptedextensions; + break; + case certificate: + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ss_client_cert; + else if (ssl->options.side == WOLFSSL_CLIENT_END) + state = ss_server_cert; + else { + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + break; + case server_key_exchange: + state = ss_server_keyexchange; + break; + case certificate_request: + state = ss_server_certrequest; + break; + case server_hello_done: + state = ss_server_hellodone; + break; + case certificate_verify: + state = ss_client_certverify; + break; + case client_key_exchange: + state = ss_client_keyexchange; + break; + case finished: + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ss_client_finished; + else if (ssl->options.side == WOLFSSL_CLIENT_END) + state = ss_server_finished; + else { + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + break; + case certificate_status: + state = ss_server_certificatestatus; + break; + case key_update: + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ss_client_keyupdate; + else if (ssl->options.side == WOLFSSL_CLIENT_END) + state = ss_server_keyupdate; + else { + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + break; + case change_cipher_hs: + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ss_client_changecipherspec; + else if (ssl->options.side == WOLFSSL_CLIENT_END) + state = ss_server_changecipherspec; + else { + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + break; + default: + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; } + } + else { + /* Send process */ + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ssl->options.serverState; + else + state = ssl->options.clientState; - if ((sz = wc_EccPublicKeyToDer(ssl->peerEccKey, der, derSz, 1)) <= 0) { - WOLFSSL_MSG("get ecc der failed"); - XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); - return WOLFSSL_FAILURE; + switch (state) { + case SERVER_HELLOVERIFYREQUEST_COMPLETE: + state = ss_server_helloverify; + break; + case SERVER_HELLO_RETRY_REQUEST_COMPLETE: + state = ss_server_helloretryrequest; + break; + case SERVER_HELLO_COMPLETE: + state = ss_server_hello; + break; + case SERVER_ENCRYPTED_EXTENSIONS_COMPLETE: + state = ss_server_encryptedextensions; + break; + case SERVER_CERT_COMPLETE: + state = ss_server_cert; + break; + case SERVER_KEYEXCHANGE_COMPLETE: + state = ss_server_keyexchange; + break; + case SERVER_HELLODONE_COMPLETE: + state = ss_server_hellodone; + break; + case SERVER_CHANGECIPHERSPEC_COMPLETE: + state = ss_server_changecipherspec; + break; + case SERVER_FINISHED_COMPLETE: + state = ss_server_finished; + break; + case CLIENT_HELLO_RETRY: + case CLIENT_HELLO_COMPLETE: + state = ss_client_hello; + break; + case CLIENT_KEYEXCHANGE_COMPLETE: + state = ss_client_keyexchange; + break; + case CLIENT_CHANGECIPHERSPEC_COMPLETE: + state = ss_client_changecipherspec; + break; + case CLIENT_FINISHED_COMPLETE: + state = ss_client_finished; + break; + case HANDSHAKE_DONE: + state = ss_handshake_done; + break; + default: + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; } - pt = der; /* in case pointer gets advanced */ - ret = wolfSSL_d2i_PUBKEY(NULL, &pt, sz); - XFREE(der, ssl->heap, DYNAMIC_TYPE_KEY); } -#endif - *pkey = ret; -#ifdef HAVE_ECC - if (ret != NULL) - return WOLFSSL_SUCCESS; - else -#endif - return WOLFSSL_FAILURE; + if (protocol == UNKNOWN) { + WOLFSSL_MSG("Unknown protocol"); + return ""; + } + else { + return OUTPUT_STR[state][protocol][cbmode]; + } } -#endif /* !NO_WOLFSSL_SERVER */ +#endif /* OPENSSL_EXTRA */ -/** - * This function checks if any compiled in protocol versions are - * left enabled after calls to set_min or set_max API. - * @param major The SSL/TLS major version - * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no - * protocol versions are left enabled. - */ -static int CheckSslMethodVersion(byte major, unsigned long options) +static long wolf_set_options(long old_op, long op) { - int sanityConfirmed = 0; + /* if SSL_OP_ALL then turn all bug workarounds on */ + if ((op & WOLFSSL_OP_ALL) == WOLFSSL_OP_ALL) { + WOLFSSL_MSG("\tSSL_OP_ALL"); + } - (void)options; + /* by default cookie exchange is on with DTLS */ + if ((op & WOLFSSL_OP_COOKIE_EXCHANGE) == WOLFSSL_OP_COOKIE_EXCHANGE) { + WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); + } - switch (major) { - #ifndef NO_TLS - case SSLv3_MAJOR: - #ifdef WOLFSSL_ALLOW_SSLV3 - if (!(options & WOLFSSL_OP_NO_SSLv3)) { - sanityConfirmed = 1; - } - #endif - #ifndef NO_OLD_TLS - if (!(options & WOLFSSL_OP_NO_TLSv1)) - sanityConfirmed = 1; - if (!(options & WOLFSSL_OP_NO_TLSv1_1)) - sanityConfirmed = 1; - #endif - #ifndef WOLFSSL_NO_TLS12 - if (!(options & WOLFSSL_OP_NO_TLSv1_2)) - sanityConfirmed = 1; - #endif - #ifdef WOLFSSL_TLS13 - if (!(options & WOLFSSL_OP_NO_TLSv1_3)) - sanityConfirmed = 1; - #endif - break; - #endif - #ifdef WOLFSSL_DTLS - case DTLS_MAJOR: - sanityConfirmed = 1; - break; - #endif - default: - WOLFSSL_MSG("Invalid major version"); - return WOLFSSL_FAILURE; + if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); } - if (!sanityConfirmed) { - WOLFSSL_MSG("All compiled in TLS versions disabled"); - return WOLFSSL_FAILURE; + +#ifdef SSL_OP_NO_TLSv1_3 + if ((op & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3"); } - return WOLFSSL_SUCCESS; -} +#endif -/** - * protoVerTbl holds (D)TLS version numbers in ascending order. - * Except DTLS versions, the newer version is located in the latter part of - * the table. This table is referred by wolfSSL_CTX_set_min_proto_version and - * wolfSSL_CTX_set_max_proto_version. - */ -static const int protoVerTbl[] = { - SSL3_VERSION, - TLS1_VERSION, - TLS1_1_VERSION, - TLS1_2_VERSION, - TLS1_3_VERSION, - DTLS1_VERSION, - DTLS1_2_VERSION -}; -/* number of protocol versions listed in protoVerTbl */ -#define NUMBER_OF_PROTOCOLS (sizeof(protoVerTbl)/sizeof(int)) + if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); + } -/** - * wolfSSL_CTX_set_min_proto_version attempts to set the minimum protocol - * version to use by SSL objects created from this WOLFSSL_CTX. - * This API guarantees that a version of SSL/TLS lower than specified - * here will not be allowed. If the version specified is not compiled in - * then this API sets the lowest compiled in protocol version. - * This API also accept 0 as version, to set the minimum version automatically. - * CheckSslMethodVersion() is called to check if any remaining protocol versions - * are enabled. - * @param ctx The wolfSSL CONTEXT factory for spawning SSL/TLS objects - * @param version Any of the following - * * 0 - * * SSL3_VERSION - * * TLS1_VERSION - * * TLS1_1_VERSION - * * TLS1_2_VERSION - * * TLS1_3_VERSION - * * DTLS1_VERSION - * * DTLS1_2_VERSION - * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no - * protocol versions are left enabled. - */ -static int Set_CTX_min_proto_version(WOLFSSL_CTX* ctx, int version) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version_ex"); + if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); + } - if (ctx == NULL) { - return WOLFSSL_FAILURE; + if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); } - switch (version) { -#ifndef NO_TLS - case SSL3_VERSION: -#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) - ctx->minDowngrade = SSLv3_MINOR; - break; -#endif - case TLS1_VERSION: - #ifdef WOLFSSL_ALLOW_TLSV10 - ctx->minDowngrade = TLSv1_MINOR; - break; - #endif - case TLS1_1_VERSION: - #ifndef NO_OLD_TLS - ctx->minDowngrade = TLSv1_1_MINOR; - break; - #endif - case TLS1_2_VERSION: - #ifndef WOLFSSL_NO_TLS12 - ctx->minDowngrade = TLSv1_2_MINOR; - break; - #endif - case TLS1_3_VERSION: - #ifdef WOLFSSL_TLS13 - ctx->minDowngrade = TLSv1_3_MINOR; - break; - #endif -#endif -#ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - #ifndef NO_OLD_TLS - ctx->minDowngrade = DTLS_MINOR; - break; - #endif - case DTLS1_2_VERSION: - ctx->minDowngrade = DTLSv1_2_MINOR; - break; -#endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; + if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); } - switch (version) { -#ifndef NO_TLS - case TLS1_3_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2); - FALL_THROUGH; - case TLS1_2_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_1); - FALL_THROUGH; - case TLS1_1_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1); - FALL_THROUGH; - case TLS1_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_SSLv3); - break; - case SSL3_VERSION: - case SSL2_VERSION: - /* Nothing to do here */ - break; -#endif -#ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - case DTLS1_2_VERSION: - break; -#endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; + if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) == + WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) { + WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE"); } - return CheckSslMethodVersion(ctx->method->version.major, ctx->mask); + if ((op & WOLFSSL_OP_NO_COMPRESSION) == WOLFSSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); + #else + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in"); + #endif + } + + return old_op | op; } -/* Sets the min protocol version allowed with WOLFSSL_CTX - * returns WOLFSSL_SUCCESS on success */ -int wolfSSL_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) +static int FindHashSig(const Suites* suites, byte first, byte second) { - int ret; - int proto = 0; - int maxProto = 0; - int i; - int idx = 0; + word16 i; - WOLFSSL_ENTER("wolfSSL_CTX_set_min_proto_version"); - - if (ctx == NULL) { - return WOLFSSL_FAILURE; + if (suites == NULL || suites->hashSigAlgoSz == 0) { + WOLFSSL_MSG("Suites pointer error or suiteSz 0"); + return SUITES_ERROR; } - if (version != 0) { - proto = version; - ctx->minProto = 0; /* turn min proto flag off */ - for (i = 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) { - if (protoVerTbl[i] == version) { - break; - } - } + + for (i = 0; i < suites->hashSigAlgoSz-1; i += 2) { + if (suites->hashSigAlgo[i] == first && + suites->hashSigAlgo[i+1] == second ) + return i; } - else { - /* when 0 is specified as version, try to find out the min version */ - for (i = 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) { - ret = Set_CTX_min_proto_version(ctx, protoVerTbl[i]); - if (ret == WOLFSSL_SUCCESS) { - proto = protoVerTbl[i]; - ctx->minProto = 1; /* turn min proto flag on */ - break; - } - } + + return MATCH_SUITE_ERROR; +} + +long wolfSSL_set_options(WOLFSSL* ssl, long op) +{ + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; + + WOLFSSL_ENTER("wolfSSL_set_options"); + + if (ssl == NULL) { + return 0; } - /* check case where max > min , if so then clear the NO_* options - * i is the index into the table for proto version used, see if the max - * proto version index found is smaller */ - maxProto = wolfSSL_CTX_get_max_proto_version(ctx); - for (idx = 0; (unsigned)idx < NUMBER_OF_PROTOCOLS; idx++) { - if (protoVerTbl[idx] == maxProto) { - break; - } + ssl->options.mask = wolf_set_options(ssl->options.mask, op); + + if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) { + WOLFSSL_MSG("Disabling TLS 1.3"); + if (ssl->version.minor == TLSv1_3_MINOR) + ssl->version.minor = TLSv1_2_MINOR; } - if (idx < i) { - wolfSSL_CTX_clear_options(ctx, WOLFSSL_OP_NO_TLSv1 | - WOLFSSL_OP_NO_TLSv1_1 | WOLFSSL_OP_NO_TLSv1_2 | - WOLFSSL_OP_NO_TLSv1_3); + + if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("Disabling TLS 1.2"); + if (ssl->version.minor == TLSv1_2_MINOR) + ssl->version.minor = TLSv1_1_MINOR; } - ret = Set_CTX_min_proto_version(ctx, proto); - return ret; -} + if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("Disabling TLS 1.1"); + if (ssl->version.minor == TLSv1_1_MINOR) + ssl->version.minor = TLSv1_MINOR; + } -/** - * wolfSSL_CTX_set_max_proto_version attempts to set the maximum protocol - * version to use by SSL objects created from this WOLFSSL_CTX. - * This API guarantees that a version of SSL/TLS higher than specified - * here will not be allowed. If the version specified is not compiled in - * then this API sets the highest compiled in protocol version. - * This API also accept 0 as version, to set the maximum version automatically. - * CheckSslMethodVersion() is called to check if any remaining protocol versions - * are enabled. - * @param ctx The wolfSSL CONTEXT factory for spawning SSL/TLS objects - * @param ver Any of the following - * * 0 - * * SSL3_VERSION - * * TLS1_VERSION - * * TLS1_1_VERSION - * * TLS1_2_VERSION - * * TLS1_3_VERSION - * * DTLS1_VERSION - * * DTLS1_2_VERSION - * @return WOLFSSL_SUCCESS on valid settings and WOLFSSL_FAILURE when no - * protocol versions are left enabled. - */ -static int Set_CTX_max_proto_version(WOLFSSL_CTX* ctx, int ver) -{ - int ret; - WOLFSSL_ENTER("Set_CTX_max_proto_version"); + if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { + WOLFSSL_MSG("Disabling TLS 1.0"); + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; + } - if (!ctx || !ctx->method) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; + if ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION) + == WOLFSSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + ssl->options.usingCompression = 0; + #endif } - switch (ver) { - case SSL2_VERSION: - WOLFSSL_MSG("wolfSSL does not support SSLv2"); - return WOLFSSL_FAILURE; -#ifndef NO_TLS - case SSL3_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1); - FALL_THROUGH; - case TLS1_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_1); - FALL_THROUGH; - case TLS1_1_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_2); - FALL_THROUGH; - case TLS1_2_VERSION: - wolfSSL_CTX_set_options(ctx, WOLFSSL_OP_NO_TLSv1_3); - FALL_THROUGH; - case TLS1_3_VERSION: - /* Nothing to do here */ - break; -#endif -#ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - case DTLS1_2_VERSION: - break; -#endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; +#if defined(HAVE_SESSION_TICKET) && (defined(OPENSSL_EXTRA) \ + || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)) + if ((ssl->options.mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) { + ssl->options.noTicketTls12 = 1; } +#endif - ret = CheckSslMethodVersion(ctx->method->version.major, ctx->mask); - if (ret == WOLFSSL_SUCCESS) { - /* Check the major */ - switch (ver) { - #ifndef NO_TLS - case SSL3_VERSION: - case TLS1_VERSION: - case TLS1_1_VERSION: - case TLS1_2_VERSION: - case TLS1_3_VERSION: - if (ctx->method->version.major != SSLv3_MAJOR) { - WOLFSSL_MSG("Mismatched protocol version"); - return WOLFSSL_FAILURE; + + /* in the case of a version change the cipher suites should be reset */ +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif +#ifdef NO_RSA + haveRSA = 0; +#endif +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + + if (ssl->options.side != WOLFSSL_NEITHER_END) { + if (AllocateSuites(ssl) != 0) + return 0; + if (!ssl->suites->setSuites) { + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, + havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig, + ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, + ssl->options.haveFalconSig, + ssl->options.haveDilithiumSig, ssl->options.useAnon, + TRUE, ssl->options.side); + } + else { + /* Only preserve overlapping suites */ + Suites tmpSuites; + word16 in, out, haveECDSAsig = 0; + word16 haveStaticECC = ssl->options.haveStaticECC; +#ifdef NO_RSA + haveECDSAsig = 1; + haveStaticECC = 1; +#endif + XMEMSET(&tmpSuites, 0, sizeof(Suites)); + /* Get all possible ciphers and sigalgs for the version. Following + * options limit the allowed ciphers so let's try to get as many as + * possible. + * - haveStaticECC turns off haveRSA + * - haveECDSAsig turns off haveRSAsig */ + InitSuites(&tmpSuites, ssl->version, 0, 1, 1, 1, haveECDSAsig, 1, 1, + haveStaticECC, 1, 1, 1, 1, ssl->options.side); + for (in = 0, out = 0; in < ssl->suites->suiteSz; in += SUITE_LEN) { + if (FindSuite(&tmpSuites, ssl->suites->suites[in], + ssl->suites->suites[in+1]) >= 0) { + ssl->suites->suites[out] = ssl->suites->suites[in]; + ssl->suites->suites[out+1] = ssl->suites->suites[in+1]; + out += SUITE_LEN; + } } - break; - #endif - #ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - case DTLS1_2_VERSION: - if (ctx->method->version.major != DTLS_MAJOR) { - WOLFSSL_MSG("Mismatched protocol version"); - return WOLFSSL_FAILURE; + ssl->suites->suiteSz = out; + for (in = 0, out = 0; in < ssl->suites->hashSigAlgoSz; in += 2) { + if (FindHashSig(&tmpSuites, ssl->suites->hashSigAlgo[in], + ssl->suites->hashSigAlgo[in+1]) >= 0) { + ssl->suites->hashSigAlgo[out] = + ssl->suites->hashSigAlgo[in]; + ssl->suites->hashSigAlgo[out+1] = + ssl->suites->hashSigAlgo[in+1]; + out += 2; + } } - break; - #endif - } - /* Update the method */ - switch (ver) { - case SSL2_VERSION: - WOLFSSL_MSG("wolfSSL does not support SSLv2"); - return WOLFSSL_FAILURE; - #ifndef NO_TLS - case SSL3_VERSION: - ctx->method->version.minor = SSLv3_MINOR; - break; - case TLS1_VERSION: - ctx->method->version.minor = TLSv1_MINOR; - break; - case TLS1_1_VERSION: - ctx->method->version.minor = TLSv1_1_MINOR; - break; - case TLS1_2_VERSION: - ctx->method->version.minor = TLSv1_2_MINOR; - break; - case TLS1_3_VERSION: - ctx->method->version.minor = TLSv1_3_MINOR; - break; - #endif - #ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - ctx->method->version.minor = DTLS_MINOR; - break; - case DTLS1_2_VERSION: - ctx->method->version.minor = DTLSv1_2_MINOR; - break; - #endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; + ssl->suites->hashSigAlgoSz = out; } } - return ret; + + return ssl->options.mask; } -/* Sets the max protocol version allowed with WOLFSSL_CTX - * returns WOLFSSL_SUCCESS on success */ -int wolfSSL_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version) +long wolfSSL_get_options(const WOLFSSL* ssl) { - int i; - int ret = WOLFSSL_FAILURE; - int minProto; + WOLFSSL_ENTER("wolfSSL_get_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + return ssl->options.mask; +} - WOLFSSL_ENTER("wolfSSL_CTX_set_max_proto_version"); +#if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) +/* clears the counter for number of renegotiations done + * returns the current count before it is cleared */ +long wolfSSL_clear_num_renegotiations(WOLFSSL *s) +{ + long total; - if (ctx == NULL) { - return ret; - } + WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations"); + if (s == NULL) + return 0; - /* clear out flags and reset min protocol version */ - minProto = wolfSSL_CTX_get_min_proto_version(ctx); - wolfSSL_CTX_clear_options(ctx, - WOLFSSL_OP_NO_TLSv1 | WOLFSSL_OP_NO_TLSv1_1 | - WOLFSSL_OP_NO_TLSv1_2 | WOLFSSL_OP_NO_TLSv1_3); - wolfSSL_CTX_set_min_proto_version(ctx, minProto); - if (version != 0) { - ctx->maxProto = 0; /* turn max proto flag off */ - return Set_CTX_max_proto_version(ctx, version); - } + total = s->secure_rene_count; + s->secure_rene_count = 0; + return total; +} - /* when 0 is specified as version, try to find out the min version from - * the bottom to top of the protoverTbl. - */ - for (i = NUMBER_OF_PROTOCOLS -1; i >= 0; i--) { - ret = Set_CTX_max_proto_version(ctx, protoVerTbl[i]); - if (ret == WOLFSSL_SUCCESS) { - ctx->maxProto = 1; /* turn max proto flag on */ - break; - } - } - return ret; +/* return the number of renegotiations since wolfSSL_new */ +long wolfSSL_total_renegotiations(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_total_renegotiations"); + return wolfSSL_num_renegotiations(s); } -static int Set_SSL_min_proto_version(WOLFSSL* ssl, int ver) +/* return the number of renegotiations since wolfSSL_new */ +long wolfSSL_num_renegotiations(WOLFSSL* s) { - WOLFSSL_ENTER("Set_SSL_min_proto_version"); - - if (ssl == NULL) { - return WOLFSSL_FAILURE; + if (s == NULL) { + return 0; } - switch (ver) { -#ifndef NO_TLS - case SSL3_VERSION: -#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) - ssl->options.minDowngrade = SSLv3_MINOR; - break; -#endif - case TLS1_VERSION: - #ifdef WOLFSSL_ALLOW_TLSV10 - ssl->options.minDowngrade = TLSv1_MINOR; - break; - #endif - case TLS1_1_VERSION: - #ifndef NO_OLD_TLS - ssl->options.minDowngrade = TLSv1_1_MINOR; - break; - #endif - case TLS1_2_VERSION: - #ifndef WOLFSSL_NO_TLS12 - ssl->options.minDowngrade = TLSv1_2_MINOR; - break; - #endif - case TLS1_3_VERSION: - #ifdef WOLFSSL_TLS13 - ssl->options.minDowngrade = TLSv1_3_MINOR; - break; - #endif -#endif -#ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - #ifndef NO_OLD_TLS - ssl->options.minDowngrade = DTLS_MINOR; - break; - #endif - case DTLS1_2_VERSION: - ssl->options.minDowngrade = DTLSv1_2_MINOR; - break; -#endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; - } + return s->secure_rene_count; +} - switch (ver) { -#ifndef NO_TLS - case TLS1_3_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_2; - FALL_THROUGH; - case TLS1_2_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_1; - FALL_THROUGH; - case TLS1_1_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1; - FALL_THROUGH; - case TLS1_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_SSLv3; - break; - case SSL3_VERSION: - case SSL2_VERSION: - /* Nothing to do here */ - break; -#endif -#ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - case DTLS1_2_VERSION: - break; -#endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); - return WOLFSSL_FAILURE; - } - return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); +/* Is there a renegotiation currently in progress? */ +int wolfSSL_SSL_renegotiate_pending(WOLFSSL *s) +{ + return s && s->options.handShakeDone && + s->options.handShakeState != HANDSHAKE_DONE ? 1 : 0; } +#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */ -int wolfSSL_set_min_proto_version(WOLFSSL* ssl, int version) -{ - int i; - int ret = WOLFSSL_FAILURE;; +#ifdef OPENSSL_EXTRA - WOLFSSL_ENTER("wolfSSL_set_min_proto_version"); +long wolfSSL_clear_options(WOLFSSL* ssl, long opt) +{ + WOLFSSL_ENTER("wolfSSL_clear_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + ssl->options.mask &= ~opt; + return ssl->options.mask; +} +#ifdef HAVE_PK_CALLBACKS +long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) +{ if (ssl == NULL) { return WOLFSSL_FAILURE; } - if (version != 0) { - return Set_SSL_min_proto_version(ssl, version); - } - - /* when 0 is specified as version, try to find out the min version */ - for (i= 0; (unsigned)i < NUMBER_OF_PROTOCOLS; i++) { - ret = Set_SSL_min_proto_version(ssl, protoVerTbl[i]); - if (ret == WOLFSSL_SUCCESS) - break; - } - return ret; + ssl->loggingCtx = arg; + return WOLFSSL_SUCCESS; } +#endif /* HAVE_PK_CALLBACKS */ -static int Set_SSL_max_proto_version(WOLFSSL* ssl, int ver) +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st) { + (void)st; + WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero"); + /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */ + return WOLFSSL_FAILURE; +} +#endif - WOLFSSL_ENTER("Set_SSL_max_proto_version"); +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +{ + WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type"); - if (!ssl) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; + if (s == NULL){ + return BAD_FUNC_ARG; } - switch (ver) { - case SSL2_VERSION: - WOLFSSL_MSG("wolfSSL does not support SSLv2"); - return WOLFSSL_FAILURE; -#ifndef NO_TLS - case SSL3_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1; - FALL_THROUGH; - case TLS1_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_1; - FALL_THROUGH; - case TLS1_1_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_2; - FALL_THROUGH; - case TLS1_2_VERSION: - ssl->options.mask |= WOLFSSL_OP_NO_TLSv1_3; - FALL_THROUGH; - case TLS1_3_VERSION: - /* Nothing to do here */ - break; -#endif -#ifdef WOLFSSL_DTLS - case DTLS1_VERSION: - case DTLS1_2_VERSION: - break; -#endif - default: - WOLFSSL_MSG("Unrecognized protocol version or not compiled in"); + if (type == TLSEXT_STATUSTYPE_ocsp){ + int r = TLSX_UseCertificateStatusRequest(&s->extensions, (byte)type, 0, + s, s->heap, s->devId); + return (long)r; + } else { + WOLFSSL_MSG( + "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type."); return WOLFSSL_FAILURE; } - return CheckSslMethodVersion(ssl->version.major, ssl->options.mask); } -int wolfSSL_set_max_proto_version(WOLFSSL* ssl, int version) +long wolfSSL_get_tlsext_status_type(WOLFSSL *s) { - int i; - int ret = WOLFSSL_FAILURE;; - - WOLFSSL_ENTER("wolfSSL_set_max_proto_version"); - - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } - if (version != 0) { - return Set_SSL_max_proto_version(ssl, version); - } + TLSX* extension; - /* when 0 is specified as version, try to find out the min version from - * the bottom to top of the protoverTbl. - */ - for (i = NUMBER_OF_PROTOCOLS -1; i >= 0; i--) { - ret = Set_SSL_max_proto_version(ssl, protoVerTbl[i]); - if (ret == WOLFSSL_SUCCESS) - break; - } + if (s == NULL) + return WOLFSSL_FATAL_ERROR; + extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST); + return extension != NULL ? TLSEXT_STATUSTYPE_ocsp : WOLFSSL_FATAL_ERROR; +} +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ - return ret; +#ifndef NO_WOLFSSL_STUB +long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); + return WOLFSSL_FAILURE; } +#endif -static int GetMinProtoVersion(int minDowngrade) +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) { - int ret; + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return WOLFSSL_FAILURE; +} +#endif - switch (minDowngrade) { -#ifndef NO_OLD_TLS - #ifdef WOLFSSL_ALLOW_SSLV3 - case SSLv3_MINOR: - ret = SSL3_VERSION; - break; - #endif - #ifdef WOLFSSL_ALLOW_TLSV10 - case TLSv1_MINOR: - ret = TLS1_VERSION; - break; - #endif - case TLSv1_1_MINOR: - ret = TLS1_1_VERSION; - break; +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + return WOLFSSL_FAILURE; +} #endif -#ifndef WOLFSSL_NO_TLS12 - case TLSv1_2_MINOR: - ret = TLS1_2_VERSION; - break; + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); + return WOLFSSL_FAILURE; +} #endif -#ifdef WOLFSSL_TLS13 - case TLSv1_3_MINOR: - ret = TLS1_3_VERSION; - break; + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); + return NULL; +} #endif - default: - ret = 0; - break; - } - return ret; +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +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"); } +#endif -int wolfSSL_CTX_get_min_proto_version(WOLFSSL_CTX* ctx) +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) { - int ret = 0; + WOLFSSL_STUB("SSL_COMP_get_compression_methods"); + return NULL; +} +#endif - WOLFSSL_ENTER("wolfSSL_CTX_get_min_proto_version"); - if (ctx != NULL) { - if (ctx->minProto) { - ret = 0; - } - else { - ret = GetMinProtoVersion(ctx->minDowngrade); - } - } - else { - ret = GetMinProtoVersion(WOLFSSL_MIN_DOWNGRADE); +int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p) +{ + WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num"); + if (p == NULL) { + return WOLFSSL_FATAL_ERROR; } - - WOLFSSL_LEAVE("wolfSSL_CTX_get_min_proto_version", ret); - - return ret; + return (int)p->num; } - -/* returns the maximum allowed protocol version given the 'options' used - * returns WOLFSSL_FATAL_ERROR on no match */ -static int GetMaxProtoVersion(long options) +WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i) { -#ifndef NO_TLS -#ifdef WOLFSSL_TLS13 - if (!(options & WOLFSSL_OP_NO_TLSv1_3)) - return TLS1_3_VERSION; -#endif -#ifndef WOLFSSL_NO_TLS12 - if (!(options & WOLFSSL_OP_NO_TLSv1_2)) - return TLS1_2_VERSION; -#endif -#ifndef NO_OLD_TLS - if (!(options & WOLFSSL_OP_NO_TLSv1_1)) - return TLS1_1_VERSION; - #ifdef WOLFSSL_ALLOW_TLSV10 - if (!(options & WOLFSSL_OP_NO_TLSv1)) - return TLS1_VERSION; - #endif - #ifdef WOLFSSL_ALLOW_SSLV3 - if (!(options & WOLFSSL_OP_NO_SSLv3)) - return SSL3_VERSION; - #endif -#endif -#else - (void)options; -#endif /* NO_TLS */ - return WOLFSSL_FATAL_ERROR; + WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value"); + return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i); } - -/* returns the maximum protocol version for 'ctx' */ -int wolfSSL_CTX_get_max_proto_version(WOLFSSL_CTX* ctx) +#if !defined(NETOS) +void ERR_load_SSL_strings(void) { - int ret = 0; - long options = 0; /* default to nothing set */ - WOLFSSL_ENTER("wolfSSL_CTX_get_max_proto_version"); +} +#endif - if (ctx != NULL) { - options = wolfSSL_CTX_get_options(ctx); - } +#ifdef HAVE_OCSP +long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) +{ + if (s == NULL || resp == NULL) + return 0; - if ((ctx != NULL) && ctx->maxProto) { - ret = 0; - } - else { - ret = GetMaxProtoVersion(options); - } + *resp = s->ocspResp; + return s->ocspRespSz; +} - WOLFSSL_LEAVE("wolfSSL_CTX_get_max_proto_version", ret); +long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, + int len) +{ + if (s == NULL) + return WOLFSSL_FAILURE; - if (ret == WOLFSSL_FATAL_ERROR) { - WOLFSSL_MSG("Error getting max proto version"); - ret = 0; /* setting ret to 0 to match compat return */ - } - return ret; + s->ocspResp = resp; + s->ocspRespSz = len; + + return WOLFSSL_SUCCESS; } -#endif /* OPENSSL_EXTRA */ +#endif /* HAVE_OCSP */ -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ - defined(HAVE_SECRET_CALLBACK) -#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 +#ifdef HAVE_MAX_FRAGMENT +#ifndef NO_WOLFSSL_CLIENT +/** + * Set max fragment tls extension + * @param c a pointer to WOLFSSL_CTX object + * @param mode maximum fragment length mode + * @return 1 on success, otherwise 0 or negative error code */ -size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, - size_t outSz) +int wolfSSL_CTX_set_tlsext_max_fragment_length(WOLFSSL_CTX *c, + unsigned char mode) { - size_t size; + if (c == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) + return BAD_FUNC_ARG; - /* return max size of buffer */ - if (outSz == 0) { - return RAN_LEN; - } + return wolfSSL_CTX_UseMaxFragment(c, mode); +} +/** + * Set max fragment tls extension + * @param c a pointer to WOLFSSL object + * @param mode maximum fragment length mode + * @return 1 on success, otherwise 0 or negative error code + */ +int wolfSSL_set_tlsext_max_fragment_length(WOLFSSL *s, unsigned char mode) +{ + if (s == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) + return BAD_FUNC_ARG; - if (ssl == NULL || out == NULL) { - return 0; - } + return wolfSSL_UseMaxFragment(s, mode); +} +#endif /* NO_WOLFSSL_CLIENT */ +#endif /* HAVE_MAX_FRAGMENT */ - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays struct not saved after handshake"); - return 0; +#endif /* OPENSSL_EXTRA */ + +#ifdef WOLFSSL_HAVE_TLS_UNIQUE +size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count) +{ + byte len = 0; + + WOLFSSL_ENTER("wolfSSL_get_finished"); + + if (!ssl || !buf || count < TLS_FINISHED_SZ) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } - if (outSz > RAN_LEN) { - size = RAN_LEN; + if (ssl->options.side == WOLFSSL_SERVER_END) { + len = ssl->serverFinished_len; + XMEMCPY(buf, ssl->serverFinished, len); } else { - size = outSz; + len = ssl->clientFinished_len; + XMEMCPY(buf, ssl->clientFinished, len); } - - XMEMCPY(out, ssl->arrays->clientRandom, size); - return size; + return len; } -#endif /* !NO_WOLFSSL_CLIENT */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_SECRET_CALLBACK */ -#ifdef OPENSSL_EXTRA +size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count) +{ + byte len = 0; + WOLFSSL_ENTER("wolfSSL_get_peer_finished"); - unsigned long wolfSSLeay(void) - { - return SSLEAY_VERSION_NUMBER; + if (!ssl || !buf || count < TLS_FINISHED_SZ) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } - unsigned long wolfSSL_OpenSSL_version_num(void) - { - return OPENSSL_VERSION_NUMBER; + if (ssl->options.side == WOLFSSL_CLIENT_END) { + len = ssl->serverFinished_len; + XMEMCPY(buf, ssl->serverFinished, len); } - - const char* wolfSSLeay_version(int type) - { - (void)type; -#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L - return wolfSSL_OpenSSL_version(type); -#else - return wolfSSL_OpenSSL_version(); -#endif + else { + len = ssl->clientFinished_len; + XMEMCPY(buf, ssl->clientFinished, len); } -#endif /* OPENSSL_EXTRA */ -#ifdef OPENSSL_EXTRA - void wolfSSL_ERR_free_strings(void) - { - /* handled internally */ - } + return len; +} +#endif /* WOLFSSL_HAVE_TLS_UNIQUE */ - void wolfSSL_cleanup_all_ex_data(void) - { - /* nothing to do here */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(OPENSSL_ALL) +long wolfSSL_get_verify_result(const WOLFSSL *ssl) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; } -#endif /* OPENSSL_EXTRA */ + return ssl->peerVerifyRet; +} +#endif -#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) || \ - defined(HAVE_CURL) - void wolfSSL_ERR_clear_error(void) - { - WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); - #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) - wc_ClearErrorNodes(); - #endif - } +#ifdef OPENSSL_EXTRA + +#ifndef NO_WOLFSSL_STUB +/* shows the number of accepts attempted by CTX in it's lifetime */ +long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_accept"); + (void)ctx; + return 0; +} #endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) - int wolfSSL_clear(WOLFSSL* ssl) - { - WOLFSSL_ENTER("wolfSSL_clear"); +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects attempted CTX in it's lifetime */ +long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_connect"); + (void)ctx; + return 0; +} +#endif - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } - if (!ssl->options.handShakeDone) { - /* Only reset the session if we didn't complete a handshake */ - wolfSSL_FreeSession(ssl->ctx, ssl->session); - ssl->session = wolfSSL_NewSession(ssl->heap); - if (ssl->session == NULL) { - return WOLFSSL_FAILURE; - } - } +#ifndef NO_WOLFSSL_STUB +/* shows the number of accepts completed by CTX in it's lifetime */ +long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good"); + (void)ctx; + return 0; +} +#endif - /* reset error */ - ssl->error = 0; - /* reset option bits */ - ssl->options.isClosed = 0; - ssl->options.connReset = 0; - ssl->options.sentNotify = 0; - ssl->options.closeNotify = 0; - ssl->options.sendVerify = 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 = 0; /* doProcessInit */ - ssl->options.havePeerVerify = 0; - ssl->options.havePeerCert = 0; - ssl->options.peerAuthGood = 0; - ssl->options.tls1_3 = 0; - ssl->options.haveSessionId = 0; - ssl->options.tls = 0; - ssl->options.tls1_1 = 0; - #ifdef WOLFSSL_DTLS - ssl->options.dtlsStateful = 0; - #endif - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - ssl->options.noPskDheKe = 0; - #ifdef HAVE_SUPPORTED_CURVES - ssl->options.onlyPskDheKe = 0; - #endif - #endif - #ifdef HAVE_SESSION_TICKET - #ifdef WOLFSSL_TLS13 - ssl->options.ticketsSent = 0; - #endif - ssl->options.rejectTicket = 0; - #endif - #ifdef WOLFSSL_EARLY_DATA - ssl->earlyData = no_early_data; - ssl->earlyDataSz = 0; - #endif +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects completed by CTX in it's lifetime */ +long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good"); + (void)ctx; + return 0; +} +#endif - #if defined(HAVE_TLS_EXTENSIONS) && !defined(NO_TLS) - TLSX_FreeAll(ssl->extensions, ssl->heap); - ssl->extensions = NULL; - #endif - if (ssl->keys.encryptionOn) { - ForceZero(ssl->buffers.inputBuffer.buffer - - ssl->buffers.inputBuffer.offset, - ssl->buffers.inputBuffer.bufferSize); - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Check(ssl->buffers.inputBuffer.buffer - - ssl->buffers.inputBuffer.offset, - ssl->buffers.inputBuffer.bufferSize); - #endif - } - ssl->keys.encryptionOn = 0; - XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); - - if (InitSSL_Suites(ssl) != WOLFSSL_SUCCESS) - return WOLFSSL_FAILURE; +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ +long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate"); + (void)ctx; + return 0; +} +#endif - if (InitHandshakeHashes(ssl) != 0) - return WOLFSSL_FAILURE; -#ifdef KEEP_PEER_CERT - FreeX509(&ssl->peerCert); - InitX509(&ssl->peerCert, 0, ssl->heap); +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ +long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate"); + (void)ctx; + return 0; +} #endif -#ifdef WOLFSSL_QUIC - wolfSSL_quic_clear(ssl); + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_hits"); + (void)ctx; + return 0; +} #endif - return WOLFSSL_SUCCESS; - } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits"); + (void)ctx; + return 0; +} +#endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_MEMCACHED) - long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode) - { - /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ - WOLFSSL_ENTER("wolfSSL_CTX_set_mode"); - switch(mode) { - case SSL_MODE_ENABLE_PARTIAL_WRITE: - ctx->partialWrite = 1; - break; - #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - case SSL_MODE_RELEASE_BUFFERS: - WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented."); - break; - #endif - case SSL_MODE_AUTO_RETRY: - ctx->autoRetry = 1; - break; - default: - WOLFSSL_MSG("Mode Not Implemented"); - } +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full"); + (void)ctx; + return 0; +} +#endif - /* SSL_MODE_AUTO_RETRY - * Should not return -1 with renegotiation on read/write */ - return mode; - } +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_misses"); + (void)ctx; + return 0; +} +#endif - long wolfSSL_CTX_clear_mode(WOLFSSL_CTX* ctx, long mode) - { - /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ - WOLFSSL_ENTER("wolfSSL_CTX_clear_mode"); - switch(mode) { - case SSL_MODE_ENABLE_PARTIAL_WRITE: - ctx->partialWrite = 0; - break; - #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - case SSL_MODE_RELEASE_BUFFERS: - WOLFSSL_MSG("SSL_MODE_RELEASE_BUFFERS not implemented."); - break; - #endif - case SSL_MODE_AUTO_RETRY: - ctx->autoRetry = 0; - break; - default: - WOLFSSL_MSG("Mode Not Implemented"); - } +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts"); + (void)ctx; + return 0; +} +#endif - /* SSL_MODE_AUTO_RETRY - * Should not return -1 with renegotiation on read/write */ +#ifndef NO_CERTS - return 0; +long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +{ + if (ctx == NULL || ctx->cm == NULL) { + return WOLFSSL_FAILURE; } -#endif -#ifdef WOLFSSL_SESSION_ID_CTX - /* Storing app session context id, this value is inherited by WOLFSSL - * objects created from WOLFSSL_CTX. Any session that is imported with a - * different session context id will be rejected. - * - * ctx structure to set context in - * sid_ctx value of context to set - * sid_ctx_len length of sid_ctx buffer - * - * Returns WOLFSSL_SUCCESS in success case and WOLFSSL_FAILURE when failing - */ - int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx, - const unsigned char* sid_ctx, - unsigned int sid_ctx_len) - { - WOLFSSL_ENTER("wolfSSL_CTX_set_session_id_context"); + ctx->cm->ocspIOCtx = arg; + return WOLFSSL_SUCCESS; +} - /* No application specific context needed for wolfSSL */ - if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) { - return WOLFSSL_FAILURE; - } - XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len); - ctx->sessionCtxSz = (byte)sid_ctx_len; +#endif /* !NO_CERTS */ - return WOLFSSL_SUCCESS; +int wolfSSL_get_read_ahead(const WOLFSSL* ssl) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; } + return ssl->readAhead; +} - /* Storing app session context id. Any session that is imported with a - * different session context id will be rejected. - * - * ssl structure to set context in - * id value of context to set - * len length of sid_ctx buffer - * - * Returns WOLFSSL_SUCCESS in success case and WOLFSSL_FAILURE when failing - */ - int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, - unsigned int len) - { - WOLFSSL_ENTER("wolfSSL_set_session_id_context"); - - if (len > ID_LEN || ssl == NULL || id == NULL) { - return WOLFSSL_FAILURE; - } - XMEMCPY(ssl->sessionCtx, id, len); - ssl->sessionCtxSz = (byte)len; - - return WOLFSSL_SUCCESS; +int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; } -#endif -#ifdef OPENSSL_EXTRA + ssl->readAhead = (byte)v; - #ifndef NO_WOLFSSL_STUB - long wolfSSL_SSL_get_mode(WOLFSSL* ssl) - { - /* TODO: */ - (void)ssl; - WOLFSSL_STUB("SSL_get_mode"); - return 0; - } - #endif + return WOLFSSL_SUCCESS; +} - #ifndef NO_WOLFSSL_STUB - long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx) - { - /* TODO: */ - (void)ctx; - WOLFSSL_STUB("SSL_CTX_get_mode"); - return 0; - } - #endif - #ifndef NO_WOLFSSL_STUB - void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m) - { - /* TODO: maybe? */ - (void)ctx; - (void)m; - WOLFSSL_STUB("SSL_CTX_set_default_read_ahead"); +int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; } - #endif + + return ctx->readAhead; +} - long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) - { - (void)ctx; - #ifndef NO_SESSION_CACHE - return (long)(SESSIONS_PER_ROW * SESSION_ROWS); - #else - return 0; - #endif +int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; } + ctx->readAhead = (byte)v; - /* returns the unsigned error value and increments the pointer into the - * error queue. - * - * file pointer to file name - * line gets set to line number of error when not NULL - */ - unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line) - { - #ifdef WOLFSSL_HAVE_ERROR_QUEUE - int ret = wc_PullErrorNode(file, NULL, line); - if (ret < 0) { - if (ret == BAD_STATE_E) return 0; /* no errors in queue */ - WOLFSSL_MSG("Issue getting error node"); - WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret); - ret = 0 - ret; /* return absolute value of error */ + return WOLFSSL_SUCCESS; +} - /* panic and try to clear out nodes */ - wc_ClearErrorNodes(); - } - return (unsigned long)ret; - #else - (void)file; - (void)line; - return 0; - #endif +long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, + void* arg) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; } + ctx->userPRFArg = arg; + return WOLFSSL_SUCCESS; +} -#if (defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA)) && \ - (!defined(_WIN32) && !defined(NO_ERROR_QUEUE)) - static const char WOLFSSL_SYS_ACCEPT_T[] = "accept"; - static const char WOLFSSL_SYS_BIND_T[] = "bind"; - static const char WOLFSSL_SYS_CONNECT_T[] = "connect"; - static const char WOLFSSL_SYS_FOPEN_T[] = "fopen"; - static const char WOLFSSL_SYS_FREAD_T[] = "fread"; - static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo"; - static const char WOLFSSL_SYS_GETSOCKOPT_T[] = "getsockopt"; - static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname"; - static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname"; - static const char WOLFSSL_SYS_GETNAMEINFO_T[] = "getnameinfo"; - static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname"; - static const char WOLFSSL_SYS_IOCTLSOCKET_T[] = "ioctlsocket"; - static const char WOLFSSL_SYS_LISTEN_T[] = "listen"; - static const char WOLFSSL_SYS_OPENDIR_T[] = "opendir"; - static const char WOLFSSL_SYS_SETSOCKOPT_T[] = "setsockopt"; - static const char WOLFSSL_SYS_SOCKET_T[] = "socket"; +#endif /* OPENSSL_EXTRA */ - /* switch with int mapped to function name for compatibility */ - static const char* wolfSSL_ERR_sys_func(int fun) - { - switch (fun) { - case WOLFSSL_SYS_ACCEPT: return WOLFSSL_SYS_ACCEPT_T; - case WOLFSSL_SYS_BIND: return WOLFSSL_SYS_BIND_T; - case WOLFSSL_SYS_CONNECT: return WOLFSSL_SYS_CONNECT_T; - case WOLFSSL_SYS_FOPEN: return WOLFSSL_SYS_FOPEN_T; - case WOLFSSL_SYS_FREAD: return WOLFSSL_SYS_FREAD_T; - case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T; - case WOLFSSL_SYS_GETSOCKOPT: return WOLFSSL_SYS_GETSOCKOPT_T; - case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T; - case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T; - case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T; - case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T; - case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T; - case WOLFSSL_SYS_LISTEN: return WOLFSSL_SYS_LISTEN_T; - case WOLFSSL_SYS_OPENDIR: return WOLFSSL_SYS_OPENDIR_T; - case WOLFSSL_SYS_SETSOCKOPT: return WOLFSSL_SYS_SETSOCKOPT_T; - case WOLFSSL_SYS_SOCKET: return WOLFSSL_SYS_SOCKET_T; - default: - return "NULL"; - } - } -#endif /* DEBUG_WOLFSSL */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +int wolfSSL_sk_num(const WOLFSSL_STACK* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_num"); + if (sk == NULL) + return 0; + return (int)sk->num; +} +void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_value"); - void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file, - int line) - { - WOLFSSL_ENTER("wolfSSL_ERR_put_error"); + for (; sk != NULL && i > 0; i--) + sk = sk->next; + if (sk == NULL) + return NULL; - #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA) - (void)fun; - (void)err; - (void)file; - (void)line; - WOLFSSL_MSG("Not compiled in debug mode"); - #elif defined(OPENSSL_EXTRA) && \ - (defined(_WIN32) || defined(NO_ERROR_QUEUE)) - (void)fun; - (void)file; - (void)line; - WOLFSSL_ERROR(err); - #else - WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line, - file, NULL); - #endif - (void)lib; + switch (sk->type) { + case STACK_TYPE_X509: + return (void*)sk->data.x509; + case STACK_TYPE_GEN_NAME: + return (void*)sk->data.gn; + case STACK_TYPE_BIO: + return (void*)sk->data.bio; + case STACK_TYPE_OBJ: + return (void*)sk->data.obj; + case STACK_TYPE_STRING: + return (void*)sk->data.string; + case STACK_TYPE_CIPHER: + return (void*)&sk->data.cipher; + case STACK_TYPE_ACCESS_DESCRIPTION: + return (void*)sk->data.access; + case STACK_TYPE_X509_EXT: + return (void*)sk->data.ext; + case STACK_TYPE_X509_REQ_ATTR: + return (void*)sk->data.generic; + case STACK_TYPE_NULL: + return (void*)sk->data.generic; + case STACK_TYPE_X509_NAME: + return (void*)sk->data.name; + case STACK_TYPE_X509_NAME_ENTRY: + return (void*)sk->data.name_entry; + case STACK_TYPE_CONF_VALUE: + #ifdef OPENSSL_EXTRA + return (void*)sk->data.conf; + #else + return NULL; + #endif + case STACK_TYPE_X509_INFO: + return (void*)sk->data.info; + case STACK_TYPE_BY_DIR_entry: + return (void*)sk->data.dir_entry; + case STACK_TYPE_BY_DIR_hash: + return (void*)sk->data.dir_hash; + case STACK_TYPE_X509_OBJ: + return (void*)sk->data.x509_obj; + case STACK_TYPE_DIST_POINT: + return (void*)sk->data.dp; + case STACK_TYPE_X509_CRL: + return (void*)sk->data.crl; + default: + return (void*)sk->data.generic; } +} +/* copies over data of "in" to "out" */ +static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out) +{ + if (in == NULL || out == NULL) + return; - /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for - * more flexibility. - * - * file output pointer to file where error happened - * line output to line number of error - * data output data. Is a string if ERR_TXT_STRING flag is used - * flags output format of output - * - * Returns the error value or 0 if no errors are in the queue - */ - unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, - const char** data, int *flags) - { -#ifdef WOLFSSL_HAVE_ERROR_QUEUE - int ret; - - WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data"); - - if (flags != NULL) - *flags = ERR_TXT_STRING; /* Clear the flags */ - - ret = wc_PullErrorNode(file, data, line); - if (ret < 0) { - if (ret == BAD_STATE_E) return 0; /* no errors in queue */ - WOLFSSL_MSG("Error with pulling error node!"); - WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret); - ret = 0 - ret; /* return absolute value of error */ - - /* panic and try to clear out nodes */ - wc_ClearErrorNodes(); - } - - return (unsigned long)ret; -#else - WOLFSSL_ENTER("wolfSSL_ERR_get_error_line_data"); - WOLFSSL_MSG("Error queue turned off, can not get error line"); - (void)file; - (void)line; - (void)data; - (void)flags; - return 0; -#endif - } + *out = *in; +} -#endif /* OPENSSL_EXTRA */ +WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) +{ + WOLFSSL_STACK* ret = NULL; + WOLFSSL_STACK* last = NULL; -#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \ - (defined(OPENSSL_EXTRA) && defined(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; - #else - DecodedCert cert[1]; - #endif - if (x509 == NULL || in == NULL || len <= 0) - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_sk_dup"); - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_DCERT); - if (cert == NULL) - return MEMORY_E; - #endif + while (sk) { + WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); - /* 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) { - /* Check if x509 was not previously initialized by wolfSSL_X509_new() */ - if (x509->dynamicMemory != TRUE) - InitX509(x509, 0, NULL); - ret = CopyDecodedToX509(x509, cert); + if (!cur) { + WOLFSSL_MSG("wolfSSL_sk_new_node error"); + goto error; } - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); - #endif - - return ret; - } -#endif /* (KEEP_PEER_CERT & SESSION_CERTS) || (OPENSSL_EXTRA & SESSION_CERTS) */ - -#ifdef KEEP_PEER_CERT - WOLFSSL_ABI - WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) - { - WOLFSSL_X509* ret = NULL; - WOLFSSL_ENTER("wolfSSL_get_peer_certificate"); - if (ssl != NULL) { - if (ssl->peerCert.issuer.sz) - ret = wolfSSL_X509_dup(&ssl->peerCert); -#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) { - ret = wolfSSL_X509_dup(&ssl->peerCert); - } - } -#endif + if (!ret) { + /* Set first node */ + ret = cur; } - WOLFSSL_LEAVE("wolfSSL_get_peer_certificate", ret != NULL); - return ret; - } - -#endif /* KEEP_PEER_CERT */ -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) -/* Return stack of peer certs. - * Caller does not need to free return. The stack is Free'd when WOLFSSL* ssl is. - */ -WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); + if (last) { + last->next = cur; + } - if (ssl == NULL) - return NULL; + XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); - /* Try to populate if NULL or empty */ - if (ssl->peerCertChain == NULL || - wolfSSL_sk_X509_num(ssl->peerCertChain) == 0) - wolfSSL_set_peer_cert_chain((WOLFSSL*) ssl); - return ssl->peerCertChain; -} + /* We will allocate new memory for this */ + XMEMSET(&cur->data, 0, sizeof(cur->data)); + cur->next = NULL; -#ifndef WOLFSSL_QT -static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, - WOLFSSL_X509 *x); -/** - * Recursively push the issuer CA chain onto the stack - * @param cm The cert manager that is queried for the issuer - * @param x This cert's issuer will be queried in cm - * @param sk The issuer is pushed onto this stack - * @return WOLFSSL_SUCCESS on success - * WOLFSSL_FAILURE on no issuer found - * WOLFSSL_FATAL_ERROR on a fatal error - */ -static int PushCAx509Chain(WOLFSSL_CERT_MANAGER* cm, - WOLFSSL_X509 *x, WOLFSSL_STACK* sk) -{ - WOLFSSL_X509* issuer[MAX_CHAIN_DEPTH]; - int i; - int push = 1; - int ret = WOLFSSL_SUCCESS; - - for (i = 0; i < MAX_CHAIN_DEPTH; i++) { - if (x509GetIssuerFromCM(&issuer[i], cm, x) - != WOLFSSL_SUCCESS) - break; - x = issuer[i]; - } - if (i == 0) /* No further chain found */ - return WOLFSSL_FAILURE; - i--; - for (; i >= 0; i--) { - if (push) { - if (wolfSSL_sk_X509_push(sk, issuer[i]) != WOLFSSL_SUCCESS) { - wolfSSL_X509_free(issuer[i]); - ret = WOLFSSL_FATAL_ERROR; - push = 0; /* Free the rest of the unpushed certs */ - } - } - else { - wolfSSL_X509_free(issuer[i]); + switch (sk->type) { + case STACK_TYPE_X509: + if (!sk->data.x509) + break; + cur->data.x509 = wolfSSL_X509_dup(sk->data.x509); + if (!cur->data.x509) { + WOLFSSL_MSG("wolfSSL_X509_dup error"); + goto error; + } + break; + case STACK_TYPE_CIPHER: + wolfSSL_CIPHER_copy(&sk->data.cipher, &cur->data.cipher); + break; + case STACK_TYPE_GEN_NAME: + if (!sk->data.gn) + break; + cur->data.gn = wolfSSL_GENERAL_NAME_dup(sk->data.gn); + if (!cur->data.gn) { + WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error"); + goto error; + } + break; + case STACK_TYPE_OBJ: + if (!sk->data.obj) + break; + cur->data.obj = wolfSSL_ASN1_OBJECT_dup(sk->data.obj); + if (!cur->data.obj) { + WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error"); + goto error; + } + break; + case STACK_TYPE_BIO: + case STACK_TYPE_STRING: + case STACK_TYPE_ACCESS_DESCRIPTION: + case STACK_TYPE_X509_EXT: + case STACK_TYPE_X509_REQ_ATTR: + case STACK_TYPE_NULL: + case STACK_TYPE_X509_NAME: + case STACK_TYPE_X509_NAME_ENTRY: + case STACK_TYPE_CONF_VALUE: + case STACK_TYPE_X509_INFO: + case STACK_TYPE_BY_DIR_entry: + case STACK_TYPE_BY_DIR_hash: + case STACK_TYPE_X509_OBJ: + case STACK_TYPE_DIST_POINT: + case STACK_TYPE_X509_CRL: + default: + WOLFSSL_MSG("Unsupported stack type"); + goto error; } + + sk = sk->next; + last = cur; } return ret; + +error: + if (ret) { + wolfSSL_sk_GENERAL_NAME_free(ret); + } + return NULL; } -#endif /* !WOLFSSL_QT */ -/* Builds up and creates a stack of peer certificates for ssl->peerCertChain - based off of the ssl session chain. Attempts to place CA certificates - at the bottom of the stack. Returns stack of WOLFSSL_X509 certs or - NULL on failure */ -WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) + +WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk) { - WOLFSSL_STACK* sk; - WOLFSSL_X509* x509; - int i = 0; - int ret; - WOLFSSL_ENTER("wolfSSL_set_peer_cert_chain"); - if ((ssl == NULL) || (ssl->session->chain.count == 0)) - return NULL; + WOLFSSL_STACK* ret = NULL; + WOLFSSL_STACK** prev = &ret; - sk = wolfSSL_sk_X509_new_null(); - i = ssl->session->chain.count-1; - for (; i >= 0; i--) { - x509 = wolfSSL_X509_new_ex(ssl->heap); - if (x509 == NULL) { - WOLFSSL_MSG("Error Creating X509"); - wolfSSL_sk_X509_pop_free(sk, NULL); - return NULL; - } - ret = DecodeToX509(x509, ssl->session->chain.certs[i].buffer, - ssl->session->chain.certs[i].length); -#if !defined(WOLFSSL_QT) - if (ret == 0 && i == ssl->session->chain.count-1) { - /* On the last element in the chain try to add the CA chain - * first if we have one for this cert */ - SSL_CM_WARNING(ssl); - if (PushCAx509Chain(SSL_CM(ssl), x509, sk) - == WOLFSSL_FATAL_ERROR) { - ret = WOLFSSL_FATAL_ERROR; - } - } -#endif + WOLFSSL_ENTER("wolfSSL_shallow_sk_dup"); - if (ret != 0 || wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error decoding cert"); - wolfSSL_X509_free(x509); - wolfSSL_sk_X509_pop_free(sk, NULL); - return NULL; + for (; sk != NULL; sk = sk->next) { + WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); + + if (!cur) { + WOLFSSL_MSG("wolfSSL_sk_new_node error"); + goto error; } - } - if (sk == NULL) { - WOLFSSL_MSG("Null session chain"); + XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); + cur->next = NULL; + + *prev = cur; + prev = &cur->next; } -#if defined(OPENSSL_ALL) - else if (ssl->options.side == WOLFSSL_SERVER_END) { - /* to be compliant with openssl - first element is kept as peer cert on server side.*/ - wolfSSL_sk_X509_pop(sk); + return ret; + +error: + if (ret) { + wolfSSL_sk_free(ret); } -#endif - if (ssl->peerCertChain != NULL) - wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); - /* This is Free'd when ssl is Free'd */ - ssl->peerCertChain = sk; - return sk; + return NULL; } -#endif /* SESSION_CERTS && OPENSSL_EXTRA */ - -#ifndef NO_CERTS -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -/* create a generic wolfSSL stack node - * returns a new WOLFSSL_STACK structure on success */ -WOLFSSL_STACK* wolfSSL_sk_new_node(void* heap) +/* Free the just the stack structure */ +void wolfSSL_sk_free(WOLFSSL_STACK* sk) { - WOLFSSL_STACK* sk; - WOLFSSL_ENTER("wolfSSL_sk_new_node"); + WOLFSSL_ENTER("wolfSSL_sk_free"); - sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), heap, - DYNAMIC_TYPE_OPENSSL); - if (sk != NULL) { - XMEMSET(sk, 0, sizeof(*sk)); - sk->heap = heap; + while (sk != NULL) { + WOLFSSL_STACK* next = sk->next; + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = next; } - - return sk; } -/* free's node but does not free internal data such as in->data.x509 */ -void wolfSSL_sk_free_node(WOLFSSL_STACK* in) +/* Frees each node in the stack and frees the stack. + */ +void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, + void (*f) (void*)) { - if (in != NULL) { - XFREE(in, in->heap, DYNAMIC_TYPE_OPENSSL); - } + WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free"); + wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); } -/* pushes node "in" onto "stack" and returns pointer to the new stack on success - * also handles internal "num" for number of nodes on stack - * return WOLFSSL_SUCCESS on success - */ -int wolfSSL_sk_push_node(WOLFSSL_STACK** stack, WOLFSSL_STACK* in) +/* return 1 on success 0 on fail */ +int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic) { - if (stack == NULL || in == NULL) { - return WOLFSSL_FAILURE; - } - - if (*stack == NULL) { - in->num = 1; - *stack = in; - return WOLFSSL_SUCCESS; - } + WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push"); - in->num = (*stack)->num + 1; - in->next = *stack; - *stack = in; - return WOLFSSL_SUCCESS; + return wolfSSL_sk_push(sk, generic); } - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) -static WC_INLINE int compare_WOLFSSL_CIPHER( - WOLFSSL_CIPHER *a, - WOLFSSL_CIPHER *b) +void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk) { - if ((a->cipherSuite0 == b->cipherSuite0) && - (a->cipherSuite == b->cipherSuite) && - (a->ssl == b->ssl) && - (XMEMCMP(a->description, b->description, sizeof a->description) == 0) && - (a->offset == b->offset) && - (a->in_stack == b->in_stack) && - (a->bits == b->bits)) - return 0; - else - return -1; + wolfSSL_sk_free(sk); } -#endif /* OPENSSL_ALL || WOLFSSL_QT */ - -/* return 1 on success 0 on fail */ -int wolfSSL_sk_push(WOLFSSL_STACK* sk, const void *data) +/* Pop off data from the stack. Checks that the type matches the stack type. + * + * @param [in, out] sk Stack of objects. + * @param [in] type Type of stack. + * @return Object on success. + * @return NULL when stack is NULL or no nodes left in stack. + */ +void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type) { WOLFSSL_STACK* node; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - WOLFSSL_CIPHER ciph; -#endif - WOLFSSL_ENTER("wolfSSL_sk_push"); + void* data = NULL; - if (!sk) { - return WOLFSSL_FAILURE; - } + /* Check we have a stack passed in of the right type. */ + if ((sk != NULL) && (sk->type == type)) { + /* Get the next node to become the new first node. */ + node = sk->next; + /* Get the ASN.1 OBJECT_ID object in the first node. */ + data = sk->data.generic; - /* Check if empty data */ - switch (sk->type) { - case STACK_TYPE_CIPHER: -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - /* check if entire struct is zero */ - XMEMSET(&ciph, 0, sizeof(WOLFSSL_CIPHER)); - if (compare_WOLFSSL_CIPHER(&sk->data.cipher, &ciph) == 0) { - sk->data.cipher = *(WOLFSSL_CIPHER*)data; - sk->num = 1; - if (sk->hash_fn) { - sk->hash = sk->hash_fn(&sk->data.cipher); - } - return WOLFSSL_SUCCESS; - } - break; -#endif - case STACK_TYPE_X509: - case STACK_TYPE_GEN_NAME: - case STACK_TYPE_BIO: - case STACK_TYPE_OBJ: - case STACK_TYPE_STRING: - case STACK_TYPE_ACCESS_DESCRIPTION: - case STACK_TYPE_X509_EXT: - case STACK_TYPE_X509_REQ_ATTR: - case STACK_TYPE_NULL: - case STACK_TYPE_X509_NAME: - case STACK_TYPE_X509_NAME_ENTRY: - case STACK_TYPE_CONF_VALUE: - case STACK_TYPE_X509_INFO: - case STACK_TYPE_BY_DIR_entry: - case STACK_TYPE_BY_DIR_hash: - case STACK_TYPE_X509_OBJ: - case STACK_TYPE_DIST_POINT: - case STACK_TYPE_X509_CRL: - default: - /* All other types are pointers */ - if (!sk->data.generic) { - sk->data.generic = (void*)data; - sk->num = 1; -#ifdef OPENSSL_ALL - if (sk->hash_fn) { - sk->hash = sk->hash_fn(sk->data.generic); - } -#endif - return WOLFSSL_SUCCESS; - } - break; - } + /* Check whether there is a next node. */ + if (node != NULL) { + /* Move content out of next node into current node. */ + sk->data.obj = node->data.obj; + sk->next = node->next; + /* Dispose of node. */ + XFREE(node, NULL, DYNAMIC_TYPE_ASN1); + } + else { + /* No more nodes - clear out data. */ + sk->data.obj = NULL; + } - /* stack already has value(s) create a new node and add more */ - node = wolfSSL_sk_new_node(sk->heap); - if (!node) { - WOLFSSL_MSG("Memory error"); - return WOLFSSL_FAILURE; + /* Decrement count as long as we thought we had nodes. */ + if (sk->num > 0) { + sk->num -= 1; + } } - /* push new x509 onto head of stack */ - node->next = sk->next; - node->type = sk->type; - sk->next = node; - sk->num += 1; + return data; +} -#ifdef OPENSSL_ALL - node->hash_fn = sk->hash_fn; - node->hash = sk->hash; - sk->hash = 0; +/* Free all nodes in a stack including the pushed objects */ +void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + wolfSSL_sk_freefunc func) +{ + WOLFSSL_ENTER("wolfSSL_sk_pop_free"); + + if (sk == NULL) { + /* pop_free can be called with NULL, do not print bad argument */ + return; + } + #if defined(WOLFSSL_QT) + /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free). + * By using OPENSSL_sk_free for free causes access violation. + * Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free + * is needed even the func isn't NULL. + */ + if (sk->type == STACK_TYPE_ACCESS_DESCRIPTION) { + func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free; + } + #endif + if (func == NULL) { + switch(sk->type) { + case STACK_TYPE_ACCESS_DESCRIPTION: + #if defined(OPENSSL_ALL) + func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free; + #endif + break; + case STACK_TYPE_X509: + func = (wolfSSL_sk_freefunc)wolfSSL_X509_free; + break; + case STACK_TYPE_X509_OBJ: + #ifdef OPENSSL_ALL + func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free; + #endif + break; + case STACK_TYPE_OBJ: + func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free; + break; + case STACK_TYPE_DIST_POINT: + #ifdef OPENSSL_EXTRA + func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free; + #endif + break; + case STACK_TYPE_GEN_NAME: + func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free; + break; + case STACK_TYPE_STRING: + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free; + #endif + break; + case STACK_TYPE_X509_NAME: + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \ + && !defined(WOLFCRYPT_ONLY) + func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free; + #endif + break; + case STACK_TYPE_X509_NAME_ENTRY: + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \ + && !defined(WOLFCRYPT_ONLY) + func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free; + #endif + break; + case STACK_TYPE_X509_EXT: + #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) + func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free; + #endif + break; + case STACK_TYPE_X509_REQ_ATTR: + #if defined(OPENSSL_ALL) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ)) + func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free; + #endif + break; + case STACK_TYPE_CONF_VALUE: + #if defined(OPENSSL_ALL) + func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free; + #endif + break; + case STACK_TYPE_X509_INFO: + #if defined(OPENSSL_ALL) + func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free; + #endif + break; + case STACK_TYPE_BIO: +#if !defined(NO_BIO) && defined(OPENSSL_EXTRA) + func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree; #endif - switch (sk->type) { - case STACK_TYPE_CIPHER: -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - node->data.cipher = sk->data.cipher; - sk->data.cipher = *(WOLFSSL_CIPHER*)data; - if (sk->hash_fn) { - sk->hash = sk->hash_fn(&sk->data.cipher); - } - break; + break; + case STACK_TYPE_BY_DIR_entry: +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free; #endif - case STACK_TYPE_X509: - case STACK_TYPE_GEN_NAME: - case STACK_TYPE_BIO: - case STACK_TYPE_OBJ: - case STACK_TYPE_STRING: - case STACK_TYPE_ACCESS_DESCRIPTION: - case STACK_TYPE_X509_EXT: - case STACK_TYPE_X509_REQ_ATTR: - case STACK_TYPE_NULL: - case STACK_TYPE_X509_NAME: - case STACK_TYPE_X509_NAME_ENTRY: - case STACK_TYPE_CONF_VALUE: - case STACK_TYPE_X509_INFO: - case STACK_TYPE_BY_DIR_entry: - case STACK_TYPE_BY_DIR_hash: - case STACK_TYPE_X509_OBJ: - case STACK_TYPE_DIST_POINT: - case STACK_TYPE_X509_CRL: - default: - /* All other types are pointers */ - node->data.generic = sk->data.generic; - sk->data.generic = (void*)data; -#ifdef OPENSSL_ALL - if (sk->hash_fn) { - sk->hash = sk->hash_fn(sk->data.generic); - } + break; + case STACK_TYPE_BY_DIR_hash: +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free; #endif - break; + break; + case STACK_TYPE_X509_CRL: +#if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) + func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free; +#endif + break; + case STACK_TYPE_CIPHER: + case STACK_TYPE_NULL: + default: + break; + } } - return WOLFSSL_SUCCESS; -} - -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + while (sk != NULL) { + WOLFSSL_STACK* next = sk->next; -#ifdef OPENSSL_EXTRA + if (func != NULL) { + if (sk->type != STACK_TYPE_CIPHER) + func(sk->data.generic); + } + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = next; + } +} -/* returns the node at index "idx", NULL if not found */ -WOLFSSL_STACK* wolfSSL_sk_get_node(WOLFSSL_STACK* sk, int idx) -{ - int i; - WOLFSSL_STACK* ret = NULL; - WOLFSSL_STACK* current; +/* Creates a new stack of the requested type. + * + * @param [in] type Type of stack. + * @return Empty stack on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type) +{ + WOLFSSL_STACK* sk; - current = sk; - for (i = 0; i <= idx && current != NULL; i++) { - if (i == idx) { - ret = current; - break; - } - current = current->next; + /* Allocate a new stack - first node. */ + sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (sk == NULL) { + WOLFSSL_MSG("WOLFSSL_STACK memory error"); } - return ret; + else { + /* Clear node and set type. */ + XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); + sk->type = type; + } + + return sk; +} + +/* Creates and returns a new null stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_null(void) +{ + WOLFSSL_ENTER("wolfSSL_sk_new_null"); + + return wolfssl_sk_new_type(STACK_TYPE_NULL); } +int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk) +{ + if (sk == NULL) + return 0; + return (int)sk->num; +} -#endif /* OPENSSL_EXTRA */ +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #ifdef OPENSSL_EXTRA -#if defined(OPENSSL_ALL) - -void *wolfSSL_lh_retrieve(WOLFSSL_STACK *sk, void *data) +#if defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM) +int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) { - unsigned long hash; + int ret = WOLFSSL_FATAL_ERROR; - WOLFSSL_ENTER("wolfSSL_lh_retrieve"); + WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); + if (ssl != NULL && fname != NULL) + { + #ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ + #else + byte staticBuffer[FILE_BUFFER_SIZE]; + #endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + XFILE file; + long sz = 0; + WOLFSSL_CTX* ctx = ssl->ctx; + WOLFSSL_X509* peer_cert = &ssl->peerCert; + DerBuffer* fileDer = NULL; - if (!sk || !data) { - WOLFSSL_MSG("Bad parameters"); - return NULL; - } + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return WOLFSSL_BAD_FILE; - if (!sk->hash_fn) { - WOLFSSL_MSG("No hash function defined"); - return NULL; - } + if (XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(file); + if (XFSEEK(file, 0, XSEEK_SET) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } - hash = sk->hash_fn(data); + if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + WOLFSSL_MSG("cmp_peer_cert_to_file size error"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } - while (sk) { - /* Calc hash if not done so yet */ - if (!sk->hash) { - switch (sk->type) { - case STACK_TYPE_CIPHER: - sk->hash = sk->hash_fn(&sk->data.cipher); - break; - case STACK_TYPE_X509: - case STACK_TYPE_GEN_NAME: - case STACK_TYPE_BIO: - case STACK_TYPE_OBJ: - case STACK_TYPE_STRING: - case STACK_TYPE_ACCESS_DESCRIPTION: - case STACK_TYPE_X509_EXT: - case STACK_TYPE_X509_REQ_ATTR: - case STACK_TYPE_NULL: - case STACK_TYPE_X509_NAME: - case STACK_TYPE_X509_NAME_ENTRY: - case STACK_TYPE_CONF_VALUE: - case STACK_TYPE_X509_INFO: - case STACK_TYPE_BY_DIR_entry: - case STACK_TYPE_BY_DIR_hash: - case STACK_TYPE_X509_OBJ: - case STACK_TYPE_DIST_POINT: - case STACK_TYPE_X509_CRL: - default: - sk->hash = sk->hash_fn(sk->data.generic); - break; - } + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); + dynamic = 1; } - if (sk->hash == hash) { - switch (sk->type) { - case STACK_TYPE_CIPHER: - return &sk->data.cipher; - case STACK_TYPE_X509: - case STACK_TYPE_GEN_NAME: - case STACK_TYPE_BIO: - case STACK_TYPE_OBJ: - case STACK_TYPE_STRING: - case STACK_TYPE_ACCESS_DESCRIPTION: - case STACK_TYPE_X509_EXT: - case STACK_TYPE_X509_REQ_ATTR: - case STACK_TYPE_NULL: - case STACK_TYPE_X509_NAME: - case STACK_TYPE_X509_NAME_ENTRY: - case STACK_TYPE_CONF_VALUE: - case STACK_TYPE_X509_INFO: - case STACK_TYPE_BY_DIR_entry: - case STACK_TYPE_BY_DIR_hash: - case STACK_TYPE_X509_OBJ: - case STACK_TYPE_DIST_POINT: - case STACK_TYPE_X509_CRL: - default: - return sk->data.generic; - } + + if ((myBuffer != NULL) && + (sz > 0) && + (XFREAD(myBuffer, 1, (size_t)sz, file) == (size_t)sz) && + (PemToDer(myBuffer, (long)sz, CERT_TYPE, + &fileDer, ctx->heap, NULL, NULL) == 0) && + (fileDer->length != 0) && + (fileDer->length == peer_cert->derCert->length) && + (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, + fileDer->length) == 0)) + { + ret = 0; } - sk = sk->next; - } - return NULL; -} + FreeDer(&fileDer); -#endif /* OPENSSL_ALL */ + if (dynamic) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + XFCLOSE(file); + } + + return ret; +} +#endif #endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +const WOLFSSL_ObjectInfo wolfssl_object_info[] = { +#ifndef NO_CERTS + /* oidCertExtType */ + { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints", + "X509v3 Basic Constraints"}, + { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName", + "X509v3 Subject Alternative Name"}, + { NID_crl_distribution_points, CRL_DIST_OID, oidCertExtType, + "crlDistributionPoints", "X509v3 CRL Distribution Points"}, + { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess", + "Authority Information Access"}, + { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType, + "authorityKeyIdentifier", "X509v3 Authority Key Identifier"}, + { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType, + "subjectKeyIdentifier", "X509v3 Subject Key Identifier"}, + { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage", + "X509v3 Key Usage"}, + { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType, + "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"}, + { NID_ext_key_usage, EXT_KEY_USAGE_OID, oidCertExtType, + "extendedKeyUsage", "X509v3 Extended Key Usage"}, + { NID_name_constraints, NAME_CONS_OID, oidCertExtType, + "nameConstraints", "X509v3 Name Constraints"}, + { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType, + "certificatePolicies", "X509v3 Certificate Policies"}, -/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function - KEEP_OUR_CERT is to insure ability for returning ssl certificate */ -#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ - defined(KEEP_OUR_CERT) -WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) -{ - if (ssl == NULL) { - return NULL; - } + /* oidCertAuthInfoType */ + { NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP", + "OCSP"}, + { NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType, + "caIssuers", "CA Issuers"}, - if (ssl->buffers.weOwnCert) { - if (ssl->ourCert == NULL) { - if (ssl->buffers.certificate == NULL) { - WOLFSSL_MSG("Certificate buffer not set!"); - return NULL; - } - #ifndef WOLFSSL_X509_STORE_CERTS - ssl->ourCert = wolfSSL_X509_d2i_ex(NULL, - ssl->buffers.certificate->buffer, - ssl->buffers.certificate->length, - ssl->heap); - #endif - } - return ssl->ourCert; - } - else { /* if cert not owned get parent ctx cert or return null */ - if (ssl->ctx) { - if (ssl->ctx->ourCert == NULL) { - if (ssl->ctx->certificate == NULL) { - WOLFSSL_MSG("Ctx Certificate buffer not set!"); - return NULL; - } - #ifndef WOLFSSL_X509_STORE_CERTS - ssl->ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, - ssl->ctx->certificate->buffer, - ssl->ctx->certificate->length, - ssl->heap); - #endif - ssl->ctx->ownOurCert = 1; - } - return ssl->ctx->ourCert; - } - } + /* oidCertPolicyType */ + { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy", + "X509v3 Any Policy"}, - return NULL; -} + /* oidCertAltNameType */ + { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""}, -WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx) -{ - if (ctx) { - if (ctx->ourCert == NULL) { - if (ctx->certificate == NULL) { - WOLFSSL_MSG("Ctx Certificate buffer not set!"); - return NULL; - } - #ifndef WOLFSSL_X509_STORE_CERTS - ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, - ctx->certificate->buffer, - ctx->certificate->length, ctx->heap); - #endif - ctx->ownOurCert = 1; - } - return ctx->ourCert; - } - return NULL; -} -#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ -#endif /* NO_CERTS */ + /* oidCertKeyUseType */ + { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType, + "anyExtendedKeyUsage", "Any Extended Key Usage"}, + { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType, + "serverAuth", "TLS Web Server Authentication"}, + { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType, + "clientAuth", "TLS Web Client Authentication"}, + { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType, + "OCSPSigning", "OCSP Signing"}, -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -void wolfSSL_set_connect_state(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_set_connect_state"); - if (ssl == NULL) { - WOLFSSL_MSG("WOLFSSL struct pointer passed in was null"); - return; - } + /* oidCertNameType */ + { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"}, +#if !defined(WOLFSSL_CERT_REQ) + { NID_surname, NID_surname, oidCertNameType, "SN", "surname"}, +#endif + { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber", + "serialNumber"}, + { NID_userId, NID_userId, oidCertNameType, "UID", "userid"}, + { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"}, + { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"}, + { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST", + "stateOrProvinceName"}, + { NID_streetAddress, NID_streetAddress, oidCertNameType, "street", + "streetAddress"}, + { NID_organizationName, NID_organizationName, oidCertNameType, "O", + "organizationName"}, + { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType, + "OU", "organizationalUnitName"}, + { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress", + "emailAddress"}, + { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC", + "domainComponent"}, + { NID_favouriteDrink, NID_favouriteDrink, oidCertNameType, "favouriteDrink", + "favouriteDrink"}, + { NID_businessCategory, NID_businessCategory, oidCertNameType, + "businessCategory", "businessCategory"}, + { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, + "jurisdictionC", "jurisdictionCountryName"}, + { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName, + oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"}, + { NID_postalCode, NID_postalCode, oidCertNameType, "postalCode", + "postalCode"}, + { NID_userId, NID_userId, oidCertNameType, "UID", "userId"}, + +#if defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_NAME_ALL) + { NID_pkcs9_challengePassword, CHALLENGE_PASSWORD_OID, + oidCsrAttrType, "challengePassword", "challengePassword"}, + { NID_pkcs9_contentType, PKCS9_CONTENT_TYPE_OID, + oidCsrAttrType, "contentType", "contentType" }, + { NID_pkcs9_unstructuredName, UNSTRUCTURED_NAME_OID, + oidCsrAttrType, "unstructuredName", "unstructuredName" }, + { NID_name, NAME_OID, oidCsrAttrType, "name", "name" }, + { NID_surname, SURNAME_OID, + oidCsrAttrType, "surname", "surname" }, + { NID_givenName, GIVEN_NAME_OID, + oidCsrAttrType, "givenName", "givenName" }, + { NID_initials, INITIALS_OID, + oidCsrAttrType, "initials", "initials" }, + { NID_dnQualifier, DNQUALIFIER_OID, + oidCsrAttrType, "dnQualifer", "dnQualifier" }, +#endif +#endif +#ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */ + /* oidHashType */ + #ifdef WOLFSSL_MD2 + { NID_md2, MD2h, oidHashType, "MD2", "md2"}, + #endif + #ifdef WOLFSSL_MD5 + { NID_md5, MD5h, oidHashType, "MD5", "md5"}, + #endif + #ifndef NO_SHA + { NID_sha1, SHAh, oidHashType, "SHA1", "sha1"}, + #endif + #ifdef WOLFSSL_SHA224 + { NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"}, + #endif + #ifndef NO_SHA256 + { NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"}, + #endif + #ifdef WOLFSSL_SHA384 + { NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"}, + #endif + #ifdef WOLFSSL_SHA512 + { NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"}, + #endif + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + { NID_sha3_224, SHA3_224h, oidHashType, "SHA3-224", "sha3-224"}, + #endif + #ifndef WOLFSSL_NOSHA3_256 + { NID_sha3_256, SHA3_256h, oidHashType, "SHA3-256", "sha3-256"}, + #endif + #ifndef WOLFSSL_NOSHA3_384 + { NID_sha3_384, SHA3_384h, oidHashType, "SHA3-384", "sha3-384"}, + #endif + #ifndef WOLFSSL_NOSHA3_512 + { NID_sha3_512, SHA3_512h, oidHashType, "SHA3-512", "sha3-512"}, + #endif + #endif /* WOLFSSL_SHA3 */ + #ifdef WOLFSSL_SM3 + { NID_sm3, SM3h, oidHashType, "SM3", "sm3"}, + #endif + /* oidSigType */ + #ifndef NO_DSA + #ifndef NO_SHA + { NID_dsaWithSHA1, CTC_SHAwDSA, oidSigType, "DSA-SHA1", "dsaWithSHA1"}, + { NID_dsa_with_SHA256, CTC_SHA256wDSA, oidSigType, "dsa_with_SHA256", + "dsa_with_SHA256"}, + #endif + #endif /* NO_DSA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + { NID_md2WithRSAEncryption, CTC_MD2wRSA, oidSigType, "RSA-MD2", + "md2WithRSAEncryption"}, + #endif + #ifndef NO_MD5 + { NID_md5WithRSAEncryption, CTC_MD5wRSA, oidSigType, "RSA-MD5", + "md5WithRSAEncryption"}, + #endif + #ifndef NO_SHA + { NID_sha1WithRSAEncryption, CTC_SHAwRSA, oidSigType, "RSA-SHA1", + "sha1WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA224 + { NID_sha224WithRSAEncryption, CTC_SHA224wRSA, oidSigType, "RSA-SHA224", + "sha224WithRSAEncryption"}, + #endif + #ifndef NO_SHA256 + { NID_sha256WithRSAEncryption, CTC_SHA256wRSA, oidSigType, "RSA-SHA256", + "sha256WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA384 + { NID_sha384WithRSAEncryption, CTC_SHA384wRSA, oidSigType, "RSA-SHA384", + "sha384WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA512 + { NID_sha512WithRSAEncryption, CTC_SHA512wRSA, oidSigType, "RSA-SHA512", + "sha512WithRSAEncryption"}, + #endif + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + { NID_RSA_SHA3_224, CTC_SHA3_224wRSA, oidSigType, "RSA-SHA3-224", + "sha3-224WithRSAEncryption"}, + #endif + #ifndef WOLFSSL_NOSHA3_256 + { NID_RSA_SHA3_256, CTC_SHA3_256wRSA, oidSigType, "RSA-SHA3-256", + "sha3-256WithRSAEncryption"}, + #endif + #ifndef WOLFSSL_NOSHA3_384 + { NID_RSA_SHA3_384, CTC_SHA3_384wRSA, oidSigType, "RSA-SHA3-384", + "sha3-384WithRSAEncryption"}, + #endif + #ifndef WOLFSSL_NOSHA3_512 + { NID_RSA_SHA3_512, CTC_SHA3_512wRSA, oidSigType, "RSA-SHA3-512", + "sha3-512WithRSAEncryption"}, + #endif + #endif + #ifdef WC_RSA_PSS + { NID_rsassaPss, CTC_RSASSAPSS, oidSigType, "RSASSA-PSS", "rsassaPss" }, + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + { NID_ecdsa_with_SHA1, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1", + "shaWithECDSA"}, + #endif + #ifdef WOLFSSL_SHA224 + { NID_ecdsa_with_SHA224, CTC_SHA224wECDSA, oidSigType, + "ecdsa-with-SHA224","sha224WithECDSA"}, + #endif + #ifndef NO_SHA256 + { NID_ecdsa_with_SHA256, CTC_SHA256wECDSA, oidSigType, + "ecdsa-with-SHA256","sha256WithECDSA"}, + #endif + #ifdef WOLFSSL_SHA384 + { NID_ecdsa_with_SHA384, CTC_SHA384wECDSA, oidSigType, + "ecdsa-with-SHA384","sha384WithECDSA"}, + #endif + #ifdef WOLFSSL_SHA512 + { NID_ecdsa_with_SHA512, CTC_SHA512wECDSA, oidSigType, + "ecdsa-with-SHA512","sha512WithECDSA"}, + #endif + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + { NID_ecdsa_with_SHA3_224, CTC_SHA3_224wECDSA, oidSigType, + "id-ecdsa-with-SHA3-224", "ecdsa_with_SHA3-224"}, + #endif + #ifndef WOLFSSL_NOSHA3_256 + { NID_ecdsa_with_SHA3_256, CTC_SHA3_256wECDSA, oidSigType, + "id-ecdsa-with-SHA3-256", "ecdsa_with_SHA3-256"}, + #endif + #ifndef WOLFSSL_NOSHA3_384 + { NID_ecdsa_with_SHA3_384, CTC_SHA3_384wECDSA, oidSigType, + "id-ecdsa-with-SHA3-384", "ecdsa_with_SHA3-384"}, + #endif + #ifndef WOLFSSL_NOSHA3_512 + { NID_ecdsa_with_SHA3_512, CTC_SHA3_512wECDSA, oidSigType, + "id-ecdsa-with-SHA3-512", "ecdsa_with_SHA3-512"}, + #endif + #endif + #endif /* HAVE_ECC */ + /* oidKeyType */ + #ifndef NO_DSA + { NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"}, + #endif /* NO_DSA */ + #ifndef NO_RSA + { NID_rsaEncryption, RSAk, oidKeyType, "rsaEncryption", + "rsaEncryption"}, + #ifdef WC_RSA_PSS + { NID_rsassaPss, RSAPSSk, oidKeyType, "RSASSA-PSS", "rsassaPss"}, + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + { NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey", + "id-ecPublicKey"}, + #endif /* HAVE_ECC */ #ifndef NO_DH - /* client creates its own DH parameters on handshake */ - if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, - DYNAMIC_TYPE_PUBLIC_KEY); - } - 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_PUBLIC_KEY); - } - ssl->buffers.serverDH_G.buffer = NULL; + { NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement", + "dhKeyAgreement"}, + #endif + #ifdef HAVE_ED448 + { NID_ED448, ED448k, oidKeyType, "ED448", "ED448"}, + #endif + #ifdef HAVE_ED25519 + { NID_ED25519, ED25519k, oidKeyType, "ED25519", "ED25519"}, #endif + #ifdef HAVE_FALCON + { CTC_FALCON_LEVEL1, FALCON_LEVEL1k, oidKeyType, "Falcon Level 1", + "Falcon Level 1"}, + { CTC_FALCON_LEVEL5, FALCON_LEVEL5k, oidKeyType, "Falcon Level 5", + "Falcon Level 5"}, + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + { CTC_DILITHIUM_LEVEL2, DILITHIUM_LEVEL2k, oidKeyType, + "Dilithium Level 2", "Dilithium Level 2"}, + { CTC_DILITHIUM_LEVEL3, DILITHIUM_LEVEL3k, oidKeyType, + "Dilithium Level 3", "Dilithium Level 3"}, + { CTC_DILITHIUM_LEVEL5, DILITHIUM_LEVEL5k, oidKeyType, + "Dilithium Level 5", "Dilithium Level 5"}, + #endif /* HAVE_DILITHIUM */ - if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error initializing client side"); - } -} -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + /* oidCurveType */ + #ifdef HAVE_ECC + { NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType, "prime192v1", + "prime192v1"}, + { NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType, "prime192v2", + "prime192v2"}, + { NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType, "prime192v3", + "prime192v3"}, + + { NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType, "prime239v1", + "prime239v1"}, + { NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType, "prime239v2", + "prime239v2"}, + { NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType, "prime239v3", + "prime239v3"}, + + { NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType, "prime256v1", + "prime256v1"}, + + { NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1", + "secp112r1"}, + { NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2", + "secp112r2"}, + + { NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1", + "secp128r1"}, + { NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2", + "secp128r2"}, + + { NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1", + "secp160r1"}, + { NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2", + "secp160r2"}, + + { NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1", + "secp224r1"}, + { NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1", + "secp384r1"}, + { NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1", + "secp521r1"}, + + { NID_secp160k1, ECC_SECP160K1_OID, oidCurveType, "secp160k1", + "secp160k1"}, + { NID_secp192k1, ECC_SECP192K1_OID, oidCurveType, "secp192k1", + "secp192k1"}, + { NID_secp224k1, ECC_SECP224K1_OID, oidCurveType, "secp224k1", + "secp224k1"}, + { NID_secp256k1, ECC_SECP256K1_OID, oidCurveType, "secp256k1", + "secp256k1"}, + + { NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID, oidCurveType, + "brainpoolP160r1", "brainpoolP160r1"}, + { NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID, oidCurveType, + "brainpoolP192r1", "brainpoolP192r1"}, + { NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID, oidCurveType, + "brainpoolP224r1", "brainpoolP224r1"}, + { NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID, oidCurveType, + "brainpoolP256r1", "brainpoolP256r1"}, + { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID, oidCurveType, + "brainpoolP320r1", "brainpoolP320r1"}, + { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID, oidCurveType, + "brainpoolP384r1", "brainpoolP384r1"}, + { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID, oidCurveType, + "brainpoolP512r1", "brainpoolP512r1"}, + #ifdef WOLFSSL_SM2 + { NID_sm2, ECC_SM2P256V1_OID, oidCurveType, "sm2", "sm2"}, + #endif + #endif /* HAVE_ECC */ -int wolfSSL_get_shutdown(const WOLFSSL* ssl) -{ - int isShutdown = 0; + /* oidBlkType */ + #ifdef WOLFSSL_AES_128 + { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC", "aes-128-cbc"}, + #endif + #ifdef WOLFSSL_AES_192 + { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC", "aes-192-cbc"}, + #endif + #ifdef WOLFSSL_AES_256 + { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC", "aes-256-cbc"}, + #endif + #ifndef NO_DES3 + { NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"}, + { NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"}, + #endif /* !NO_DES3 */ + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + { NID_chacha20_poly1305, NID_chacha20_poly1305, oidBlkType, + "ChaCha20-Poly1305", "chacha20-poly1305"}, + #endif - WOLFSSL_ENTER("wolfSSL_get_shutdown"); + /* oidOcspType */ + #ifdef HAVE_OCSP + { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, + "basicOCSPResponse", "Basic OCSP Response"}, + { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "Nonce", "OCSP Nonce"}, + #endif /* HAVE_OCSP */ - if (ssl) { -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) - if (ssl->options.shutdownDone) { - /* The SSL object was possibly cleared with wolfSSL_clear after - * a successful shutdown. Simulate a response for a full - * bidirectional shutdown. */ - isShutdown = WOLFSSL_SENT_SHUTDOWN | WOLFSSL_RECEIVED_SHUTDOWN; - } - else -#endif - { - /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * - * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ - if (ssl->options.sentNotify) - isShutdown |= WOLFSSL_SENT_SHUTDOWN; - if (ssl->options.closeNotify||ssl->options.connReset) - isShutdown |= WOLFSSL_RECEIVED_SHUTDOWN; - } - - } - - WOLFSSL_LEAVE("wolfSSL_get_shutdown", isShutdown); - return isShutdown; -} + #ifndef NO_PWDBASED + /* oidKdfType */ + { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"}, + /* oidPBEType */ + { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType, + "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4"}, + { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE-SHA1-DES", + "pbeWithSHA1AndDES-CBC"}, + { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE-SHA1-3DES", + "pbeWithSHA1And3-KeyTripleDES-CBC"}, + #endif -int wolfSSL_session_reused(WOLFSSL* ssl) -{ - int resuming = 0; - WOLFSSL_ENTER("wolfSSL_session_reused"); - if (ssl) { -#ifndef HAVE_SECURE_RENEGOTIATION - resuming = ssl->options.resuming; -#else - resuming = ssl->options.resuming || ssl->options.resumed; -#endif - } - WOLFSSL_LEAVE("wolfSSL_session_reused", resuming); - return resuming; -} + /* oidKeyWrapType */ + #ifdef WOLFSSL_AES_128 + { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap", + "aes128-wrap"}, + #endif + #ifdef WOLFSSL_AES_192 + { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap", + "aes192-wrap"}, + #endif + #ifdef WOLFSSL_AES_256 + { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap", + "aes256-wrap"}, + #endif -/* return a new malloc'd session with default settings on success */ -WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) -{ - WOLFSSL_SESSION* ret = NULL; + #ifndef NO_PKCS7 + #ifndef NO_DH + /* oidCmsKeyAgreeType */ + #ifndef NO_SHA + { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme, + oidCmsKeyAgreeType, "dhSinglePass-stdDH-sha1kdf-scheme", + "dhSinglePass-stdDH-sha1kdf-scheme"}, + #endif + #ifdef WOLFSSL_SHA224 + { dhSinglePass_stdDH_sha224kdf_scheme, + dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha224kdf-scheme", + "dhSinglePass-stdDH-sha224kdf-scheme"}, + #endif + #ifndef NO_SHA256 + { dhSinglePass_stdDH_sha256kdf_scheme, + dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha256kdf-scheme", + "dhSinglePass-stdDH-sha256kdf-scheme"}, + #endif + #ifdef WOLFSSL_SHA384 + { dhSinglePass_stdDH_sha384kdf_scheme, + dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha384kdf-scheme", + "dhSinglePass-stdDH-sha384kdf-scheme"}, + #endif + #ifdef WOLFSSL_SHA512 + { dhSinglePass_stdDH_sha512kdf_scheme, + dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType, + "dhSinglePass-stdDH-sha512kdf-scheme", + "dhSinglePass-stdDH-sha512kdf-scheme"}, + #endif + #endif + #endif + #if defined(WOLFSSL_APACHE_HTTPD) + /* "1.3.6.1.5.5.7.8.7" */ + { NID_id_on_dnsSRV, NID_id_on_dnsSRV, oidCertNameType, + WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV }, - WOLFSSL_ENTER("wolfSSL_NewSession"); + /* "1.3.6.1.4.1.311.20.2.3" */ + { NID_ms_upn, WOLFSSL_MS_UPN_SUM, oidCertExtType, WOLFSSL_SN_MS_UPN, + WOLFSSL_LN_MS_UPN }, - ret = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), heap, - DYNAMIC_TYPE_SESSION); - if (ret != NULL) { - int err; - XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION)); - wolfSSL_RefInit(&ret->ref, &err); - #ifdef WOLFSSL_REFCNT_ERROR_RETURN - if (err != 0) { - WOLFSSL_MSG("Error setting up session reference mutex"); - XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); - return NULL; - } - #else - (void)err; - #endif -#ifndef NO_SESSION_CACHE - ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ -#endif - ret->type = WOLFSSL_SESSION_TYPE_HEAP; - ret->heap = heap; -#ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("SESSION master secret", ret->masterSecret, SECRET_LEN); - wc_MemZero_Add("SESSION id", ret->sessionID, ID_LEN); -#endif - #ifdef HAVE_SESSION_TICKET - ret->ticket = ret->staticTicket; - #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - ret->ticketNonce.data = ret->ticketNonce.dataStatic; - #endif + /* "1.3.6.1.5.5.7.1.24" */ + { NID_tlsfeature, WOLFSSL_TLS_FEATURE_SUM, oidTlsExtType, + WOLFSSL_SN_TLS_FEATURE, WOLFSSL_LN_TLS_FEATURE }, #endif -#ifdef HAVE_EX_DATA - ret->ownExData = 1; - if (crypto_ex_cb_ctx_session != NULL) { - crypto_ex_cb_setup_new_data(ret, crypto_ex_cb_ctx_session, - &ret->ex_data); - } -#endif - } - return ret; -} +#endif /* OPENSSL_EXTRA */ +}; +#define WOLFSSL_OBJECT_INFO_SZ \ + (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info)) +const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ; +#endif -WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. + */ +void wolfSSL_OPENSSL_free(void* p) { - return wolfSSL_NewSession(heap); + WOLFSSL_MSG("wolfSSL_OPENSSL_free"); + + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA -WOLFSSL_SESSION* wolfSSL_SESSION_new(void) +void *wolfSSL_OPENSSL_malloc(size_t a) { - return wolfSSL_SESSION_new_ex(NULL); + return (void *)XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL); } -/* add one to session reference count - * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ -int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) +int wolfSSL_OPENSSL_hexchar2int(unsigned char c) { - int ret; - - session = ClientSessionToSession(session); - - if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP) - return WOLFSSL_FAILURE; - - wolfSSL_RefInc(&session->ref, &ret); -#ifdef WOLFSSL_REFCNT_ERROR_RETURN - if (ret != 0) { - WOLFSSL_MSG("Failed to lock session mutex"); - return WOLFSSL_FAILURE; - } -#else - (void)ret; -#endif - - return WOLFSSL_SUCCESS; + /* 'char' is unsigned on some platforms. */ + return (int)(signed char)HexCharToByte((char)c); } -/** - * Deep copy the contents from input to output. - * @param input The source of the copy. - * @param output The destination of the copy. - * @param avoidSysCalls If true, then system calls will be avoided or an error - * will be returned if it is not possible to proceed - * without a system call. This is useful for fetching - * sessions from cache. When a cache row is locked, we - * don't want to block other threads with long running - * system calls. - * @param ticketNonceBuf If not null and @avoidSysCalls is true, the copy of the - * ticketNonce will happen in this pre allocated buffer - * @param ticketNonceLen @ticketNonceBuf len as input, used length on output - * @param ticketNonceUsed if @ticketNonceBuf was used to copy the ticket noncet - * @return WOLFSSL_SUCCESS on success - * WOLFSSL_FAILURE on failure - */ -static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input, - WOLFSSL_SESSION* output, int avoidSysCalls, byte* ticketNonceBuf, - byte* ticketNonceLen, byte* preallocUsed) +unsigned char *wolfSSL_OPENSSL_hexstr2buf(const char *str, long *len) { -#ifdef HAVE_SESSION_TICKET - int ticLenAlloc = 0; - byte *ticBuff = NULL; -#endif - const size_t copyOffset = OFFSETOF(WOLFSSL_SESSION, heap) + sizeof(input->heap); - int ret = WOLFSSL_SUCCESS; - - (void)avoidSysCalls; - (void)ticketNonceBuf; - (void)ticketNonceLen; - (void)preallocUsed; - - input = ClientSessionToSession(input); - output = ClientSessionToSession(output); + unsigned char* targetBuf; + int srcDigitHigh = 0; + int srcDigitLow = 0; + size_t srcLen; + size_t srcIdx = 0; + long targetIdx = 0; - if (input == NULL || output == NULL || input == output) { - WOLFSSL_MSG("input or output are null or same"); - return WOLFSSL_FAILURE; + srcLen = XSTRLEN(str); + targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL); + if (targetBuf == NULL) { + return NULL; } -#ifdef HAVE_SESSION_TICKET - if (output->ticket != output->staticTicket) { - ticBuff = output->ticket; - ticLenAlloc = output->ticketLenAlloc; - } -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - /* free the data, it would be better to reuse the buffer but this - * maintain the code simpler. A smart allocator should reuse the free'd - * buffer in the next malloc without much performance penalties. */ - if (output->ticketNonce.data != output->ticketNonce.dataStatic) { - - /* Callers that avoid syscall should never calls this with - * output->tickeNonce.data being a dynamic buffer.*/ - if (avoidSysCalls) { - WOLFSSL_MSG("can't avoid syscalls with dynamic TicketNonce buffer"); - return WOLFSSL_FAILURE; + while (srcIdx < srcLen) { + if (str[srcIdx] == ':') { + srcIdx++; + continue; } - XFREE(output->ticketNonce.data, - output->heap, DYNAMIC_TYPE_SESSION_TICK); - output->ticketNonce.data = output->ticketNonce.dataStatic; - output->ticketNonce.len = 0; - } -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ -#endif /* HAVE_SESSION_TICKET */ - -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (output->peer != NULL) { - if (avoidSysCalls) { - WOLFSSL_MSG("Can't free cert when avoiding syscalls"); - return WOLFSSL_FAILURE; + srcDigitHigh = wolfSSL_OPENSSL_hexchar2int((unsigned char)str[srcIdx++]); + srcDigitLow = wolfSSL_OPENSSL_hexchar2int((unsigned char)str[srcIdx++]); + if (srcDigitHigh < 0 || srcDigitLow < 0) { + WOLFSSL_MSG("Invalid hex character."); + XFREE(targetBuf, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; } - wolfSSL_X509_free(output->peer); - output->peer = NULL; - } -#endif - XMEMCPY((byte*)output + copyOffset, (byte*)input + copyOffset, - sizeof(WOLFSSL_SESSION) - copyOffset); - -#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ - defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - /* fix pointer to static after the copy */ - output->ticketNonce.data = output->ticketNonce.dataStatic; -#endif - /* Set sane values for copy */ -#ifndef NO_SESSION_CACHE - if (output->type != WOLFSSL_SESSION_TYPE_CACHE) - output->cacheRow = INVALID_SESSION_ROW; -#endif -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (input->peer != NULL && input->peer->dynamicMemory) { - if (wolfSSL_X509_up_ref(input->peer) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Can't increase peer cert ref count"); - output->peer = NULL; - } - } - else if (!avoidSysCalls) - output->peer = wolfSSL_X509_dup(input->peer); - else - /* output->peer is not that important to copy */ - output->peer = NULL; -#endif -#ifdef HAVE_SESSION_TICKET - if (input->ticketLen > SESSION_TICKET_LEN) { - /* Need dynamic buffer */ - if (ticBuff == NULL || ticLenAlloc < input->ticketLen) { - /* allocate new one */ - byte* tmp; - if (avoidSysCalls) { - WOLFSSL_MSG("Failed to allocate memory for ticket when avoiding" - " syscalls"); - output->ticket = ticBuff; - output->ticketLenAlloc = (word16) ticLenAlloc; - output->ticketLen = 0; - ret = WOLFSSL_FAILURE; - } - else { -#ifdef WOLFSSL_NO_REALLOC - tmp = (byte*)XMALLOC(input->ticketLen, - output->heap, DYNAMIC_TYPE_SESSION_TICK); - XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK); - ticBuff = NULL; -#else - tmp = (byte*)XREALLOC(ticBuff, input->ticketLen, - output->heap, DYNAMIC_TYPE_SESSION_TICK); -#endif /* WOLFSSL_NO_REALLOC */ - if (tmp == NULL) { - WOLFSSL_MSG("Failed to allocate memory for ticket"); -#ifndef WOLFSSL_NO_REALLOC - XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK); - ticBuff = NULL; -#endif /* WOLFSSL_NO_REALLOC */ - output->ticket = NULL; - output->ticketLen = 0; - output->ticketLenAlloc = 0; - ret = WOLFSSL_FAILURE; - } - else { - ticBuff = tmp; - ticLenAlloc = input->ticketLen; - } - } - } - if (ticBuff != NULL && ret == WOLFSSL_SUCCESS) { - XMEMCPY(ticBuff, input->ticket, input->ticketLen); - output->ticket = ticBuff; - output->ticketLenAlloc = (word16) ticLenAlloc; - } - } - else { - /* Default ticket to non dynamic */ - if (avoidSysCalls) { - /* Try to use ticBuf if available. Caller can later move it to - * the static buffer. */ - if (ticBuff != NULL) { - if (ticLenAlloc >= input->ticketLen) { - output->ticket = ticBuff; - output->ticketLenAlloc = ticLenAlloc; - } - else { - WOLFSSL_MSG("ticket dynamic buffer too small but we are " - "avoiding system calls"); - ret = WOLFSSL_FAILURE; - output->ticket = ticBuff; - output->ticketLenAlloc = (word16) ticLenAlloc; - output->ticketLen = 0; - } - } - else { - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - } - } - else { - if (ticBuff != NULL) - XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK); - output->ticket = output->staticTicket; - output->ticketLenAlloc = 0; - } - if (input->ticketLenAlloc > 0 && ret == WOLFSSL_SUCCESS) { - /* Shouldn't happen as session should have placed this in - * the static buffer */ - XMEMCPY(output->ticket, input->ticket, - input->ticketLen); - } - } - ticBuff = NULL; - -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (preallocUsed != NULL) - *preallocUsed = 0; - - if (input->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ && - ret == WOLFSSL_SUCCESS) { - /* TicketNonce does not fit in the static buffer */ - if (!avoidSysCalls) { - output->ticketNonce.data = (byte*)XMALLOC(input->ticketNonce.len, - output->heap, DYNAMIC_TYPE_SESSION_TICK); - - if (output->ticketNonce.data == NULL) { - WOLFSSL_MSG("Failed to allocate space for ticket nonce"); - output->ticketNonce.data = output->ticketNonce.dataStatic; - output->ticketNonce.len = 0; - ret = WOLFSSL_FAILURE; - } - else { - output->ticketNonce.len = input->ticketNonce.len; - XMEMCPY(output->ticketNonce.data, input->ticketNonce.data, - input->ticketNonce.len); - ret = WOLFSSL_SUCCESS; - } - } - /* we can't do syscalls. Use prealloc buffers if provided from the - * caller. */ - else if (ticketNonceBuf != NULL && - *ticketNonceLen >= input->ticketNonce.len) { - XMEMCPY(ticketNonceBuf, input->ticketNonce.data, - input->ticketNonce.len); - *ticketNonceLen = input->ticketNonce.len; - if (preallocUsed != NULL) - *preallocUsed = 1; - ret = WOLFSSL_SUCCESS; - } - else { - WOLFSSL_MSG("TicketNonce bigger than static buffer, and we can't " - "do syscalls"); - ret = WOLFSSL_FAILURE; - } + targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) | + srcDigitLow ); } -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ - -#endif /* HAVE_SESSION_TICKET */ -#ifdef HAVE_EX_DATA - if (input->type != WOLFSSL_SESSION_TYPE_CACHE && - output->type != WOLFSSL_SESSION_TYPE_CACHE) { - /* Not called with cache as that passes ownership of ex_data */ - ret = crypto_ex_cb_dup_data(&input->ex_data, &output->ex_data, - crypto_ex_cb_ctx_session); - } -#endif + if (len != NULL) + *len = targetIdx; - return ret; + return targetBuf; } -/** - * Deep copy the contents from input to output. - * @param input The source of the copy. - * @param output The destination of the copy. - * @param avoidSysCalls If true, then system calls will be avoided or an error - * will be returned if it is not possible to proceed - * without a system call. This is useful for fetching - * sessions from cache. When a cache row is locked, we - * don't want to block other threads with long running - * system calls. - * @return WOLFSSL_SUCCESS on success - * WOLFSSL_FAILURE on failure - */ -int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, - int avoidSysCalls) +int wolfSSL_OPENSSL_init_ssl(word64 opts, const OPENSSL_INIT_SETTINGS *settings) { - return wolfSSL_DupSessionEx(input, output, avoidSysCalls, NULL, NULL, NULL); + (void)opts; + (void)settings; + return wolfSSL_library_init(); } -WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) +int wolfSSL_OPENSSL_init_crypto(word64 opts, + const OPENSSL_INIT_SETTINGS* settings) { - WOLFSSL_SESSION* copy; - - WOLFSSL_ENTER("wolfSSL_SESSION_dup"); + (void)opts; + (void)settings; + return wolfSSL_library_init(); +} - session = ClientSessionToSession(session); - if (session == NULL) - return NULL; +/* Colon separated list of + algorithms. + * Replaces list in context. + */ +int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list) +{ + WOLFSSL_MSG("wolfSSL_CTX_set1_sigalg_list"); -#ifdef HAVE_SESSION_TICKET - if (session->ticketLenAlloc > 0 && !session->ticket) { - WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null"); - return NULL; + if (ctx == NULL || list == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; } -#endif - copy = wolfSSL_NewSession(session->heap); - if (copy != NULL && - wolfSSL_DupSession(session, copy, 0) != WOLFSSL_SUCCESS) { - wolfSSL_FreeSession(NULL, copy); - copy = NULL; - } - return copy; + if (AllocateCtxSuites(ctx) != 0) + return WOLFSSL_FAILURE; + + return SetSuitesHashSigAlgo(ctx->suites, list); } -void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +/* Colon separated list of + algorithms. + * Replaces list in SSL. + */ +int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list) { - session = ClientSessionToSession(session); - if (session == NULL) - return; + WOLFSSL_MSG("wolfSSL_set1_sigalg_list"); - (void)ctx; + if (ssl == NULL || list == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } - WOLFSSL_ENTER("wolfSSL_FreeSession"); + if (AllocateSuites(ssl) != 0) + return WOLFSSL_FAILURE; - if (session->ref.count > 0) { - int ret; - int isZero; - wolfSSL_RefDec(&session->ref, &isZero, &ret); - (void)ret; - if (!isZero) { - return; - } - wolfSSL_RefFree(&session->ref); - } + return SetSuitesHashSigAlgo(ssl->suites, list); +} - WOLFSSL_MSG("wolfSSL_FreeSession full free"); +static int HashToNid(byte hashAlgo, int* nid) +{ + int ret = WOLFSSL_SUCCESS; -#ifdef HAVE_EX_DATA - if (session->ownExData) { - crypto_ex_cb_free_data(session, crypto_ex_cb_ctx_session, - &session->ex_data); + /* Cast for compiler to check everything is implemented */ + switch ((enum wc_MACAlgorithm)hashAlgo) { + case no_mac: + case rmd_mac: + *nid = NID_undef; + break; + case md5_mac: + *nid = NID_md5; + break; + case sha_mac: + *nid = NID_sha1; + break; + case sha224_mac: + *nid = NID_sha224; + break; + case sha256_mac: + *nid = NID_sha256; + break; + case sha384_mac: + *nid = NID_sha384; + break; + case sha512_mac: + *nid = NID_sha512; + break; + case blake2b_mac: + *nid = NID_blake2b512; + break; + case sm3_mac: + *nid = NID_sm3; + break; + default: + ret = WOLFSSL_FAILURE; + break; } -#endif - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); -#endif -#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) - if (session->peer) { - wolfSSL_X509_free(session->peer); - session->peer = NULL; - } -#endif + return ret; +} -#ifdef HAVE_SESSION_TICKET - if (session->ticketLenAlloc > 0) { - XFREE(session->ticket, session->heap, DYNAMIC_TYPE_SESSION_TICK); - session->ticket = session->staticTicket; - session->ticketLen = 0; - session->ticketLenAlloc = 0; - } -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - if (session->ticketNonce.data != session->ticketNonce.dataStatic) { - XFREE(session->ticketNonce.data, session->heap, - DYNAMIC_TYPE_SESSION_TICK); - session->ticketNonce.data = session->ticketNonce.dataStatic; - session->ticketNonce.len = 0; - } -#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ +static int SaToNid(byte sa, int* nid) +{ + int ret = WOLFSSL_SUCCESS; + /* Cast for compiler to check everything is implemented */ + switch ((enum SignatureAlgorithm)sa) { + case anonymous_sa_algo: + *nid = NID_undef; + break; + case rsa_sa_algo: + *nid = NID_rsaEncryption; + break; + case dsa_sa_algo: + *nid = NID_dsa; + break; + case ecc_dsa_sa_algo: + *nid = NID_X9_62_id_ecPublicKey; + break; + case rsa_pss_sa_algo: + *nid = NID_rsassaPss; + break; + case ed25519_sa_algo: +#ifdef HAVE_ED25519 + *nid = NID_ED25519; +#else + ret = WOLFSSL_FAILURE; #endif - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); + break; + case rsa_pss_pss_algo: + *nid = NID_rsassaPss; + break; + case ed448_sa_algo: +#ifdef HAVE_ED448 + *nid = NID_ED448; +#else + ret = WOLFSSL_FAILURE; #endif - - /* Make sure masterSecret is zeroed. */ - ForceZero(session->masterSecret, SECRET_LEN); - /* Session ID is sensitive information too. */ - ForceZero(session->sessionID, ID_LEN); - - if (session->type == WOLFSSL_SESSION_TYPE_HEAP) { - XFREE(session, session->heap, DYNAMIC_TYPE_SESSION); + break; + case falcon_level1_sa_algo: + *nid = CTC_FALCON_LEVEL1; + break; + case falcon_level5_sa_algo: + *nid = CTC_FALCON_LEVEL5; + break; + case dilithium_level2_sa_algo: + *nid = CTC_DILITHIUM_LEVEL2; + break; + case dilithium_level3_sa_algo: + *nid = CTC_DILITHIUM_LEVEL3; + break; + case dilithium_level5_sa_algo: + *nid = CTC_DILITHIUM_LEVEL5; + break; + case sm2_sa_algo: + *nid = NID_sm2; + break; + case invalid_sa_algo: + default: + ret = WOLFSSL_FAILURE; + break; } + return ret; } -/* DO NOT use this API internally. Use wolfSSL_FreeSession directly instead - * and pass in the ctx parameter if possible (like from ssl->ctx). */ -void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) +/* This API returns the hash selected. */ +int wolfSSL_get_signature_nid(WOLFSSL *ssl, int* nid) { - session = ClientSessionToSession(session); - wolfSSL_FreeSession(NULL, session); + WOLFSSL_MSG("wolfSSL_get_signature_nid"); + + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + return HashToNid(ssl->options.hashAlgo, nid); } -#ifndef NO_SESSION_CACHE -int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +/* This API returns the signature selected. */ +int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid) { - int error = 0; - const byte* id = NULL; - byte idSz = 0; - - WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + WOLFSSL_MSG("wolfSSL_get_signature_type_nid"); - session = ClientSessionToSession(session); - if (session == NULL) + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); return WOLFSSL_FAILURE; - - /* Session cache is global */ - (void)ctx; - - if (session->haveAltSessionID) { - id = session->altSessionID; - idSz = ID_LEN; } - else { - id = session->sessionID; - idSz = session->sessionIDSz; - } - - error = AddSessionToCache(ctx, session, id, idSz, - NULL, session->side, -#ifdef HAVE_SESSION_TICKET - session->ticketLen > 0, -#else - 0, -#endif - NULL); - return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + return SaToNid(ssl->options.sigAlgo, nid); } -#endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) - -/** -* set cipher to WOLFSSL_SESSION from WOLFSSL_CIPHER -* @param session a pointer to WOLFSSL_SESSION structure -* @param cipher a function pointer to WOLFSSL_CIPHER -* @return WOLFSSL_SUCCESS on success, otherwise WOLFSSL_FAILURE -*/ -int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, - const WOLFSSL_CIPHER* cipher) +int wolfSSL_get_peer_signature_nid(WOLFSSL* ssl, int* nid) { - WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); + WOLFSSL_MSG("wolfSSL_get_peer_signature_nid"); - session = ClientSessionToSession(session); - /* sanity check */ - if (session == NULL || cipher == NULL) { - WOLFSSL_MSG("bad argument"); + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); return WOLFSSL_FAILURE; } - session->cipherSuite0 = cipher->cipherSuite0; - session->cipherSuite = cipher->cipherSuite; - WOLFSSL_LEAVE("wolfSSL_SESSION_set_cipher", WOLFSSL_SUCCESS); - return WOLFSSL_SUCCESS; + return HashToNid(ssl->options.peerHashAlgo, nid); } -#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ - -/* helper function that takes in a protocol version struct and returns string */ -static const char* wolfSSL_internal_get_version(const ProtocolVersion* version) +int wolfSSL_get_peer_signature_type_nid(const WOLFSSL* ssl, int* nid) { - WOLFSSL_ENTER("wolfSSL_get_version"); + WOLFSSL_MSG("wolfSSL_get_peer_signature_type_nid"); - if (version == NULL) { - return "Bad arg"; + if (ssl == NULL || nid == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; } - if (version->major == SSLv3_MAJOR) { - switch (version->minor) { - case SSLv3_MINOR : - return "SSLv3"; - case TLSv1_MINOR : - return "TLSv1"; - case TLSv1_1_MINOR : - return "TLSv1.1"; - case TLSv1_2_MINOR : - return "TLSv1.2"; - case TLSv1_3_MINOR : - return "TLSv1.3"; - default: - return "unknown"; - } - } -#ifdef WOLFSSL_DTLS - else if (version->major == DTLS_MAJOR) { - switch (version->minor) { - case DTLS_MINOR : - return "DTLS"; - case DTLSv1_2_MINOR : - return "DTLSv1.2"; - case DTLSv1_3_MINOR : - return "DTLSv1.3"; - default: - return "unknown"; - } - } -#endif /* WOLFSSL_DTLS */ - return "unknown"; + return SaToNid(ssl->options.peerSigAlgo, nid); } +#ifdef HAVE_ECC -const char* wolfSSL_get_version(const WOLFSSL* ssl) +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) +int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list) { - if (ssl == NULL) { - WOLFSSL_MSG("Bad argument"); - return "unknown"; + if (!ctx || !list) { + return WOLFSSL_FAILURE; } - return wolfSSL_internal_get_version(&ssl->version); + return set_curves_list(NULL, ctx, list, 0); } - -/* current library version */ -const char* wolfSSL_lib_version(void) +int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list) { - return LIBWOLFSSL_VERSION_STRING; -} + if (!ssl || !list) { + return WOLFSSL_FAILURE; + } -#ifdef OPENSSL_EXTRA -#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L -const char* wolfSSL_OpenSSL_version(int a) -{ - (void)a; - return "wolfSSL " LIBWOLFSSL_VERSION_STRING; -} -#else -const char* wolfSSL_OpenSSL_version(void) -{ - return "wolfSSL " LIBWOLFSSL_VERSION_STRING; + return set_curves_list(ssl, NULL, list, 0); } -#endif /* WOLFSSL_QT */ -#endif +#endif /* WOLFSSL_TLS13 */ +#endif /* HAVE_ECC */ -/* current library version in hex */ -word32 wolfSSL_lib_version_hex(void) +#endif /* OPENSSL_EXTRA */ + +#ifdef WOLFSSL_ALT_CERT_CHAINS +int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl) { - return LIBWOLFSSL_VERSION_HEX; + int isUsing = 0; + if (ssl) + isUsing = ssl->options.usingAltCertChain; + return isUsing; } +#endif /* WOLFSSL_ALT_CERT_CHAINS */ -int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl) +#ifdef SESSION_CERTS + +#ifdef WOLFSSL_ALT_CERT_CHAINS +/* Get peer's alternate certificate chain */ +WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_get_current_cipher_suite"); + WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); if (ssl) - return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite; + return &ssl->session->altChain; + return 0; } - -WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_current_cipher"); - if (ssl) { - ssl->cipher.cipherSuite0 = ssl->options.cipherSuite0; - ssl->cipher.cipherSuite = ssl->options.cipherSuite; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - ssl->cipher.bits = ssl->specs.key_size * 8; -#endif - return &ssl->cipher; - } - else - return NULL; -} +#endif /* WOLFSSL_ALT_CERT_CHAINS */ -const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) +/* Get peer's certificate chain */ +WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_CIPHER_get_name"); - - if (cipher == NULL) { - return NULL; - } + WOLFSSL_ENTER("wolfSSL_get_peer_chain"); + if (ssl) + return &ssl->session->chain; - #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) && \ - !defined(WOLFSSL_QT) - return GetCipherNameIana(cipher->cipherSuite0, cipher->cipherSuite); - #else - return wolfSSL_get_cipher_name_from_suite(cipher->cipherSuite0, - cipher->cipherSuite); - #endif + return 0; } -const char* wolfSSL_CIPHER_get_version(const WOLFSSL_CIPHER* cipher) -{ - WOLFSSL_ENTER("wolfSSL_CIPHER_get_version"); - if (cipher == NULL || cipher->ssl == NULL) { - return NULL; - } +/* 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 wolfSSL_get_version(cipher->ssl); + return 0; } -const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session) + +/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */ +int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) { - session = ClientSessionToSession(session); - if (session == NULL) { - return NULL; - } + WOLFSSL_ENTER("wolfSSL_get_chain_length"); + if (chain) + return chain->certs[idx].length; -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) - return GetCipherNameIana(session->cipherSuite0, session->cipherSuite); - #else - return GetCipherNameInternal(session->cipherSuite0, session->cipherSuite); - #endif -#else - return NULL; -#endif + return 0; } -const char* wolfSSL_get_cipher(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_cipher"); - return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); -} -/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */ -const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) +/* Get peer's ASN.1 DER certificate at index (idx) */ +byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) { - /* get access to cipher_name_idx in internal.c */ - return wolfSSL_get_cipher_name_internal(ssl); -} + WOLFSSL_ENTER("wolfSSL_get_chain_cert"); + if (chain) + return chain->certs[idx].buffer; -const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0, - const byte cipherSuite) -{ - return GetCipherNameInternal(cipherSuite0, cipherSuite); + return 0; } -const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0, - const byte cipherSuite) + +/* Get peer's wolfSSL X509 certificate at index (idx) */ +WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) { - return GetCipherNameIana(cipherSuite0, cipherSuite); -} + int ret = 0; + WOLFSSL_X509* x509 = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif -int wolfSSL_get_cipher_suite_from_name(const char* name, byte* cipherSuite0, - byte* cipherSuite, int *flags) { - if ((name == NULL) || - (cipherSuite0 == NULL) || - (cipherSuite == NULL) || - (flags == NULL)) - return BAD_FUNC_ARG; - return GetCipherSuiteFromName(name, cipherSuite0, cipherSuite, flags); -} + WOLFSSL_ENTER("wolfSSL_get_chain_X509"); + if (chain != NULL && idx < MAX_CHAIN_DEPTH) { + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert != NULL) + #endif + { + InitDecodedCert(cert, chain->certs[idx].buffer, + chain->certs[idx].length, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL, 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 defined(WOLFSSL_QT) || defined(OPENSSL_ALL) -/* Creates and returns a new WOLFSSL_CIPHER stack. */ -WOLFSSL_STACK* wolfSSL_sk_new_cipher(void) -{ - WOLFSSL_STACK* sk; - WOLFSSL_ENTER("wolfSSL_sk_new_cipher"); + if ((ret = CopyDecodedToX509(x509, cert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded"); + wolfSSL_X509_free(x509); + x509 = NULL; + } + } + } - sk = wolfSSL_sk_new_null(); - if (sk == NULL) - return NULL; - sk->type = STACK_TYPE_CIPHER; + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } + } + (void)ret; - return sk; + return x509; } -/* return 1 on success 0 on fail */ -int wolfSSL_sk_CIPHER_push(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, - WOLFSSL_CIPHER* cipher) -{ - return wolfSSL_sk_push(sk, cipher); -} -#ifndef NO_WOLFSSL_STUB -WOLFSSL_CIPHER* wolfSSL_sk_CIPHER_pop(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +/* 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 WOLFSSL_SUCCESS on ok */ +int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, + unsigned char* buf, int inLen, int* outLen) { - WOLFSSL_STUB("wolfSSL_sk_CIPHER_pop"); - (void)sk; - return NULL; -} -#endif /* NO_WOLFSSL_STUB */ -#endif /* WOLFSSL_QT || OPENSSL_ALL */ +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + const char* header = NULL; + const char* footer = NULL; + int headerLen; + int footerLen; + int i; + int err; + word32 szNeeded = 0; -word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher) -{ - word16 cipher_id = 0; + WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); + if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain)) + return BAD_FUNC_ARG; - WOLFSSL_ENTER("wolfSSL_CIPHER_get_id"); + err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer); + if (err != 0) + return err; - if (cipher && cipher->ssl) { - cipher_id = (cipher->ssl->options.cipherSuite0 << 8) | - cipher->ssl->options.cipherSuite; + headerLen = (int)XSTRLEN(header); + footerLen = (int)XSTRLEN(footer); + + /* Null output buffer return size needed in outLen */ + if(!buf) { + if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length, + NULL, &szNeeded) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) + return WOLFSSL_FAILURE; + *outLen = szNeeded + headerLen + footerLen; + return LENGTH_ONLY_E; } - return cipher_id; -} + /* don't even try if inLen too short */ + if (inLen < headerLen + footerLen + chain->certs[idx].length) + return BAD_FUNC_ARG; -const WOLFSSL_CIPHER* wolfSSL_get_cipher_by_value(word16 value) -{ - const WOLFSSL_CIPHER* cipher = NULL; - byte cipherSuite0, cipherSuite; - WOLFSSL_ENTER("wolfSSL_get_cipher_by_value"); + /* header */ + if (XMEMCPY(buf, header, headerLen) == NULL) + return WOLFSSL_FATAL_ERROR; - /* extract cipher id information */ - cipherSuite = (value & 0xFF); - cipherSuite0 = ((value >> 8) & 0xFF); + i = headerLen; - /* TODO: lookup by cipherSuite0 / cipherSuite */ - (void)cipherSuite0; - (void)cipherSuite; + /* 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; - return cipher; + /* footer */ + if ( (i + footerLen) > inLen) + return BAD_FUNC_ARG; + if (XMEMCPY(buf + i, footer, footerLen) == NULL) + return WOLFSSL_FATAL_ERROR; + *outLen += headerLen + footerLen; + + return WOLFSSL_SUCCESS; +#else + (void)chain; + (void)idx; + (void)buf; + (void)inLen; + (void)outLen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ } +#endif /* SESSION_CERTS */ -#if defined(OPENSSL_EXTRA) -/* Free the structure for WOLFSSL_CIPHER stack - * - * sk stack to free nodes in - */ -void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) +#ifdef HAVE_FUZZER +void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx) { - WOLFSSL_ENTER("wolfSSL_sk_CIPHER_free"); - - wolfSSL_sk_free(sk); + if (ssl) { + ssl->fuzzerCb = cbf; + ssl->fuzzerCtx = fCtx; + } } -#endif /* OPENSSL_ALL */ +#endif -#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ - !defined(NO_DH) -#ifdef HAVE_FFDHE -static const char* wolfssl_ffdhe_name(word16 group) +#ifndef NO_CERTS +#ifdef HAVE_PK_CALLBACKS + +#ifdef HAVE_ECC +void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb) { - const char* str = NULL; - switch (group) { - case WOLFSSL_FFDHE_2048: - str = "FFDHE_2048"; - break; - case WOLFSSL_FFDHE_3072: - str = "FFDHE_3072"; - break; - case WOLFSSL_FFDHE_4096: - str = "FFDHE_4096"; - break; - case WOLFSSL_FFDHE_6144: - str = "FFDHE_6144"; - break; - case WOLFSSL_FFDHE_8192: - str = "FFDHE_8192"; - break; - default: - break; - } - return str; + if (ctx) + ctx->EccKeyGenCb = cb; } -#endif -/* 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 wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx) { - const char* cName = NULL; + if (ssl) + ssl->EccKeyGenCtx = ctx; +} +void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccKeyGenCtx; - WOLFSSL_ENTER("wolfSSL_get_curve_name"); + return NULL; +} +void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx) +{ + if (ctx) + ctx->EccSignCtx = userCtx; +} +void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx) +{ + if (ctx) + return ctx->EccSignCtx; - if (ssl == NULL) - return NULL; + return NULL; +} -#if defined(WOLFSSL_TLS13) && defined(HAVE_PQC) - /* Check for post-quantum groups. Return now because we do not want the ECC - * check to override this result in the case of a hybrid. */ - if (IsAtLeastTLSv1_3(ssl->version)) { - switch (ssl->namedGroup) { -#ifdef HAVE_LIBOQS - case WOLFSSL_KYBER_LEVEL1: - return "KYBER_LEVEL1"; - case WOLFSSL_KYBER_LEVEL3: - return "KYBER_LEVEL3"; - case WOLFSSL_KYBER_LEVEL5: - return "KYBER_LEVEL5"; - case WOLFSSL_P256_KYBER_LEVEL1: - return "P256_KYBER_LEVEL1"; - case WOLFSSL_P384_KYBER_LEVEL3: - return "P384_KYBER_LEVEL3"; - case WOLFSSL_P521_KYBER_LEVEL5: - return "P521_KYBER_LEVEL5"; -#elif defined(HAVE_PQM4) - case WOLFSSL_KYBER_LEVEL1: - return "KYBER_LEVEL1"; -#elif defined(WOLFSSL_WC_KYBER) - #ifdef WOLFSSL_KYBER512 - case WOLFSSL_KYBER_LEVEL1: - return "KYBER_LEVEL1"; - #endif - #ifdef WOLFSSL_KYBER768 - case WOLFSSL_KYBER_LEVEL3: - return "KYBER_LEVEL3"; - #endif - #ifdef WOLFSSL_KYBER1024 - case WOLFSSL_KYBER_LEVEL5: - return "KYBER_LEVEL5"; - #endif -#endif - } - } +WOLFSSL_ABI +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; -#endif /* WOLFSSL_TLS13 && HAVE_PQC */ -#ifdef HAVE_FFDHE - if (ssl->namedGroup != 0) { - cName = wolfssl_ffdhe_name(ssl->namedGroup); - } -#endif + return NULL; +} -#ifdef HAVE_CURVE25519 - if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) { - cName = "X25519"; - } -#endif +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; -#ifdef HAVE_CURVE448 - if (ssl->ecdhCurveOID == ECC_X448_OID && cName == NULL) { - cName = "X448"; - } -#endif + return NULL; +} -#ifdef HAVE_ECC - if (ssl->ecdhCurveOID != 0 && cName == NULL) { - cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, - NULL)); - } -#endif +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 cName; + return NULL; } -#endif +#endif /* HAVE_ECC */ -#ifdef OPENSSL_EXTRA -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) -/* return authentication NID corresponding to cipher suite - * @param cipher a pointer to WOLFSSL_CIPHER - * return NID if found, NID_undef if not found - */ -int wolfSSL_CIPHER_get_auth_nid(const WOLFSSL_CIPHER* cipher) +#ifdef HAVE_ED25519 +void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb) { - static const struct authnid { - const char* alg_name; - const int nid; - } authnid_tbl[] = { - {"RSA", NID_auth_rsa}, - {"PSK", NID_auth_psk}, - {"SRP", NID_auth_srp}, - {"ECDSA", NID_auth_ecdsa}, - {"None", NID_auth_null}, - {NULL, NID_undef} - }; - - const char* authStr; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + if (ctx) + ctx->Ed25519SignCb = cb; +} +void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519SignCtx = ctx; +} +void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519SignCtx; - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } + return NULL; +} - authStr = GetCipherAuthStr(n); +void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) +{ + if (ctx) + ctx->Ed25519VerifyCb = cb; +} +void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519VerifyCtx = ctx; +} +void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519VerifyCtx; - if (authStr != NULL) { - const struct authnid* sa; - for(sa = authnid_tbl; sa->alg_name != NULL; sa++) { - if (XSTRCMP(sa->alg_name, authStr) == 0) { - return sa->nid; - } - } - } + return NULL; +} +#endif /* HAVE_ED25519 */ - return NID_undef; +#ifdef HAVE_CURVE25519 +void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx, + CallbackX25519KeyGen cb) +{ + if (ctx) + ctx->X25519KeyGenCb = cb; } -/* return cipher NID corresponding to cipher suite - * @param cipher a pointer to WOLFSSL_CIPHER - * return NID if found, NID_undef if not found - */ -int wolfSSL_CIPHER_get_cipher_nid(const WOLFSSL_CIPHER* cipher) +void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx) { - static const struct ciphernid { - const char* alg_name; - const int nid; - } ciphernid_tbl[] = { - {"AESGCM(256)", NID_aes_256_gcm}, - {"AESGCM(128)", NID_aes_128_gcm}, - {"AESCCM(128)", NID_aes_128_ccm}, - {"AES(128)", NID_aes_128_cbc}, - {"AES(256)", NID_aes_256_cbc}, - {"CAMELLIA(256)", NID_camellia_256_cbc}, - {"CAMELLIA(128)", NID_camellia_128_cbc}, - {"RC4", NID_rc4}, - {"3DES", NID_des_ede3_cbc}, - {"CHACHA20/POLY1305(256)", NID_chacha20_poly1305}, - {"None", NID_undef}, - {NULL, NID_undef} - }; - - const char* encStr; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - - WOLFSSL_ENTER("wolfSSL_CIPHER_get_cipher_nid"); - - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } - - encStr = GetCipherEncStr(n); - - if (encStr != NULL) { - const struct ciphernid* c; - for(c = ciphernid_tbl; c->alg_name != NULL; c++) { - if (XSTRCMP(c->alg_name, encStr) == 0) { - return c->nid; - } - } - } - - return NID_undef; + if (ssl) + ssl->X25519KeyGenCtx = ctx; } -/* return digest NID corresponding to cipher suite - * @param cipher a pointer to WOLFSSL_CIPHER - * return NID if found, NID_undef if not found - */ -int wolfSSL_CIPHER_get_digest_nid(const WOLFSSL_CIPHER* cipher) +void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl) { - static const struct macnid { - const char* alg_name; - const int nid; - } macnid_tbl[] = { - {"SHA1", NID_sha1}, - {"SHA256", NID_sha256}, - {"SHA384", NID_sha384}, - {NULL, NID_undef} - }; - - const char* name; - const char* macStr; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - (void)name; + if (ssl) + return ssl->X25519KeyGenCtx; - WOLFSSL_ENTER("wolfSSL_CIPHER_get_digest_nid"); + return NULL; +} - if ((name = GetCipherSegment(cipher, n)) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } +void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx, + CallbackX25519SharedSecret cb) +{ + if (ctx) + ctx->X25519SharedSecretCb = cb; +} +void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X25519SharedSecretCtx = ctx; +} +void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X25519SharedSecretCtx; - /* in MD5 case, NID will be NID_md5 */ - if (XSTRSTR(name, "MD5") != NULL) { - return NID_md5; - } + return NULL; +} +#endif /* HAVE_CURVE25519 */ - macStr = GetCipherMacStr(n); +#ifdef HAVE_ED448 +void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb) +{ + if (ctx) + ctx->Ed448SignCb = cb; +} +void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed448SignCtx = ctx; +} +void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed448SignCtx; - if (macStr != NULL) { - const struct macnid* mc; - for(mc = macnid_tbl; mc->alg_name != NULL; mc++) { - if (XSTRCMP(mc->alg_name, macStr) == 0) { - return mc->nid; - } - } - } + return NULL; +} - return NID_undef; +void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb) +{ + if (ctx) + ctx->Ed448VerifyCb = cb; } -/* return key exchange NID corresponding to cipher suite - * @param cipher a pointer to WOLFSSL_CIPHER - * return NID if found, NID_undef if not found - */ -int wolfSSL_CIPHER_get_kx_nid(const WOLFSSL_CIPHER* cipher) +void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx) { - static const struct kxnid { - const char* name; - const int nid; - } kxnid_table[] = { - {"ECDHEPSK", NID_kx_ecdhe_psk}, - {"ECDH", NID_kx_ecdhe}, - {"DHEPSK", NID_kx_dhe_psk}, - {"DH", NID_kx_dhe}, - {"RSAPSK", NID_kx_rsa_psk}, - {"SRP", NID_kx_srp}, - {"EDH", NID_kx_dhe}, - {"RSA", NID_kx_rsa}, - {NULL, NID_undef} - }; - - const char* keaStr; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + if (ssl) + ssl->Ed448VerifyCtx = ctx; +} +void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed448VerifyCtx; - WOLFSSL_ENTER("wolfSSL_CIPHER_get_kx_nid"); + return NULL; +} +#endif /* HAVE_ED448 */ - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } +#ifdef HAVE_CURVE448 +void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx, + CallbackX448KeyGen cb) +{ + if (ctx) + ctx->X448KeyGenCb = cb; +} +void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X448KeyGenCtx = ctx; +} +void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X448KeyGenCtx; - /* in TLS 1.3 case, NID will be NID_kx_any */ - if (XSTRCMP(n[0], "TLS13") == 0) { - return NID_kx_any; - } + return NULL; +} - keaStr = GetCipherKeaStr(n); +void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx, + CallbackX448SharedSecret cb) +{ + if (ctx) + ctx->X448SharedSecretCb = cb; +} +void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X448SharedSecretCtx = ctx; +} +void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X448SharedSecretCtx; - if (keaStr != NULL) { - const struct kxnid* k; - for(k = kxnid_table; k->name != NULL; k++) { - if (XSTRCMP(k->name, keaStr) == 0) { - return k->nid; - } - } - } + return NULL; +} +#endif /* HAVE_CURVE448 */ - return NID_undef; +#ifndef NO_RSA +void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) +{ + if (ctx) + ctx->RsaSignCb = cb; } -/* check if cipher suite is AEAD - * @param cipher a pointer to WOLFSSL_CIPHER - * return 1 if cipher is AEAD, 0 otherwise - */ -int wolfSSL_CIPHER_is_aead(const WOLFSSL_CIPHER* cipher) +void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) { - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; + if (ctx) + ctx->RsaSignCheckCb = cb; +} +void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaSignCtx = ctx; +} +void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaSignCtx; - WOLFSSL_ENTER("wolfSSL_CIPHER_is_aead"); + return NULL; +} - if (GetCipherSegment(cipher, n) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return NID_undef; - } - return IsCipherAEAD(n); +void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) +{ + if (ctx) + ctx->RsaVerifyCb = cb; } -/* Creates cipher->description based on cipher->offset - * cipher->offset is set in wolfSSL_get_ciphers_compat when it is added - * to a stack of ciphers. - * @param [in] cipher: A cipher from a stack of ciphers. - * return WOLFSSL_SUCCESS if cipher->description is set, else WOLFSSL_FAILURE - */ -int wolfSSL_sk_CIPHER_description(WOLFSSL_CIPHER* cipher) +void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx) { - int strLen; - unsigned long offset; - char* dp; - const char* name; - const char *keaStr, *authStr, *encStr, *macStr, *protocol; - char n[MAX_SEGMENTS][MAX_SEGMENT_SZ] = {{0}}; - int len = MAX_DESCRIPTION_SZ-1; - const CipherSuiteInfo* cipher_names; - ProtocolVersion pv; - WOLFSSL_ENTER("wolfSSL_sk_CIPHER_description"); - - if (cipher == NULL) - return WOLFSSL_FAILURE; + if (ssl) + ssl->RsaVerifyCtx = ctx; +} +void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaVerifyCtx; - dp = cipher->description; - if (dp == NULL) - return WOLFSSL_FAILURE; + return NULL; +} - cipher_names = GetCipherNames(); +#ifdef WC_RSA_PSS +void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb) +{ + if (ctx) + ctx->RsaPssSignCb = cb; +} +void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, + CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssSignCheckCb = cb; +} +void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssSignCtx = ctx; +} +void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssSignCtx; - offset = cipher->offset; - if (offset >= (unsigned long)GetCipherNamesSize()) - return WOLFSSL_FAILURE; - pv.major = cipher_names[offset].major; - pv.minor = cipher_names[offset].minor; - protocol = wolfSSL_internal_get_version(&pv); + return NULL; +} - if ((name = GetCipherSegment(cipher, n)) == NULL) { - WOLFSSL_MSG("no suitable cipher name found"); - return WOLFSSL_FAILURE; - } +void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssVerifyCb = cb; +} +void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssVerifyCtx = ctx; +} +void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssVerifyCtx; - /* keaStr */ - keaStr = GetCipherKeaStr(n); - /* authStr */ - authStr = GetCipherAuthStr(n); - /* encStr */ - encStr = GetCipherEncStr(n); - if ((cipher->bits = SetCipherBits(encStr)) == WOLFSSL_FAILURE) { - WOLFSSL_MSG("Cipher Bits Not Set."); - } - /* macStr */ - macStr = GetCipherMacStr(n); + return NULL; +} +#endif /* WC_RSA_PSS */ +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; - /* Build up the string by copying onto the end. */ - XSTRNCPY(dp, name, len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; + return NULL; +} - XSTRNCPY(dp, " ", len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; - XSTRNCPY(dp, protocol, len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; +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; - XSTRNCPY(dp, " Kx=", len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; - XSTRNCPY(dp, keaStr, len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; + return NULL; +} +#endif /* NO_RSA */ - XSTRNCPY(dp, " Au=", len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; - XSTRNCPY(dp, authStr, len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; +/* callback for premaster secret generation */ +void wolfSSL_CTX_SetGenPreMasterCb(WOLFSSL_CTX* ctx, CallbackGenPreMaster cb) +{ + if (ctx) + ctx->GenPreMasterCb = cb; +} +/* Set premaster secret generation callback context */ +void wolfSSL_SetGenPreMasterCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->GenPreMasterCtx = ctx; +} +/* Get premaster secret generation callback context */ +void* wolfSSL_GetGenPreMasterCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->GenPreMasterCtx; - XSTRNCPY(dp, " Enc=", len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; - XSTRNCPY(dp, encStr, len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; + return NULL; +} - XSTRNCPY(dp, " Mac=", len); - dp[len-1] = '\0'; strLen = (int)XSTRLEN(dp); - len -= strLen; dp += strLen; - XSTRNCPY(dp, macStr, len); - dp[len-1] = '\0'; +/* callback for master secret generation */ +void wolfSSL_CTX_SetGenMasterSecretCb(WOLFSSL_CTX* ctx, + CallbackGenMasterSecret cb) +{ + if (ctx) + ctx->GenMasterCb = cb; +} +/* Set master secret generation callback context */ +void wolfSSL_SetGenMasterSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->GenMasterCtx = ctx; +} +/* Get master secret generation callback context */ +void* wolfSSL_GetGenMasterSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->GenMasterCtx; - return WOLFSSL_SUCCESS; + return NULL; } -#endif /* OPENSSL_ALL || WOLFSSL_QT */ -static WC_INLINE const char* wolfssl_kea_to_string(int kea) +/* callback for session key generation */ +void wolfSSL_CTX_SetGenSessionKeyCb(WOLFSSL_CTX* ctx, CallbackGenSessionKey cb) { - const char* keaStr; - - switch (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_ECC - case ecc_diffie_hellman_kea: - keaStr = "ECDHE"; - break; - case ecc_static_diffie_hellman_kea: - keaStr = "ECDH"; - break; -#endif - default: - keaStr = "unknown"; - break; - } + if (ctx) + ctx->GenSessionKeyCb = cb; +} +/* Set session key generation callback context */ +void wolfSSL_SetGenSessionKeyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->GenSessionKeyCtx = ctx; +} +/* Get session key generation callback context */ +void* wolfSSL_GetGenSessionKeyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->GenSessionKeyCtx; - return keaStr; + return NULL; } -static WC_INLINE const char* wolfssl_sigalg_to_string(int sig_algo) +/* callback for setting encryption keys */ +void wolfSSL_CTX_SetEncryptKeysCb(WOLFSSL_CTX* ctx, CallbackEncryptKeys cb) { - const char* authStr; - - switch (sig_algo) { - case anonymous_sa_algo: - authStr = "None"; - break; -#ifndef NO_RSA - case rsa_sa_algo: - authStr = "RSA"; - break; - #ifdef WC_RSA_PSS - case rsa_pss_sa_algo: - authStr = "RSA-PSS"; - break; - #endif -#endif -#ifndef NO_DSA - case dsa_sa_algo: - authStr = "DSA"; - break; -#endif -#ifdef HAVE_ECC - case ecc_dsa_sa_algo: - authStr = "ECDSA"; - break; -#endif -#ifdef WOLFSSL_SM2 - case sm2_sa_algo: - authStr = "SM2"; - break; -#endif -#ifdef HAVE_ED25519 - case ed25519_sa_algo: - authStr = "Ed25519"; - break; -#endif -#ifdef HAVE_ED448 - case ed448_sa_algo: - authStr = "Ed448"; - break; -#endif - default: - authStr = "unknown"; - break; - } - - return authStr; + if (ctx) + ctx->EncryptKeysCb = cb; } - -static WC_INLINE const char* wolfssl_cipher_to_string(int cipher, int key_size) +/* Set encryption keys callback context */ +void wolfSSL_SetEncryptKeysCtx(WOLFSSL* ssl, void *ctx) { - const char* encStr; - - (void)key_size; + if (ssl) + ssl->EncryptKeysCtx = ctx; +} +/* Get encryption keys callback context */ +void* wolfSSL_GetEncryptKeysCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EncryptKeysCtx; - switch (cipher) { - 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 -#ifndef NO_AES - case wolfssl_aes: - if (key_size == 128) - encStr = "AES(128)"; - else if (key_size == 256) - encStr = "AES(256)"; - else - encStr = "AES(?)"; - break; - #ifdef HAVE_AESGCM - case wolfssl_aes_gcm: - if (key_size == 128) - encStr = "AESGCM(128)"; - else if (key_size == 256) - encStr = "AESGCM(256)"; - else - encStr = "AESGCM(?)"; - break; - #endif - #ifdef HAVE_AESCCM - case wolfssl_aes_ccm: - if (key_size == 128) - encStr = "AESCCM(128)"; - else if (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_ARIA - case wolfssl_aria_gcm: - if (key_size == 128) - encStr = "Aria(128)"; - else if (key_size == 192) - encStr = "Aria(192)"; - else if (key_size == 256) - encStr = "Aria(256)"; - else - encStr = "Aria(?)"; - break; -#endif -#ifdef HAVE_CAMELLIA - case wolfssl_camellia: - if (key_size == 128) - encStr = "Camellia(128)"; - else if (key_size == 256) - encStr = "Camellia(256)"; - else - encStr = "Camellia(?)"; - break; -#endif - default: - encStr = "unknown"; - break; - } + return NULL; +} - return encStr; +/* callback for Tls finished */ +/* the callback can be used to build TLS Finished message if enabled */ +void wolfSSL_CTX_SetTlsFinishedCb(WOLFSSL_CTX* ctx, CallbackTlsFinished cb) +{ + if (ctx) + ctx->TlsFinishedCb = cb; +} +/* Set Tls finished callback context */ +void wolfSSL_SetTlsFinishedCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->TlsFinishedCtx = ctx; } +/* Get Tls finished callback context */ +void* wolfSSL_GetTlsFinishedCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->TlsFinishedCtx; -static WC_INLINE const char* wolfssl_mac_to_string(int mac) + return NULL; +} +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) +/* callback for verify data */ +void wolfSSL_CTX_SetVerifyMacCb(WOLFSSL_CTX* ctx, CallbackVerifyMac cb) { - const char* macStr; + if (ctx) + ctx->VerifyMacCb = cb; +} - switch (mac) { - 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 - default: - macStr = "unknown"; - break; - } +/* Set set keys callback context */ +void wolfSSL_SetVerifyMacCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->VerifyMacCtx = ctx; +} +/* Get set keys callback context */ +void* wolfSSL_GetVerifyMacCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->VerifyMacCtx; - return macStr; + return NULL; } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ -char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, - int len) +void wolfSSL_CTX_SetHKDFExpandLabelCb(WOLFSSL_CTX* ctx, + CallbackHKDFExpandLabel cb) { - char *ret = in; - const char *keaStr, *authStr, *encStr, *macStr; - size_t strLen; - WOLFSSL_ENTER("wolfSSL_CIPHER_description"); - - if (cipher == NULL || in == NULL) - return NULL; + if (ctx) + ctx->HKDFExpandLabelCb = cb; +} +#ifdef WOLFSSL_PUBLIC_ASN +void wolfSSL_CTX_SetProcessPeerCertCb(WOLFSSL_CTX* ctx, + CallbackProcessPeerCert cb) +{ + if (ctx) + ctx->ProcessPeerCertCb = cb; +} +#endif /* WOLFSSL_PUBLIC_ASN */ +void wolfSSL_CTX_SetProcessServerSigKexCb(WOLFSSL_CTX* ctx, + CallbackProcessServerSigKex cb) +{ + if (ctx) + ctx->ProcessServerSigKexCb = cb; +} +void wolfSSL_CTX_SetPerformTlsRecordProcessingCb(WOLFSSL_CTX* ctx, + CallbackPerformTlsRecordProcessing cb) +{ + if (ctx) + ctx->PerformTlsRecordProcessingCb = cb; +} +#endif /* HAVE_PK_CALLBACKS */ +#endif /* NO_CERTS */ -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - /* if cipher is in the stack from wolfSSL_get_ciphers_compat then - * Return the description based on cipher_names[cipher->offset] - */ - if (cipher->in_stack == TRUE) { - wolfSSL_sk_CIPHER_description((WOLFSSL_CIPHER*)cipher); - XSTRNCPY(in,cipher->description,len); - return ret; - } -#endif - - /* Get the cipher description based on the SSL session cipher */ - keaStr = wolfssl_kea_to_string(cipher->ssl->specs.kea); - authStr = wolfssl_sigalg_to_string(cipher->ssl->specs.sig_algo); - encStr = wolfssl_cipher_to_string(cipher->ssl->specs.bulk_cipher_algorithm, - cipher->ssl->specs.key_size); - macStr = wolfssl_mac_to_string(cipher->ssl->specs.mac_algorithm); - - /* 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; +#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH) +void wolfSSL_CTX_SetDhGenerateKeyPair(WOLFSSL_CTX* ctx, + CallbackDhGenerateKeyPair cb) { + if (ctx) + ctx->DhGenerateKeyPairCb = cb; } - - -#ifndef NO_WOLFSSL_STUB -int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, - int* ssl) +void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb) { - (void)url; - (void)host; - (void)port; - (void)path; - (void)ssl; - WOLFSSL_STUB("OCSP_parse_url"); - return 0; + if (ctx) + ctx->DhAgreeCb = cb; } -#endif - -#ifndef NO_WOLFSSL_STUB -void wolfSSL_RAND_screen(void) +void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx) { - WOLFSSL_STUB("RAND_screen"); + if (ssl) + ssl->DhAgreeCtx = ctx; } -#endif - - - -int wolfSSL_RAND_load_file(const char* fname, long len) +void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) { - (void)fname; - /* wolfCrypt provides enough entropy internally or will report error */ - if (len == -1) - return 1024; - else - return (int)len; -} - + if (ssl) + return ssl->DhAgreeCtx; -#ifndef NO_WOLFSSL_STUB -WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) -{ - WOLFSSL_STUB("COMP_zlib"); - return 0; + return NULL; } -#endif +#endif /* HAVE_PK_CALLBACKS && !NO_DH */ -#ifndef NO_WOLFSSL_STUB -WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) -{ - WOLFSSL_STUB("COMP_rle"); - return 0; -} -#endif +#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_HKDF) -#ifndef NO_WOLFSSL_STUB -int wolfSSL_COMP_add_compression_method(int method, void* data) +void wolfSSL_CTX_SetHKDFExtractCb(WOLFSSL_CTX* ctx, CallbackHKDFExtract cb) { - (void)method; - (void)data; - WOLFSSL_STUB("COMP_add_compression_method"); - return 0; + if (ctx) + ctx->HkdfExtractCb = cb; } -#endif -/* wolfSSL_set_dynlock_create_callback - * CRYPTO_set_dynlock_create_callback has been deprecated since openSSL 1.0.1. - * This function exists for compatibility purposes because wolfSSL satisfies - * thread safety without relying on the callback. - */ -void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)( - const char*, int)) -{ - WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback"); - (void)f; -} -/* wolfSSL_set_dynlock_lock_callback - * CRYPTO_set_dynlock_lock_callback has been deprecated since openSSL 1.0.1. - * This function exists for compatibility purposes because wolfSSL satisfies - * thread safety without relying on the callback. - */ -void wolfSSL_set_dynlock_lock_callback( - void (*f)(int, WOLFSSL_dynlock_value*, const char*, int)) -{ - WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback"); - (void)f; -} -/* wolfSSL_set_dynlock_destroy_callback - * CRYPTO_set_dynlock_destroy_callback has been deprecated since openSSL 1.0.1. - * This function exists for compatibility purposes because wolfSSL satisfies - * thread safety without relying on the callback. - */ -void wolfSSL_set_dynlock_destroy_callback( - void (*f)(WOLFSSL_dynlock_value*, const char*, int)) +void wolfSSL_SetHKDFExtractCtx(WOLFSSL* ssl, void *ctx) { - WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback"); - (void)f; + if (ssl) + ssl->HkdfExtractCtx = ctx; } - -#endif /* OPENSSL_EXTRA */ - -#ifdef OPENSSL_EXTRA -#ifndef NO_CERTS - -#if !defined(NO_ASN) && !defined(NO_PWDBASED) -/* Copies unencrypted DER key buffer into "der". If "der" is null then the size - * of buffer needed is returned. If *der == NULL then it allocates a buffer. - * NOTE: This also advances the "der" pointer to be at the end of buffer. - * - * Returns size of key buffer on success - */ -int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der) +void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl) { - return wolfSSL_EVP_PKEY_get_der(key, der); + if (ssl) + return ssl->HkdfExtractCtx; + + return NULL; } +#endif /* HAVE_PK_CALLBACKS && HAVE_HKDF */ -int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) -{ -#if !defined(NO_RSA) || defined(HAVE_ECC) -#ifdef HAVE_ECC - unsigned char *local_der = NULL; - word32 local_derSz = 0; - unsigned char *pub_der = NULL; - ecc_key *eccKey = NULL; - word32 inOutIdx = 0; +#ifdef WOLFSSL_HAVE_WOLFSCEP + /* Used by autoconf to see if wolfSCEP is available */ + void wolfSSL_wolfSCEP(void) {} #endif - word32 pub_derSz = 0; - int ret; - int key_type = 0; - if (key == NULL) { - return WOLFSSL_FATAL_ERROR; - } - - key_type = key->type; - if ((key_type != EVP_PKEY_EC) && (key_type != EVP_PKEY_RSA)) { - return WOLFSSL_FATAL_ERROR; - } -#ifndef NO_RSA - if (key_type == EVP_PKEY_RSA) { - return wolfSSL_i2d_RSAPublicKey(key->rsa, der); - } +#ifdef WOLFSSL_HAVE_CERT_SERVICE + /* Used by autoconf to see if cert service is available */ + void wolfSSL_cert_service(void) {} #endif - /* Now that RSA is taken care of, we only need to consider the ECC case. */ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(WOLFCRYPT_ONLY) -#ifdef HAVE_ECC + /* NID variables are dependent on compatibility header files currently + * + * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL + * on fail + */ - /* We need to get the DER, then convert it to a public key. But what we get - * might be a buffered private key so we need to decode it and then encode - * the public part. */ - ret = wolfSSL_EVP_PKEY_get_der(key, &local_der); - if (ret <= 0) { - /* In this case, there was no buffered DER at all. This could be the - * case where the key that was passed in was generated. So now we - * have to create the local DER. */ - local_derSz = wolfSSL_i2d_ECPrivateKey(key->ecc, &local_der); - if (local_derSz == 0) { - ret = WOLFSSL_FATAL_ERROR; - } - } else { - local_derSz = ret; - ret = 0; + WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id) + { + return wolfSSL_OBJ_nid2obj_ex(id, NULL); } - if (ret == 0) { - eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC); - if (eccKey == NULL) { - WOLFSSL_MSG("Failed to allocate key buffer."); - ret = WOLFSSL_FATAL_ERROR; - } - } - if (ret == 0) { - ret = wc_ecc_init(eccKey); - } + WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id, + WOLFSSL_ASN1_OBJECT* arg_obj) + { + word32 oidSz = 0; + int nid = 0; + const byte* oid; + word32 type = 0; + WOLFSSL_ASN1_OBJECT* obj = arg_obj; + byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */ + word32 objSz = 0; + const char* sName = NULL; + int i; - if (ret == 0) { - ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz); - if (ret < 0) { - /* We now try again as x.963 [point type][x][opt y]. */ - ret = wc_ecc_import_x963(local_der, local_derSz, eccKey); - } - } +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj"); +#endif - if (ret == 0) { - pub_derSz = wc_EccPublicKeyDerSize(eccKey, 0); - if ((int)pub_derSz <= 0) { - ret = WOLFSSL_FAILURE; + for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { + if (wolfssl_object_info[i].nid == id) { + nid = id; + id = wolfssl_object_info[i].id; + sName = wolfssl_object_info[i].sName; + type = wolfssl_object_info[i].type; + break; + } } - } - - if (ret == 0) { - pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL, - DYNAMIC_TYPE_PUBLIC_KEY); - if (pub_der == NULL) { - WOLFSSL_MSG("Failed to allocate output buffer."); - ret = WOLFSSL_FATAL_ERROR; + if (i == (int)WOLFSSL_OBJECT_INFO_SZ) { + WOLFSSL_MSG("NID not in table"); + #ifdef WOLFSSL_QT + sName = NULL; + type = (word32)id; + #else + return NULL; + #endif } - } - if (ret == 0) { - pub_derSz = wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 0); - if ((int)pub_derSz <= 0) { - ret = WOLFSSL_FATAL_ERROR; - } - } + #ifdef HAVE_ECC + if (type == 0 && wc_ecc_get_oid((word32)id, &oid, &oidSz) > 0) { + type = oidCurveType; + } + #endif /* HAVE_ECC */ - /* This block is for actually returning the DER of the public key */ - if ((ret == 0) && (der != NULL)) { - if (*der == NULL) { - *der = (unsigned char*)XMALLOC(pub_derSz, NULL, - DYNAMIC_TYPE_PUBLIC_KEY); - if (*der == NULL) { - WOLFSSL_MSG("Failed to allocate output buffer."); - ret = WOLFSSL_FATAL_ERROR; + if (sName != NULL) { + if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) { + WOLFSSL_MSG("Attempted short name is too large"); + return NULL; } + } - if (ret == 0) { - XMEMCPY(*der, pub_der, pub_derSz); + oid = OidFromId((word32)id, type, &oidSz); + + /* set object ID to buffer */ + if (obj == NULL){ + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; } } - else { - XMEMCPY(*der, pub_der, pub_derSz); - *der += pub_derSz; + obj->nid = nid; + obj->type = id; + obj->grp = (int)type; + + obj->sName[0] = '\0'; + if (sName != NULL) { + XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName)); } - } - XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(local_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + objBuf[0] = ASN_OBJECT_ID; objSz++; + objSz += SetLength(oidSz, objBuf + 1); + if (oidSz) { + XMEMCPY(objBuf + objSz, oid, oidSz); + objSz += oidSz; + } - wc_ecc_free(eccKey); - XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); + if (obj->objSz == 0 || objSz != obj->objSz) { + obj->objSz = objSz; + if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || + (obj->obj == NULL)) { + if (obj->obj != NULL) + XFREE((byte*)obj->obj, NULL, DYNAMIC_TYPE_ASN1); + obj->obj = (byte*)XMALLOC(obj->objSz, NULL, DYNAMIC_TYPE_ASN1); + if (obj->obj == NULL) { + wolfSSL_ASN1_OBJECT_free(obj); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + } + XMEMCPY((byte*)obj->obj, objBuf, obj->objSz); -#else - ret = WOLFSSL_FATAL_ERROR; -#endif /* HAVE_ECC */ + (void)type; - if (ret == 0) { - return pub_derSz; + return obj; } - return ret; -#else - return WOLFSSL_FATAL_ERROR; -#endif /* !NO_RSA || HAVE_ECC */ -} -#endif /* !NO_ASN && !NO_PWDBASED */ + static const char* oid_translate_num_to_str(const char* oid) + { + const struct oid_dict { + const char* num; + const char* desc; + } oid_dict[] = { + { "2.5.29.37.0", "Any Extended Key Usage" }, + { "1.3.6.1.5.5.7.3.1", "TLS Web Server Authentication" }, + { "1.3.6.1.5.5.7.3.2", "TLS Web Client Authentication" }, + { "1.3.6.1.5.5.7.3.3", "Code Signing" }, + { "1.3.6.1.5.5.7.3.4", "E-mail Protection" }, + { "1.3.6.1.5.5.7.3.8", "Time Stamping" }, + { "1.3.6.1.5.5.7.3.9", "OCSP Signing" }, + { NULL, NULL } + }; + const struct oid_dict* idx; -#endif /* !NO_CERTS */ -#endif /* OPENSSL_EXTRA */ + for (idx = oid_dict; idx->num != NULL; idx++) { + if (!XSTRCMP(oid, idx->num)) { + return idx->desc; + } + } + return NULL; + } -#ifdef OPENSSL_EXTRA + static int wolfssl_obj2txt_numeric(char *buf, int bufLen, + const WOLFSSL_ASN1_OBJECT *a) + { + int bufSz; + int length; + word32 idx = 0; + byte tag; -/* Sets the DNS hostname to name. - * Hostname is cleared if name is NULL or empty. */ -int wolfSSL_set1_host(WOLFSSL * ssl, const char* name) -{ - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } + if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) { + return WOLFSSL_FAILURE; + } - return wolfSSL_X509_VERIFY_PARAM_set1_host(ssl->param, name, 0); -} + if (tag != ASN_OBJECT_ID) { + WOLFSSL_MSG("Bad ASN1 Object"); + return WOLFSSL_FAILURE; + } -/****************************************************************************** -* wolfSSL_CTX_set1_param - set a pointer to the SSL verification parameters -* -* RETURNS: -* WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE -* Note: Returns WOLFSSL_SUCCESS, in case either parameter is NULL, -* same as openssl. -*/ -int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm) -{ - if (ctx == NULL || vpm == NULL) - return WOLFSSL_SUCCESS; + if (GetLength((const byte*)a->obj, &idx, &length, + a->objSz) < 0 || length < 0) { + return ASN_PARSE_E; + } - return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, vpm); -} + if (bufLen < MAX_OID_STRING_SZ) { + bufSz = bufLen - 1; + } + else { + bufSz = MAX_OID_STRING_SZ; + } -/****************************************************************************** -* wolfSSL_CTX/_get0_param - return a pointer to the SSL verification parameters -* -* RETURNS: -* returns pointer to the SSL verification parameters on success, -* otherwise returns NULL -*/ -WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx) -{ - if (ctx == NULL) { - return NULL; - } + if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx, + (word32)length)) <= 0) { + WOLFSSL_MSG("Error decoding OID"); + return WOLFSSL_FAILURE; + } - return ctx->param; -} + buf[bufSz] = '\0'; -WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) -{ - if (ssl == NULL) { - return NULL; + return bufSz; } - return ssl->param; -} -#endif /* OPENSSL_EXTRA */ + /* If no_name is one then use numerical form, otherwise short name. + * + * Returns the buffer size on success, WOLFSSL_FAILURE on error + */ + int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, const WOLFSSL_ASN1_OBJECT *a, + int no_name) + { + int bufSz; + const char* desc; + const char* name; -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -/* Gets an index to store SSL structure at. - * - * Returns positive index on success and negative values on failure - */ -int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) -{ - WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); + WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt"); - /* store SSL at index 0 */ - return 0; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + if (buf == NULL || bufLen <= 1 || a == NULL) { + WOLFSSL_MSG("Bad input argument"); + return WOLFSSL_FAILURE; + } -#ifdef OPENSSL_EXTRA -/* Sets a function callback that will send information about the state of all - * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed - * in. - * - * ctx WOLFSSL_CTX structure to set callback function in - * f callback function to use - */ -void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, - void (*f)(const WOLFSSL* ssl, int type, int val)) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback"); - if (ctx == NULL) { - WOLFSSL_MSG("Bad function argument"); - } - else { - ctx->CBIS = f; - } -} + if (no_name == 1) { + return wolfssl_obj2txt_numeric(buf, bufLen, a); + } -void wolfSSL_set_info_callback(WOLFSSL* ssl, - void (*f)(const WOLFSSL* ssl, int type, int val)) -{ - WOLFSSL_ENTER("wolfSSL_set_info_callback"); - if (ssl == NULL) { - WOLFSSL_MSG("Bad function argument"); + /* return long name unless using x509small, then return short name */ +#if defined(OPENSSL_EXTRA_X509_SMALL) && !defined(OPENSSL_EXTRA) + name = a->sName; +#else + name = wolfSSL_OBJ_nid2ln(wolfSSL_OBJ_obj2nid(a)); +#endif + + if (name == NULL) { + WOLFSSL_MSG("Name not found"); + bufSz = 0; + } + else if (XSTRLEN(name) + 1 < (word32)bufLen - 1) { + bufSz = (int)XSTRLEN(name); + } + else { + bufSz = bufLen - 1; + } + if (bufSz) { + XMEMCPY(buf, name, bufSz); + } + else if (a->type == GEN_DNS || a->type == GEN_EMAIL || + a->type == GEN_URI) { + bufSz = (int)XSTRLEN((const char*)a->obj); + XMEMCPY(buf, a->obj, min((word32)bufSz, (word32)bufLen)); + } + else if ((bufSz = wolfssl_obj2txt_numeric(buf, bufLen, a)) > 0) { + if ((desc = oid_translate_num_to_str(buf))) { + bufSz = (int)XSTRLEN(desc); + bufSz = (int)min((word32)bufSz,(word32) bufLen - 1); + XMEMCPY(buf, desc, bufSz); + } + } + else { + bufSz = 0; + } + + buf[bufSz] = '\0'; + + return bufSz; } - else { - ssl->CBIS = f; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS_SMALL) + /* Returns the long name that corresponds with an ASN1_OBJECT nid value. + * n : NID value of ASN1_OBJECT to search */ + const char* wolfSSL_OBJ_nid2ln(int n) + { + const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; + size_t i; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { + if (obj_info->nid == n) { + return obj_info->lName; + } + } + WOLFSSL_MSG("NID not found in table"); + return NULL; } -} +#endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL, + WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY, WOLFSSL_WPAS_SMALL */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) + /* Return the corresponding short name for the nid . + * or NULL if short name can't be found. + */ + const char * wolfSSL_OBJ_nid2sn(int n) { + const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; + size_t i; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn"); -unsigned long wolfSSL_ERR_peek_error(void) -{ - WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + if (n == NID_md5) { + /* NID_surname == NID_md5 and NID_surname comes before NID_md5 in + * wolfssl_object_info. As a result, the loop below will incorrectly + * return "SN" instead of "MD5." NID_surname isn't the true OpenSSL + * NID, but other functions rely on this table and modifying it to + * conform with OpenSSL's NIDs isn't trivial. */ + return "MD5"; + } + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { + if (obj_info->nid == n) { + return obj_info->sName; + } + } + WOLFSSL_MSG_EX("SN not found (nid:%d)",n); + return NULL; + } - return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); -} +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + int wolfSSL_OBJ_sn2nid(const char *sn) { + WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid"); + if (sn == NULL) + return NID_undef; + return wc_OBJ_sn2nid(sn); + } +#endif -int wolfSSL_ERR_GET_LIB(unsigned long err) -{ - unsigned long value; + size_t wolfSSL_OBJ_length(const WOLFSSL_ASN1_OBJECT* o) + { + size_t ret = 0; + int err = 0; + word32 idx = 0; + int len = 0; - value = (err & 0xFFFFFFL); - switch (value) { - case -SSL_R_HTTP_REQUEST: - return ERR_LIB_SSL; - case -ASN_NO_PEM_HEADER: - case PEM_R_NO_START_LINE: - case PEM_R_PROBLEMS_GETTING_PASSWORD: - case PEM_R_BAD_PASSWORD_READ: - case PEM_R_BAD_DECRYPT: - return ERR_LIB_PEM; - case EVP_R_BAD_DECRYPT: - case EVP_R_BN_DECODE_ERROR: - case EVP_R_DECODE_ERROR: - case EVP_R_PRIVATE_KEY_DECODE_ERROR: - return ERR_LIB_EVP; - case ASN1_R_HEADER_TOO_LONG: - return ERR_LIB_ASN1; - default: - return 0; - } -} + WOLFSSL_ENTER("wolfSSL_OBJ_length"); -/* This function is to find global error values that are the same through out - * all library version. With wolfSSL having only one set of error codes the - * return value is pretty straight forward. The only thing needed is all wolfSSL - * error values are typically negative. - * - * Returns the error reason - */ -int wolfSSL_ERR_GET_REASON(unsigned long err) -{ - int ret = (int)err; + if (o == NULL || o->obj == NULL) { + WOLFSSL_MSG("Bad argument."); + err = 1; + } - WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON"); + if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) { + WOLFSSL_MSG("Error parsing ASN.1 header."); + err = 1; + } + if (err == 0) { + ret = (size_t)len; + } -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - /* Nginx looks for this error to know to stop parsing certificates. - * Same for HAProxy. */ - if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE) || - ((err & 0xFFFFFFL) == -ASN_NO_PEM_HEADER) || - ((err & 0xFFFL) == PEM_R_NO_START_LINE )) - return PEM_R_NO_START_LINE; - if (err == ((ERR_LIB_SSL << 24) | -SSL_R_HTTP_REQUEST)) - return SSL_R_HTTP_REQUEST; -#endif -#if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) - if (err == ((ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG)) - return ASN1_R_HEADER_TOO_LONG; -#endif + WOLFSSL_LEAVE("wolfSSL_OBJ_length", (int)ret); - /* check if error value is in range of wolfSSL errors */ - ret = 0 - ret; /* setting as negative value */ - /* wolfCrypt range is less than MAX (-100) - wolfSSL range is MIN (-300) and lower */ - if (ret < MAX_CODE_E && ret > MIN_CODE_E) { return ret; } - else { - WOLFSSL_MSG("Not in range of typical error values"); - ret = (int)err; - } - return ret; -} + const unsigned char* wolfSSL_OBJ_get0_data(const WOLFSSL_ASN1_OBJECT* o) + { + const unsigned char* ret = NULL; + int err = 0; + word32 idx = 0; + int len = 0; -/* returns a string that describes the alert - * - * alertID the alert value to look up - */ -const char* wolfSSL_alert_type_string_long(int alertID) -{ - WOLFSSL_ENTER("wolfSSL_alert_type_string_long"); + WOLFSSL_ENTER("wolfSSL_OBJ_get0_data"); - return AlertTypeToString(alertID); -} + if (o == NULL || o->obj == NULL) { + WOLFSSL_MSG("Bad argument."); + err = 1; + } + if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) { + WOLFSSL_MSG("Error parsing ASN.1 header."); + err = 1; + } + if (err == 0) { + ret = o->obj + idx; + } -const char* wolfSSL_alert_desc_string_long(int alertID) -{ - WOLFSSL_ENTER("wolfSSL_alert_desc_string_long"); + return ret; + } - return AlertTypeToString(alertID); -} -#define STATE_STRINGS_PROTO(s) \ - { \ - {"SSLv3 " s, \ - "SSLv3 " s, \ - "SSLv3 " s}, \ - {"TLSv1 " s, \ - "TLSv1 " s, \ - "TLSv1 " s}, \ - {"TLSv1_1 " s, \ - "TLSv1_1 " s, \ - "TLSv1_1 " s}, \ - {"TLSv1_2 " s, \ - "TLSv1_2 " s, \ - "TLSv1_2 " s}, \ - {"TLSv1_3 " s, \ - "TLSv1_3 " s, \ - "TLSv1_3 " s}, \ - {"DTLSv1 " s, \ - "DTLSv1 " s, \ - "DTLSv1 " s}, \ - {"DTLSv1_2 " s, \ - "DTLSv1_2 " s, \ - "DTLSv1_2 " s}, \ - {"DTLSv1_3 " s, \ - "DTLSv1_3 " s, \ - "DTLSv1_3 " s}, \ - } + /* Gets the NID value that corresponds with the ASN1 object. + * + * o ASN1 object to get NID of + * + * Return NID on success and a negative value on failure + */ + int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) + { + word32 oid = 0; + word32 idx = 0; + int ret; -#define STATE_STRINGS_PROTO_RW(s) \ - { \ - {"SSLv3 read " s, \ - "SSLv3 write " s, \ - "SSLv3 " s}, \ - {"TLSv1 read " s, \ - "TLSv1 write " s, \ - "TLSv1 " s}, \ - {"TLSv1_1 read " s, \ - "TLSv1_1 write " s, \ - "TLSv1_1 " s}, \ - {"TLSv1_2 read " s, \ - "TLSv1_2 write " s, \ - "TLSv1_2 " s}, \ - {"TLSv1_3 read " s, \ - "TLSv1_3 write " s, \ - "TLSv1_3 " s}, \ - {"DTLSv1 read " s, \ - "DTLSv1 write " s, \ - "DTLSv1 " s}, \ - {"DTLSv1_2 read " s, \ - "DTLSv1_2 write " s, \ - "DTLSv1_2 " s}, \ - {"DTLSv1_3 read " s, \ - "DTLSv1_3 write " s, \ - "DTLSv1_3 " s}, \ - } +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); +#endif -/* Gets the current state of the WOLFSSL structure - * - * ssl WOLFSSL structure to get state of - * - * Returns a human readable string of the WOLFSSL structure state - */ -const char* wolfSSL_state_string_long(const WOLFSSL* ssl) -{ + if (o == NULL) { + return -1; + } - static const char* OUTPUT_STR[24][8][3] = { - STATE_STRINGS_PROTO("Initialization"), - STATE_STRINGS_PROTO_RW("Server Hello Request"), - STATE_STRINGS_PROTO_RW("Server Hello Verify Request"), - STATE_STRINGS_PROTO_RW("Server Hello Retry Request"), - STATE_STRINGS_PROTO_RW("Server Hello"), - STATE_STRINGS_PROTO_RW("Server Certificate Status"), - STATE_STRINGS_PROTO_RW("Server Encrypted Extensions"), - STATE_STRINGS_PROTO_RW("Server Session Ticket"), - STATE_STRINGS_PROTO_RW("Server Certificate Request"), - STATE_STRINGS_PROTO_RW("Server Cert"), - STATE_STRINGS_PROTO_RW("Server Key Exchange"), - STATE_STRINGS_PROTO_RW("Server Hello Done"), - STATE_STRINGS_PROTO_RW("Server Change CipherSpec"), - STATE_STRINGS_PROTO_RW("Server Finished"), - STATE_STRINGS_PROTO_RW("server Key Update"), - STATE_STRINGS_PROTO_RW("Client Hello"), - STATE_STRINGS_PROTO_RW("Client Key Exchange"), - STATE_STRINGS_PROTO_RW("Client Cert"), - STATE_STRINGS_PROTO_RW("Client Change CipherSpec"), - STATE_STRINGS_PROTO_RW("Client Certificate Verify"), - STATE_STRINGS_PROTO_RW("Client End Of Early Data"), - STATE_STRINGS_PROTO_RW("Client Finished"), - STATE_STRINGS_PROTO_RW("Client Key Update"), - STATE_STRINGS_PROTO("Handshake Done"), - }; - enum ProtocolVer { - SSL_V3 = 0, - TLS_V1, - TLS_V1_1, - TLS_V1_2, - TLS_V1_3, - DTLS_V1, - DTLS_V1_2, - DTLS_V1_3, - UNKNOWN = 100 - }; + #ifdef WOLFSSL_QT + if (o->grp == oidCertExtType) { + /* If nid is an unknown extension, return NID_undef */ + if (wolfSSL_OBJ_nid2sn(o->nid) == NULL) + return NID_undef; + } + #endif - enum IOMode { - SS_READ = 0, - SS_WRITE, - SS_NEITHER - }; + if (o->nid > 0) + return o->nid; + if ((ret = GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz)) < 0) { + if (ret == WC_NO_ERR_TRACE(ASN_OBJECT_ID_E)) { + /* Put ASN object tag in front and try again */ + int len = SetObjectId(o->objSz, NULL) + o->objSz; + byte* buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (!buf) { + WOLFSSL_MSG("malloc error"); + return -1; + } + idx = SetObjectId(o->objSz, buf); + XMEMCPY(buf + idx, o->obj, o->objSz); + idx = 0; + ret = GetObjectId(buf, &idx, &oid, o->grp, len); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_MSG("Issue getting OID of object"); + return -1; + } + } + else { + WOLFSSL_MSG("Issue getting OID of object"); + return -1; + } + } - enum SslState { - ss_null_state = 0, - ss_server_hellorequest, - ss_server_helloverify, - ss_server_helloretryrequest, - ss_server_hello, - ss_server_certificatestatus, - ss_server_encryptedextensions, - ss_server_sessionticket, - ss_server_certrequest, - ss_server_cert, - ss_server_keyexchange, - ss_server_hellodone, - ss_server_changecipherspec, - ss_server_finished, - ss_server_keyupdate, - ss_client_hello, - ss_client_keyexchange, - ss_client_cert, - ss_client_changecipherspec, - ss_client_certverify, - ss_client_endofearlydata, - ss_client_finished, - ss_client_keyupdate, - ss_handshake_done - }; + return oid2nid(oid, o->grp); + } - int protocol = 0; - int cbmode = 0; - int state = 0; + /* Return the corresponding NID for the long name + * or NID_undef if NID can't be found. + */ + int wolfSSL_OBJ_ln2nid(const char *ln) + { + const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; + size_t lnlen; + WOLFSSL_ENTER("wolfSSL_OBJ_ln2nid"); + if (ln && (lnlen = XSTRLEN(ln)) > 0) { + /* Accept input like "/commonName=" */ + if (ln[0] == '/') { + ln++; + lnlen--; + } + if (lnlen) { + size_t i; - WOLFSSL_ENTER("wolfSSL_state_string_long"); - if (ssl == NULL) { - WOLFSSL_MSG("Null argument passed in"); - return NULL; + if (ln[lnlen-1] == '=') { + lnlen--; + } + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { + if (lnlen == XSTRLEN(obj_info->lName) && + XSTRNCMP(ln, obj_info->lName, lnlen) == 0) { + return obj_info->nid; + } + } + } + } + return NID_undef; } - /* Get state of callback */ - if (ssl->cbmode == SSL_CB_MODE_WRITE) { - cbmode = SS_WRITE; - } - else if (ssl->cbmode == SSL_CB_MODE_READ) { - cbmode = SS_READ; - } - else { - cbmode = SS_NEITHER; - } + /* compares two objects, return 0 if equal */ + int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a, + const WOLFSSL_ASN1_OBJECT* b) + { + WOLFSSL_ENTER("wolfSSL_OBJ_cmp"); - /* Get protocol version */ - switch (ssl->version.major) { - case SSLv3_MAJOR: - switch (ssl->version.minor) { - case SSLv3_MINOR: - protocol = SSL_V3; - break; - case TLSv1_MINOR: - protocol = TLS_V1; - break; - case TLSv1_1_MINOR: - protocol = TLS_V1_1; - break; - case TLSv1_2_MINOR: - protocol = TLS_V1_2; - break; - case TLSv1_3_MINOR: - protocol = TLS_V1_3; - break; - default: - protocol = UNKNOWN; + if (a && b && a->obj && b->obj) { + if (a->objSz == b->objSz) { + return XMEMCMP(a->obj, b->obj, a->objSz); } - break; - case DTLS_MAJOR: - switch (ssl->version.minor) { - case DTLS_MINOR: - protocol = DTLS_V1; - break; - case DTLSv1_2_MINOR: - protocol = DTLS_V1_2; - break; - case DTLSv1_3_MINOR: - protocol = DTLS_V1_3; - break; - default: - protocol = UNKNOWN; + else if (a->type == EXT_KEY_USAGE_OID || + b->type == EXT_KEY_USAGE_OID) { + /* Special case for EXT_KEY_USAGE_OID so that + * cmp will be treated as a substring search */ + /* Used in libest to check for id-kp-cmcRA in + * EXT_KEY_USAGE extension */ + unsigned int idx; + const byte* s; /* shorter */ + unsigned int sLen; + const byte* l; /* longer */ + unsigned int lLen; + if (a->objSz > b->objSz) { + s = b->obj; sLen = b->objSz; + l = a->obj; lLen = a->objSz; + } + else { + s = a->obj; sLen = a->objSz; + l = b->obj; lLen = b->objSz; + } + for (idx = 0; idx <= lLen - sLen; idx++) { + if (XMEMCMP(l + idx, s, sLen) == 0) { + /* Found substring */ + return 0; + } + } } - break; - default: - protocol = UNKNOWN; - } - - /* accept process */ - if (ssl->cbmode == SSL_CB_MODE_READ) { - state = ssl->cbtype; - switch (state) { - case hello_request: - state = ss_server_hellorequest; - break; - case client_hello: - state = ss_client_hello; - break; - case server_hello: - state = ss_server_hello; - break; - case hello_verify_request: - state = ss_server_helloverify; - break; - case session_ticket: - state = ss_server_sessionticket; - break; - case end_of_early_data: - state = ss_client_endofearlydata; - break; - case hello_retry_request: - state = ss_server_helloretryrequest; - break; - case encrypted_extensions: - state = ss_server_encryptedextensions; - break; - case certificate: - if (ssl->options.side == WOLFSSL_SERVER_END) - state = ss_client_cert; - else if (ssl->options.side == WOLFSSL_CLIENT_END) - state = ss_server_cert; - else { - WOLFSSL_MSG("Unknown State"); - state = ss_null_state; - } - break; - case server_key_exchange: - state = ss_server_keyexchange; - break; - case certificate_request: - state = ss_server_certrequest; - break; - case server_hello_done: - state = ss_server_hellodone; - break; - case certificate_verify: - state = ss_client_certverify; - break; - case client_key_exchange: - state = ss_client_keyexchange; - break; - case finished: - if (ssl->options.side == WOLFSSL_SERVER_END) - state = ss_client_finished; - else if (ssl->options.side == WOLFSSL_CLIENT_END) - state = ss_server_finished; - else { - WOLFSSL_MSG("Unknown State"); - state = ss_null_state; - } - break; - case certificate_status: - state = ss_server_certificatestatus; - break; - case key_update: - if (ssl->options.side == WOLFSSL_SERVER_END) - state = ss_client_keyupdate; - else if (ssl->options.side == WOLFSSL_CLIENT_END) - state = ss_server_keyupdate; - else { - WOLFSSL_MSG("Unknown State"); - state = ss_null_state; - } - break; - case change_cipher_hs: - if (ssl->options.side == WOLFSSL_SERVER_END) - state = ss_client_changecipherspec; - else if (ssl->options.side == WOLFSSL_CLIENT_END) - state = ss_server_changecipherspec; - else { - WOLFSSL_MSG("Unknown State"); - state = ss_null_state; - } - break; - default: - WOLFSSL_MSG("Unknown State"); - state = ss_null_state; - } - } - else { - /* Send process */ - if (ssl->options.side == WOLFSSL_SERVER_END) - state = ssl->options.serverState; - else - state = ssl->options.clientState; - - switch (state) { - case SERVER_HELLOVERIFYREQUEST_COMPLETE: - state = ss_server_helloverify; - break; - case SERVER_HELLO_RETRY_REQUEST_COMPLETE: - state = ss_server_helloretryrequest; - break; - case SERVER_HELLO_COMPLETE: - state = ss_server_hello; - break; - case SERVER_ENCRYPTED_EXTENSIONS_COMPLETE: - state = ss_server_encryptedextensions; - break; - case SERVER_CERT_COMPLETE: - state = ss_server_cert; - break; - case SERVER_KEYEXCHANGE_COMPLETE: - state = ss_server_keyexchange; - break; - case SERVER_HELLODONE_COMPLETE: - state = ss_server_hellodone; - break; - case SERVER_CHANGECIPHERSPEC_COMPLETE: - state = ss_server_changecipherspec; - break; - case SERVER_FINISHED_COMPLETE: - state = ss_server_finished; - break; - case CLIENT_HELLO_RETRY: - case CLIENT_HELLO_COMPLETE: - state = ss_client_hello; - break; - case CLIENT_KEYEXCHANGE_COMPLETE: - state = ss_client_keyexchange; - break; - case CLIENT_CHANGECIPHERSPEC_COMPLETE: - state = ss_client_changecipherspec; - break; - case CLIENT_FINISHED_COMPLETE: - state = ss_client_finished; - break; - case HANDSHAKE_DONE: - state = ss_handshake_done; - break; - default: - WOLFSSL_MSG("Unknown State"); - state = ss_null_state; } - } - if (protocol == UNKNOWN) { - WOLFSSL_MSG("Unknown protocol"); - return ""; - } - else { - return OUTPUT_STR[state][protocol][cbmode]; + return WOLFSSL_FATAL_ERROR; } -} +#endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL, + WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY) + /* Gets the NID value that is related to the OID string passed in. Example + * string would be "2.5.29.14" for subject key ID. + * + * returns NID value on success and NID_undef on error + */ + int wolfSSL_OBJ_txt2nid(const char* s) + { + unsigned int i; + #ifdef WOLFSSL_CERT_EXT + int ret; + unsigned int sum = 0; + unsigned int outSz = MAX_OID_SZ; + unsigned char out[MAX_OID_SZ]; + #endif -/* - * Sets default PEM callback password if null is passed into - * the callback parameter of a PEM_read_bio_* function. - * - * Returns callback phrase size on success or WOLFSSL_FAILURE otherwise. - */ -int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) -{ - (void)w; - WOLFSSL_ENTER("wolfSSL_PEM_def_callback"); + WOLFSSL_ENTER("wolfSSL_OBJ_txt2nid"); - /* We assume that the user passes a default password as userdata */ - if (key) { - int sz = (int)XSTRLEN((const char*)key); - sz = (sz > num) ? num : sz; - XMEMCPY(name, key, sz); - return sz; - } else { - WOLFSSL_MSG("Error, default password cannot be created."); - return WOLFSSL_FAILURE; - } -} + if (s == NULL) { + return NID_undef; + } -#endif /* OPENSSL_EXTRA */ + #ifdef WOLFSSL_CERT_EXT + ret = EncodePolicyOID(out, &outSz, s, NULL); + if (ret == 0) { + /* sum OID */ + for (i = 0; i < outSz; i++) { + sum += out[i]; + } + } + #endif /* WOLFSSL_CERT_EXT */ -static long wolf_set_options(long old_op, long op) -{ - /* if SSL_OP_ALL then turn all bug workarounds on */ - if ((op & WOLFSSL_OP_ALL) == WOLFSSL_OP_ALL) { - WOLFSSL_MSG("\tSSL_OP_ALL"); - } + /* get the group that the OID's sum is in + * @TODO possible conflict with multiples */ + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) { + int len; + #ifdef WOLFSSL_CERT_EXT + if (ret == 0) { + if (wolfssl_object_info[i].id == (int)sum) { + return wolfssl_object_info[i].nid; + } + } + #endif - /* by default cookie exchange is on with DTLS */ - if ((op & WOLFSSL_OP_COOKIE_EXCHANGE) == WOLFSSL_OP_COOKIE_EXCHANGE) { - WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); - } + /* try as a short name */ + len = (int)XSTRLEN(s); + if ((int)XSTRLEN(wolfssl_object_info[i].sName) == len && + XSTRNCMP(wolfssl_object_info[i].sName, s, len) == 0) { + return wolfssl_object_info[i].nid; + } - if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { - WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); - } + /* try as a long name */ + if ((int)XSTRLEN(wolfssl_object_info[i].lName) == len && + XSTRNCMP(wolfssl_object_info[i].lName, s, len) == 0) { + return wolfssl_object_info[i].nid; + } + } -#ifdef SSL_OP_NO_TLSv1_3 - if ((op & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3"); + return NID_undef; } #endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) - if ((op & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); - } - - if ((op & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); - } - - if ((op & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { - WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); - } - - if ((op & WOLFSSL_OP_NO_SSLv3) == WOLFSSL_OP_NO_SSLv3) { - WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); - } - - if ((op & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) == - WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) { - WOLFSSL_MSG("\tWOLFSSL_OP_CIPHER_SERVER_PREFERENCE"); - } - - if ((op & WOLFSSL_OP_NO_COMPRESSION) == WOLFSSL_OP_NO_COMPRESSION) { - #ifdef HAVE_LIBZ - WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); - #else - WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in"); - #endif - } - - return old_op | op; -} + /* Creates new ASN1_OBJECT from short name, long name, or text + * representation of oid. If no_name is 0, then short name, long name, and + * numerical value of oid are interpreted. If no_name is 1, then only the + * numerical value of the oid is interpreted. + * + * Returns pointer to ASN1_OBJECT on success, or NULL on error. + */ +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) + WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name) + { + int i, ret; + int nid = NID_undef; + unsigned int outSz = MAX_OID_SZ; + unsigned char out[MAX_OID_SZ]; + WOLFSSL_ASN1_OBJECT* obj; -long wolfSSL_set_options(WOLFSSL* ssl, long op) -{ - word16 haveRSA = 1; - word16 havePSK = 0; - int keySz = 0; + WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj"); - WOLFSSL_ENTER("wolfSSL_set_options"); + if (s == NULL) + return NULL; - if (ssl == NULL) { - return 0; - } + /* If s is numerical value, try to sum oid */ + ret = EncodePolicyOID(out, &outSz, s, NULL); + if (ret == 0 && outSz > 0) { + /* If numerical encode succeeded then just + * create object from that because sums are + * not unique and can cause confusion. */ + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->obj = (byte*)XMALLOC(1 + MAX_LENGTH_SZ + outSz, NULL, + DYNAMIC_TYPE_ASN1); + if (obj->obj == NULL) { + wolfSSL_ASN1_OBJECT_free(obj); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; + i = SetObjectId((int)outSz, (byte*)obj->obj); + XMEMCPY((byte*)obj->obj + i, out, outSz); + obj->objSz = i + outSz; + return obj; + } - ssl->options.mask = wolf_set_options(ssl->options.mask, op); + /* TODO: update short names in wolfssl_object_info and check OID sums + are correct */ + for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { + /* Short name, long name, and numerical value are interpreted */ + if (no_name == 0 && + ((XSTRCMP(s, wolfssl_object_info[i].sName) == 0) || + (XSTRCMP(s, wolfssl_object_info[i].lName) == 0))) + { + nid = wolfssl_object_info[i].nid; + } + } - if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3) == WOLFSSL_OP_NO_TLSv1_3) { - if (ssl->version.minor == TLSv1_3_MINOR) - ssl->version.minor = TLSv1_2_MINOR; - } + if (nid != NID_undef) + return wolfSSL_OBJ_nid2obj(nid); - if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2) == WOLFSSL_OP_NO_TLSv1_2) { - if (ssl->version.minor == TLSv1_2_MINOR) - ssl->version.minor = TLSv1_1_MINOR; + return NULL; } +#endif - if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1) == WOLFSSL_OP_NO_TLSv1_1) { - if (ssl->version.minor == TLSv1_1_MINOR) - ssl->version.minor = TLSv1_MINOR; + /* compatibility function. Its intended use is to remove OID's from an + * internal table that have been added with OBJ_create. wolfSSL manages its + * own internal OID values and does not currently support OBJ_create. */ + void wolfSSL_OBJ_cleanup(void) + { + WOLFSSL_ENTER("wolfSSL_OBJ_cleanup"); } - if ((ssl->options.mask & WOLFSSL_OP_NO_TLSv1) == WOLFSSL_OP_NO_TLSv1) { - if (ssl->version.minor == TLSv1_MINOR) - ssl->version.minor = SSLv3_MINOR; + #ifndef NO_WOLFSSL_STUB + int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln) + { + (void)oid; + (void)sn; + (void)ln; + WOLFSSL_STUB("wolfSSL_OBJ_create"); + return WOLFSSL_FAILURE; } + #endif - if ((ssl->options.mask & WOLFSSL_OP_NO_COMPRESSION) - == WOLFSSL_OP_NO_COMPRESSION) { - #ifdef HAVE_LIBZ - ssl->options.usingCompression = 0; + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) + { + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); + ssl->options.verifyDepth = (byte)depth; #endif } -#if defined(HAVE_SESSION_TICKET) && (defined(OPENSSL_EXTRA) \ - || defined(HAVE_WEBSERVER) || defined(WOLFSSL_WPAS_SMALL)) - if ((ssl->options.mask & WOLFSSL_OP_NO_TICKET) == WOLFSSL_OP_NO_TICKET) { - ssl->options.noTicketTls12 = 1; - } -#endif +#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || + HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#ifdef OPENSSL_EXTRA - /* in the case of a version change the cipher suites should be reset */ -#ifndef NO_PSK - havePSK = ssl->options.havePSK; -#endif -#ifdef NO_RSA - haveRSA = 0; -#endif -#ifndef NO_CERTS - keySz = ssl->buffers.keySz; -#endif +/* 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"); - if (ssl->options.side != WOLFSSL_NEITHER_END) { - if (AllocateSuites(ssl) != 0) + (void)line; + (void)file; +#ifdef WOLFSSL_HAVE_ERROR_QUEUE + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); return 0; - InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, - ssl->options.haveDH, ssl->options.haveECDSAsig, - ssl->options.haveECC, TRUE, ssl->options.haveStaticECC, - ssl->options.haveFalconSig, ssl->options.haveDilithiumSig, - ssl->options.useAnon, TRUE, ssl->options.side); + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) + if (ret == -ASN_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #endif + #if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) + if (ret == ASN1_R_HEADER_TOO_LONG) { + return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; + } + #endif + return (unsigned long)ret; } - - return ssl->options.mask; +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } +#endif /* OPENSSL_EXTRA */ -long wolfSSL_get_options(const WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_options"); - if(ssl == NULL) - return WOLFSSL_FAILURE; - return ssl->options.mask; -} +#if defined(HAVE_EX_DATA) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ + defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || \ + defined(WOLFSSL_WPAS_SMALL) +CRYPTO_EX_cb_ctx* crypto_ex_cb_ctx_session = NULL; -#if defined(HAVE_SECURE_RENEGOTIATION) \ - || defined(HAVE_SERVER_RENEGOTIATION_INFO) -/* clears the counter for number of renegotiations done - * returns the current count before it is cleared */ -long wolfSSL_clear_num_renegotiations(WOLFSSL *s) +static int crypto_ex_cb_new(CRYPTO_EX_cb_ctx** dst, long ctx_l, void* ctx_ptr, + WOLFSSL_CRYPTO_EX_new* new_func, WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func) { - long total; - - WOLFSSL_ENTER("wolfSSL_clear_num_renegotiations"); - if (s == NULL) - return 0; - - total = s->secure_rene_count; - s->secure_rene_count = 0; - return total; + CRYPTO_EX_cb_ctx* new_ctx = (CRYPTO_EX_cb_ctx*)XMALLOC( + sizeof(CRYPTO_EX_cb_ctx), NULL, DYNAMIC_TYPE_OPENSSL); + if (new_ctx == NULL) + return -1; + new_ctx->ctx_l = ctx_l; + new_ctx->ctx_ptr = ctx_ptr; + new_ctx->new_func = new_func; + new_ctx->free_func = free_func; + new_ctx->dup_func = dup_func; + new_ctx->next = NULL; + /* Push to end of list */ + while (*dst != NULL) + dst = &(*dst)->next; + *dst = new_ctx; + return 0; } - -/* return the number of renegotiations since wolfSSL_new */ -long wolfSSL_total_renegotiations(WOLFSSL *s) +void crypto_ex_cb_free(CRYPTO_EX_cb_ctx* cb_ctx) { - WOLFSSL_ENTER("wolfSSL_total_renegotiations"); - return wolfSSL_num_renegotiations(s); + while (cb_ctx != NULL) { + CRYPTO_EX_cb_ctx* next = cb_ctx->next; + XFREE(cb_ctx, NULL, DYNAMIC_TYPE_OPENSSL); + cb_ctx = next; + } } - -/* return the number of renegotiations since wolfSSL_new */ -long wolfSSL_num_renegotiations(WOLFSSL* s) +void crypto_ex_cb_setup_new_data(void *new_obj, CRYPTO_EX_cb_ctx* cb_ctx, + WOLFSSL_CRYPTO_EX_DATA* ex_data) { - if (s == NULL) { - return 0; + int idx = 0; + for (; cb_ctx != NULL; idx++, cb_ctx = cb_ctx->next) { + if (cb_ctx->new_func != NULL) + cb_ctx->new_func(new_obj, NULL, ex_data, idx, cb_ctx->ctx_l, + cb_ctx->ctx_ptr); } - - return s->secure_rene_count; } - -/* Is there a renegotiation currently in progress? */ -int wolfSSL_SSL_renegotiate_pending(WOLFSSL *s) +int crypto_ex_cb_dup_data(const WOLFSSL_CRYPTO_EX_DATA *in, + WOLFSSL_CRYPTO_EX_DATA *out, CRYPTO_EX_cb_ctx* cb_ctx) { - return s && s->options.handShakeDone && - s->options.handShakeState != HANDSHAKE_DONE ? 1 : 0; + int idx = 0; + for (; cb_ctx != NULL; idx++, cb_ctx = cb_ctx->next) { + if (cb_ctx->dup_func != NULL) { + void* ptr = wolfSSL_CRYPTO_get_ex_data(in, idx); + if (!cb_ctx->dup_func(out, in, + &ptr, idx, + cb_ctx->ctx_l, cb_ctx->ctx_ptr)) { + return WOLFSSL_FAILURE; + } + wolfSSL_CRYPTO_set_ex_data(out, idx, ptr); + } + } + return WOLFSSL_SUCCESS; } -#endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */ - -#ifdef OPENSSL_EXTRA -long wolfSSL_clear_options(WOLFSSL* ssl, long opt) +void crypto_ex_cb_free_data(void *obj, CRYPTO_EX_cb_ctx* cb_ctx, + WOLFSSL_CRYPTO_EX_DATA* ex_data) { - WOLFSSL_ENTER("wolfSSL_clear_options"); - if(ssl == NULL) - return WOLFSSL_FAILURE; - ssl->options.mask &= ~opt; - return ssl->options.mask; + int idx = 0; + for (; cb_ctx != NULL; idx++, cb_ctx = cb_ctx->next) { + if (cb_ctx->free_func != NULL) + cb_ctx->free_func(obj, NULL, ex_data, idx, cb_ctx->ctx_l, + cb_ctx->ctx_ptr); + } } -#ifdef HAVE_PK_CALLBACKS -long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) +/** + * get_ex_new_index is a helper function for the following + * xx_get_ex_new_index functions: + * - wolfSSL_CRYPTO_get_ex_new_index + * - wolfSSL_CTX_get_ex_new_index + * - wolfSSL_get_ex_new_index + * Issues a unique index number for the specified class-index. + * Returns an index number greater or equal to zero on success, + * -1 on failure. + */ +int wolfssl_get_ex_new_index(int class_index, long ctx_l, void* ctx_ptr, + WOLFSSL_CRYPTO_EX_new* new_func, WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } + /* index counter for each class index*/ + static int ctx_idx = 0; + static int ssl_idx = 0; + static int ssl_session_idx = 0; + static int x509_idx = 0; - ssl->loggingCtx = arg; - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_PK_CALLBACKS */ + int idx = -1; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) -const unsigned char *wolfSSL_SESSION_get0_id_context( - const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length) -{ - return wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); -} -int wolfSSL_SESSION_set1_id(WOLFSSL_SESSION *s, - const unsigned char *sid, unsigned int sid_len) -{ - if (s == NULL) { - return WOLFSSL_FAILURE; - } - if (sid_len > ID_LEN) { - return WOLFSSL_FAILURE; - } - s->sessionIDSz = sid_len; - if (sid != s->sessionID) { - XMEMCPY(s->sessionID, sid, sid_len); + switch(class_index) { + case WOLF_CRYPTO_EX_INDEX_SSL: + WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(ctx_l, ctx_ptr, new_func, + dup_func, free_func); + idx = ssl_idx++; + break; + case WOLF_CRYPTO_EX_INDEX_SSL_CTX: + WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(ctx_l, ctx_ptr, new_func, + dup_func, free_func); + idx = ctx_idx++; + break; + case WOLF_CRYPTO_EX_INDEX_X509: + WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(ctx_l, ctx_ptr, new_func, + dup_func, free_func); + idx = x509_idx++; + break; + case WOLF_CRYPTO_EX_INDEX_SSL_SESSION: + if (crypto_ex_cb_new(&crypto_ex_cb_ctx_session, ctx_l, ctx_ptr, + new_func, dup_func, free_func) != 0) + return -1; + idx = ssl_session_idx++; + break; + + /* following class indexes are not supoprted */ + case WOLF_CRYPTO_EX_INDEX_X509_STORE: + case WOLF_CRYPTO_EX_INDEX_X509_STORE_CTX: + case WOLF_CRYPTO_EX_INDEX_DH: + case WOLF_CRYPTO_EX_INDEX_DSA: + case WOLF_CRYPTO_EX_INDEX_EC_KEY: + case WOLF_CRYPTO_EX_INDEX_RSA: + case WOLF_CRYPTO_EX_INDEX_ENGINE: + case WOLF_CRYPTO_EX_INDEX_UI: + case WOLF_CRYPTO_EX_INDEX_BIO: + case WOLF_CRYPTO_EX_INDEX_APP: + case WOLF_CRYPTO_EX_INDEX_UI_METHOD: + case WOLF_CRYPTO_EX_INDEX_DRBG: + default: + break; } - return WOLFSSL_SUCCESS; + if (idx >= MAX_EX_DATA) + return -1; + return idx; } +#endif /* HAVE_EX_DATA || WOLFSSL_WPAS_SMALL */ -int wolfSSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, - const unsigned char *sid_ctx, unsigned int sid_ctx_len) +#if defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) +void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) { - if (s == NULL) { - return WOLFSSL_FAILURE; - } - if (sid_ctx_len > ID_LEN) { - return WOLFSSL_FAILURE; - } - s->sessionCtxSz = sid_ctx_len; - if (sid_ctx != s->sessionCtx) { - XMEMCPY(s->sessionCtx, sid_ctx, sid_ctx_len); + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); +#ifdef HAVE_EX_DATA + if(ctx != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx); } - - return WOLFSSL_SUCCESS; -} - +#else + (void)ctx; + (void)idx; #endif - -/*** TBD ***/ -#ifndef NO_WOLFSSL_STUB -int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st) -{ - (void)st; - WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero"); - /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */ - return WOLFSSL_FAILURE; + return NULL; } -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST -long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, + WOLFSSL_CRYPTO_EX_new* new_func, + WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func) { - WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type"); - - if (s == NULL){ - return BAD_FUNC_ARG; - } - if (type == TLSEXT_STATUSTYPE_ocsp){ - int r = TLSX_UseCertificateStatusRequest(&s->extensions, (byte)type, 0, s, - s->heap, s->devId); - return (long)r; - } else { - WOLFSSL_MSG( - "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type."); - return WOLFSSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); + return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX, idx, arg, + new_func, dup_func, free_func); } -long wolfSSL_get_tlsext_status_type(WOLFSSL *s) +/* Return the index that can be used for the WOLFSSL structure to store + * application data. + * + */ +int wolfSSL_get_ex_new_index(long argValue, void* arg, + WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2, + WOLFSSL_CRYPTO_EX_free* cb3) { - TLSX* extension; + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); - if (s == NULL) - return WOLFSSL_FATAL_ERROR; - extension = TLSX_Find(s->extensions, TLSX_STATUS_REQUEST); - return extension != NULL ? TLSEXT_STATUSTYPE_ocsp : WOLFSSL_FATAL_ERROR; + return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL, argValue, arg, + cb1, cb2, cb3); } -#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ -#ifndef NO_WOLFSSL_STUB -long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) -{ - (void)s; - (void)arg; - WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); - return WOLFSSL_FAILURE; -} -#endif -/*** TBD ***/ -#ifndef NO_WOLFSSL_STUB -long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) +int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) { - (void)s; - (void)arg; - WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); + #ifdef HAVE_EX_DATA + if (ctx != NULL) + { + return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data); + } + #else + (void)ctx; + (void)idx; + (void)data; + #endif return WOLFSSL_FAILURE; } -#endif -/*** TBD ***/ -#ifndef NO_WOLFSSL_STUB -long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_CTX_set_ex_data_with_cleanup( + WOLFSSL_CTX* ctx, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) { - (void)s; - (void)arg; - WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data_with_cleanup"); + if (ctx != NULL) + { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, data, + cleanup_routine); + } return WOLFSSL_FAILURE; } -#endif +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ -/*** TBD ***/ -#ifndef NO_WOLFSSL_STUB -long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) -{ - (void)s; - (void)arg; - WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); - return WOLFSSL_FAILURE; -} -#endif +#endif /* defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) */ -#ifndef NO_WOLFSSL_STUB -/*** TBD ***/ -WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + +/* Returns char* to app data stored in ex[0]. + * + * ssl WOLFSSL structure to get app data from + */ +void* wolfSSL_get_app_data(const WOLFSSL *ssl) { - (void)ssl; - WOLFSSL_STUB("SSL_get_privatekey"); - return NULL; + /* checkout exdata stuff... */ + WOLFSSL_ENTER("wolfSSL_get_app_data"); + + return wolfSSL_get_ex_data(ssl, 0); } -#endif -#ifndef NO_WOLFSSL_STUB -/*** TBD ***/ -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"); -} -#endif -#ifndef NO_WOLFSSL_STUB -/*** TBD ***/ -WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) -{ - WOLFSSL_STUB("SSL_COMP_get_compression_methods"); - return NULL; +/* Set ex array 0 to have app data + * + * ssl WOLFSSL struct to set app data in + * arg data to be stored + * + * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) { + WOLFSSL_ENTER("wolfSSL_set_app_data"); + + return wolfSSL_set_ex_data(ssl, 0, arg); } -#endif +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ -int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p) +#if defined(HAVE_EX_DATA) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL) + +int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) { - WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_num"); - if (p == NULL) { - return WOLFSSL_FATAL_ERROR; + WOLFSSL_ENTER("wolfSSL_set_ex_data"); +#ifdef HAVE_EX_DATA + if (ssl != NULL) + { + return wolfSSL_CRYPTO_set_ex_data(&ssl->ex_data, idx, data); } - return (int)p->num; +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; } -WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(WOLFSSL_STACK* sk, int i) +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_set_ex_data_with_cleanup( + WOLFSSL* ssl, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) { - WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_value"); - return (WOLFSSL_CIPHER*)wolfSSL_sk_value(sk, i); + WOLFSSL_ENTER("wolfSSL_set_ex_data_with_cleanup"); + if (ssl != NULL) + { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ssl->ex_data, idx, data, + cleanup_routine); + } + return WOLFSSL_FAILURE; } +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ -#if !defined(NETOS) -void ERR_load_SSL_strings(void) +void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) { - -} + WOLFSSL_ENTER("wolfSSL_get_ex_data"); +#ifdef HAVE_EX_DATA + if (ssl != NULL) { + return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx); + } +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; #endif - -#ifdef HAVE_OCSP -long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) -{ - if (s == NULL || resp == NULL) - return 0; - - *resp = s->ocspResp; - return s->ocspRespSz; + return 0; } -long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, - int len) -{ - if (s == NULL) - return WOLFSSL_FAILURE; - - s->ocspResp = resp; - s->ocspRespSz = len; - - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_OCSP */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */ -#ifdef HAVE_MAX_FRAGMENT -#ifndef NO_WOLFSSL_CLIENT -/** - * Set max fragment tls extension - * @param c a pointer to WOLFSSL_CTX object - * @param mode maximum fragment length mode - * @return 1 on success, otherwise 0 or negative error code - */ -int wolfSSL_CTX_set_tlsext_max_fragment_length(WOLFSSL_CTX *c, - unsigned char mode) -{ - if (c == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) - return BAD_FUNC_ARG; +#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) - return wolfSSL_CTX_UseMaxFragment(c, mode); -} -/** - * Set max fragment tls extension - * @param c a pointer to WOLFSSL object - * @param mode maximum fragment length mode - * @return 1 on success, otherwise 0 or negative error code +/* returns the enum value associated with handshake state + * + * ssl the WOLFSSL structure to get state of */ -int wolfSSL_set_tlsext_max_fragment_length(WOLFSSL *s, unsigned char mode) -{ - if (s == NULL || (mode < WOLFSSL_MFL_2_9 || mode > WOLFSSL_MFL_2_12 )) - return BAD_FUNC_ARG; - - return wolfSSL_UseMaxFragment(s, mode); -} -#endif /* NO_WOLFSSL_CLIENT */ -#endif /* HAVE_MAX_FRAGMENT */ - -#endif /* OPENSSL_EXTRA */ - -#ifdef WOLFSSL_HAVE_TLS_UNIQUE -size_t wolfSSL_get_finished(const WOLFSSL *ssl, void *buf, size_t count) +int wolfSSL_get_state(const WOLFSSL* ssl) { - byte len = 0; - - WOLFSSL_ENTER("wolfSSL_get_finished"); + WOLFSSL_ENTER("wolfSSL_get_state"); - if (!ssl || !buf || count < TLS_FINISHED_SZ) { - WOLFSSL_MSG("Bad parameter"); + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); return WOLFSSL_FAILURE; } - if (ssl->options.side == WOLFSSL_SERVER_END) { - len = ssl->serverFinished_len; - XMEMCPY(buf, ssl->serverFinished, len); - } - else { - len = ssl->clientFinished_len; - XMEMCPY(buf, ssl->clientFinished, len); - } - return len; + return ssl->options.handShakeState; } +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ -size_t wolfSSL_get_peer_finished(const WOLFSSL *ssl, void *buf, size_t count) +#ifdef OPENSSL_EXTRA +void wolfSSL_certs_clear(WOLFSSL* ssl) { - byte len = 0; - WOLFSSL_ENTER("wolfSSL_get_peer_finished"); + WOLFSSL_ENTER("wolfSSL_certs_clear"); - if (!ssl || !buf || count < TLS_FINISHED_SZ) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } + if (ssl == NULL) + return; - if (ssl->options.side == WOLFSSL_CLIENT_END) { - len = ssl->serverFinished_len; - XMEMCPY(buf, ssl->serverFinished, len); + /* ctx still owns certificate, certChain, key, dh, and cm */ + if (ssl->buffers.weOwnCert) + FreeDer(&ssl->buffers.certificate); + ssl->buffers.certificate = NULL; + if (ssl->buffers.weOwnCertChain) + FreeDer(&ssl->buffers.certChain); + ssl->buffers.certChain = NULL; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = 0; +#endif + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif } - else { - len = ssl->clientFinished_len; - XMEMCPY(buf, ssl->clientFinished, len); + ssl->buffers.key = NULL; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.keyMask = NULL; +#endif + ssl->buffers.keyType = 0; + ssl->buffers.keyId = 0; + ssl->buffers.keyLabel = 0; + ssl->buffers.keySz = 0; + ssl->buffers.keyDevId = 0; +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->buffers.weOwnAltKey) { + FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif } - - return len; + ssl->buffers.altKey = NULL; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.altKeyMask = NULL; +#endif +#endif /* WOLFSSL_DUAL_ALG_CERTS */ } -#endif /* WOLFSSL_HAVE_TLS_UNIQUE */ +#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(OPENSSL_ALL) -long wolfSSL_get_verify_result(const WOLFSSL *ssl) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ + || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) + +long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } + WOLFSSL_ENTER("wolfSSL_ctrl"); + if (ssl == NULL) + return BAD_FUNC_ARG; - return ssl->peerVerifyRet; + switch (cmd) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || \ + defined(OPENSSL_ALL) + #ifdef HAVE_SNI + case SSL_CTRL_SET_TLSEXT_HOSTNAME: + WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TLSEXT_HOSTNAME."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in NULL Host Name."); + break; + } + return wolfSSL_set_tlsext_host_name(ssl, (const char*) pt); + #endif /* HAVE_SNI */ + #endif /* WOLFSSL_NGINX || WOLFSSL_QT || OPENSSL_ALL */ + default: + WOLFSSL_MSG("Case not implemented."); + } + (void)opt; + (void)pt; + return WOLFSSL_FAILURE; } -#endif - -#ifdef OPENSSL_EXTRA -#ifndef NO_WOLFSSL_STUB -/* shows the number of accepts attempted by CTX in it's lifetime */ -long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) +long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) { - WOLFSSL_STUB("wolfSSL_CTX_sess_accept"); - (void)ctx; - return 0; -} -#endif - -#ifndef NO_WOLFSSL_STUB -/* shows the number of connects attempted CTX in it's lifetime */ -long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_connect"); - (void)ctx; - return 0; -} -#endif - - -#ifndef NO_WOLFSSL_STUB -/* shows the number of accepts completed by CTX in it's lifetime */ -long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good"); - (void)ctx; - return 0; -} +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + long ctrl_opt; #endif + long ret = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_CTX_ctrl"); + if (ctx == NULL) + return WOLFSSL_FAILURE; -#ifndef NO_WOLFSSL_STUB -/* shows the number of connects completed by CTX in it's lifetime */ -long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good"); - (void)ctx; - return 0; -} + switch (cmd) { + case SSL_CTRL_CHAIN: +#ifdef SESSION_CERTS + { + /* + * We don't care about opt here because a copy of the certificate is + * stored anyway so increasing the reference counter is not necessary. + * Just check to make sure that it is set to one of the correct values. + */ + WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt; + WOLFSSL_X509* x509; + int i; + if (opt != 0 && opt != 1) { + ret = WOLFSSL_FAILURE; + break; + } + /* Clear certificate chain */ + FreeDer(&ctx->certChain); + if (sk) { + for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { + x509 = wolfSSL_sk_X509_value(sk, i); + /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */ + if (wolfSSL_X509_up_ref(x509) != 1) { + WOLFSSL_MSG("Error increasing reference count"); + continue; + } + if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error adding certificate to context"); + /* Decrease reference count on failure */ + wolfSSL_X509_free(x509); + } + } + } + /* Free previous chain */ + wolfSSL_sk_X509_pop_free(ctx->x509Chain, NULL); + ctx->x509Chain = sk; + if (sk && opt == 1) { + /* up all refs when opt == 1 */ + for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { + x509 = wolfSSL_sk_X509_value(sk, i); + if (wolfSSL_X509_up_ref(x509) != 1) { + WOLFSSL_MSG("Error increasing reference count"); + continue; + } + } + } + } +#else + WOLFSSL_MSG("Session certificates not compiled in"); + ret = WOLFSSL_FAILURE; #endif + break; +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + case SSL_CTRL_OPTIONS: + WOLFSSL_MSG("Entering Case: SSL_CTRL_OPTIONS."); + ctrl_opt = wolfSSL_CTX_set_options(ctx, opt); -#ifndef NO_WOLFSSL_STUB -/* shows the number of renegotiation accepts attempted by CTX */ -long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate"); - (void)ctx; - return 0; -} -#endif + #ifdef WOLFSSL_QT + /* Set whether to use client or server cipher preference */ + if ((ctrl_opt & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) + == WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) { + WOLFSSL_MSG("Using Server's Cipher Preference."); + ctx->useClientOrder = FALSE; + } else { + WOLFSSL_MSG("Using Client's Cipher Preference."); + ctx->useClientOrder = TRUE; + } + #endif /* WOLFSSL_QT */ + return ctrl_opt; +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + case SSL_CTRL_EXTRA_CHAIN_CERT: + WOLFSSL_MSG("Entering Case: SSL_CTRL_EXTRA_CHAIN_CERT."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in x509 pointer NULL."); + ret = WOLFSSL_FAILURE; + break; + } + return wolfSSL_CTX_add_extra_chain_cert(ctx, (WOLFSSL_X509*)pt); -#ifndef NO_WOLFSSL_STUB -/* shows the number of renegotiation accepts attempted by CTX */ -long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate"); - (void)ctx; - return 0; -} +#ifndef NO_DH + case SSL_CTRL_SET_TMP_DH: + WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_DH."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in DH pointer NULL."); + ret = WOLFSSL_FAILURE; + break; + } + return wolfSSL_CTX_set_tmp_dh(ctx, (WOLFSSL_DH*)pt); #endif - -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_hits"); - (void)ctx; - return 0; -} +#ifdef HAVE_ECC + case SSL_CTRL_SET_TMP_ECDH: + WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_ECDH."); + if (pt == NULL) { + WOLFSSL_MSG("Passed in ECDH pointer NULL."); + ret = WOLFSSL_FAILURE; + break; + } + return wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, (WOLFSSL_EC_KEY*)pt); #endif + case SSL_CTRL_MODE: + wolfSSL_CTX_set_mode(ctx,opt); + break; + case SSL_CTRL_SET_MIN_PROTO_VERSION: + WOLFSSL_MSG("set min proto version"); + return wolfSSL_CTX_set_min_proto_version(ctx, (int)opt); + case SSL_CTRL_SET_MAX_PROTO_VERSION: + WOLFSSL_MSG("set max proto version"); + return wolfSSL_CTX_set_max_proto_version(ctx, (int)opt); + case SSL_CTRL_GET_MIN_PROTO_VERSION: + WOLFSSL_MSG("get min proto version"); + return wolfSSL_CTX_get_min_proto_version(ctx); + case SSL_CTRL_GET_MAX_PROTO_VERSION: + WOLFSSL_MSG("get max proto version"); + return wolfSSL_CTX_get_max_proto_version(ctx); + default: + WOLFSSL_MSG("CTX_ctrl cmd not implemented"); + ret = WOLFSSL_FAILURE; + break; + } - -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits"); (void)ctx; - return 0; + (void)cmd; + (void)opt; + (void)pt; + WOLFSSL_LEAVE("wolfSSL_CTX_ctrl", (int)ret); + return ret; } -#endif - #ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) +long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)) { - WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full"); - (void)ctx; - return 0; -} -#endif - + (void) ctx; + (void) cmd; + (void) fp; + WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl"); + return WOLFSSL_FAILURE; -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) -{ - WOLFSSL_STUB("wolfSSL_CTX_sess_misses"); - (void)ctx; - return 0; } -#endif - +#endif /* NO_WOLFSSL_STUB */ #ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) +long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx) { - WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts"); - (void)ctx; - return 0; + return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0L, NULL); } #endif - -/* Return the total number of sessions */ -long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) +/* Returns the verifyCallback from the ssl structure if successful. +Returns NULL otherwise. */ +VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl) { - word32 total = 0; - - WOLFSSL_ENTER("wolfSSL_CTX_sess_number"); - (void)ctx; - -#if defined(WOLFSSL_SESSION_STATS) && !defined(NO_SESSION_CACHE) - if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error getting session stats"); + WOLFSSL_ENTER("wolfSSL_get_verify_callback"); + if (ssl) { + return ssl->verifyCallback; } -#else - WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats"); -#endif - - return (long)total; + return NULL; } - -#ifndef NO_CERTS -long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +#ifndef NO_BIO +/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure. +Returns pointer to private EVP_PKEY struct upon success, NULL if there +is a failure.*/ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) { - byte* chain = NULL; - int derSz; - const byte* der; - int ret; - DerBuffer *derBuffer = NULL; + unsigned char* mem = NULL; + int memSz = 0; + WOLFSSL_EVP_PKEY* key = NULL; + unsigned char* extraBioMem = NULL; - WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio"); - if (ctx == NULL || x509 == NULL) { - WOLFSSL_MSG("Bad Argument"); - return WOLFSSL_FAILURE; + if (bio == NULL) { + return NULL; } + (void)out; - der = wolfSSL_X509_get_der(x509, &derSz); - if (der == NULL || derSz <= 0) { - WOLFSSL_MSG("Error getting X509 DER"); - return WOLFSSL_FAILURE; + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_get_len() failure"); + return NULL; } - if (ctx->certificate == NULL) { - WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); - - /* Process buffer makes first certificate the leaf. */ - ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, - NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx)); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); - return WOLFSSL_FAILURE; - } + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Malloc failure"); + return NULL; } - else { - long chainSz = 0; - int idx = 0; - /* TODO: Do this elsewhere. */ - ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap); - if (ret != 0) { - WOLFSSL_MSG("Memory Error"); - return WOLFSSL_FAILURE; - } - XMEMCPY(derBuffer->buffer, der, derSz); - ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, - GET_VERIFY_SETTING_CTX(ctx)); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); - return WOLFSSL_FAILURE; - } + if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { + int extraBioMemSz; + int derLength; - /* adding cert to existing chain */ - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - chainSz += ctx->certChain->length; + /* Determines key type and returns the new private EVP_PKEY object */ + if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == + NULL) { + WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; } - chainSz += OPAQUE24_LEN + derSz; - chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER); - if (chain == NULL) { - WOLFSSL_MSG("Memory Error"); - return WOLFSSL_FAILURE; - } + /* Write extra data back into bio object if necessary. */ + derLength = key->pkey_sz; + extraBioMemSz = (memSz - derLength); + if (extraBioMemSz > 0) { + int i; + int j = 0; + + extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (extraBioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + for (i = derLength; i < memSz; i++) { + *(extraBioMem + j) = *(mem + i); + j++; + } - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); - idx = ctx->certChain->length; + wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz); + if (wolfSSL_BIO_get_len(bio) <= 0) { + WOLFSSL_MSG("Failed to write memory to bio"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); } - c32to24(derSz, chain + idx); - idx += OPAQUE24_LEN; - XMEMCPY(chain + idx, der, derSz); - idx += derSz; -#ifdef WOLFSSL_TLS13 - ctx->certChainCnt++; -#endif - FreeDer(&ctx->certChain); - ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap); - if (ret == 0) { - XMEMCPY(ctx->certChain->buffer, chain, idx); + if (out != NULL) { + *out = key; } } + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return key; +} +#endif /* !NO_BIO */ - /* on success WOLFSSL_X509 memory is responsibility of ctx */ - wolfSSL_X509_free(x509); - if (chain != NULL) - XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER); +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */ - return WOLFSSL_SUCCESS; -} +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL) -long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure. + * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL + * on fail */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out, + unsigned char** in, long inSz) { - if (ctx == NULL || ctx->cm == NULL) { - return WOLFSSL_FAILURE; - } - - ctx->cm->ocspIOCtx = arg; - return WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP"); + return d2iGenericKey(out, (const unsigned char**)in, inSz, 1); } -#endif /* !NO_CERTS */ +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT || + * WOLFSSL_WPAS_SMALL*/ -int wolfSSL_get_read_ahead(const WOLFSSL* ssl) -{ - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } - return ssl->readAhead; +/* stunnel compatibility functions*/ +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ + (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH))) +void wolfSSL_ERR_remove_thread_state(void* pid) +{ + (void) pid; + return; } - -int wolfSSL_set_read_ahead(WOLFSSL* ssl, int v) +#ifndef NO_FILESYSTEM +/***TBD ***/ +void wolfSSL_print_all_errors_fp(XFILE fp) { - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } + (void)fp; +} +#endif /* !NO_FILESYSTEM */ - ssl->readAhead = (byte)v; +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || + HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH */ - return WOLFSSL_SUCCESS; -} +/* Note: This is a huge section of API's - through + * wolfSSL_X509_OBJECT_get0_X509_CRL */ +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ + (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY) && \ + !defined(WOLFSSL_STATIC_MEMORY) +static wolfSSL_OSSL_Malloc_cb ossl_malloc = NULL; +static wolfSSL_OSSL_Free_cb ossl_free = NULL; +static wolfSSL_OSSL_Realloc_cb ossl_realloc = NULL; -int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +static void* OSSL_Malloc(size_t size) { - if (ctx == NULL) { - return WOLFSSL_FAILURE; - } + if (ossl_malloc != NULL) + return ossl_malloc(size, NULL, 0); + else + return NULL; +} - return ctx->readAhead; +static void OSSL_Free(void *ptr) +{ + if (ossl_free != NULL) + ossl_free(ptr, NULL, 0); } +static void* OSSL_Realloc(void *ptr, size_t size) +{ + if (ossl_realloc != NULL) + return ossl_realloc(ptr, size, NULL, 0); + else + return NULL; +} +#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY && + * !WOLFSSL_STATIC_MEMORY */ -int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) +int wolfSSL_CRYPTO_set_mem_functions( + wolfSSL_OSSL_Malloc_cb m, + wolfSSL_OSSL_Realloc_cb r, + wolfSSL_OSSL_Free_cb f) { - if (ctx == NULL) { - return WOLFSSL_FAILURE; +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) +#ifdef WOLFSSL_DEBUG_MEMORY + WOLFSSL_MSG("mem functions will receive function name instead of " + "file name"); + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)m, (wolfSSL_Free_cb)f, + (wolfSSL_Realloc_cb)r) == 0) + return WOLFSSL_SUCCESS; +#else + WOLFSSL_MSG("wolfSSL was compiled without WOLFSSL_DEBUG_MEMORY mem " + "functions will receive a NULL file name and 0 for the " + "line number."); + if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)OSSL_Malloc, + (wolfSSL_Free_cb)OSSL_Free, (wolfSSL_Realloc_cb)OSSL_Realloc) == 0) { + ossl_malloc = m; + ossl_free = f; + ossl_realloc = r; + return WOLFSSL_SUCCESS; } +#endif + else + return WOLFSSL_FAILURE; +#else + (void)m; + (void)r; + (void)f; + WOLFSSL_MSG("wolfSSL allocator callback functions not compiled in"); + return WOLFSSL_FAILURE; +#endif +} - ctx->readAhead = (byte)v; - +int wolfSSL_ERR_load_ERR_strings(void) +{ return WOLFSSL_SUCCESS; } +void wolfSSL_ERR_load_crypto_strings(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + /* Do nothing */ + return; +} -long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, - void* arg) +int wolfSSL_FIPS_mode(void) { - if (ctx == NULL) { +#ifdef HAVE_FIPS + return 1; +#else + return 0; +#endif +} + +int wolfSSL_FIPS_mode_set(int r) +{ +#ifdef HAVE_FIPS + if (r == 0) { + WOLFSSL_MSG("Cannot disable FIPS at runtime."); return WOLFSSL_FAILURE; } - - ctx->userPRFArg = arg; return WOLFSSL_SUCCESS; +#else + if (r == 0) { + return WOLFSSL_SUCCESS; + } + WOLFSSL_MSG("Cannot enable FIPS. This isn't the wolfSSL FIPS code."); + return WOLFSSL_FAILURE; +#endif } -#endif /* OPENSSL_EXTRA */ - -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -int wolfSSL_sk_num(const WOLFSSL_STACK* sk) +int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) { - WOLFSSL_ENTER("wolfSSL_sk_num"); - if (sk == NULL) - return 0; - return (int)sk->num; + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); + + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + (void)alg_bits; + if (c!= NULL) + ret = c->bits; + #else + if (c != NULL && c->ssl != NULL) { + ret = 8 * c->ssl->specs.key_size; + if (alg_bits != NULL) { + *alg_bits = ret; + } + } + #endif + return ret; } -void* wolfSSL_sk_value(const WOLFSSL_STACK* sk, int i) +/* returns value less than 0 on fail to match + * On a successful match the priority level found is returned + */ +int wolfSSL_sk_SSL_CIPHER_find( + WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind) { - WOLFSSL_ENTER("wolfSSL_sk_value"); + WOLFSSL_STACK* next; + int i, sz; - for (; sk != NULL && i > 0; i--) - sk = sk->next; - if (sk == NULL) - return NULL; + if (sk == NULL || toFind == NULL) { + return WOLFSSL_FATAL_ERROR; + } - switch (sk->type) { - case STACK_TYPE_X509: - return (void*)sk->data.x509; - case STACK_TYPE_GEN_NAME: - return (void*)sk->data.gn; - case STACK_TYPE_BIO: - return (void*)sk->data.bio; - case STACK_TYPE_OBJ: - return (void*)sk->data.obj; - case STACK_TYPE_STRING: - return (void*)sk->data.string; - case STACK_TYPE_CIPHER: - return (void*)&sk->data.cipher; - case STACK_TYPE_ACCESS_DESCRIPTION: - return (void*)sk->data.access; - case STACK_TYPE_X509_EXT: - return (void*)sk->data.ext; - case STACK_TYPE_X509_REQ_ATTR: - return (void*)sk->data.generic; - case STACK_TYPE_NULL: - return (void*)sk->data.generic; - case STACK_TYPE_X509_NAME: - return (void*)sk->data.name; - case STACK_TYPE_X509_NAME_ENTRY: - return (void*)sk->data.name_entry; - case STACK_TYPE_CONF_VALUE: - #ifdef OPENSSL_EXTRA - return (void*)sk->data.conf; - #else - return NULL; - #endif - case STACK_TYPE_X509_INFO: - return (void*)sk->data.info; - case STACK_TYPE_BY_DIR_entry: - return (void*)sk->data.dir_entry; - case STACK_TYPE_BY_DIR_hash: - return (void*)sk->data.dir_hash; - case STACK_TYPE_X509_OBJ: - return (void*)sk->data.x509_obj; - case STACK_TYPE_DIST_POINT: - return (void*)sk->data.dp; - case STACK_TYPE_X509_CRL: - return (void*)sk->data.crl; - default: - return (void*)sk->data.generic; + sz = wolfSSL_sk_SSL_CIPHER_num(sk); + next = sk; + for (i = 0; i < sz && next != NULL; i++) { + if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 && + next->data.cipher.cipherSuite == toFind->cipherSuite) { + return sz - i; /* reverse because stack pushed highest on first */ + } + next = next->next; } + return WOLFSSL_FATAL_ERROR; } -/* copies over data of "in" to "out" */ -static void wolfSSL_CIPHER_copy(WOLFSSL_CIPHER* in, WOLFSSL_CIPHER* out) +/* free's all nodes in the stack and there data */ +void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) { - if (in == NULL || out == NULL) - return; - - *out = *in; + WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free"); + wolfSSL_sk_free(sk); } -WOLFSSL_STACK* wolfSSL_sk_dup(WOLFSSL_STACK* sk) +#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, (word16)XSTRLEN(host_name)); + WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); + return ret; +} - WOLFSSL_STACK* ret = NULL; - WOLFSSL_STACK* last = NULL; +/* May be called by server to get the requested accepted name and by the client + * to get the requested name. */ +const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) +{ + void * serverName = NULL; + if (ssl == NULL) + return NULL; + TLSX_SNI_GetRequest(ssl->extensions, type, &serverName, + !wolfSSL_is_server(ssl)); + return (const char *)serverName; +} +#endif /* HAVE_SNI */ - WOLFSSL_ENTER("wolfSSL_sk_dup"); +WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +{ + int ret; + /* This method requires some explanation. Its sibling is + * int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) + * which re-inits the WOLFSSL* with all settings in the new CTX. + * That one is the right one to use *before* a handshake is started. + * + * This method was added by OpenSSL to be used *during* the handshake, e.g. + * when a server inspects the SNI in a ClientHello callback and + * decides which set of certificates to use. + * + * Since, at the time the SNI callback is run, some decisions on + * Extensions or the ServerHello might already have been taken, this + * method is very restricted in what it does: + * - changing the server certificate(s) + * - changing the server id for session handling + * and everything else in WOLFSSL* needs to remain untouched. + */ + WOLFSSL_ENTER("wolfSSL_set_SSL_CTX"); + if (ssl == NULL || ctx == NULL) + return NULL; + if (ssl->ctx == ctx) + return ssl->ctx; - while (sk) { - WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); + if (ctx->suites == NULL) { + /* suites */ + if (AllocateCtxSuites(ctx) != 0) + return NULL; + InitSSL_CTX_Suites(ctx); + } - if (!cur) { - WOLFSSL_MSG("wolfSSL_sk_new_node error"); - goto error; - } + wolfSSL_RefInc(&ctx->ref, &ret); +#ifdef WOLFSSL_REFCNT_ERROR_RETURN + if (ret != 0) { + /* can only fail on serious stuff, like mutex not working + * or ctx refcount out of whack. */ + return NULL; + } +#else + (void)ret; +#endif + if (ssl->ctx != NULL) + wolfSSL_CTX_free(ssl->ctx); + ssl->ctx = ctx; - if (!ret) { - /* Set first node */ - ret = cur; +#ifndef NO_CERTS + /* ctx owns certificate, certChain and key */ + ssl->buffers.certificate = ctx->certificate; + ssl->buffers.certChain = ctx->certChain; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = ctx->certChainCnt; +#endif +#ifndef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.key = ctx->privateKey; +#else + if (ctx->privateKey != NULL) { + AllocCopyDer(&ssl->buffers.key, ctx->privateKey->buffer, + ctx->privateKey->length, ctx->privateKey->type, + ctx->privateKey->heap); + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.key, ctx->privateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + if (ret != 0) { + return ret; } - - if (last) { - last->next = cur; + } +#endif + ssl->buffers.keyType = ctx->privateKeyType; + ssl->buffers.keyId = ctx->privateKeyId; + ssl->buffers.keyLabel = ctx->privateKeyLabel; + ssl->buffers.keySz = ctx->privateKeySz; + ssl->buffers.keyDevId = ctx->privateKeyDevId; + /* flags indicating what certs/keys are available */ + ssl->options.haveRSA = ctx->haveRSA; + ssl->options.haveDH = ctx->haveDH; + ssl->options.haveECDSAsig = ctx->haveECDSAsig; + ssl->options.haveECC = ctx->haveECC; + ssl->options.haveStaticECC = ctx->haveStaticECC; + ssl->options.haveFalconSig = ctx->haveFalconSig; + ssl->options.haveDilithiumSig = ctx->haveDilithiumSig; +#ifdef WOLFSSL_DUAL_ALG_CERTS +#ifndef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.altKey = ctx->altPrivateKey; +#else + if (ctx->altPrivateKey != NULL) { + AllocCopyDer(&ssl->buffers.altkey, ctx->altPrivateKey->buffer, + ctx->altPrivateKey->length, ctx->altPrivateKey->type, + ctx->altPrivateKey->heap); + /* Blind the private key for the SSL with new random mask. */ + wolfssl_priv_der_unblind(ssl->buffers.altKey, ctx->altPrivateKeyMask); + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + if (ret != 0) { + return ret; } + } +#endif + ssl->buffers.altKeySz = ctx->altPrivateKeySz; + ssl->buffers.altKeyType = ctx->altPrivateKeyType; +#endif /* WOLFSSL_DUAL_ALG_CERTS */ +#endif - XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); - - /* We will allocate new memory for this */ - XMEMSET(&cur->data, 0, sizeof(cur->data)); - cur->next = NULL; +#ifdef WOLFSSL_SESSION_ID_CTX + /* copy over application session context ID */ + ssl->sessionCtxSz = ctx->sessionCtxSz; + XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz); +#endif - switch (sk->type) { - case STACK_TYPE_X509: - if (!sk->data.x509) - break; - cur->data.x509 = wolfSSL_X509_dup(sk->data.x509); - if (!cur->data.x509) { - WOLFSSL_MSG("wolfSSL_X509_dup error"); - goto error; - } - break; - case STACK_TYPE_CIPHER: - wolfSSL_CIPHER_copy(&sk->data.cipher, &cur->data.cipher); - break; - case STACK_TYPE_GEN_NAME: - if (!sk->data.gn) - break; - cur->data.gn = wolfSSL_GENERAL_NAME_dup(sk->data.gn); - if (!cur->data.gn) { - WOLFSSL_MSG("wolfSSL_GENERAL_NAME_new error"); - goto error; - } - break; - case STACK_TYPE_OBJ: - if (!sk->data.obj) - break; - cur->data.obj = wolfSSL_ASN1_OBJECT_dup(sk->data.obj); - if (!cur->data.obj) { - WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup error"); - goto error; - } - break; - case STACK_TYPE_BIO: - case STACK_TYPE_STRING: - case STACK_TYPE_ACCESS_DESCRIPTION: - case STACK_TYPE_X509_EXT: - case STACK_TYPE_X509_REQ_ATTR: - case STACK_TYPE_NULL: - case STACK_TYPE_X509_NAME: - case STACK_TYPE_X509_NAME_ENTRY: - case STACK_TYPE_CONF_VALUE: - case STACK_TYPE_X509_INFO: - case STACK_TYPE_BY_DIR_entry: - case STACK_TYPE_BY_DIR_hash: - case STACK_TYPE_X509_OBJ: - case STACK_TYPE_DIST_POINT: - case STACK_TYPE_X509_CRL: - default: - WOLFSSL_MSG("Unsupported stack type"); - goto error; - } + return ssl->ctx; +} - sk = sk->next; - last = cur; - } - return ret; -error: - if (ret) { - wolfSSL_sk_GENERAL_NAME_free(ret); - } +VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); + if(ctx) + return ctx->verifyCallback; return NULL; } - -WOLFSSL_STACK* wolfSSL_shallow_sk_dup(WOLFSSL_STACK* sk) +#ifdef HAVE_SNI +/* this is a compatibily function, consider using + * wolfSSL_CTX_set_servername_callback */ +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 WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} - WOLFSSL_STACK* ret = NULL; - WOLFSSL_STACK** prev = &ret; - - WOLFSSL_ENTER("wolfSSL_shallow_sk_dup"); +#endif /* HAVE_SNI */ - for (; sk != NULL; sk = sk->next) { - WOLFSSL_STACK* cur = wolfSSL_sk_new_node(sk->heap); - - if (!cur) { - WOLFSSL_MSG("wolfSSL_sk_new_node error"); - goto error; - } - - XMEMCPY(cur, sk, sizeof(WOLFSSL_STACK)); - cur->next = NULL; - - *prev = cur; - prev = &cur->next; - } - return ret; - -error: - if (ret) { - wolfSSL_sk_free(ret); - } - return NULL; +#ifndef NO_BIO +void wolfSSL_ERR_load_BIO_strings(void) { + WOLFSSL_ENTER("wolfSSL_ERR_load_BIO_strings"); + /* do nothing */ } +#endif -/* Free the just the stack structure */ -void wolfSSL_sk_free(WOLFSSL_STACK* sk) +#ifndef NO_WOLFSSL_STUB +/* Set THREADID callback, return 1 on success, 0 on error */ +int wolfSSL_THREADID_set_callback( + void(*threadid_func)(WOLFSSL_CRYPTO_THREADID*)) { - WOLFSSL_ENTER("wolfSSL_sk_free"); - - while (sk != NULL) { - WOLFSSL_STACK* next = sk->next; - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = next; - } + WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); + WOLFSSL_STUB("CRYPTO_THREADID_set_callback"); + (void)threadid_func; + return 1; } +#endif -/* Frees each node in the stack and frees the stack. - */ -void wolfSSL_sk_GENERIC_pop_free(WOLFSSL_STACK* sk, - void (*f) (void*)) +#ifndef NO_WOLFSSL_STUB +void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) { - WOLFSSL_ENTER("wolfSSL_sk_GENERIC_pop_free"); - wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); + WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); + WOLFSSL_STUB("CRYPTO_THREADID_set_numeric"); + (void)id; + (void)val; + return; } +#endif -/* return 1 on success 0 on fail */ -int wolfSSL_sk_GENERIC_push(WOLFSSL_STACK* sk, void* generic) -{ - WOLFSSL_ENTER("wolfSSL_sk_GENERIC_push"); +#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || + * HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH || + * HAVE_SBLIM_SFCB)) */ - return wolfSSL_sk_push(sk, generic); -} -void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk) -{ - wolfSSL_sk_free(sk); -} +#ifdef HAVE_SNI -/* Pop off data from the stack. Checks that the type matches the stack type. - * - * @param [in, out] sk Stack of objects. - * @param [in] type Type of stack. - * @return Object on success. - * @return NULL when stack is NULL or no nodes left in stack. - */ -void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type) +void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) { - WOLFSSL_STACK* node; - void* data = NULL; - - /* Check we have a stack passed in of the right type. */ - if ((sk != NULL) && (sk->type == type)) { - /* Get the next node to become the new first node. */ - node = sk->next; - /* Get the ASN.1 OBJECT_ID object in the first node. */ - data = sk->data.generic; - - /* Check whether there is a next node. */ - if (node != NULL) { - /* Move content out of next node into current node. */ - sk->data.obj = node->data.obj; - sk->next = node->next; - /* Dispose of node. */ - XFREE(node, NULL, DYNAMIC_TYPE_ASN1); - } - else { - /* No more nodes - clear out data. */ - sk->data.obj = NULL; - } - - /* Decrement count as long as we thought we had nodes. */ - if (sk->num > 0) { - sk->num -= 1; - } - } - - return data; + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); + if (ctx) + ctx->sniRecvCb = cb; } -/* Free all nodes in a stack including the pushed objects */ -void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, - wolfSSL_sk_freefunc func) -{ - WOLFSSL_ENTER("wolfSSL_sk_pop_free"); - - if (sk == NULL) { - /* pop_free can be called with NULL, do not print bad argument */ - return; - } - #if defined(WOLFSSL_QT) - /* In Qt v15.5, it calls OPENSSL_sk_free(xxx, OPENSSL_sk_free). - * By using OPENSSL_sk_free for free causes access violation. - * Therefore, switching free func to wolfSSL_ACCESS_DESCRIPTION_free - * is needed even the func isn't NULL. - */ - if (sk->type == STACK_TYPE_ACCESS_DESCRIPTION) { - func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free; - } - #endif - if (func == NULL) { - switch(sk->type) { - case STACK_TYPE_ACCESS_DESCRIPTION: - #if defined(OPENSSL_ALL) - func = (wolfSSL_sk_freefunc)wolfSSL_ACCESS_DESCRIPTION_free; - #endif - break; - case STACK_TYPE_X509: - func = (wolfSSL_sk_freefunc)wolfSSL_X509_free; - break; - case STACK_TYPE_X509_OBJ: - #ifdef OPENSSL_ALL - func = (wolfSSL_sk_freefunc)wolfSSL_X509_OBJECT_free; - #endif - break; - case STACK_TYPE_OBJ: - func = (wolfSSL_sk_freefunc)wolfSSL_ASN1_OBJECT_free; - break; - case STACK_TYPE_DIST_POINT: - #ifdef OPENSSL_EXTRA - func = (wolfSSL_sk_freefunc)wolfSSL_DIST_POINT_free; - #endif - break; - case STACK_TYPE_GEN_NAME: - func = (wolfSSL_sk_freefunc)wolfSSL_GENERAL_NAME_free; - break; - case STACK_TYPE_STRING: - #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ - defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) - func = (wolfSSL_sk_freefunc)wolfSSL_WOLFSSL_STRING_free; - #endif - break; - case STACK_TYPE_X509_NAME: - #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \ - && !defined(WOLFCRYPT_ONLY) - func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_free; - #endif - break; - case STACK_TYPE_X509_NAME_ENTRY: - #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \ - && !defined(WOLFCRYPT_ONLY) - func = (wolfSSL_sk_freefunc)wolfSSL_X509_NAME_ENTRY_free; - #endif - break; - case STACK_TYPE_X509_EXT: - #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) - func = (wolfSSL_sk_freefunc)wolfSSL_X509_EXTENSION_free; - #endif - break; - case STACK_TYPE_X509_REQ_ATTR: - #if defined(OPENSSL_ALL) && \ - (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ)) - func = (wolfSSL_sk_freefunc)wolfSSL_X509_ATTRIBUTE_free; - #endif - break; - case STACK_TYPE_CONF_VALUE: - #if defined(OPENSSL_ALL) - func = (wolfSSL_sk_freefunc)wolfSSL_X509V3_conf_free; - #endif - break; - case STACK_TYPE_X509_INFO: - #if defined(OPENSSL_ALL) - func = (wolfSSL_sk_freefunc)wolfSSL_X509_INFO_free; - #endif - break; - case STACK_TYPE_BIO: -#if !defined(NO_BIO) && defined(OPENSSL_EXTRA) - func = (wolfSSL_sk_freefunc)wolfSSL_BIO_vfree; -#endif - break; - case STACK_TYPE_BY_DIR_entry: -#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) - func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_entry_free; -#endif - break; - case STACK_TYPE_BY_DIR_hash: -#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) - func = (wolfSSL_sk_freefunc)wolfSSL_BY_DIR_HASH_free; -#endif - break; - case STACK_TYPE_X509_CRL: -#if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) - func = (wolfSSL_sk_freefunc)wolfSSL_X509_CRL_free; -#endif - break; - case STACK_TYPE_CIPHER: - case STACK_TYPE_NULL: - default: - break; - } - } - - while (sk != NULL) { - WOLFSSL_STACK* next = sk->next; - if (func != NULL) { - if (sk->type != STACK_TYPE_CIPHER) - func(sk->data.generic); - } - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = next; +int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); + if (ctx) { + ctx->sniRecvCbArg = arg; + return WOLFSSL_SUCCESS; } + return WOLFSSL_FAILURE; } -/* Creates a new stack of the requested type. - * - * @param [in] type Type of stack. - * @return Empty stack on success. - * @return NULL when dynamic memory allocation fails. - */ -WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type) -{ - WOLFSSL_STACK* sk; +#endif /* HAVE_SNI */ - /* Allocate a new stack - first node. */ - sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, - DYNAMIC_TYPE_OPENSSL); - if (sk == NULL) { - WOLFSSL_MSG("WOLFSSL_STACK memory error"); - } - else { - /* Clear node and set type. */ - XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); - sk->type = type; - } - - return sk; -} - -/* Creates and returns a new null stack. */ -WOLFSSL_STACK* wolfSSL_sk_new_null(void) -{ - WOLFSSL_ENTER("wolfSSL_sk_new_null"); - - return wolfssl_sk_new_type(STACK_TYPE_NULL); -} - -int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk) -{ - if (sk == NULL) - return 0; - return (int)sk->num; -} - -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -#if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \ - defined(HAVE_EXT_CACHE)) -/* stunnel 4.28 needs - * - * Callback that is called if a session tries to resume but could not find - * the session to resume it. - */ -void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, - WOLFSSL_SESSION*(*f)(WOLFSSL*, const unsigned char*, int, int*)) -{ - if (ctx == NULL) - return; - -#ifdef HAVE_EXT_CACHE - ctx->get_sess_cb = f; -#else - (void)f; -#endif -} - -void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, - int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) -{ - if (ctx == NULL) - return; - -#ifdef HAVE_EXT_CACHE - ctx->new_sess_cb = f; -#else - (void)f; -#endif -} - -void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, - WOLFSSL_SESSION*)) -{ - if (ctx == NULL) - return; - -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - ctx->rem_sess_cb = f; -#else - (void)f; -#endif -} - - -/* - * - * Note: It is expected that the importing and exporting function have been - * built with the same settings. For example if session tickets was - * enabled with the wolfSSL library exporting a session then it is - * expected to be turned on with the wolfSSL library importing the session. - */ -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 - - WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); - - sess = ClientSessionToSession(sess); - if (sess == NULL) { - return BAD_FUNC_ARG; - } - - /* side | bornOn | timeout | sessionID len | sessionID | masterSecret | - * haveEMS */ - size += OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + - sess->sessionIDSz + SECRET_LEN + OPAQUE8_LEN; - /* altSessionID */ - size += OPAQUE8_LEN + (sess->haveAltSessionID ? ID_LEN : 0); -#ifdef SESSION_CERTS - /* Peer chain */ - size += OPAQUE8_LEN; - for (i = 0; i < sess->chain.count; i++) - size += OPAQUE16_LEN + sess->chain.certs[i].length; -#endif -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - /* Protocol version */ - size += OPAQUE16_LEN; -#endif -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - /* cipher suite */ - size += OPAQUE16_LEN; -#endif -#ifndef NO_CLIENT_CACHE - /* ServerID len | ServerID */ - size += OPAQUE16_LEN + sess->idLen; -#endif -#ifdef WOLFSSL_SESSION_ID_CTX - /* session context ID len | session context ID */ - size += OPAQUE8_LEN + sess->sessionCtxSz; -#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - /* peerVerifyRet */ - size += OPAQUE8_LEN; -#endif -#ifdef WOLFSSL_TLS13 - /* namedGroup */ - size += OPAQUE16_LEN; -#endif -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) -#ifdef WOLFSSL_TLS13 -#ifdef WOLFSSL_32BIT_MILLI_TIME - /* ticketSeen | ticketAdd */ - size += OPAQUE32_LEN + OPAQUE32_LEN; -#else - /* ticketSeen Hi 32 bits | ticketSeen Lo 32 bits | ticketAdd */ - size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE32_LEN; -#endif - /* ticketNonce */ - size += OPAQUE8_LEN + sess->ticketNonce.len; -#endif -#ifdef WOLFSSL_EARLY_DATA - size += OPAQUE32_LEN; -#endif -#endif -#ifdef HAVE_SESSION_TICKET - /* ticket len | ticket */ - size += OPAQUE16_LEN + sess->ticketLen; -#endif - - if (p != NULL) { - unsigned char *data; - - if (*p == NULL) - *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); - if (*p == NULL) - return 0; - data = *p; - - data[idx++] = sess->side; - 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++] = (byte)sess->haveEMS; - data[idx++] = sess->haveAltSessionID ? ID_LEN : 0; - if (sess->haveAltSessionID) { - XMEMCPY(data + idx, sess->altSessionID, ID_LEN); - idx += ID_LEN; - } -#ifdef SESSION_CERTS - data[idx++] = (byte)sess->chain.count; - for (i = 0; i < sess->chain.count; i++) { - c16toa((word16)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; - } -#endif -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - data[idx++] = sess->version.major; - data[idx++] = sess->version.minor; -#endif -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - 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 WOLFSSL_SESSION_ID_CTX - data[idx++] = sess->sessionCtxSz; - XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz); - idx += sess->sessionCtxSz; -#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - data[idx++] = sess->peerVerifyRet; -#endif -#ifdef WOLFSSL_TLS13 - c16toa(sess->namedGroup, data + idx); - idx += OPAQUE16_LEN; -#endif -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) -#ifdef WOLFSSL_TLS13 -#ifdef WOLFSSL_32BIT_MILLI_TIME - c32toa(sess->ticketSeen, data + idx); - idx += OPAQUE32_LEN; -#else - c32toa((word32)(sess->ticketSeen >> 32), data + idx); - idx += OPAQUE32_LEN; - c32toa((word32)sess->ticketSeen, data + idx); - idx += OPAQUE32_LEN; -#endif - c32toa(sess->ticketAdd, data + idx); - idx += OPAQUE32_LEN; - data[idx++] = sess->ticketNonce.len; - XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len); - idx += sess->ticketNonce.len; -#endif -#ifdef WOLFSSL_EARLY_DATA - c32toa(sess->maxEarlyDataSz, data + idx); - idx += OPAQUE32_LEN; -#endif -#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 - - (void)sess; - (void)p; -#ifdef HAVE_EXT_CACHE - (void)idx; -#endif - - return size; -} - - -/* TODO: no function to free new session. - * - * Note: It is expected that the importing and exporting function have been - * built with the same settings. For example if session tickets was - * enabled with the wolfSSL library exporting a session then it is - * expected to be turned on with the wolfSSL library importing the session. - */ -WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, - const unsigned char** p, long i) -{ - WOLFSSL_SESSION* s = NULL; - int ret = 0; -#if defined(HAVE_EXT_CACHE) - int idx = 0; - byte* data; -#ifdef SESSION_CERTS - int j; - word16 length; -#endif -#endif /* HAVE_EXT_CACHE */ - - (void)p; - (void)i; - (void)ret; - (void)sess; - -#ifdef HAVE_EXT_CACHE - if (p == NULL || *p == NULL) - return NULL; - - s = wolfSSL_SESSION_new(); - if (s == NULL) - return NULL; - - idx = 0; - data = (byte*)*p; - - /* side | bornOn | timeout | sessionID len */ - if (i < OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { - ret = BUFFER_ERROR; - goto end; - } - s->side = data[idx++]; - ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; - ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; - s->sessionIDSz = data[idx++]; - - /* sessionID | secret | haveEMS | haveAltSessionID */ - if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_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++]; - if (data[idx] != ID_LEN && data[idx] != 0) { - ret = BUFFER_ERROR; - goto end; - } - s->haveAltSessionID = data[idx++] == ID_LEN; - - /* altSessionID */ - if (s->haveAltSessionID) { - if (i - idx < ID_LEN) { - ret = BUFFER_ERROR; - goto end; - } - XMEMCPY(s->altSessionID, data + idx, ID_LEN); idx += ID_LEN; - } - -#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; - } -#endif -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - /* Protocol Version */ - if (i - idx < OPAQUE16_LEN) { - ret = BUFFER_ERROR; - goto end; - } - s->version.major = data[idx++]; - s->version.minor = data[idx++]; -#endif -#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) - /* Cipher suite */ - if (i - idx < OPAQUE16_LEN) { - ret = BUFFER_ERROR; - goto end; - } - 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; - - /* ServerID */ - if (i - idx < s->idLen) { - ret = BUFFER_ERROR; - goto end; - } - XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; -#endif -#ifdef WOLFSSL_SESSION_ID_CTX - /* byte for length of session context ID */ - if (i - idx < OPAQUE8_LEN) { - ret = BUFFER_ERROR; - goto end; - } - s->sessionCtxSz = data[idx++]; - - /* app session context ID */ - if (i - idx < s->sessionCtxSz) { - ret = BUFFER_ERROR; - goto end; - } - XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz; -#endif -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - /* byte for peerVerifyRet */ - if (i - idx < OPAQUE8_LEN) { - ret = BUFFER_ERROR; - goto end; - } - s->peerVerifyRet = data[idx++]; -#endif -#ifdef WOLFSSL_TLS13 - if (i - idx < OPAQUE16_LEN) { - ret = BUFFER_ERROR; - goto end; - } - ato16(data + idx, &s->namedGroup); - idx += OPAQUE16_LEN; -#endif -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) -#ifdef WOLFSSL_TLS13 - if (i - idx < (OPAQUE32_LEN * 2)) { - ret = BUFFER_ERROR; - goto end; - } -#ifdef WOLFSSL_32BIT_MILLI_TIME - ato32(data + idx, &s->ticketSeen); - idx += OPAQUE32_LEN; -#else - { - word32 seenHi, seenLo; - - ato32(data + idx, &seenHi); - idx += OPAQUE32_LEN; - ato32(data + idx, &seenLo); - idx += OPAQUE32_LEN; - s->ticketSeen = ((sword64)seenHi << 32) + seenLo; - } -#endif - ato32(data + idx, &s->ticketAdd); - idx += OPAQUE32_LEN; - if (i - idx < OPAQUE8_LEN) { - ret = BUFFER_ERROR; - goto end; - } - s->ticketNonce.len = data[idx++]; - - if (i - idx < s->ticketNonce.len) { - ret = BUFFER_ERROR; - goto end; - } -#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ - (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) - ret = SessionTicketNoncePopulate(s, data + idx, s->ticketNonce.len); - if (ret != 0) - goto end; -#else - if (s->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ) { - ret = BUFFER_ERROR; - goto end; - } - XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len); -#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */ - - idx += s->ticketNonce.len; -#endif -#ifdef WOLFSSL_EARLY_DATA - if (i - idx < OPAQUE32_LEN) { - ret = BUFFER_ERROR; - goto end; - } - ato32(data + idx, &s->maxEarlyDataSz); - idx += OPAQUE32_LEN; -#endif -#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->ticketLenAlloc > 0) { - 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->ticketLenAlloc = (word16)s->ticketLen; - } - - /* ticket */ - if (i - idx < s->ticketLen) { - ret = BUFFER_ERROR; - goto end; - } - XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; -#endif - (void)idx; - - if (sess != NULL) { - *sess = s; - } - - s->isSetup = 1; - - *p += idx; - -end: - if (ret != 0 && (sess == NULL || *sess != s)) { - wolfSSL_FreeSession(NULL, s); - s = NULL; - } -#endif /* HAVE_EXT_CACHE */ - return s; -} - -/* Check if there is a session ticket associated with this WOLFSSL_SESSION. - * - * sess - pointer to WOLFSSL_SESSION struct - * - * Returns 1 if has session ticket, otherwise 0 */ -int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket"); -#ifdef HAVE_SESSION_TICKET - sess = ClientSessionToSession(sess); - if (sess) { - if ((sess->ticketLen > 0) && (sess->ticket != NULL)) { - return WOLFSSL_SUCCESS; - } - } -#else - (void)sess; -#endif - return WOLFSSL_FAILURE; -} - -unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( - const WOLFSSL_SESSION* sess) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); - sess = ClientSessionToSession(sess); - if (sess) { - return sess->timeout; - } - return 0; -} - -long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) -{ - long timeout = 0; - WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); - sess = ClientSessionToSession(sess); - if (sess) - timeout = sess->timeout; - return timeout; -} - -long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) -{ - word32 tmptime; - - ses = ClientSessionToSession(ses); - if (ses == NULL || t < 0) { - return BAD_FUNC_ARG; - } - - tmptime = t & 0xFFFFFFFF; - ses->timeout = tmptime; - - return WOLFSSL_SUCCESS; -} - -long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) -{ - long bornOn = 0; - WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); - sess = ClientSessionToSession(sess); - if (sess) - bornOn = sess->bornOn; - return bornOn; -} - -long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t) -{ - - ses = ClientSessionToSession(ses); - if (ses == NULL || t < 0) { - return 0; - } - ses->bornOn = (word32)t; - return t; -} - -#endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ - -#ifdef OPENSSL_EXTRA - -#if defined(HAVE_EX_DATA) && !defined(NO_FILESYSTEM) -int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) -{ - int ret = WOLFSSL_FATAL_ERROR; - - WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); - if (ssl != NULL && fname != NULL) - { - #ifdef WOLFSSL_SMALL_STACK - byte staticBuffer[1]; /* force heap usage */ - #else - byte staticBuffer[FILE_BUFFER_SIZE]; - #endif - byte* myBuffer = staticBuffer; - int dynamic = 0; - XFILE file; - long sz = 0; - WOLFSSL_CTX* ctx = ssl->ctx; - WOLFSSL_X509* peer_cert = &ssl->peerCert; - DerBuffer* fileDer = NULL; - - file = XFOPEN(fname, "rb"); - if (file == XBADFILE) - return WOLFSSL_BAD_FILE; - - if (XFSEEK(file, 0, XSEEK_END) != 0) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - sz = XFTELL(file); - if (XFSEEK(file, 0, XSEEK_SET) != 0) { - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { - WOLFSSL_MSG("cmp_peer_cert_to_file size error"); - XFCLOSE(file); - return WOLFSSL_BAD_FILE; - } - - if (sz > (long)sizeof(staticBuffer)) { - WOLFSSL_MSG("Getting dynamic buffer"); - myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); - dynamic = 1; - } - - if ((myBuffer != NULL) && - (sz > 0) && - (XFREAD(myBuffer, 1, sz, file) == (size_t)sz) && - (PemToDer(myBuffer, (long)sz, CERT_TYPE, - &fileDer, ctx->heap, NULL, NULL) == 0) && - (fileDer->length != 0) && - (fileDer->length == peer_cert->derCert->length) && - (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, - fileDer->length) == 0)) - { - ret = 0; - } - - FreeDer(&fileDer); - - if (dynamic) - XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); - - XFCLOSE(file); - } - - return ret; -} -#endif -#endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) -const WOLFSSL_ObjectInfo wolfssl_object_info[] = { -#ifndef NO_CERTS - /* oidCertExtType */ - { NID_basic_constraints, BASIC_CA_OID, oidCertExtType, "basicConstraints", - "X509v3 Basic Constraints"}, - { NID_subject_alt_name, ALT_NAMES_OID, oidCertExtType, "subjectAltName", - "X509v3 Subject Alternative Name"}, - { NID_crl_distribution_points, CRL_DIST_OID, oidCertExtType, "crlDistributionPoints", - "X509v3 CRL Distribution Points"}, - { NID_info_access, AUTH_INFO_OID, oidCertExtType, "authorityInfoAccess", - "Authority Information Access"}, - { NID_authority_key_identifier, AUTH_KEY_OID, oidCertExtType, - "authorityKeyIdentifier", "X509v3 Authority Key Identifier"}, - { NID_subject_key_identifier, SUBJ_KEY_OID, oidCertExtType, - "subjectKeyIdentifier", "X509v3 Subject Key Identifier"}, - { NID_key_usage, KEY_USAGE_OID, oidCertExtType, "keyUsage", - "X509v3 Key Usage"}, - { NID_inhibit_any_policy, INHIBIT_ANY_OID, oidCertExtType, - "inhibitAnyPolicy", "X509v3 Inhibit Any Policy"}, - { NID_ext_key_usage, EXT_KEY_USAGE_OID, oidCertExtType, - "extendedKeyUsage", "X509v3 Extended Key Usage"}, - { NID_name_constraints, NAME_CONS_OID, oidCertExtType, - "nameConstraints", "X509v3 Name Constraints"}, - { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType, - "certificatePolicies", "X509v3 Certificate Policies"}, - - /* oidCertAuthInfoType */ - { NID_ad_OCSP, AIA_OCSP_OID, oidCertAuthInfoType, "OCSP", - "OCSP"}, - { NID_ad_ca_issuers, AIA_CA_ISSUER_OID, oidCertAuthInfoType, - "caIssuers", "CA Issuers"}, - - /* oidCertPolicyType */ - { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "anyPolicy", - "X509v3 Any Policy"}, - - /* oidCertAltNameType */ - { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name",""}, - - /* oidCertKeyUseType */ - { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType, - "anyExtendedKeyUsage", "Any Extended Key Usage"}, - { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType, - "serverAuth", "TLS Web Server Authentication"}, - { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType, - "clientAuth", "TLS Web Client Authentication"}, - { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType, - "OCSPSigning", "OCSP Signing"}, - - /* oidCertNameType */ - { NID_commonName, NID_commonName, oidCertNameType, "CN", "commonName"}, -#if !defined(WOLFSSL_CERT_REQ) - { NID_surname, NID_surname, oidCertNameType, "SN", "surname"}, -#endif - { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber", - "serialNumber"}, - { NID_userId, NID_userId, oidCertNameType, "UID", "userid"}, - { NID_countryName, NID_countryName, oidCertNameType, "C", "countryName"}, - { NID_localityName, NID_localityName, oidCertNameType, "L", "localityName"}, - { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, "ST", - "stateOrProvinceName"}, - { NID_streetAddress, NID_streetAddress, oidCertNameType, "street", - "streetAddress"}, - { NID_organizationName, NID_organizationName, oidCertNameType, "O", - "organizationName"}, - { NID_organizationalUnitName, NID_organizationalUnitName, oidCertNameType, - "OU", "organizationalUnitName"}, - { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress", - "emailAddress"}, - { NID_domainComponent, NID_domainComponent, oidCertNameType, "DC", - "domainComponent"}, - { NID_favouriteDrink, NID_favouriteDrink, oidCertNameType, "favouriteDrink", - "favouriteDrink"}, - { NID_businessCategory, NID_businessCategory, oidCertNameType, "businessCategory", - "businessCategory"}, - { NID_jurisdictionCountryName, NID_jurisdictionCountryName, oidCertNameType, "jurisdictionC", - "jurisdictionCountryName"}, - { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName, - oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"}, - { NID_postalCode, NID_postalCode, oidCertNameType, "postalCode", "postalCode"}, - { NID_userId, NID_userId, oidCertNameType, "UID", "userId"}, - -#if defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_NAME_ALL) - { NID_pkcs9_challengePassword, CHALLENGE_PASSWORD_OID, - oidCsrAttrType, "challengePassword", "challengePassword"}, - { NID_pkcs9_contentType, PKCS9_CONTENT_TYPE_OID, - oidCsrAttrType, "contentType", "contentType" }, - { NID_pkcs9_unstructuredName, UNSTRUCTURED_NAME_OID, - oidCsrAttrType, "unstructuredName", "unstructuredName" }, - { NID_name, NAME_OID, oidCsrAttrType, "name", "name" }, - { NID_surname, SURNAME_OID, - oidCsrAttrType, "surname", "surname" }, - { NID_givenName, GIVEN_NAME_OID, - oidCsrAttrType, "givenName", "givenName" }, - { NID_initials, INITIALS_OID, - oidCsrAttrType, "initials", "initials" }, - { NID_dnQualifier, DNQUALIFIER_OID, - oidCsrAttrType, "dnQualifer", "dnQualifier" }, -#endif -#endif -#ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */ - /* oidHashType */ - #ifdef WOLFSSL_MD2 - { NID_md2, MD2h, oidHashType, "MD2", "md2"}, - #endif - #ifdef WOLFSSL_MD5 - { NID_md5, MD5h, oidHashType, "MD5", "md5"}, - #endif - #ifndef NO_SHA - { NID_sha1, SHAh, oidHashType, "SHA1", "sha1"}, - #endif - #ifdef WOLFSSL_SHA224 - { NID_sha224, SHA224h, oidHashType, "SHA224", "sha224"}, - #endif - #ifndef NO_SHA256 - { NID_sha256, SHA256h, oidHashType, "SHA256", "sha256"}, - #endif - #ifdef WOLFSSL_SHA384 - { NID_sha384, SHA384h, oidHashType, "SHA384", "sha384"}, - #endif - #ifdef WOLFSSL_SHA512 - { NID_sha512, SHA512h, oidHashType, "SHA512", "sha512"}, - #endif - #ifdef WOLFSSL_SHA3 - #ifndef WOLFSSL_NOSHA3_224 - { NID_sha3_224, SHA3_224h, oidHashType, "SHA3-224", "sha3-224"}, - #endif - #ifndef WOLFSSL_NOSHA3_256 - { NID_sha3_256, SHA3_256h, oidHashType, "SHA3-256", "sha3-256"}, - #endif - #ifndef WOLFSSL_NOSHA3_384 - { NID_sha3_384, SHA3_384h, oidHashType, "SHA3-384", "sha3-384"}, - #endif - #ifndef WOLFSSL_NOSHA3_512 - { NID_sha3_512, SHA3_512h, oidHashType, "SHA3-512", "sha3-512"}, - #endif - #endif /* WOLFSSL_SHA3 */ - #ifdef WOLFSSL_SM3 - { NID_sm3, SM3h, oidHashType, "SM3", "sm3"}, - #endif - /* oidSigType */ - #ifndef NO_DSA - #ifndef NO_SHA - { NID_dsaWithSHA1, CTC_SHAwDSA, oidSigType, "DSA-SHA1", "dsaWithSHA1"}, - { NID_dsa_with_SHA256, CTC_SHA256wDSA, oidSigType, "dsa_with_SHA256", - "dsa_with_SHA256"}, - #endif - #endif /* NO_DSA */ - #ifndef NO_RSA - #ifdef WOLFSSL_MD2 - { NID_md2WithRSAEncryption, CTC_MD2wRSA, oidSigType, "RSA-MD2", - "md2WithRSAEncryption"}, - #endif - #ifndef NO_MD5 - { NID_md5WithRSAEncryption, CTC_MD5wRSA, oidSigType, "RSA-MD5", - "md5WithRSAEncryption"}, - #endif - #ifndef NO_SHA - { NID_sha1WithRSAEncryption, CTC_SHAwRSA, oidSigType, "RSA-SHA1", - "sha1WithRSAEncryption"}, - #endif - #ifdef WOLFSSL_SHA224 - { NID_sha224WithRSAEncryption, CTC_SHA224wRSA, oidSigType, "RSA-SHA224", - "sha224WithRSAEncryption"}, - #endif - #ifndef NO_SHA256 - { NID_sha256WithRSAEncryption, CTC_SHA256wRSA, oidSigType, "RSA-SHA256", - "sha256WithRSAEncryption"}, - #endif - #ifdef WOLFSSL_SHA384 - { NID_sha384WithRSAEncryption, CTC_SHA384wRSA, oidSigType, "RSA-SHA384", - "sha384WithRSAEncryption"}, - #endif - #ifdef WOLFSSL_SHA512 - { NID_sha512WithRSAEncryption, CTC_SHA512wRSA, oidSigType, "RSA-SHA512", - "sha512WithRSAEncryption"}, - #endif - #ifdef WOLFSSL_SHA3 - #ifndef WOLFSSL_NOSHA3_224 - { NID_RSA_SHA3_224, CTC_SHA3_224wRSA, oidSigType, "RSA-SHA3-224", - "sha3-224WithRSAEncryption"}, - #endif - #ifndef WOLFSSL_NOSHA3_256 - { NID_RSA_SHA3_256, CTC_SHA3_256wRSA, oidSigType, "RSA-SHA3-256", - "sha3-256WithRSAEncryption"}, - #endif - #ifndef WOLFSSL_NOSHA3_384 - { NID_RSA_SHA3_384, CTC_SHA3_384wRSA, oidSigType, "RSA-SHA3-384", - "sha3-384WithRSAEncryption"}, - #endif - #ifndef WOLFSSL_NOSHA3_512 - { NID_RSA_SHA3_512, CTC_SHA3_512wRSA, oidSigType, "RSA-SHA3-512", - "sha3-512WithRSAEncryption"}, - #endif - #endif - #ifdef WC_RSA_PSS - { NID_rsassaPss, CTC_RSASSAPSS, oidSigType, "RSASSA-PSS", "rsassaPss" }, - #endif - #endif /* NO_RSA */ - #ifdef HAVE_ECC - #ifndef NO_SHA - { NID_ecdsa_with_SHA1, CTC_SHAwECDSA, oidSigType, "ecdsa-with-SHA1", "shaWithECDSA"}, - #endif - #ifdef WOLFSSL_SHA224 - { NID_ecdsa_with_SHA224, CTC_SHA224wECDSA, oidSigType, "ecdsa-with-SHA224","sha224WithECDSA"}, - #endif - #ifndef NO_SHA256 - { NID_ecdsa_with_SHA256, CTC_SHA256wECDSA, oidSigType, "ecdsa-with-SHA256","sha256WithECDSA"}, - #endif - #ifdef WOLFSSL_SHA384 - { NID_ecdsa_with_SHA384, CTC_SHA384wECDSA, oidSigType, "ecdsa-with-SHA384","sha384WithECDSA"}, - #endif - #ifdef WOLFSSL_SHA512 - { NID_ecdsa_with_SHA512, CTC_SHA512wECDSA, oidSigType, "ecdsa-with-SHA512","sha512WithECDSA"}, - #endif - #ifdef WOLFSSL_SHA3 - #ifndef WOLFSSL_NOSHA3_224 - { NID_ecdsa_with_SHA3_224, CTC_SHA3_224wECDSA, oidSigType, "id-ecdsa-with-SHA3-224", - "ecdsa_with_SHA3-224"}, - #endif - #ifndef WOLFSSL_NOSHA3_256 - { NID_ecdsa_with_SHA3_256, CTC_SHA3_256wECDSA, oidSigType, "id-ecdsa-with-SHA3-256", - "ecdsa_with_SHA3-256"}, - #endif - #ifndef WOLFSSL_NOSHA3_384 - { NID_ecdsa_with_SHA3_384, CTC_SHA3_384wECDSA, oidSigType, "id-ecdsa-with-SHA3-384", - "ecdsa_with_SHA3-384"}, - #endif - #ifndef WOLFSSL_NOSHA3_512 - { NID_ecdsa_with_SHA3_512, CTC_SHA3_512wECDSA, oidSigType, "id-ecdsa-with-SHA3-512", - "ecdsa_with_SHA3-512"}, - #endif - #endif - #endif /* HAVE_ECC */ - - /* oidKeyType */ - #ifndef NO_DSA - { NID_dsa, DSAk, oidKeyType, "DSA", "dsaEncryption"}, - #endif /* NO_DSA */ - #ifndef NO_RSA - { NID_rsaEncryption, RSAk, oidKeyType, "rsaEncryption", "rsaEncryption"}, - #ifdef WC_RSA_PSS - { NID_rsassaPss, RSAPSSk, oidKeyType, "RSASSA-PSS", "rsassaPss"}, - #endif - #endif /* NO_RSA */ - #ifdef HAVE_ECC - { NID_X9_62_id_ecPublicKey, ECDSAk, oidKeyType, "id-ecPublicKey", - "id-ecPublicKey"}, - #endif /* HAVE_ECC */ - #ifndef NO_DH - { NID_dhKeyAgreement, DHk, oidKeyType, "dhKeyAgreement", "dhKeyAgreement"}, - #endif - #ifdef HAVE_ED448 - { NID_ED448, ED448k, oidKeyType, "ED448", "ED448"}, - #endif - #ifdef HAVE_ED25519 - { NID_ED25519, ED25519k, oidKeyType, "ED25519", "ED25519"}, - #endif - #ifdef HAVE_PQC - #ifdef HAVE_FALCON - { CTC_FALCON_LEVEL1, FALCON_LEVEL1k, oidKeyType, "Falcon Level 1", - "Falcon Level 1"}, - { CTC_FALCON_LEVEL5, FALCON_LEVEL5k, oidKeyType, "Falcon Level 5", - "Falcon Level 5"}, - #endif /* HAVE_FALCON */ - #ifdef HAVE_DILITHIUM - { CTC_DILITHIUM_LEVEL2, DILITHIUM_LEVEL2k, oidKeyType, - "Dilithium Level 2", "Dilithium Level 2"}, - { CTC_DILITHIUM_LEVEL3, DILITHIUM_LEVEL3k, oidKeyType, - "Dilithium Level 3", "Dilithium Level 3"}, - { CTC_DILITHIUM_LEVEL5, DILITHIUM_LEVEL5k, oidKeyType, - "Dilithium Level 5", "Dilithium Level 5"}, - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ - - /* oidCurveType */ - #ifdef HAVE_ECC - { NID_X9_62_prime192v1, ECC_SECP192R1_OID, oidCurveType, "prime192v1", "prime192v1"}, - { NID_X9_62_prime192v2, ECC_PRIME192V2_OID, oidCurveType, "prime192v2", "prime192v2"}, - { NID_X9_62_prime192v3, ECC_PRIME192V3_OID, oidCurveType, "prime192v3", "prime192v3"}, - - { NID_X9_62_prime239v1, ECC_PRIME239V1_OID, oidCurveType, "prime239v1", "prime239v1"}, - { NID_X9_62_prime239v2, ECC_PRIME239V2_OID, oidCurveType, "prime239v2", "prime239v2"}, - { NID_X9_62_prime239v3, ECC_PRIME239V3_OID, oidCurveType, "prime239v3", "prime239v3"}, - - { NID_X9_62_prime256v1, ECC_SECP256R1_OID, oidCurveType, "prime256v1", "prime256v1"}, - - { NID_secp112r1, ECC_SECP112R1_OID, oidCurveType, "secp112r1", "secp112r1"}, - { NID_secp112r2, ECC_SECP112R2_OID, oidCurveType, "secp112r2", "secp112r2"}, - - { NID_secp128r1, ECC_SECP128R1_OID, oidCurveType, "secp128r1", "secp128r1"}, - { NID_secp128r2, ECC_SECP128R2_OID, oidCurveType, "secp128r2", "secp128r2"}, - - { NID_secp160r1, ECC_SECP160R1_OID, oidCurveType, "secp160r1", "secp160r1"}, - { NID_secp160r2, ECC_SECP160R2_OID, oidCurveType, "secp160r2", "secp160r2"}, - - { NID_secp224r1, ECC_SECP224R1_OID, oidCurveType, "secp224r1", "secp224r1"}, - { NID_secp384r1, ECC_SECP384R1_OID, oidCurveType, "secp384r1", "secp384r1"}, - { NID_secp521r1, ECC_SECP521R1_OID, oidCurveType, "secp521r1", "secp521r1"}, - - { NID_secp160k1, ECC_SECP160K1_OID, oidCurveType, "secp160k1", "secp160k1"}, - { NID_secp192k1, ECC_SECP192K1_OID, oidCurveType, "secp192k1", "secp192k1"}, - { NID_secp224k1, ECC_SECP224K1_OID, oidCurveType, "secp224k1", "secp224k1"}, - { NID_secp256k1, ECC_SECP256K1_OID, oidCurveType, "secp256k1", "secp256k1"}, - - { NID_brainpoolP160r1, ECC_BRAINPOOLP160R1_OID, oidCurveType, "brainpoolP160r1", "brainpoolP160r1"}, - { NID_brainpoolP192r1, ECC_BRAINPOOLP192R1_OID, oidCurveType, "brainpoolP192r1", "brainpoolP192r1"}, - { NID_brainpoolP224r1, ECC_BRAINPOOLP224R1_OID, oidCurveType, "brainpoolP224r1", "brainpoolP224r1"}, - { NID_brainpoolP256r1, ECC_BRAINPOOLP256R1_OID, oidCurveType, "brainpoolP256r1", "brainpoolP256r1"}, - { NID_brainpoolP320r1, ECC_BRAINPOOLP320R1_OID, oidCurveType, "brainpoolP320r1", "brainpoolP320r1"}, - { NID_brainpoolP384r1, ECC_BRAINPOOLP384R1_OID, oidCurveType, "brainpoolP384r1", "brainpoolP384r1"}, - { NID_brainpoolP512r1, ECC_BRAINPOOLP512R1_OID, oidCurveType, "brainpoolP512r1", "brainpoolP512r1"}, - - #ifdef WOLFSSL_SM2 - { NID_sm2, ECC_SM2P256V1_OID, oidCurveType, "sm2", "sm2"}, - #endif - #endif /* HAVE_ECC */ - - /* oidBlkType */ - #ifdef WOLFSSL_AES_128 - { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC", "aes-128-cbc"}, - #endif - #ifdef WOLFSSL_AES_192 - { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC", "aes-192-cbc"}, - #endif - #ifdef WOLFSSL_AES_256 - { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC", "aes-256-cbc"}, - #endif - #ifndef NO_DES3 - { NID_des, DESb, oidBlkType, "DES-CBC", "des-cbc"}, - { NID_des3, DES3b, oidBlkType, "DES-EDE3-CBC", "des-ede3-cbc"}, - #endif /* !NO_DES3 */ - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - { NID_chacha20_poly1305, NID_chacha20_poly1305, oidBlkType, "ChaCha20-Poly1305", "chacha20-poly1305"}, - #endif - - /* oidOcspType */ - #ifdef HAVE_OCSP - { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, "basicOCSPResponse", - "Basic OCSP Response"}, - { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "Nonce", - "OCSP Nonce"}, - #endif /* HAVE_OCSP */ - - #ifndef NO_PWDBASED - /* oidKdfType */ - { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2", "PBKDF2"}, - - /* oidPBEType */ - { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType, - "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4"}, - { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE-SHA1-DES", - "pbeWithSHA1AndDES-CBC"}, - { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE-SHA1-3DES", - "pbeWithSHA1And3-KeyTripleDES-CBC"}, - #endif - - /* oidKeyWrapType */ - #ifdef WOLFSSL_AES_128 - { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap", "aes128-wrap"}, - #endif - #ifdef WOLFSSL_AES_192 - { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap", "aes192-wrap"}, - #endif - #ifdef WOLFSSL_AES_256 - { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap", "aes256-wrap"}, - #endif - - #ifndef NO_PKCS7 - #ifndef NO_DH - /* oidCmsKeyAgreeType */ - #ifndef NO_SHA - { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme, - oidCmsKeyAgreeType, "dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme"}, - #endif - #ifdef WOLFSSL_SHA224 - { dhSinglePass_stdDH_sha224kdf_scheme, - dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType, - "dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme"}, - #endif - #ifndef NO_SHA256 - { dhSinglePass_stdDH_sha256kdf_scheme, - dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType, - "dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme"}, - #endif - #ifdef WOLFSSL_SHA384 - { dhSinglePass_stdDH_sha384kdf_scheme, - dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType, - "dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme"}, - #endif - #ifdef WOLFSSL_SHA512 - { dhSinglePass_stdDH_sha512kdf_scheme, - dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType, - "dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme"}, - #endif - #endif - #endif - #if defined(WOLFSSL_APACHE_HTTPD) - /* "1.3.6.1.5.5.7.8.7" */ - { NID_id_on_dnsSRV, NID_id_on_dnsSRV, oidCertNameType, - WOLFSSL_SN_DNS_SRV, WOLFSSL_LN_DNS_SRV }, - - /* "1.3.6.1.4.1.311.20.2.3" */ - { NID_ms_upn, WOLFSSL_MS_UPN_SUM, oidCertExtType, WOLFSSL_SN_MS_UPN, - WOLFSSL_LN_MS_UPN }, - - /* "1.3.6.1.5.5.7.1.24" */ - { NID_tlsfeature, WOLFSSL_TLS_FEATURE_SUM, oidTlsExtType, - WOLFSSL_SN_TLS_FEATURE, WOLFSSL_LN_TLS_FEATURE }, - #endif -#endif /* OPENSSL_EXTRA */ -}; - -#define WOLFSSL_OBJECT_INFO_SZ \ - (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info)) -const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ; -#endif - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) -/* Free the dynamically allocated data. - * - * p Pointer to dynamically allocated memory. - */ -void wolfSSL_OPENSSL_free(void* p) -{ - WOLFSSL_MSG("wolfSSL_OPENSSL_free"); - - XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); -} -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - -#ifdef OPENSSL_EXTRA - -void *wolfSSL_OPENSSL_malloc(size_t a) -{ - return (void *)XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL); -} - -int wolfSSL_OPENSSL_hexchar2int(unsigned char c) -{ - /* 'char' is unsigned on some platforms. */ - return (int)(signed char)HexCharToByte((char)c); -} - -unsigned char *wolfSSL_OPENSSL_hexstr2buf(const char *str, long *len) -{ - unsigned char* targetBuf; - int srcDigitHigh = 0; - int srcDigitLow = 0; - size_t srcLen; - size_t srcIdx = 0; - long targetIdx = 0; - - srcLen = XSTRLEN(str); - targetBuf = (unsigned char*)XMALLOC(srcLen / 2, NULL, DYNAMIC_TYPE_OPENSSL); - if (targetBuf == NULL) { - return NULL; - } - - while (srcIdx < srcLen) { - if (str[srcIdx] == ':') { - srcIdx++; - continue; - } - - srcDigitHigh = wolfSSL_OPENSSL_hexchar2int(str[srcIdx++]); - srcDigitLow = wolfSSL_OPENSSL_hexchar2int(str[srcIdx++]); - if (srcDigitHigh < 0 || srcDigitLow < 0) { - WOLFSSL_MSG("Invalid hex character."); - XFREE(targetBuf, NULL, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - - targetBuf[targetIdx++] = (unsigned char)((srcDigitHigh << 4) | srcDigitLow); - } - - if (len != NULL) - *len = targetIdx; - - return targetBuf; -} - -int wolfSSL_OPENSSL_init_ssl(word64 opts, const OPENSSL_INIT_SETTINGS *settings) -{ - (void)opts; - (void)settings; - return wolfSSL_library_init(); -} - -int wolfSSL_OPENSSL_init_crypto(word64 opts, const OPENSSL_INIT_SETTINGS* settings) -{ - (void)opts; - (void)settings; - return wolfSSL_library_init(); -} - -#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER) - -int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, byte **cipherInfo, - int maxDerSz) -{ - 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_ENCRYPTEDINFO); - if (info == NULL) { - WOLFSSL_MSG("malloc failed"); - return WOLFSSL_FAILURE; - } -#endif - - XMEMSET(info, 0, sizeof(EncryptedInfo)); - - /* set the cipher name on info */ - XSTRNCPY(info->name, cipher, NAME_SZ-1); - info->name[NAME_SZ-1] = '\0'; /* null term */ - - ret = wc_EncryptedInfoGet(info, info->name); - if (ret != 0) { - WOLFSSL_MSG("unsupported cipher"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); - #endif - return WOLFSSL_FAILURE; - } - - /* Generate a random salt */ - if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("generate iv failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); -#endif - return WOLFSSL_FAILURE; - } - - /* add the padding before encryption */ - paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz); - if (paddingSz == 0) - paddingSz = info->ivSz; - if (maxDerSz < *derSz + paddingSz) { - WOLFSSL_MSG("not enough DER buffer allocated"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); -#endif - return WOLFSSL_FAILURE; - } - XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz); - (*derSz) += paddingSz; - - /* encrypt buffer */ - if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) { - WOLFSSL_MSG("encrypt key failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); -#endif - return WOLFSSL_FAILURE; - } - - /* create cipher info : 'cipher_name,Salt(hex)' */ - cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2); - *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, - DYNAMIC_TYPE_STRING); - if (*cipherInfo == NULL) { - WOLFSSL_MSG("malloc failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); -#endif - return WOLFSSL_FAILURE; - } - XSTRLCPY((char*)*cipherInfo, info->name, cipherInfoSz); - XSTRLCAT((char*)*cipherInfo, ",", cipherInfoSz); - - 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_ENCRYPTEDINFO); -#endif - if (ret != 0) { - WOLFSSL_MSG("Base16_Encode failed"); - XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} -#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */ - -#if !defined(NO_BIO) -static int pem_write_pubkey(WOLFSSL_EVP_PKEY* key, void* heap, byte** derBuf, - int* derSz) -{ - byte* buf = NULL; - int sz = 0; - - (void)heap; - - if (key == NULL) { - WOLFSSL_MSG("Bad parameters"); - return WOLFSSL_FAILURE; - } - - switch (key->type) { -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) - case EVP_PKEY_RSA: - if ((sz = wolfSSL_RSA_To_Der(key->rsa, &buf, 1, heap)) - < 0) { - WOLFSSL_MSG("wolfSSL_RSA_To_Der failed"); - break; - } - break; -#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ -#if !defined(NO_DSA) && !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \ - defined(WOLFSSL_CERT_GEN)) - case EVP_PKEY_DSA: - if (key->dsa == NULL) { - WOLFSSL_MSG("key->dsa is null"); - break; - } - sz = MAX_DSA_PUBKEY_SZ; - buf = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) { - WOLFSSL_MSG("malloc failed"); - break; - } - /* Key to DER */ - sz = wc_DsaKeyToPublicDer((DsaKey*)key->dsa->internal, buf, sz); - if (sz < 0) { - WOLFSSL_MSG("wc_DsaKeyToDer failed"); - break; - } - break; -#endif /* !NO_DSA && !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */ -#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) - case EVP_PKEY_EC: - { - if (key->ecc == NULL) { - WOLFSSL_MSG("key->ecc is null"); - break; - } - if ((sz = wolfssl_ec_key_to_pubkey_der(key->ecc, &buf, heap)) <= - 0) { - WOLFSSL_MSG("wolfssl_ec_key_to_pubkey_der failed"); - break; - } - break; - } -#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) - case EVP_PKEY_DH: - WOLFSSL_MSG("Writing DH PUBKEY not supported!"); - break; -#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ - default: - WOLFSSL_MSG("Unknown Key type!"); - break; - } - - if (buf == NULL || sz <= 0) { - if (buf != NULL) - XFREE(buf, heap, DYNAMIC_TYPE_DER); - return WOLFSSL_FAILURE; - } - - *derBuf = buf; - *derSz = sz; - return WOLFSSL_SUCCESS; -} -#endif - -#ifndef NO_BIO -static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) -{ - int ret; - int derSz = 0; - byte* derBuf = NULL; - - ret = pem_write_pubkey(key, bio->heap, &derBuf, &derSz); - if (ret == WOLFSSL_SUCCESS) { - ret = der_write_to_bio_as_pem(derBuf, derSz, bio, PUBLICKEY_TYPE); - XFREE(derBuf, bio->heap, DYNAMIC_TYPE_DER); - } - - return ret; -} - -/* Takes a public key and writes it out to a WOLFSSL_BIO - * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE - */ -int wolfSSL_PEM_write_bio_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) -{ - int ret; - - WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PUBKEY"); - - if ((bio == NULL) || (key == NULL)) { - ret = WOLFSSL_FAILURE; - } - else { - ret = pem_write_bio_pubkey(bio, key); - } - - return ret; -} - -/* Takes a private key and writes it out to a WOLFSSL_BIO - * Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE - */ -int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, - const WOLFSSL_EVP_CIPHER* cipher, - unsigned char* passwd, int len, - wc_pem_password_cb* cb, void* arg) -{ - byte* keyDer; - int type; - - (void)cipher; - (void)passwd; - (void)len; - (void)cb; - (void)arg; - - WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); - - if (bio == NULL || key == NULL) { - WOLFSSL_MSG("Bad Function Arguments"); - return WOLFSSL_FAILURE; - } - - keyDer = (byte*)key->pkey.ptr; - - switch (key->type) { -#ifndef NO_RSA - case EVP_PKEY_RSA: - type = PRIVATEKEY_TYPE; - break; -#endif - -#ifndef NO_DSA - case EVP_PKEY_DSA: - type = DSA_PRIVATEKEY_TYPE; - break; -#endif - -#ifdef HAVE_ECC - case EVP_PKEY_EC: - type = ECC_PRIVATEKEY_TYPE; - break; -#endif - -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) - case EVP_PKEY_DH: - type = DH_PRIVATEKEY_TYPE; - break; -#endif - - default: - WOLFSSL_MSG("Unknown Key type!"); - type = PRIVATEKEY_TYPE; - } - - return der_write_to_bio_as_pem(keyDer, key->pkey_sz, bio, type); -} -#endif /* !NO_BIO */ - -/* Colon separated list of + algorithms. - * Replaces list in context. - */ -int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, const char* list) -{ - WOLFSSL_MSG("wolfSSL_CTX_set1_sigalg_list"); - - if (ctx == NULL || list == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return WOLFSSL_FAILURE; - } - - if (AllocateCtxSuites(ctx) != 0) - return WOLFSSL_FAILURE; - - return SetSuitesHashSigAlgo(ctx->suites, list); -} - -/* Colon separated list of + algorithms. - * Replaces list in SSL. - */ -int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list) -{ - WOLFSSL_MSG("wolfSSL_set1_sigalg_list"); - - if (ssl == NULL || list == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return WOLFSSL_FAILURE; - } - - if (AllocateSuites(ssl) != 0) - return WOLFSSL_FAILURE; - - return SetSuitesHashSigAlgo(ssl->suites, list); -} - -static int HashToNid(byte hashAlgo, int* nid) -{ - int ret = WOLFSSL_SUCCESS; - - /* Cast for compiler to check everything is implemented */ - switch ((enum wc_MACAlgorithm)hashAlgo) { - case no_mac: - case rmd_mac: - *nid = NID_undef; - break; - case md5_mac: - *nid = NID_md5; - break; - case sha_mac: - *nid = NID_sha1; - break; - case sha224_mac: - *nid = NID_sha224; - break; - case sha256_mac: - *nid = NID_sha256; - break; - case sha384_mac: - *nid = NID_sha384; - break; - case sha512_mac: - *nid = NID_sha512; - break; - case blake2b_mac: - *nid = NID_blake2b512; - break; - case sm3_mac: - *nid = NID_sm3; - break; - default: - ret = WOLFSSL_FAILURE; - break; - } - - return ret; -} - -static int SaToNid(byte sa, int* nid) -{ - int ret = WOLFSSL_SUCCESS; - /* Cast for compiler to check everything is implemented */ - switch ((enum SignatureAlgorithm)sa) { - case anonymous_sa_algo: - *nid = NID_undef; - break; - case rsa_sa_algo: - *nid = NID_rsaEncryption; - break; - case dsa_sa_algo: - *nid = NID_dsa; - break; - case ecc_dsa_sa_algo: - *nid = NID_X9_62_id_ecPublicKey; - break; - case rsa_pss_sa_algo: - *nid = NID_rsassaPss; - break; - case ed25519_sa_algo: -#ifdef HAVE_ED25519 - *nid = NID_ED25519; -#else - ret = WOLFSSL_FAILURE; -#endif - break; - case rsa_pss_pss_algo: - *nid = NID_rsassaPss; - break; - case ed448_sa_algo: -#ifdef HAVE_ED448 - *nid = NID_ED448; -#else - ret = WOLFSSL_FAILURE; -#endif - break; - case falcon_level1_sa_algo: - *nid = CTC_FALCON_LEVEL1; - break; - case falcon_level5_sa_algo: - *nid = CTC_FALCON_LEVEL5; - break; - case dilithium_level2_sa_algo: - *nid = CTC_DILITHIUM_LEVEL2; - break; - case dilithium_level3_sa_algo: - *nid = CTC_DILITHIUM_LEVEL3; - break; - case dilithium_level5_sa_algo: - *nid = CTC_DILITHIUM_LEVEL5; - break; - case sm2_sa_algo: - *nid = NID_sm2; - break; - case invalid_sa_algo: - default: - ret = WOLFSSL_FAILURE; - break; - } - return ret; -} - -/* This API returns the hash selected. */ -int wolfSSL_get_signature_nid(WOLFSSL *ssl, int* nid) -{ - WOLFSSL_MSG("wolfSSL_get_signature_nid"); - - if (ssl == NULL || nid == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return WOLFSSL_FAILURE; - } - - return HashToNid(ssl->options.hashAlgo, nid); -} - -/* This API returns the signature selected. */ -int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid) -{ - WOLFSSL_MSG("wolfSSL_get_signature_type_nid"); - - if (ssl == NULL || nid == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return WOLFSSL_FAILURE; - } - - return SaToNid(ssl->options.sigAlgo, nid); -} - -int wolfSSL_get_peer_signature_nid(WOLFSSL* ssl, int* nid) -{ - WOLFSSL_MSG("wolfSSL_get_peer_signature_nid"); - - if (ssl == NULL || nid == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return WOLFSSL_FAILURE; - } - - return HashToNid(ssl->options.peerHashAlgo, nid); -} - -int wolfSSL_get_peer_signature_type_nid(const WOLFSSL* ssl, int* nid) -{ - WOLFSSL_MSG("wolfSSL_get_peer_signature_type_nid"); - - if (ssl == NULL || nid == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return WOLFSSL_FAILURE; - } - - return SaToNid(ssl->options.peerSigAlgo, nid); -} - -#ifdef HAVE_ECC - -#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) -static int populate_groups(int* groups, int max_count, const char *list) -{ - const char *end; - int count = 0; - const WOLF_EC_NIST_NAME* nist_name; - - if (!groups || !list) { - return -1; - } - - for (end = list; ; list = ++end) { - int len; - - if (count > max_count) { - WOLFSSL_MSG("Too many curves in list"); - return -1; - } - while (*end != ':' && *end != '\0') end++; - len = (int)(end - list); /* end points to char after end - * of curve name so no need for -1 */ - if ((len < kNistCurves_MIN_NAME_LEN) || - (len > kNistCurves_MAX_NAME_LEN)) { - WOLFSSL_MSG("Unrecognized curve name in list"); - return -1; - } - for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { - if (len == nist_name->name_len && - XSTRNCMP(list, nist_name->name, nist_name->name_len) == 0) { - break; - } - } - if (!nist_name->name) { - WOLFSSL_MSG("Unrecognized curve name in list"); - return -1; - } - groups[count++] = nist_name->nid; - if (*end == '\0') break; - } - - return count; -} - -int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list) -{ - int groups[WOLFSSL_MAX_GROUP_COUNT]; - int count = 0; - - if (!ctx || !list) { - return WOLFSSL_FAILURE; - } - - if ((count = populate_groups(groups, - WOLFSSL_MAX_GROUP_COUNT, list)) == -1) { - return WOLFSSL_FAILURE; - } - - return wolfSSL_CTX_set1_groups(ctx, groups, count); -} - -int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list) -{ - int groups[WOLFSSL_MAX_GROUP_COUNT]; - int count = 0; - - if (!ssl || !list) { - return WOLFSSL_FAILURE; - } - - if ((count = populate_groups(groups, - WOLFSSL_MAX_GROUP_COUNT, list)) == -1) { - return WOLFSSL_FAILURE; - } - - return wolfSSL_set1_groups(ssl, groups, count); -} -#endif /* WOLFSSL_TLS13 */ - -#endif /* HAVE_ECC */ - -#ifndef NO_BIO -WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** key, - wc_pem_password_cb* cb, - void* pass) -{ - WOLFSSL_EVP_PKEY* pkey = NULL; - DerBuffer* der = NULL; - int keyFormat = 0; - - WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey"); - - if (bio == NULL) - return pkey; - - if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &keyFormat, &der) - >= 0) { - const unsigned char* ptr = der->buffer; - int type = -1; - - if (keyFormat) { - /* keyFormat is Key_Sum enum */ - if (keyFormat == RSAk) - type = EVP_PKEY_RSA; - else if (keyFormat == ECDSAk) - type = EVP_PKEY_EC; - else if (keyFormat == DSAk) - type = EVP_PKEY_DSA; - else if (keyFormat == DHk) - type = EVP_PKEY_DH; - } - else { - /* Default to RSA if format is not set */ - type = EVP_PKEY_RSA; - } - - /* handle case where reuse is attempted */ - if (key != NULL && *key != NULL) - pkey = *key; - - wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length); - if (pkey == NULL) { - WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); - } - } - - FreeDer(&der); - - if (key != NULL && pkey != NULL) - *key = pkey; - - WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0); - - return pkey; -} - -WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY **key, - wc_pem_password_cb *cb, - void *pass) -{ - WOLFSSL_EVP_PKEY* pkey = NULL; - DerBuffer* der = NULL; - int keyFormat = 0; - - WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY"); - - if (bio == NULL) - return pkey; - - if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der) - >= 0) { - const unsigned char* ptr = der->buffer; - - /* handle case where reuse is attempted */ - if (key != NULL && *key != NULL) - pkey = *key; - - wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length); - if (pkey == NULL) { - WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); - } - } - - FreeDer(&der); - - if (key != NULL && pkey != NULL) - *key = pkey; - - WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PUBKEY", 0); - - return pkey; -} -#endif /* !NO_BIO */ - -#if !defined(NO_FILESYSTEM) -WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, WOLFSSL_EVP_PKEY **key, - wc_pem_password_cb *cb, void *pass) -{ - WOLFSSL_EVP_PKEY* pkey = NULL; - DerBuffer* der = NULL; - int keyFormat = 0; - - WOLFSSL_ENTER("wolfSSL_PEM_read_PUBKEY"); - - if ((pem_read_file_key(fp, cb, pass, PUBLICKEY_TYPE, &keyFormat, &der) - >= 0) && (der != NULL)) { - const unsigned char* ptr = der->buffer; - - /* handle case where reuse is attempted */ - if ((key != NULL) && (*key != NULL)) { - pkey = *key; - } - - if ((wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length) == NULL) || - (pkey == NULL)) { - WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); - pkey = NULL; - } - } - - FreeDer(&der); - - if ((key != NULL) && (pkey != NULL)) { - *key = pkey; - } - - WOLFSSL_LEAVE("wolfSSL_PEM_read_PUBKEY", 0); - - return pkey; -} -#endif /* NO_FILESYSTEM */ -#endif /* OPENSSL_EXTRA */ - -#ifdef WOLFSSL_ALT_CERT_CHAINS -int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl) -{ - int isUsing = 0; - if (ssl) - isUsing = ssl->options.usingAltCertChain; - return isUsing; -} -#endif /* WOLFSSL_ALT_CERT_CHAINS */ - - -#ifdef SESSION_CERTS - -#ifdef WOLFSSL_ALT_CERT_CHAINS -/* Get peer's alternate certificate chain */ -WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); - if (ssl) - return &ssl->session->altChain; - - return 0; -} -#endif /* WOLFSSL_ALT_CERT_CHAINS */ - - -/* 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 = 0; - 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_DCERT); - 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"); - wolfSSL_X509_free(x509); - x509 = NULL; - } - } - } - - FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); - #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 WOLFSSL_SUCCESS on ok */ -int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, - unsigned char* buf, int inLen, int* outLen) -{ -#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) - const char* header = NULL; - const char* footer = NULL; - int headerLen; - int footerLen; - 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; - - err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer); - if (err != 0) - return err; - - headerLen = (int)XSTRLEN(header); - footerLen = (int)XSTRLEN(footer); - - /* 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 WOLFSSL_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 WOLFSSL_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 WOLFSSL_FATAL_ERROR; - *outLen += headerLen + footerLen; - - return WOLFSSL_SUCCESS; -#else - (void)chain; - (void)idx; - (void)buf; - (void)inLen; - (void)outLen; - return WOLFSSL_FAILURE; -#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ -} - - -/* get session ID */ -WOLFSSL_ABI -const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) -{ - WOLFSSL_ENTER("wolfSSL_get_sessionID"); - session = ClientSessionToSession(session); - 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_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb) -{ - if (ctx) - ctx->EccKeyGenCb = cb; -} -void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->EccKeyGenCtx = ctx; -} -void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->EccKeyGenCtx; - - return NULL; -} -void wolfSSL_CTX_SetEccSignCtx(WOLFSSL_CTX* ctx, void *userCtx) -{ - if (ctx) - ctx->EccSignCtx = userCtx; -} -void* wolfSSL_CTX_GetEccSignCtx(WOLFSSL_CTX* ctx) -{ - if (ctx) - return ctx->EccSignCtx; - - return NULL; -} - -WOLFSSL_ABI -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 */ - -#ifdef HAVE_ED25519 -void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb) -{ - if (ctx) - ctx->Ed25519SignCb = cb; -} -void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->Ed25519SignCtx = ctx; -} -void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->Ed25519SignCtx; - - return NULL; -} - -void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) -{ - if (ctx) - ctx->Ed25519VerifyCb = cb; -} -void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->Ed25519VerifyCtx = ctx; -} -void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->Ed25519VerifyCtx; - - return NULL; -} -#endif /* HAVE_ED25519 */ - -#ifdef HAVE_CURVE25519 -void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx, - CallbackX25519KeyGen cb) -{ - if (ctx) - ctx->X25519KeyGenCb = cb; -} -void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->X25519KeyGenCtx = ctx; -} -void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->X25519KeyGenCtx; - - return NULL; -} - -void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx, - CallbackX25519SharedSecret cb) -{ - if (ctx) - ctx->X25519SharedSecretCb = cb; -} -void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->X25519SharedSecretCtx = ctx; -} -void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->X25519SharedSecretCtx; - - return NULL; -} -#endif /* HAVE_CURVE25519 */ - -#ifdef HAVE_ED448 -void wolfSSL_CTX_SetEd448SignCb(WOLFSSL_CTX* ctx, CallbackEd448Sign cb) -{ - if (ctx) - ctx->Ed448SignCb = cb; -} -void wolfSSL_SetEd448SignCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->Ed448SignCtx = ctx; -} -void* wolfSSL_GetEd448SignCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->Ed448SignCtx; - - return NULL; -} - -void wolfSSL_CTX_SetEd448VerifyCb(WOLFSSL_CTX* ctx, CallbackEd448Verify cb) -{ - if (ctx) - ctx->Ed448VerifyCb = cb; -} -void wolfSSL_SetEd448VerifyCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->Ed448VerifyCtx = ctx; -} -void* wolfSSL_GetEd448VerifyCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->Ed448VerifyCtx; - - return NULL; -} -#endif /* HAVE_ED448 */ - -#ifdef HAVE_CURVE448 -void wolfSSL_CTX_SetX448KeyGenCb(WOLFSSL_CTX* ctx, - CallbackX448KeyGen cb) -{ - if (ctx) - ctx->X448KeyGenCb = cb; -} -void wolfSSL_SetX448KeyGenCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->X448KeyGenCtx = ctx; -} -void* wolfSSL_GetX448KeyGenCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->X448KeyGenCtx; - - return NULL; -} - -void wolfSSL_CTX_SetX448SharedSecretCb(WOLFSSL_CTX* ctx, - CallbackX448SharedSecret cb) -{ - if (ctx) - ctx->X448SharedSecretCb = cb; -} -void wolfSSL_SetX448SharedSecretCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->X448SharedSecretCtx = ctx; -} -void* wolfSSL_GetX448SharedSecretCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->X448SharedSecretCtx; - - return NULL; -} -#endif /* HAVE_CURVE448 */ - -#ifndef NO_RSA -void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) -{ - if (ctx) - ctx->RsaSignCb = cb; -} -void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) -{ - if (ctx) - ctx->RsaSignCheckCb = 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; -} - -#ifdef WC_RSA_PSS -void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb) -{ - if (ctx) - ctx->RsaPssSignCb = cb; -} -void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) -{ - if (ctx) - ctx->RsaPssSignCheckCb = cb; -} -void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->RsaPssSignCtx = ctx; -} -void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->RsaPssSignCtx; - - return NULL; -} - -void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) -{ - if (ctx) - ctx->RsaPssVerifyCb = cb; -} -void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->RsaPssVerifyCtx = ctx; -} -void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->RsaPssVerifyCtx; - - return NULL; -} -#endif /* WC_RSA_PSS */ - -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 */ - -/* callback for premaster secret generation */ -void wolfSSL_CTX_SetGenPreMasterCb(WOLFSSL_CTX* ctx, CallbackGenPreMaster cb) -{ - if (ctx) - ctx->GenPreMasterCb = cb; -} -/* Set premaster secret generation callback context */ -void wolfSSL_SetGenPreMasterCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->GenPreMasterCtx = ctx; -} -/* Get premaster secret generation callback context */ -void* wolfSSL_GetGenPreMasterCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->GenPreMasterCtx; - - return NULL; -} - -/* callback for master secret generation */ -void wolfSSL_CTX_SetGenMasterSecretCb(WOLFSSL_CTX* ctx, CallbackGenMasterSecret cb) -{ - if (ctx) - ctx->GenMasterCb = cb; -} -/* Set master secret generation callback context */ -void wolfSSL_SetGenMasterSecretCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->GenMasterCtx = ctx; -} -/* Get master secret generation callback context */ -void* wolfSSL_GetGenMasterSecretCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->GenMasterCtx; - - return NULL; -} - -/* callback for session key generation */ -void wolfSSL_CTX_SetGenSessionKeyCb(WOLFSSL_CTX* ctx, CallbackGenSessionKey cb) -{ - if (ctx) - ctx->GenSessionKeyCb = cb; -} -/* Set session key generation callback context */ -void wolfSSL_SetGenSessionKeyCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->GenSessionKeyCtx = ctx; -} -/* Get session key generation callback context */ -void* wolfSSL_GetGenSessionKeyCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->GenSessionKeyCtx; - - return NULL; -} - -/* callback for setting encryption keys */ -void wolfSSL_CTX_SetEncryptKeysCb(WOLFSSL_CTX* ctx, CallbackEncryptKeys cb) -{ - if (ctx) - ctx->EncryptKeysCb = cb; -} -/* Set encryption keys callback context */ -void wolfSSL_SetEncryptKeysCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->EncryptKeysCtx = ctx; -} -/* Get encryption keys callback context */ -void* wolfSSL_GetEncryptKeysCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->EncryptKeysCtx; - - return NULL; -} - -/* callback for Tls finished */ -/* the callback can be used to build TLS Finished message if enabled */ -void wolfSSL_CTX_SetTlsFinishedCb(WOLFSSL_CTX* ctx, CallbackTlsFinished cb) -{ - if (ctx) - ctx->TlsFinishedCb = cb; -} -/* Set Tls finished callback context */ -void wolfSSL_SetTlsFinishedCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->TlsFinishedCtx = ctx; -} -/* Get Tls finished callback context */ -void* wolfSSL_GetTlsFinishedCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->TlsFinishedCtx; - - return NULL; -} -#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) -/* callback for verify data */ -void wolfSSL_CTX_SetVerifyMacCb(WOLFSSL_CTX* ctx, CallbackVerifyMac cb) -{ - if (ctx) - ctx->VerifyMacCb = cb; -} - -/* Set set keys callback context */ -void wolfSSL_SetVerifyMacCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->VerifyMacCtx = ctx; -} -/* Get set keys callback context */ -void* wolfSSL_GetVerifyMacCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->VerifyMacCtx; - - return NULL; -} -#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ - -void wolfSSL_CTX_SetHKDFExpandLabelCb(WOLFSSL_CTX* ctx, - CallbackHKDFExpandLabel cb) -{ - if (ctx) - ctx->HKDFExpandLabelCb = cb; -} -#ifdef WOLFSSL_PUBLIC_ASN -void wolfSSL_CTX_SetProcessPeerCertCb(WOLFSSL_CTX* ctx, - CallbackProcessPeerCert cb) -{ - if (ctx) - ctx->ProcessPeerCertCb = cb; -} -#endif /* WOLFSSL_PUBLIC_ASN */ -void wolfSSL_CTX_SetProcessServerSigKexCb(WOLFSSL_CTX* ctx, - CallbackProcessServerSigKex cb) -{ - if (ctx) - ctx->ProcessServerSigKexCb = cb; -} -void wolfSSL_CTX_SetPerformTlsRecordProcessingCb(WOLFSSL_CTX* ctx, - CallbackPerformTlsRecordProcessing cb) -{ - if (ctx) - ctx->PerformTlsRecordProcessingCb = cb; -} -#endif /* HAVE_PK_CALLBACKS */ -#endif /* NO_CERTS */ - -#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH) -void wolfSSL_CTX_SetDhGenerateKeyPair(WOLFSSL_CTX* ctx, - CallbackDhGenerateKeyPair cb) { - if (ctx) - ctx->DhGenerateKeyPairCb = cb; -} -void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb) -{ - if (ctx) - ctx->DhAgreeCb = cb; -} -void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->DhAgreeCtx = ctx; -} -void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->DhAgreeCtx; - - return NULL; -} -#endif /* HAVE_PK_CALLBACKS && !NO_DH */ - -#if defined(HAVE_PK_CALLBACKS) && defined(HAVE_HKDF) - -void wolfSSL_CTX_SetHKDFExtractCb(WOLFSSL_CTX* ctx, CallbackHKDFExtract cb) -{ - if (ctx) - ctx->HkdfExtractCb = cb; -} - -void wolfSSL_SetHKDFExtractCtx(WOLFSSL* ssl, void *ctx) -{ - if (ssl) - ssl->HkdfExtractCtx = ctx; -} - -void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl) -{ - if (ssl) - return ssl->HkdfExtractCtx; - - return NULL; -} -#endif /* HAVE_PK_CALLBACKS && HAVE_HKDF */ - -#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 - -#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ - !defined(WOLFCRYPT_ONLY) -#ifndef NO_CERTS - -#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) -#if !defined(NO_FILESYSTEM) - WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_PrivateKey(XFILE fp, - WOLFSSL_EVP_PKEY **key, wc_pem_password_cb *cb, void *pass) - { - WOLFSSL_EVP_PKEY* pkey = NULL; - DerBuffer* der = NULL; - int keyFormat = 0; - - WOLFSSL_ENTER("wolfSSL_PEM_read_PrivateKey"); - - if (pem_read_file_key(fp, cb, pass, PRIVATEKEY_TYPE, &keyFormat, - &der) >= 0) { - const unsigned char* ptr = der->buffer; - int type = -1; - - if (keyFormat) { - /* keyFormat is Key_Sum enum */ - if (keyFormat == RSAk) - type = EVP_PKEY_RSA; - else if (keyFormat == ECDSAk) - type = EVP_PKEY_EC; - else if (keyFormat == DSAk) - type = EVP_PKEY_DSA; - else if (keyFormat == DHk) - type = EVP_PKEY_DH; - } - else { - /* Default to RSA if format is not set */ - type = EVP_PKEY_RSA; - } - - /* handle case where reuse is attempted */ - if (key != NULL && *key != NULL) - pkey = *key; - - wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length); - if (pkey == NULL) { - WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); - } - } - - FreeDer(&der); - - if (key != NULL && pkey != NULL) - *key = pkey; - - WOLFSSL_LEAVE("wolfSSL_PEM_read_PrivateKey", 0); - - return pkey; - } -#endif -#endif - -#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL*/ - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) - - #define PEM_BEGIN "-----BEGIN " - #define PEM_BEGIN_SZ 11 - #define PEM_END "-----END " - #define PEM_END_SZ 9 - #define PEM_HDR_FIN "-----" - #define PEM_HDR_FIN_SZ 5 - #define PEM_HDR_FIN_EOL_NEWLINE "-----\n" - #define PEM_HDR_FIN_EOL_NULL_TERM "-----\0" - #define PEM_HDR_FIN_EOL_SZ 6 - -#ifndef NO_BIO - - int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header, - unsigned char **data, long *len) - { - int ret = WOLFSSL_SUCCESS; - char pem[256]; - int pemLen; - char* p; - char* nameStr = NULL; - int nameLen = 0; - char* headerStr = NULL; - int headerFound = 0; - unsigned char* der = NULL; - word32 derLen = 0; - - if (bio == NULL || name == NULL || header == NULL || data == NULL || - len == NULL) { - return WOLFSSL_FAILURE; - } - - /* Find header line. */ - pem[sizeof(pem) - 1] = '\0'; - while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { - if (XSTRNCMP(pem, PEM_BEGIN, PEM_BEGIN_SZ) == 0) - break; - } - if (pemLen <= 0) - ret = WOLFSSL_FAILURE; - /* Have a header line. */ - if (ret == WOLFSSL_SUCCESS) { - while (pem[pemLen - 1] == '\r' || pem[pemLen - 1] == '\n') - pemLen--; - pem[pemLen] = '\0'; - if (XSTRNCMP(pem + pemLen - PEM_HDR_FIN_SZ, PEM_HDR_FIN, - PEM_HDR_FIN_SZ) != 0) { - ret = WOLFSSL_FAILURE; - } - } - - /* Get out name. */ - if (ret == WOLFSSL_SUCCESS) { - nameLen = pemLen - PEM_BEGIN_SZ - PEM_HDR_FIN_SZ; - nameStr = (char*)XMALLOC(nameLen + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (nameStr == NULL) - ret = WOLFSSL_FAILURE; - } - if (ret == WOLFSSL_SUCCESS) { - int headerLen; - - XSTRNCPY(nameStr, pem + PEM_BEGIN_SZ, nameLen); - nameStr[nameLen] = '\0'; - - /* Get header of PEM - encryption header. */ - headerLen = 0; - while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { - while (pemLen > 0 && (pem[pemLen - 1] == '\r' || - pem[pemLen - 1] == '\n')) { - pemLen--; - } - pem[pemLen++] = '\n'; - pem[pemLen] = '\0'; - - /* Header separator is a blank line. */ - if (pem[0] == '\n') { - headerFound = 1; - break; - } - - /* Didn't find a blank line - no header. */ - if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) { - der = (unsigned char*)headerStr; - derLen = headerLen; - /* Empty header - empty string. */ - headerStr = (char*)XMALLOC(1, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (headerStr == NULL) - ret = WOLFSSL_FAILURE; - else - headerStr[0] = '\0'; - break; - } - - p = (char*)XREALLOC(headerStr, headerLen + pemLen + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (p == NULL) { - ret = WOLFSSL_FAILURE; - break; - } - - headerStr = p; - XMEMCPY(headerStr + headerLen, pem, pemLen + 1); - headerLen += pemLen; - } - if (pemLen <= 0) - ret = WOLFSSL_FAILURE; - } - - /* Get body of PEM - if there was a header */ - if (ret == WOLFSSL_SUCCESS && headerFound) { - derLen = 0; - while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { - while (pemLen > 0 && (pem[pemLen - 1] == '\r' || - pem[pemLen - 1] == '\n')) { - pemLen--; - } - pem[pemLen++] = '\n'; - pem[pemLen] = '\0'; - - if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) - break; - - p = (char*)XREALLOC(der, derLen + pemLen + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (p == NULL) { - ret = WOLFSSL_FAILURE; - break; - } - - der = (unsigned char*)p; - XMEMCPY(der + derLen, pem, pemLen + 1); - derLen += pemLen; - } - if (pemLen <= 0) - ret = WOLFSSL_FAILURE; - } - - /* Check trailer. */ - if (ret == WOLFSSL_SUCCESS) { - if (XSTRNCMP(pem + PEM_END_SZ, nameStr, nameLen) != 0) - ret = WOLFSSL_FAILURE; - } - if (ret == WOLFSSL_SUCCESS) { - if (XSTRNCMP(pem + PEM_END_SZ + nameLen, - PEM_HDR_FIN_EOL_NEWLINE, - PEM_HDR_FIN_EOL_SZ) != 0 && - XSTRNCMP(pem + PEM_END_SZ + nameLen, - PEM_HDR_FIN_EOL_NULL_TERM, - PEM_HDR_FIN_EOL_SZ) != 0) { - ret = WOLFSSL_FAILURE; - } - } - - /* Base64 decode body. */ - if (ret == WOLFSSL_SUCCESS) { - if (Base64_Decode(der, derLen, der, &derLen) != 0) - ret = WOLFSSL_FAILURE; - } - - if (ret == WOLFSSL_SUCCESS) { - *name = nameStr; - *header = headerStr; - *data = der; - *len = derLen; - nameStr = NULL; - headerStr = NULL; - der = NULL; - } - - if (nameStr != NULL) - XFREE(nameStr, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (headerStr != NULL) - XFREE(headerStr, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (der != NULL) - XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return ret; - } - - int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name, - const char *header, const unsigned char *data, - long len) - { - int err = 0; - int outSz = 0; - int nameLen; - int headerLen; - byte* pem = NULL; - word32 pemLen; - word32 derLen = (word32)len; - - if (bio == NULL || name == NULL || header == NULL || data == NULL) - return 0; - - nameLen = (int)XSTRLEN(name); - headerLen = (int)XSTRLEN(header); - - pemLen = (derLen + 2) / 3 * 4; - pemLen += (pemLen + 63) / 64; - - pem = (byte*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); - err = pem == NULL; - if (!err) - err = Base64_Encode(data, derLen, pem, &pemLen) != 0; - - if (!err) { - err = wolfSSL_BIO_write(bio, PEM_BEGIN, PEM_BEGIN_SZ) != - (int)PEM_BEGIN_SZ; - } - if (!err) - err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen; - if (!err) { - err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE, - PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ; - } - if (!err && headerLen > 0) { - err = wolfSSL_BIO_write(bio, header, headerLen) != headerLen; - /* Blank line after a header and before body. */ - if (!err) - err = wolfSSL_BIO_write(bio, "\n", 1) != 1; - headerLen++; - } - if (!err) - err = wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen; - if (!err) - err = wolfSSL_BIO_write(bio, PEM_END, PEM_END_SZ) != - (int)PEM_END_SZ; - if (!err) - err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen; - if (!err) { - err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL_NEWLINE, - PEM_HDR_FIN_EOL_SZ) != (int)PEM_HDR_FIN_EOL_SZ; - } - - if (!err) { - outSz = PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ + headerLen + - pemLen + PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ; - } - - if (pem != NULL) - XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return outSz; - } - -#if !defined(NO_FILESYSTEM) - int wolfSSL_PEM_read(XFILE fp, char **name, char **header, - unsigned char **data, long *len) - { - int ret; - WOLFSSL_BIO* bio; - - if (name == NULL || header == NULL || data == NULL || len == NULL) - return WOLFSSL_FAILURE; - - bio = wolfSSL_BIO_new_fp(fp, BIO_NOCLOSE); - if (bio == NULL) - return 0; - - ret = wolfSSL_PEM_read_bio(bio, name, header, data, len); - - if (bio != NULL) - wolfSSL_BIO_free(bio); - - return ret; - } - - int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header, - const unsigned char *data, long len) - { - int ret; - WOLFSSL_BIO* bio; - - if (name == NULL || header == NULL || data == NULL) - return 0; - - bio = wolfSSL_BIO_new_fp(fp, BIO_NOCLOSE); - if (bio == NULL) - return 0; - - ret = wolfSSL_PEM_write_bio(bio, name, header, data, len); - - if (bio != NULL) - wolfSSL_BIO_free(bio); - - return ret; - } -#endif -#endif /* !NO_BIO */ - - int wolfSSL_PEM_get_EVP_CIPHER_INFO(const char* header, - EncryptedInfo* cipher) - { - if (header == NULL || cipher == NULL) - return WOLFSSL_FAILURE; - - XMEMSET(cipher, 0, sizeof(*cipher)); - - if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0) - return WOLFSSL_FAILURE; - - return WOLFSSL_SUCCESS; - } - - int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data, - long* len, wc_pem_password_cb* callback, - void* ctx) - { - int ret = WOLFSSL_SUCCESS; - char password[NAME_SZ]; - int passwordSz; - - if (cipher == NULL || data == NULL || len == NULL || callback == NULL) - return WOLFSSL_FAILURE; - - passwordSz = callback(password, sizeof(password), PEM_PASS_READ, ctx); - if (passwordSz < 0) - ret = WOLFSSL_FAILURE; - - if (ret == WOLFSSL_SUCCESS) { - if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password, - passwordSz, WC_MD5) != 0) { - ret = WOLFSSL_FAILURE; - } - } - - if (passwordSz > 0) - XMEMSET(password, 0, passwordSz); - - return ret; - } - -#ifndef NO_BIO - /* - * 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, wc_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 - * readability and does not support extra trusted/rejected uses for - * root CA. */ - return wolfSSL_PEM_read_bio_X509(bp, x, cb, u); - } -#endif /* !NO_BIO */ - - -#endif /* OPENSSL_EXTRA || OPENSSL_ALL */ -#endif /* !NO_CERTS */ - - /* NID variables are dependent on compatibility header files currently - * - * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL - * on fail - */ - - WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id) - { - return wolfSSL_OBJ_nid2obj_ex(id, NULL); - } - - - WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id, - WOLFSSL_ASN1_OBJECT* arg_obj) - { - word32 oidSz = 0; - int nid = 0; - const byte* oid; - word32 type = 0; - WOLFSSL_ASN1_OBJECT* obj = arg_obj; - byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */ - word32 objSz = 0; - const char* sName = NULL; - int i; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj"); -#endif - - for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { - if (wolfssl_object_info[i].nid == id) { - nid = id; - id = wolfssl_object_info[i].id; - sName = wolfssl_object_info[i].sName; - type = wolfssl_object_info[i].type; - break; - } - } - if (i == (int)WOLFSSL_OBJECT_INFO_SZ) { - WOLFSSL_MSG("NID not in table"); - #ifdef WOLFSSL_QT - sName = NULL; - type = id; - #else - return NULL; - #endif - } - - #ifdef HAVE_ECC - if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) { - type = oidCurveType; - } - #endif /* HAVE_ECC */ - - if (sName != NULL) { - if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) { - WOLFSSL_MSG("Attempted short name is too large"); - return NULL; - } - } - - oid = OidFromId(id, type, &oidSz); - - /* set object ID to buffer */ - if (obj == NULL){ - obj = wolfSSL_ASN1_OBJECT_new(); - if (obj == NULL) { - WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); - return NULL; - } - } - obj->nid = nid; - obj->type = id; - obj->grp = type; - - obj->sName[0] = '\0'; - if (sName != NULL) { - XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName)); - } - - objBuf[0] = ASN_OBJECT_ID; objSz++; - objSz += SetLength(oidSz, objBuf + 1); - if (oidSz) { - XMEMCPY(objBuf + objSz, oid, oidSz); - objSz += oidSz; - } - - if (obj->objSz == 0 || objSz != obj->objSz) { - obj->objSz = objSz; - if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || - (obj->obj == NULL)) { - if (obj->obj != NULL) - XFREE((byte*)obj->obj, NULL, DYNAMIC_TYPE_ASN1); - obj->obj = (byte*)XMALLOC(obj->objSz, NULL, DYNAMIC_TYPE_ASN1); - if (obj->obj == NULL) { - wolfSSL_ASN1_OBJECT_free(obj); - return NULL; - } - obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ; - } - else { - obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ; - } - } - XMEMCPY((byte*)obj->obj, objBuf, obj->objSz); - - (void)type; - - return obj; - } - - static const char* oid_translate_num_to_str(const char* oid) - { - const struct oid_dict { - const char* num; - const char* desc; - } oid_dict[] = { - { "2.5.29.37.0", "Any Extended Key Usage" }, - { "1.3.6.1.5.5.7.3.1", "TLS Web Server Authentication" }, - { "1.3.6.1.5.5.7.3.2", "TLS Web Client Authentication" }, - { "1.3.6.1.5.5.7.3.3", "Code Signing" }, - { "1.3.6.1.5.5.7.3.4", "E-mail Protection" }, - { "1.3.6.1.5.5.7.3.8", "Time Stamping" }, - { "1.3.6.1.5.5.7.3.9", "OCSP Signing" }, - { NULL, NULL } - }; - const struct oid_dict* idx; - - for (idx = oid_dict; idx->num != NULL; idx++) { - if (!XSTRCMP(oid, idx->num)) { - return idx->desc; - } - } - return NULL; - } - - static int wolfssl_obj2txt_numeric(char *buf, int bufLen, - const WOLFSSL_ASN1_OBJECT *a) - { - int bufSz; - int length; - word32 idx = 0; - byte tag; - - if (GetASNTag(a->obj, &idx, &tag, a->objSz) != 0) { - return WOLFSSL_FAILURE; - } - - if (tag != ASN_OBJECT_ID) { - WOLFSSL_MSG("Bad ASN1 Object"); - return WOLFSSL_FAILURE; - } - - if (GetLength((const byte*)a->obj, &idx, &length, - a->objSz) < 0 || length < 0) { - return ASN_PARSE_E; - } - - if (bufLen < MAX_OID_STRING_SZ) { - bufSz = bufLen - 1; - } - else { - bufSz = MAX_OID_STRING_SZ; - } - - if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx, - (word32)length)) <= 0) { - WOLFSSL_MSG("Error decoding OID"); - return WOLFSSL_FAILURE; - } - - buf[bufSz] = '\0'; - - return bufSz; - } - - /* If no_name is one then use numerical form, otherwise short name. - * - * Returns the buffer size on success, WOLFSSL_FAILURE on error - */ - int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, const WOLFSSL_ASN1_OBJECT *a, - int no_name) - { - int bufSz; - const char* desc; - const char* name; - - WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt"); - - if (buf == NULL || bufLen <= 1 || a == NULL) { - WOLFSSL_MSG("Bad input argument"); - return WOLFSSL_FAILURE; - } - - if (no_name == 1) { - return wolfssl_obj2txt_numeric(buf, bufLen, a); - } - - /* return long name unless using x509small, then return short name */ -#if defined(OPENSSL_EXTRA_X509_SMALL) && !defined(OPENSSL_EXTRA) - name = a->sName; -#else - name = wolfSSL_OBJ_nid2ln(wolfSSL_OBJ_obj2nid(a)); -#endif - - if (name == NULL) { - WOLFSSL_MSG("Name not found"); - bufSz = 0; - } - else if (XSTRLEN(name) + 1 < (word32)bufLen - 1) { - bufSz = (int)XSTRLEN(name); - } - else { - bufSz = bufLen - 1; - } - if (bufSz) { - XMEMCPY(buf, name, bufSz); - } - else if (a->type == GEN_DNS || a->type == GEN_EMAIL || - a->type == GEN_URI) { - bufSz = (int)XSTRLEN((const char*)a->obj); - XMEMCPY(buf, a->obj, min(bufSz, bufLen)); - } - else if ((bufSz = wolfssl_obj2txt_numeric(buf, bufLen, a)) > 0) { - if ((desc = oid_translate_num_to_str(buf))) { - bufSz = (int)XSTRLEN(desc); - bufSz = min(bufSz, bufLen - 1); - XMEMCPY(buf, desc, bufSz); - } - } - else { - bufSz = 0; - } - - buf[bufSz] = '\0'; - - return bufSz; - } -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - -#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ - defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS_SMALL) - /* Returns the long name that corresponds with an ASN1_OBJECT nid value. - * n : NID value of ASN1_OBJECT to search */ - const char* wolfSSL_OBJ_nid2ln(int n) - { - const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; - size_t i; - WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); - for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { - if (obj_info->nid == n) { - return obj_info->lName; - } - } - WOLFSSL_MSG("NID not found in table"); - return NULL; - } -#endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL, - WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY, WOLFSSL_WPAS_SMALL */ - -#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ - defined(WOLFSSL_HAPROXY) - char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) - { - int ret; - - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); - if (!ctx || !x || !x->derCert) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - - FreeDer(&ctx->certificate); /* Make sure previous is free'd */ - ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE, - ctx->heap); - if (ret != 0) - return WOLFSSL_FAILURE; - - XMEMCPY(ctx->certificate->buffer, x->derCert->buffer, - x->derCert->length); -#ifdef KEEP_OUR_CERT - if (ctx->ourCert != NULL && ctx->ownOurCert) { - wolfSSL_X509_free(ctx->ourCert); - } - #ifndef WOLFSSL_X509_STORE_CERTS - ctx->ourCert = x; - if (wolfSSL_X509_up_ref(x) != 1) { - return WOLFSSL_FAILURE; - } - #else - ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, x->derCert->buffer, - x->derCert->length, ctx->heap); - if(ctx->ourCert == NULL){ - return WOLFSSL_FAILURE; - } - #endif - - /* We own the cert because either we up its reference counter - * or we create our own copy of the cert object. */ - ctx->ownOurCert = 1; -#endif - - /* Update the available options with public keys. */ - switch (x->pubKeyOID) { - #ifndef NO_RSA - #ifdef WC_RSA_PSS - case RSAPSSk: - #endif - case RSAk: - ctx->haveRSA = 1; - break; - #endif - #ifdef HAVE_ED25519 - case ED25519k: - #endif - #ifdef HAVE_ED448 - case ED448k: - #endif - case ECDSAk: - ctx->haveECC = 1; - #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) - ctx->pkCurveOID = x->pkCurveOID; - #endif - break; - } - - return WOLFSSL_SUCCESS; - } - - static int PushCertToDerBuffer(DerBuffer** inOutDer, int weOwn, - byte* cert, word32 certSz, void* heap) - { - int ret; - DerBuffer* inChain = NULL; - DerBuffer* der = NULL; - word32 len = 0; - if (inOutDer == NULL) - return BAD_FUNC_ARG; - inChain = *inOutDer; - if (inChain != NULL) - len = inChain->length; - ret = AllocDer(&der, len + CERT_HEADER_SZ + certSz, CERT_TYPE, - heap); - if (ret != 0) { - WOLFSSL_MSG("AllocDer error"); - return ret; - } - if (inChain != NULL) - XMEMCPY(der->buffer, inChain->buffer, len); - c32to24(certSz, der->buffer + len); - XMEMCPY(der->buffer + len + CERT_HEADER_SZ, cert, certSz); - if (weOwn) - FreeDer(inOutDer); - *inOutDer = der; - return WOLFSSL_SUCCESS; - } - - /** - * wolfSSL_CTX_add1_chain_cert makes a copy of the cert so we free it - * on success - */ - int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) - { - WOLFSSL_ENTER("wolfSSL_CTX_add0_chain_cert"); - if (wolfSSL_CTX_add1_chain_cert(ctx, x509) != WOLFSSL_SUCCESS) { - return WOLFSSL_FAILURE; - } - wolfSSL_X509_free(x509); - return WOLFSSL_SUCCESS; - } - - int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) - { - int ret; - WOLFSSL_ENTER("wolfSSL_CTX_add1_chain_cert"); - if (ctx == NULL || x509 == NULL || x509->derCert == NULL) { - return WOLFSSL_FAILURE; - } - - if (ctx->certificate == NULL) - ret = (int)wolfSSL_CTX_use_certificate(ctx, x509); - else { - if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_up_ref error"); - return WOLFSSL_FAILURE; - } - ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer, - x509->derCert->length, WOLFSSL_FILETYPE_ASN1); - if (ret == WOLFSSL_SUCCESS) { - /* push to ctx->certChain */ - ret = PushCertToDerBuffer(&ctx->certChain, 1, - x509->derCert->buffer, x509->derCert->length, ctx->heap); - } - /* Store cert to free it later */ - if (ret == WOLFSSL_SUCCESS && ctx->x509Chain == NULL) { - ctx->x509Chain = wolfSSL_sk_X509_new_null(); - if (ctx->x509Chain == NULL) { - WOLFSSL_MSG("wolfSSL_sk_X509_new_null error"); - ret = WOLFSSL_FAILURE; - } - } - if (ret == WOLFSSL_SUCCESS && - wolfSSL_sk_X509_push(ctx->x509Chain, x509) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_X509_push error"); - ret = WOLFSSL_FAILURE; - } - if (ret != WOLFSSL_SUCCESS) - wolfSSL_X509_free(x509); /* Decrease ref counter */ - } - - return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; - } - -#ifdef KEEP_OUR_CERT - int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509) - { - int ret; - - WOLFSSL_ENTER("wolfSSL_add0_chain_cert"); - - if (ssl == NULL || ssl->ctx == NULL || x509 == NULL || - x509->derCert == NULL) - return WOLFSSL_FAILURE; - - if (ssl->buffers.certificate == NULL) { - ret = wolfSSL_use_certificate(ssl, x509); - /* Store cert to free it later */ - if (ret == WOLFSSL_SUCCESS) { - if (ssl->buffers.weOwnCert) - wolfSSL_X509_free(ssl->ourCert); - ssl->ourCert = x509; - ssl->buffers.weOwnCert = 1; - } - } - else { - ret = PushCertToDerBuffer(&ssl->buffers.certChain, - ssl->buffers.weOwnCertChain, x509->derCert->buffer, - x509->derCert->length, ssl->heap); - if (ret == WOLFSSL_SUCCESS) { - ssl->buffers.weOwnCertChain = 1; - /* Store cert to free it later */ - if (ssl->ourCertChain == NULL) { - ssl->ourCertChain = wolfSSL_sk_X509_new_null(); - if (ssl->ourCertChain == NULL) { - WOLFSSL_MSG("wolfSSL_sk_X509_new_null error"); - return WOLFSSL_FAILURE; - } - } - if (wolfSSL_sk_X509_push(ssl->ourCertChain, x509) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_X509_push error"); - return WOLFSSL_FAILURE; - } - } - } - return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; - } - - int wolfSSL_add1_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509) - { - int ret; - - WOLFSSL_ENTER("wolfSSL_add1_chain_cert"); - if (ssl == NULL || ssl->ctx == NULL || x509 == NULL || - x509->derCert == NULL) - return WOLFSSL_FAILURE; - - if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_X509_up_ref error"); - return WOLFSSL_FAILURE; - } - ret = wolfSSL_add0_chain_cert(ssl, x509); - /* Decrease ref counter on error */ - if (ret != WOLFSSL_SUCCESS) - wolfSSL_X509_free(x509); - return ret; - } -#endif - - /* Return the corresponding short name for the nid . - * or NULL if short name can't be found. - */ - const char * wolfSSL_OBJ_nid2sn(int n) { - const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; - size_t i; - WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn"); - - if (n == NID_md5) { - /* NID_surname == NID_md5 and NID_surname comes before NID_md5 in - * wolfssl_object_info. As a result, the loop below will incorrectly - * return "SN" instead of "MD5." NID_surname isn't the true OpenSSL - * NID, but other functions rely on this table and modifying it to - * conform with OpenSSL's NIDs isn't trivial. */ - return "MD5"; - } - for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { - if (obj_info->nid == n) { - return obj_info->sName; - } - } - WOLFSSL_MSG_EX("SN not found (nid:%d)",n); - return NULL; - } - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - int wolfSSL_OBJ_sn2nid(const char *sn) { - WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid"); - if (sn == NULL) - return NID_undef; - return wc_OBJ_sn2nid(sn); - } -#endif - - size_t wolfSSL_OBJ_length(const WOLFSSL_ASN1_OBJECT* o) - { - size_t ret = 0; - int err = 0; - word32 idx = 0; - int len = 0; - - WOLFSSL_ENTER("wolfSSL_OBJ_length"); - - if (o == NULL || o->obj == NULL) { - WOLFSSL_MSG("Bad argument."); - err = 1; - } - - if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) { - WOLFSSL_MSG("Error parsing ASN.1 header."); - err = 1; - } - if (err == 0) { - ret = len; - } - - WOLFSSL_LEAVE("wolfSSL_OBJ_length", (int)ret); - - return ret; - } - - const unsigned char* wolfSSL_OBJ_get0_data(const WOLFSSL_ASN1_OBJECT* o) - { - const unsigned char* ret = NULL; - int err = 0; - word32 idx = 0; - int len = 0; - - WOLFSSL_ENTER("wolfSSL_OBJ_get0_data"); - - if (o == NULL || o->obj == NULL) { - WOLFSSL_MSG("Bad argument."); - err = 1; - } - - if (err == 0 && GetASNObjectId(o->obj, &idx, &len, o->objSz)) { - WOLFSSL_MSG("Error parsing ASN.1 header."); - err = 1; - } - if (err == 0) { - ret = o->obj + idx; - } - - return ret; - } - - - /* Gets the NID value that corresponds with the ASN1 object. - * - * o ASN1 object to get NID of - * - * Return NID on success and a negative value on failure - */ - int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) - { - word32 oid = 0; - word32 idx = 0; - int ret; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); -#endif - - if (o == NULL) { - return -1; - } - - #ifdef WOLFSSL_QT - if (o->grp == oidCertExtType) { - /* If nid is an unknown extension, return NID_undef */ - if (wolfSSL_OBJ_nid2sn(o->nid) == NULL) - return NID_undef; - } - #endif - - if (o->nid > 0) - return o->nid; - if ((ret = GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz)) < 0) { - if (ret == ASN_OBJECT_ID_E) { - /* Put ASN object tag in front and try again */ - int len = SetObjectId(o->objSz, NULL) + o->objSz; - byte* buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!buf) { - WOLFSSL_MSG("malloc error"); - return -1; - } - idx = SetObjectId(o->objSz, buf); - XMEMCPY(buf + idx, o->obj, o->objSz); - idx = 0; - ret = GetObjectId(buf, &idx, &oid, o->grp, len); - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ret < 0) { - WOLFSSL_MSG("Issue getting OID of object"); - return -1; - } - } - else { - WOLFSSL_MSG("Issue getting OID of object"); - return -1; - } - } - - return oid2nid(oid, o->grp); - } - - /* Return the corresponding NID for the long name - * or NID_undef if NID can't be found. - */ - int wolfSSL_OBJ_ln2nid(const char *ln) - { - const WOLFSSL_ObjectInfo *obj_info = wolfssl_object_info; - size_t lnlen; - WOLFSSL_ENTER("wolfSSL_OBJ_ln2nid"); - if (ln && (lnlen = XSTRLEN(ln)) > 0) { - /* Accept input like "/commonName=" */ - if (ln[0] == '/') { - ln++; - lnlen--; - } - if (lnlen) { - size_t i; - - if (ln[lnlen-1] == '=') { - lnlen--; - } - for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++, obj_info++) { - if (lnlen == XSTRLEN(obj_info->lName) && - XSTRNCMP(ln, obj_info->lName, lnlen) == 0) { - return obj_info->nid; - } - } - } - } - return NID_undef; - } - - /* compares two objects, return 0 if equal */ - int wolfSSL_OBJ_cmp(const WOLFSSL_ASN1_OBJECT* a, - const WOLFSSL_ASN1_OBJECT* b) - { - WOLFSSL_ENTER("wolfSSL_OBJ_cmp"); - - if (a && b && a->obj && b->obj) { - if (a->objSz == b->objSz) { - return XMEMCMP(a->obj, b->obj, a->objSz); - } - else if (a->type == EXT_KEY_USAGE_OID || - b->type == EXT_KEY_USAGE_OID) { - /* Special case for EXT_KEY_USAGE_OID so that - * cmp will be treated as a substring search */ - /* Used in libest to check for id-kp-cmcRA in - * EXT_KEY_USAGE extension */ - unsigned int idx; - const byte* s; /* shorter */ - unsigned int sLen; - const byte* l; /* longer */ - unsigned int lLen; - if (a->objSz > b->objSz) { - s = b->obj; sLen = b->objSz; - l = a->obj; lLen = a->objSz; - } - else { - s = a->obj; sLen = a->objSz; - l = b->obj; lLen = b->objSz; - } - for (idx = 0; idx <= lLen - sLen; idx++) { - if (XMEMCMP(l + idx, s, sLen) == 0) { - /* Found substring */ - return 0; - } - } - } - } - - return WOLFSSL_FATAL_ERROR; - } -#endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL, - WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY */ -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ - defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ - defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ - defined(HAVE_POCO_LIB) || defined(WOLFSSL_HAPROXY) - /* Gets the NID value that is related to the OID string passed in. Example - * string would be "2.5.29.14" for subject key ID. - * - * returns NID value on success and NID_undef on error - */ - int wolfSSL_OBJ_txt2nid(const char* s) - { - unsigned int i; - #ifdef WOLFSSL_CERT_EXT - int ret; - unsigned int sum = 0; - unsigned int outSz = MAX_OID_SZ; - unsigned char out[MAX_OID_SZ]; - #endif - - WOLFSSL_ENTER("wolfSSL_OBJ_txt2nid"); - - if (s == NULL) { - return NID_undef; - } - - #ifdef WOLFSSL_CERT_EXT - ret = EncodePolicyOID(out, &outSz, s, NULL); - if (ret == 0) { - /* sum OID */ - for (i = 0; i < outSz; i++) { - sum += out[i]; - } - } - #endif /* WOLFSSL_CERT_EXT */ - - /* get the group that the OID's sum is in - * @TODO possible conflict with multiples */ - for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) { - int len; - #ifdef WOLFSSL_CERT_EXT - if (ret == 0) { - if (wolfssl_object_info[i].id == (int)sum) { - return wolfssl_object_info[i].nid; - } - } - #endif - - /* try as a short name */ - len = (int)XSTRLEN(s); - if ((int)XSTRLEN(wolfssl_object_info[i].sName) == len && - XSTRNCMP(wolfssl_object_info[i].sName, s, len) == 0) { - return wolfssl_object_info[i].nid; - } - - /* try as a long name */ - if ((int)XSTRLEN(wolfssl_object_info[i].lName) == len && - XSTRNCMP(wolfssl_object_info[i].lName, s, len) == 0) { - return wolfssl_object_info[i].nid; - } - } - - return NID_undef; - } -#endif -#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ - defined(WOLFSSL_HAPROXY) - - /* Creates new ASN1_OBJECT from short name, long name, or text - * representation of oid. If no_name is 0, then short name, long name, and - * numerical value of oid are interpreted. If no_name is 1, then only the - * numerical value of the oid is interpreted. - * - * Returns pointer to ASN1_OBJECT on success, or NULL on error. - */ -#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) - WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_txt2obj(const char* s, int no_name) - { - int i, ret; - int nid = NID_undef; - unsigned int outSz = MAX_OID_SZ; - unsigned char out[MAX_OID_SZ]; - WOLFSSL_ASN1_OBJECT* obj; - - WOLFSSL_ENTER("wolfSSL_OBJ_txt2obj"); - - if (s == NULL) - return NULL; - - /* If s is numerical value, try to sum oid */ - ret = EncodePolicyOID(out, &outSz, s, NULL); - if (ret == 0 && outSz > 0) { - /* If numerical encode succeeded then just - * create object from that because sums are - * not unique and can cause confusion. */ - obj = wolfSSL_ASN1_OBJECT_new(); - if (obj == NULL) { - WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); - return NULL; - } - obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; - obj->obj = (byte*)XMALLOC(1 + MAX_LENGTH_SZ + outSz, NULL, - DYNAMIC_TYPE_ASN1); - if (obj->obj == NULL) { - wolfSSL_ASN1_OBJECT_free(obj); - return NULL; - } - obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ; - i = SetObjectId(outSz, (byte*)obj->obj); - XMEMCPY((byte*)obj->obj + i, out, outSz); - obj->objSz = i + outSz; - return obj; - } - - /* TODO: update short names in wolfssl_object_info and check OID sums - are correct */ - for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { - /* Short name, long name, and numerical value are interpreted */ - if (no_name == 0 && - ((XSTRCMP(s, wolfssl_object_info[i].sName) == 0) || - (XSTRCMP(s, wolfssl_object_info[i].lName) == 0))) - { - nid = wolfssl_object_info[i].nid; - } - } - - if (nid != NID_undef) - return wolfSSL_OBJ_nid2obj(nid); - - return NULL; - } -#endif - - /* compatibility function. Its intended use is to remove OID's from an - * internal table that have been added with OBJ_create. wolfSSL manages its - * own internal OID values and does not currently support OBJ_create. */ - void wolfSSL_OBJ_cleanup(void) - { - WOLFSSL_ENTER("wolfSSL_OBJ_cleanup"); - } - - #ifndef NO_WOLFSSL_STUB - int wolfSSL_OBJ_create(const char *oid, const char *sn, const char *ln) - { - (void)oid; - (void)sn; - (void)ln; - WOLFSSL_STUB("wolfSSL_OBJ_create"); - return WOLFSSL_FAILURE; - } - #endif - - void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) - { - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - WOLFSSL_ENTER("wolfSSL_set_verify_depth"); - ssl->options.verifyDepth = (byte)depth; - #endif - } - -#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || - HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ - -#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; -#ifdef WOLFSSL_HAVE_ERROR_QUEUE - { - int ret; - - if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { - WOLFSSL_MSG("Issue peeking at error node in queue"); - return 0; - } - #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) \ - || defined(WOLFSSL_HAPROXY) - if (ret == -ASN_NO_PEM_HEADER) - return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; - #endif - #if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) - if (ret == ASN1_R_HEADER_TOO_LONG) { - return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; - } - #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 WOLFSSL_FAILURE; - } - - switch (pkey->type) { -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) - case EVP_PKEY_RSA: - WOLFSSL_MSG("populating RSA key"); - if (PopulateRSAEvpPkeyDer(pkey) != WOLFSSL_SUCCESS) - return WOLFSSL_FAILURE; - break; -#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA */ -#if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \ - defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA) - case EVP_PKEY_DSA: - break; -#endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) && !NO_DSA */ -#ifdef HAVE_ECC - case EVP_PKEY_EC: - WOLFSSL_MSG("populating ECC key"); - if (ECC_populate_EVP_PKEY(pkey, pkey->ecc) - != WOLFSSL_SUCCESS) - return WOLFSSL_FAILURE; - break; -#endif - default: - return WOLFSSL_FAILURE; - } - - if (pkey->pkey.ptr != NULL) { - /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */ - return wolfSSL_CTX_use_PrivateKey_buffer(ctx, - (const unsigned char*)pkey->pkey.ptr, - pkey->pkey_sz, SSL_FILETYPE_ASN1); - } - - WOLFSSL_MSG("wolfSSL private key not set"); - return BAD_FUNC_ARG; -} -#endif /* !NO_CERTS */ - -#endif /* OPENSSL_EXTRA */ - -#if defined(HAVE_EX_DATA) && \ - (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ - defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || \ - defined(WOLFSSL_WPAS_SMALL) -CRYPTO_EX_cb_ctx* crypto_ex_cb_ctx_session = NULL; - -static int crypto_ex_cb_new(CRYPTO_EX_cb_ctx** dst, long ctx_l, void* ctx_ptr, - WOLFSSL_CRYPTO_EX_new* new_func, WOLFSSL_CRYPTO_EX_dup* dup_func, - WOLFSSL_CRYPTO_EX_free* free_func) -{ - CRYPTO_EX_cb_ctx* new_ctx = (CRYPTO_EX_cb_ctx*)XMALLOC( - sizeof(CRYPTO_EX_cb_ctx), NULL, DYNAMIC_TYPE_OPENSSL); - if (new_ctx == NULL) - return -1; - new_ctx->ctx_l = ctx_l; - new_ctx->ctx_ptr = ctx_ptr; - new_ctx->new_func = new_func; - new_ctx->free_func = free_func; - new_ctx->dup_func = dup_func; - new_ctx->next = NULL; - /* Push to end of list */ - while (*dst != NULL) - dst = &(*dst)->next; - *dst = new_ctx; - return 0; -} - -void crypto_ex_cb_free(CRYPTO_EX_cb_ctx* cb_ctx) -{ - while (cb_ctx != NULL) { - CRYPTO_EX_cb_ctx* next = cb_ctx->next; - XFREE(cb_ctx, NULL, DYNAMIC_TYPE_OPENSSL); - cb_ctx = next; - } -} - -void crypto_ex_cb_setup_new_data(void *new_obj, CRYPTO_EX_cb_ctx* cb_ctx, - WOLFSSL_CRYPTO_EX_DATA* ex_data) -{ - int idx = 0; - for (; cb_ctx != NULL; idx++, cb_ctx = cb_ctx->next) { - if (cb_ctx->new_func != NULL) - cb_ctx->new_func(new_obj, NULL, ex_data, idx, cb_ctx->ctx_l, - cb_ctx->ctx_ptr); - } -} - -int crypto_ex_cb_dup_data(const WOLFSSL_CRYPTO_EX_DATA *in, - WOLFSSL_CRYPTO_EX_DATA *out, CRYPTO_EX_cb_ctx* cb_ctx) -{ - int idx = 0; - for (; cb_ctx != NULL; idx++, cb_ctx = cb_ctx->next) { - if (cb_ctx->dup_func != NULL) { - void* ptr = wolfSSL_CRYPTO_get_ex_data(in, idx); - if (!cb_ctx->dup_func(out, in, - &ptr, idx, - cb_ctx->ctx_l, cb_ctx->ctx_ptr)) { - return WOLFSSL_FAILURE; - } - wolfSSL_CRYPTO_set_ex_data(out, idx, ptr); - } - } - return WOLFSSL_SUCCESS; -} - -void crypto_ex_cb_free_data(void *obj, CRYPTO_EX_cb_ctx* cb_ctx, - WOLFSSL_CRYPTO_EX_DATA* ex_data) -{ - int idx = 0; - for (; cb_ctx != NULL; idx++, cb_ctx = cb_ctx->next) { - if (cb_ctx->free_func != NULL) - cb_ctx->free_func(obj, NULL, ex_data, idx, cb_ctx->ctx_l, - cb_ctx->ctx_ptr); - } -} - -/** - * get_ex_new_index is a helper function for the following - * xx_get_ex_new_index functions: - * - wolfSSL_CRYPTO_get_ex_new_index - * - wolfSSL_CTX_get_ex_new_index - * - wolfSSL_get_ex_new_index - * Issues a unique index number for the specified class-index. - * Returns an index number greater or equal to zero on success, - * -1 on failure. - */ -int wolfssl_get_ex_new_index(int class_index, long ctx_l, void* ctx_ptr, - WOLFSSL_CRYPTO_EX_new* new_func, WOLFSSL_CRYPTO_EX_dup* dup_func, - WOLFSSL_CRYPTO_EX_free* free_func) -{ - /* index counter for each class index*/ - static int ctx_idx = 0; - static int ssl_idx = 0; - static int ssl_session_idx = 0; - static int x509_idx = 0; - - int idx = -1; - - switch(class_index) { - case WOLF_CRYPTO_EX_INDEX_SSL: - WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(ctx_l, ctx_ptr, new_func, - dup_func, free_func); - idx = ssl_idx++; - break; - case WOLF_CRYPTO_EX_INDEX_SSL_CTX: - WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(ctx_l, ctx_ptr, new_func, - dup_func, free_func); - idx = ctx_idx++; - break; - case WOLF_CRYPTO_EX_INDEX_X509: - WOLFSSL_CRYPTO_EX_DATA_IGNORE_PARAMS(ctx_l, ctx_ptr, new_func, - dup_func, free_func); - idx = x509_idx++; - break; - case WOLF_CRYPTO_EX_INDEX_SSL_SESSION: - if (crypto_ex_cb_new(&crypto_ex_cb_ctx_session, ctx_l, ctx_ptr, - new_func, dup_func, free_func) != 0) - return -1; - idx = ssl_session_idx++; - break; - - /* following class indexes are not supoprted */ - case WOLF_CRYPTO_EX_INDEX_X509_STORE: - case WOLF_CRYPTO_EX_INDEX_X509_STORE_CTX: - case WOLF_CRYPTO_EX_INDEX_DH: - case WOLF_CRYPTO_EX_INDEX_DSA: - case WOLF_CRYPTO_EX_INDEX_EC_KEY: - case WOLF_CRYPTO_EX_INDEX_RSA: - case WOLF_CRYPTO_EX_INDEX_ENGINE: - case WOLF_CRYPTO_EX_INDEX_UI: - case WOLF_CRYPTO_EX_INDEX_BIO: - case WOLF_CRYPTO_EX_INDEX_APP: - case WOLF_CRYPTO_EX_INDEX_UI_METHOD: - case WOLF_CRYPTO_EX_INDEX_DRBG: - default: - break; - } - if (idx >= MAX_EX_DATA) - return -1; - return idx; -} -#endif /* HAVE_EX_DATA || WOLFSSL_WPAS_SMALL */ - -#if defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) -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) { - return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx); - } -#else - (void)ctx; - (void)idx; -#endif - return NULL; -} - -int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, - WOLFSSL_CRYPTO_EX_new* new_func, - WOLFSSL_CRYPTO_EX_dup* dup_func, - WOLFSSL_CRYPTO_EX_free* free_func) -{ - - WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); - - return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_CTX, idx, arg, - new_func, dup_func, free_func); -} - -/* Return the index that can be used for the WOLFSSL structure to store - * application data. - * - */ -int wolfSSL_get_ex_new_index(long argValue, void* arg, - WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2, - WOLFSSL_CRYPTO_EX_free* cb3) -{ - WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); - - return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL, argValue, arg, - cb1, cb2, cb3); -} - - -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) - { - return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data); - } - #else - (void)ctx; - (void)idx; - (void)data; - #endif - return WOLFSSL_FAILURE; -} - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS -int wolfSSL_CTX_set_ex_data_with_cleanup( - WOLFSSL_CTX* ctx, - int idx, - void* data, - wolfSSL_ex_data_cleanup_routine_t cleanup_routine) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data_with_cleanup"); - if (ctx != NULL) - { - return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx, data, - cleanup_routine); - } - return WOLFSSL_FAILURE; -} -#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ - -#endif /* defined(HAVE_EX_DATA) || defined(WOLFSSL_WPAS_SMALL) */ - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - -/* Returns char* to app data stored in ex[0]. - * - * ssl WOLFSSL structure to get app data from - */ -void* wolfSSL_get_app_data(const WOLFSSL *ssl) -{ - /* checkout exdata stuff... */ - WOLFSSL_ENTER("wolfSSL_get_app_data"); - - return wolfSSL_get_ex_data(ssl, 0); -} - - -/* Set ex array 0 to have app data - * - * ssl WOLFSSL struct to set app data in - * arg data to be stored - * - * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure - */ -int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) { - WOLFSSL_ENTER("wolfSSL_set_app_data"); - - return wolfSSL_set_ex_data(ssl, 0, arg); -} - -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - -#if defined(HAVE_EX_DATA) || defined(OPENSSL_EXTRA) || \ - defined(OPENSSL_EXTRA_X509_SMALL) || defined(WOLFSSL_WPAS_SMALL) - -int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) -{ - WOLFSSL_ENTER("wolfSSL_set_ex_data"); -#ifdef HAVE_EX_DATA - if (ssl != NULL) - { - return wolfSSL_CRYPTO_set_ex_data(&ssl->ex_data, idx, data); - } -#else - WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); - (void)ssl; - (void)idx; - (void)data; -#endif - return WOLFSSL_FAILURE; -} - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS -int wolfSSL_set_ex_data_with_cleanup( - WOLFSSL* ssl, - int idx, - void* data, - wolfSSL_ex_data_cleanup_routine_t cleanup_routine) -{ - WOLFSSL_ENTER("wolfSSL_set_ex_data_with_cleanup"); - if (ssl != NULL) - { - return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ssl->ex_data, idx, data, - cleanup_routine); - } - return WOLFSSL_FAILURE; -} -#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ - -void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) -{ - WOLFSSL_ENTER("wolfSSL_get_ex_data"); -#ifdef HAVE_EX_DATA - if (ssl != NULL) { - return wolfSSL_CRYPTO_get_ex_data(&ssl->ex_data, idx); - } -#else - WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); - (void)ssl; - (void)idx; -#endif - return 0; -} - -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || WOLFSSL_WPAS_SMALL */ - -#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) - -#if defined(OPENSSL_EXTRA) && !defined(NO_DH) -/* Initialize ctx->dh with dh's params. Return WOLFSSL_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 WOLFSSL_FATAL_ERROR; - - p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if(!p) - return MEMORY_E; - - g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if(!g) { - XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - 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_PUBLIC_KEY); - XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); - - return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; -} -#endif /* OPENSSL_EXTRA && !NO_DH */ - - -/* returns the enum value associated with handshake state - * - * ssl the WOLFSSL structure to get state of - */ -int wolfSSL_get_state(const WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_state"); - - if (ssl == NULL) { - WOLFSSL_MSG("Null argument passed in"); - return WOLFSSL_FAILURE; - } - - return ssl->options.handShakeState; -} -#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ - -#ifdef OPENSSL_EXTRA -void wolfSSL_certs_clear(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_certs_clear"); - - if (ssl == NULL) - return; - - /* ctx still owns certificate, certChain, key, dh, and cm */ - if (ssl->buffers.weOwnCert) - FreeDer(&ssl->buffers.certificate); - ssl->buffers.certificate = NULL; - if (ssl->buffers.weOwnCertChain) - FreeDer(&ssl->buffers.certChain); - ssl->buffers.certChain = NULL; -#ifdef WOLFSSL_TLS13 - ssl->buffers.certChainCnt = 0; -#endif - if (ssl->buffers.weOwnKey) - FreeDer(&ssl->buffers.key); - ssl->buffers.key = NULL; - ssl->buffers.keyType = 0; - ssl->buffers.keyId = 0; - ssl->buffers.keyLabel = 0; - ssl->buffers.keySz = 0; - ssl->buffers.keyDevId = 0; -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (ssl->buffers.weOwnAltKey) - FreeDer(&ssl->buffers.altKey); - ssl->buffers.altKey = NULL; -#endif /* WOLFSSL_DUAL_ALG_CERTS */ -} -#endif - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) \ - || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) - -long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) -{ - WOLFSSL_ENTER("wolfSSL_ctrl"); - if (ssl == NULL) - return BAD_FUNC_ARG; - - switch (cmd) { - #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - #ifdef HAVE_SNI - case SSL_CTRL_SET_TLSEXT_HOSTNAME: - WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TLSEXT_HOSTNAME."); - if (pt == NULL) { - WOLFSSL_MSG("Passed in NULL Host Name."); - break; - } - return wolfSSL_set_tlsext_host_name(ssl, (const char*) pt); - #endif /* HAVE_SNI */ - #endif /* WOLFSSL_NGINX || WOLFSSL_QT || OPENSSL_ALL */ - default: - WOLFSSL_MSG("Case not implemented."); - } - (void)opt; - (void)pt; - return WOLFSSL_FAILURE; -} - -long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) -{ -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - long ctrl_opt; -#endif - long ret = WOLFSSL_SUCCESS; - - WOLFSSL_ENTER("wolfSSL_CTX_ctrl"); - if (ctx == NULL) - return WOLFSSL_FAILURE; - - switch (cmd) { - case SSL_CTRL_CHAIN: -#ifdef SESSION_CERTS - { - /* - * We don't care about opt here because a copy of the certificate is - * stored anyway so increasing the reference counter is not necessary. - * Just check to make sure that it is set to one of the correct values. - */ - WOLF_STACK_OF(WOLFSSL_X509)* sk = (WOLF_STACK_OF(WOLFSSL_X509)*) pt; - WOLFSSL_X509* x509; - int i; - if (opt != 0 && opt != 1) { - ret = WOLFSSL_FAILURE; - break; - } - /* Clear certificate chain */ - FreeDer(&ctx->certChain); - if (sk) { - for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { - x509 = wolfSSL_sk_X509_value(sk, i); - /* Prevent wolfSSL_CTX_add_extra_chain_cert from freeing cert */ - if (wolfSSL_X509_up_ref(x509) != 1) { - WOLFSSL_MSG("Error increasing reference count"); - continue; - } - if (wolfSSL_CTX_add_extra_chain_cert(ctx, x509) != - WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error adding certificate to context"); - /* Decrease reference count on failure */ - wolfSSL_X509_free(x509); - } - } - } - /* Free previous chain */ - wolfSSL_sk_X509_pop_free(ctx->x509Chain, NULL); - ctx->x509Chain = sk; - if (sk && opt == 1) { - /* up all refs when opt == 1 */ - for (i = 0; i < wolfSSL_sk_X509_num(sk); i++) { - x509 = wolfSSL_sk_X509_value(sk, i); - if (wolfSSL_X509_up_ref(x509) != 1) { - WOLFSSL_MSG("Error increasing reference count"); - continue; - } - } - } - } -#else - WOLFSSL_MSG("Session certificates not compiled in"); - ret = WOLFSSL_FAILURE; -#endif - break; - -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) - case SSL_CTRL_OPTIONS: - WOLFSSL_MSG("Entering Case: SSL_CTRL_OPTIONS."); - ctrl_opt = wolfSSL_CTX_set_options(ctx, opt); - - #ifdef WOLFSSL_QT - /* Set whether to use client or server cipher preference */ - if ((ctrl_opt & WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) - == WOLFSSL_OP_CIPHER_SERVER_PREFERENCE) { - WOLFSSL_MSG("Using Server's Cipher Preference."); - ctx->useClientOrder = FALSE; - } else { - WOLFSSL_MSG("Using Client's Cipher Preference."); - ctx->useClientOrder = TRUE; - } - #endif /* WOLFSSL_QT */ - - return ctrl_opt; -#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ - case SSL_CTRL_EXTRA_CHAIN_CERT: - WOLFSSL_MSG("Entering Case: SSL_CTRL_EXTRA_CHAIN_CERT."); - if (pt == NULL) { - WOLFSSL_MSG("Passed in x509 pointer NULL."); - ret = WOLFSSL_FAILURE; - break; - } - return wolfSSL_CTX_add_extra_chain_cert(ctx, (WOLFSSL_X509*)pt); - -#ifndef NO_DH - case SSL_CTRL_SET_TMP_DH: - WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_DH."); - if (pt == NULL) { - WOLFSSL_MSG("Passed in DH pointer NULL."); - ret = WOLFSSL_FAILURE; - break; - } - return wolfSSL_CTX_set_tmp_dh(ctx, (WOLFSSL_DH*)pt); -#endif - -#ifdef HAVE_ECC - case SSL_CTRL_SET_TMP_ECDH: - WOLFSSL_MSG("Entering Case: SSL_CTRL_SET_TMP_ECDH."); - if (pt == NULL) { - WOLFSSL_MSG("Passed in ECDH pointer NULL."); - ret = WOLFSSL_FAILURE; - break; - } - return wolfSSL_SSL_CTX_set_tmp_ecdh(ctx, (WOLFSSL_EC_KEY*)pt); -#endif - case SSL_CTRL_MODE: - wolfSSL_CTX_set_mode(ctx,opt); - break; - case SSL_CTRL_SET_MIN_PROTO_VERSION: - WOLFSSL_MSG("set min proto version"); - return wolfSSL_CTX_set_min_proto_version(ctx, (int)opt); - case SSL_CTRL_SET_MAX_PROTO_VERSION: - WOLFSSL_MSG("set max proto version"); - return wolfSSL_CTX_set_max_proto_version(ctx, (int)opt); - case SSL_CTRL_GET_MIN_PROTO_VERSION: - WOLFSSL_MSG("get min proto version"); - return wolfSSL_CTX_get_min_proto_version(ctx); - case SSL_CTRL_GET_MAX_PROTO_VERSION: - WOLFSSL_MSG("get max proto version"); - return wolfSSL_CTX_get_max_proto_version(ctx); - default: - WOLFSSL_MSG("CTX_ctrl cmd not implemented"); - ret = WOLFSSL_FAILURE; - break; - } - - (void)ctx; - (void)cmd; - (void)opt; - (void)pt; - WOLFSSL_LEAVE("wolfSSL_CTX_ctrl", (int)ret); - return ret; -} - -#ifndef WOLFSSL_NO_STUB -long wolfSSL_CTX_callback_ctrl(WOLFSSL_CTX* ctx, int cmd, void (*fp)(void)) -{ - (void) ctx; - (void) cmd; - (void) fp; - WOLFSSL_STUB("wolfSSL_CTX_callback_ctrl"); - return WOLFSSL_FAILURE; - -} -#endif /* WOLFSSL_NO_STUB */ - -#ifndef NO_WOLFSSL_STUB -long wolfSSL_CTX_clear_extra_chain_certs(WOLFSSL_CTX* ctx) -{ - return wolfSSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0L, NULL); -} -#endif - -/* Returns the verifyCallback from the ssl structure if successful. -Returns NULL otherwise. */ -VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_verify_callback"); - if (ssl) { - return ssl->verifyCallback; - } - return NULL; -} - -/* Adds the ASN1 certificate to the user ctx. -Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/ -int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz, - const unsigned char *der) -{ - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1"); - if (der != NULL && ctx != NULL) { - if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, - WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) { - return WOLFSSL_SUCCESS; - } - - } - return WOLFSSL_FAILURE; -} - - -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) -/* Adds the rsa private key to the user ctx. -Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/ -int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa) -{ - int ret; - int derSize; - unsigned char *maxDerBuf; - unsigned char* key = NULL; - - WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey"); - - if (ctx == NULL || rsa == NULL) { - WOLFSSL_MSG("one or more inputs were NULL"); - return BAD_FUNC_ARG; - } - maxDerBuf = (unsigned char*)XMALLOC(4096, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (maxDerBuf == NULL) { - WOLFSSL_MSG("Malloc failure"); - return MEMORY_E; - } - key = maxDerBuf; - /* convert RSA struct to der encoded buffer and get the size */ - if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) { - WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure"); - XFREE(maxDerBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; - } - ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf, - derSize, SSL_FILETYPE_ASN1); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure"); - XFREE(maxDerBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; - } - XFREE(maxDerBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; -} -#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ - - -#ifndef NO_BIO -/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure. -Returns pointer to private EVP_PKEY struct upon success, NULL if there -is a failure.*/ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** out) -{ - unsigned char* mem = NULL; - int memSz = 0; - WOLFSSL_EVP_PKEY* key = NULL; - unsigned char* extraBioMem = NULL; - - WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio"); - - if (bio == NULL) { - return NULL; - } - (void)out; - - memSz = wolfSSL_BIO_get_len(bio); - if (memSz <= 0) { - WOLFSSL_MSG("wolfSSL_BIO_get_len() failure"); - return NULL; - } - - mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (mem == NULL) { - WOLFSSL_MSG("Malloc failure"); - return NULL; - } - - if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { - int extraBioMemSz; - int derLength; - - /* Determines key type and returns the new private EVP_PKEY object */ - if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) { - WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure"); - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - - /* Write extra data back into bio object if necessary. */ - derLength = key->pkey_sz; - extraBioMemSz = (memSz - derLength); - if (extraBioMemSz > 0) { - int i; - int j = 0; - - extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (extraBioMem == NULL) { - WOLFSSL_MSG("Malloc failure"); - XFREE((unsigned char*)extraBioMem, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - - for (i = derLength; i < memSz; i++) { - *(extraBioMem + j) = *(mem + i); - j++; - } - - wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz); - if (wolfSSL_BIO_get_len(bio) <= 0) { - WOLFSSL_MSG("Failed to write memory to bio"); - XFREE((unsigned char*)extraBioMem, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - XFREE((unsigned char*)extraBioMem, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - } - - if (out != NULL) { - *out = key; - } - } - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - return key; -} -#endif /* !NO_BIO */ - -#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */ - - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || defined(WOLFSSL_HAPROXY) || \ - defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL) - -/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure. - * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL - * on fail */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out, - unsigned char** in, long inSz) -{ - WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP"); - return d2iGenericKey(out, (const unsigned char**)in, inSz, 1); -} - -#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT || WOLFSSL_WPAS_SMALL*/ - - -/* stunnel compatibility functions*/ -#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) -void wolfSSL_ERR_remove_thread_state(void* pid) -{ - (void) pid; - return; -} - -#ifndef NO_FILESYSTEM -/***TBD ***/ -void wolfSSL_print_all_errors_fp(XFILE fp) -{ - (void)fp; -} -#endif /* !NO_FILESYSTEM */ - -#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || - HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH */ - - -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ - defined(HAVE_EX_DATA) - -#if defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE) -static void SESSION_ex_data_cache_update(WOLFSSL_SESSION* session, int idx, - void* data, byte get, void** getRet, int* setRet) -{ - int row; - int i; - int error = 0; - SessionRow* sessRow = NULL; - const byte* id; - byte foundCache = 0; - - if (getRet != NULL) - *getRet = NULL; - if (setRet != NULL) - *setRet = WOLFSSL_FAILURE; - - id = session->sessionID; - if (session->haveAltSessionID) - id = session->altSessionID; - - row = (int)(HashObject(id, ID_LEN, &error) % SESSION_ROWS); - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return; - } - - sessRow = &SessionCache[row]; - if (get) - error = SESSION_ROW_RD_LOCK(sessRow); - else - error = SESSION_ROW_WR_LOCK(sessRow); - if (error != 0) { - WOLFSSL_MSG("Session row lock failed"); - return; - } - - for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { - WOLFSSL_SESSION* cacheSession; -#ifdef SESSION_CACHE_DYNAMIC_MEM - cacheSession = sessRow->Sessions[i]; -#else - cacheSession = &sessRow->Sessions[i]; -#endif - if (cacheSession && - XMEMCMP(id, cacheSession->sessionID, ID_LEN) == 0 - && session->side == cacheSession->side - #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) - && (IsAtLeastTLSv1_3(session->version) == - IsAtLeastTLSv1_3(cacheSession->version)) - #endif - ) { - if (get) { - if (getRet) { - *getRet = wolfSSL_CRYPTO_get_ex_data( - &cacheSession->ex_data, idx); - } - } - else { - if (setRet) { - *setRet = wolfSSL_CRYPTO_set_ex_data( - &cacheSession->ex_data, idx, data); - } - } - foundCache = 1; - break; - } - } - SESSION_ROW_UNLOCK(sessRow); - /* If we don't have a session in cache then clear the ex_data and - * own it */ - if (!foundCache) { - XMEMSET(&session->ex_data, 0, sizeof(WOLFSSL_CRYPTO_EX_DATA)); - session->ownExData = 1; - if (!get) { - *setRet = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, - data); - } - } - -} -#endif - -int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) -{ - int ret = WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); -#ifdef HAVE_EX_DATA - session = ClientSessionToSession(session); - if (session != NULL) { -#ifndef NO_SESSION_CACHE - if (!session->ownExData) { - /* Need to update in cache */ - SESSION_ex_data_cache_update(session, idx, data, 0, NULL, &ret); - } - else -#endif - { - ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); - } - } -#else - (void)session; - (void)idx; - (void)data; -#endif - return ret; -} - -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS -int wolfSSL_SESSION_set_ex_data_with_cleanup( - WOLFSSL_SESSION* session, - int idx, - void* data, - wolfSSL_ex_data_cleanup_routine_t cleanup_routine) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data_with_cleanup"); - session = ClientSessionToSession(session); - if(session != NULL) { - return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&session->ex_data, idx, - data, cleanup_routine); - } - return WOLFSSL_FAILURE; -} -#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ - -void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) -{ - void* ret = NULL; - WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); -#ifdef HAVE_EX_DATA - session = ClientSessionToSession(session); - if (session != NULL) { -#ifndef NO_SESSION_CACHE - if (!session->ownExData) { - /* Need to retrieve the data from the session cache */ - SESSION_ex_data_cache_update((WOLFSSL_SESSION*)session, idx, NULL, - 1, &ret, NULL); - } - else -#endif - { - ret = wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); - } - } -#else - (void)session; - (void)idx; -#endif - return ret; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_EX_DATA */ - -/* Note: This is a huge section of API's - through - * wolfSSL_X509_OBJECT_get0_X509_CRL */ -#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ - (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ - defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ - defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) -#ifdef HAVE_EX_DATA -int wolfSSL_SESSION_get_ex_new_index(long ctx_l,void* ctx_ptr, - WOLFSSL_CRYPTO_EX_new* new_func, WOLFSSL_CRYPTO_EX_dup* dup_func, - WOLFSSL_CRYPTO_EX_free* free_func) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index"); - return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_SESSION, ctx_l, - ctx_ptr, new_func, dup_func, free_func); -} -#endif - -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY) && \ - !defined(WOLFSSL_STATIC_MEMORY) -static wolfSSL_OSSL_Malloc_cb ossl_malloc = NULL; -static wolfSSL_OSSL_Free_cb ossl_free = NULL; -static wolfSSL_OSSL_Realloc_cb ossl_realloc = NULL; - -static void* OSSL_Malloc(size_t size) -{ - if (ossl_malloc != NULL) - return ossl_malloc(size, NULL, 0); - else - return NULL; -} - -static void OSSL_Free(void *ptr) -{ - if (ossl_free != NULL) - ossl_free(ptr, NULL, 0); -} - -static void* OSSL_Realloc(void *ptr, size_t size) -{ - if (ossl_realloc != NULL) - return ossl_realloc(ptr, size, NULL, 0); - else - return NULL; -} -#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY && - * !WOLFSSL_STATIC_MEMORY */ - -int wolfSSL_CRYPTO_set_mem_functions( - wolfSSL_OSSL_Malloc_cb m, - wolfSSL_OSSL_Realloc_cb r, - wolfSSL_OSSL_Free_cb f) -{ -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) -#ifdef WOLFSSL_DEBUG_MEMORY - WOLFSSL_MSG("mem functions will receive function name instead of " - "file name"); - if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)m, (wolfSSL_Free_cb)f, - (wolfSSL_Realloc_cb)r) == 0) - return WOLFSSL_SUCCESS; -#else - WOLFSSL_MSG("wolfSSL was compiled without WOLFSSL_DEBUG_MEMORY mem " - "functions will receive a NULL file name and 0 for the " - "line number."); - if (wolfSSL_SetAllocators((wolfSSL_Malloc_cb)OSSL_Malloc, - (wolfSSL_Free_cb)OSSL_Free, (wolfSSL_Realloc_cb)OSSL_Realloc) == 0) { - ossl_malloc = m; - ossl_free = f; - ossl_realloc = r; - return WOLFSSL_SUCCESS; - } -#endif - else - return WOLFSSL_FAILURE; -#else - (void)m; - (void)r; - (void)f; - WOLFSSL_MSG("wolfSSL allocator callback functions not compiled in"); - return WOLFSSL_FAILURE; -#endif -} - -int wolfSSL_ERR_load_ERR_strings(void) -{ - return WOLFSSL_SUCCESS; -} - -void wolfSSL_ERR_load_crypto_strings(void) -{ - WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); - /* Do nothing */ - return; -} - -int wolfSSL_FIPS_mode(void) -{ -#ifdef HAVE_FIPS - return 1; -#else - return 0; -#endif -} - -int wolfSSL_FIPS_mode_set(int r) -{ -#ifdef HAVE_FIPS - if (r == 0) { - WOLFSSL_MSG("Cannot disable FIPS at runtime."); - return WOLFSSL_FAILURE; - } - return WOLFSSL_SUCCESS; -#else - if (r == 0) { - return WOLFSSL_SUCCESS; - } - WOLFSSL_MSG("Cannot enable FIPS. This isn't the wolfSSL FIPS code."); - return WOLFSSL_FAILURE; -#endif -} - -int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) -{ - int ret = WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); - - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - (void)alg_bits; - if (c!= NULL) - ret = c->bits; - #else - if (c != NULL && c->ssl != NULL) { - ret = 8 * c->ssl->specs.key_size; - if (alg_bits != NULL) { - *alg_bits = ret; - } - } - #endif - return ret; -} - -/* returns value less than 0 on fail to match - * On a successful match the priority level found is returned - */ -int wolfSSL_sk_SSL_CIPHER_find( - WOLF_STACK_OF(WOLFSSL_CIPHER)* sk, const WOLFSSL_CIPHER* toFind) -{ - WOLFSSL_STACK* next; - int i, sz; - - if (sk == NULL || toFind == NULL) { - return WOLFSSL_FATAL_ERROR; - } - - sz = wolfSSL_sk_SSL_CIPHER_num(sk); - next = sk; - for (i = 0; i < sz && next != NULL; i++) { - if (next->data.cipher.cipherSuite0 == toFind->cipherSuite0 && - next->data.cipher.cipherSuite == toFind->cipherSuite) { - return sz - i; /* reverse because stack pushed highest on first */ - } - next = next->next; - } - return WOLFSSL_FATAL_ERROR; -} - -/* free's all nodes in the stack and there data */ -void wolfSSL_sk_SSL_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk) -{ - WOLFSSL_ENTER("wolfSSL_sk_SSL_CIPHER_free"); - wolfSSL_sk_free(sk); -} - -#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, (word16)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) -{ - int ret; - /* This method requires some explanation. Its sibling is - * int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) - * which re-inits the WOLFSSL* with all settings in the new CTX. - * That one is the right one to use *before* a handshake is started. - * - * This method was added by OpenSSL to be used *during* the handshake, e.g. - * when a server inspects the SNI in a ClientHello callback and - * decides which set of certificates to use. - * - * Since, at the time the SNI callback is run, some decisions on - * Extensions or the ServerHello might already have been taken, this - * method is very restricted in what it does: - * - changing the server certificate(s) - * - changing the server id for session handling - * and everything else in WOLFSSL* needs to remain untouched. - */ - WOLFSSL_ENTER("wolfSSL_set_SSL_CTX"); - if (ssl == NULL || ctx == NULL) - return NULL; - if (ssl->ctx == ctx) - return ssl->ctx; - - wolfSSL_RefInc(&ctx->ref, &ret); -#ifdef WOLFSSL_REFCNT_ERROR_RETURN - if (ret != 0) { - /* can only fail on serious stuff, like mutex not working - * or ctx refcount out of whack. */ - return NULL; - } -#else - (void)ret; -#endif - if (ssl->ctx != NULL) - wolfSSL_CTX_free(ssl->ctx); - ssl->ctx = ctx; - -#ifndef NO_CERTS - /* ctx owns certificate, certChain and key */ - ssl->buffers.certificate = ctx->certificate; - ssl->buffers.certChain = ctx->certChain; -#ifdef WOLFSSL_TLS13 - ssl->buffers.certChainCnt = ctx->certChainCnt; -#endif - ssl->buffers.key = ctx->privateKey; - ssl->buffers.keyType = ctx->privateKeyType; - ssl->buffers.keyId = ctx->privateKeyId; - ssl->buffers.keyLabel = ctx->privateKeyLabel; - ssl->buffers.keySz = ctx->privateKeySz; - ssl->buffers.keyDevId = ctx->privateKeyDevId; - /* flags indicating what certs/keys are available */ - ssl->options.haveRSA = ctx->haveRSA; - ssl->options.haveDH = ctx->haveDH; - ssl->options.haveECDSAsig = ctx->haveECDSAsig; - ssl->options.haveECC = ctx->haveECC; - ssl->options.haveStaticECC = ctx->haveStaticECC; - ssl->options.haveFalconSig = ctx->haveFalconSig; - ssl->options.haveDilithiumSig = ctx->haveDilithiumSig; -#ifdef WOLFSSL_DUAL_ALG_CERTS - ssl->buffers.altKey = ctx->altPrivateKey; - ssl->buffers.altKeySz = ctx->altPrivateKeySz; - ssl->buffers.altKeyType = ctx->altPrivateKeyType; -#endif /* WOLFSSL_DUAL_ALG_CERTS */ -#endif - -#ifdef WOLFSSL_SESSION_ID_CTX - /* copy over application session context ID */ - ssl->sessionCtxSz = ctx->sessionCtxSz; - XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz); -#endif - - return ssl->ctx; -} - - -VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); - if(ctx) - return ctx->verifyCallback; - return NULL; -} - - -#ifdef HAVE_SNI - -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 WOLFSSL_SUCCESS; - } - return WOLFSSL_FAILURE; -} - -int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); - if (ctx) { - ctx->sniRecvCbArg = arg; - return WOLFSSL_SUCCESS; - } - return WOLFSSL_FAILURE; -} - -#endif /* HAVE_SNI */ - - -#ifndef NO_BIO -void wolfSSL_ERR_load_BIO_strings(void) { - WOLFSSL_ENTER("wolfSSL_ERR_load_BIO_strings"); - /* do nothing */ -} -#endif - -#ifndef NO_WOLFSSL_STUB -/* Set THREADID callback, return 1 on success, 0 on error */ -int wolfSSL_THREADID_set_callback( - void(*threadid_func)(WOLFSSL_CRYPTO_THREADID*)) -{ - WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); - WOLFSSL_STUB("CRYPTO_THREADID_set_callback"); - (void)threadid_func; - return 1; -} -#endif - -#ifndef NO_WOLFSSL_STUB -void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) -{ - WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); - WOLFSSL_STUB("CRYPTO_THREADID_set_numeric"); - (void)id; - (void)val; - return; -} -#endif - -#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || - * HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH || - * HAVE_SBLIM_SFCB)) */ - - -#if defined(OPENSSL_EXTRA) - -int wolfSSL_CRYPTO_memcmp(const void *a, const void *b, size_t size) -{ - if (!a || !b) - return 0; - return ConstantCompare((const byte*)a, (const byte*)b, (int)size); -} - -unsigned long wolfSSL_ERR_peek_last_error(void) -{ - WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - -#ifdef WOLFSSL_HAVE_ERROR_QUEUE - { - int ret; - - if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { - WOLFSSL_MSG("Issue peeking at error node in queue"); - return 0; - } - if (ret == -ASN_NO_PEM_HEADER) - return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; - #if defined(WOLFSSL_PYTHON) - if (ret == ASN1_R_HEADER_TOO_LONG) - return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; - #endif - return (unsigned long)ret; - } -#else - return (unsigned long)(0 - NOT_COMPILED_IN); -#endif -} - -#endif /* OPENSSL_EXTRA */ - -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 : - return TLS1_VERSION; - case TLSv1_1_MINOR : - return TLS1_1_VERSION; - case TLSv1_2_MINOR : - return TLS1_2_VERSION; - case TLSv1_3_MINOR : - return TLS1_3_VERSION; - default: - return WOLFSSL_FAILURE; - } - } - else if (ssl->version.major == DTLS_MAJOR) { - switch (ssl->version.minor) { - case DTLS_MINOR : - return DTLS1_VERSION; - case DTLSv1_2_MINOR : - return DTLS1_2_VERSION; - case DTLSv1_3_MINOR: - return DTLS1_3_VERSION; - default: - return WOLFSSL_FAILURE; - } - } - return WOLFSSL_FAILURE; -} - -WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); - return ssl->ctx; -} - -#if defined(OPENSSL_ALL) || \ - defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - -const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess, - unsigned int* idLen) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - sess = ClientSessionToSession(sess); - if (sess == NULL || idLen == NULL) { - WOLFSSL_MSG("Bad func args. Please provide idLen"); - return NULL; - } -#ifdef HAVE_SESSION_TICKET - if (sess->haveAltSessionID) { - *idLen = ID_LEN; - return sess->altSessionID; - } -#endif - *idLen = sess->sessionIDSz; - return sess->sessionID; -} - -#if (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \ - !defined(NO_FILESYSTEM) - -#ifndef NO_BIO - -#if defined(SESSION_CERTS) || \ - (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) -/* returns a pointer to the protocol used by the session */ -static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) -{ - in = ClientSessionToSession(in); - return wolfSSL_internal_get_version((ProtocolVersion*)&in->version); -} -#endif - -/* returns true (non 0) if the session has EMS (extended master secret) */ -static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in) -{ - in = ClientSessionToSession(in); - if (in == NULL) - return 0; - return in->haveEMS; -} - -#if defined(HAVE_SESSION_TICKET) -/* prints out the ticket to bio passed in - * return WOLFSSL_SUCCESS on success - */ -static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, - const WOLFSSL_SESSION* in, const char* tab) -{ - unsigned short i, j, z, sz; - short tag = 0; - byte* pt; - - - in = ClientSessionToSession(in); - if (in == NULL || bio == NULL) { - return BAD_FUNC_ARG; - } - - sz = in->ticketLen; - pt = in->ticket; - - if (wolfSSL_BIO_printf(bio, "%s\n", (sz == 0)? " NONE": "") <= 0) - return WOLFSSL_FAILURE; - - for (i = 0; i < sz;) { - char asc[16]; - XMEMSET(asc, 0, sizeof(asc)); - - if (sz - i < 16) { - if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag + (sz - i)) <= 0) - return WOLFSSL_FAILURE; - } - else { - if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag) <= 0) - return WOLFSSL_FAILURE; - } - for (j = 0; i < sz && j < 8; j++,i++) { - asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; - if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0) - return WOLFSSL_FAILURE; - } - - if (i < sz) { - asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; - if (wolfSSL_BIO_printf(bio, "-%02X", pt[i]) <= 0) - return WOLFSSL_FAILURE; - j++; - i++; - } - - for (; i < sz && j < 16; j++,i++) { - asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; - if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0) - return WOLFSSL_FAILURE; - } - - /* pad out spacing */ - for (z = j; z < 17; z++) { - if (wolfSSL_BIO_printf(bio, " ") <= 0) - return WOLFSSL_FAILURE; - } - - for (z = 0; z < j; z++) { - if (wolfSSL_BIO_printf(bio, "%c", asc[z]) <= 0) - return WOLFSSL_FAILURE; - } - if (wolfSSL_BIO_printf(bio, "\n") <= 0) - return WOLFSSL_FAILURE; - - tag += 16; - } - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_SESSION_TICKET */ - - -/* prints out the session information in human readable form - * return WOLFSSL_SUCCESS on success - */ -int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *session) -{ - const unsigned char* pt; - unsigned char buf[SECRET_LEN]; - unsigned int sz = 0, i; - int ret; - - session = ClientSessionToSession(session); - if (session == NULL) { - return WOLFSSL_FAILURE; - } - - if (wolfSSL_BIO_printf(bp, "%s\n", "SSL-Session:") <= 0) - return WOLFSSL_FAILURE; - -#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ - defined(HAVE_SESSION_TICKET)) - if (wolfSSL_BIO_printf(bp, " Protocol : %s\n", - wolfSSL_SESSION_get_protocol(session)) <= 0) - return WOLFSSL_FAILURE; -#endif - - if (wolfSSL_BIO_printf(bp, " Cipher : %s\n", - wolfSSL_SESSION_CIPHER_get_name(session)) <= 0) - return WOLFSSL_FAILURE; - - pt = wolfSSL_SESSION_get_id(session, &sz); - if (wolfSSL_BIO_printf(bp, " Session-ID: ") <= 0) - return WOLFSSL_FAILURE; - - for (i = 0; i < sz; i++) { - if (wolfSSL_BIO_printf(bp, "%02X", pt[i]) <= 0) - return WOLFSSL_FAILURE; - } - if (wolfSSL_BIO_printf(bp, "\n") <= 0) - return WOLFSSL_FAILURE; - - if (wolfSSL_BIO_printf(bp, " Session-ID-ctx: \n") <= 0) - return WOLFSSL_FAILURE; - - ret = wolfSSL_SESSION_get_master_key(session, buf, sizeof(buf)); - if (wolfSSL_BIO_printf(bp, " Master-Key: ") <= 0) - return WOLFSSL_FAILURE; - - if (ret > 0) { - sz = (unsigned int)ret; - for (i = 0; i < sz; i++) { - if (wolfSSL_BIO_printf(bp, "%02X", buf[i]) <= 0) - return WOLFSSL_FAILURE; - } - } - if (wolfSSL_BIO_printf(bp, "\n") <= 0) - return WOLFSSL_FAILURE; - - /* @TODO PSK identity hint and SRP */ - - if (wolfSSL_BIO_printf(bp, " TLS session ticket:") <= 0) - return WOLFSSL_FAILURE; - -#ifdef HAVE_SESSION_TICKET - if (wolfSSL_SESSION_print_ticket(bp, session, " ") != WOLFSSL_SUCCESS) - return WOLFSSL_FAILURE; -#endif - -#if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \ - defined(HAVE_EXT_CACHE)) - if (wolfSSL_BIO_printf(bp, " Start Time: %ld\n", - wolfSSL_SESSION_get_time(session)) <= 0) - return WOLFSSL_FAILURE; - - if (wolfSSL_BIO_printf(bp, " Timeout : %ld (sec)\n", - wolfSSL_SESSION_get_timeout(session)) <= 0) - return WOLFSSL_FAILURE; -#endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ - - /* @TODO verify return code print */ - - if (wolfSSL_BIO_printf(bp, " Extended master secret: %s\n", - (wolfSSL_SESSION_haveEMS(session) == 0)? "no" : "yes") <= 0) - return WOLFSSL_FAILURE; - - return WOLFSSL_SUCCESS; -} - -#endif /* !NO_BIO */ -#endif /* (HAVE_SESSION_TICKET || SESSION_CERTS) && !NO_FILESYSTEM */ - -#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ - -#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) - -/* TODO: Doesn't currently track SSL_VERIFY_CLIENT_ONCE */ -int wolfSSL_get_verify_mode(const WOLFSSL* ssl) { - int mode = 0; - WOLFSSL_ENTER("wolfSSL_get_verify_mode"); - - if (!ssl) { - return WOLFSSL_FAILURE; - } - - if (ssl->options.verifyNone) { - mode = WOLFSSL_VERIFY_NONE; - } - else { - if (ssl->options.verifyPeer) { - mode |= WOLFSSL_VERIFY_PEER; - } - if (ssl->options.failNoCert) { - mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; - } - if (ssl->options.failNoCertxPSK) { - mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; - } -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - if (ssl->options.verifyPostHandshake) { - mode |= WOLFSSL_VERIFY_POST_HANDSHAKE; - } -#endif - } - - WOLFSSL_LEAVE("wolfSSL_get_verify_mode", mode); - return mode; -} - -int wolfSSL_CTX_get_verify_mode(const WOLFSSL_CTX* ctx) -{ - int mode = 0; - WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); - - if (!ctx) { - return WOLFSSL_FAILURE; - } - - if (ctx->verifyNone) { - mode = WOLFSSL_VERIFY_NONE; - } - else { - if (ctx->verifyPeer) { - mode |= WOLFSSL_VERIFY_PEER; - } - if (ctx->failNoCert) { - mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; - } - if (ctx->failNoCertxPSK) { - mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; - } -#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) - if (ctx->verifyPostHandshake) { - mode |= WOLFSSL_VERIFY_POST_HANDSHAKE; - } -#endif - } - - 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 WOLFSSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = WOLFSSL_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 WOLFSSL_FAILURE; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return WOLFSSL_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 = WOLFSSL_SUCCESS; - - wc_curve25519_free(&key); - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); -#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 WOLFSSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = WOLFSSL_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 WOLFSSL_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 = WOLFSSL_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 WOLFSSL_FAILURE; -#elif !defined(HAVE_ED25519_KEY_EXPORT) - WOLFSSL_MSG("No ED25519 key export built in"); - (void) priv; - (void) privSz; - (void) pub; - (void) pubSz; - return WOLFSSL_FAILURE; -#else /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */ - int ret = WOLFSSL_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 WOLFSSL_FAILURE; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return WOLFSSL_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 = WOLFSSL_SUCCESS; - - wc_ed25519_free(&key); - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); -#endif - - return ret; -#endif /* WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_EXPORT */ -} - -/* 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) -{ -#if !defined(HAVE_ED25519_SIGN) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED25519_KEY_IMPORT) -#if !defined(HAVE_ED25519_SIGN) - WOLFSSL_MSG("No ED25519 sign built in"); -#elif !defined(WOLFSSL_KEY_GEN) - WOLFSSL_MSG("No Key Gen built in"); -#elif !defined(HAVE_ED25519_KEY_IMPORT) - WOLFSSL_MSG("No ED25519 Key import built in"); -#endif - (void) msg; - (void) msgSz; - (void) priv; - (void) privSz; - (void) sig; - (void) sigSz; - return WOLFSSL_FAILURE; -#else /* HAVE_ED25519_SIGN && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */ - ed25519_key key; - int ret = WOLFSSL_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 WOLFSSL_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 = WOLFSSL_SUCCESS; - - wc_ed25519_free(&key); - - return ret; -#endif /* HAVE_ED25519_SIGN && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */ -} - -/* 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) -{ -#if !defined(HAVE_ED25519_VERIFY) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED25519_KEY_IMPORT) -#if !defined(HAVE_ED25519_VERIFY) - WOLFSSL_MSG("No ED25519 verify built in"); -#elif !defined(WOLFSSL_KEY_GEN) - WOLFSSL_MSG("No Key Gen built in"); -#elif !defined(HAVE_ED25519_KEY_IMPORT) - WOLFSSL_MSG("No ED25519 Key import built in"); -#endif - (void) msg; - (void) msgSz; - (void) pub; - (void) pubSz; - (void) sig; - (void) sigSz; - return WOLFSSL_FAILURE; -#else /* HAVE_ED25519_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */ - ed25519_key key; - int ret = WOLFSSL_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 WOLFSSL_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 = WOLFSSL_SUCCESS; - - wc_ed25519_free(&key); - - return ret; -#endif /* HAVE_ED25519_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED25519_KEY_IMPORT */ -} - -#endif /* OPENSSL_EXTRA && HAVE_ED25519 */ - -#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE448) -/* return 1 if success, 0 if error - * output keys are little endian format - */ -int wolfSSL_EC448_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 WOLFSSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = WOLFSSL_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_EC448_generate_key"); - - if (priv == NULL || privSz == NULL || *privSz < CURVE448_KEY_SIZE || - pub == NULL || pubSz == NULL || *pubSz < CURVE448_KEY_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return WOLFSSL_FAILURE; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return WOLFSSL_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) { - curve448_key key; - - if (wc_curve448_init(&key) != MP_OKAY) - WOLFSSL_MSG("wc_curve448_init failed"); - else if (wc_curve448_make_key(rng, CURVE448_KEY_SIZE, &key)!=MP_OKAY) - WOLFSSL_MSG("wc_curve448_make_key failed"); - /* export key pair */ - else if (wc_curve448_export_key_raw_ex(&key, priv, privSz, pub, pubSz, - EC448_LITTLE_ENDIAN) - != MP_OKAY) - WOLFSSL_MSG("wc_curve448_export_key_raw_ex failed"); - else - ret = WOLFSSL_SUCCESS; - - wc_curve448_free(&key); - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); -#endif - - return ret; -#endif /* WOLFSSL_KEY_GEN */ -} - -/* return 1 if success, 0 if error - * input and output keys are little endian format - */ -int wolfSSL_EC448_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 WOLFSSL_FAILURE; -#else /* WOLFSSL_KEY_GEN */ - int ret = WOLFSSL_FAILURE; - curve448_key privkey, pubkey; - - WOLFSSL_ENTER("wolfSSL_EC448_shared_key"); - - if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE448_KEY_SIZE || - priv == NULL || privSz < CURVE448_KEY_SIZE || - pub == NULL || pubSz < CURVE448_KEY_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return WOLFSSL_FAILURE; - } - - /* import private key */ - if (wc_curve448_init(&privkey) != MP_OKAY) { - WOLFSSL_MSG("wc_curve448_init privkey failed"); - return ret; - } - if (wc_curve448_import_private_ex(priv, privSz, &privkey, - EC448_LITTLE_ENDIAN) != MP_OKAY) { - WOLFSSL_MSG("wc_curve448_import_private_ex failed"); - wc_curve448_free(&privkey); - return ret; - } - - /* import public key */ - if (wc_curve448_init(&pubkey) != MP_OKAY) { - WOLFSSL_MSG("wc_curve448_init pubkey failed"); - wc_curve448_free(&privkey); - return ret; - } - if (wc_curve448_import_public_ex(pub, pubSz, &pubkey, - EC448_LITTLE_ENDIAN) != MP_OKAY) { - WOLFSSL_MSG("wc_curve448_import_public_ex failed"); - wc_curve448_free(&privkey); - wc_curve448_free(&pubkey); - return ret; - } - - if (wc_curve448_shared_secret_ex(&privkey, &pubkey, shared, sharedSz, - EC448_LITTLE_ENDIAN) != MP_OKAY) - WOLFSSL_MSG("wc_curve448_shared_secret_ex failed"); - else - ret = WOLFSSL_SUCCESS; - - wc_curve448_free(&privkey); - wc_curve448_free(&pubkey); - - return ret; -#endif /* WOLFSSL_KEY_GEN */ -} -#endif /* OPENSSL_EXTRA && HAVE_CURVE448 */ - -#if defined(OPENSSL_EXTRA) && defined(HAVE_ED448) -/* return 1 if success, 0 if error - * output keys are little endian format - */ -int wolfSSL_ED448_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 WOLFSSL_FAILURE; -#elif !defined(HAVE_ED448_KEY_EXPORT) - WOLFSSL_MSG("No ED448 key export built in"); - (void) priv; - (void) privSz; - (void) pub; - (void) pubSz; - return WOLFSSL_FAILURE; -#else /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */ - int ret = WOLFSSL_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_ED448_generate_key"); - - if (priv == NULL || privSz == NULL || *privSz < ED448_PRV_KEY_SIZE || - pub == NULL || pubSz == NULL || *pubSz < ED448_PUB_KEY_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return WOLFSSL_FAILURE; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return WOLFSSL_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) { - ed448_key key; - - if (wc_ed448_init(&key) != MP_OKAY) - WOLFSSL_MSG("wc_ed448_init failed"); - else if (wc_ed448_make_key(rng, ED448_KEY_SIZE, &key) != MP_OKAY) - WOLFSSL_MSG("wc_ed448_make_key failed"); - /* export private key */ - else if (wc_ed448_export_key(&key, priv, privSz, pub, pubSz) != MP_OKAY) - WOLFSSL_MSG("wc_ed448_export_key failed"); - else - ret = WOLFSSL_SUCCESS; - - wc_ed448_free(&key); - } - - if (initTmpRng) - wc_FreeRng(tmpRNG); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); -#endif - - return ret; -#endif /* WOLFSSL_KEY_GEN && HAVE_ED448_KEY_EXPORT */ -} - -/* 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_ED448_sign(const unsigned char *msg, unsigned int msgSz, - const unsigned char *priv, unsigned int privSz, - unsigned char *sig, unsigned int *sigSz) -{ -#if !defined(HAVE_ED448_SIGN) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED448_KEY_IMPORT) -#if !defined(HAVE_ED448_SIGN) - WOLFSSL_MSG("No ED448 sign built in"); -#elif !defined(WOLFSSL_KEY_GEN) - WOLFSSL_MSG("No Key Gen built in"); -#elif !defined(HAVE_ED448_KEY_IMPORT) - WOLFSSL_MSG("No ED448 Key import built in"); -#endif - (void) msg; - (void) msgSz; - (void) priv; - (void) privSz; - (void) sig; - (void) sigSz; - return WOLFSSL_FAILURE; -#else /* HAVE_ED448_SIGN && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */ - ed448_key key; - int ret = WOLFSSL_FAILURE; - - WOLFSSL_ENTER("wolfSSL_ED448_sign"); - - if (priv == NULL || privSz != ED448_PRV_KEY_SIZE || msg == NULL || - sig == NULL || *sigSz < ED448_SIG_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return WOLFSSL_FAILURE; - } - - /* import key */ - if (wc_ed448_init(&key) != MP_OKAY) { - WOLFSSL_MSG("wc_curve448_init failed"); - return ret; - } - if (wc_ed448_import_private_key(priv, privSz/2, priv+(privSz/2), - ED448_PUB_KEY_SIZE, &key) != MP_OKAY){ - WOLFSSL_MSG("wc_ed448_import_private failed"); - wc_ed448_free(&key); - return ret; - } - - if (wc_ed448_sign_msg(msg, msgSz, sig, sigSz, &key, NULL, 0) != MP_OKAY) - WOLFSSL_MSG("wc_curve448_shared_secret_ex failed"); - else - ret = WOLFSSL_SUCCESS; - - wc_ed448_free(&key); - - return ret; -#endif /* HAVE_ED448_SIGN && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */ -} - -/* 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_ED448_verify(const unsigned char *msg, unsigned int msgSz, - const unsigned char *pub, unsigned int pubSz, - const unsigned char *sig, unsigned int sigSz) -{ -#if !defined(HAVE_ED448_VERIFY) || !defined(WOLFSSL_KEY_GEN) || !defined(HAVE_ED448_KEY_IMPORT) -#if !defined(HAVE_ED448_VERIFY) - WOLFSSL_MSG("No ED448 verify built in"); -#elif !defined(WOLFSSL_KEY_GEN) - WOLFSSL_MSG("No Key Gen built in"); -#elif !defined(HAVE_ED448_KEY_IMPORT) - WOLFSSL_MSG("No ED448 Key import built in"); -#endif - (void) msg; - (void) msgSz; - (void) pub; - (void) pubSz; - (void) sig; - (void) sigSz; - return WOLFSSL_FAILURE; -#else /* HAVE_ED448_VERIFY && WOLFSSL_KEY_GEN && HAVE_ED448_KEY_IMPORT */ - ed448_key key; - int ret = WOLFSSL_FAILURE, check = 0; - - WOLFSSL_ENTER("wolfSSL_ED448_verify"); - - if (pub == NULL || pubSz != ED448_PUB_KEY_SIZE || msg == NULL || - sig == NULL || sigSz != ED448_SIG_SIZE) { - WOLFSSL_MSG("Bad arguments"); - return WOLFSSL_FAILURE; - } - - /* import key */ - if (wc_ed448_init(&key) != MP_OKAY) { - WOLFSSL_MSG("wc_curve448_init failed"); - return ret; - } - if (wc_ed448_import_public(pub, pubSz, &key) != MP_OKAY){ - WOLFSSL_MSG("wc_ed448_import_public failed"); - wc_ed448_free(&key); - return ret; - } - - if ((ret = wc_ed448_verify_msg((byte*)sig, sigSz, msg, msgSz, &check, - &key, NULL, 0)) != MP_OKAY) { - WOLFSSL_MSG("wc_ed448_verify_msg failed"); - } - else if (!check) - WOLFSSL_MSG("wc_ed448_verify_msg failed (signature invalid)"); - else - ret = WOLFSSL_SUCCESS; - - wc_ed448_free(&key); - - return ret; -#endif /* HAVE_ED448_VERIFY && WOLFSSL_KEY_GEN */ -} - -#endif /* OPENSSL_EXTRA && HAVE_ED448 */ - -#ifdef WOLFSSL_JNI - -int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) -{ - WOLFSSL_ENTER("wolfSSL_set_jobject"); - if (ssl != NULL) - { - ssl->jObjectRef = objPtr; - return WOLFSSL_SUCCESS; - } - return WOLFSSL_FAILURE; -} - -void* wolfSSL_get_jobject(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_jobject"); - if (ssl != NULL) - return ssl->jObjectRef; - return NULL; -} - -#endif /* WOLFSSL_JNI */ - - -#ifdef WOLFSSL_ASYNC_CRYPT -int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, - WOLF_EVENT_FLAG flags, int* eventCount) -{ - if (ctx == NULL) { - return BAD_FUNC_ARG; - } - - return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, - events, maxEvents, flags, eventCount); -} - -int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) -{ - int ret, eventCount = 0; - WOLF_EVENT* events[1]; - - if (ssl == NULL) { - return BAD_FUNC_ARG; - } - - ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, - events, sizeof(events)/sizeof(events[0]), flags, &eventCount); - if (ret == 0) { - ret = eventCount; - } - - return ret; -} -#endif /* WOLFSSL_ASYNC_CRYPT */ - -#ifdef OPENSSL_EXTRA - -static int peek_ignore_err(int err) -{ - switch(err) { - case -WANT_READ: - case -WANT_WRITE: - case -ZERO_RETURN: - case -WOLFSSL_ERROR_ZERO_RETURN: - case -SOCKET_PEER_CLOSED_E: - case -SOCKET_ERROR_E: - return 1; - default: - return 0; - } -} - -unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, - const char **data, int *flags) -{ - unsigned long err; - - WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); - err = wc_PeekErrorNodeLineData(file, line, data, flags, peek_ignore_err); - - if (err == -ASN_NO_PEM_HEADER) - return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; -#ifdef OPENSSL_ALL - /* PARSE_ERROR is returned if an HTTP request is detected. */ - else if (err == -SSL_R_HTTP_REQUEST) - return (ERR_LIB_SSL << 24) | -SSL_R_HTTP_REQUEST; -#endif -#if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) - else if (err == ASN1_R_HEADER_TOO_LONG) - return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; -#endif - return err; -} -#endif - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) - -#if !defined(WOLFSSL_USER_IO) -/* converts an IPv6 or IPv4 address into an octet string for use with rfc3280 - * example input would be "127.0.0.1" and the returned value would be 7F000001 - */ -WOLFSSL_ASN1_STRING* wolfSSL_a2i_IPADDRESS(const char* ipa) -{ - int ipaSz = WOLFSSL_IP4_ADDR_LEN; - char buf[WOLFSSL_IP6_ADDR_LEN + 1]; /* plus 1 for terminator */ - int af = WOLFSSL_IP4; - WOLFSSL_ASN1_STRING *ret = NULL; - - if (ipa == NULL) - return NULL; - - if (XSTRSTR(ipa, ":") != NULL) { - af = WOLFSSL_IP6; - ipaSz = WOLFSSL_IP6_ADDR_LEN; - } - - buf[WOLFSSL_IP6_ADDR_LEN] = '\0'; - if (XINET_PTON(af, ipa, (void*)buf) != 1) { - WOLFSSL_MSG("Error parsing IP address"); - return NULL; - } - - ret = wolfSSL_ASN1_STRING_new(); - if (ret != NULL) { - if (wolfSSL_ASN1_STRING_set(ret, buf, ipaSz) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error setting the string"); - wolfSSL_ASN1_STRING_free(ret); - ret = NULL; - } - } - - return ret; -} -#endif /* !WOLFSSL_USER_IO */ - -/* Is the specified cipher suite a fake one used an an extension proxy? */ -static WC_INLINE int SCSV_Check(byte suite0, byte suite) -{ - (void)suite0; - (void)suite; -#ifdef HAVE_RENEGOTIATION_INDICATION - if (suite0 == CIPHER_BYTE && suite == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) - return 1; -#endif - return 0; -} - -static WC_INLINE int sslCipherMinMaxCheck(const WOLFSSL *ssl, byte suite0, - byte suite) -{ - const CipherSuiteInfo* cipher_names = GetCipherNames(); - int cipherSz = GetCipherNamesSize(); - int i; - for (i = 0; i < cipherSz; i++) - if (cipher_names[i].cipherSuite0 == suite0 && - cipher_names[i].cipherSuite == suite) - break; - if (i == cipherSz) - return 1; - /* Check min version */ - if (cipher_names[i].minor < ssl->options.minDowngrade) { - if (ssl->options.minDowngrade <= TLSv1_2_MINOR && - cipher_names[i].minor >= TLSv1_MINOR) - /* 1.0 ciphersuites are in general available in 1.1 and - * 1.1 ciphersuites are in general available in 1.2 */ - return 0; - return 1; - } - /* Check max version */ - switch (cipher_names[i].minor) { - case SSLv3_MINOR : - return ssl->options.mask & WOLFSSL_OP_NO_SSLv3; - case TLSv1_MINOR : - return ssl->options.mask & WOLFSSL_OP_NO_TLSv1; - case TLSv1_1_MINOR : - return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1; - case TLSv1_2_MINOR : - return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2; - case TLSv1_3_MINOR : - return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3; - default: - WOLFSSL_MSG("Unrecognized minor version"); - return 1; - } -} - -/* returns a pointer to internal cipher suite list. Should not be free'd by - * caller. - */ -WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) -{ - WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL; - const Suites* suites; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - const CipherSuiteInfo* cipher_names = GetCipherNames(); - int cipherSz = GetCipherNamesSize(); -#endif - - WOLFSSL_ENTER("wolfSSL_get_ciphers_compat"); - if (ssl == NULL) - return NULL; - - suites = WOLFSSL_SUITES(ssl); - if (suites == NULL) - return NULL; - - /* check if stack needs populated */ - if (ssl->suitesStack == NULL) { - int i; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - int j; - - /* higher priority of cipher suite will be on top of stack */ - for (i = suites->suiteSz - 2; i >=0; i-=2) { -#else - for (i = 0; i < suites->suiteSz; i+=2) { -#endif - WOLFSSL_STACK* add; - - /* A couple of suites are placeholders for special options, - * skip those. */ - if (SCSV_Check(suites->suites[i], suites->suites[i+1]) - || sslCipherMinMaxCheck(ssl, suites->suites[i], - suites->suites[i+1])) { - continue; - } - - add = wolfSSL_sk_new_node(ssl->heap); - if (add != NULL) { - add->type = STACK_TYPE_CIPHER; - add->data.cipher.cipherSuite0 = suites->suites[i]; - add->data.cipher.cipherSuite = suites->suites[i+1]; - add->data.cipher.ssl = ssl; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - for (j = 0; j < cipherSz; j++) { - if (cipher_names[j].cipherSuite0 == - add->data.cipher.cipherSuite0 && - cipher_names[j].cipherSuite == - add->data.cipher.cipherSuite) { - add->data.cipher.offset = j; - break; - } - } -#endif - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - /* in_stack is checked in wolfSSL_CIPHER_description */ - add->data.cipher.in_stack = 1; - #endif - - add->next = ret; - if (ret != NULL) { - add->num = ret->num + 1; - } - else { - add->num = 1; - } - ret = add; - } - } - ((WOLFSSL*)ssl)->suitesStack = ret; - } - return ssl->suitesStack; -} -#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ - || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || defined(HAVE_SECRET_CALLBACK) -long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) -{ - WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); - - if (ctx == NULL) - return 0; - - return ctx->timeout; -} - - -/* returns the time in seconds of the current timeout */ -long wolfSSL_get_timeout(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_get_timeout"); - - if (ssl == NULL) - return 0; - return ssl->timeout; -} -#endif - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ - || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) - -#ifdef HAVE_ECC -int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) -{ - WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); - - if (ctx == NULL || ecdh == NULL) - return BAD_FUNC_ARG; - - ctx->ecdhCurveOID = ecdh->group->curve_oid; - - return WOLFSSL_SUCCESS; -} -#endif -#ifndef NO_SESSION_CACHE -int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) -{ -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - int rem_called = FALSE; -#endif - - WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); - - s = ClientSessionToSession(s); - if (ctx == NULL || s == NULL) - return BAD_FUNC_ARG; - -#ifdef HAVE_EXT_CACHE - if (!ctx->internalCacheOff) -#endif - { - const byte* id; - WOLFSSL_SESSION *sess = NULL; - word32 row = 0; - int ret; - - id = s->sessionID; - if (s->haveAltSessionID) - id = s->altSessionID; - - ret = TlsSessionCacheGetAndWrLock(id, &sess, &row, ctx->method->side); - if (ret == 0 && sess != NULL) { -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - if (sess->rem_sess_cb != NULL) { - rem_called = TRUE; - } -#endif - /* Call this before changing ownExData so that calls to ex_data - * don't try to access the SessionCache again. */ - EvictSessionFromCache(sess); -#ifdef HAVE_EX_DATA - if (sess->ownExData) { - /* Most recent version of ex data is in cache. Copy it - * over so the user can free it. */ - XMEMCPY(&s->ex_data, &sess->ex_data, - sizeof(WOLFSSL_CRYPTO_EX_DATA)); - s->ownExData = 1; - sess->ownExData = 0; - } -#endif -#ifdef SESSION_CACHE_DYNAMIC_MEM - { - /* Find and clear entry. Row is locked so we are good to go. */ - int idx; - for (idx = 0; idx < SESSIONS_PER_ROW; idx++) { - if (sess == SessionCache[row].Sessions[idx]) { - XFREE(sess, sess->heap, DYNAMIC_TYPE_SESSION); - SessionCache[row].Sessions[idx] = NULL; - break; - } - } - } -#endif - TlsSessionCacheUnlockRow(row); - } - } - -#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) - if (ctx->rem_sess_cb != NULL && !rem_called) { - ctx->rem_sess_cb(ctx, s); - } -#endif - - /* s cannot be resumed at this point */ - s->timeout = 0; - - return 0; -} -#endif /* !NO_SESSION_CACHE */ -#ifndef NO_BIO -BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) -{ - WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); - /* 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. - */ - if (s == NULL) - return NULL; - - return s->biord; -} -BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) -{ - 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. - */ - if (s == NULL) - return NULL; - - return s->biowr; -} -#endif /* !NO_BIO */ - -int wolfSSL_SSL_do_handshake_internal(WOLFSSL *s) -{ - WOLFSSL_ENTER("wolfSSL_SSL_do_handshake_internal"); - if (s == NULL) - return WOLFSSL_FAILURE; - - if (s->options.side == WOLFSSL_CLIENT_END) { - #ifndef NO_WOLFSSL_CLIENT - return wolfSSL_connect(s); - #else - WOLFSSL_MSG("Client not compiled in"); - return WOLFSSL_FAILURE; - #endif - } - -#ifndef NO_WOLFSSL_SERVER - return wolfSSL_accept(s); -#else - WOLFSSL_MSG("Server not compiled in"); - return WOLFSSL_FAILURE; -#endif -} - -int wolfSSL_SSL_do_handshake(WOLFSSL *s) -{ - WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); -#ifdef WOLFSSL_QUIC - if (WOLFSSL_IS_QUIC(s)) { - return wolfSSL_quic_do_handshake(s); - } -#endif - return wolfSSL_SSL_do_handshake_internal(s); -} - -#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L -int wolfSSL_SSL_in_init(const WOLFSSL *ssl) -#else -int wolfSSL_SSL_in_init(WOLFSSL *ssl) -#endif -{ - WOLFSSL_ENTER("wolfSSL_SSL_in_init"); - - return !wolfSSL_is_init_finished(ssl); -} - -int wolfSSL_SSL_in_before(const WOLFSSL *ssl) -{ - WOLFSSL_ENTER("wolfSSL_SSL_in_before"); - - if (ssl == NULL) - return WOLFSSL_FAILURE; - - return ssl->options.handShakeState == NULL_STATE; -} - -int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl) -{ - WOLFSSL_ENTER("wolfSSL_SSL_in_connect_init"); - - if (ssl == NULL) - return WOLFSSL_FAILURE; - - if (ssl->options.side == WOLFSSL_CLIENT_END) { - return ssl->options.connectState > CONNECT_BEGIN && - ssl->options.connectState < SECOND_REPLY_DONE; - } - - return ssl->options.acceptState > ACCEPT_BEGIN && - ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE; -} - -#ifndef NO_SESSION_CACHE - -WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) -{ - WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); - - return ssl->session; -} - -#endif /* NO_SESSION_CACHE */ - -#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) -/* 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 - -/* 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[WC_MAX_DIGEST_SIZE]; -#ifdef WOLFSSL_SMALL_STACK - WOLFSSL_EVP_CIPHER_CTX *evpCtx; -#else - WOLFSSL_EVP_CIPHER_CTX evpCtx[1]; -#endif - WOLFSSL_HMAC_CTX hmacCtx; - unsigned int mdSz = 0; - int len = 0; - int ret = WOLFSSL_TICKET_RET_FATAL; - int res; - int totalSz = 0; - - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_TicketKeyCb"); - - if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketEncWrapCb == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_TICKET_RET_FATAL; - } - -#ifdef WOLFSSL_SMALL_STACK - evpCtx = (WOLFSSL_EVP_CIPHER_CTX *)XMALLOC(sizeof(*evpCtx), ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (evpCtx == NULL) { - WOLFSSL_MSG("out of memory"); - return WOLFSSL_TICKET_RET_FATAL; - } -#endif - - /* Initialize the cipher and HMAC. */ - wolfSSL_EVP_CIPHER_CTX_init(evpCtx); - if (wolfSSL_HMAC_CTX_Init(&hmacCtx) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init error"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return WOLFSSL_TICKET_RET_FATAL; - } - res = ssl->ctx->ticketEncWrapCb(ssl, keyName, - iv, evpCtx, &hmacCtx, enc); - if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) { - WOLFSSL_MSG("Ticket callback error"); - ret = WOLFSSL_TICKET_RET_FATAL; - goto end; - } - - if (wolfSSL_HMAC_size(&hmacCtx) > WOLFSSL_TICKET_MAC_SZ) { - WOLFSSL_MSG("Ticket cipher MAC size error"); - goto end; - } - - if (enc) - { - /* Encrypt in place. */ - if (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len, - encTicket, encTicketLen)) - goto end; - totalSz = len; - if (totalSz > *encLen) - goto end; - if (!wolfSSL_EVP_EncryptFinal(evpCtx, &encTicket[len], &len)) - goto end; - /* Total length of encrypted data. */ - totalSz += len; - if (totalSz > *encLen) - goto end; - - /* HMAC the encrypted data into the parameter 'mac'. */ - if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, totalSz)) - goto end; - if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz)) - goto end; - } - else - { - /* HMAC the encrypted data and compare it to the passed in data. */ - if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen)) - goto end; - if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz)) - goto end; - 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; - totalSz = len; - if (totalSz > encTicketLen) - goto end; - if (!wolfSSL_EVP_DecryptFinal(evpCtx, &encTicket[len], &len)) - goto end; - /* Total length of decrypted data. */ - totalSz += len; - if (totalSz > encTicketLen) - goto end; - } - *encLen = totalSz; - - if (res == TICKET_KEY_CB_RET_RENEW && !IsAtLeastTLSv1_3(ssl->version) - && !enc) - ret = WOLFSSL_TICKET_RET_CREATE; - else - ret = WOLFSSL_TICKET_RET_OK; -end: - - (void)wc_HmacFree(&hmacCtx.hmac); - (void)wolfSSL_EVP_CIPHER_CTX_cleanup(evpCtx); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -/* Set the callback to use when encrypting/decrypting tickets. - * - * ctx The SSL/TLS context object. - * cb The OpenSSL session ticket callback. - * returns WOLFSSL_SUCCESS to indicate success. - */ -int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, ticketCompatCb cb) -{ - - /* Set the ticket encryption callback to be a wrapper around OpenSSL - * callback. - */ - ctx->ticketEncCb = wolfSSL_TicketKeyCb; - ctx->ticketEncWrapCb = cb; - - return WOLFSSL_SUCCESS; -} - -#endif /* HAVE_SESSION_TICKET */ - -#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || - OPENSSL_EXTRA || HAVE_LIGHTY */ - -#if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ - !defined(NO_WOLFSSL_SERVER) -/* Serialize the session ticket encryption keys. - * - * @param [in] ctx SSL/TLS context object. - * @param [in] keys Buffer to hold session ticket keys. - * @param [in] keylen Length of buffer. - * @return WOLFSSL_SUCCESS on success. - * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the - * correct length. - */ -long wolfSSL_CTX_get_tlsext_ticket_keys(WOLFSSL_CTX *ctx, - unsigned char *keys, int keylen) -{ - if (ctx == NULL || keys == NULL) { - return WOLFSSL_FAILURE; - } - if (keylen != WOLFSSL_TICKET_KEYS_SZ) { - return WOLFSSL_FAILURE; - } - - XMEMCPY(keys, ctx->ticketKeyCtx.name, WOLFSSL_TICKET_NAME_SZ); - keys += WOLFSSL_TICKET_NAME_SZ; - XMEMCPY(keys, ctx->ticketKeyCtx.key[0], WOLFSSL_TICKET_KEY_SZ); - keys += WOLFSSL_TICKET_KEY_SZ; - XMEMCPY(keys, ctx->ticketKeyCtx.key[1], WOLFSSL_TICKET_KEY_SZ); - keys += WOLFSSL_TICKET_KEY_SZ; - c32toa(ctx->ticketKeyCtx.expirary[0], keys); - keys += OPAQUE32_LEN; - c32toa(ctx->ticketKeyCtx.expirary[1], keys); - - return WOLFSSL_SUCCESS; -} - -/* Deserialize the session ticket encryption keys. - * - * @param [in] ctx SSL/TLS context object. - * @param [in] keys Session ticket keys. - * @param [in] keylen Length of data. - * @return WOLFSSL_SUCCESS on success. - * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the - * correct length. - */ -long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx, - unsigned char *keys, int keylen) -{ - if (ctx == NULL || keys == NULL) { - return WOLFSSL_FAILURE; - } - if (keylen != WOLFSSL_TICKET_KEYS_SZ) { - return WOLFSSL_FAILURE; - } - - XMEMCPY(ctx->ticketKeyCtx.name, keys, WOLFSSL_TICKET_NAME_SZ); - keys += WOLFSSL_TICKET_NAME_SZ; - XMEMCPY(ctx->ticketKeyCtx.key[0], keys, WOLFSSL_TICKET_KEY_SZ); - keys += WOLFSSL_TICKET_KEY_SZ; - XMEMCPY(ctx->ticketKeyCtx.key[1], keys, WOLFSSL_TICKET_KEY_SZ); - keys += WOLFSSL_TICKET_KEY_SZ; - ato32(keys, &ctx->ticketKeyCtx.expirary[0]); - keys += OPAQUE32_LEN; - ato32(keys, &ctx->ticketKeyCtx.expirary[1]); - - return WOLFSSL_SUCCESS; -} -#endif - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) -#ifdef HAVE_OCSP -/* Not an OpenSSL API. */ -int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) -{ - *response = ssl->ocspResp; - return ssl->ocspRespSz; -} - -/* Not an OpenSSL API. */ -char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) -{ - return ssl->url; -} - -/* Not an OpenSSL API. */ -int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) -{ - if (ssl == NULL) - return WOLFSSL_FAILURE; - - ssl->url = url; - return WOLFSSL_SUCCESS; -} -#endif /* OCSP */ -#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ - -#if defined(HAVE_OCSP) && !defined(NO_ASN_TIME) -int wolfSSL_get_ocsp_producedDate( - WOLFSSL *ssl, - byte *producedDate, - size_t producedDate_space, - int *producedDateFormat) -{ - if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) && - (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME)) - return BAD_FUNC_ARG; - - if ((producedDate == NULL) || (producedDateFormat == NULL)) - return BAD_FUNC_ARG; - - if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space) - return BUFFER_E; - - XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate, producedDate_space); - *producedDateFormat = ssl->ocspProducedDateFormat; - - return 0; -} - -int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) { - int idx = 0; - - if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) && - (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME)) - return BAD_FUNC_ARG; - - if (produced_tm == NULL) - return BAD_FUNC_ARG; - - if (ExtractDate(ssl->ocspProducedDate, - (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx)) - return 0; - else - return ASN_PARSE_E; -} -#endif - - -#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ - defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) -int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain) -{ - word32 idx; - word32 length; - WOLFSSL_STACK* node; - WOLFSSL_STACK* last = NULL; - - if (ctx == NULL || chain == NULL) { - chain = NULL; - return WOLFSSL_FAILURE; - } - if (ctx->x509Chain != NULL) { - *chain = ctx->x509Chain; - return WOLFSSL_SUCCESS; - } - - /* If there are no chains then success! */ - *chain = NULL; - if (ctx->certChain == NULL || ctx->certChain->length == 0) { - return WOLFSSL_SUCCESS; - } - - /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ - for (idx = 0; idx < ctx->certChain->length; ) { - node = wolfSSL_sk_X509_new_null(); - if (node == NULL) - return WOLFSSL_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_ex(NULL, - ctx->certChain->buffer + idx, length, ctx->heap); - if (node->data.x509 == NULL) { - XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); - /* Return as much of the chain as we created. */ - ctx->x509Chain = *chain; - return WOLFSSL_FAILURE; - } - idx += length; - - /* Add object to the end of the stack. */ - if (last == NULL) { - node->num = 1; - *chain = node; - } - else { - (*chain)->num++; - last->next = node; - } - - last = node; - } - - ctx->x509Chain = *chain; - - return WOLFSSL_SUCCESS; -} - -int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb) -{ - if (ctx == NULL || ctx->cm == NULL || cb == NULL) - return WOLFSSL_FAILURE; - -#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) - if (ctx->cm->ocsp_stapling == NULL) - return WOLFSSL_FAILURE; - - *cb = ctx->cm->ocsp_stapling->statusCb; -#else - (void)cb; - *cb = NULL; -#endif - - return WOLFSSL_SUCCESS; - -} - -int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb) -{ - if (ctx == NULL || ctx->cm == NULL) - return WOLFSSL_FAILURE; - -#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) - /* Ensure stapling is on for callback to be used. */ - wolfSSL_CTX_EnableOCSPStapling(ctx); - - if (ctx->cm->ocsp_stapling == NULL) - return WOLFSSL_FAILURE; - - ctx->cm->ocsp_stapling->statusCb = cb; -#else - (void)cb; -#endif - - return WOLFSSL_SUCCESS; -} - -int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx, - WOLF_STACK_OF(WOLFSSL_X509) **sk) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs"); - if (ctx == NULL || sk == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - - /* This function should return ctx->x509Chain if it is populated, otherwise - it should be populated from ctx->certChain. This matches the behavior of - wolfSSL_CTX_get_extra_chain_certs, so it is used directly. */ - return wolfSSL_CTX_get_extra_chain_certs(ctx, sk); -} - -#ifdef KEEP_OUR_CERT -int wolfSSL_get0_chain_certs(WOLFSSL *ssl, - WOLF_STACK_OF(WOLFSSL_X509) **sk) -{ - WOLFSSL_ENTER("wolfSSL_get0_chain_certs"); - if (ssl == NULL || sk == NULL) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - *sk = ssl->ourCertChain; - return WOLFSSL_SUCCESS; -} -#endif - -WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void) -{ - WOLF_STACK_OF(WOLFSSL_STRING)* ret = wolfSSL_sk_new_node(NULL); - - if (ret) { - ret->type = STACK_TYPE_STRING; - } - - return ret; -} - -void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s) -{ - WOLFSSL_ENTER("wolfSSL_WOLFSSL_STRING_free"); - - if (s != NULL) - XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); -} - -void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* sk) -{ - WOLFSSL_STACK* tmp; - WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free"); - - if (sk == NULL) - return; - - /* parse through stack freeing each node */ - while (sk) { - tmp = sk->next; - XFREE(sk->data.string, NULL, DYNAMIC_TYPE_OPENSSL); - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = tmp; - } -} - -WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value(WOLF_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; -} - -int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings) -{ - if (strings) - return (int)strings->num; - return 0; -} - -#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_QUIC) -#ifdef HAVE_ALPN -void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, - unsigned int *len) -{ - word16 nameLen; - - if (ssl != NULL && data != NULL && len != NULL) { - TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); - *len = nameLen; - } -} - -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) -{ - unsigned int i, j; - byte lenIn, lenClient; - - 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++]; - - 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_set_alpn_select_cb(WOLFSSL *ssl, - int (*cb) (WOLFSSL *ssl, - const unsigned char **out, - unsigned char *outlen, - const unsigned char *in, - unsigned int inlen, - void *arg), void *arg) -{ - if (ssl != NULL) { - ssl->alpnSelect = cb; - ssl->alpnSelectArg = arg; - } -} - -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) { - ctx->alpnSelect = cb; - ctx->alpnSelectArg = arg; - } -} - -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"); -} - -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) -{ - (void)s; - (void)cb; - (void)arg; - WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); -} - -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 */ - -#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ - -#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) -int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id) -{ - if (curve_id >= WOLFSSL_FFDHE_START) { - /* DH parameters are never disabled. */ - return 0; - } - if (curve_id > WOLFSSL_ECC_MAX_AVAIL) { - WOLFSSL_MSG("Curve id out of supported range"); - /* Disabled if not in valid range. */ - return 1; - } - if (curve_id >= 32) { - /* 0 is for invalid and 1-14 aren't used otherwise. */ - return (ssl->disabledCurves & (1U << (curve_id - 32))) != 0; - } - return (ssl->disabledCurves & (1U << curve_id)) != 0; -} - -#if (defined(HAVE_ECC) || \ - defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) -static int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names) -{ - int idx, start = 0, len, i, ret = WOLFSSL_FAILURE; - word16 curve; - word32 disabled; - char name[MAX_CURVE_NAME_SZ]; - byte groups_len = 0; -#ifdef WOLFSSL_SMALL_STACK - void *heap = ssl? ssl->heap : ctx ? ctx->heap : NULL; - int *groups; -#else - int groups[WOLFSSL_MAX_GROUP_COUNT]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - groups = (int*)XMALLOC(sizeof(int)*WOLFSSL_MAX_GROUP_COUNT, - heap, DYNAMIC_TYPE_TMP_BUFFER); - if (groups == NULL) { - ret = MEMORY_E; - goto leave; - } -#endif - - for (idx = 1; names[idx-1] != '\0'; idx++) { - if (names[idx] != ':' && names[idx] != '\0') - continue; - - len = idx - start; - if (len > MAX_CURVE_NAME_SZ - 1) - goto leave; - - XMEMCPY(name, names + start, len); - name[len++] = 0; - - /* Use XSTRNCMP to avoid valgrind error. */ - if ((XSTRNCMP(name, "prime256v1", len) == 0) || - (XSTRNCMP(name, "secp256r1", len) == 0) || - (XSTRNCMP(name, "P-256", len) == 0)) - { - curve = WOLFSSL_ECC_SECP256R1; - } - else if ((XSTRNCMP(name, "secp384r1", len) == 0) || - (XSTRNCMP(name, "P-384", len) == 0)) - { - curve = WOLFSSL_ECC_SECP384R1; - } - else if ((XSTRNCMP(name, "secp521r1", len) == 0) || - (XSTRNCMP(name, "P-521", len) == 0)) - { - curve = WOLFSSL_ECC_SECP521R1; - } - #ifdef WOLFSSL_SM2 - else if ((XSTRNCMP(name, "sm2p256v1", len) == 0) || - (XSTRNCMP(name, "SM2", len) == 0)) - { - curve = WOLFSSL_ECC_SM2P256V1; - } - #endif - #ifdef HAVE_CURVE25519 - else if (XSTRNCMP(name, "X25519", len) == 0) - { - curve = WOLFSSL_ECC_X25519; - } - #endif - #ifdef HAVE_CURVE448 - else if (XSTRNCMP(name, "X448", len) == 0) - { - curve = WOLFSSL_ECC_X448; - } - #endif - else { - #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) - int nret; - const ecc_set_type *eccSet; - - nret = wc_ecc_get_curve_idx_from_name(name); - if (nret < 0) { - WOLFSSL_MSG("Could not find name in set"); - goto leave; - } - - eccSet = wc_ecc_get_curve_params(ret); - if (eccSet == NULL) { - WOLFSSL_MSG("NULL set returned"); - goto leave; - } - - curve = GetCurveByOID(eccSet->oidSum); - #else - WOLFSSL_MSG("API not present to search farther using name"); - goto leave; - #endif - } - - if (curve >= WOLFSSL_ECC_MAX_AVAIL) { - WOLFSSL_MSG("curve value is not supported"); - goto leave; - } - - for (i = 0; i < groups_len; ++i) { - if (groups[i] == curve) { - /* silently drop duplicates */ - break; - } - } - if (i >= groups_len) { - if (groups_len >= WOLFSSL_MAX_GROUP_COUNT) { - WOLFSSL_MSG_EX("setting %d or more supported " - "curves is not permitted", groups_len); - goto leave; - } - groups[groups_len++] = (int)curve; - } - - start = idx + 1; - } - - /* Disable all curves so that only the ones the user wants are enabled. */ - disabled = 0xFFFFFFFFUL; - for (i = 0; i < groups_len; ++i) { - /* Switch the bit to off and therefore is enabled. */ - curve = (word16)groups[i]; - if (curve >= 32) { - /* 0 is for invalid and 1-14 aren't used otherwise. */ - disabled &= ~(1U << (curve - 32)); - } - else { - disabled &= ~(1U << curve); - } - #ifdef HAVE_SUPPORTED_CURVES - #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_OLD_SET_CURVES_LIST) - /* using the wolfSSL API to set the groups, this will populate - * (ssl|ctx)->groups and reset any TLSX_SUPPORTED_GROUPS. - * The order in (ssl|ctx)->groups will then be respected - * when TLSX_KEY_SHARE needs to be established */ - if ((ssl && wolfSSL_set_groups(ssl, groups, groups_len) - != WOLFSSL_SUCCESS) - || (ctx && wolfSSL_CTX_set_groups(ctx, groups, groups_len) - != WOLFSSL_SUCCESS)) { - WOLFSSL_MSG("Unable to set supported curve"); - goto leave; - } - #elif !defined(NO_WOLFSSL_CLIENT) - /* set the supported curve so client TLS extension contains only the - * desired curves */ - if ((ssl && wolfSSL_UseSupportedCurve(ssl, curve) != WOLFSSL_SUCCESS) - || (ctx && wolfSSL_CTX_UseSupportedCurve(ctx, curve) - != WOLFSSL_SUCCESS)) { - WOLFSSL_MSG("Unable to set supported curve"); - goto leave; - } - #endif - #endif /* HAVE_SUPPORTED_CURVES */ - } - - if (ssl) - ssl->disabledCurves = disabled; - else - ctx->disabledCurves = disabled; - ret = WOLFSSL_SUCCESS; - -leave: -#ifdef WOLFSSL_SMALL_STACK - if (groups) - XFREE((void*)groups, heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; -} - -int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names) -{ - if (ctx == NULL || names == NULL) { - WOLFSSL_MSG("ctx or names was NULL"); - return WOLFSSL_FAILURE; - } - return set_curves_list(NULL, ctx, names); -} - -int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names) -{ - if (ssl == NULL || names == NULL) { - WOLFSSL_MSG("ssl or names was NULL"); - return WOLFSSL_FAILURE; - } - return set_curves_list(ssl, NULL, names); -} -#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) */ -#endif /* OPENSSL_EXTRA || HAVE_CURL */ - -#ifdef OPENSSL_EXTRA -/* Sets a callback for when sending and receiving protocol messages. - * This callback is copied to all WOLFSSL objects created from the ctx. - * - * ctx WOLFSSL_CTX structure to set callback in - * cb callback to use - * - * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE with error case - */ -int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback"); - if (ctx == NULL) { - WOLFSSL_MSG("Null ctx passed in"); - return WOLFSSL_FAILURE; - } - - ctx->protoMsgCb = cb; - return WOLFSSL_SUCCESS; -} - - -/* Sets a callback for when sending and receiving protocol messages. - * - * ssl WOLFSSL structure to set callback in - * cb callback to use - * - * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE with error case - */ -int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) -{ - WOLFSSL_ENTER("wolfSSL_set_msg_callback"); - - if (ssl == NULL) { - return WOLFSSL_FAILURE; - } - - if (cb != NULL) { - ssl->toInfoOn = 1; - } - - ssl->protoMsgCb = cb; - return WOLFSSL_SUCCESS; -} - - -/* set the user argument to pass to the msg callback when called - * return WOLFSSL_SUCCESS on success */ -int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback_arg"); - if (ctx == NULL) { - WOLFSSL_MSG("Null WOLFSSL_CTX passed in"); - return WOLFSSL_FAILURE; - } - - ctx->protoMsgCtx = arg; - return WOLFSSL_SUCCESS; -} - - -int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) -{ - WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg"); - if (ssl == NULL) - return WOLFSSL_FAILURE; - - ssl->protoMsgCtx = arg; - return WOLFSSL_SUCCESS; -} - -void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line) -{ - void *ret; - (void)file; - (void)line; - - if (data == NULL || siz >= INT_MAX) - return NULL; - - ret = OPENSSL_malloc(siz); - if (ret == NULL) { - return NULL; - } - return XMEMCPY(ret, data, siz); -} - -void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len) -{ - if (ptr) - ForceZero(ptr, (word32)len); -} - -int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p, - unsigned int p_len) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos"); - if (ctx == NULL) - return BAD_FUNC_ARG; - if (ctx->alpn_cli_protos != NULL) { - XFREE((void*)ctx->alpn_cli_protos, ctx->heap, DYNAMIC_TYPE_OPENSSL); - } - - ctx->alpn_cli_protos = (const unsigned char*)XMALLOC(p_len, - ctx->heap, DYNAMIC_TYPE_OPENSSL); - if (ctx->alpn_cli_protos == NULL) { -#if defined(WOLFSSL_ERROR_CODE_OPENSSL) - /* 0 on success in OpenSSL, non-0 on failure in OpenSSL - * the function reverses the return value convention. - */ - return 1; -#else - return WOLFSSL_FAILURE; -#endif - } - XMEMCPY((void*)ctx->alpn_cli_protos, p, p_len); - ctx->alpn_cli_protos_len = p_len; - -#if defined(WOLFSSL_ERROR_CODE_OPENSSL) - /* 0 on success in OpenSSL, non-0 on failure in OpenSSL - * the function reverses the return value convention. - */ - return 0; -#else - return WOLFSSL_SUCCESS; -#endif -} - - -#ifdef HAVE_ALPN -#ifndef NO_BIO -/* Sets the ALPN extension protos - * - * example format is - * unsigned char p[] = { - * 8, 'h', 't', 't', 'p', '/', '1', '.', '1' - * }; - * - * returns WOLFSSL_SUCCESS on success */ -int wolfSSL_set_alpn_protos(WOLFSSL* ssl, - const unsigned char* p, unsigned int p_len) -{ - WOLFSSL_BIO* bio; - char* pt = NULL; - - unsigned int sz; - unsigned int idx = 0; - int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; - WOLFSSL_ENTER("wolfSSL_set_alpn_protos"); - - if (ssl == NULL || p_len <= 1) { -#if defined(WOLFSSL_ERROR_CODE_OPENSSL) - /* 0 on success in OpenSSL, non-0 on failure in OpenSSL - * the function reverses the return value convention. - */ - return 1; -#else - return WOLFSSL_FAILURE; -#endif - } - - bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); - if (bio == NULL) { -#if defined(WOLFSSL_ERROR_CODE_OPENSSL) - /* 0 on success in OpenSSL, non-0 on failure in OpenSSL - * the function reverses the return value convention. - */ - return 1; -#else - return WOLFSSL_FAILURE; -#endif - } - - /* convert into comma separated list */ - while (idx < p_len - 1) { - unsigned int i; - - sz = p[idx++]; - if (idx + sz > p_len) { - WOLFSSL_MSG("Bad list format"); - wolfSSL_BIO_free(bio); - #if defined(WOLFSSL_ERROR_CODE_OPENSSL) - /* 0 on success in OpenSSL, non-0 on failure in OpenSSL - * the function reverses the return value convention. - */ - return 1; - #else - return WOLFSSL_FAILURE; - #endif - } - if (sz > 0) { - for (i = 0; i < sz; i++) { - wolfSSL_BIO_write(bio, &p[idx++], 1); - } - if (idx < p_len - 1) - wolfSSL_BIO_write(bio, ",", 1); - } - } - wolfSSL_BIO_write(bio, "\0", 1); - - /* clears out all current ALPN extensions set */ - TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap); - - if ((sz = wolfSSL_BIO_get_mem_data(bio, &pt)) > 0) { - wolfSSL_UseALPN(ssl, pt, sz, (byte) alpn_opt); - } - wolfSSL_BIO_free(bio); -#if defined(WOLFSSL_ERROR_CODE_OPENSSL) - /* 0 on success in OpenSSL, non-0 on failure in OpenSSL - * the function reverses the return value convention. - */ - return 0; -#else - return WOLFSSL_SUCCESS; -#endif -} -#endif /* !NO_BIO */ -#endif /* HAVE_ALPN */ -#endif /* OPENSSL_EXTRA */ - -#if defined(OPENSSL_EXTRA) - -#ifndef NO_BIO -#define WOLFSSL_BIO_INCLUDED -#include "src/bio.c" -#endif - -word32 nid2oid(int nid, int grp) -{ - /* get OID type */ - switch (grp) { - /* oidHashType */ - case oidHashType: - switch (nid) { - #ifdef WOLFSSL_MD2 - case NID_md2: - return MD2h; - #endif - #ifndef NO_MD5 - case NID_md5: - return MD5h; - #endif - #ifndef NO_SHA - case NID_sha1: - return SHAh; - #endif - case NID_sha224: - return SHA224h; - #ifndef NO_SHA256 - case NID_sha256: - return SHA256h; - #endif - #ifdef WOLFSSL_SHA384 - case NID_sha384: - return SHA384h; - #endif - #ifdef WOLFSSL_SHA512 - case NID_sha512: - return SHA512h; - #endif - #ifndef WOLFSSL_NOSHA3_224 - case NID_sha3_224: - return SHA3_224h; - #endif - #ifndef WOLFSSL_NOSHA3_256 - case NID_sha3_256: - return SHA3_256h; - #endif - #ifndef WOLFSSL_NOSHA3_384 - case NID_sha3_384: - return SHA3_384h; - #endif - #ifndef WOLFSSL_NOSHA3_512 - case NID_sha3_512: - return SHA3_512h; - #endif - } - break; - - /* oidSigType */ - case oidSigType: - switch (nid) { - #ifndef NO_DSA - case NID_dsaWithSHA1: - return CTC_SHAwDSA; - case NID_dsa_with_SHA256: - return CTC_SHA256wDSA; - #endif /* NO_DSA */ - #ifndef NO_RSA - case NID_md2WithRSAEncryption: - return CTC_MD2wRSA; - case NID_md5WithRSAEncryption: - return CTC_MD5wRSA; - case NID_sha1WithRSAEncryption: - return CTC_SHAwRSA; - case NID_sha224WithRSAEncryption: - return CTC_SHA224wRSA; - case NID_sha256WithRSAEncryption: - return CTC_SHA256wRSA; - case NID_sha384WithRSAEncryption: - return CTC_SHA384wRSA; - case NID_sha512WithRSAEncryption: - return CTC_SHA512wRSA; - #ifdef WOLFSSL_SHA3 - case NID_RSA_SHA3_224: - return CTC_SHA3_224wRSA; - case NID_RSA_SHA3_256: - return CTC_SHA3_256wRSA; - case NID_RSA_SHA3_384: - return CTC_SHA3_384wRSA; - case NID_RSA_SHA3_512: - return CTC_SHA3_512wRSA; - #endif - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case NID_ecdsa_with_SHA1: - return CTC_SHAwECDSA; - case NID_ecdsa_with_SHA224: - return CTC_SHA224wECDSA; - case NID_ecdsa_with_SHA256: - return CTC_SHA256wECDSA; - case NID_ecdsa_with_SHA384: - return CTC_SHA384wECDSA; - case NID_ecdsa_with_SHA512: - return CTC_SHA512wECDSA; - #ifdef WOLFSSL_SHA3 - case NID_ecdsa_with_SHA3_224: - return CTC_SHA3_224wECDSA; - case NID_ecdsa_with_SHA3_256: - return CTC_SHA3_256wECDSA; - case NID_ecdsa_with_SHA3_384: - return CTC_SHA3_384wECDSA; - case NID_ecdsa_with_SHA3_512: - return CTC_SHA3_512wECDSA; - #endif - #endif /* HAVE_ECC */ - } - break; - - /* oidKeyType */ - case oidKeyType: - switch (nid) { - #ifndef NO_DSA - case NID_dsa: - return DSAk; - #endif /* NO_DSA */ - #ifndef NO_RSA - case NID_rsaEncryption: - return RSAk; - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case NID_X9_62_id_ecPublicKey: - return ECDSAk; - #endif /* HAVE_ECC */ - } - break; - - - #ifdef HAVE_ECC - case oidCurveType: - switch (nid) { - case NID_X9_62_prime192v1: - return ECC_SECP192R1_OID; - case NID_X9_62_prime192v2: - return ECC_PRIME192V2_OID; - case NID_X9_62_prime192v3: - return ECC_PRIME192V3_OID; - case NID_X9_62_prime239v1: - return ECC_PRIME239V1_OID; - case NID_X9_62_prime239v2: - return ECC_PRIME239V2_OID; - case NID_X9_62_prime239v3: - return ECC_PRIME239V3_OID; - case NID_X9_62_prime256v1: - return ECC_SECP256R1_OID; - case NID_secp112r1: - return ECC_SECP112R1_OID; - case NID_secp112r2: - return ECC_SECP112R2_OID; - case NID_secp128r1: - return ECC_SECP128R1_OID; - case NID_secp128r2: - return ECC_SECP128R2_OID; - case NID_secp160r1: - return ECC_SECP160R1_OID; - case NID_secp160r2: - return ECC_SECP160R2_OID; - case NID_secp224r1: - return ECC_SECP224R1_OID; - case NID_secp384r1: - return ECC_SECP384R1_OID; - case NID_secp521r1: - return ECC_SECP521R1_OID; - case NID_secp160k1: - return ECC_SECP160K1_OID; - case NID_secp192k1: - return ECC_SECP192K1_OID; - case NID_secp224k1: - return ECC_SECP224K1_OID; - case NID_secp256k1: - return ECC_SECP256K1_OID; - case NID_brainpoolP160r1: - return ECC_BRAINPOOLP160R1_OID; - case NID_brainpoolP192r1: - return ECC_BRAINPOOLP192R1_OID; - case NID_brainpoolP224r1: - return ECC_BRAINPOOLP224R1_OID; - case NID_brainpoolP256r1: - return ECC_BRAINPOOLP256R1_OID; - case NID_brainpoolP320r1: - return ECC_BRAINPOOLP320R1_OID; - case NID_brainpoolP384r1: - return ECC_BRAINPOOLP384R1_OID; - case NID_brainpoolP512r1: - return ECC_BRAINPOOLP512R1_OID; - } - break; - #endif /* HAVE_ECC */ - - /* oidBlkType */ - case oidBlkType: - switch (nid) { - #ifdef WOLFSSL_AES_128 - case AES128CBCb: - return AES128CBCb; - #endif - #ifdef WOLFSSL_AES_192 - case AES192CBCb: - return AES192CBCb; - #endif - #ifdef WOLFSSL_AES_256 - case AES256CBCb: - return AES256CBCb; - #endif - #ifndef NO_DES3 - case NID_des: - return DESb; - case NID_des3: - return DES3b; - #endif - } - break; - - #ifdef HAVE_OCSP - case oidOcspType: - switch (nid) { - case NID_id_pkix_OCSP_basic: - return OCSP_BASIC_OID; - case OCSP_NONCE_OID: - return OCSP_NONCE_OID; - } - break; - #endif /* HAVE_OCSP */ - - /* oidCertExtType */ - case oidCertExtType: - switch (nid) { - case NID_basic_constraints: - return BASIC_CA_OID; - case NID_subject_alt_name: - return ALT_NAMES_OID; - case NID_crl_distribution_points: - return CRL_DIST_OID; - case NID_info_access: - return AUTH_INFO_OID; - case NID_authority_key_identifier: - return AUTH_KEY_OID; - case NID_subject_key_identifier: - return SUBJ_KEY_OID; - case NID_inhibit_any_policy: - return INHIBIT_ANY_OID; - case NID_key_usage: - return KEY_USAGE_OID; - case NID_name_constraints: - return NAME_CONS_OID; - case NID_certificate_policies: - return CERT_POLICY_OID; - case NID_ext_key_usage: - return EXT_KEY_USAGE_OID; - } - break; - - /* oidCertAuthInfoType */ - case oidCertAuthInfoType: - switch (nid) { - case NID_ad_OCSP: - return AIA_OCSP_OID; - case NID_ad_ca_issuers: - return AIA_CA_ISSUER_OID; - } - break; - - /* oidCertPolicyType */ - case oidCertPolicyType: - switch (nid) { - case NID_any_policy: - return CP_ANY_OID; - } - break; - - /* oidCertAltNameType */ - case oidCertAltNameType: - switch (nid) { - case NID_hw_name_oid: - return HW_NAME_OID; - } - break; - - /* oidCertKeyUseType */ - case oidCertKeyUseType: - switch (nid) { - case NID_anyExtendedKeyUsage: - return EKU_ANY_OID; - case EKU_SERVER_AUTH_OID: - return EKU_SERVER_AUTH_OID; - case EKU_CLIENT_AUTH_OID: - return EKU_CLIENT_AUTH_OID; - case EKU_OCSP_SIGN_OID: - return EKU_OCSP_SIGN_OID; - } - break; - - /* oidKdfType */ - case oidKdfType: - switch (nid) { - case PBKDF2_OID: - return PBKDF2_OID; - } - break; - - /* oidPBEType */ - case oidPBEType: - switch (nid) { - case PBE_SHA1_RC4_128: - return PBE_SHA1_RC4_128; - case PBE_SHA1_DES: - return PBE_SHA1_DES; - case PBE_SHA1_DES3: - return PBE_SHA1_DES3; - } - break; - - /* oidKeyWrapType */ - case oidKeyWrapType: - switch (nid) { - #ifdef WOLFSSL_AES_128 - case AES128_WRAP: - return AES128_WRAP; - #endif - #ifdef WOLFSSL_AES_192 - case AES192_WRAP: - return AES192_WRAP; - #endif - #ifdef WOLFSSL_AES_256 - case AES256_WRAP: - return AES256_WRAP; - #endif - } - break; - - /* oidCmsKeyAgreeType */ - case oidCmsKeyAgreeType: - switch (nid) { - #ifndef NO_SHA - case dhSinglePass_stdDH_sha1kdf_scheme: - return dhSinglePass_stdDH_sha1kdf_scheme; - #endif - #ifdef WOLFSSL_SHA224 - case dhSinglePass_stdDH_sha224kdf_scheme: - return dhSinglePass_stdDH_sha224kdf_scheme; - #endif - #ifndef NO_SHA256 - case dhSinglePass_stdDH_sha256kdf_scheme: - return dhSinglePass_stdDH_sha256kdf_scheme; - #endif - #ifdef WOLFSSL_SHA384 - case dhSinglePass_stdDH_sha384kdf_scheme: - return dhSinglePass_stdDH_sha384kdf_scheme; - #endif - #ifdef WOLFSSL_SHA512 - case dhSinglePass_stdDH_sha512kdf_scheme: - return dhSinglePass_stdDH_sha512kdf_scheme; - #endif - } - break; - - /* oidCmsKeyAgreeType */ - #ifdef WOLFSSL_CERT_REQ - case oidCsrAttrType: - switch (nid) { - case NID_pkcs9_contentType: - return PKCS9_CONTENT_TYPE_OID; - case NID_pkcs9_challengePassword: - return CHALLENGE_PASSWORD_OID; - case NID_serialNumber: - return SERIAL_NUMBER_OID; - case NID_userId: - return USER_ID_OID; - case NID_surname: - return SURNAME_OID; - } - break; - #endif - - default: - WOLFSSL_MSG("NID not in table"); - /* MSVC warns without the cast */ - return (word32)-1; - } - - /* MSVC warns without the cast */ - return (word32)-1; -} - -int oid2nid(word32 oid, int grp) -{ - size_t i; - /* get OID type */ - switch (grp) { - /* oidHashType */ - case oidHashType: - switch (oid) { - #ifdef WOLFSSL_MD2 - case MD2h: - return NID_md2; - #endif - #ifndef NO_MD5 - case MD5h: - return NID_md5; - #endif - #ifndef NO_SHA - case SHAh: - return NID_sha1; - #endif - case SHA224h: - return NID_sha224; - #ifndef NO_SHA256 - case SHA256h: - return NID_sha256; - #endif - #ifdef WOLFSSL_SHA384 - case SHA384h: - return NID_sha384; - #endif - #ifdef WOLFSSL_SHA512 - case SHA512h: - return NID_sha512; - #endif - } - break; - - /* oidSigType */ - case oidSigType: - switch (oid) { - #ifndef NO_DSA - case CTC_SHAwDSA: - return NID_dsaWithSHA1; - case CTC_SHA256wDSA: - return NID_dsa_with_SHA256; - #endif /* NO_DSA */ - #ifndef NO_RSA - case CTC_MD2wRSA: - return NID_md2WithRSAEncryption; - case CTC_MD5wRSA: - return NID_md5WithRSAEncryption; - case CTC_SHAwRSA: - return NID_sha1WithRSAEncryption; - case CTC_SHA224wRSA: - return NID_sha224WithRSAEncryption; - case CTC_SHA256wRSA: - return NID_sha256WithRSAEncryption; - case CTC_SHA384wRSA: - return NID_sha384WithRSAEncryption; - case CTC_SHA512wRSA: - return NID_sha512WithRSAEncryption; - #ifdef WOLFSSL_SHA3 - case CTC_SHA3_224wRSA: - return NID_RSA_SHA3_224; - case CTC_SHA3_256wRSA: - return NID_RSA_SHA3_256; - case CTC_SHA3_384wRSA: - return NID_RSA_SHA3_384; - case CTC_SHA3_512wRSA: - return NID_RSA_SHA3_512; - #endif - #ifdef WC_RSA_PSS - case CTC_RSASSAPSS: - return NID_rsassaPss; - #endif - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case CTC_SHAwECDSA: - return NID_ecdsa_with_SHA1; - case CTC_SHA224wECDSA: - return NID_ecdsa_with_SHA224; - case CTC_SHA256wECDSA: - return NID_ecdsa_with_SHA256; - case CTC_SHA384wECDSA: - return NID_ecdsa_with_SHA384; - case CTC_SHA512wECDSA: - return NID_ecdsa_with_SHA512; - #ifdef WOLFSSL_SHA3 - case CTC_SHA3_224wECDSA: - return NID_ecdsa_with_SHA3_224; - case CTC_SHA3_256wECDSA: - return NID_ecdsa_with_SHA3_256; - case CTC_SHA3_384wECDSA: - return NID_ecdsa_with_SHA3_384; - case CTC_SHA3_512wECDSA: - return NID_ecdsa_with_SHA3_512; - #endif - #endif /* HAVE_ECC */ - } - break; - - /* oidKeyType */ - case oidKeyType: - switch (oid) { - #ifndef NO_DSA - case DSAk: - return NID_dsa; - #endif /* NO_DSA */ - #ifndef NO_RSA - case RSAk: - return NID_rsaEncryption; - #ifdef WC_RSA_PSS - case RSAPSSk: - return NID_rsassaPss; - #endif - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - return NID_X9_62_id_ecPublicKey; - #endif /* HAVE_ECC */ - } - break; - - - #ifdef HAVE_ECC - case oidCurveType: - switch (oid) { - case ECC_SECP192R1_OID: - return NID_X9_62_prime192v1; - case ECC_PRIME192V2_OID: - return NID_X9_62_prime192v2; - case ECC_PRIME192V3_OID: - return NID_X9_62_prime192v3; - case ECC_PRIME239V1_OID: - return NID_X9_62_prime239v1; - case ECC_PRIME239V2_OID: - return NID_X9_62_prime239v2; - case ECC_PRIME239V3_OID: - return NID_X9_62_prime239v3; - case ECC_SECP256R1_OID: - return NID_X9_62_prime256v1; - case ECC_SECP112R1_OID: - return NID_secp112r1; - case ECC_SECP112R2_OID: - return NID_secp112r2; - case ECC_SECP128R1_OID: - return NID_secp128r1; - case ECC_SECP128R2_OID: - return NID_secp128r2; - case ECC_SECP160R1_OID: - return NID_secp160r1; - case ECC_SECP160R2_OID: - return NID_secp160r2; - case ECC_SECP224R1_OID: - return NID_secp224r1; - case ECC_SECP384R1_OID: - return NID_secp384r1; - case ECC_SECP521R1_OID: - return NID_secp521r1; - case ECC_SECP160K1_OID: - return NID_secp160k1; - case ECC_SECP192K1_OID: - return NID_secp192k1; - case ECC_SECP224K1_OID: - return NID_secp224k1; - case ECC_SECP256K1_OID: - return NID_secp256k1; - case ECC_BRAINPOOLP160R1_OID: - return NID_brainpoolP160r1; - case ECC_BRAINPOOLP192R1_OID: - return NID_brainpoolP192r1; - case ECC_BRAINPOOLP224R1_OID: - return NID_brainpoolP224r1; - case ECC_BRAINPOOLP256R1_OID: - return NID_brainpoolP256r1; - case ECC_BRAINPOOLP320R1_OID: - return NID_brainpoolP320r1; - case ECC_BRAINPOOLP384R1_OID: - return NID_brainpoolP384r1; - case ECC_BRAINPOOLP512R1_OID: - return NID_brainpoolP512r1; - } - break; - #endif /* HAVE_ECC */ - - /* oidBlkType */ - case oidBlkType: - switch (oid) { - #ifdef WOLFSSL_AES_128 - case AES128CBCb: - return AES128CBCb; - #endif - #ifdef WOLFSSL_AES_192 - case AES192CBCb: - return AES192CBCb; - #endif - #ifdef WOLFSSL_AES_256 - case AES256CBCb: - return AES256CBCb; - #endif - #ifndef NO_DES3 - case DESb: - return NID_des; - case DES3b: - return NID_des3; - #endif - } - break; - - #ifdef HAVE_OCSP - case oidOcspType: - switch (oid) { - case OCSP_BASIC_OID: - return NID_id_pkix_OCSP_basic; - case OCSP_NONCE_OID: - return OCSP_NONCE_OID; - } - break; - #endif /* HAVE_OCSP */ +#if defined(OPENSSL_EXTRA) - /* oidCertExtType */ - case oidCertExtType: - switch (oid) { - case BASIC_CA_OID: - return NID_basic_constraints; - case ALT_NAMES_OID: - return NID_subject_alt_name; - case CRL_DIST_OID: - return NID_crl_distribution_points; - case AUTH_INFO_OID: - return NID_info_access; - case AUTH_KEY_OID: - return NID_authority_key_identifier; - case SUBJ_KEY_OID: - return NID_subject_key_identifier; - case INHIBIT_ANY_OID: - return NID_inhibit_any_policy; - case KEY_USAGE_OID: - return NID_key_usage; - case NAME_CONS_OID: - return NID_name_constraints; - case CERT_POLICY_OID: - return NID_certificate_policies; - case EXT_KEY_USAGE_OID: - return NID_ext_key_usage; - } - break; +int wolfSSL_CRYPTO_memcmp(const void *a, const void *b, size_t size) +{ + if (!a || !b) + return 0; + return ConstantCompare((const byte*)a, (const byte*)b, (int)size); +} - /* oidCertAuthInfoType */ - case oidCertAuthInfoType: - switch (oid) { - case AIA_OCSP_OID: - return NID_ad_OCSP; - case AIA_CA_ISSUER_OID: - return NID_ad_ca_issuers; - } - break; +unsigned long wolfSSL_ERR_peek_last_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - /* oidCertPolicyType */ - case oidCertPolicyType: - switch (oid) { - case CP_ANY_OID: - return NID_any_policy; - } - break; +#ifdef WOLFSSL_HAVE_ERROR_QUEUE + { + int ret; - /* oidCertAltNameType */ - case oidCertAltNameType: - switch (oid) { - case HW_NAME_OID: - return NID_hw_name_oid; - } - break; + if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + if (ret == -ASN_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #if defined(WOLFSSL_PYTHON) + if (ret == ASN1_R_HEADER_TOO_LONG) + return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; + #endif + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} - /* oidCertKeyUseType */ - case oidCertKeyUseType: - switch (oid) { - case EKU_ANY_OID: - return NID_anyExtendedKeyUsage; - case EKU_SERVER_AUTH_OID: - return EKU_SERVER_AUTH_OID; - case EKU_CLIENT_AUTH_OID: - return EKU_CLIENT_AUTH_OID; - case EKU_OCSP_SIGN_OID: - return EKU_OCSP_SIGN_OID; - } - break; +#endif /* OPENSSL_EXTRA */ - /* oidKdfType */ - case oidKdfType: - switch (oid) { - case PBKDF2_OID: - return PBKDF2_OID; - } - break; +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 : + return TLS1_VERSION; + case TLSv1_1_MINOR : + return TLS1_1_VERSION; + case TLSv1_2_MINOR : + return TLS1_2_VERSION; + case TLSv1_3_MINOR : + return TLS1_3_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + return DTLS1_VERSION; + case DTLSv1_2_MINOR : + return DTLS1_2_VERSION; + case DTLSv1_3_MINOR: + return DTLS1_3_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_FAILURE; +} - /* oidPBEType */ - case oidPBEType: - switch (oid) { - case PBE_SHA1_RC4_128: - return PBE_SHA1_RC4_128; - case PBE_SHA1_DES: - return PBE_SHA1_DES; - case PBE_SHA1_DES3: - return PBE_SHA1_DES3; - } - break; +WOLFSSL_CTX* wolfSSL_get_SSL_CTX(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); + return ssl->ctx; +} - /* oidKeyWrapType */ - case oidKeyWrapType: - switch (oid) { - #ifdef WOLFSSL_AES_128 - case AES128_WRAP: - return AES128_WRAP; - #endif - #ifdef WOLFSSL_AES_192 - case AES192_WRAP: - return AES192_WRAP; - #endif - #ifdef WOLFSSL_AES_256 - case AES256_WRAP: - return AES256_WRAP; - #endif - } - break; +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) - /* oidCmsKeyAgreeType */ - case oidCmsKeyAgreeType: - switch (oid) { - #ifndef NO_SHA - case dhSinglePass_stdDH_sha1kdf_scheme: - return dhSinglePass_stdDH_sha1kdf_scheme; - #endif - #ifdef WOLFSSL_SHA224 - case dhSinglePass_stdDH_sha224kdf_scheme: - return dhSinglePass_stdDH_sha224kdf_scheme; - #endif - #ifndef NO_SHA256 - case dhSinglePass_stdDH_sha256kdf_scheme: - return dhSinglePass_stdDH_sha256kdf_scheme; - #endif - #ifdef WOLFSSL_SHA384 - case dhSinglePass_stdDH_sha384kdf_scheme: - return dhSinglePass_stdDH_sha384kdf_scheme; - #endif - #ifdef WOLFSSL_SHA512 - case dhSinglePass_stdDH_sha512kdf_scheme: - return dhSinglePass_stdDH_sha512kdf_scheme; - #endif - } - break; +/* TODO: Doesn't currently track SSL_VERIFY_CLIENT_ONCE */ +int wolfSSL_get_verify_mode(const WOLFSSL* ssl) { + int mode = 0; + WOLFSSL_ENTER("wolfSSL_get_verify_mode"); -#ifdef WOLFSSL_CERT_REQ - case oidCsrAttrType: - switch (oid) { - case PKCS9_CONTENT_TYPE_OID: - return NID_pkcs9_contentType; - case CHALLENGE_PASSWORD_OID: - return NID_pkcs9_challengePassword; - case SERIAL_NUMBER_OID: - return NID_serialNumber; - case USER_ID_OID: - return NID_userId; - } - break; + if (!ssl) { + return WOLFSSL_FAILURE; + } + + if (ssl->options.verifyNone) { + mode = WOLFSSL_VERIFY_NONE; + } + else { + if (ssl->options.verifyPeer) { + mode |= WOLFSSL_VERIFY_PEER; + } + if (ssl->options.failNoCert) { + mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; + } + if (ssl->options.failNoCertxPSK) { + mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; + } +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (ssl->options.verifyPostHandshake) { + mode |= WOLFSSL_VERIFY_POST_HANDSHAKE; + } #endif + } - default: - WOLFSSL_MSG("OID not in table"); + WOLFSSL_LEAVE("wolfSSL_get_verify_mode", mode); + return mode; +} + +int wolfSSL_CTX_get_verify_mode(const WOLFSSL_CTX* ctx) +{ + int mode = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); + + if (!ctx) { + return WOLFSSL_FAILURE; } - /* If not found in above switch then try the table */ - for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) { - if (wolfssl_object_info[i].id == (int)oid) { - return wolfssl_object_info[i].nid; + + if (ctx->verifyNone) { + mode = WOLFSSL_VERIFY_NONE; + } + else { + if (ctx->verifyPeer) { + mode |= WOLFSSL_VERIFY_PEER; + } + if (ctx->failNoCert) { + mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; + } + if (ctx->failNoCertxPSK) { + mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; + } +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (ctx->verifyPostHandshake) { + mode |= WOLFSSL_VERIFY_POST_HANDSHAKE; } +#endif } - return -1; + WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); + return mode; +} + +#endif + +#ifdef WOLFSSL_JNI + +int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) +{ + WOLFSSL_ENTER("wolfSSL_set_jobject"); + if (ssl != NULL) + { + ssl->jObjectRef = objPtr; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; } -/* frees all nodes in the current threads error queue - * - * id thread id. ERR_remove_state is depreciated and id is ignored. The - * current threads queue will be free'd. - */ -void wolfSSL_ERR_remove_state(unsigned long id) +void* wolfSSL_get_jobject(WOLFSSL* ssl) { - WOLFSSL_ENTER("wolfSSL_ERR_remove_state"); - (void)id; - if (wc_ERR_remove_state() != 0) { - WOLFSSL_MSG("Error with removing the state"); - } + WOLFSSL_ENTER("wolfSSL_get_jobject"); + if (ssl != NULL) + return ssl->jObjectRef; + return NULL; } -#endif /* OPENSSL_EXTRA */ +#endif /* WOLFSSL_JNI */ -#ifdef OPENSSL_ALL -#if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) -int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY* pkey, - const WOLFSSL_EVP_CIPHER* enc, - char* passwd, int passwdSz, - wc_pem_password_cb* cb, void* ctx) +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount) { - int ret = 0; - char password[NAME_SZ]; - byte* key = NULL; - word32 keySz; - byte* pem = NULL; - int pemSz = 0; - int type = PKCS8_PRIVATEKEY_TYPE; - const byte* curveOid; - word32 oidSz; - - if (bio == NULL || pkey == NULL) - return -1; - - keySz = pkey->pkey_sz + 128; - key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) - ret = MEMORY_E; - - if (ret == 0 && enc != NULL && passwd == NULL) { - passwdSz = cb(password, sizeof(password), 1, ctx); - if (passwdSz < 0) - ret = WOLFSSL_FAILURE; - passwd = password; + if (ctx == NULL) { + return BAD_FUNC_ARG; } - if (ret == 0 && enc != NULL) { - WC_RNG rng; - ret = wc_InitRng(&rng); - if (ret == 0) { - int encAlgId = 0; - #ifndef NO_DES3 - if (enc == EVP_DES_CBC) - encAlgId = DESb; - else if (enc == EVP_DES_EDE3_CBC) - encAlgId = DES3b; - else - #endif - #if !defined(NO_AES) && defined(HAVE_AES_CBC) - #ifdef WOLFSSL_AES_256 - if (enc == EVP_AES_256_CBC) - encAlgId = AES256CBCb; - else - #endif - #endif - ret = -1; - if (ret == 0) { - ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, key, - &keySz, passwd, passwdSz, PKCS5, PBES2, - encAlgId, NULL, 0, WC_PKCS12_ITT_DEFAULT, - &rng, NULL); - if (ret > 0) { - keySz = ret; - ret = 0; - } - } - wc_FreeRng(&rng); - } - type = PKCS8_ENC_PRIVATEKEY_TYPE; - } - if (ret == 0 && enc == NULL) { - int algId; - type = PKCS8_PRIVATEKEY_TYPE; - #ifdef HAVE_ECC - if (pkey->type == EVP_PKEY_EC) { - algId = ECDSAk; - ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid, - &oidSz); - } - else - #endif - { - algId = RSAk; - curveOid = NULL; - oidSz = 0; - } + return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, + events, maxEvents, flags, eventCount); +} - #ifdef HAVE_ECC - if (ret >= 0) - #endif - { - ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr, - pkey->pkey_sz, algId, curveOid, oidSz); - keySz = ret; - } - } +int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) +{ + int ret, eventCount = 0; + WOLF_EVENT* events[1]; - if (password == passwd) - XMEMSET(password, 0, passwdSz); + if (ssl == NULL) { + return BAD_FUNC_ARG; + } - if (ret >= 0) { - pemSz = 2 * keySz + 2 * 64; - pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (pem == NULL) - ret = MEMORY_E; + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, + events, sizeof(events)/sizeof(events[0]), flags, &eventCount); + if (ret == 0) { + ret = eventCount; } - if (ret >= 0) - ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type); + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ - if (key != NULL) - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef OPENSSL_EXTRA - if (ret >= 0) { - if (wolfSSL_BIO_write(bio, pem, ret) != ret) - ret = -1; - } +static int peek_ignore_err(int err) +{ + switch(err) { + case -WC_NO_ERR_TRACE(WANT_READ): + case -WC_NO_ERR_TRACE(WANT_WRITE): + case -WC_NO_ERR_TRACE(ZERO_RETURN): + case -WOLFSSL_ERROR_ZERO_RETURN: + case -WC_NO_ERR_TRACE(SOCKET_PEER_CLOSED_E): + case -WC_NO_ERR_TRACE(SOCKET_ERROR_E): + return 1; + default: + return 0; + } +} - if (pem != NULL) - XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + unsigned long err; - return ret < 0 ? 0 : ret; + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); + err = wc_PeekErrorNodeLineData(file, line, data, flags, peek_ignore_err); + if (err == -WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; +#ifdef OPENSSL_ALL + /* PARSE_ERROR is returned if an HTTP request is detected. */ + else if (err == -WC_NO_ERR_TRACE(PARSE_ERROR)) + return (ERR_LIB_SSL << 24) | -SSL_R_HTTP_REQUEST; +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_PYTHON) + else if (err == WC_NO_ERR_TRACE(ASN1_R_HEADER_TOO_LONG)) + return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; +#endif + return err; } +#endif -#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) -int wolfSSL_PEM_write_PKCS8PrivateKey(XFILE f, WOLFSSL_EVP_PKEY* pkey, - const WOLFSSL_EVP_CIPHER* enc, char* passwd, int passwdSz, - wc_pem_password_cb* cb, void* ctx) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +#if !defined(WOLFSSL_USER_IO) +/* converts an IPv6 or IPv4 address into an octet string for use with rfc3280 + * example input would be "127.0.0.1" and the returned value would be 7F000001 + */ +WOLFSSL_ASN1_STRING* wolfSSL_a2i_IPADDRESS(const char* ipa) { - int ret = WOLFSSL_SUCCESS; - BIO *b; + int ipaSz = WOLFSSL_IP4_ADDR_LEN; + char buf[WOLFSSL_IP6_ADDR_LEN + 1]; /* plus 1 for terminator */ + int af = WOLFSSL_IP4; + WOLFSSL_ASN1_STRING *ret = NULL; - WOLFSSL_ENTER("wolfSSL_PEM_write_PKCS8PrivateKey"); + if (ipa == NULL) + return NULL; - b = wolfSSL_BIO_new_fp(f, BIO_NOCLOSE); - if (b == NULL) { - ret = WOLFSSL_FAILURE; + if (XSTRSTR(ipa, ":") != NULL) { + af = WOLFSSL_IP6; + ipaSz = WOLFSSL_IP6_ADDR_LEN; } - if (ret == WOLFSSL_SUCCESS) { - ret = wolfSSL_PEM_write_bio_PKCS8PrivateKey(b, pkey, enc, passwd, - passwdSz, cb, ctx); + + buf[WOLFSSL_IP6_ADDR_LEN] = '\0'; + if (XINET_PTON(af, ipa, (void*)buf) != 1) { + WOLFSSL_MSG("Error parsing IP address"); + return NULL; } - wolfSSL_BIO_free(b); + ret = wolfSSL_ASN1_STRING_new(); + if (ret != NULL) { + if (wolfSSL_ASN1_STRING_set(ret, buf, ipaSz) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error setting the string"); + wolfSSL_ASN1_STRING_free(ret); + ret = NULL; + } + } return ret; } -#endif /* !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */ +#endif /* !WOLFSSL_USER_IO */ -static int bio_get_data(WOLFSSL_BIO* bio, byte** data) +/* Is the specified cipher suite a fake one used an an extension proxy? */ +static WC_INLINE int SCSV_Check(byte suite0, byte suite) { - int ret = 0; - byte* mem = NULL; + (void)suite0; + (void)suite; +#ifdef HAVE_RENEGOTIATION_INDICATION + if (suite0 == CIPHER_BYTE && suite == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) + return 1; +#endif + return 0; +} - ret = wolfSSL_BIO_get_len(bio); - if (ret > 0) { - mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL); - if (mem == NULL) { - WOLFSSL_MSG("Memory error"); - ret = MEMORY_E; - } - if (ret >= 0) { - if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) { - XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); - ret = MEMORY_E; - mem = NULL; +static WC_INLINE int sslCipherMinMaxCheck(const WOLFSSL *ssl, byte suite0, + byte suite) +{ + const CipherSuiteInfo* cipher_names = GetCipherNames(); + int cipherSz = GetCipherNamesSize(); + int i; + for (i = 0; i < cipherSz; i++) + if (cipher_names[i].cipherSuite0 == suite0 && + cipher_names[i].cipherSuite == suite) + break; + if (i == cipherSz) + return 1; + /* Check min version */ + if (cipher_names[i].minor < ssl->options.minDowngrade) { + if (ssl->options.minDowngrade <= TLSv1_2_MINOR && + cipher_names[i].minor >= TLSv1_MINOR) + /* 1.0 ciphersuites are in general available in 1.1 and + * 1.1 ciphersuites are in general available in 1.2 */ + return 0; + return 1; + } + /* Check max version */ + switch (cipher_names[i].minor) { + case SSLv3_MINOR : + return ssl->options.mask & WOLFSSL_OP_NO_SSLv3; + case TLSv1_MINOR : + return ssl->options.mask & WOLFSSL_OP_NO_TLSv1; + case TLSv1_1_MINOR : + return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_1; + case TLSv1_2_MINOR : + return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_2; + case TLSv1_3_MINOR : + return ssl->options.mask & WOLFSSL_OP_NO_TLSv1_3; + default: + WOLFSSL_MSG("Unrecognized minor version"); + return 1; + } +} + +/* returns a pointer to internal cipher suite list. Should not be free'd by + * caller. + */ +WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) +{ + WOLF_STACK_OF(WOLFSSL_CIPHER)* ret = NULL; + const Suites* suites; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + const CipherSuiteInfo* cipher_names = GetCipherNames(); + int cipherSz = GetCipherNamesSize(); +#endif + + WOLFSSL_ENTER("wolfSSL_get_ciphers_compat"); + if (ssl == NULL) + return NULL; + + suites = WOLFSSL_SUITES(ssl); + if (suites == NULL) + return NULL; + + /* check if stack needs populated */ + if (ssl->suitesStack == NULL) { + int i; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + int j; + + /* higher priority of cipher suite will be on top of stack */ + for (i = suites->suiteSz - 2; i >=0; i-=2) { +#else + for (i = 0; i < suites->suiteSz; i+=2) { +#endif + WOLFSSL_STACK* add; + + /* A couple of suites are placeholders for special options, + * skip those. */ + if (SCSV_Check(suites->suites[i], suites->suites[i+1]) + || sslCipherMinMaxCheck(ssl, suites->suites[i], + suites->suites[i+1])) { + continue; + } + + add = wolfSSL_sk_new_node(ssl->heap); + if (add != NULL) { + add->type = STACK_TYPE_CIPHER; + add->data.cipher.cipherSuite0 = suites->suites[i]; + add->data.cipher.cipherSuite = suites->suites[i+1]; + add->data.cipher.ssl = ssl; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + for (j = 0; j < cipherSz; j++) { + if (cipher_names[j].cipherSuite0 == + add->data.cipher.cipherSuite0 && + cipher_names[j].cipherSuite == + add->data.cipher.cipherSuite) { + add->data.cipher.offset = (unsigned long)j; + break; + } + } +#endif + #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + /* in_stack is checked in wolfSSL_CIPHER_description */ + add->data.cipher.in_stack = 1; + #endif + + add->next = ret; + if (ret != NULL) { + add->num = ret->num + 1; + } + else { + add->num = 1; + } + ret = add; } } + ((WOLFSSL*)ssl)->suitesStack = ret; } - - *data = mem; - - return ret; + return ssl->suitesStack; } +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ -/* DER data is PKCS#8 encrypted. */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** pkey, - wc_pem_password_cb* cb, - void* ctx) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ + defined(HAVE_LIGHTY) || defined(HAVE_SECRET_CALLBACK) +long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) { - int ret; - byte* der; - int len; - byte* p; - word32 algId; - WOLFSSL_EVP_PKEY* key; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); - if ((len = bio_get_data(bio, &der)) < 0) - return NULL; + if (ctx == NULL) + return 0; - if (cb != NULL) { - char password[NAME_SZ]; - int passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); - if (passwordSz < 0) { - XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password, - passwordSz); - #endif + return ctx->timeout; +} - ret = ToTraditionalEnc(der, len, password, passwordSz, &algId); - if (ret < 0) { - XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - ForceZero(password, passwordSz); - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Check(password, passwordSz); - #endif - } +/* returns the time in seconds of the current timeout */ +long wolfSSL_get_timeout(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_timeout"); - p = der; - key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len); - XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); - return key; + if (ssl == NULL) + return 0; + return ssl->timeout; } +#endif -#endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) -/* Detect which type of key it is before decoding. */ -WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey, - const unsigned char** pp, - long length) +#ifdef HAVE_ECC +int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) { - int ret; - WOLFSSL_EVP_PKEY* key = NULL; - const byte* der = *pp; - word32 idx = 0; - int len = 0; - int cnt = 0; - word32 algId; - word32 keyLen = (word32)length; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); - /* Take off PKCS#8 wrapper if found. */ - if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { - der += idx; - keyLen = len; - } - idx = 0; - len = 0; + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; - /* Use the number of elements in the outer sequence to determine key type. - */ - ret = GetSequence(der, &idx, &len, keyLen); - if (ret >= 0) { - word32 end = idx + len; - while (ret >= 0 && idx < end) { - /* Skip type */ - idx++; - /* Get length and skip over - keeping count */ - len = 0; - ret = GetLength(der, &idx, &len, keyLen); - if (ret >= 0) { - if (idx + len > end) - ret = ASN_PARSE_E; - else { - idx += len; - cnt++; - } - } - } - } + ctx->ecdhCurveOID = (word32)ecdh->group->curve_oid; - if (ret >= 0) { - int type; - /* ECC includes version, private[, curve][, public key] */ - if (cnt >= 2 && cnt <= 4) - type = EVP_PKEY_EC; - else - type = EVP_PKEY_RSA; + return WOLFSSL_SUCCESS; +} +#endif +#ifndef NO_BIO +BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); + /* 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. + */ + if (s == NULL) + return NULL; - key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); - *pp = der; - } + return s->biord; +} +BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) +{ + 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. + */ + if (s == NULL) + return NULL; - return key; + return s->biowr; } -#endif /* OPENSSL_ALL */ +#endif /* !NO_BIO */ -#ifdef WOLFSSL_STATIC_EPHEMERAL -int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr) +int wolfSSL_SSL_do_handshake_internal(WOLFSSL *s) { - int ret; - word32 idx = 0; - DerBuffer* der = NULL; + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake_internal"); + if (s == NULL) + return WOLFSSL_FAILURE; - if (ssl == NULL || ssl->ctx == NULL || keyPtr == NULL) { - return BAD_FUNC_ARG; + if (s->options.side == WOLFSSL_CLIENT_END) { + #ifndef NO_WOLFSSL_CLIENT + return wolfSSL_connect(s); + #else + WOLFSSL_MSG("Client not compiled in"); + return WOLFSSL_FAILURE; + #endif } -#ifndef SINGLE_THREADED - if (!ssl->ctx->staticKELockInit) { - return BUFFER_E; /* no keys set */ - } - ret = wc_LockMutex(&ssl->ctx->staticKELock); - if (ret != 0) { - return ret; - } +#ifndef NO_WOLFSSL_SERVER + return wolfSSL_accept(s); +#else + WOLFSSL_MSG("Server not compiled in"); + return WOLFSSL_FAILURE; #endif +} - ret = BUFFER_E; /* set default error */ - switch (keyAlgo) { - #ifndef NO_DH - case WC_PK_TYPE_DH: - if (ssl != NULL) - der = ssl->staticKE.dhKey; - if (der == NULL) - der = ssl->ctx->staticKE.dhKey; - if (der != NULL) { - DhKey* key = (DhKey*)keyPtr; - WOLFSSL_MSG("Using static DH key"); - ret = wc_DhKeyDecode(der->buffer, &idx, key, der->length); - } - break; - #endif - #ifdef HAVE_ECC - case WC_PK_TYPE_ECDH: - if (ssl != NULL) - der = ssl->staticKE.ecKey; - if (der == NULL) - der = ssl->ctx->staticKE.ecKey; - if (der != NULL) { - ecc_key* key = (ecc_key*)keyPtr; - WOLFSSL_MSG("Using static ECDH key"); - ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length); - } - break; - #endif - #ifdef HAVE_CURVE25519 - case WC_PK_TYPE_CURVE25519: - if (ssl != NULL) - der = ssl->staticKE.x25519Key; - if (der == NULL) - der = ssl->ctx->staticKE.x25519Key; - if (der != NULL) { - curve25519_key* key = (curve25519_key*)keyPtr; - WOLFSSL_MSG("Using static X25519 key"); - ret = wc_Curve25519PrivateKeyDecode(der->buffer, &idx, key, - der->length); - } - break; - #endif - #ifdef HAVE_CURVE448 - case WC_PK_TYPE_CURVE448: - if (ssl != NULL) - der = ssl->staticKE.x448Key; - if (der == NULL) - der = ssl->ctx->staticKE.x448Key; - if (der != NULL) { - curve448_key* key = (curve448_key*)keyPtr; - WOLFSSL_MSG("Using static X448 key"); - ret = wc_Curve448PrivateKeyDecode(der->buffer, &idx, key, - der->length); - } - break; - #endif - default: - /* not supported */ - ret = NOT_COMPILED_IN; - break; +int wolfSSL_SSL_do_handshake(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); +#ifdef WOLFSSL_QUIC + if (WOLFSSL_IS_QUIC(s)) { + return wolfSSL_quic_do_handshake(s); } +#endif + return wolfSSL_SSL_do_handshake_internal(s); +} -#ifndef SINGLE_THREADED - wc_UnLockMutex(&ssl->ctx->staticKELock); +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L +int wolfSSL_SSL_in_init(const WOLFSSL *ssl) +#else +int wolfSSL_SSL_in_init(WOLFSSL *ssl) #endif - return ret; +{ + WOLFSSL_ENTER("wolfSSL_SSL_in_init"); + + return !wolfSSL_is_init_finished(ssl); } -static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx, - StaticKeyExchangeInfo_t* staticKE, int keyAlgo, const char* key, - unsigned int keySz, int format, void* heap) +int wolfSSL_SSL_in_before(const WOLFSSL *ssl) { - int ret = 0; - DerBuffer* der = NULL; - byte* keyBuf = NULL; -#ifndef NO_FILESYSTEM - const char* keyFile = NULL; -#endif + WOLFSSL_ENTER("wolfSSL_SSL_in_before"); - /* allow empty key to free buffer */ - if (staticKE == NULL || (key == NULL && keySz > 0)) { - return BAD_FUNC_ARG; + if (ssl == NULL) + return WOLFSSL_FAILURE; + + return ssl->options.handShakeState == NULL_STATE; +} + +int wolfSSL_SSL_in_connect_init(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_SSL_in_connect_init"); + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + return ssl->options.connectState > CONNECT_BEGIN && + ssl->options.connectState < SECOND_REPLY_DONE; } - WOLFSSL_ENTER("SetStaticEphemeralKey"); + return ssl->options.acceptState > ACCEPT_BEGIN && + ssl->options.acceptState < ACCEPT_THIRD_REPLY_DONE; +} - /* if just free'ing key then skip loading */ - if (key != NULL) { - #ifndef NO_FILESYSTEM - /* load file from filesystem */ - if (key != NULL && keySz == 0) { - size_t keyBufSz = 0; - keyFile = (const char*)key; - ret = wc_FileLoad(keyFile, &keyBuf, &keyBufSz, heap); - if (ret != 0) { - return ret; - } - keySz = (unsigned int)keyBufSz; - } - else - #endif - { - /* use as key buffer directly */ - keyBuf = (byte*)key; - } +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) +/* 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 (format == WOLFSSL_FILETYPE_PEM) { - #ifdef WOLFSSL_PEM_TO_DER - int keyFormat = 0; - ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &der, - heap, NULL, &keyFormat); - /* auto detect key type */ - if (ret == 0 && keyAlgo == WC_PK_TYPE_NONE) { - if (keyFormat == ECDSAk) - keyAlgo = WC_PK_TYPE_ECDH; - else if (keyFormat == X25519k) - keyAlgo = WC_PK_TYPE_CURVE25519; - else - keyAlgo = WC_PK_TYPE_DH; - } - #else - ret = NOT_COMPILED_IN; - #endif - } - else { - /* Detect PK type (if required) */ - #ifdef HAVE_ECC - if (keyAlgo == WC_PK_TYPE_NONE) { - word32 idx = 0; - ecc_key eccKey; - ret = wc_ecc_init_ex(&eccKey, heap, INVALID_DEVID); - if (ret == 0) { - ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &eccKey, keySz); - if (ret == 0) - keyAlgo = WC_PK_TYPE_ECDH; - wc_ecc_free(&eccKey); - } - } - #endif - #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) - if (keyAlgo == WC_PK_TYPE_NONE) { - word32 idx = 0; - DhKey dhKey; - ret = wc_InitDhKey_ex(&dhKey, heap, INVALID_DEVID); - if (ret == 0) { - ret = wc_DhKeyDecode(keyBuf, &idx, &dhKey, keySz); - if (ret == 0) - keyAlgo = WC_PK_TYPE_DH; - wc_FreeDhKey(&dhKey); - } - } - #endif - #ifdef HAVE_CURVE25519 - if (keyAlgo == WC_PK_TYPE_NONE) { - word32 idx = 0; - curve25519_key x25519Key; - ret = wc_curve25519_init_ex(&x25519Key, heap, INVALID_DEVID); - if (ret == 0) { - ret = wc_Curve25519PrivateKeyDecode(keyBuf, &idx, &x25519Key, - keySz); - if (ret == 0) - keyAlgo = WC_PK_TYPE_CURVE25519; - wc_curve25519_free(&x25519Key); - } - } - #endif - #ifdef HAVE_CURVE448 - if (keyAlgo == WC_PK_TYPE_NONE) { - word32 idx = 0; - curve448_key x448Key; - ret = wc_curve448_init(&x448Key); - if (ret == 0) { - ret = wc_Curve448PrivateKeyDecode(keyBuf, &idx, &x448Key, - keySz); - if (ret == 0) - keyAlgo = WC_PK_TYPE_CURVE448; - wc_curve448_free(&x448Key); - } - } - #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[WC_MAX_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + WOLFSSL_EVP_CIPHER_CTX *evpCtx; +#else + WOLFSSL_EVP_CIPHER_CTX evpCtx[1]; +#endif + WOLFSSL_HMAC_CTX hmacCtx; + unsigned int mdSz = 0; + int len = 0; + int ret = WOLFSSL_TICKET_RET_FATAL; + int res; + int totalSz = 0; - if (keyAlgo != WC_PK_TYPE_NONE) { - ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap); - if (ret == 0) { - XMEMCPY(der->buffer, keyBuf, keySz); - } - } - } + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_TicketKeyCb"); + + if (ssl == NULL || ssl->ctx == NULL || ssl->ctx->ticketEncWrapCb == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_TICKET_RET_FATAL; } -#ifndef NO_FILESYSTEM - /* done with keyFile buffer */ - if (keyFile && keyBuf) { - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + evpCtx = (WOLFSSL_EVP_CIPHER_CTX *)XMALLOC(sizeof(*evpCtx), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (evpCtx == NULL) { + WOLFSSL_MSG("out of memory"); + return WOLFSSL_TICKET_RET_FATAL; } #endif -#ifndef SINGLE_THREADED - if (ret == 0 && !ctx->staticKELockInit) { - ret = wc_InitMutex(&ctx->staticKELock); - if (ret == 0) { - ctx->staticKELockInit = 1; - } - } + /* Initialize the cipher and HMAC. */ + wolfSSL_EVP_CIPHER_CTX_init(evpCtx); + if (wolfSSL_HMAC_CTX_Init(&hmacCtx) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (ret == 0 - #ifndef SINGLE_THREADED - && (ret = wc_LockMutex(&ctx->staticKELock)) == 0 - #endif - ) { - switch (keyAlgo) { - #ifndef NO_DH - case WC_PK_TYPE_DH: - FreeDer(&staticKE->dhKey); - staticKE->dhKey = der; der = NULL; - break; - #endif - #ifdef HAVE_ECC - case WC_PK_TYPE_ECDH: - FreeDer(&staticKE->ecKey); - staticKE->ecKey = der; der = NULL; - break; - #endif - #ifdef HAVE_CURVE25519 - case WC_PK_TYPE_CURVE25519: - FreeDer(&staticKE->x25519Key); - staticKE->x25519Key = der; der = NULL; - break; - #endif - #ifdef HAVE_CURVE448 - case WC_PK_TYPE_CURVE448: - FreeDer(&staticKE->x448Key); - staticKE->x448Key = der; der = NULL; - break; - #endif - default: - /* not supported */ - ret = NOT_COMPILED_IN; - break; - } + return WOLFSSL_TICKET_RET_FATAL; + } + res = ssl->ctx->ticketEncWrapCb(ssl, keyName, + iv, evpCtx, &hmacCtx, enc); + if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) { + WOLFSSL_MSG("Ticket callback error"); + ret = WOLFSSL_TICKET_RET_FATAL; + goto end; + } - #ifndef SINGLE_THREADED - wc_UnLockMutex(&ctx->staticKELock); - #endif + if (wolfSSL_HMAC_size(&hmacCtx) > WOLFSSL_TICKET_MAC_SZ) { + WOLFSSL_MSG("Ticket cipher MAC size error"); + goto end; } - if (ret != 0) { - FreeDer(&der); + if (enc) + { + /* Encrypt in place. */ + if (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + totalSz = len; + if (totalSz > *encLen) + goto end; + if (!wolfSSL_EVP_EncryptFinal(evpCtx, &encTicket[len], &len)) + goto end; + /* Total length of encrypted data. */ + totalSz += len; + if (totalSz > *encLen) + goto end; + + /* HMAC the encrypted data into the parameter 'mac'. */ + if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, totalSz)) + goto end; + if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz)) + goto end; } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen)) + goto end; + if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz)) + goto end; + if (XMEMCMP(mac, digest, mdSz) != 0) + goto end; - (void)ctx; /* not used for single threaded */ + /* Decrypt the ticket data in place. */ + if (!wolfSSL_EVP_CipherUpdate(evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + totalSz = len; + if (totalSz > encTicketLen) + goto end; + if (!wolfSSL_EVP_DecryptFinal(evpCtx, &encTicket[len], &len)) + goto end; + /* Total length of decrypted data. */ + totalSz += len; + if (totalSz > encTicketLen) + goto end; + } + *encLen = totalSz; - WOLFSSL_LEAVE("SetStaticEphemeralKey", ret); + if (res == TICKET_KEY_CB_RET_RENEW && !IsAtLeastTLSv1_3(ssl->version) + && !enc) + ret = WOLFSSL_TICKET_RET_CREATE; + else + ret = WOLFSSL_TICKET_RET_OK; +end: + + (void)wc_HmacFree(&hmacCtx.hmac); + (void)wolfSSL_EVP_CIPHER_CTX_cleanup(evpCtx); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(evpCtx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif return ret; } -int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, - const char* key, unsigned int keySz, int format) +/* Set the callback to use when encrypting/decrypting tickets. + * + * ctx The SSL/TLS context object. + * cb The OpenSSL session ticket callback. + * returns WOLFSSL_SUCCESS to indicate success. + */ +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, ticketCompatCb cb) { - if (ctx == NULL) { - return BAD_FUNC_ARG; - } - return SetStaticEphemeralKey(ctx, &ctx->staticKE, keyAlgo, - key, keySz, format, ctx->heap); + + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + ctx->ticketEncWrapCb = cb; + + return WOLFSSL_SUCCESS; } -int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, - const char* key, unsigned int keySz, int format) + +#endif /* HAVE_SESSION_TICKET */ + +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY */ + +#if defined(HAVE_SESSION_TICKET) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) && \ + !defined(NO_WOLFSSL_SERVER) +/* Serialize the session ticket encryption keys. + * + * @param [in] ctx SSL/TLS context object. + * @param [in] keys Buffer to hold session ticket keys. + * @param [in] keylen Length of buffer. + * @return WOLFSSL_SUCCESS on success. + * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the + * correct length. + */ +long wolfSSL_CTX_get_tlsext_ticket_keys(WOLFSSL_CTX *ctx, + unsigned char *keys, int keylen) { - if (ssl == NULL || ssl->ctx == NULL) { - return BAD_FUNC_ARG; + if (ctx == NULL || keys == NULL) { + return WOLFSSL_FAILURE; } - return SetStaticEphemeralKey(ssl->ctx, &ssl->staticKE, keyAlgo, - key, keySz, format, ssl->heap); + if (keylen != WOLFSSL_TICKET_KEYS_SZ) { + return WOLFSSL_FAILURE; + } + + XMEMCPY(keys, ctx->ticketKeyCtx.name, WOLFSSL_TICKET_NAME_SZ); + keys += WOLFSSL_TICKET_NAME_SZ; + XMEMCPY(keys, ctx->ticketKeyCtx.key[0], WOLFSSL_TICKET_KEY_SZ); + keys += WOLFSSL_TICKET_KEY_SZ; + XMEMCPY(keys, ctx->ticketKeyCtx.key[1], WOLFSSL_TICKET_KEY_SZ); + keys += WOLFSSL_TICKET_KEY_SZ; + c32toa(ctx->ticketKeyCtx.expirary[0], keys); + keys += OPAQUE32_LEN; + c32toa(ctx->ticketKeyCtx.expirary[1], keys); + + return WOLFSSL_SUCCESS; } -static int GetStaticEphemeralKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, - int keyAlgo, const unsigned char** key, unsigned int* keySz) +/* Deserialize the session ticket encryption keys. + * + * @param [in] ctx SSL/TLS context object. + * @param [in] keys Session ticket keys. + * @param [in] keylen Length of data. + * @return WOLFSSL_SUCCESS on success. + * @return WOLFSSL_FAILURE when ctx is NULL, keys is NULL or keylen is not the + * correct length. + */ +long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx, + const void *keys_vp, int keylen) { - int ret = 0; - DerBuffer* der = NULL; + const byte* keys = (const byte*)keys_vp; + if (ctx == NULL || keys == NULL) { + return WOLFSSL_FAILURE; + } + if (keylen != WOLFSSL_TICKET_KEYS_SZ) { + return WOLFSSL_FAILURE; + } - if (key) *key = NULL; - if (keySz) *keySz = 0; + XMEMCPY(ctx->ticketKeyCtx.name, keys, WOLFSSL_TICKET_NAME_SZ); + keys += WOLFSSL_TICKET_NAME_SZ; + XMEMCPY(ctx->ticketKeyCtx.key[0], keys, WOLFSSL_TICKET_KEY_SZ); + keys += WOLFSSL_TICKET_KEY_SZ; + XMEMCPY(ctx->ticketKeyCtx.key[1], keys, WOLFSSL_TICKET_KEY_SZ); + keys += WOLFSSL_TICKET_KEY_SZ; + ato32(keys, &ctx->ticketKeyCtx.expirary[0]); + keys += OPAQUE32_LEN; + ato32(keys, &ctx->ticketKeyCtx.expirary[1]); -#ifndef SINGLE_THREADED - if (ctx->staticKELockInit && - (ret = wc_LockMutex(&ctx->staticKELock)) != 0) { - return ret; - } + return WOLFSSL_SUCCESS; +} #endif - switch (keyAlgo) { - #ifndef NO_DH - case WC_PK_TYPE_DH: - if (ssl != NULL) - der = ssl->staticKE.dhKey; - if (der == NULL) - der = ctx->staticKE.dhKey; - break; - #endif - #ifdef HAVE_ECC - case WC_PK_TYPE_ECDH: - if (ssl != NULL) - der = ssl->staticKE.ecKey; - if (der == NULL) - der = ctx->staticKE.ecKey; - break; - #endif - #ifdef HAVE_CURVE25519 - case WC_PK_TYPE_CURVE25519: - if (ssl != NULL) - der = ssl->staticKE.x25519Key; - if (der == NULL) - der = ctx->staticKE.x25519Key; - break; - #endif - #ifdef HAVE_CURVE448 - case WC_PK_TYPE_CURVE448: - if (ssl != NULL) - der = ssl->staticKE.x448Key; - if (der == NULL) - der = ctx->staticKE.x448Key; - break; - #endif - default: - /* not supported */ - ret = NOT_COMPILED_IN; - break; - } +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#ifdef HAVE_OCSP +/* Not an OpenSSL API. */ +int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) +{ + *response = ssl->ocspResp; + return ssl->ocspRespSz; +} - if (der) { - if (key) - *key = der->buffer; - if (keySz) - *keySz = der->length; - } +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) +{ + return ssl->url; +} + +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) + return WOLFSSL_FAILURE; + + ssl->url = url; + return WOLFSSL_SUCCESS; +} +#endif /* OCSP */ +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(HAVE_OCSP) && !defined(NO_ASN_TIME) +int wolfSSL_get_ocsp_producedDate( + WOLFSSL *ssl, + byte *producedDate, + size_t producedDate_space, + int *producedDateFormat) +{ + if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) && + (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME)) + return BAD_FUNC_ARG; -#ifndef SINGLE_THREADED - wc_UnLockMutex(&ctx->staticKELock); -#endif + if ((producedDate == NULL) || (producedDateFormat == NULL)) + return BAD_FUNC_ARG; - return ret; + if (XSTRLEN((char *)ssl->ocspProducedDate) >= producedDate_space) + return BUFFER_E; + + XSTRNCPY((char *)producedDate, (const char *)ssl->ocspProducedDate, + producedDate_space); + *producedDateFormat = ssl->ocspProducedDateFormat; + + return 0; } -/* returns pointer to currently loaded static ephemeral as ASN.1 */ -/* this can be converted to PEM using wc_DerToPem */ -int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, - const unsigned char** key, unsigned int* keySz) -{ - if (ctx == NULL) { +int wolfSSL_get_ocsp_producedDate_tm(WOLFSSL *ssl, struct tm *produced_tm) { + int idx = 0; + + if ((ssl->ocspProducedDateFormat != ASN_UTC_TIME) && + (ssl->ocspProducedDateFormat != ASN_GENERALIZED_TIME)) return BAD_FUNC_ARG; - } - return GetStaticEphemeralKey(ctx, NULL, keyAlgo, key, keySz); -} -int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, - const unsigned char** key, unsigned int* keySz) -{ - if (ssl == NULL || ssl->ctx == NULL) { + if (produced_tm == NULL) return BAD_FUNC_ARG; - } - return GetStaticEphemeralKey(ssl->ctx, ssl, keyAlgo, key, keySz); + if (ExtractDate(ssl->ocspProducedDate, + (unsigned char)ssl->ocspProducedDateFormat, produced_tm, &idx)) + return 0; + else + return ASN_PARSE_E; } +#endif -#endif /* WOLFSSL_STATIC_EPHEMERAL */ -#if defined(OPENSSL_EXTRA) -/* wolfSSL_THREADID_current is provided as a compat API with - * CRYPTO_THREADID_current to register current thread id into given id object. - * However, CRYPTO_THREADID_current API has been deprecated and no longer - * exists in the OpenSSL 1.0.0 or later.This API only works as a stub - * like as existing wolfSSL_THREADID_set_numeric. - */ -void wolfSSL_THREADID_current(WOLFSSL_CRYPTO_THREADID* id) -{ - (void)id; - return; -} -/* wolfSSL_THREADID_hash is provided as a compatible API with - * CRYPTO_THREADID_hash which returns a hash value calculated from the - * specified thread id. However, CRYPTO_THREADID_hash API has been - * deprecated and no longer exists in the OpenSSL 1.0.0 or later. - * This API only works as a stub to returns 0. This behavior is - * equivalent to the latest OpenSSL CRYPTO_THREADID_hash. - */ -unsigned long wolfSSL_THREADID_hash(const WOLFSSL_CRYPTO_THREADID* id) -{ - (void)id; - return 0UL; -} -/* wolfSSL_CTX_set_ecdh_auto is provided as compatible API with - * SSL_CTX_set_ecdh_auto to enable auto ecdh curve selection functionality. - * Since this functionality is enabled by default in wolfSSL, - * this API exists as a stub. - */ -int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff) +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(X509)** chain) { - (void)ctx; - (void)onoff; - return WOLFSSL_SUCCESS; -} + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; -/** - * set security level (wolfSSL doesn't support security level) - * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure - * @param level security level - */ -void wolfSSL_CTX_set_security_level(WOLFSSL_CTX* ctx, int level) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_security_level"); - (void)ctx; - (void)level; -} -/** - * get security level (wolfSSL doesn't support security level) - * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure - * @return always 0(level 0) - */ -int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get_security_level"); - (void)ctx; - return 0; -} + if (ctx == NULL || chain == NULL) { + chain = NULL; + return WOLFSSL_FAILURE; + } + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return WOLFSSL_SUCCESS; + } + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return WOLFSSL_SUCCESS; + } -/** - * Determine whether a WOLFSSL_SESSION object can be used for resumption - * @param s a pointer to WOLFSSL_SESSION structure - * @return return 1 if session is resumable, otherwise 0. - */ -int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) -{ - s = ClientSessionToSession(s); - if (s == NULL) - return 0; + /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ + for (idx = 0; idx < ctx->certChain->length; ) { + node = wolfSSL_sk_X509_new_null(); + if (node == NULL) + return WOLFSSL_FAILURE; + node->next = NULL; -#ifdef HAVE_SESSION_TICKET - if (s->ticketLen > 0) - return 1; -#endif + /* 3 byte length | X509 DER data */ + ato24(ctx->certChain->buffer + idx, &length); + idx += 3; - if (s->sessionIDSz > 0) - return 1; + /* Create a new X509 from DER encoded data. */ + node->data.x509 = wolfSSL_X509_d2i_ex(NULL, + ctx->certChain->buffer + idx, (int)length, ctx->heap); + if (node->data.x509 == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + /* Return as much of the chain as we created. */ + ctx->x509Chain = *chain; + return WOLFSSL_FAILURE; + } + idx += length; - return 0; -} + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; + } + else { + (*chain)->num++; + last->next = node; + } -#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) -/* - * This API accepts a user callback which puts key-log records into - * a KEY LOGFILE. The callback is stored into a CTX and propagated to - * each SSL object on its creation timing. - */ -void wolfSSL_CTX_set_keylog_callback(WOLFSSL_CTX* ctx, wolfSSL_CTX_keylog_cb_func cb) -{ - WOLFSSL_ENTER("wolfSSL_CTX_set_keylog_callback"); - /* stores the callback into WOLFSSL_CTX */ - if (ctx != NULL) { - ctx->keyLogCb = cb; + last = node; } -} -wolfSSL_CTX_keylog_cb_func wolfSSL_CTX_get_keylog_callback( - const WOLFSSL_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_CTX_get_keylog_callback"); - if (ctx != NULL) - return ctx->keyLogCb; - else - return NULL; -} -#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ -#endif /* OPENSSL_EXTRA */ + ctx->x509Chain = *chain; -#ifndef NO_CERT -#define WOLFSSL_X509_INCLUDED -#include "src/x509.c" -#endif + return WOLFSSL_SUCCESS; +} -/******************************************************************************* - * START OF standard C library wrapping APIs - ******************************************************************************/ -#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) -#ifndef NO_WOLFSSL_STUB -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 *)) +int wolfSSL_CTX_get_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb* cb) { - (void) m; - (void) r; - (void) f; - WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); - WOLFSSL_STUB("CRYPTO_set_mem_ex_functions"); + if (ctx == NULL || ctx->cm == NULL || cb == NULL) + return WOLFSSL_FAILURE; - return WOLFSSL_FAILURE; -} -#endif +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + if (ctx->cm->ocsp_stapling == NULL) + return WOLFSSL_FAILURE; + + *cb = ctx->cm->ocsp_stapling->statusCb; +#else + (void)cb; + *cb = NULL; #endif -#if defined(OPENSSL_EXTRA) + return WOLFSSL_SUCCESS; -/** - * free allocated memory resource - * @param str a pointer to resource to be freed - * @param file dummy argument - * @param line dummy argument - */ -void wolfSSL_CRYPTO_free(void *str, const char *file, int line) -{ - (void)file; - (void)line; - XFREE(str, 0, DYNAMIC_TYPE_TMP_BUFFER); } -/** - * allocate memory with size of num - * @param num size of memory allocation to be malloced - * @param file dummy argument - * @param line dummy argument - * @return a pointer to allocated memory on succssesful, otherwise NULL - */ -void *wolfSSL_CRYPTO_malloc(size_t num, const char *file, int line) + +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, tlsextStatusCb cb) { - (void)file; - (void)line; - return XMALLOC(num, 0, DYNAMIC_TYPE_TMP_BUFFER); -} + if (ctx == NULL || ctx->cm == NULL) + return WOLFSSL_FAILURE; -#endif +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + /* Ensure stapling is on for callback to be used. */ + wolfSSL_CTX_EnableOCSPStapling(ctx); -/******************************************************************************* - * END OF standard C library wrapping APIs - ******************************************************************************/ + if (ctx->cm->ocsp_stapling == NULL) + return WOLFSSL_FAILURE; -/******************************************************************************* - * START OF EX_DATA APIs - ******************************************************************************/ -#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ - defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ - defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_OPENSSH))) -void wolfSSL_CRYPTO_cleanup_all_ex_data(void){ - WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data"); -} + ctx->cm->ocsp_stapling->statusCb = cb; +#else + (void)cb; #endif -#ifdef HAVE_EX_DATA -void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx) + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_get0_chain_certs(WOLFSSL_CTX *ctx, + WOLF_STACK_OF(WOLFSSL_X509) **sk) { - WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); -#ifdef MAX_EX_DATA - if(ex_data && idx < MAX_EX_DATA && idx >= 0) { - return ex_data->ex_data[idx]; + WOLFSSL_ENTER("wolfSSL_CTX_get0_chain_certs"); + if (ctx == NULL || sk == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } -#else - (void)ex_data; - (void)idx; -#endif - return NULL; + + /* This function should return ctx->x509Chain if it is populated, otherwise + it should be populated from ctx->certChain. This matches the behavior of + wolfSSL_CTX_get_extra_chain_certs, so it is used directly. */ + return wolfSSL_CTX_get_extra_chain_certs(ctx, sk); } -int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, void *data) +#ifdef KEEP_OUR_CERT +int wolfSSL_get0_chain_certs(WOLFSSL *ssl, + WOLF_STACK_OF(WOLFSSL_X509) **sk) { - WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data"); -#ifdef MAX_EX_DATA - if (ex_data && idx < MAX_EX_DATA && idx >= 0) { -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - if (ex_data->ex_data_cleanup_routines[idx]) { - if (ex_data->ex_data[idx]) - ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]); - ex_data->ex_data_cleanup_routines[idx] = NULL; - } -#endif - ex_data->ex_data[idx] = data; - return WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_get0_chain_certs"); + if (ssl == NULL || sk == NULL) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; } -#else - (void)ex_data; - (void)idx; - (void)data; -#endif - return WOLFSSL_FAILURE; + *sk = ssl->ourCertChain; + return WOLFSSL_SUCCESS; } +#endif -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS -int wolfSSL_CRYPTO_set_ex_data_with_cleanup( - WOLFSSL_CRYPTO_EX_DATA* ex_data, - int idx, - void *data, - wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +WOLF_STACK_OF(WOLFSSL_STRING)* wolfSSL_sk_WOLFSSL_STRING_new(void) { - WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data_with_cleanup"); - if (ex_data && idx < MAX_EX_DATA && idx >= 0) { - if (ex_data->ex_data_cleanup_routines[idx] && ex_data->ex_data[idx]) - ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]); - ex_data->ex_data[idx] = data; - ex_data->ex_data_cleanup_routines[idx] = cleanup_routine; - return WOLFSSL_SUCCESS; + WOLF_STACK_OF(WOLFSSL_STRING)* ret = wolfSSL_sk_new_node(NULL); + + if (ret) { + ret->type = STACK_TYPE_STRING; } - return WOLFSSL_FAILURE; + + return ret; } -#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ -/** - * Issues unique index for the class specified by class_index. - * Other parameter except class_index are ignored. - * Currently, following class_index are accepted: - * - WOLF_CRYPTO_EX_INDEX_SSL - * - WOLF_CRYPTO_EX_INDEX_SSL_CTX - * - WOLF_CRYPTO_EX_INDEX_X509 - * @param class_index index one of CRYPTO_EX_INDEX_xxx - * @param argp parameters to be saved - * @param argl parameters to be saved - * @param new_func a pointer to WOLFSSL_CRYPTO_EX_new - * @param dup_func a pointer to WOLFSSL_CRYPTO_EX_dup - * @param free_func a pointer to WOLFSSL_CRYPTO_EX_free - * @return index value grater or equal to zero on success, -1 on failure. - */ -int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, - WOLFSSL_CRYPTO_EX_new* new_func, - WOLFSSL_CRYPTO_EX_dup* dup_func, - WOLFSSL_CRYPTO_EX_free* free_func) +void wolfSSL_WOLFSSL_STRING_free(WOLFSSL_STRING s) { - WOLFSSL_ENTER("wolfSSL_CRYPTO_get_ex_new_index"); + WOLFSSL_ENTER("wolfSSL_WOLFSSL_STRING_free"); - return wolfssl_get_ex_new_index(class_index, argl, argp, new_func, - dup_func, free_func); + if (s != NULL) + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); } -#endif /* HAVE_EX_DATA */ -/******************************************************************************* - * END OF EX_DATA APIs - ******************************************************************************/ +void wolfSSL_sk_WOLFSSL_STRING_free(WOLF_STACK_OF(WOLFSSL_STRING)* sk) +{ + WOLFSSL_STACK* tmp; + WOLFSSL_ENTER("wolfSSL_sk_WOLFSSL_STRING_free"); -/******************************************************************************* - * START OF BUF_MEM API - ******************************************************************************/ + if (sk == NULL) + return; -#if defined(OPENSSL_EXTRA) + /* parse through stack freeing each node */ + while (sk) { + tmp = sk->next; + XFREE(sk->data.string, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = tmp; + } +} -/* Begin functions for openssl/buffer.h */ -WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void) +WOLFSSL_STRING wolfSSL_sk_WOLFSSL_STRING_value( + WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx) { - WOLFSSL_BUF_MEM* buf; - buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL, - DYNAMIC_TYPE_OPENSSL); - if (buf) { - XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM)); - } - return buf; + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; } -/* non-compat API returns length of buffer on success */ -int wolfSSL_BUF_MEM_grow_ex(WOLFSSL_BUF_MEM* buf, size_t len, - char zeroFill) +int wolfSSL_sk_WOLFSSL_STRING_num(WOLF_STACK_OF(WOLFSSL_STRING)* strings) { + if (strings) + return (int)strings->num; + return 0; +} - int len_int = (int)len; - int mx; - char* tmp; +#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ - /* verify provided arguments */ - if (buf == NULL || len_int < 0) { - return 0; /* BAD_FUNC_ARG; */ - } +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_QUIC) +#ifdef HAVE_ALPN +void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, + unsigned int *len) +{ + word16 nameLen; - /* check to see if fits in existing length */ - if (buf->length > len) { - buf->length = len; - return len_int; + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; } +} - /* check to see if fits in max buffer */ - if (buf->max >= len) { - if (buf->data != NULL && zeroFill) { - XMEMSET(&buf->data[buf->length], 0, len - buf->length); +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) +{ + unsigned int i, j; + byte lenIn, lenClient; + + 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++]; + + if (lenIn != lenClient) + continue; + + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } } - buf->length = len; - return len_int; } - /* expand size, to handle growth */ - mx = (len_int + 3) / 3 * 4; + *out = (unsigned char *)clientNames + 1; + *outLen = clientNames[0]; + return OPENSSL_NPN_NO_OVERLAP; +} - /* use realloc */ - tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL); - if (tmp == NULL) { - return 0; /* ERR_R_MALLOC_FAILURE; */ +void wolfSSL_set_alpn_select_cb(WOLFSSL *ssl, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + if (ssl != NULL) { + ssl->alpnSelect = cb; + ssl->alpnSelectArg = arg; } - buf->data = tmp; +} - buf->max = mx; - if (zeroFill) - XMEMSET(&buf->data[buf->length], 0, len - buf->length); - buf->length = len; +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) { + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; + } +} - return len_int; +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"); +} +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) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); } -/* returns length of buffer on success */ -int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len) +void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, + const unsigned char **data, unsigned *len) { - return wolfSSL_BUF_MEM_grow_ex(buf, len, 1); + (void)s; + (void)data; + (void)len; + WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); } +#endif /* HAVE_ALPN */ -/* non-compat API returns length of buffer on success */ -int wolfSSL_BUF_MEM_resize(WOLFSSL_BUF_MEM* buf, size_t len) +#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL) +int wolfSSL_curve_is_disabled(const WOLFSSL* ssl, word16 curve_id) { - char* tmp; - int mx; + int ret = 0; - /* verify provided arguments */ - if (buf == NULL || len == 0 || (int)len <= 0) { - return 0; /* BAD_FUNC_ARG; */ + WOLFSSL_ENTER("wolfSSL_curve_is_disabled"); + WOLFSSL_MSG_EX("wolfSSL_curve_is_disabled checking for %d", curve_id); + + /* (curve_id >= WOLFSSL_FFDHE_START) - DH parameters are never disabled. */ + if (curve_id < WOLFSSL_FFDHE_START) { + if (curve_id > WOLFSSL_ECC_MAX_AVAIL) { + WOLFSSL_MSG("Curve id out of supported range"); + /* Disabled if not in valid range. */ + ret = 1; + } + else if (curve_id >= 32) { + /* 0 is for invalid and 1-14 aren't used otherwise. */ + ret = (ssl->disabledCurves & (1U << (curve_id - 32))) != 0; + } + else { + ret = (ssl->disabledCurves & (1U << curve_id)) != 0; + } } - if (len == buf->length) - return (int)len; + WOLFSSL_LEAVE("wolfSSL_curve_is_disabled", ret); + return ret; +} - if (len > buf->length) - return wolfSSL_BUF_MEM_grow_ex(buf, len, 0); +#if (defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) +#define CURVE_NAME(c) XSTR_SIZEOF((c)), (c) - /* expand size, to handle growth */ - mx = ((int)len + 3) / 3 * 4; +const WOLF_EC_NIST_NAME kNistCurves[] = { +#ifdef HAVE_ECC + {CURVE_NAME("P-160"), NID_secp160r1, WOLFSSL_ECC_SECP160R1}, + {CURVE_NAME("P-160-2"), NID_secp160r2, WOLFSSL_ECC_SECP160R2}, + {CURVE_NAME("P-192"), NID_X9_62_prime192v1, WOLFSSL_ECC_SECP192R1}, + {CURVE_NAME("P-224"), NID_secp224r1, WOLFSSL_ECC_SECP224R1}, + {CURVE_NAME("P-256"), NID_X9_62_prime256v1, WOLFSSL_ECC_SECP256R1}, + {CURVE_NAME("P-384"), NID_secp384r1, WOLFSSL_ECC_SECP384R1}, + {CURVE_NAME("P-521"), NID_secp521r1, WOLFSSL_ECC_SECP521R1}, + {CURVE_NAME("K-160"), NID_secp160k1, WOLFSSL_ECC_SECP160K1}, + {CURVE_NAME("K-192"), NID_secp192k1, WOLFSSL_ECC_SECP192K1}, + {CURVE_NAME("K-224"), NID_secp224k1, WOLFSSL_ECC_SECP224R1}, + {CURVE_NAME("K-256"), NID_secp256k1, WOLFSSL_ECC_SECP256K1}, + {CURVE_NAME("B-256"), NID_brainpoolP256r1, WOLFSSL_ECC_BRAINPOOLP256R1}, + {CURVE_NAME("B-384"), NID_brainpoolP384r1, WOLFSSL_ECC_BRAINPOOLP384R1}, + {CURVE_NAME("B-512"), NID_brainpoolP512r1, WOLFSSL_ECC_BRAINPOOLP512R1}, +#endif +#ifdef HAVE_CURVE25519 + {CURVE_NAME("X25519"), NID_X25519, WOLFSSL_ECC_X25519}, +#endif +#ifdef HAVE_CURVE448 + {CURVE_NAME("X448"), NID_X448, WOLFSSL_ECC_X448}, +#endif +#ifdef WOLFSSL_HAVE_KYBER + {CURVE_NAME("KYBER_LEVEL1"), WOLFSSL_KYBER_LEVEL1, WOLFSSL_KYBER_LEVEL1}, + {CURVE_NAME("KYBER_LEVEL3"), WOLFSSL_KYBER_LEVEL3, WOLFSSL_KYBER_LEVEL1}, + {CURVE_NAME("KYBER_LEVEL5"), WOLFSSL_KYBER_LEVEL5, WOLFSSL_KYBER_LEVEL1}, +#if (defined(WOLFSSL_WC_KYBER) || defined(HAVE_LIBOQS)) && defined(HAVE_ECC) + {CURVE_NAME("P256_KYBER_LEVEL1"), WOLFSSL_P256_KYBER_LEVEL1, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("P384_KYBER_LEVEL3"), WOLFSSL_P384_KYBER_LEVEL3, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("P521_KYBER_LEVEL5"), WOLFSSL_P521_KYBER_LEVEL5, WOLFSSL_P256_KYBER_LEVEL1}, +#endif +#endif +#ifdef WOLFSSL_SM2 + {CURVE_NAME("SM2"), NID_sm2, WOLFSSL_ECC_SM2P256V1}, +#endif +#ifdef HAVE_ECC + /* Alternative curve names */ + {CURVE_NAME("prime256v1"), NID_X9_62_prime256v1, WOLFSSL_ECC_SECP256R1}, + {CURVE_NAME("secp256r1"), NID_X9_62_prime256v1, WOLFSSL_ECC_SECP256R1}, + {CURVE_NAME("secp384r1"), NID_secp384r1, WOLFSSL_ECC_SECP384R1}, + {CURVE_NAME("secp521r1"), NID_secp521r1, WOLFSSL_ECC_SECP521R1}, +#endif +#ifdef WOLFSSL_SM2 + {CURVE_NAME("sm2p256v1"), NID_sm2, WOLFSSL_ECC_SM2P256V1}, +#endif + {0, NULL, 0, 0}, +}; - /* We want to shrink the internal buffer */ - tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL); - if (tmp == NULL) - return 0; +int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, const char* names, + byte curves_only) +{ + int idx, start = 0, len, i, ret = WOLFSSL_FAILURE; + word16 curve; + word32 disabled; + char name[MAX_CURVE_NAME_SZ]; + byte groups_len = 0; +#ifdef WOLFSSL_SMALL_STACK + void *heap = ssl? ssl->heap : ctx ? ctx->heap : NULL; + int *groups; +#else + int groups[WOLFSSL_MAX_GROUP_COUNT]; +#endif + const WOLF_EC_NIST_NAME* nist_name; - buf->data = tmp; - buf->length = len; - buf->max = mx; +#ifdef WOLFSSL_SMALL_STACK + groups = (int*)XMALLOC(sizeof(int)*WOLFSSL_MAX_GROUP_COUNT, + heap, DYNAMIC_TYPE_TMP_BUFFER); + if (groups == NULL) { + ret = MEMORY_E; + goto leave; + } +#endif - return (int)len; -} + for (idx = 1; names[idx-1] != '\0'; idx++) { + if (names[idx] != ':' && names[idx] != '\0') + continue; -void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf) -{ - if (buf) { - if (buf->data) { - XFREE(buf->data, NULL, DYNAMIC_TYPE_OPENSSL); - buf->data = NULL; - } - buf->max = 0; - buf->length = 0; - XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); - } -} -/* End Functions for openssl/buffer.h */ + len = idx - start; + if (len > MAX_CURVE_NAME_SZ - 1) + goto leave; -#endif /* OPENSSL_EXTRA */ + XMEMCPY(name, names + start, len); + name[len] = 0; + curve = WOLFSSL_NAMED_GROUP_INVALID; -/******************************************************************************* - * END OF BUF_MEM API - ******************************************************************************/ + for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { + if (len == nist_name->name_len && + XSTRNCMP(name, nist_name->name, len) == 0) { + curve = nist_name->curve; + break; + } + } -#define WOLFSSL_CONF_INCLUDED -#include + if (curve == WOLFSSL_NAMED_GROUP_INVALID) { + #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && defined(HAVE_ECC) + int nret; + const ecc_set_type *eccSet; -/******************************************************************************* - * START OF RAND API - ******************************************************************************/ + nret = wc_ecc_get_curve_idx_from_name(name); + if (nret < 0) { + WOLFSSL_MSG("Could not find name in set"); + goto leave; + } -#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) -static int wolfSSL_RAND_InitMutex(void) -{ -#ifndef WOLFSSL_MUTEX_INITIALIZER - if (gRandMethodsInit == 0) { - if (wc_InitMutex(&gRandMethodMutex) != 0) { - WOLFSSL_MSG("Bad Init Mutex rand methods"); - return BAD_MUTEX_E; + eccSet = wc_ecc_get_curve_params(ret); + if (eccSet == NULL) { + WOLFSSL_MSG("NULL set returned"); + goto leave; + } + + curve = GetCurveByOID(eccSet->oidSum); + #else + WOLFSSL_MSG("API not present to search farther using name"); + goto leave; + #endif } - gRandMethodsInit = 1; - } -#endif - return 0; -} -#endif -#ifdef OPENSSL_EXTRA + if ((curves_only && curve >= WOLFSSL_ECC_MAX_AVAIL) || + curve == WOLFSSL_NAMED_GROUP_INVALID) { + WOLFSSL_MSG("curve value is not supported"); + goto leave; + } -/* Checks if the global RNG has been created. If not then one is created. - * - * Returns WOLFSSL_SUCCESS when no error is encountered. - */ -int wolfSSL_RAND_Init(void) -{ - int ret = WOLFSSL_FAILURE; -#ifdef HAVE_GLOBAL_RNG - if (wc_LockMutex(&globalRNGMutex) == 0) { - if (initGlobalRNG == 0) { - ret = wc_InitRng(&globalRNG); - if (ret == 0) { - initGlobalRNG = 1; - ret = WOLFSSL_SUCCESS; + for (i = 0; i < groups_len; ++i) { + if (groups[i] == curve) { + /* silently drop duplicates */ + break; } } - else { - /* GlobalRNG is already initialized */ - ret = WOLFSSL_SUCCESS; + if (i >= groups_len) { + if (groups_len >= WOLFSSL_MAX_GROUP_COUNT) { + WOLFSSL_MSG_EX("setting %d or more supported " + "curves is not permitted", groups_len); + goto leave; + } + groups[groups_len++] = (int)curve; } - wc_UnLockMutex(&globalRNGMutex); + start = idx + 1; + } + + /* Disable all curves so that only the ones the user wants are enabled. */ + disabled = 0xFFFFFFFFUL; + for (i = 0; i < groups_len; ++i) { + /* Switch the bit to off and therefore is enabled. */ + curve = (word16)groups[i]; + if (curve >= 64) { + WC_DO_NOTHING; + } + else if (curve >= 32) { + /* 0 is for invalid and 1-14 aren't used otherwise. */ + disabled &= ~(1U << (curve - 32)); + } + else { + disabled &= ~(1U << curve); + } + #ifdef HAVE_SUPPORTED_CURVES + #if !defined(WOLFSSL_OLD_SET_CURVES_LIST) + /* using the wolfSSL API to set the groups, this will populate + * (ssl|ctx)->groups and reset any TLSX_SUPPORTED_GROUPS. + * The order in (ssl|ctx)->groups will then be respected + * when TLSX_KEY_SHARE needs to be established */ + if ((ssl && wolfSSL_set_groups(ssl, groups, groups_len) + != WOLFSSL_SUCCESS) + || (ctx && wolfSSL_CTX_set_groups(ctx, groups, groups_len) + != WOLFSSL_SUCCESS)) { + WOLFSSL_MSG("Unable to set supported curve"); + goto leave; + } + #elif !defined(NO_WOLFSSL_CLIENT) + /* set the supported curve so client TLS extension contains only the + * desired curves */ + if ((ssl && wolfSSL_UseSupportedCurve(ssl, curve) != WOLFSSL_SUCCESS) + || (ctx && wolfSSL_CTX_UseSupportedCurve(ctx, curve) + != WOLFSSL_SUCCESS)) { + WOLFSSL_MSG("Unable to set supported curve"); + goto leave; + } + #endif + #endif /* HAVE_SUPPORTED_CURVES */ } + + if (ssl) + ssl->disabledCurves = disabled; + else + ctx->disabledCurves = disabled; + ret = WOLFSSL_SUCCESS; + +leave: +#ifdef WOLFSSL_SMALL_STACK + if (groups) + XFREE((void*)groups, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } +int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set1_curves_list"); + if (ctx == NULL || names == NULL) { + WOLFSSL_MSG("ctx or names was NULL"); + return WOLFSSL_FAILURE; + } + return set_curves_list(NULL, ctx, names, 1); +} + +int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names) +{ + WOLFSSL_ENTER("wolfSSL_set1_curves_list"); + if (ssl == NULL || names == NULL) { + WOLFSSL_MSG("ssl or names was NULL"); + return WOLFSSL_FAILURE; + } + return set_curves_list(ssl, NULL, names, 1); +} +#endif /* (HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448) */ +#endif /* OPENSSL_EXTRA || HAVE_CURL */ -/* WOLFSSL_SUCCESS on ok */ -int wolfSSL_RAND_seed(const void* seed, int len) +#ifdef OPENSSL_EXTRA +/* Sets a callback for when sending and receiving protocol messages. + * This callback is copied to all WOLFSSL objects created from the ctx. + * + * ctx WOLFSSL_CTX structure to set callback in + * cb callback to use + * + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE with error case + */ +int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) { -#ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->seed) { - int ret = gRandMethods->seed(seed, len); - wc_UnLockMutex(&gRandMethodMutex); - return ret; - } - wc_UnLockMutex(&gRandMethodMutex); + WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback"); + if (ctx == NULL) { + WOLFSSL_MSG("Null ctx passed in"); + return WOLFSSL_FAILURE; } -#else - (void)seed; - (void)len; -#endif - /* Make sure global shared RNG (globalRNG) is initialized */ - return wolfSSL_RAND_Init(); + ctx->protoMsgCb = cb; + return WOLFSSL_SUCCESS; } -/* Returns the path for reading seed data from. - * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd - * - * Note uses stdlib by default unless XGETENV macro is overwritten +/* Sets a callback for when sending and receiving protocol messages. * - * fname buffer to hold path - * len length of fname buffer + * ssl WOLFSSL structure to set callback in + * cb callback to use * - * Returns a pointer to fname on success and NULL on failure + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE with error case */ -const char* wolfSSL_RAND_file_name(char* fname, unsigned long len) +int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) { -#if !defined(NO_FILESYSTEM) && defined(XGETENV) - char* rt; - - WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + WOLFSSL_ENTER("wolfSSL_set_msg_callback"); - if (fname == NULL) { - return NULL; + if (ssl == NULL) { + return WOLFSSL_FAILURE; } - XMEMSET(fname, 0, len); - - if ((rt = XGETENV("RANDFILE")) != NULL) { - if (len > XSTRLEN(rt)) { - XMEMCPY(fname, rt, XSTRLEN(rt)); - } - else { - WOLFSSL_MSG("RANDFILE too large for buffer"); - rt = NULL; - } + if (cb != NULL) { + ssl->toInfoOn = 1; } - /* $RANDFILE was not set or is too large, check $HOME */ - if (rt == NULL) { - const char ap[] = "/.rnd"; + ssl->protoMsgCb = cb; + return WOLFSSL_SUCCESS; +} - WOLFSSL_MSG("Environment variable RANDFILE not set"); - if ((rt = XGETENV("HOME")) == NULL) { - WOLFSSL_MSG("Environment variable HOME not set"); - return NULL; - } - if (len > XSTRLEN(rt) + XSTRLEN(ap)) { - fname[0] = '\0'; - XSTRNCAT(fname, rt, len); - XSTRNCAT(fname, ap, len - XSTRLEN(rt)); - return fname; - } - else { - WOLFSSL_MSG("HOME too large for buffer"); - return NULL; - } +/* set the user argument to pass to the msg callback when called + * return WOLFSSL_SUCCESS on success */ +int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_msg_callback_arg"); + if (ctx == NULL) { + WOLFSSL_MSG("Null WOLFSSL_CTX passed in"); + return WOLFSSL_FAILURE; } - return fname; -#else - WOLFSSL_ENTER("wolfSSL_RAND_file_name"); - WOLFSSL_MSG("RAND_file_name requires filesystem and getenv support, " - "not compiled in"); - (void)fname; - (void)len; - return NULL; -#endif + ctx->protoMsgCtx = arg; + return WOLFSSL_SUCCESS; } -/* Writes 1024 bytes from the RNG to the given file name. - * - * fname name of file to write to - * - * Returns the number of bytes written - */ -int wolfSSL_RAND_write_file(const char* fname) +int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) { - int bytes = 0; - - WOLFSSL_ENTER("wolfSSL_RAND_write_file"); - - if (fname == NULL) { + WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg"); + if (ssl == NULL) return WOLFSSL_FAILURE; - } - -#ifndef NO_FILESYSTEM - { - #ifndef WOLFSSL_SMALL_STACK - unsigned char buf[1024]; - #else - unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) { - WOLFSSL_MSG("malloc failed"); - return WOLFSSL_FAILURE; - } - #endif - bytes = 1024; /* default size of buf */ - if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("No RNG to use"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return 0; - } + ssl->protoMsgCtx = arg; + return WOLFSSL_SUCCESS; +} - if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) { - WOLFSSL_MSG("Error generating random buffer"); - bytes = 0; - } - else { - XFILE f; +void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, + int line) +{ + void *ret; + (void)file; + (void)line; - #ifdef WOLFSSL_CHECK_MEM_ZERO - wc_MemZero_Add("wolfSSL_RAND_write_file buf", buf, bytes); - #endif + if (data == NULL || siz >= INT_MAX) + return NULL; - f = XFOPEN(fname, "wb"); - if (f == XBADFILE) { - WOLFSSL_MSG("Error opening the file"); - bytes = 0; - } - else { - size_t bytes_written = XFWRITE(buf, 1, bytes, f); - bytes = (int)bytes_written; - XFCLOSE(f); - } - } - ForceZero(buf, bytes); - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #elif defined(WOLFSSL_CHECK_MEM_ZERO) - wc_MemZero_Check(buf, sizeof(buf)); - #endif + ret = OPENSSL_malloc(siz); + if (ret == NULL) { + return NULL; } -#endif + return XMEMCPY(ret, data, siz); +} - return bytes; +void wolfSSL_OPENSSL_cleanse(void *ptr, size_t len) +{ + if (ptr) + ForceZero(ptr, (word32)len); } -#ifndef FREERTOS_TCP +int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p, + unsigned int p_len) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos"); + if (ctx == NULL) + return BAD_FUNC_ARG; + if (ctx->alpn_cli_protos != NULL) { + XFREE((void*)ctx->alpn_cli_protos, ctx->heap, DYNAMIC_TYPE_OPENSSL); + } -/* These constant values are protocol values made by egd */ -#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS) && \ - defined(HAVE_HASHDRBG) && !defined(NETOS) && defined(HAVE_SYS_UN_H) - #define WOLFSSL_EGD_NBLOCK 0x01 - #include + ctx->alpn_cli_protos = (const unsigned char*)XMALLOC(p_len, + ctx->heap, DYNAMIC_TYPE_OPENSSL); + if (ctx->alpn_cli_protos == NULL) { +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* 0 on success in OpenSSL, non-0 on failure in OpenSSL + * the function reverses the return value convention. + */ + return 1; +#else + return WOLFSSL_FAILURE; #endif + } + XMEMCPY((void*)ctx->alpn_cli_protos, p, p_len); + ctx->alpn_cli_protos_len = p_len; -/* This collects entropy from the path nm and seeds the global PRNG with it. +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* 0 on success in OpenSSL, non-0 on failure in OpenSSL + * the function reverses the return value convention. + */ + return 0; +#else + return WOLFSSL_SUCCESS; +#endif +} + + +#ifdef HAVE_ALPN +#ifndef NO_BIO +/* Sets the ALPN extension protos * - * nm is the file path to the egd server + * example format is + * unsigned char p[] = { + * 8, 'h', 't', 't', 'p', '/', '1', '.', '1' + * }; * - * Returns the number of bytes read. - */ -int wolfSSL_RAND_egd(const char* nm) + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_set_alpn_protos(WOLFSSL* ssl, + const unsigned char* p, unsigned int p_len) { -#ifdef WOLFSSL_EGD_NBLOCK - struct sockaddr_un rem; - int fd; - int ret = WOLFSSL_SUCCESS; - word32 bytes = 0; - word32 idx = 0; -#ifndef WOLFSSL_SMALL_STACK - unsigned char buf[256]; + WOLFSSL_BIO* bio; + char* pt = NULL; + + unsigned int sz; + unsigned int idx = 0; + int alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; + WOLFSSL_ENTER("wolfSSL_set_alpn_protos"); + + if (ssl == NULL || p_len <= 1) { +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* 0 on success in OpenSSL, non-0 on failure in OpenSSL + * the function reverses the return value convention. + */ + return 1; #else - unsigned char* buf; - buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) { - WOLFSSL_MSG("Not enough memory"); - return WOLFSSL_FATAL_ERROR; - } + return WOLFSSL_FAILURE; #endif + } - XMEMSET(&rem, 0, sizeof(struct sockaddr_un)); - if (nm == NULL) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return WOLFSSL_FATAL_ERROR; + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + if (bio == NULL) { +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* 0 on success in OpenSSL, non-0 on failure in OpenSSL + * the function reverses the return value convention. + */ + return 1; +#else + return WOLFSSL_FAILURE; +#endif } - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - WOLFSSL_MSG("Error creating socket"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + /* convert into comma separated list */ + while (idx < p_len - 1) { + unsigned int i; + + sz = p[idx++]; + if (idx + sz > p_len) { + WOLFSSL_MSG("Bad list format"); + wolfSSL_BIO_free(bio); + #if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* 0 on success in OpenSSL, non-0 on failure in OpenSSL + * the function reverses the return value convention. + */ + return 1; + #else + return WOLFSSL_FAILURE; #endif - return WOLFSSL_FATAL_ERROR; + } + if (sz > 0) { + for (i = 0; i < sz; i++) { + wolfSSL_BIO_write(bio, &p[idx++], 1); + } + if (idx < p_len - 1) + wolfSSL_BIO_write(bio, ",", 1); + } } - rem.sun_family = AF_UNIX; - XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1); - rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; + wolfSSL_BIO_write(bio, "\0", 1); - /* connect to egd server */ - if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) == -1) { - WOLFSSL_MSG("error connecting to egd server"); - ret = WOLFSSL_FATAL_ERROR; - } + /* clears out all current ALPN extensions set */ + TLSX_Remove(&ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL, ssl->heap); -#ifdef WOLFSSL_CHECK_MEM_ZERO - if (ret == WOLFSSL_SUCCESS) { - wc_MemZero_Add("wolfSSL_RAND_egd buf", buf, 256); + if ((sz = (unsigned int)wolfSSL_BIO_get_mem_data(bio, &pt)) > 0) { + wolfSSL_UseALPN(ssl, pt, sz, (byte) alpn_opt); } + wolfSSL_BIO_free(bio); +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + /* 0 on success in OpenSSL, non-0 on failure in OpenSSL + * the function reverses the return value convention. + */ + return 0; +#else + return WOLFSSL_SUCCESS; #endif - while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) { - buf[idx] = WOLFSSL_EGD_NBLOCK; - buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */ - ret = (int)write(fd, buf + idx, 2); - if (ret != 2) { - if (errno == EAGAIN) { - ret = WOLFSSL_SUCCESS; - continue; - } - WOLFSSL_MSG("error requesting entropy from egd server"); - ret = WOLFSSL_FATAL_ERROR; - break; - } +} +#endif /* !NO_BIO */ +#endif /* HAVE_ALPN */ +#endif /* OPENSSL_EXTRA */ - /* attempting to read */ - buf[idx] = 0; - ret = (int)read(fd, buf + idx, 256 - bytes); - if (ret == 0) { - WOLFSSL_MSG("error reading entropy from egd server"); - ret = WOLFSSL_FATAL_ERROR; - break; - } - if (ret > 0 && buf[idx] > 0) { - bytes += buf[idx]; /* egd stores amount sent in first byte */ - if (bytes + idx > 255 || buf[idx] > ret) { - WOLFSSL_MSG("Buffer error"); - ret = WOLFSSL_FATAL_ERROR; - break; - } - XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]); - idx = bytes; - ret = WOLFSSL_SUCCESS; - if (bytes >= 255) { - break; - } - } - else { - if (errno == EAGAIN || errno == EINTR) { - WOLFSSL_MSG("EGD would read"); - ret = WOLFSSL_SUCCESS; /* try again */ - } - else if (buf[idx] == 0) { - /* if egd returned 0 then there is no more entropy to be had. - Do not try more reads. */ - ret = WOLFSSL_SUCCESS; - break; - } - else { - WOLFSSL_MSG("Error with read"); - ret = WOLFSSL_FATAL_ERROR; +#if defined(OPENSSL_EXTRA) + +#ifndef NO_BIO +#define WOLFSSL_BIO_INCLUDED +#include "src/bio.c" +#endif + +word32 nid2oid(int nid, int grp) +{ + /* get OID type */ + switch (grp) { + /* oidHashType */ + case oidHashType: + switch (nid) { + #ifdef WOLFSSL_MD2 + case NID_md2: + return MD2h; + #endif + #ifndef NO_MD5 + case NID_md5: + return MD5h; + #endif + #ifndef NO_SHA + case NID_sha1: + return SHAh; + #endif + case NID_sha224: + return SHA224h; + #ifndef NO_SHA256 + case NID_sha256: + return SHA256h; + #endif + #ifdef WOLFSSL_SHA384 + case NID_sha384: + return SHA384h; + #endif + #ifdef WOLFSSL_SHA512 + case NID_sha512: + return SHA512h; + #endif + #ifndef WOLFSSL_NOSHA3_224 + case NID_sha3_224: + return SHA3_224h; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case NID_sha3_256: + return SHA3_256h; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case NID_sha3_384: + return SHA3_384h; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case NID_sha3_512: + return SHA3_512h; + #endif } - } - } + break; - if (bytes > 0 && ret == WOLFSSL_SUCCESS) { - /* call to check global RNG is created */ - if (wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error with initializing global RNG structure"); - ret = WOLFSSL_FATAL_ERROR; - } - else if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes) - != 0) { - WOLFSSL_MSG("Error with reseeding DRBG structure"); - ret = WOLFSSL_FATAL_ERROR; - } - #ifdef SHOW_SECRETS - else { /* print out entropy found only when no error occurred */ - word32 i; - printf("EGD Entropy = "); - for (i = 0; i < bytes; i++) { - printf("%02X", buf[i]); + /* oidSigType */ + case oidSigType: + switch (nid) { + #ifndef NO_DSA + case NID_dsaWithSHA1: + return CTC_SHAwDSA; + case NID_dsa_with_SHA256: + return CTC_SHA256wDSA; + #endif /* NO_DSA */ + #ifndef NO_RSA + case NID_md2WithRSAEncryption: + return CTC_MD2wRSA; + case NID_md5WithRSAEncryption: + return CTC_MD5wRSA; + case NID_sha1WithRSAEncryption: + return CTC_SHAwRSA; + case NID_sha224WithRSAEncryption: + return CTC_SHA224wRSA; + case NID_sha256WithRSAEncryption: + return CTC_SHA256wRSA; + case NID_sha384WithRSAEncryption: + return CTC_SHA384wRSA; + case NID_sha512WithRSAEncryption: + return CTC_SHA512wRSA; + #ifdef WOLFSSL_SHA3 + case NID_RSA_SHA3_224: + return CTC_SHA3_224wRSA; + case NID_RSA_SHA3_256: + return CTC_SHA3_256wRSA; + case NID_RSA_SHA3_384: + return CTC_SHA3_384wRSA; + case NID_RSA_SHA3_512: + return CTC_SHA3_512wRSA; + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case NID_ecdsa_with_SHA1: + return CTC_SHAwECDSA; + case NID_ecdsa_with_SHA224: + return CTC_SHA224wECDSA; + case NID_ecdsa_with_SHA256: + return CTC_SHA256wECDSA; + case NID_ecdsa_with_SHA384: + return CTC_SHA384wECDSA; + case NID_ecdsa_with_SHA512: + return CTC_SHA512wECDSA; + #ifdef WOLFSSL_SHA3 + case NID_ecdsa_with_SHA3_224: + return CTC_SHA3_224wECDSA; + case NID_ecdsa_with_SHA3_256: + return CTC_SHA3_256wECDSA; + case NID_ecdsa_with_SHA3_384: + return CTC_SHA3_384wECDSA; + case NID_ecdsa_with_SHA3_512: + return CTC_SHA3_512wECDSA; + #endif + #endif /* HAVE_ECC */ } - printf("\n"); - } - #endif - } - - ForceZero(buf, bytes); -#ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#elif defined(WOLFSSL_CHECK_MEM_ZERO) - wc_MemZero_Check(buf, 256); -#endif - close(fd); - - if (ret == WOLFSSL_SUCCESS) { - return bytes; - } - else { - return ret; - } -#else - WOLFSSL_MSG("Type of socket needed is not available"); - WOLFSSL_MSG("\tor using mode where DRBG API is not available"); - (void)nm; + break; - return WOLFSSL_FATAL_ERROR; -#endif /* WOLFSSL_EGD_NBLOCK */ -} + /* oidKeyType */ + case oidKeyType: + switch (nid) { + #ifndef NO_DSA + case NID_dsa: + return DSAk; + #endif /* NO_DSA */ + #ifndef NO_RSA + case NID_rsaEncryption: + return RSAk; + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case NID_X9_62_id_ecPublicKey: + return ECDSAk; + #endif /* HAVE_ECC */ + } + break; -#endif /* !FREERTOS_TCP */ -void wolfSSL_RAND_Cleanup(void) -{ -#ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->cleanup) - gRandMethods->cleanup(); - wc_UnLockMutex(&gRandMethodMutex); - } + #ifdef HAVE_ECC + case oidCurveType: + switch (nid) { + case NID_X9_62_prime192v1: + return ECC_SECP192R1_OID; + case NID_X9_62_prime192v2: + return ECC_PRIME192V2_OID; + case NID_X9_62_prime192v3: + return ECC_PRIME192V3_OID; + case NID_X9_62_prime239v1: + return ECC_PRIME239V1_OID; + case NID_X9_62_prime239v2: + return ECC_PRIME239V2_OID; + case NID_X9_62_prime239v3: + return ECC_PRIME239V3_OID; + case NID_X9_62_prime256v1: + return ECC_SECP256R1_OID; + case NID_secp112r1: + return ECC_SECP112R1_OID; + case NID_secp112r2: + return ECC_SECP112R2_OID; + case NID_secp128r1: + return ECC_SECP128R1_OID; + case NID_secp128r2: + return ECC_SECP128R2_OID; + case NID_secp160r1: + return ECC_SECP160R1_OID; + case NID_secp160r2: + return ECC_SECP160R2_OID; + case NID_secp224r1: + return ECC_SECP224R1_OID; + case NID_secp384r1: + return ECC_SECP384R1_OID; + case NID_secp521r1: + return ECC_SECP521R1_OID; + case NID_secp160k1: + return ECC_SECP160K1_OID; + case NID_secp192k1: + return ECC_SECP192K1_OID; + case NID_secp224k1: + return ECC_SECP224K1_OID; + case NID_secp256k1: + return ECC_SECP256K1_OID; + case NID_brainpoolP160r1: + return ECC_BRAINPOOLP160R1_OID; + case NID_brainpoolP192r1: + return ECC_BRAINPOOLP192R1_OID; + case NID_brainpoolP224r1: + return ECC_BRAINPOOLP224R1_OID; + case NID_brainpoolP256r1: + return ECC_BRAINPOOLP256R1_OID; + case NID_brainpoolP320r1: + return ECC_BRAINPOOLP320R1_OID; + case NID_brainpoolP384r1: + return ECC_BRAINPOOLP384R1_OID; + case NID_brainpoolP512r1: + return ECC_BRAINPOOLP512R1_OID; + } + break; + #endif /* HAVE_ECC */ - #ifndef WOLFSSL_MUTEX_INITIALIZER - if (wc_FreeMutex(&gRandMethodMutex) == 0) - gRandMethodsInit = 0; - #endif -#endif -#ifdef HAVE_GLOBAL_RNG - if (wc_LockMutex(&globalRNGMutex) == 0) { - if (initGlobalRNG) { - wc_FreeRng(&globalRNG); - initGlobalRNG = 0; - } - wc_UnLockMutex(&globalRNGMutex); - } -#endif -} + /* oidBlkType */ + case oidBlkType: + switch (nid) { + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + return AES128CBCb; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + return AES192CBCb; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + return AES256CBCb; + #endif + #ifndef NO_DES3 + case NID_des: + return DESb; + case NID_des3: + return DES3b; + #endif + } + break; -/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */ -int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) -{ - int ret; - int hash; - byte secret[DRBG_SEED_LEN]; /* secret length arbitrarily chosen */ + #ifdef HAVE_OCSP + case oidOcspType: + switch (nid) { + case NID_id_pkix_OCSP_basic: + return OCSP_BASIC_OID; + case OCSP_NONCE_OID: + return OCSP_NONCE_OID; + } + break; + #endif /* HAVE_OCSP */ -#ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->pseudorand) { - ret = gRandMethods->pseudorand(buf, num); - wc_UnLockMutex(&gRandMethodMutex); - return ret; - } - wc_UnLockMutex(&gRandMethodMutex); - } -#endif + /* oidCertExtType */ + case oidCertExtType: + switch (nid) { + case NID_basic_constraints: + return BASIC_CA_OID; + case NID_subject_alt_name: + return ALT_NAMES_OID; + case NID_crl_distribution_points: + return CRL_DIST_OID; + case NID_info_access: + return AUTH_INFO_OID; + case NID_authority_key_identifier: + return AUTH_KEY_OID; + case NID_subject_key_identifier: + return SUBJ_KEY_OID; + case NID_inhibit_any_policy: + return INHIBIT_ANY_OID; + case NID_key_usage: + return KEY_USAGE_OID; + case NID_name_constraints: + return NAME_CONS_OID; + case NID_certificate_policies: + return CERT_POLICY_OID; + case NID_ext_key_usage: + return EXT_KEY_USAGE_OID; + } + break; -#ifdef WOLFSSL_HAVE_PRF - #ifndef NO_SHA256 - hash = WC_SHA256; - #elif defined(WOLFSSL_SHA384) - hash = WC_SHA384; - #elif !defined(NO_SHA) - hash = WC_SHA; - #elif !defined(NO_MD5) - hash = WC_MD5; - #endif + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (nid) { + case NID_ad_OCSP: + return AIA_OCSP_OID; + case NID_ad_ca_issuers: + return AIA_CA_ISSUER_OID; + } + break; - /* get secret value from source of entropy */ - ret = wolfSSL_RAND_bytes(secret, DRBG_SEED_LEN); + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (nid) { + case NID_any_policy: + return CP_ANY_OID; + } + break; - /* uses input buffer to seed for pseudo random number generation, each - * thread will potentially have different results this way */ - if (ret == WOLFSSL_SUCCESS) { - PRIVATE_KEY_UNLOCK(); - ret = wc_PRF(buf, num, secret, DRBG_SEED_LEN, (const byte*)buf, num, - hash, NULL, INVALID_DEVID); - PRIVATE_KEY_LOCK(); - ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; - } -#else - /* fall back to just doing wolfSSL_RAND_bytes if PRF not avialbale */ - ret = wolfSSL_RAND_bytes(buf, num); - (void)hash; - (void)secret; -#endif - return ret; -} + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (nid) { + case NID_hw_name_oid: + return HW_NAME_OID; + } + break; -/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */ -int wolfSSL_RAND_bytes(unsigned char* buf, int num) -{ - int ret = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRNG = NULL; -#else - WC_RNG tmpRNG[1]; -#endif - int initTmpRng = 0; -#ifdef HAVE_GLOBAL_RNG - int used_global = 0; -#endif + /* oidCertKeyUseType */ + case oidCertKeyUseType: + switch (nid) { + case NID_anyExtendedKeyUsage: + return EKU_ANY_OID; + case EKU_SERVER_AUTH_OID: + return EKU_SERVER_AUTH_OID; + case EKU_CLIENT_AUTH_OID: + return EKU_CLIENT_AUTH_OID; + case EKU_OCSP_SIGN_OID: + return EKU_OCSP_SIGN_OID; + } + break; - WOLFSSL_ENTER("wolfSSL_RAND_bytes"); - /* sanity check */ - if (buf == NULL || num < 0) - /* return code compliant with OpenSSL */ - return 0; + /* oidKdfType */ + case oidKdfType: + switch (nid) { + case PBKDF2_OID: + return PBKDF2_OID; + } + break; - /* if a RAND callback has been set try and use it */ -#ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->bytes) { - ret = gRandMethods->bytes(buf, num); - wc_UnLockMutex(&gRandMethodMutex); - return ret; - } - wc_UnLockMutex(&gRandMethodMutex); - } -#endif -#ifdef HAVE_GLOBAL_RNG - if (initGlobalRNG) { - if (wc_LockMutex(&globalRNGMutex) != 0) { - WOLFSSL_MSG("Bad Lock Mutex rng"); - return ret; - } + /* oidPBEType */ + case oidPBEType: + switch (nid) { + case PBE_SHA1_RC4_128: + return PBE_SHA1_RC4_128; + case PBE_SHA1_DES: + return PBE_SHA1_DES; + case PBE_SHA1_DES3: + return PBE_SHA1_DES3; + } + break; - rng = &globalRNG; - used_global = 1; - } - else -#endif - { - #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRNG == NULL) - return ret; - #endif - if (wc_InitRng(tmpRNG) == 0) { - rng = tmpRNG; - initTmpRng = 1; - } - } - if (rng) { - /* handles size greater than RNG_MAX_BLOCK_LEN */ - int blockCount = num / RNG_MAX_BLOCK_LEN; + /* oidKeyWrapType */ + case oidKeyWrapType: + switch (nid) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + return AES128_WRAP; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + return AES192_WRAP; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + return AES256_WRAP; + #endif + } + break; - while (blockCount--) { - ret = wc_RNG_GenerateBlock(rng, buf, RNG_MAX_BLOCK_LEN); - if (ret != 0) { - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - break; + /* oidCmsKeyAgreeType */ + case oidCmsKeyAgreeType: + switch (nid) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + return dhSinglePass_stdDH_sha1kdf_scheme; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + return dhSinglePass_stdDH_sha224kdf_scheme; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + return dhSinglePass_stdDH_sha256kdf_scheme; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + return dhSinglePass_stdDH_sha384kdf_scheme; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + return dhSinglePass_stdDH_sha512kdf_scheme; + #endif } - num -= RNG_MAX_BLOCK_LEN; - buf += RNG_MAX_BLOCK_LEN; - } + break; - if (ret == 0 && num) - ret = wc_RNG_GenerateBlock(rng, buf, num); + /* oidCmsKeyAgreeType */ + #ifdef WOLFSSL_CERT_REQ + case oidCsrAttrType: + switch (nid) { + case NID_pkcs9_contentType: + return PKCS9_CONTENT_TYPE_OID; + case NID_pkcs9_challengePassword: + return CHALLENGE_PASSWORD_OID; + case NID_serialNumber: + return SERIAL_NUMBER_OID; + case NID_userId: + return USER_ID_OID; + case NID_surname: + return SURNAME_OID; + } + break; + #endif - if (ret != 0) - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - else - ret = WOLFSSL_SUCCESS; + default: + WOLFSSL_MSG("NID not in table"); + /* MSVC warns without the cast */ + return (word32)-1; } -#ifdef HAVE_GLOBAL_RNG - if (used_global == 1) - wc_UnLockMutex(&globalRNGMutex); -#endif - if (initTmpRng) - wc_FreeRng(tmpRNG); -#ifdef WOLFSSL_SMALL_STACK - if (tmpRNG) - XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); -#endif - - return ret; + /* MSVC warns without the cast */ + return (word32)-1; } - -int wolfSSL_RAND_poll(void) +int oid2nid(word32 oid, int grp) { - byte entropy[16]; - int ret = 0; - word32 entropy_sz = 16; + size_t i; + /* get OID type */ + switch (grp) { + /* oidHashType */ + case oidHashType: + switch (oid) { + #ifdef WOLFSSL_MD2 + case MD2h: + return NID_md2; + #endif + #ifndef NO_MD5 + case MD5h: + return NID_md5; + #endif + #ifndef NO_SHA + case SHAh: + return NID_sha1; + #endif + case SHA224h: + return NID_sha224; + #ifndef NO_SHA256 + case SHA256h: + return NID_sha256; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + return NID_sha384; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + return NID_sha512; + #endif + } + break; - WOLFSSL_ENTER("wolfSSL_RAND_poll"); - if (initGlobalRNG == 0){ - WOLFSSL_MSG("Global RNG no Init"); - return WOLFSSL_FAILURE; - } - ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz); - if (ret != 0){ - WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); - ret = WOLFSSL_FAILURE; - }else - ret = WOLFSSL_SUCCESS; + /* oidSigType */ + case oidSigType: + switch (oid) { + #ifndef NO_DSA + case CTC_SHAwDSA: + return NID_dsaWithSHA1; + case CTC_SHA256wDSA: + return NID_dsa_with_SHA256; + #endif /* NO_DSA */ + #ifndef NO_RSA + case CTC_MD2wRSA: + return NID_md2WithRSAEncryption; + case CTC_MD5wRSA: + return NID_md5WithRSAEncryption; + case CTC_SHAwRSA: + return NID_sha1WithRSAEncryption; + case CTC_SHA224wRSA: + return NID_sha224WithRSAEncryption; + case CTC_SHA256wRSA: + return NID_sha256WithRSAEncryption; + case CTC_SHA384wRSA: + return NID_sha384WithRSAEncryption; + case CTC_SHA512wRSA: + return NID_sha512WithRSAEncryption; + #ifdef WOLFSSL_SHA3 + case CTC_SHA3_224wRSA: + return NID_RSA_SHA3_224; + case CTC_SHA3_256wRSA: + return NID_RSA_SHA3_256; + case CTC_SHA3_384wRSA: + return NID_RSA_SHA3_384; + case CTC_SHA3_512wRSA: + return NID_RSA_SHA3_512; + #endif + #ifdef WC_RSA_PSS + case CTC_RSASSAPSS: + return NID_rsassaPss; + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case CTC_SHAwECDSA: + return NID_ecdsa_with_SHA1; + case CTC_SHA224wECDSA: + return NID_ecdsa_with_SHA224; + case CTC_SHA256wECDSA: + return NID_ecdsa_with_SHA256; + case CTC_SHA384wECDSA: + return NID_ecdsa_with_SHA384; + case CTC_SHA512wECDSA: + return NID_ecdsa_with_SHA512; + #ifdef WOLFSSL_SHA3 + case CTC_SHA3_224wECDSA: + return NID_ecdsa_with_SHA3_224; + case CTC_SHA3_256wECDSA: + return NID_ecdsa_with_SHA3_256; + case CTC_SHA3_384wECDSA: + return NID_ecdsa_with_SHA3_384; + case CTC_SHA3_512wECDSA: + return NID_ecdsa_with_SHA3_512; + #endif + #endif /* HAVE_ECC */ + } + break; - return ret; -} + /* oidKeyType */ + case oidKeyType: + switch (oid) { + #ifndef NO_DSA + case DSAk: + return NID_dsa; + #endif /* NO_DSA */ + #ifndef NO_RSA + case RSAk: + return NID_rsaEncryption; + #ifdef WC_RSA_PSS + case RSAPSSk: + return NID_rsassaPss; + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + return NID_X9_62_id_ecPublicKey; + #endif /* HAVE_ECC */ + } + break; - /* If a valid struct is provided with function pointers, will override - RAND_seed, bytes, cleanup, add, pseudo_bytes and status. If a NULL - pointer is passed in, it will cancel any previous function overrides. - Returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure. */ - int wolfSSL_RAND_set_rand_method(const WOLFSSL_RAND_METHOD *methods) - { - #ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - gRandMethods = methods; - wc_UnLockMutex(&gRandMethodMutex); - return WOLFSSL_SUCCESS; - } - #else - (void)methods; - #endif - return WOLFSSL_FAILURE; - } + #ifdef HAVE_ECC + case oidCurveType: + switch (oid) { + case ECC_SECP192R1_OID: + return NID_X9_62_prime192v1; + case ECC_PRIME192V2_OID: + return NID_X9_62_prime192v2; + case ECC_PRIME192V3_OID: + return NID_X9_62_prime192v3; + case ECC_PRIME239V1_OID: + return NID_X9_62_prime239v1; + case ECC_PRIME239V2_OID: + return NID_X9_62_prime239v2; + case ECC_PRIME239V3_OID: + return NID_X9_62_prime239v3; + case ECC_SECP256R1_OID: + return NID_X9_62_prime256v1; + case ECC_SECP112R1_OID: + return NID_secp112r1; + case ECC_SECP112R2_OID: + return NID_secp112r2; + case ECC_SECP128R1_OID: + return NID_secp128r1; + case ECC_SECP128R2_OID: + return NID_secp128r2; + case ECC_SECP160R1_OID: + return NID_secp160r1; + case ECC_SECP160R2_OID: + return NID_secp160r2; + case ECC_SECP224R1_OID: + return NID_secp224r1; + case ECC_SECP384R1_OID: + return NID_secp384r1; + case ECC_SECP521R1_OID: + return NID_secp521r1; + case ECC_SECP160K1_OID: + return NID_secp160k1; + case ECC_SECP192K1_OID: + return NID_secp192k1; + case ECC_SECP224K1_OID: + return NID_secp224k1; + case ECC_SECP256K1_OID: + return NID_secp256k1; + case ECC_BRAINPOOLP160R1_OID: + return NID_brainpoolP160r1; + case ECC_BRAINPOOLP192R1_OID: + return NID_brainpoolP192r1; + case ECC_BRAINPOOLP224R1_OID: + return NID_brainpoolP224r1; + case ECC_BRAINPOOLP256R1_OID: + return NID_brainpoolP256r1; + case ECC_BRAINPOOLP320R1_OID: + return NID_brainpoolP320r1; + case ECC_BRAINPOOLP384R1_OID: + return NID_brainpoolP384r1; + case ECC_BRAINPOOLP512R1_OID: + return NID_brainpoolP512r1; + } + break; + #endif /* HAVE_ECC */ - /* Returns WOLFSSL_SUCCESS if the RNG has been seeded with enough data */ - int wolfSSL_RAND_status(void) - { - int ret = WOLFSSL_SUCCESS; - #ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->status) - ret = gRandMethods->status(); - wc_UnLockMutex(&gRandMethodMutex); - } - else { - ret = WOLFSSL_FAILURE; - } - #else - /* wolfCrypt provides enough seed internally, so return success */ - #endif - return ret; - } + /* oidBlkType */ + case oidBlkType: + switch (oid) { + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + return AES128CBCb; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + return AES192CBCb; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + return AES256CBCb; + #endif + #ifndef NO_DES3 + case DESb: + return NID_des; + case DES3b: + return NID_des3; + #endif + } + break; - void wolfSSL_RAND_add(const void* add, int len, double entropy) - { - #ifndef WOLFSSL_NO_OPENSSL_RAND_CB - if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { - if (gRandMethods && gRandMethods->add) { - /* callback has return code, but RAND_add does not */ - (void)gRandMethods->add(add, len, entropy); + #ifdef HAVE_OCSP + case oidOcspType: + switch (oid) { + case OCSP_BASIC_OID: + return NID_id_pkix_OCSP_basic; + case OCSP_NONCE_OID: + return OCSP_NONCE_OID; } - wc_UnLockMutex(&gRandMethodMutex); - } - #else - /* wolfSSL seeds/adds internally, use explicit RNG if you want - to take control */ - (void)add; - (void)len; - (void)entropy; - #endif - } + break; + #endif /* HAVE_OCSP */ -#endif /* OPENSSL_EXTRA */ + /* oidCertExtType */ + case oidCertExtType: + switch (oid) { + case BASIC_CA_OID: + return NID_basic_constraints; + case ALT_NAMES_OID: + return NID_subject_alt_name; + case CRL_DIST_OID: + return NID_crl_distribution_points; + case AUTH_INFO_OID: + return NID_info_access; + case AUTH_KEY_OID: + return NID_authority_key_identifier; + case SUBJ_KEY_OID: + return NID_subject_key_identifier; + case INHIBIT_ANY_OID: + return NID_inhibit_any_policy; + case KEY_USAGE_OID: + return NID_key_usage; + case NAME_CONS_OID: + return NID_name_constraints; + case CERT_POLICY_OID: + return NID_certificate_policies; + case EXT_KEY_USAGE_OID: + return NID_ext_key_usage; + } + break; -/******************************************************************************* - * END OF RAND API - ******************************************************************************/ + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (oid) { + case AIA_OCSP_OID: + return NID_ad_OCSP; + case AIA_CA_ISSUER_OID: + return NID_ad_ca_issuers; + } + break; -/******************************************************************************* - * START OF EVP_CIPHER API - ******************************************************************************/ + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (oid) { + case CP_ANY_OID: + return NID_any_policy; + } + break; -#ifdef OPENSSL_EXTRA + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (oid) { + case HW_NAME_OID: + return NID_hw_name_oid; + } + break; - /* store for external read of iv, WOLFSSL_SUCCESS on success */ - int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) - { - WOLFSSL_ENTER("wolfSSL_StoreExternalIV"); + /* oidCertKeyUseType */ + case oidCertKeyUseType: + switch (oid) { + case EKU_ANY_OID: + return NID_anyExtendedKeyUsage; + case EKU_SERVER_AUTH_OID: + return EKU_SERVER_AUTH_OID; + case EKU_CLIENT_AUTH_OID: + return EKU_CLIENT_AUTH_OID; + case EKU_OCSP_SIGN_OID: + return EKU_OCSP_SIGN_OID; + } + break; - if (ctx == NULL) { - WOLFSSL_MSG("Bad function argument"); - return WOLFSSL_FATAL_ERROR; - } + /* oidKdfType */ + case oidKdfType: + switch (oid) { + case PBKDF2_OID: + return PBKDF2_OID; + } + break; - switch (ctx->cipherType) { -#ifndef NO_AES -#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) - case AES_128_CBC_TYPE : - case AES_192_CBC_TYPE : - case AES_256_CBC_TYPE : - WOLFSSL_MSG("AES CBC"); - XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz); - break; -#endif -#ifdef HAVE_AESGCM - case AES_128_GCM_TYPE : - case AES_192_GCM_TYPE : - case AES_256_GCM_TYPE : - WOLFSSL_MSG("AES GCM"); - XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz); - break; -#endif /* HAVE_AESGCM */ -#ifdef HAVE_AESCCM - case AES_128_CCM_TYPE : - case AES_192_CCM_TYPE : - case AES_256_CCM_TYPE : - WOLFSSL_MSG("AES CCM"); - XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz); - break; -#endif /* HAVE_AESCCM */ -#ifdef HAVE_AES_ECB - case AES_128_ECB_TYPE : - case AES_192_ECB_TYPE : - case AES_256_ECB_TYPE : - WOLFSSL_MSG("AES ECB"); - break; -#endif -#ifdef WOLFSSL_AES_COUNTER - case AES_128_CTR_TYPE : - case AES_192_CTR_TYPE : - case AES_256_CTR_TYPE : - WOLFSSL_MSG("AES CTR"); - XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); - break; -#endif /* WOLFSSL_AES_COUNTER */ -#ifdef WOLFSSL_AES_CFB -#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) - case AES_128_CFB1_TYPE: - case AES_192_CFB1_TYPE: - case AES_256_CFB1_TYPE: - WOLFSSL_MSG("AES CFB1"); - break; - case AES_128_CFB8_TYPE: - case AES_192_CFB8_TYPE: - case AES_256_CFB8_TYPE: - WOLFSSL_MSG("AES CFB8"); - break; -#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ - case AES_128_CFB128_TYPE: - case AES_192_CFB128_TYPE: - case AES_256_CFB128_TYPE: - WOLFSSL_MSG("AES CFB128"); - break; -#endif /* WOLFSSL_AES_CFB */ -#if defined(WOLFSSL_AES_OFB) - case AES_128_OFB_TYPE: - case AES_192_OFB_TYPE: - case AES_256_OFB_TYPE: - WOLFSSL_MSG("AES OFB"); - break; -#endif /* WOLFSSL_AES_OFB */ -#ifdef WOLFSSL_AES_XTS - case AES_128_XTS_TYPE: - case AES_256_XTS_TYPE: - WOLFSSL_MSG("AES XTS"); - break; -#endif /* WOLFSSL_AES_XTS */ -#endif /* NO_AES */ + /* oidPBEType */ + case oidPBEType: + switch (oid) { + case PBE_SHA1_RC4_128: + return PBE_SHA1_RC4_128; + case PBE_SHA1_DES: + return PBE_SHA1_DES; + case PBE_SHA1_DES3: + return PBE_SHA1_DES3; + } + break; -#ifdef HAVE_ARIA - case ARIA_128_GCM_TYPE : - case ARIA_192_GCM_TYPE : - case ARIA_256_GCM_TYPE : - WOLFSSL_MSG("ARIA GCM"); - XMEMCPY(ctx->iv, &ctx->cipher.aria.nonce, ARIA_BLOCK_SIZE); - break; -#endif /* HAVE_ARIA */ + /* oidKeyWrapType */ + case oidKeyWrapType: + switch (oid) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + return AES128_WRAP; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + return AES192_WRAP; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + return AES256_WRAP; + #endif + } + break; -#ifndef NO_DES3 - case DES_CBC_TYPE : - WOLFSSL_MSG("DES CBC"); - XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE); - break; + /* oidCmsKeyAgreeType */ + case oidCmsKeyAgreeType: + switch (oid) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + return dhSinglePass_stdDH_sha1kdf_scheme; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + return dhSinglePass_stdDH_sha224kdf_scheme; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + return dhSinglePass_stdDH_sha256kdf_scheme; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + return dhSinglePass_stdDH_sha384kdf_scheme; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + return dhSinglePass_stdDH_sha512kdf_scheme; + #endif + } + break; - case DES_EDE3_CBC_TYPE : - WOLFSSL_MSG("DES EDE3 CBC"); - XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); - break; -#endif -#ifdef WOLFSSL_DES_ECB - case DES_ECB_TYPE : - WOLFSSL_MSG("DES ECB"); - break; - case DES_EDE3_ECB_TYPE : - WOLFSSL_MSG("DES3 ECB"); - break; +#ifdef WOLFSSL_CERT_REQ + case oidCsrAttrType: + switch (oid) { + case PKCS9_CONTENT_TYPE_OID: + return NID_pkcs9_contentType; + case CHALLENGE_PASSWORD_OID: + return NID_pkcs9_challengePassword; + case SERIAL_NUMBER_OID: + return NID_serialNumber; + case USER_ID_OID: + return NID_userId; + } + break; #endif - case ARC4_TYPE : - WOLFSSL_MSG("ARC4"); - break; -#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case CHACHA20_POLY1305_TYPE: - break; -#endif + default: + WOLFSSL_MSG("OID not in table"); + } + /* If not found in above switch then try the table */ + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) { + if (wolfssl_object_info[i].id == (int)oid) { + return wolfssl_object_info[i].nid; + } + } -#ifdef HAVE_CHACHA - case CHACHA20_TYPE: - break; -#endif + return -1; +} -#ifdef WOLFSSL_SM4_ECB - case SM4_ECB_TYPE: - break; -#endif -#ifdef WOLFSSL_SM4_CBC - case SM4_CBC_TYPE: - WOLFSSL_MSG("SM4 CBC"); - XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); - break; -#endif -#ifdef WOLFSSL_SM4_CTR - case SM4_CTR_TYPE: - WOLFSSL_MSG("SM4 CTR"); - XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); - break; -#endif -#ifdef WOLFSSL_SM4_GCM - case SM4_GCM_TYPE: - WOLFSSL_MSG("SM4 GCM"); - XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); - break; -#endif -#ifdef WOLFSSL_SM4_CCM - case SM4_CCM_TYPE: - WOLFSSL_MSG("SM4 CCM"); - XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); - break; -#endif +/* frees all nodes in the current threads error queue + * + * id thread id. ERR_remove_state is depreciated and id is ignored. The + * current threads queue will be free'd. + */ +void wolfSSL_ERR_remove_state(unsigned long id) +{ + WOLFSSL_ENTER("wolfSSL_ERR_remove_state"); + (void)id; + if (wc_ERR_remove_state() != 0) { + WOLFSSL_MSG("Error with removing the state"); + } +} - case NULL_CIPHER_TYPE : - WOLFSSL_MSG("NULL"); - break; +#endif /* OPENSSL_EXTRA */ - default: { - WOLFSSL_MSG("bad type"); - return WOLFSSL_FATAL_ERROR; +#ifdef OPENSSL_ALL + +#if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) + +static int bio_get_data(WOLFSSL_BIO* bio, byte** data) +{ + int ret = 0; + byte* mem = NULL; + + ret = wolfSSL_BIO_get_len(bio); + if (ret > 0) { + mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (mem == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + if (ret >= 0) { + if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + ret = MEMORY_E; + mem = NULL; } } - return WOLFSSL_SUCCESS; } - /* set internal IV from external, WOLFSSL_SUCCESS on success */ - int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) - { + *data = mem; - WOLFSSL_ENTER("wolfSSL_SetInternalIV"); + return ret; +} - if (ctx == NULL) { - WOLFSSL_MSG("Bad function argument"); - return WOLFSSL_FATAL_ERROR; +/* DER data is PKCS#8 encrypted. */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** pkey, + wc_pem_password_cb* cb, + void* ctx) +{ + int ret; + byte* der; + int len; + byte* p; + word32 algId; + WOLFSSL_EVP_PKEY* key; + + if ((len = bio_get_data(bio, &der)) < 0) + return NULL; + + if (cb != NULL) { + char password[NAME_SZ]; + int passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); + if (passwordSz < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; } + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password, + passwordSz); + #endif - switch (ctx->cipherType) { + ret = ToTraditionalEnc(der, (word32)len, password, passwordSz, &algId); + if (ret < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; + } -#ifndef NO_AES -#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) - case AES_128_CBC_TYPE : - case AES_192_CBC_TYPE : - case AES_256_CBC_TYPE : - WOLFSSL_MSG("AES CBC"); - XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); - break; -#endif -#ifdef HAVE_AESGCM - case AES_128_GCM_TYPE : - case AES_192_GCM_TYPE : - case AES_256_GCM_TYPE : - WOLFSSL_MSG("AES GCM"); - XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); - break; -#endif -#ifdef HAVE_AES_ECB - case AES_128_ECB_TYPE : - case AES_192_ECB_TYPE : - case AES_256_ECB_TYPE : - WOLFSSL_MSG("AES ECB"); - break; -#endif -#ifdef WOLFSSL_AES_COUNTER - case AES_128_CTR_TYPE : - case AES_192_CTR_TYPE : - case AES_256_CTR_TYPE : - WOLFSSL_MSG("AES CTR"); - XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); - break; -#endif + ForceZero(password, (word32)passwordSz); + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(password, passwordSz); + #endif + } -#endif /* NO_AES */ + p = der; + key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len); + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return key; +} -#ifdef HAVE_ARIA - case ARIA_128_GCM_TYPE : - case ARIA_192_GCM_TYPE : - case ARIA_256_GCM_TYPE : - WOLFSSL_MSG("ARIA GCM"); - XMEMCPY(&ctx->cipher.aria.nonce, ctx->iv, ARIA_BLOCK_SIZE); - break; -#endif /* HAVE_ARIA */ +#endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ -#ifndef NO_DES3 - case DES_CBC_TYPE : - WOLFSSL_MSG("DES CBC"); - XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE); - break; +/* Detect which type of key it is before decoding. */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey, + const unsigned char** pp, + long length) +{ + int ret; + WOLFSSL_EVP_PKEY* key = NULL; + const byte* der = *pp; + word32 idx = 0; + int len = 0; + int cnt = 0; + word32 algId; + word32 keyLen = (word32)length; - case DES_EDE3_CBC_TYPE : - WOLFSSL_MSG("DES EDE3 CBC"); - XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE); - break; -#endif -#ifdef WOLFSSL_DES_ECB - case DES_ECB_TYPE : - WOLFSSL_MSG("DES ECB"); - break; - case DES_EDE3_ECB_TYPE : - WOLFSSL_MSG("DES3 ECB"); - break; -#endif + /* Take off PKCS#8 wrapper if found. */ + if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { + der += idx; + keyLen = (word32)len; + } + idx = 0; + len = 0; - case ARC4_TYPE : - WOLFSSL_MSG("ARC4"); - break; + /* Use the number of elements in the outer sequence to determine key type. + */ + ret = GetSequence(der, &idx, &len, keyLen); + if (ret >= 0) { + word32 end = idx + len; + while (ret >= 0 && idx < end) { + /* Skip type */ + idx++; + /* Get length and skip over - keeping count */ + len = 0; + ret = GetLength(der, &idx, &len, keyLen); + if (ret >= 0) { + if (idx + len > end) + ret = ASN_PARSE_E; + else { + idx += len; + cnt++; + } + } + } + } -#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case CHACHA20_POLY1305_TYPE: - break; -#endif + if (ret >= 0) { + int type; + /* ECC includes version, private[, curve][, public key] */ + if (cnt >= 2 && cnt <= 4) + type = EVP_PKEY_EC; + else + type = EVP_PKEY_RSA; -#ifdef HAVE_CHACHA - case CHACHA20_TYPE: - break; -#endif + key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); + *pp = der; + } -#ifdef WOLFSSL_SM4_ECB - case SM4_ECB_TYPE: - break; -#endif -#ifdef WOLFSSL_SM4_CBC - case SM4_CBC_TYPE: - WOLFSSL_MSG("SM4 CBC"); - XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); - break; -#endif -#ifdef WOLFSSL_SM4_CTR - case SM4_CTR_TYPE: - WOLFSSL_MSG("SM4 CTR"); - XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); - break; -#endif -#ifdef WOLFSSL_SM4_GCM - case SM4_GCM_TYPE: - WOLFSSL_MSG("SM4 GCM"); - XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); - break; -#endif -#ifdef WOLFSSL_SM4_CCM - case SM4_CCM_TYPE: - WOLFSSL_MSG("SM4 CCM"); - XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); - break; -#endif + return key; +} +#endif /* OPENSSL_ALL */ - case NULL_CIPHER_TYPE : - WOLFSSL_MSG("NULL"); - break; +#ifdef WOLFSSL_STATIC_EPHEMERAL +int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr) +{ + int ret; + word32 idx = 0; + DerBuffer* der = NULL; + + if (ssl == NULL || ssl->ctx == NULL || keyPtr == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + if (!ssl->ctx->staticKELockInit) { + return BUFFER_E; /* no keys set */ + } + ret = wc_LockMutex(&ssl->ctx->staticKELock); + if (ret != 0) { + return ret; + } +#endif - default: { - WOLFSSL_MSG("bad type"); - return WOLFSSL_FATAL_ERROR; + ret = BUFFER_E; /* set default error */ + switch (keyAlgo) { + #ifndef NO_DH + case WC_PK_TYPE_DH: + if (ssl != NULL) + der = ssl->staticKE.dhKey; + if (der == NULL) + der = ssl->ctx->staticKE.dhKey; + if (der != NULL) { + DhKey* key = (DhKey*)keyPtr; + WOLFSSL_MSG("Using static DH key"); + ret = wc_DhKeyDecode(der->buffer, &idx, key, der->length); } - } - return WOLFSSL_SUCCESS; + break; + #endif + #ifdef HAVE_ECC + case WC_PK_TYPE_ECDH: + if (ssl != NULL) + der = ssl->staticKE.ecKey; + if (der == NULL) + der = ssl->ctx->staticKE.ecKey; + if (der != NULL) { + ecc_key* key = (ecc_key*)keyPtr; + WOLFSSL_MSG("Using static ECDH key"); + ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, + der->length); + } + break; + #endif + #ifdef HAVE_CURVE25519 + case WC_PK_TYPE_CURVE25519: + if (ssl != NULL) + der = ssl->staticKE.x25519Key; + if (der == NULL) + der = ssl->ctx->staticKE.x25519Key; + if (der != NULL) { + curve25519_key* key = (curve25519_key*)keyPtr; + WOLFSSL_MSG("Using static X25519 key"); + ret = wc_Curve25519PrivateKeyDecode(der->buffer, &idx, key, + der->length); + } + break; + #endif + #ifdef HAVE_CURVE448 + case WC_PK_TYPE_CURVE448: + if (ssl != NULL) + der = ssl->staticKE.x448Key; + if (der == NULL) + der = ssl->ctx->staticKE.x448Key; + if (der != NULL) { + curve448_key* key = (curve448_key*)keyPtr; + WOLFSSL_MSG("Using static X448 key"); + ret = wc_Curve448PrivateKeyDecode(der->buffer, &idx, key, + der->length); + } + break; + #endif + default: + /* not supported */ + ret = NOT_COMPILED_IN; + break; } -#ifndef NO_DES3 +#ifndef SINGLE_THREADED + wc_UnLockMutex(&ssl->ctx->staticKELock); +#endif + return ret; +} -void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, - unsigned char* iv, int len) +static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx, + StaticKeyExchangeInfo_t* staticKE, int keyAlgo, const char* key, + unsigned int keySz, int format, void* heap) { - (void)len; - - WOLFSSL_MSG("wolfSSL_3des_iv"); + int ret = 0; + DerBuffer* der = NULL; + byte* keyBuf = NULL; +#ifndef NO_FILESYSTEM + const char* keyFile = NULL; +#endif - if (ctx == NULL || iv == NULL) { - WOLFSSL_MSG("Bad function argument"); - return; + /* allow empty key to free buffer */ + if (staticKE == NULL || (key == NULL && keySz > 0)) { + return BAD_FUNC_ARG; } - if (doset) - wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */ - else - XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); -} - -#endif /* NO_DES3 */ - + WOLFSSL_ENTER("SetStaticEphemeralKey"); -#ifndef NO_AES + /* if just free'ing key then skip loading */ + if (key != NULL) { + #ifndef NO_FILESYSTEM + /* load file from filesystem */ + if (key != NULL && keySz == 0) { + size_t keyBufSz = 0; + keyFile = (const char*)key; + ret = wc_FileLoad(keyFile, &keyBuf, &keyBufSz, heap); + if (ret != 0) { + return ret; + } + keySz = (unsigned int)keyBufSz; + } + else + #endif + { + /* use as key buffer directly */ + keyBuf = (byte*)key; + } -void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, - unsigned char* iv, int len) -{ - (void)len; + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + int keyFormat = 0; + ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &der, + heap, NULL, &keyFormat); + /* auto detect key type */ + if (ret == 0 && keyAlgo == WC_PK_TYPE_NONE) { + if (keyFormat == ECDSAk) + keyAlgo = WC_PK_TYPE_ECDH; + else if (keyFormat == X25519k) + keyAlgo = WC_PK_TYPE_CURVE25519; + else + keyAlgo = WC_PK_TYPE_DH; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + /* Detect PK type (if required) */ + #ifdef HAVE_ECC + if (keyAlgo == WC_PK_TYPE_NONE) { + word32 idx = 0; + ecc_key eccKey; + ret = wc_ecc_init_ex(&eccKey, heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &eccKey, keySz); + if (ret == 0) + keyAlgo = WC_PK_TYPE_ECDH; + wc_ecc_free(&eccKey); + } + } + #endif + #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) + if (keyAlgo == WC_PK_TYPE_NONE) { + word32 idx = 0; + DhKey dhKey; + ret = wc_InitDhKey_ex(&dhKey, heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_DhKeyDecode(keyBuf, &idx, &dhKey, keySz); + if (ret == 0) + keyAlgo = WC_PK_TYPE_DH; + wc_FreeDhKey(&dhKey); + } + } + #endif + #ifdef HAVE_CURVE25519 + if (keyAlgo == WC_PK_TYPE_NONE) { + word32 idx = 0; + curve25519_key x25519Key; + ret = wc_curve25519_init_ex(&x25519Key, heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Curve25519PrivateKeyDecode(keyBuf, &idx, + &x25519Key, keySz); + if (ret == 0) + keyAlgo = WC_PK_TYPE_CURVE25519; + wc_curve25519_free(&x25519Key); + } + } + #endif + #ifdef HAVE_CURVE448 + if (keyAlgo == WC_PK_TYPE_NONE) { + word32 idx = 0; + curve448_key x448Key; + ret = wc_curve448_init(&x448Key); + if (ret == 0) { + ret = wc_Curve448PrivateKeyDecode(keyBuf, &idx, &x448Key, + keySz); + if (ret == 0) + keyAlgo = WC_PK_TYPE_CURVE448; + wc_curve448_free(&x448Key); + } + } + #endif - WOLFSSL_MSG("wolfSSL_aes_ctr_iv"); + if (keyAlgo != WC_PK_TYPE_NONE) { + ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap); + if (ret == 0) { + XMEMCPY(der->buffer, keyBuf, keySz); + } + } + } + } - if (ctx == NULL || iv == NULL) { - WOLFSSL_MSG("Bad function argument"); - return; +#ifndef NO_FILESYSTEM + /* done with keyFile buffer */ + if (keyFile && keyBuf) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); } +#endif - if (doset) - (void)wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ - else - XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); -} +#ifndef SINGLE_THREADED + if (ret == 0 && !ctx->staticKELockInit) { + ret = wc_InitMutex(&ctx->staticKELock); + if (ret == 0) { + ctx->staticKELockInit = 1; + } + } +#endif + if (ret == 0 + #ifndef SINGLE_THREADED + && (ret = wc_LockMutex(&ctx->staticKELock)) == 0 + #endif + ) { + switch (keyAlgo) { + #ifndef NO_DH + case WC_PK_TYPE_DH: + FreeDer(&staticKE->dhKey); + staticKE->dhKey = der; der = NULL; + break; + #endif + #ifdef HAVE_ECC + case WC_PK_TYPE_ECDH: + FreeDer(&staticKE->ecKey); + staticKE->ecKey = der; der = NULL; + break; + #endif + #ifdef HAVE_CURVE25519 + case WC_PK_TYPE_CURVE25519: + FreeDer(&staticKE->x25519Key); + staticKE->x25519Key = der; der = NULL; + break; + #endif + #ifdef HAVE_CURVE448 + case WC_PK_TYPE_CURVE448: + FreeDer(&staticKE->x448Key); + staticKE->x448Key = der; der = NULL; + break; + #endif + default: + /* not supported */ + ret = NOT_COMPILED_IN; + break; + } -#endif /* NO_AES */ + #ifndef SINGLE_THREADED + wc_UnLockMutex(&ctx->staticKELock); + #endif + } -#endif /* OPENSSL_EXTRA */ + if (ret != 0) { + FreeDer(&der); + } -/******************************************************************************* - * END OF EVP_CIPHER API - ******************************************************************************/ + (void)ctx; /* not used for single threaded */ -#ifndef NO_CERTS + WOLFSSL_LEAVE("SetStaticEphemeralKey", ret); -#define WOLFSSL_X509_STORE_INCLUDED -#include + return ret; +} -/******************************************************************************* - * START OF PKCS7 APIs - ******************************************************************************/ -#ifdef HAVE_PKCS7 +int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const char* key, unsigned int keySz, int format) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + return SetStaticEphemeralKey(ctx, &ctx->staticKE, keyAlgo, + key, keySz, format, ctx->heap); +} +int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const char* key, unsigned int keySz, int format) +{ + if (ssl == NULL || ssl->ctx == NULL) { + return BAD_FUNC_ARG; + } + return SetStaticEphemeralKey(ssl->ctx, &ssl->staticKE, keyAlgo, + key, keySz, format, ssl->heap); +} -#ifdef OPENSSL_ALL -PKCS7* wolfSSL_PKCS7_new(void) +static int GetStaticEphemeralKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + int keyAlgo, const unsigned char** key, unsigned int* keySz) { - WOLFSSL_PKCS7* pkcs7; int ret = 0; + DerBuffer* der = NULL; - pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(WOLFSSL_PKCS7), NULL, - DYNAMIC_TYPE_PKCS7); - if (pkcs7 != NULL) { - XMEMSET(pkcs7, 0, sizeof(WOLFSSL_PKCS7)); - ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID); + if (key) *key = NULL; + if (keySz) *keySz = 0; + +#ifndef SINGLE_THREADED + if (ctx->staticKELockInit && + (ret = wc_LockMutex(&ctx->staticKELock)) != 0) { + return ret; + } +#endif + + switch (keyAlgo) { + #ifndef NO_DH + case WC_PK_TYPE_DH: + if (ssl != NULL) + der = ssl->staticKE.dhKey; + if (der == NULL) + der = ctx->staticKE.dhKey; + break; + #endif + #ifdef HAVE_ECC + case WC_PK_TYPE_ECDH: + if (ssl != NULL) + der = ssl->staticKE.ecKey; + if (der == NULL) + der = ctx->staticKE.ecKey; + break; + #endif + #ifdef HAVE_CURVE25519 + case WC_PK_TYPE_CURVE25519: + if (ssl != NULL) + der = ssl->staticKE.x25519Key; + if (der == NULL) + der = ctx->staticKE.x25519Key; + break; + #endif + #ifdef HAVE_CURVE448 + case WC_PK_TYPE_CURVE448: + if (ssl != NULL) + der = ssl->staticKE.x448Key; + if (der == NULL) + der = ctx->staticKE.x448Key; + break; + #endif + default: + /* not supported */ + ret = NOT_COMPILED_IN; + break; } - if (ret != 0 && pkcs7 != NULL) { - XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7); - pkcs7 = NULL; + if (der) { + if (key) + *key = der->buffer; + if (keySz) + *keySz = der->length; } - return (PKCS7*)pkcs7; +#ifndef SINGLE_THREADED + wc_UnLockMutex(&ctx->staticKELock); +#endif + + return ret; } -/****************************************************************************** -* wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data -* -* RETURNS: -* returns pointer to the PKCS7 structure on success, otherwise returns NULL -*/ -PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void) +/* returns pointer to currently loaded static ephemeral as ASN.1 */ +/* this can be converted to PEM using wc_DerToPem */ +int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo, + const unsigned char** key, unsigned int* keySz) { - byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02}; - PKCS7* pkcs7 = NULL; - - if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL) - return NULL; - pkcs7->contentOID = SIGNED_DATA; - if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) { - if (pkcs7) { - wolfSSL_PKCS7_free(pkcs7); - return NULL; - } + if (ctx == NULL) { + return BAD_FUNC_ARG; } - return pkcs7; -} -void wolfSSL_PKCS7_free(PKCS7* pkcs7) + return GetStaticEphemeralKey(ctx, NULL, keyAlgo, key, keySz); +} +int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo, + const unsigned char** key, unsigned int* keySz) { - WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; - - if (p7 != NULL) { - if (p7->data != NULL) - XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); - wc_PKCS7_Free(&p7->pkcs7); - if (p7->certs) - wolfSSL_sk_pop_free(p7->certs, NULL); - XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7); + if (ssl == NULL || ssl->ctx == NULL) { + return BAD_FUNC_ARG; } + + return GetStaticEphemeralKey(ssl->ctx, ssl, keyAlgo, key, keySz); } -void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7) +#endif /* WOLFSSL_STATIC_EPHEMERAL */ + +#if defined(OPENSSL_EXTRA) +/* wolfSSL_THREADID_current is provided as a compat API with + * CRYPTO_THREADID_current to register current thread id into given id object. + * However, CRYPTO_THREADID_current API has been deprecated and no longer + * exists in the OpenSSL 1.0.0 or later.This API only works as a stub + * like as existing wolfSSL_THREADID_set_numeric. + */ +void wolfSSL_THREADID_current(WOLFSSL_CRYPTO_THREADID* id) { - wolfSSL_PKCS7_free(p7); + (void)id; return; } +/* wolfSSL_THREADID_hash is provided as a compatible API with + * CRYPTO_THREADID_hash which returns a hash value calculated from the + * specified thread id. However, CRYPTO_THREADID_hash API has been + * deprecated and no longer exists in the OpenSSL 1.0.0 or later. + * This API only works as a stub to returns 0. This behavior is + * equivalent to the latest OpenSSL CRYPTO_THREADID_hash. + */ +unsigned long wolfSSL_THREADID_hash(const WOLFSSL_CRYPTO_THREADID* id) +{ + (void)id; + return 0UL; +} +/* wolfSSL_set_ecdh_auto is provided as compatible API with + * SSL_set_ecdh_auto to enable auto ecdh curve selection functionality. + * Since this functionality is enabled by default in wolfSSL, + * this API exists as a stub. + */ +int wolfSSL_set_ecdh_auto(WOLFSSL* ssl, int onoff) +{ + (void)ssl; + (void)onoff; + return WOLFSSL_SUCCESS; +} +/* wolfSSL_CTX_set_ecdh_auto is provided as compatible API with + * SSL_CTX_set_ecdh_auto to enable auto ecdh curve selection functionality. + * Since this functionality is enabled by default in wolfSSL, + * this API exists as a stub. + */ +int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff) +{ + (void)ctx; + (void)onoff; + return WOLFSSL_SUCCESS; +} /** - * Convert DER/ASN.1 encoded signedData structure to internal PKCS7 - * structure. Note, does not support detached content. - * - * p7 - pointer to set to address of newly created PKCS7 structure on return - * in - pointer to pointer of DER/ASN.1 data - * len - length of input data, bytes - * - * Returns newly allocated and populated PKCS7 structure or NULL on error. + * set security level (wolfSSL doesn't support security level) + * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @param level security level */ -PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) +void wolfSSL_CTX_set_security_level(WOLFSSL_CTX* ctx, int level) { - return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0); + WOLFSSL_ENTER("wolfSSL_CTX_set_security_level"); + (void)ctx; + (void)level; } - -/* This internal function is only decoding and setting up the PKCS7 struct. It -* does not verify the PKCS7 signature. -* -* RETURNS: -* returns pointer to a PKCS7 structure on success, otherwise returns NULL -*/ -static PKCS7* wolfSSL_d2i_PKCS7_only(PKCS7** p7, const unsigned char** in, - int len, byte* content, word32 contentSz) +/** + * get security level (wolfSSL doesn't support security level) + * @param ctx a pointer to WOLFSSL_EVP_PKEY_CTX structure + * @return always 0(level 0) + */ +int wolfSSL_CTX_get_security_level(const WOLFSSL_CTX* ctx) { - WOLFSSL_PKCS7* pkcs7 = NULL; - - WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex"); - - if (in == NULL || *in == NULL || len < 0) - return NULL; - - if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) - return NULL; - - pkcs7->len = len; - pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); - if (pkcs7->data == NULL) { - wolfSSL_PKCS7_free((PKCS7*)pkcs7); - return NULL; - } - XMEMCPY(pkcs7->data, *in, pkcs7->len); + WOLFSSL_ENTER("wolfSSL_CTX_get_security_level"); + (void)ctx; + return 0; +} - if (content != NULL) { - pkcs7->pkcs7.content = content; - pkcs7->pkcs7.contentSz = contentSz; +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) +/* + * This API accepts a user callback which puts key-log records into + * a KEY LOGFILE. The callback is stored into a CTX and propagated to + * each SSL object on its creation timing. + */ +void wolfSSL_CTX_set_keylog_callback(WOLFSSL_CTX* ctx, + wolfSSL_CTX_keylog_cb_func cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_keylog_callback"); + /* stores the callback into WOLFSSL_CTX */ + if (ctx != NULL) { + ctx->keyLogCb = cb; } - - if (p7 != NULL) - *p7 = (PKCS7*)pkcs7; - *in += pkcs7->len; - return (PKCS7*)pkcs7; } - - -/***************************************************************************** -* wolfSSL_d2i_PKCS7_ex - Converts the given unsigned char buffer of size len -* into a PKCS7 object. Optionally, accepts a byte buffer of content which -* is stored as the PKCS7 object's content, to support detached signatures. -* @param content The content which is signed, in case the signature is -* detached. Ignored if NULL. -* @param contentSz The size of the passed in content. -* -* RETURNS: -* returns pointer to a PKCS7 structure on success, otherwise returns NULL -*/ -PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, int len, - byte* content, word32 contentSz) +wolfSSL_CTX_keylog_cb_func wolfSSL_CTX_get_keylog_callback( + const WOLFSSL_CTX* ctx) { - WOLFSSL_PKCS7* pkcs7 = NULL; + WOLFSSL_ENTER("wolfSSL_CTX_get_keylog_callback"); + if (ctx != NULL) + return ctx->keyLogCb; + else + return NULL; +} +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ - WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex"); +#endif /* OPENSSL_EXTRA */ - if (in == NULL || *in == NULL || len < 0) - return NULL; +#ifndef NO_CERTS +#define WOLFSSL_X509_INCLUDED +#include "src/x509.c" +#endif - pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_d2i_PKCS7_only(p7, in, len, content, - contentSz); - if (pkcs7 != NULL) { - if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len) - != 0) { - WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed"); - wolfSSL_PKCS7_free((PKCS7*)pkcs7); - if (p7 != NULL) { - *p7 = NULL; - } - return NULL; - } - } +/******************************************************************************* + * START OF standard C library wrapping APIs + ******************************************************************************/ +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ + (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH))) +#ifndef NO_WOLFSSL_STUB +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("CRYPTO_set_mem_ex_functions"); - return (PKCS7*)pkcs7; + return WOLFSSL_FAILURE; } +#endif +#endif +#if defined(OPENSSL_EXTRA) /** - * This API was added as a helper function for libest. It - * extracts a stack of certificates from the pkcs7 object. - * @param pkcs7 PKCS7 parameter object - * @return WOLFSSL_STACK_OF(WOLFSSL_X509)* + * free allocated memory resource + * @param str a pointer to resource to be freed + * @param file dummy argument + * @param line dummy argument */ -WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7) +void wolfSSL_CRYPTO_free(void *str, const char *file, int line) { - int i; - WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; - WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL; - - WOLFSSL_ENTER("wolfSSL_PKCS7_to_stack"); - - if (!p7) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - - if (p7->certs) - return p7->certs; - - for (i = 0; i < MAX_PKCS7_CERTS && p7->pkcs7.cert[i]; i++) { - WOLFSSL_X509* x509 = wolfSSL_X509_d2i_ex(NULL, p7->pkcs7.cert[i], - p7->pkcs7.certSz[i], pkcs7->heap); - if (!ret) - ret = wolfSSL_sk_X509_new_null(); - if (x509) { - if (wolfSSL_sk_X509_push(ret, x509) != WOLFSSL_SUCCESS) { - wolfSSL_X509_free(x509); - WOLFSSL_MSG("wolfSSL_sk_X509_push error"); - goto error; - } - } - else { - WOLFSSL_MSG("wolfSSL_X509_d2i error"); - goto error; - } - } - - /* Save stack to free later */ - if (p7->certs) - wolfSSL_sk_pop_free(p7->certs, NULL); - p7->certs = ret; - - return ret; -error: - if (ret) { - wolfSSL_sk_pop_free(ret, NULL); - } - return NULL; + (void)file; + (void)line; + XFREE(str, 0, DYNAMIC_TYPE_TMP_BUFFER); } - /** - * Return stack of signers contained in PKCS7 cert. - * Notes: - * - Currently only PKCS#7 messages with a single signer cert is supported. - * - Returned WOLFSSL_STACK must be freed by caller. - * - * pkcs7 - PKCS7 struct to retrieve signer certs from. - * certs - currently unused - * flags - flags to control function behavior. - * - * Return WOLFSSL_STACK of signers on success, NULL on error. + * allocate memory with size of num + * @param num size of memory allocation to be malloced + * @param file dummy argument + * @param line dummy argument + * @return a pointer to allocated memory on succssesful, otherwise NULL */ -WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs, - int flags) +void *wolfSSL_CRYPTO_malloc(size_t num, const char *file, int line) { - WOLFSSL_X509* x509 = NULL; - WOLFSSL_STACK* signers = NULL; - WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + (void)file; + (void)line; + return XMALLOC(num, 0, DYNAMIC_TYPE_TMP_BUFFER); +} - if (p7 == NULL) - return NULL; +#endif - /* Only PKCS#7 messages with a single cert that is the verifying certificate - * is supported. - */ - if (flags & PKCS7_NOINTERN) { - WOLFSSL_MSG("PKCS7_NOINTERN flag not supported"); - return NULL; - } +/******************************************************************************* + * END OF standard C library wrapping APIs + ******************************************************************************/ - signers = wolfSSL_sk_X509_new_null(); - if (signers == NULL) - return NULL; +/******************************************************************************* + * START OF EX_DATA APIs + ******************************************************************************/ +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ + (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH))) +void wolfSSL_CRYPTO_cleanup_all_ex_data(void){ + WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data"); +} +#endif - if (wolfSSL_d2i_X509(&x509, (const byte**)&p7->pkcs7.singleCert, - p7->pkcs7.singleCertSz) == NULL) { - wolfSSL_sk_X509_pop_free(signers, NULL); - return NULL; +#ifdef HAVE_EX_DATA +void* wolfSSL_CRYPTO_get_ex_data(const WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); +#ifdef MAX_EX_DATA + if(ex_data && idx < MAX_EX_DATA && idx >= 0) { + return ex_data->ex_data[idx]; } +#else + (void)ex_data; + (void)idx; +#endif + return NULL; +} - if (wolfSSL_sk_X509_push(signers, x509) != WOLFSSL_SUCCESS) { - wolfSSL_sk_X509_pop_free(signers, NULL); - return NULL; +int wolfSSL_CRYPTO_set_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data, int idx, + void *data) +{ + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data"); +#ifdef MAX_EX_DATA + if (ex_data && idx < MAX_EX_DATA && idx >= 0) { +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + if (ex_data->ex_data_cleanup_routines[idx]) { + if (ex_data->ex_data[idx]) + ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]); + ex_data->ex_data_cleanup_routines[idx] = NULL; + } +#endif + ex_data->ex_data[idx] = data; + return WOLFSSL_SUCCESS; } - - (void)certs; - - return signers; +#else + (void)ex_data; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; } -#ifndef NO_BIO - -PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7) +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_CRYPTO_set_ex_data_with_cleanup( + WOLFSSL_CRYPTO_EX_DATA* ex_data, + int idx, + void *data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) { - WOLFSSL_PKCS7* pkcs7; - int ret; + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_ex_data_with_cleanup"); + if (ex_data && idx < MAX_EX_DATA && idx >= 0) { + if (ex_data->ex_data_cleanup_routines[idx] && ex_data->ex_data[idx]) + ex_data->ex_data_cleanup_routines[idx](ex_data->ex_data[idx]); + ex_data->ex_data[idx] = data; + ex_data->ex_data_cleanup_routines[idx] = cleanup_routine; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ - WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_bio"); +/** + * Issues unique index for the class specified by class_index. + * Other parameter except class_index are ignored. + * Currently, following class_index are accepted: + * - WOLF_CRYPTO_EX_INDEX_SSL + * - WOLF_CRYPTO_EX_INDEX_SSL_CTX + * - WOLF_CRYPTO_EX_INDEX_X509 + * @param class_index index one of CRYPTO_EX_INDEX_xxx + * @param argp parameters to be saved + * @param argl parameters to be saved + * @param new_func a pointer to WOLFSSL_CRYPTO_EX_new + * @param dup_func a pointer to WOLFSSL_CRYPTO_EX_dup + * @param free_func a pointer to WOLFSSL_CRYPTO_EX_free + * @return index value grater or equal to zero on success, -1 on failure. + */ +int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, + WOLFSSL_CRYPTO_EX_new* new_func, + WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func) +{ + WOLFSSL_ENTER("wolfSSL_CRYPTO_get_ex_new_index"); - if (bio == NULL) - return NULL; + return wolfssl_get_ex_new_index(class_index, argl, argp, new_func, + dup_func, free_func); +} +#endif /* HAVE_EX_DATA */ - if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) - return NULL; +/******************************************************************************* + * END OF EX_DATA APIs + ******************************************************************************/ - pkcs7->len = wolfSSL_BIO_get_len(bio); - pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); - if (pkcs7->data == NULL) { - wolfSSL_PKCS7_free((PKCS7*)pkcs7); - return NULL; - } +/******************************************************************************* + * START OF BUF_MEM API + ******************************************************************************/ - if ((ret = wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len)) <= 0) { - wolfSSL_PKCS7_free((PKCS7*)pkcs7); - return NULL; - } - /* pkcs7->len may change if using b64 for example */ - pkcs7->len = ret; +#if defined(OPENSSL_EXTRA) - if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len) - != 0) { - WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed"); - wolfSSL_PKCS7_free((PKCS7*)pkcs7); - return NULL; +/* Begin functions for openssl/buffer.h */ +WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void) +{ + WOLFSSL_BUF_MEM* buf; + buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL, + DYNAMIC_TYPE_OPENSSL); + if (buf) { + XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM)); } - - if (p7 != NULL) - *p7 = (PKCS7*)pkcs7; - return (PKCS7*)pkcs7; + return buf; } -int wolfSSL_i2d_PKCS7(PKCS7 *p7, unsigned char **out) +/* non-compat API returns length of buffer on success */ +int wolfSSL_BUF_MEM_grow_ex(WOLFSSL_BUF_MEM* buf, size_t len, + char zeroFill) { - byte* output = NULL; - int localBuf = 0; - int len; - WC_RNG rng; - int ret = WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_i2d_PKCS7"); - if (!out || !p7) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } + int len_int = (int)len; + int mx; + char* tmp; - if (!p7->rng) { - if (wc_InitRng(&rng) != 0) { - WOLFSSL_MSG("wc_InitRng error"); - return WOLFSSL_FAILURE; - } - p7->rng = &rng; /* cppcheck-suppress autoVariables - */ + /* verify provided arguments */ + if (buf == NULL || len_int < 0) { + return 0; /* BAD_FUNC_ARG; */ } - if ((len = wc_PKCS7_EncodeSignedData(p7, NULL, 0)) < 0) { - WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error"); - goto cleanup; + /* check to see if fits in existing length */ + if (buf->length > len) { + buf->length = len; + return len_int; } - if (*out == NULL) { - output = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!output) { - WOLFSSL_MSG("malloc error"); - goto cleanup; + /* check to see if fits in max buffer */ + if (buf->max >= len) { + if (buf->data != NULL && zeroFill) { + XMEMSET(&buf->data[buf->length], 0, len - buf->length); } - localBuf = 1; - } - else { - output = *out; - } - - if ((len = wc_PKCS7_EncodeSignedData(p7, output, len)) < 0) { - WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error"); - goto cleanup; + buf->length = len; + return len_int; } - ret = len; -cleanup: - if (p7->rng == &rng) { - wc_FreeRng(&rng); - p7->rng = NULL; - } - if (ret == WOLFSSL_FAILURE && localBuf && output) - XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ret != WOLFSSL_FAILURE) - *out = output; - return ret; -} - -int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7) -{ - byte* output = NULL; - int len; - int ret = WOLFSSL_FAILURE; - WOLFSSL_ENTER("wolfSSL_i2d_PKCS7_bio"); + /* expand size, to handle growth */ + mx = (len_int + 3) / 3 * 4; - if (!bio || !p7) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; + /* use realloc */ + tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + return 0; /* ERR_R_MALLOC_FAILURE; */ } + buf->data = tmp; - if ((len = wolfSSL_i2d_PKCS7(p7, &output)) == WOLFSSL_FAILURE) { - WOLFSSL_MSG("wolfSSL_i2d_PKCS7 error"); - goto cleanup; - } + buf->max = (size_t)mx; + if (zeroFill) + XMEMSET(&buf->data[buf->length], 0, len - buf->length); + buf->length = len; - if (wolfSSL_BIO_write(bio, output, len) <= 0) { - WOLFSSL_MSG("wolfSSL_BIO_write error"); - goto cleanup; - } + return len_int; - ret = WOLFSSL_SUCCESS; -cleanup: - if (output) - XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; } -/** - * Creates and returns a PKCS7 signedData structure. - * - * Inner content type is set to DATA to match OpenSSL behavior. - * - * signer - certificate to sign bundle with - * pkey - private key matching signer - * certs - optional additional set of certificates to include - * in - input data to be signed - * flags - optional set of flags to control sign behavior - * - * PKCS7_BINARY - Do not translate input data to MIME canonical - * format (\r\n line endings), thus preventing corruption of - * binary content. - * PKCS7_TEXT - Prepend MIME headers for text/plain to content. - * PKCS7_DETACHED - Set signature detached, omit content from output bundle. - * PKCS7_STREAM - initialize PKCS7 struct for signing, do not read data. - * - * Flags not currently supported: - * PKCS7_NOCERTS - Do not include the signer cert in the output bundle. - * PKCS7_PARTIAL - Allow for PKCS7_sign() to be only partially set up, - * then signers etc to be added separately before - * calling PKCS7_final(). - * - * Returns valid PKCS7 structure pointer, or NULL if an error occurred. - */ -PKCS7* wolfSSL_PKCS7_sign(WOLFSSL_X509* signer, WOLFSSL_EVP_PKEY* pkey, - WOLFSSL_STACK* certs, WOLFSSL_BIO* in, int flags) +/* returns length of buffer on success */ +int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len) { - int err = 0; - WOLFSSL_PKCS7* p7 = NULL; - WOLFSSL_STACK* cert = certs; + return wolfSSL_BUF_MEM_grow_ex(buf, len, 1); +} - WOLFSSL_ENTER("wolfSSL_PKCS7_sign"); +/* non-compat API returns length of buffer on success */ +int wolfSSL_BUF_MEM_resize(WOLFSSL_BUF_MEM* buf, size_t len) +{ + char* tmp; + int mx; - if (flags & PKCS7_NOCERTS) { - WOLFSSL_MSG("PKCS7_NOCERTS flag not yet supported"); - err = 1; + /* verify provided arguments */ + if (buf == NULL || len == 0 || (int)len <= 0) { + return 0; /* BAD_FUNC_ARG; */ } - if (flags & PKCS7_PARTIAL) { - WOLFSSL_MSG("PKCS7_PARTIAL flag not yet supported"); - err = 1; - } + if (len == buf->length) + return (int)len; - if ((err == 0) && (signer == NULL || signer->derCert == NULL || - signer->derCert->length == 0)) { - WOLFSSL_MSG("Bad function arg, signer is NULL or incomplete"); - err = 1; - } + if (len > buf->length) + return wolfSSL_BUF_MEM_grow_ex(buf, len, 0); - if ((err == 0) && (pkey == NULL || pkey->pkey.ptr == NULL || - pkey->pkey_sz <= 0)) { - WOLFSSL_MSG("Bad function arg, pkey is NULL or incomplete"); - err = 1; - } + /* expand size, to handle growth */ + mx = ((int)len + 3) / 3 * 4; + + /* We want to shrink the internal buffer */ + tmp = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) + return 0; - if ((err == 0) && (in == NULL) && !(flags & PKCS7_STREAM)) { - WOLFSSL_MSG("input data required unless PKCS7_STREAM used"); - err = 1; - } + buf->data = tmp; + buf->length = len; + buf->max = (size_t)mx; - if ((err == 0) && ((p7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)) { - WOLFSSL_MSG("Error allocating new WOLFSSL_PKCS7"); - err = 1; - } + return (int)len; +} - /* load signer certificate */ - if (err == 0) { - if (wc_PKCS7_InitWithCert(&p7->pkcs7, signer->derCert->buffer, - signer->derCert->length) != 0) { - WOLFSSL_MSG("Failed to load signer certificate"); - err = 1; +void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf) +{ + if (buf) { + if (buf->data) { + XFREE(buf->data, NULL, DYNAMIC_TYPE_OPENSSL); + buf->data = NULL; } + buf->max = 0; + buf->length = 0; + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); } +} +/* End Functions for openssl/buffer.h */ - /* set signer private key, data types, defaults */ - if (err == 0) { - p7->pkcs7.privateKey = (byte*)pkey->pkey.ptr; - p7->pkcs7.privateKeySz = pkey->pkey_sz; - p7->pkcs7.contentOID = DATA; /* inner content default is DATA */ - p7->pkcs7.hashOID = SHA256h; /* default to SHA-256 hash type */ - p7->type = SIGNED_DATA; /* PKCS7_final switches on type */ - } - - /* add additional chain certs if provided */ - while (cert && (err == 0)) { - if (cert->data.x509 != NULL && cert->data.x509->derCert != NULL) { - if (wc_PKCS7_AddCertificate(&p7->pkcs7, - cert->data.x509->derCert->buffer, - cert->data.x509->derCert->length) != 0) { - WOLFSSL_MSG("Error in wc_PKCS7_AddCertificate"); - err = 1; - } - } - cert = cert->next; - } +#endif /* OPENSSL_EXTRA */ - if ((err == 0) && (flags & PKCS7_DETACHED)) { - if (wc_PKCS7_SetDetached(&p7->pkcs7, 1) != 0) { - WOLFSSL_MSG("Failed to set signature detached"); - err = 1; - } - } +/******************************************************************************* + * END OF BUF_MEM API + ******************************************************************************/ - if ((err == 0) && (flags & PKCS7_STREAM)) { - /* if streaming, return before finalizing */ - return (PKCS7*)p7; - } +#define WOLFSSL_CONF_INCLUDED +#include - if ((err == 0) && (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1)) { - WOLFSSL_MSG("Error calling wolfSSL_PKCS7_final"); - err = 1; - } +/******************************************************************************* + * START OF RAND API + ******************************************************************************/ - if ((err != 0) && (p7 != NULL)) { - wolfSSL_PKCS7_free((PKCS7*)p7); - p7 = NULL; +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB) +static int wolfSSL_RAND_InitMutex(void) +{ +#ifndef WOLFSSL_MUTEX_INITIALIZER + if (gRandMethodsInit == 0) { + if (wc_InitMutex(&gRandMethodMutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex rand methods"); + return BAD_MUTEX_E; + } + gRandMethodsInit = 1; } - - return (PKCS7*)p7; +#endif + return 0; } - -#ifdef HAVE_SMIME - -#ifndef MAX_MIME_LINE_LEN - #define MAX_MIME_LINE_LEN 1024 #endif -/** - * Copy input BIO to output BIO, but convert all line endings to CRLF (\r\n), - * used by PKCS7_final(). - * - * in - input WOLFSSL_BIO to be converted - * out - output WOLFSSL_BIO to hold copy of in, with line endings adjusted +#ifdef OPENSSL_EXTRA + +/* Checks if the global RNG has been created. If not then one is created. * - * Return 0 on success, negative on error + * Returns WOLFSSL_SUCCESS when no error is encountered. */ -static int wolfSSL_BIO_to_MIME_crlf(WOLFSSL_BIO* in, WOLFSSL_BIO* out) +int wolfSSL_RAND_Init(void) { - int ret = 0; - int lineLen = 0; - word32 canonLineLen = 0; - char* canonLine = NULL; -#ifdef WOLFSSL_SMALL_STACK - char* line = NULL; -#else - char line[MAX_MIME_LINE_LEN]; -#endif - - if (in == NULL || out == NULL) { - return BAD_FUNC_ARG; - } - -#ifdef WOLFSSL_SMALL_STACK - line = (char*)XMALLOC(MAX_MIME_LINE_LEN, in->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (line == NULL) { - return MEMORY_E; - } -#endif - XMEMSET(line, 0, MAX_MIME_LINE_LEN); - - while ((lineLen = wolfSSL_BIO_gets(in, line, MAX_MIME_LINE_LEN)) > 0) { - - if (line[lineLen - 1] == '\r' || line[lineLen - 1] == '\n') { - canonLineLen = (word32)lineLen; - if ((canonLine = wc_MIME_single_canonicalize( - line, &canonLineLen)) == NULL) { - ret = -1; - break; - } - - /* remove trailing null */ - if (canonLineLen >= 1 && canonLine[canonLineLen-1] == '\0') { - canonLineLen--; - } - - if (wolfSSL_BIO_write(out, canonLine, (int)canonLineLen) < 0) { - ret = -1; - break; + int ret = WOLFSSL_FAILURE; +#ifdef HAVE_GLOBAL_RNG + if (wc_LockMutex(&globalRNGMutex) == 0) { + if (initGlobalRNG == 0) { + ret = wc_InitRng(&globalRNG); + if (ret == 0) { + initGlobalRNG = 1; + ret = WOLFSSL_SUCCESS; } - XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); - canonLine = NULL; } else { - /* no line ending in current line, write direct to out */ - if (wolfSSL_BIO_write(out, line, lineLen) < 0) { - ret = -1; - break; - } + /* GlobalRNG is already initialized */ + ret = WOLFSSL_SUCCESS; } - } - if (canonLine != NULL) { - XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); + wc_UnLockMutex(&globalRNGMutex); } -#ifdef WOLFSSL_SMALL_STACK - XFREE(line, in->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ret; } -#endif /* HAVE_SMIME */ - -/* Used by both PKCS7_final() and PKCS7_verify() */ -static const char contTypeText[] = "Content-Type: text/plain\r\n\r\n"; -/** - * Finalize PKCS7 structure, currently supports signedData only. - * - * Does not generate final bundle (ie: signedData), but finalizes - * the PKCS7 structure in preparation for a output function to be called next. - * - * pkcs7 - initialized PKCS7 structure, populated with signer, etc - * in - input data - * flags - flags to control PKCS7 behavior. Other flags except those noted - * below are ignored: - * - * PKCS7_BINARY - Do not translate input data to MIME canonical - * format (\r\n line endings), thus preventing corruption of - * binary content. - * PKCS7_TEXT - Prepend MIME headers for text/plain to content. - * - * Returns 1 on success, 0 on error - */ -int wolfSSL_PKCS7_final(PKCS7* pkcs7, WOLFSSL_BIO* in, int flags) +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_RAND_seed(const void* seed, int len) { - int ret = 1; - int memSz = 0; - unsigned char* mem = NULL; - WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; - WOLFSSL_BIO* data = NULL; - - WOLFSSL_ENTER("wolfSSL_PKCS7_final"); - - if (p7 == NULL || in == NULL) { - WOLFSSL_MSG("Bad input args to PKCS7_final"); - ret = 0; - } - - if (ret == 1) { - if ((data = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())) == NULL) { - WOLFSSL_MSG("Error in wolfSSL_BIO_new"); - ret = 0; +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->seed) { + int ret = gRandMethods->seed(seed, len); + wc_UnLockMutex(&gRandMethodMutex); + return ret; } + wc_UnLockMutex(&gRandMethodMutex); } +#else + (void)seed; + (void)len; +#endif - /* prepend Content-Type header if PKCS7_TEXT */ - if ((ret == 1) && (flags & PKCS7_TEXT)) { - if (wolfSSL_BIO_write(data, contTypeText, - (int)XSTR_SIZEOF(contTypeText)) < 0) { - WOLFSSL_MSG("Error prepending Content-Type header"); - ret = 0; - } - } + /* Make sure global shared RNG (globalRNG) is initialized */ + return wolfSSL_RAND_Init(); +} - /* convert line endings to CRLF if !PKCS7_BINARY */ - if (ret == 1) { - if (flags & PKCS7_BINARY) { - /* no CRLF conversion, direct copy content */ - if ((memSz = wolfSSL_BIO_get_len(in)) <= 0) { - ret = 0; - } - if (ret == 1) { - mem = (unsigned char*)XMALLOC(memSz, in->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (mem == NULL) { - WOLFSSL_MSG("Failed to allocate memory for input data"); - ret = 0; - } - } +/* Returns the path for reading seed data from. + * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd + * + * Note uses stdlib by default unless XGETENV macro is overwritten + * + * fname buffer to hold path + * len length of fname buffer + * + * Returns a pointer to fname on success and NULL on failure + */ +const char* wolfSSL_RAND_file_name(char* fname, unsigned long len) +{ +#if !defined(NO_FILESYSTEM) && defined(XGETENV) + char* rt; - if (ret == 1) { - if (wolfSSL_BIO_read(in, mem, memSz) != memSz) { - WOLFSSL_MSG("Error reading from input BIO"); - ret = 0; - } - else if (wolfSSL_BIO_write(data, mem, memSz) < 0) { - ret = 0; - } - } + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); - if (mem != NULL) { - XFREE(mem, in->heap, DYNAMIC_TYPE_TMP_BUFFER); - } - } - else { - #ifdef HAVE_SMIME - /* convert content line endings to CRLF */ - if (wolfSSL_BIO_to_MIME_crlf(in, data) != 0) { - WOLFSSL_MSG("Error converting line endings to CRLF"); - ret = 0; - } - else { - p7->pkcs7.contentCRLF = 1; - } - #else - WOLFSSL_MSG("Without PKCS7_BINARY requires wolfSSL to be built " - "with HAVE_SMIME"); - ret = 0; - #endif - } + if (fname == NULL) { + return NULL; } - if ((ret == 1) && ((memSz = wolfSSL_BIO_get_mem_data(data, &mem)) < 0)) { - WOLFSSL_MSG("Error in wolfSSL_BIO_get_mem_data"); - ret = 0; - } + XMEMSET(fname, 0, len); - if (ret == 1) { - if (p7->data != NULL) { - XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); - } - p7->data = (byte*)XMALLOC(memSz, NULL, DYNAMIC_TYPE_PKCS7); - if (p7->data == NULL) { - ret = 0; + if ((rt = XGETENV("RANDFILE")) != NULL) { + if (len > XSTRLEN(rt)) { + XMEMCPY(fname, rt, XSTRLEN(rt)); } else { - XMEMCPY(p7->data, mem, memSz); - p7->len = memSz; + WOLFSSL_MSG("RANDFILE too large for buffer"); + rt = NULL; } } - if (ret == 1) { - p7->pkcs7.content = p7->data; - p7->pkcs7.contentSz = p7->len; - } - - if (data != NULL) { - wolfSSL_BIO_free(data); - } - - return ret; -} - -int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs, - WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags) -{ - int i, ret = 0; - unsigned char* mem = NULL; - int memSz = 0; - WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; - int contTypeLen; - WOLFSSL_X509* signer = NULL; - WOLFSSL_STACK* signers = NULL; - - WOLFSSL_ENTER("wolfSSL_PKCS7_verify"); - - if (pkcs7 == NULL) - return WOLFSSL_FAILURE; - - if (in != NULL) { - if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0) - return WOLFSSL_FAILURE; - - p7->pkcs7.content = mem; - p7->pkcs7.contentSz = memSz; - } - - /* certs is the list of certificates to find the cert with issuer/serial. */ - (void)certs; - /* store is the certificate store to use to verify signer certificate - * associated with the signers. - */ - (void)store; - - ret = wc_PKCS7_VerifySignedData(&p7->pkcs7, p7->data, p7->len); - if (ret != 0) - return WOLFSSL_FAILURE; - - if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) { - /* Verify signer certificates */ - if (store == NULL || store->cm == NULL) { - WOLFSSL_MSG("No store or store certs, but PKCS7_NOVERIFY not set"); - return WOLFSSL_FAILURE; - } + /* $RANDFILE was not set or is too large, check $HOME */ + if (rt == NULL) { + const char ap[] = "/.rnd"; - signers = wolfSSL_PKCS7_get0_signers(pkcs7, certs, flags); - if (signers == NULL) { - WOLFSSL_MSG("No signers found to verify"); - return WOLFSSL_FAILURE; - } - for (i = 0; i < wolfSSL_sk_X509_num(signers); i++) { - signer = wolfSSL_sk_X509_value(signers, i); + WOLFSSL_MSG("Environment variable RANDFILE not set"); - if (wolfSSL_CertManagerVerifyBuffer(store->cm, - signer->derCert->buffer, - signer->derCert->length, - WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to verify signer certificate"); - wolfSSL_sk_X509_pop_free(signers, NULL); - return WOLFSSL_FAILURE; + if ((rt = XGETENV("HOME")) == NULL) { + #ifdef XALTHOMEVARNAME + if ((rt = XGETENV(XALTHOMEVARNAME)) == NULL) { + WOLFSSL_MSG("Environment variable HOME and " XALTHOMEVARNAME + " not set"); + return NULL; } + #else + WOLFSSL_MSG("Environment variable HOME not set"); + return NULL; + #endif } - wolfSSL_sk_X509_pop_free(signers, NULL); - } - if (flags & PKCS7_TEXT) { - /* strip MIME header for text/plain, otherwise error */ - contTypeLen = XSTR_SIZEOF(contTypeText); - if ((p7->pkcs7.contentSz < (word32)contTypeLen) || - (XMEMCMP(p7->pkcs7.content, contTypeText, contTypeLen) != 0)) { - WOLFSSL_MSG("Error PKCS7 Content-Type not found with PKCS7_TEXT"); - return WOLFSSL_FAILURE; + if (len > XSTRLEN(rt) + XSTRLEN(ap)) { + fname[0] = '\0'; + XSTRNCAT(fname, rt, len); + XSTRNCAT(fname, ap, len - XSTRLEN(rt)); + return fname; + } + else { + WOLFSSL_MSG("Path too large for buffer"); + return NULL; } - p7->pkcs7.content += contTypeLen; - p7->pkcs7.contentSz -= contTypeLen; - } - - if (out != NULL) { - wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz); } - WOLFSSL_LEAVE("wolfSSL_PKCS7_verify", WOLFSSL_SUCCESS); - - return WOLFSSL_SUCCESS; + return fname; +#else + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + WOLFSSL_MSG("RAND_file_name requires filesystem and getenv support, " + "not compiled in"); + (void)fname; + (void)len; + return NULL; +#endif } -/** - * This API was added as a helper function for libest. It - * encodes a stack of certificates to pkcs7 format. - * @param pkcs7 PKCS7 parameter object - * @param certs WOLFSSL_STACK_OF(WOLFSSL_X509)* - * @param out Output bio - * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure - */ -int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs, - WOLFSSL_BIO* out) -{ - int ret; - WOLFSSL_PKCS7* p7; - WOLFSSL_ENTER("wolfSSL_PKCS7_encode_certs"); - - if (!pkcs7 || !certs || !out) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - p7 = (WOLFSSL_PKCS7*)pkcs7; +/* Writes 1024 bytes from the RNG to the given file name. + * + * fname name of file to write to + * + * Returns the number of bytes written + */ +int wolfSSL_RAND_write_file(const char* fname) +{ + int bytes = 0; - /* take ownership of certs */ - p7->certs = certs; - /* TODO: takes ownership even on failure below but not on above failure. */ + WOLFSSL_ENTER("wolfSSL_RAND_write_file"); - if (pkcs7->certList) { - WOLFSSL_MSG("wolfSSL_PKCS7_encode_certs called multiple times on same " - "struct"); + if (fname == NULL) { return WOLFSSL_FAILURE; } - if (certs) { - /* Save some of the values */ - int hashOID = pkcs7->hashOID; - byte version = pkcs7->version; - - if (!certs->data.x509 || !certs->data.x509->derCert) { - WOLFSSL_MSG("Missing cert"); +#ifndef NO_FILESYSTEM + { + #ifndef WOLFSSL_SMALL_STACK + unsigned char buf[1024]; + #else + unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("malloc failed"); return WOLFSSL_FAILURE; } + #endif + bytes = 1024; /* default size of buf */ - if (wc_PKCS7_InitWithCert(pkcs7, certs->data.x509->derCert->buffer, - certs->data.x509->derCert->length) != 0) { - WOLFSSL_MSG("wc_PKCS7_InitWithCert error"); - return WOLFSSL_FAILURE; + if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No RNG to use"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; } - certs = certs->next; - - pkcs7->hashOID = hashOID; - pkcs7->version = version; - } - /* Add the certs to the PKCS7 struct */ - while (certs) { - if (!certs->data.x509 || !certs->data.x509->derCert) { - WOLFSSL_MSG("Missing cert"); - return WOLFSSL_FAILURE; - } - if (wc_PKCS7_AddCertificate(pkcs7, certs->data.x509->derCert->buffer, - certs->data.x509->derCert->length) != 0) { - WOLFSSL_MSG("wc_PKCS7_AddCertificate error"); - return WOLFSSL_FAILURE; + if (wc_RNG_GenerateBlock(&globalRNG, buf, (word32)bytes) != 0) { + WOLFSSL_MSG("Error generating random buffer"); + bytes = 0; } - certs = certs->next; - } + else { + XFILE f; - if (wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID) != 0) { - WOLFSSL_MSG("wc_PKCS7_SetSignerIdentifierType error"); - return WOLFSSL_FAILURE; - } + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("wolfSSL_RAND_write_file buf", buf, bytes); + #endif - ret = wolfSSL_i2d_PKCS7_bio(out, pkcs7); + f = XFOPEN(fname, "wb"); + if (f == XBADFILE) { + WOLFSSL_MSG("Error opening the file"); + bytes = 0; + } + else { + size_t bytes_written = XFWRITE(buf, 1, (size_t)bytes, f); + bytes = (int)bytes_written; + XFCLOSE(f); + } + } + ForceZero(buf, (word32)bytes); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #elif defined(WOLFSSL_CHECK_MEM_ZERO) + wc_MemZero_Check(buf, sizeof(buf)); + #endif + } +#endif - return ret; + return bytes; } -/****************************************************************************** -* wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO -* -* RETURNS: -* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE -*/ -int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7) -{ -#ifdef WOLFSSL_SMALL_STACK - byte* outputHead; - byte* outputFoot; -#else - byte outputHead[2048]; - byte outputFoot[2048]; -#endif - word32 outputHeadSz = 2048; - word32 outputFootSz = 2048; - word32 outputSz = 0; - byte* output = NULL; - byte* pem = NULL; - int pemSz = -1; - enum wc_HashType hashType; - byte hashBuf[WC_MAX_DIGEST_SIZE]; - word32 hashSz = -1; - - WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7"); - - if (bio == NULL || p7 == NULL) - return WOLFSSL_FAILURE; - -#ifdef WOLFSSL_SMALL_STACK - outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (outputHead == NULL) - return MEMORY_E; - - outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (outputFoot == NULL) - goto error; +#ifndef FREERTOS_TCP +/* These constant values are protocol values made by egd */ +#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && \ + !defined(HAVE_FIPS) && defined(HAVE_HASHDRBG) && !defined(NETOS) && \ + defined(HAVE_SYS_UN_H) + #define WOLFSSL_EGD_NBLOCK 0x01 + #include #endif - XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE); - XMEMSET(outputHead, 0, outputHeadSz); - XMEMSET(outputFoot, 0, outputFootSz); - - hashType = wc_OidGetHash(p7->hashOID); - hashSz = wc_HashGetDigestSize(hashType); - if (hashSz > WC_MAX_DIGEST_SIZE) - goto error; - - /* only SIGNED_DATA is supported */ - switch (p7->contentOID) { - case SIGNED_DATA: - break; - default: - WOLFSSL_MSG("Unknown PKCS#7 Type"); - goto error; - }; - - if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz, - outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0) - goto error; - - outputSz = outputHeadSz + p7->contentSz + outputFootSz; - output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - - if (!output) - goto error; - - XMEMSET(output, 0, outputSz); - outputSz = 0; - XMEMCPY(&output[outputSz], outputHead, outputHeadSz); - outputSz += outputHeadSz; - XMEMCPY(&output[outputSz], p7->content, p7->contentSz); - outputSz += p7->contentSz; - XMEMCPY(&output[outputSz], outputFoot, outputFootSz); - outputSz += outputFootSz; - - /* get PEM size */ - pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE); - if (pemSz < 0) - goto error; - - pemSz++; /* for '\0'*/ - - /* create PEM buffer and convert from DER to PEM*/ - if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER)) - == NULL) - goto error; - - XMEMSET(pem, 0, pemSz); - - if (wc_DerToPemEx(output, outputSz, pem, pemSz, NULL, CERT_TYPE) < 0) { - goto error; +/* This collects entropy from the path nm and seeds the global PRNG with it. + * + * nm is the file path to the egd server + * + * Returns the number of bytes read. + */ +int wolfSSL_RAND_egd(const char* nm) +{ +#ifdef WOLFSSL_EGD_NBLOCK + struct sockaddr_un rem; + int fd; + int ret = WOLFSSL_SUCCESS; + word32 bytes = 0; + word32 idx = 0; +#ifndef WOLFSSL_SMALL_STACK + unsigned char buf[256]; +#else + unsigned char* buf; + buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("Not enough memory"); + return WOLFSSL_FATAL_ERROR; } - if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) { - XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return WOLFSSL_SUCCESS; - } -error: -#ifdef WOLFSSL_SMALL_STACK - if (outputHead) { - XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - } - if (outputFoot) { - XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - } -#endif - if (output) { - XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - } - if (pem) { - XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + XMEMSET(&rem, 0, sizeof(struct sockaddr_un)); + if (nm == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return WOLFSSL_FATAL_ERROR; } - return WOLFSSL_FAILURE; -} -#ifdef HAVE_SMIME -/***************************************************************************** -* wolfSSL_SMIME_read_PKCS7 - Reads the given S/MIME message and parses it into -* a PKCS7 object. In case of a multipart message, stores the signed data in -* bcont. -* -* RETURNS: -* returns pointer to a PKCS7 structure on success, otherwise returns NULL -*/ -PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, - WOLFSSL_BIO** bcont) -{ - MimeHdr* allHdrs = NULL; - MimeHdr* curHdr = NULL; - MimeParam* curParam = NULL; - int inLen = 0; - byte* bcontMem = NULL; - int bcontMemSz = 0; - int sectionLen = 0; - int ret = -1; - char* section = NULL; - char* canonLine = NULL; - char* canonSection = NULL; - PKCS7* pkcs7 = NULL; - word32 outLen = 0; - word32 canonLineLen = 0; - byte* out = NULL; - byte* outHead = NULL; - - int canonPos = 0; - int lineLen = 0; - int remainLen = 0; - byte isEnd = 0; - size_t canonSize = 0; - size_t boundLen = 0; - char* boundary = NULL; - - static const char kContType[] = "Content-Type"; - static const char kCTE[] = "Content-Transfer-Encoding"; - static const char kMultSigned[] = "multipart/signed"; - static const char kAppPkcsSign[] = "application/pkcs7-signature"; - static const char kAppXPkcsSign[] = "application/x-pkcs7-signature"; - static const char kAppPkcs7Mime[] = "application/pkcs7-mime"; - static const char kAppXPkcs7Mime[] = "application/x-pkcs7-mime"; - - WOLFSSL_ENTER("wolfSSL_SMIME_read_PKCS7"); - - if (in == NULL || bcont == NULL) { - goto error; - } - inLen = wolfSSL_BIO_get_len(in); - if (inLen <= 0) { - goto error; - } - remainLen = wolfSSL_BIO_get_len(in); - if (remainLen <= 0) { - goto error; - } - - section = (char*)XMALLOC(remainLen+1, NULL, DYNAMIC_TYPE_PKCS7); - if (section == NULL) { - goto error; - } - lineLen = wolfSSL_BIO_gets(in, section, remainLen); - if (lineLen <= 0) { - goto error; - } - while (isEnd == 0 && remainLen > 0) { - sectionLen += lineLen; - remainLen -= lineLen; - lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], remainLen); - if (lineLen <= 0) { - goto error; - } - /* Line with just newline signals end of headers. */ - if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen], - "\r\n", 2)) || - (lineLen==1 && (section[sectionLen] == '\r' || - section[sectionLen] == '\n'))) { - isEnd = 1; - } + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + WOLFSSL_MSG("Error creating socket"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return WOLFSSL_FATAL_ERROR; } - section[sectionLen] = '\0'; - ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs); - if (ret < 0) { - WOLFSSL_MSG("Parsing MIME headers failed."); - goto error; - } - isEnd = 0; - section[0] = '\0'; - sectionLen = 0; - - curHdr = wc_MIME_find_header_name(kContType, allHdrs); - if (curHdr && !XSTRNCMP(curHdr->body, kMultSigned, - XSTR_SIZEOF(kMultSigned))) { - curParam = wc_MIME_find_param_attr("protocol", curHdr->params); - if (curParam && (!XSTRNCMP(curParam->value, kAppPkcsSign, - XSTR_SIZEOF(kAppPkcsSign)) || - !XSTRNCMP(curParam->value, kAppXPkcsSign, - XSTR_SIZEOF(kAppXPkcsSign)))) { - curParam = wc_MIME_find_param_attr("boundary", curHdr->params); - if (curParam == NULL) { - goto error; - } - - boundLen = XSTRLEN(curParam->value) + 2; - boundary = (char*)XMALLOC(boundLen+1, NULL, DYNAMIC_TYPE_PKCS7); - if (boundary == NULL) { - goto error; - } - XMEMSET(boundary, 0, (word32)(boundLen+1)); - boundary[0] = boundary[1] = '-'; - XSTRNCPY(&boundary[2], curParam->value, boundLen-2); - - /* Parse up to first boundary, ignore everything here. */ - lineLen = wolfSSL_BIO_gets(in, section, remainLen); - if (lineLen <= 0) { - goto error; - } - while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) && - remainLen > 0) { - sectionLen += lineLen; - remainLen -= lineLen; - lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], - remainLen); - if (lineLen <= 0) { - goto error; - } - } - - section[0] = '\0'; - sectionLen = 0; - canonSize = remainLen + 1; - canonSection = (char*)XMALLOC(canonSize, NULL, - DYNAMIC_TYPE_PKCS7); - if (canonSection == NULL) { - goto error; - } - - lineLen = wolfSSL_BIO_gets(in, section, remainLen); - if (lineLen < 0) { - goto error; - } - while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) && - remainLen > 0) { - canonLineLen = lineLen; - canonLine = wc_MIME_single_canonicalize(§ion[sectionLen], - &canonLineLen); - if (canonLine == NULL) { - goto error; - } - /* If line endings were added, the initial length may be - * exceeded. */ - if ((canonPos + canonLineLen) >= canonSize) { - canonSize = canonPos + canonLineLen; - canonSection = (char*)XREALLOC(canonSection, canonSize, - NULL, DYNAMIC_TYPE_PKCS7); - if (canonSection == NULL) { - goto error; - } - } - XMEMCPY(&canonSection[canonPos], canonLine, - (int)canonLineLen - 1); - canonPos += canonLineLen - 1; - XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); - canonLine = NULL; - - sectionLen += lineLen; - remainLen -= lineLen; - - lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], - remainLen); - if (lineLen <= 0) { - goto error; - } - } - - if (canonPos > 0) { - canonPos--; - } - - /* Strip the final trailing newline. Support \r, \n or \r\n. */ - if (canonSection[canonPos] == '\n') { - if (canonPos > 0) { - canonPos--; - } - } - - if (canonSection[canonPos] == '\r') { - if (canonPos > 0) { - canonPos--; - } - } + rem.sun_family = AF_UNIX; + XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path) - 1); + rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; - canonSection[canonPos+1] = '\0'; + /* connect to egd server */ + if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) == -1) { + WOLFSSL_MSG("error connecting to egd server"); + ret = WOLFSSL_FATAL_ERROR; + } - *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); - ret = wolfSSL_BIO_write(*bcont, canonSection, - canonPos + 1); - if (ret != (canonPos+1)) { - goto error; - } - if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem)) - < 0) { - goto error; +#ifdef WOLFSSL_CHECK_MEM_ZERO + if (ret == WOLFSSL_SUCCESS) { + wc_MemZero_Add("wolfSSL_RAND_egd buf", buf, 256); + } +#endif + while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) { + buf[idx] = WOLFSSL_EGD_NBLOCK; + buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */ + ret = (int)write(fd, buf + idx, 2); + if (ret != 2) { + if (errno == EAGAIN) { + ret = WOLFSSL_SUCCESS; + continue; } - XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); - canonSection = NULL; + WOLFSSL_MSG("error requesting entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; + } - wc_MIME_free_hdrs(allHdrs); - allHdrs = NULL; - section[0] = '\0'; - sectionLen = 0; - lineLen = wolfSSL_BIO_gets(in, section, remainLen); - if (lineLen <= 0) { - goto error; + /* attempting to read */ + buf[idx] = 0; + ret = (int)read(fd, buf + idx, 256 - bytes); + if (ret == 0) { + WOLFSSL_MSG("error reading entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + if (ret > 0 && buf[idx] > 0) { + bytes += buf[idx]; /* egd stores amount sent in first byte */ + if (bytes + idx > 255 || buf[idx] > ret) { + WOLFSSL_MSG("Buffer error"); + ret = WOLFSSL_FATAL_ERROR; + break; } - while (isEnd == 0 && remainLen > 0) { - sectionLen += lineLen; - remainLen -= lineLen; - lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], - remainLen); - if (lineLen <= 0) { - goto error; - } - /* Line with just newline signals end of headers. */ - if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen], - "\r\n", 2)) || - (lineLen==1 && (section[sectionLen] == '\r' || - section[sectionLen] == '\n'))) { - isEnd = 1; - } + XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]); + idx = bytes; + ret = WOLFSSL_SUCCESS; + if (bytes >= 255) { + break; } - section[sectionLen] = '\0'; - ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs); - if (ret < 0) { - WOLFSSL_MSG("Parsing MIME headers failed."); - goto error; + } + else { + if (errno == EAGAIN || errno == EINTR) { + WOLFSSL_MSG("EGD would read"); + ret = WOLFSSL_SUCCESS; /* try again */ } - curHdr = wc_MIME_find_header_name(kContType, allHdrs); - if (curHdr == NULL || (XSTRNCMP(curHdr->body, kAppPkcsSign, - XSTR_SIZEOF(kAppPkcsSign)) && - XSTRNCMP(curHdr->body, kAppXPkcsSign, - XSTR_SIZEOF(kAppXPkcsSign)))) { - WOLFSSL_MSG("S/MIME headers not found inside " - "multipart message.\n"); - goto error; + else if (buf[idx] == 0) { + /* if egd returned 0 then there is no more entropy to be had. + Do not try more reads. */ + ret = WOLFSSL_SUCCESS; + break; } - - section[0] = '\0'; - sectionLen = 0; - lineLen = wolfSSL_BIO_gets(in, section, remainLen); - while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) && - remainLen > 0) { - sectionLen += lineLen; - remainLen -= lineLen; - lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], - remainLen); - if (lineLen <= 0) { - goto error; - } + else { + WOLFSSL_MSG("Error with read"); + ret = WOLFSSL_FATAL_ERROR; } - - XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); - boundary = NULL; } } - else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime, - XSTR_SIZEOF(kAppPkcs7Mime)) || - !XSTRNCMP(curHdr->body, kAppXPkcs7Mime, - XSTR_SIZEOF(kAppXPkcs7Mime)))) { - sectionLen = wolfSSL_BIO_get_len(in); - if (sectionLen <= 0) { - goto error; + + if (bytes > 0 && ret == WOLFSSL_SUCCESS) { + /* call to check global RNG is created */ + if (wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error with initializing global RNG structure"); + ret = WOLFSSL_FATAL_ERROR; } - ret = wolfSSL_BIO_read(in, section, sectionLen); - if (ret < 0 || ret != sectionLen) { - WOLFSSL_MSG("Error reading input BIO."); - goto error; + else if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes) + != 0) { + WOLFSSL_MSG("Error with reseeding DRBG structure"); + ret = WOLFSSL_FATAL_ERROR; } - } - else { - WOLFSSL_MSG("S/MIME headers not found."); - goto error; + #ifdef SHOW_SECRETS + else { /* print out entropy found only when no error occurred */ + word32 i; + printf("EGD Entropy = "); + for (i = 0; i < bytes; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + } + #endif } - curHdr = wc_MIME_find_header_name(kCTE, allHdrs); - if (curHdr == NULL) { - WOLFSSL_MSG("Content-Transfer-Encoding header not found, " - "assuming base64 encoding."); - } - else if (XSTRNCMP(curHdr->body, "base64", XSTRLEN("base64"))) { - WOLFSSL_MSG("S/MIME encodings other than base64 are not " - "currently supported.\n"); - goto error; - } + ForceZero(buf, bytes); +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#elif defined(WOLFSSL_CHECK_MEM_ZERO) + wc_MemZero_Check(buf, 256); +#endif + close(fd); - if (section == NULL || sectionLen <= 0) { - goto error; - } - outLen = ((sectionLen*3+3)/4)+1; - out = (byte*)XMALLOC(outLen*sizeof(byte), NULL, DYNAMIC_TYPE_PKCS7); - outHead = out; - if (outHead == NULL) { - goto error; - } - /* Strip trailing newlines. */ - while ((sectionLen > 0) && - (section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n')) { - sectionLen--; + if (ret == WOLFSSL_SUCCESS) { + return (int)bytes; } - section[sectionLen] = '\0'; - ret = Base64_Decode((const byte*)section, sectionLen, out, &outLen); - if (ret < 0) { - WOLFSSL_MSG("Error base64 decoding S/MIME message."); - goto error; + else { + return ret; } - pkcs7 = wolfSSL_d2i_PKCS7_only(NULL, (const unsigned char**)&out, outLen, - bcontMem, bcontMemSz); +#else + WOLFSSL_MSG("Type of socket needed is not available"); + WOLFSSL_MSG("\tor using mode where DRBG API is not available"); + (void)nm; - wc_MIME_free_hdrs(allHdrs); - XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); - XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); + return WOLFSSL_FATAL_ERROR; +#endif /* WOLFSSL_EGD_NBLOCK */ +} - return pkcs7; +#endif /* !FREERTOS_TCP */ -error: - wc_MIME_free_hdrs(allHdrs); - XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); - XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); - XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); - if (canonSection != NULL) - XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); - if (canonLine != NULL) - XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); - if (bcont) { - wolfSSL_BIO_free(*bcont); - *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */ +void wolfSSL_RAND_Cleanup(void) +{ +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->cleanup) + gRandMethods->cleanup(); + wc_UnLockMutex(&gRandMethodMutex); } - return NULL; -} - -/* Convert hash algo OID (from Hash_Sum in asn.h) to SMIME string equivalent. - * Returns hash algorithm string or "unknown" if not found */ -static const char* wolfSSL_SMIME_HashOIDToString(int hashOID) -{ - switch (hashOID) { - case MD5h: - return "md5"; - case SHAh: - return "sha1"; - case SHA224h: - return "sha-224"; - case SHA256h: - return "sha-256"; - case SHA384h: - return "sha-384"; - case SHA512h: - return "sha-512"; - case SHA3_224h: - return "sha3-224"; - case SHA3_384h: - return "sha3-384"; - case SHA3_512h: - return "sha3-512"; - default: - break; + #ifndef WOLFSSL_MUTEX_INITIALIZER + if (wc_FreeMutex(&gRandMethodMutex) == 0) + gRandMethodsInit = 0; + #endif +#endif +#ifdef HAVE_GLOBAL_RNG + if (wc_LockMutex(&globalRNGMutex) == 0) { + if (initGlobalRNG) { + wc_FreeRng(&globalRNG); + initGlobalRNG = 0; + } + wc_UnLockMutex(&globalRNGMutex); } - - return "unknown"; +#endif } -/* Convert PKCS#7 type (from PKCS7_TYPES in pkcs7.h) to SMIME string. - * RFC2633 only defines signed-data, enveloped-data, certs-only. - * Returns string on success, NULL on unknown type. */ -static const char* wolfSSL_SMIME_PKCS7TypeToString(int type) +/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise + * WOLFSSL_FAILURE */ +int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) { - switch (type) { - case SIGNED_DATA: - return "signed-data"; - case ENVELOPED_DATA: - return "enveloped-data"; - default: - break; + int ret; + int hash; + byte secret[DRBG_SEED_LEN]; /* secret length arbitrarily chosen */ + +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->pseudorand) { + ret = gRandMethods->pseudorand(buf, num); + wc_UnLockMutex(&gRandMethodMutex); + return ret; + } + wc_UnLockMutex(&gRandMethodMutex); } +#endif - return NULL; -} +#ifdef WOLFSSL_HAVE_PRF + #ifndef NO_SHA256 + hash = WC_SHA256; + #elif defined(WOLFSSL_SHA384) + hash = WC_SHA384; + #elif !defined(NO_SHA) + hash = WC_SHA; + #elif !defined(NO_MD5) + hash = WC_MD5; + #endif -/** - * Convert PKCS7 structure to SMIME format, adding necessary headers. - * - * Handles generation of PKCS7 bundle (ie: signedData). PKCS7 structure - * should be set up beforehand with PKCS7_sign/final/etc. Output is always - * Base64 encoded. - * - * out - output BIO for SMIME formatted data to be placed - * pkcs7 - input PKCS7 structure, initialized and set up - * in - input content to be encoded into PKCS7 - * flags - flags to control behavior of PKCS7 generation - * - * Returns 1 on success, 0 or negative on failure - */ -int wolfSSL_SMIME_write_PKCS7(WOLFSSL_BIO* out, PKCS7* pkcs7, WOLFSSL_BIO* in, - int flags) -{ - int i; - int ret = 1; - WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; - byte* p7out = NULL; - int len = 0; + /* get secret value from source of entropy */ + ret = wolfSSL_RAND_bytes(secret, DRBG_SEED_LEN); - char boundary[33]; /* 32 chars + \0 */ - byte* sigBase64 = NULL; - word32 sigBase64Len = 0; - const char* p7TypeString = NULL; + /* uses input buffer to seed for pseudo random number generation, each + * thread will potentially have different results this way */ + if (ret == WOLFSSL_SUCCESS) { + PRIVATE_KEY_UNLOCK(); + ret = wc_PRF(buf, num, secret, DRBG_SEED_LEN, (const byte*)buf, num, + hash, NULL, INVALID_DEVID); + PRIVATE_KEY_LOCK(); + ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; + } +#else + /* fall back to just doing wolfSSL_RAND_bytes if PRF not avialbale */ + ret = wolfSSL_RAND_bytes(buf, num); + (void)hash; + (void)secret; +#endif + return ret; +} - static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +/* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise + * WOLFSSL_FAILURE */ +int wolfSSL_RAND_bytes(unsigned char* buf, int num) +{ + int ret = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + int initTmpRng = 0; +#ifdef HAVE_GLOBAL_RNG + int used_global = 0; +#endif - if (out == NULL || p7 == NULL) { - WOLFSSL_MSG("Bad function arguments"); + WOLFSSL_ENTER("wolfSSL_RAND_bytes"); + /* sanity check */ + if (buf == NULL || num < 0) + /* return code compliant with OpenSSL */ return 0; - } - if (in != NULL && (p7->pkcs7.content == NULL || p7->pkcs7.contentSz == 0 || - p7->pkcs7.contentCRLF == 0)) { - /* store and adjust content line endings for CRLF if needed */ - if (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1) { - ret = 0; + /* if a RAND callback has been set try and use it */ +#ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->bytes) { + ret = gRandMethods->bytes(buf, num); + wc_UnLockMutex(&gRandMethodMutex); + return ret; } + wc_UnLockMutex(&gRandMethodMutex); } - - if (ret > 0) { - /* Generate signedData bundle, DER in output (dynamic) */ - if ((len = wolfSSL_i2d_PKCS7((PKCS7*)p7, &p7out)) == WOLFSSL_FAILURE) { - WOLFSSL_MSG("Error in wolfSSL_i2d_PKCS7"); - ret = 0; +#endif +#ifdef HAVE_GLOBAL_RNG + if (initGlobalRNG) { + if (wc_LockMutex(&globalRNGMutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex rng"); + return ret; } - } - - /* Base64 encode signedData bundle */ - if (ret > 0) { - if (Base64_Encode(p7out, len, NULL, &sigBase64Len) != LENGTH_ONLY_E) { - ret = 0; + /* the above access to initGlobalRNG is racey -- recheck it now that we + * have the lock. + */ + if (initGlobalRNG) { + rng = &globalRNG; + used_global = 1; } else { - sigBase64 = (byte*)XMALLOC(sigBase64Len, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (sigBase64 == NULL) { - ret = 0; - } + wc_UnLockMutex(&globalRNGMutex); } } - if (ret > 0) { - XMEMSET(sigBase64, 0, sigBase64Len); - if (Base64_Encode(p7out, len, sigBase64, &sigBase64Len) < 0) { - WOLFSSL_MSG("Error in Base64_Encode of signature"); - ret = 0; + if (used_global == 0) +#endif + { + #ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return ret; + #endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; } } + if (rng) { + /* handles size greater than RNG_MAX_BLOCK_LEN */ + int blockCount = num / RNG_MAX_BLOCK_LEN; - /* build up SMIME message */ - if (ret > 0) { - if (flags & PKCS7_DETACHED) { - - /* generate random boundary */ - if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("No RNG to use"); - ret = 0; - } - - /* no need to generate random byte for null terminator (size-1) */ - if ((ret > 0) && (wc_RNG_GenerateBlock(&globalRNG, (byte*)boundary, - sizeof(boundary) - 1 ) != 0)) { - WOLFSSL_MSG("Error in wc_RNG_GenerateBlock"); - ret = 0; - } - - if (ret > 0) { - for (i = 0; i < (int)sizeof(boundary) - 1; i++) { - boundary[i] = - alphanum[boundary[i] % XSTR_SIZEOF(alphanum)]; - } - boundary[sizeof(boundary)-1] = 0; - } - - if (ret > 0) { - /* S/MIME header beginning */ - ret = wolfSSL_BIO_printf(out, - "MIME-Version: 1.0\n" - "Content-Type: multipart/signed; " - "protocol=\"application/x-pkcs7-signature\"; " - "micalg=\"%s\"; " - "boundary=\"----%s\"\n\n" - "This is an S/MIME signed message\n\n" - "------%s\n", - wolfSSL_SMIME_HashOIDToString(p7->pkcs7.hashOID), - boundary, boundary); - } - - if (ret > 0) { - /* S/MIME content */ - ret = wolfSSL_BIO_write(out, - p7->pkcs7.content, p7->pkcs7.contentSz); - } - - if (ret > 0) { - /* S/SMIME header end boundary */ - ret = wolfSSL_BIO_printf(out, - "\n------%s\n", boundary); - } - - if (ret > 0) { - /* Signature and header */ - ret = wolfSSL_BIO_printf(out, - "Content-Type: application/x-pkcs7-signature; " - "name=\"smime.p7s\"\n" - "Content-Transfer-Encoding: base64\n" - "Content-Disposition: attachment; " - "filename=\"smime.p7s\"\n\n" - "%.*s\n" /* Base64 encoded signature */ - "------%s--\n\n", - sigBase64Len, sigBase64, - boundary); - } - } - else { - p7TypeString = wolfSSL_SMIME_PKCS7TypeToString(p7->type); - if (p7TypeString == NULL) { - WOLFSSL_MSG("Unsupported PKCS7 SMIME type"); - ret = 0; - } - - if (ret > 0) { - /* not detached */ - ret = wolfSSL_BIO_printf(out, - "MIME-Version: 1.0\n" - "Content-Disposition: attachment; " - "filename=\"smime.p7m\"\n" - "Content-Type: application/x-pkcs7-mime; " - "smime-type=%s; name=\"smime.p7m\"\n" - "Content-Transfer-Encoding: base64\n\n" - "%.*s\n" /* signature */, - p7TypeString, sigBase64Len, sigBase64); + while (blockCount--) { + ret = wc_RNG_GenerateBlock(rng, buf, RNG_MAX_BLOCK_LEN); + if (ret != 0) { + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + break; } + num -= RNG_MAX_BLOCK_LEN; + buf += RNG_MAX_BLOCK_LEN; } - } - if (p7out != NULL) { - XFREE(p7out, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } - if (sigBase64 != NULL) { - XFREE(sigBase64, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } + if (ret == 0 && num) + ret = wc_RNG_GenerateBlock(rng, buf, (word32)num); - if (ret > 0) { - return WOLFSSL_SUCCESS; + if (ret != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else + ret = WOLFSSL_SUCCESS; } - return WOLFSSL_FAILURE; -} - -#endif /* HAVE_SMIME */ -#endif /* !NO_BIO */ -#endif /* OPENSSL_ALL */ - -#endif /* HAVE_PKCS7 */ -/******************************************************************************* - * END OF PKCS7 APIs - ******************************************************************************/ - -/******************************************************************************* - * START OF PKCS12 APIs - ******************************************************************************/ -#ifdef OPENSSL_EXTRA - -/* no-op function. Was initially used for adding encryption algorithms available - * for PKCS12 */ -void wolfSSL_PKCS12_PBE_add(void) -{ - WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add"); -} - -#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) -WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, - WOLFSSL_X509_PKCS12 **pkcs12) -{ - WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp"); - return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, - PKCS12_TYPE); -} -#endif /* !NO_FILESYSTEM */ - -#endif /* OPENSSL_EXTRA */ - -#if defined(HAVE_PKCS12) +#ifdef HAVE_GLOBAL_RNG + if (used_global == 1) + wc_UnLockMutex(&globalRNGMutex); +#endif + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + if (tmpRNG) + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif -#ifdef OPENSSL_EXTRA + return ret; +} -#if !defined(NO_ASN) && !defined(NO_PWDBASED) -#ifndef NO_BIO -WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) +int wolfSSL_RAND_poll(void) { - WC_PKCS12* localPkcs12 = NULL; - unsigned char* mem = NULL; - long memSz; - int ret = -1; - - WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); + byte entropy[16]; + int ret = 0; + word32 entropy_sz = 16; - if (bio == NULL) { - WOLFSSL_MSG("Bad Function Argument bio is NULL"); - return NULL; + WOLFSSL_ENTER("wolfSSL_RAND_poll"); + if (initGlobalRNG == 0){ + WOLFSSL_MSG("Global RNG no Init"); + return WOLFSSL_FAILURE; } + ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz); + if (ret != 0){ + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + ret = WOLFSSL_FAILURE; + }else + ret = WOLFSSL_SUCCESS; - memSz = wolfSSL_BIO_get_len(bio); - if (memSz <= 0) { - return NULL; - } - mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (mem == NULL) { - return NULL; - } + return ret; +} - if (mem != NULL) { - localPkcs12 = wc_PKCS12_new(); - if (localPkcs12 == NULL) { - WOLFSSL_MSG("Memory error"); + /* If a valid struct is provided with function pointers, will override + RAND_seed, bytes, cleanup, add, pseudo_bytes and status. If a NULL + pointer is passed in, it will cancel any previous function overrides. + + Returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure. */ + int wolfSSL_RAND_set_rand_method(const WOLFSSL_RAND_METHOD *methods) + { + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && + wc_LockMutex(&gRandMethodMutex) == 0) { + gRandMethods = methods; + wc_UnLockMutex(&gRandMethodMutex); + return WOLFSSL_SUCCESS; } + #else + (void)methods; + #endif + return WOLFSSL_FAILURE; } - if (mem != NULL && localPkcs12 != NULL) { - if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { - ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12); - if (ret < 0) { - WOLFSSL_MSG("Failed to get PKCS12 sequence"); - } + /* Returns WOLFSSL_SUCCESS if the RNG has been seeded with enough data */ + int wolfSSL_RAND_status(void) + { + int ret = WOLFSSL_SUCCESS; + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && + wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->status) + ret = gRandMethods->status(); + wc_UnLockMutex(&gRandMethodMutex); } else { - WOLFSSL_MSG("Failed to get data from bio struct"); + ret = WOLFSSL_FAILURE; } + #else + /* wolfCrypt provides enough seed internally, so return success */ + #endif + return ret; } - /* cleanup */ - if (mem != NULL) - XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (ret < 0 && localPkcs12 != NULL) { - wc_PKCS12_free(localPkcs12); - localPkcs12 = NULL; + void wolfSSL_RAND_add(const void* add, int len, double entropy) + { + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB + if (wolfSSL_RAND_InitMutex() == 0 && + wc_LockMutex(&gRandMethodMutex) == 0) { + if (gRandMethods && gRandMethods->add) { + /* callback has return code, but RAND_add does not */ + (void)gRandMethods->add(add, len, entropy); + } + wc_UnLockMutex(&gRandMethodMutex); + } + #else + /* wolfSSL seeds/adds internally, use explicit RNG if you want + to take control */ + (void)add; + (void)len; + (void)entropy; + #endif } - if (pkcs12 != NULL) - *pkcs12 = localPkcs12; - return localPkcs12; + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_RAND_screen(void) +{ + WOLFSSL_STUB("RAND_screen"); } +#endif -/* Converts the PKCS12 to DER format and outputs it into bio. - * - * bio is the structure to hold output DER - * pkcs12 structure to create DER from - * - * return 1 for success or 0 if an error occurs - */ -int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12) +int wolfSSL_RAND_load_file(const char* fname, long len) { - int ret = WOLFSSL_FAILURE; + (void)fname; + /* wolfCrypt provides enough entropy internally or will report error */ + if (len == -1) + return 1024; + else + return (int)len; +} - WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio"); +#endif /* OPENSSL_EXTRA */ + +/******************************************************************************* + * END OF RAND API + ******************************************************************************/ - if ((bio != NULL) && (pkcs12 != NULL)) { - word32 certSz = 0; - byte *certDer = NULL; +/******************************************************************************* + * START OF EVP_CIPHER API + ******************************************************************************/ - certSz = wc_i2d_PKCS12(pkcs12, &certDer, NULL); - if ((certSz > 0) && (certDer != NULL)) { - if (wolfSSL_BIO_write(bio, certDer, certSz) == (int)certSz) { - ret = WOLFSSL_SUCCESS; - } - } +#ifdef OPENSSL_EXTRA - if (certDer != NULL) { - XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS); + /* store for external read of iv, WOLFSSL_SUCCESS on success */ + int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_StoreExternalIV"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return WOLFSSL_FATAL_ERROR; } - } - return ret; -} -#endif /* !NO_BIO */ + switch (ctx->cipherType) { +#ifndef NO_AES +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz); + break; +#endif +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz); + break; +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + case AES_128_CCM_TYPE : + case AES_192_CCM_TYPE : + case AES_256_CCM_TYPE : + WOLFSSL_MSG("AES CCM"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz); + break; +#endif /* HAVE_AESCCM */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + break; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + break; +#endif /* WOLFSSL_AES_COUNTER */ +#ifdef WOLFSSL_AES_CFB +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) + case AES_128_CFB1_TYPE: + case AES_192_CFB1_TYPE: + case AES_256_CFB1_TYPE: + WOLFSSL_MSG("AES CFB1"); + break; + case AES_128_CFB8_TYPE: + case AES_192_CFB8_TYPE: + case AES_256_CFB8_TYPE: + WOLFSSL_MSG("AES CFB8"); + break; +#endif /* !HAVE_SELFTEST && !HAVE_FIPS */ + case AES_128_CFB128_TYPE: + case AES_192_CFB128_TYPE: + case AES_256_CFB128_TYPE: + WOLFSSL_MSG("AES CFB128"); + break; +#endif /* WOLFSSL_AES_CFB */ +#if defined(WOLFSSL_AES_OFB) + case AES_128_OFB_TYPE: + case AES_192_OFB_TYPE: + case AES_256_OFB_TYPE: + WOLFSSL_MSG("AES OFB"); + break; +#endif /* WOLFSSL_AES_OFB */ +#ifdef WOLFSSL_AES_XTS + case AES_128_XTS_TYPE: + case AES_256_XTS_TYPE: + WOLFSSL_MSG("AES XTS"); + break; +#endif /* WOLFSSL_AES_XTS */ +#endif /* NO_AES */ -/* Creates a new WC_PKCS12 structure - * - * pass password to use - * name friendlyName to use - * pkey private key to go into PKCS12 bundle - * cert certificate to go into PKCS12 bundle - * ca extra certificates that can be added to bundle. Can be NULL - * keyNID type of encryption to use on the key (-1 means no encryption) - * certNID type of encryption to use on the certificate - * itt number of iterations with encryption - * macItt number of iterations with mac creation - * keyType flag for signature and/or encryption key - * - * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail - */ -WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey, - WOLFSSL_X509* cert, WOLF_STACK_OF(WOLFSSL_X509)* ca, int keyNID, - int certNID, int itt, int macItt, int keyType) -{ - WC_PKCS12* pkcs12; - WC_DerCertList* list = NULL; - word32 passSz; - byte* keyDer = NULL; - word32 keyDerSz; - byte* certDer; - int certDerSz; - - WOLFSSL_ENTER("wolfSSL_PKCS12_create"); - - if (pass == NULL || pkey == NULL || cert == NULL) { - WOLFSSL_LEAVE("wolfSSL_PKCS12_create", BAD_FUNC_ARG); - return NULL; - } - passSz = (word32)XSTRLEN(pass); +#ifdef HAVE_ARIA + case ARIA_128_GCM_TYPE : + case ARIA_192_GCM_TYPE : + case ARIA_256_GCM_TYPE : + WOLFSSL_MSG("ARIA GCM"); + XMEMCPY(ctx->iv, &ctx->cipher.aria.nonce, ARIA_BLOCK_SIZE); + break; +#endif /* HAVE_ARIA */ - keyDer = (byte*)pkey->pkey.ptr; - keyDerSz = pkey->pkey_sz; +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE); + break; - certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz); - if (certDer == NULL) { - return NULL; - } + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + WOLFSSL_MSG("DES ECB"); + break; + case DES_EDE3_ECB_TYPE : + WOLFSSL_MSG("DES3 ECB"); + break; +#endif + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + break; - if (ca != NULL) { - unsigned long numCerts = ca->num; - WOLFSSL_STACK* sk = ca; +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case CHACHA20_POLY1305_TYPE: + break; +#endif - while (numCerts > 0 && sk != NULL) { - byte* curDer; - WC_DerCertList* cur; - int curDerSz = 0; +#ifdef HAVE_CHACHA + case CHACHA20_TYPE: + break; +#endif - cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL, - DYNAMIC_TYPE_PKCS); - if (cur == NULL) { - wc_FreeCertList(list, NULL); - return NULL; - } +#ifdef WOLFSSL_SM4_ECB + case SM4_ECB_TYPE: + break; +#endif +#ifdef WOLFSSL_SM4_CBC + case SM4_CBC_TYPE: + WOLFSSL_MSG("SM4 CBC"); + XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_SM4_CTR + case SM4_CTR_TYPE: + WOLFSSL_MSG("SM4 CTR"); + XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_SM4_GCM + case SM4_GCM_TYPE: + WOLFSSL_MSG("SM4 GCM"); + XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_SM4_CCM + case SM4_CCM_TYPE: + WOLFSSL_MSG("SM4 CCM"); + XMEMCPY(&ctx->cipher.sm4.iv, ctx->iv, SM4_BLOCK_SIZE); + break; +#endif - curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz); - if (curDer == NULL || curDerSz < 0) { - XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); - wc_FreeCertList(list, NULL); - return NULL; - } + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + break; - cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS); - if (cur->buffer == NULL) { - XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); - wc_FreeCertList(list, NULL); - return NULL; + default: { + WOLFSSL_MSG("bad type"); + return WOLFSSL_FATAL_ERROR; } - XMEMCPY(cur->buffer, curDer, curDerSz); - cur->bufferSz = curDerSz; - cur->next = list; - list = cur; - - sk = sk->next; - numCerts--; } + return WOLFSSL_SUCCESS; } - pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz, - certDer, certDerSz, list, keyNID, certNID, itt, macItt, - keyType, NULL); + /* set internal IV from external, WOLFSSL_SUCCESS on success */ + int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) + { - if (ca != NULL) { - wc_FreeCertList(list, NULL); - } + WOLFSSL_ENTER("wolfSSL_SetInternalIV"); - return pkcs12; -} + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return WOLFSSL_FATAL_ERROR; + } + switch (ctx->cipherType) { -/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */ -int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, - WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, - WOLF_STACK_OF(WOLFSSL_X509)** ca) -{ - void* heap = NULL; - int ret; - byte* certData = NULL; - word32 certDataSz; - byte* pk = NULL; - word32 pkSz; - WC_DerCertList* certList = NULL; -#ifdef WOLFSSL_SMALL_STACK - DecodedCert *DeCert; -#else - DecodedCert DeCert[1]; +#ifndef NO_AES +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + break; #endif - - WOLFSSL_ENTER("wolfSSL_PKCS12_parse"); - - /* make sure we init return args */ - if (pkey) *pkey = NULL; - if (cert) *cert = NULL; - if (ca) *ca = NULL; - - if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) { - WOLFSSL_MSG("Bad argument value"); - return WOLFSSL_FAILURE; - } - - heap = wc_PKCS12_GetHeap(pkcs12); - - if (ca == NULL) { - ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, - NULL); - } - else { - ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, - &certList); - } - if (ret < 0) { - WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret); - return WOLFSSL_FAILURE; - } - -#ifdef WOLFSSL_SMALL_STACK - DeCert = (DecodedCert *)XMALLOC(sizeof(*DeCert), heap, - DYNAMIC_TYPE_DCERT); - if (DeCert == NULL) { - WOLFSSL_MSG("out of memory"); - return WOLFSSL_FAILURE; - } +#ifdef HAVE_AESGCM + case AES_128_GCM_TYPE : + case AES_192_GCM_TYPE : + case AES_256_GCM_TYPE : + WOLFSSL_MSG("AES GCM"); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + break; +#endif +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + break; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + break; #endif - /* Decode cert and place in X509 stack struct */ - if (certList != NULL) { - WC_DerCertList* current = certList; - - *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC( - sizeof(WOLF_STACK_OF(WOLFSSL_X509)), heap, DYNAMIC_TYPE_X509); - if (*ca == NULL) { - if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); - } - if (certData != NULL) { - XFREE(certData, heap, DYNAMIC_TYPE_PKCS); - } - /* Free up WC_DerCertList and move on */ - while (current != NULL) { - WC_DerCertList* next = current->next; +#endif /* NO_AES */ - XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); - XFREE(current, heap, DYNAMIC_TYPE_PKCS); - current = next; - } - ret = WOLFSSL_FAILURE; - goto out; - } - XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509))); +#ifdef HAVE_ARIA + case ARIA_128_GCM_TYPE : + case ARIA_192_GCM_TYPE : + case ARIA_256_GCM_TYPE : + WOLFSSL_MSG("ARIA GCM"); + XMEMCPY(&ctx->cipher.aria.nonce, ctx->iv, ARIA_BLOCK_SIZE); + break; +#endif /* HAVE_ARIA */ - /* add list of DER certs as X509's to stack */ - while (current != NULL) { - WC_DerCertList* toFree = current; - WOLFSSL_X509* x509; +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE); + break; - x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_X509); - InitX509(x509, 1, heap); - InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap); - if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { - WOLFSSL_MSG("Issue with parsing certificate"); - FreeDecodedCert(DeCert); - wolfSSL_X509_free(x509); - } - else { - if (CopyDecodedToX509(x509, DeCert) != 0) { - WOLFSSL_MSG("Failed to copy decoded cert"); - FreeDecodedCert(DeCert); - wolfSSL_X509_free(x509); - wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; - if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); - } - if (certData != NULL) { - XFREE(certData, heap, DYNAMIC_TYPE_PKCS); - } - /* Free up WC_DerCertList */ - while (current != NULL) { - WC_DerCertList* next = current->next; + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE); + break; +#endif +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + WOLFSSL_MSG("DES ECB"); + break; + case DES_EDE3_ECB_TYPE : + WOLFSSL_MSG("DES3 ECB"); + break; +#endif - XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); - XFREE(current, heap, DYNAMIC_TYPE_PKCS); - current = next; - } - ret = WOLFSSL_FAILURE; - goto out; - } - FreeDecodedCert(DeCert); + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + break; - if (wolfSSL_sk_X509_push(*ca, x509) != 1) { - WOLFSSL_MSG("Failed to push x509 onto stack"); - wolfSSL_X509_free(x509); - wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; - if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); - } - if (certData != NULL) { - XFREE(certData, heap, DYNAMIC_TYPE_PKCS); - } +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case CHACHA20_POLY1305_TYPE: + break; +#endif - /* Free up WC_DerCertList */ - while (current != NULL) { - WC_DerCertList* next = current->next; +#ifdef HAVE_CHACHA + case CHACHA20_TYPE: + break; +#endif - XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); - XFREE(current, heap, DYNAMIC_TYPE_PKCS); - current = next; - } - ret = WOLFSSL_FAILURE; - goto out; - } - } - current = current->next; - XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS); - XFREE(toFree, heap, DYNAMIC_TYPE_PKCS); - } - } +#ifdef WOLFSSL_SM4_ECB + case SM4_ECB_TYPE: + break; +#endif +#ifdef WOLFSSL_SM4_CBC + case SM4_CBC_TYPE: + WOLFSSL_MSG("SM4 CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); + break; +#endif +#ifdef WOLFSSL_SM4_CTR + case SM4_CTR_TYPE: + WOLFSSL_MSG("SM4 CTR"); + XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); + break; +#endif +#ifdef WOLFSSL_SM4_GCM + case SM4_GCM_TYPE: + WOLFSSL_MSG("SM4 GCM"); + XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); + break; +#endif +#ifdef WOLFSSL_SM4_CCM + case SM4_CCM_TYPE: + WOLFSSL_MSG("SM4 CCM"); + XMEMCPY(ctx->iv, &ctx->cipher.sm4.iv, ctx->ivSz); + break; +#endif + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + break; - /* Decode cert and place in X509 struct */ - if (certData != NULL) { - *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_X509); - if (*cert == NULL) { - if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); - } - if (ca != NULL) { - wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; - } - XFREE(certData, heap, DYNAMIC_TYPE_PKCS); - ret = WOLFSSL_FAILURE; - goto out; - } - InitX509(*cert, 1, heap); - InitDecodedCert(DeCert, certData, certDataSz, heap); - if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { - WOLFSSL_MSG("Issue with parsing certificate"); - } - if (CopyDecodedToX509(*cert, DeCert) != 0) { - WOLFSSL_MSG("Failed to copy decoded cert"); - FreeDecodedCert(DeCert); - if (pk != NULL) { - XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); - } - if (ca != NULL) { - wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + default: { + WOLFSSL_MSG("bad type"); + return WOLFSSL_FATAL_ERROR; } - wolfSSL_X509_free(*cert); *cert = NULL; - XFREE(certData, heap, DYNAMIC_TYPE_PKCS); - ret = WOLFSSL_FAILURE; - goto out; } - FreeDecodedCert(DeCert); - XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_SUCCESS; } +#ifndef NO_DES3 - /* get key type */ - ret = BAD_STATE_E; - if (pk != NULL) { /* decode key if present */ - *pkey = wolfSSL_EVP_PKEY_new_ex(heap); - if (*pkey == NULL) { - wolfSSL_X509_free(*cert); *cert = NULL; - if (ca != NULL) { - wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; - } - XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); - ret = WOLFSSL_FAILURE; - goto out; - } - - #ifndef NO_RSA - { - const unsigned char* pt = pk; - if (wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, pkey, &pt, pkSz) != - NULL) { - ret = 0; - } - } - #endif /* NO_RSA */ +void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, + unsigned char* iv, int len) +{ + (void)len; - #ifdef HAVE_ECC - if (ret != 0) { /* if is in fail state check if ECC key */ - const unsigned char* pt = pk; - if (wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, pkey, &pt, pkSz) != - NULL) { - ret = 0; - } - } - #endif /* HAVE_ECC */ - if (pk != NULL) - XFREE(pk, heap, DYNAMIC_TYPE_PKCS); - if (ret != 0) { /* if is in fail state and no PKEY then fail */ - wolfSSL_X509_free(*cert); *cert = NULL; - if (ca != NULL) { - wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; - } - wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; - WOLFSSL_MSG("Bad PKCS12 key format"); - ret = WOLFSSL_FAILURE; - goto out; - } + WOLFSSL_MSG("wolfSSL_3des_iv"); - if (pkey != NULL && *pkey != NULL) { - (*pkey)->save_type = 0; - } + if (ctx == NULL || iv == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; } - (void)ret; - (void)ca; - - ret = WOLFSSL_SUCCESS; + if (doset) + wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); +} -out: +#endif /* NO_DES3 */ -#ifdef WOLFSSL_SMALL_STACK - XFREE(DeCert, heap, DYNAMIC_TYPE_DCERT); -#endif - return ret; -} +#ifndef NO_AES -int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw, - int pswLen) +void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, + unsigned char* iv, int len) { - WOLFSSL_ENTER("wolfSSL_PKCS12_verify_mac"); + (void)len; - if (!pkcs12) { - return WOLFSSL_FAILURE; + WOLFSSL_MSG("wolfSSL_aes_ctr_iv"); + + if (ctx == NULL || iv == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; } - return wc_PKCS12_verify_ex(pkcs12, (const byte*)psw, pswLen) == 0 ? - WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + if (doset) + (void)wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); } -#endif /* !NO_ASN && !NO_PWDBASED */ +#endif /* NO_AES */ #endif /* OPENSSL_EXTRA */ -#endif /* HAVE_PKCS12 */ /******************************************************************************* - * END OF PKCS12 APIs + * END OF EVP_CIPHER API ******************************************************************************/ +#ifndef NO_CERTS + +#define WOLFSSL_X509_STORE_INCLUDED +#include + +#define WOLFSSL_SSL_P7P12_INCLUDED +#include + #endif /* !NO_CERTS */ @@ -36036,7 +24630,7 @@ int wolfSSL_FIPS_drbg_init(WOLFSSL_DRBG_CTX *ctx, int type, unsigned int flags) if (ctx != NULL) { XMEMSET(ctx, 0, sizeof(WOLFSSL_DRBG_CTX)); ctx->type = type; - ctx->xflags = flags; + ctx->xflags = (int)flags; ctx->status = DRBG_STATUS_UNINITIALISED; ret = WOLFSSL_SUCCESS; } diff --git a/src/src/ssl_asn1.c b/src/src/ssl_asn1.c index eecf467..b93d8d5 100644 --- a/src/src/ssl_asn1.c +++ b/src/src/ssl_asn1.c @@ -247,6 +247,11 @@ static int wolfssl_i2d_asn1_item(void** item, int type, byte* buf) len = 0; } + if (len < 0) { + len = 0; /* wolfSSL_i2d_ASN1_INTEGER can return a value less than 0 + * on error */ + } + return len; } @@ -974,7 +979,8 @@ static int wolfssl_a2i_asn1_integer_clear_to_eol(char* str, int len, int* cont) nLen = 1; for (i = 0; i < len; i++) { /* Check if character is a hexadecimal character. */ - if (Base16_Decode((const byte*)str + i, 1, &num, &nLen) == ASN_INPUT_E) + if (Base16_Decode((const byte*)str + i, 1, &num, &nLen) == + WC_NO_ERR_TRACE(ASN_INPUT_E)) { /* Found end of hexadecimal characters, return count. */ len = i; @@ -2997,7 +3003,7 @@ void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time) { WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free"); if (asn1Time != NULL) { - XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data)); + XFREE(asn1Time, NULL, DYNAMIC_TYPE_OPENSSL); } } @@ -3509,14 +3515,17 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, if (ret != NULL) { /* Set the ASN.1 type and length of string. */ ret->type = V_ASN1_GENERALIZEDTIME; - ret->length = ASN_GENERALIZED_TIME_SIZE; if (t->type == V_ASN1_GENERALIZEDTIME) { + ret->length = ASN_GENERALIZED_TIME_SIZE; + /* Just copy as data already appropriately formatted. */ XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE); } else { /* Convert UTC TIME to GENERALIZED TIME. */ + ret->length = t->length + 2; /* Add two extra year digits */ + if (t->data[0] >= '5') { /* >= 50 is 1900s. */ ret->data[0] = '1'; ret->data[1] = '9'; @@ -3526,7 +3535,7 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, ret->data[0] = '2'; ret->data[1] = '0'; } /* Append rest of the data as it is the same. */ - XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE); + XMEMCPY(&ret->data[2], t->data, t->length); } /* Check for pointer to return result through. */ @@ -3538,6 +3547,32 @@ WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, return ret; } +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_UTCTIME_set(WOLFSSL_ASN1_TIME *s, time_t t) +{ + WOLFSSL_ASN1_TIME* ret = s; + + WOLFSSL_ENTER("wolfSSL_ASN1_UTCTIME_set"); + + if (ret == NULL) { + ret = wolfSSL_ASN1_TIME_new(); + if (ret == NULL) + return NULL; + } + + ret->length = GetFormattedTime(&t, ret->data, sizeof(ret->data)); + if (ret->length + 1 != ASN_UTC_TIME_SIZE) { + /* Either snprintf error or t can't be represented in UTC format */ + if (ret != s) + wolfSSL_ASN1_TIME_free(ret); + ret = NULL; + } + else { + ret->type = V_ASN1_UTCTIME; + } + + return ret; +} + #endif /* OPENSSL_EXTRA */ #if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) diff --git a/src/src/ssl_bn.c b/src/src/ssl_bn.c index cbb4a92..c025755 100644 --- a/src/src/ssl_bn.c +++ b/src/src/ssl_bn.c @@ -25,7 +25,7 @@ #include - #include +#include #ifndef WC_NO_RNG #include #endif diff --git a/src/src/ssl_certman.c b/src/src/ssl_certman.c index e074996..e666059 100644 --- a/src/src/ssl_certman.c +++ b/src/src/ssl_certman.c @@ -141,14 +141,12 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap) #ifdef HAVE_ECC cm->minEccKeySz = MIN_ECCKEY_SZ; #endif - #ifdef HAVE_PQC #ifdef HAVE_FALCON cm->minFalconKeySz = MIN_FALCONKEY_SZ; #endif /* HAVE_FALCON */ #ifdef HAVE_DILITHIUM cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ; #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ /* Set heap hint to use in certificate manager operations. */ cm->heap = heap; @@ -700,7 +698,7 @@ int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff, /* Parse DER into decoded certificate fields and verify signature * against a known CA. */ - ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm, NULL); } #ifdef HAVE_CRL @@ -1819,7 +1817,7 @@ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, InitDecodedCert(cert, der, (word32)sz, NULL); /* Parse certificate and perform CRL checks. */ - ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm, NULL); if (ret != 0) { WOLFSSL_MSG("ParseCert failed"); } @@ -2291,7 +2289,7 @@ int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, InitDecodedCert(cert, der, (word32)sz, NULL); /* Parse certificate and perform CRL checks. */ - ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL); if (ret != 0) { WOLFSSL_MSG("ParseCert failed"); } diff --git a/src/src/ssl_crypto.c b/src/src/ssl_crypto.c index 3c73b88..5a05324 100644 --- a/src/src/ssl_crypto.c +++ b/src/src/ssl_crypto.c @@ -1966,7 +1966,7 @@ int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) * @return NULL on failure. */ unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, - int key_len, const unsigned char* data, int len, unsigned char* md, + int key_len, const unsigned char* data, size_t len, unsigned char* md, unsigned int* md_len) { unsigned char* ret = NULL; @@ -2000,7 +2000,7 @@ unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, #endif if (rc == 0) { /* Get the HMAC output length. */ - hmacLen = wolfssl_mac_len((unsigned char)type); + hmacLen = (int)wolfssl_mac_len((unsigned char)type); /* 0 indicates the digest is not supported. */ if (hmacLen == 0) { rc = BAD_FUNC_ARG; @@ -2009,16 +2009,16 @@ unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, /* Initialize the wolfSSL HMAC object. */ if ((rc == 0) && (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0)) { /* Set the key into the wolfSSL HMAC object. */ - rc = wc_HmacSetKey(hmac, type, (const byte*)key, key_len); + rc = wc_HmacSetKey(hmac, type, (const byte*)key, (word32)key_len); if (rc == 0) { /* Update the wolfSSL HMAC object with data. */ - rc = wc_HmacUpdate(hmac, data, len); + rc = wc_HmacUpdate(hmac, data, (word32)len); } /* Finalize the wolfSSL HMAC object. */ if ((rc == 0) && (wc_HmacFinal(hmac, md) == 0)) { /* Return the length of the HMAC output if required. */ if (md_len != NULL) { - *md_len = hmacLen; + *md_len = (unsigned int)hmacLen; } /* Set the buffer to return. */ ret = md; @@ -2269,7 +2269,7 @@ int wolfSSL_CMAC_Final(WOLFSSL_CMAC_CTX* ctx, unsigned char* out, size_t* len) len32 = (word32)blockSize; /* Return size if required. */ if (len != NULL) { - *len = blockSize; + *len = (size_t)blockSize; } } } diff --git a/src/src/ssl_load.c b/src/src/ssl_load.c new file mode 100644 index 0000000..2441d48 --- /dev/null +++ b/src/src/ssl_load.c @@ -0,0 +1,5831 @@ +/* ssl_load.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* + * WOLFSSL_SYS_CA_CERTS + * Enables ability to load system CA certs from the OS via + * wolfSSL_CTX_load_system_CA_certs. + */ + +#ifdef WOLFSSL_SYS_CA_CERTS + +#ifdef _WIN32 + #include + #include + + /* mingw gcc does not support pragma comment, and the + * linking with crypt32 is handled in configure.ac */ + #if !defined(__MINGW32__) && !defined(__MINGW64__) + #pragma comment(lib, "crypt32") + #endif +#endif + +#if defined(__APPLE__) && defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) +#include +#endif + +#endif /* WOLFSSL_SYS_CA_CERTS */ + +#if !defined(WOLFSSL_SSL_LOAD_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning ssl_load.c does not need to be compiled separately from ssl.c + #endif +#else + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* PSK field of context when it exists. */ + #define CTX_HAVE_PSK(ctx) (ctx)->havePSK + /* PSK field of ssl when it exists. */ + #define SSL_HAVE_PSK(ssl) (ssl)->options.havePSK +#else + /* Have PSK value when no field. */ + #define CTX_HAVE_PSK(ctx) 0 + /* Have PSK value when no field. */ + #define SSL_HAVE_PSK(ssl) 0 +#endif +#ifdef NO_RSA + /* Boolean for RSA available. */ + #define WOLFSSL_HAVE_RSA 0 +#else + /* Boolean for RSA available. */ + #define WOLFSSL_HAVE_RSA 1 +#endif +#ifndef NO_CERTS + /* Private key size from ssl. */ + #define SSL_KEY_SZ(ssl) (ssl)->buffers.keySz +#else + /* Private key size not available. */ + #define SSL_KEY_SZ(ssl) 0 +#endif +#ifdef HAVE_ANON + /* Anonymous ciphersuite allowed field in context. */ + #define CTX_USE_ANON(ctx) (ctx)->useAnon +#else + /* Anonymous ciphersuite allowed field not in context. */ + #define CTX_USE_ANON(ctx) 0 +#endif + +#ifdef HAVE_PK_CALLBACKS + #define WOLFSSL_IS_PRIV_PK_SET(ctx, ssl) \ + wolfSSL_CTX_IsPrivatePkSet(((ssl) == NULL) ? (ctx) : (ssl)->ctx) +#else + #define WOLFSSL_IS_PRIV_PK_SET(ctx, ssl) 0 +#endif + +/* Get the heap from the context or the ssl depending on which is available. */ +#define WOLFSSL_HEAP(ctx, ssl) \ + (((ctx) != NULL) ? (ctx)->heap : (((ssl) != NULL) ? (ssl)->heap : NULL)) + + +#ifndef NO_CERTS + +/* Get DER encoding from data in a buffer as a DerBuffer. + * + * @param [in] buff Buffer containing data. + * @param [in] len Length of data in buffer. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @param [in] type Type of data: + * CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE, + * PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE. + * @param [in, out] info Info for encryption. + * @param [in] heap Dynamic memory allocation hint. + * @param [out] der Holds DER encoded data. + * @param [out] algId Algorithm identifier for private keys. + * @return 0 on success. + * @return NOT_COMPILED_IN when format is PEM and PEM not supported. + * @return ASN_PARSE_E when format is ASN.1 and invalid DER encoding. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int DataToDerBuffer(const unsigned char* buff, word32 len, int format, + int type, EncryptedInfo* info, void* heap, DerBuffer** der, int* algId) +{ + int ret; + + info->consumed = 0; + + /* Data in buffer has PEM format - extract DER data. */ + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, len, type, der, heap, info, algId); + if (ret != 0) { + FreeDer(der); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + /* Data in buffer is ASN.1 format - get first SEQ or OCT into der. */ + else { + int length; + word32 inOutIdx = 0; + + /* Get length of SEQ including header. */ + if ((info->consumed = wolfssl_der_length(buff, (int)len)) > 0) { + ret = 0; + } + /* Private keys may be wrapped in OCT when PKCS#8 wrapper removed. + * TODO: is this really needed? */ + else if ((type == PRIVATEKEY_TYPE) && + (GetOctetString(buff, &inOutIdx, &length, len) >= 0)) { + /* Include octet string DER header. */ + info->consumed = length + inOutIdx; + ret = 0; + } + else { + ret = ASN_PARSE_E; + } + + if (info->consumed > (int)len) { + ret = ASN_PARSE_E; + } + if (ret == 0) { + ret = AllocCopyDer(der, buff, (word32)info->consumed, type, heap); + } + } + + return ret; +} + +/* Process a user's certificate. + * + * Puts the 3-byte length before certificate data as required for TLS. + * CA certificates are added to the certificate manager. + * + * @param [in] cm Certificate manager. + * @param [in, out] pDer DER encoded data. + * @param [in] type Type of data. Valid values: + * CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE. + * @param [in] verify How to verify certificate. + * @param [out] chainBuffer Buffer to hold chain of certificates. + * @param [in, out] pIdx On in, current index into chainBuffer. + * On out, index after certificate added. + * @param [in] bufferSz Size of buffer in bytes. + * @return 0 on success. + * @return BUFFER_E if chain buffer not big enough to hold certificate. + */ +static int ProcessUserCert(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, + int type, int verify, byte* chainBuffer, word32* pIdx, word32 bufferSz) +{ + int ret = 0; + word32 idx = *pIdx; + DerBuffer* der = *pDer; + + /* Check there is space for certificate in chainBuffer. */ + if ((ret == 0) && ((idx + der->length + CERT_HEADER_SZ) > bufferSz)) { + WOLFSSL_MSG(" Cert Chain bigger than buffer. " + "Consider increasing MAX_CHAIN_DEPTH"); + ret = BUFFER_E; + } + if (ret == 0) { + /* 3-byte length. */ + c32to24(der->length, &chainBuffer[idx]); + idx += CERT_HEADER_SZ; + /* Add complete DER encoded certificate. */ + XMEMCPY(&chainBuffer[idx], der->buffer, der->length); + idx += der->length; + + if (type == CA_TYPE) { + /* Add CA to certificate manager */ + ret = AddCA(cm, pDer, WOLFSSL_USER_CA, verify); + if (ret == 1) { + ret = 0; + } + } + } + + /* Update the index into chainBuffer. */ + *pIdx = idx; + return ret; +} + +/* Store the certificate chain buffer aganst WOLFSSL_CTX or WOLFSSL object. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] chainBuffer Buffer containing chain of certificates. + * @param [in] len Length, in bytes, of data in buffer. + * @param [in] cnt Number of certificates in chain. + * @param [in] type Type of data. Valid values: + * CERT_TYPE, CA_TYPE or CHAIN_CERT_TYPE. + * @param [in] heap Dynamic memory allocation hint. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int ProcessUserChainRetain(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const byte* chainBuffer, word32 len, int cnt, int type, void* heap) +{ + int ret = 0; + + (void)cnt; + + /* Store in SSL object if available. */ + if (ssl != NULL) { + /* Dispose of old chain if not reference to context's. */ + if (ssl->buffers.weOwnCertChain) { + FreeDer(&ssl->buffers.certChain); + } + /* Allocate and copy the buffer into SSL object. */ + ret = AllocCopyDer(&ssl->buffers.certChain, chainBuffer, len, type, + heap); + ssl->buffers.weOwnCertChain = (ret == 0); + #ifdef WOLFSSL_TLS13 + /* Update count of certificates in chain. */ + ssl->buffers.certChainCnt = cnt; + #endif + } + /* Store in SSL context object if available. */ + else if (ctx != NULL) { + /* Dispose of old chain and allocate and copy in new chain. */ + FreeDer(&ctx->certChain); + /* Allocate and copy the buffer into SSL context object. */ + ret = AllocCopyDer(&ctx->certChain, chainBuffer, len, type, heap); + #ifdef WOLFSSL_TLS13 + /* Update count of certificates in chain. */ + ctx->certChainCnt = cnt; + #endif + } + + return ret; +} + +/* Process user cert chain to pass during the TLS handshake. + * + * If not a certificate type then data is ignored. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] buff Buffer holding certificates. + * @param [in] sz Length of data in buffer. + * @param [in] format Format of the certificate: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1 + * @param [in] type Type of certificate: + * CA_TYPE, CERT_TYPE or CHAIN_CERT_TYPE + * @param [out] used Number of bytes from buff used. + * @param [in, out] info Encryption information. + * @param [in] verify How to verify certificate. + * @return 0 on success. + * @return BAD_FUNC_ARG when type is CA_TYPE and ctx is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int ProcessUserChain(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const unsigned char* buff, long sz, int format, int type, long* used, + EncryptedInfo* info, int verify) +{ + int ret = 0; + void* heap = WOLFSSL_HEAP(ctx, ssl); + + WOLFSSL_ENTER("ProcessUserChain"); + + /* Validate parameters. */ + if ((type == CA_TYPE) && (ctx == NULL)) { + WOLFSSL_MSG("Need context for CA load"); + ret = BAD_FUNC_ARG; + } + + /* Ignore non-certificate types. */ + if ((ret == 0) && (type != CERT_TYPE) && (type != CHAIN_CERT_TYPE) && + (type != CA_TYPE)) { + WOLFSSL_MSG("File type not a certificate"); + } + /* Check we haven't consumed all the data. */ + else if ((ret == 0) && (info->consumed >= sz)) { + WOLFSSL_MSG("Already consumed data"); + } + else if (ret == 0) { + #ifndef WOLFSSL_SMALL_STACK + byte stackBuffer[FILE_BUFFER_SIZE]; + #endif + StaticBuffer chain; + long consumed = info->consumed; + word32 idx = 0; + int gotOne = 0; + int cnt = 0; + /* Calculate max possible size, including max headers */ + long maxSz = (sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH); + + /* Setup buffer to hold chain. */ + #ifdef WOLFSSL_SMALL_STACK + static_buffer_init(&chain); + #else + static_buffer_init(&chain, stackBuffer, FILE_BUFFER_SIZE); + #endif + /* Make buffer big enough to support maximum size. */ + ret = static_buffer_set_size(&chain, (word32)maxSz, heap, + DYNAMIC_TYPE_FILE); + + WOLFSSL_MSG("Processing Cert Chain"); + /* Keep parsing certificates will data available. */ + while ((ret == 0) && (consumed < sz)) { + DerBuffer* part = NULL; + + /* Get a certificate as DER. */ + ret = DataToDerBuffer(buff + consumed, (word32)(sz - consumed), + format, type, info, heap, &part, NULL); + if (ret == 0) { + /* Process the user certificate. */ + ret = ProcessUserCert(ctx->cm, &part, type, verify, + chain.buffer, &idx, (word32)maxSz); + } + /* PEM may have trailing data that can be ignored. */ + if ((ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) && gotOne) { + WOLFSSL_MSG("We got one good cert, so stuff at end ok"); + ret = 0; + break; + } + /* Certificate data handled. */ + FreeDer(&part); + + if (ret == 0) { + /* Update consumed length. */ + consumed += info->consumed; + WOLFSSL_MSG(" Consumed another Cert in Chain"); + /* Update whether we got a user certificate. */ + gotOne |= (type != CA_TYPE); + /* Update count of certificates added to chain. */ + cnt++; + } + } + if (used != NULL) { + /* Return the total consumed length. */ + *used = consumed; + } + + /* Check whether there is data in the chain buffer. */ + if ((ret == 0) && (idx > 0)) { + /* Put the chain buffer against the SSL or SSL context object. */ + ret = ProcessUserChainRetain(ctx, ssl, chain.buffer, idx, cnt, type, + heap); + } + + /* Dispose of chain buffer. */ + static_buffer_free(&chain, heap, DYNAMIC_TYPE_FILE); + } + + WOLFSSL_LEAVE("ProcessUserChain", ret); + return ret; +} + +#ifndef NO_RSA +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) +/* See if DER data is an RSA private key. + * + * Checks size meets minimum RSA key size. + * This implementation uses less dynamic memory. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not an RSA key and format unknown. + * @return RSA_KEY_SIZE_E when key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, int devId, byte* keyType, int* keySize) +{ + int ret; + word32 idx; + int keySz = 0; + + (void)devId; + + /* Validate we have an RSA private key and get key size. */ + idx = 0; + ret = wc_RsaPrivateKeyValidate(der->buffer, &idx, &keySz, der->length); +#ifdef WOLF_PRIVATE_KEY_ID + /* If that didn't work then maybe a public key if device ID or callback. */ + if ((ret != 0) && ((devId != INVALID_DEVID) || + WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) { + word32 nSz; + + /* Decode as an RSA public key. */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(der->buffer, &idx, der->length, NULL, + &nSz, NULL, NULL); + if (ret == 0) { + keySz = (int)nSz; + } + } +#endif + if (ret == 0) { + /* Get the minimum RSA key size from SSL or SSL context object. */ + int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; + + /* Format, type and size are known. */ + *keyFormat = RSAk; + *keyType = rsa_sa_algo; + *keySize = keySz; + + /* Check that the size of the RSA key is enough. */ + if (keySz < minRsaSz) { + WOLFSSL_MSG("Private Key size too small"); + ret = RSA_KEY_SIZE_E; + } + /* No static ECC key possible. */ + if ((ssl != NULL) && (ssl->options.side == WOLFSSL_SERVER_END)) { + ssl->options.haveStaticECC = 0; + } + } + /* Not an RSA key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not an RSA key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + return ret; +} +#else +/* See if DER data is an RSA private key. + * + * Checks size meets minimum RSA key size. + * This implementation uses more dynamic memory but supports older FIPS. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not an RSA key and format unknown. + * @return RSA_KEY_SIZE_E when key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType, + int* keySize) +{ + int ret; + word32 idx; + /* make sure RSA key can be used */ +#ifdef WOLFSSL_SMALL_STACK + RsaKey* key; +#else + RsaKey key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate an RSA key to parse into so we can get size. */ + key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); + if (key == NULL) + return MEMORY_E; +#endif + + /* Initialize the RSA key. */ + ret = wc_InitRsaKey_ex(key, heap, devId); + if (ret == 0) { + /* Check we have an RSA private key. */ + idx = 0; + ret = wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + /* If that didn't work then maybe a public key if device ID or callback. + */ + if ((ret != 0) && ((devId != INVALID_DEVID) || + WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) { + /* If that didn't work then maybe a public key if device ID or + * callback. */ + idx = 0; + ret = wc_RsaPublicKeyDecode(der->buffer, &idx, key, der->length); + } + #endif + if (ret == 0) { + /* Get the minimum RSA key size from SSL or SSL context object. */ + int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; + int keySz = wc_RsaEncryptSize((RsaKey*)key); + + /* Format is known. */ + *keyFormat = RSAk; + *keyType = rsa_sa_algo; + *keySize = keySz; + + /* Check that the size of the RSA key is enough. */ + if (keySz < minRsaSz) { + WOLFSSL_MSG("Private Key size too small"); + ret = RSA_KEY_SIZE_E; + } + /* No static ECC key possible. */ + if ((ssl != NULL) && (ssl->options.side == WOLFSSL_SERVER_END)) { + ssl->options.haveStaticECC = 0; + } + } + /* Not an RSA key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not an RSA key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + /* Free dynamically allocated data in key. */ + wc_FreeRsaKey(key); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of allocated key. */ + XFREE(key, heap, DYNAMIC_TYPE_RSA); +#endif + + return ret; +} +#endif +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/* See if DER data is an ECC private key. + * + * Checks size meets minimum ECC key size. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not an ECC key and format unknown. + * @return ECC_KEY_SIZE_E when ECC key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeEcc(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType, + int* keySize) +{ + int ret = 0; + word32 idx; + /* make sure ECC key can be used */ +#ifdef WOLFSSL_SMALL_STACK + ecc_key* key; +#else + ecc_key key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate an ECC key to parse into. */ + key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); + if (key == NULL) + return MEMORY_E; +#endif + + /* Initialize ECC key. */ + if (wc_ecc_init_ex(key, heap, devId) == 0) { + /* Decode as an ECC private key. */ + idx = 0; + ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + /* If that didn't work then maybe a public key if device ID or callback. + */ + if ((ret != 0) && ((devId != INVALID_DEVID) || + WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) { + /* Decode as an ECC public key. */ + idx = 0; + ret = wc_EccPublicKeyDecode(der->buffer, &idx, key, der->length); + } + #endif + #ifdef WOLFSSL_SM2 + if (*keyFormat == SM2k) { + ret = wc_ecc_set_curve(key, WOLFSSL_SM2_KEY_BITS / 8, + ECC_SM2P256V1); + } + #endif + if (ret == 0) { + /* Get the minimum ECC key size from SSL or SSL context object. */ + int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + int keySz = wc_ecc_size(key); + + /* Format is known. */ + *keyFormat = ECDSAk; + #ifdef WOLFSSL_SM2 + if (key->dp->id == ECC_SM2P256V1) { + *keyType = sm2_sa_algo; + } + else + #endif + { + *keyType = ecc_dsa_sa_algo; + } + *keySize = keySz; + + /* Check that the size of the ECC key is enough. */ + if (keySz < minKeySz) { + WOLFSSL_MSG("ECC private key too small"); + ret = ECC_KEY_SIZE_E; + } + /* Static ECC key possible. */ + if (ssl) { + ssl->options.haveStaticECC = 1; + } + else { + ctx->haveStaticECC = 1; + } + } + /* Not an ECC key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not an ECC key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + /* Free dynamically allocated data in key. */ + wc_ecc_free(key); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of allocated key. */ + XFREE(key, heap, DYNAMIC_TYPE_ECC); +#endif + return ret; +} +#endif /* HAVE_ECC */ + +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) +/* See if DER data is an Ed25519 private key. + * + * Checks size meets minimum ECC key size. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not an Ed25519 key and format unknown. + * @return ECC_KEY_SIZE_E when key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeEd25519(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType, + int* keySize) +{ + int ret; + word32 idx; + /* make sure Ed25519 key can be used */ +#ifdef WOLFSSL_SMALL_STACK + ed25519_key* key; +#else + ed25519_key key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate an Ed25519 key to parse into. */ + key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, + DYNAMIC_TYPE_ED25519); + if (key == NULL) + return MEMORY_E; +#endif + + /* Initialize Ed25519 key. */ + ret = wc_ed25519_init_ex(key, heap, devId); + if (ret == 0) { + /* Decode as an Ed25519 private key. */ + idx = 0; + ret = wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + /* If that didn't work then maybe a public key if device ID or callback. + */ + if ((ret != 0) && ((devId != INVALID_DEVID) || + WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) { + /* Decode as an Ed25519 public key. */ + idx = 0; + ret = wc_Ed25519PublicKeyDecode(der->buffer, &idx, key, + der->length); + } + #endif + if (ret == 0) { + /* Get the minimum ECC key size from SSL or SSL context object. */ + int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + + /* Format is known. */ + *keyFormat = ED25519k; + *keyType = ed25519_sa_algo; + *keySize = ED25519_KEY_SIZE; + + /* Check that the size of the ECC key is enough. */ + if (ED25519_KEY_SIZE < minKeySz) { + WOLFSSL_MSG("ED25519 private key too small"); + ret = ECC_KEY_SIZE_E; + } + if (ssl != NULL) { +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && !defined(NO_ED25519_CLIENT_AUTH) + /* Ed25519 requires caching enabled for tracking message + * hash used in EdDSA_Update for signing */ + ssl->options.cacheMessages = 1; +#endif + } + } + /* Not an Ed25519 key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not an Ed25519 key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + /* Free dynamically allocated data in key. */ + wc_ed25519_free(key); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of allocated key. */ + XFREE(key, heap, DYNAMIC_TYPE_ED25519); +#endif + return ret; +} +#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ + +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) +/* See if DER data is an Ed448 private key. + * + * Checks size meets minimum ECC key size. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not an Ed448 key and format unknown. + * @return ECC_KEY_SIZE_E when key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeEd448(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType, + int* keySize) +{ + int ret; + word32 idx; + /* make sure Ed448 key can be used */ +#ifdef WOLFSSL_SMALL_STACK + ed448_key* key = NULL; +#else + ed448_key key[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate an Ed448 key to parse into. */ + key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448); + if (key == NULL) + return MEMORY_E; +#endif + + /* Initialize Ed448 key. */ + ret = wc_ed448_init_ex(key, heap, devId); + if (ret == 0) { + /* Decode as an Ed448 private key. */ + idx = 0; + ret = wc_Ed448PrivateKeyDecode(der->buffer, &idx, key, der->length); + #ifdef WOLF_PRIVATE_KEY_ID + /* If that didn't work then maybe a public key if device ID or callback. + */ + if ((ret != 0) && ((devId != INVALID_DEVID) || + WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) { + /* Decode as an Ed448 public key. */ + idx = 0; + ret = wc_Ed448PublicKeyDecode(der->buffer, &idx, key, der->length); + } + #endif + if (ret == 0) { + /* Get the minimum ECC key size from SSL or SSL context object. */ + int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + + /* Format is known. */ + *keyFormat = ED448k; + *keyType = ed448_sa_algo; + *keySize = ED448_KEY_SIZE; + + /* Check that the size of the ECC key is enough. */ + if (ED448_KEY_SIZE < minKeySz) { + WOLFSSL_MSG("ED448 private key too small"); + ret = ECC_KEY_SIZE_E; + } + if (ssl != NULL) { + /* Ed448 requires caching enabled for tracking message + * hash used in EdDSA_Update for signing */ + ssl->options.cacheMessages = 1; + } + } + /* Not an Ed448 key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not an Ed448 key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + /* Free dynamically allocated data in key. */ + wc_ed448_free(key); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of allocated key. */ + XFREE(key, heap, DYNAMIC_TYPE_ED448); +#endif + return ret; +} +#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ + +#if defined(HAVE_FALCON) +/* See if DER data is an Falcon private key. + * + * Checks size meets minimum Falcon key size. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not an Falcon key and format unknown. + * @return FALCON_KEY_SIZE_E when key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize) +{ + int ret; + falcon_key* key; + + /* Allocate a Falcon key to parse into. */ + key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, DYNAMIC_TYPE_FALCON); + if (key == NULL) { + return MEMORY_E; + } + + /* Initialize Falcon key. */ + ret = wc_falcon_init(key); + if (ret == 0) { + /* Set up key to parse the format specified. */ + if (*keyFormat == FALCON_LEVEL1k) { + ret = wc_falcon_set_level(key, 1); + } + else if (*keyFormat == FALCON_LEVEL5k) { + ret = wc_falcon_set_level(key, 5); + } + else { + /* What if *keyformat is 0? We might want to do something more + * graceful here. */ + /* TODO: get the size of the private key for different formats and + * compare with DER length. */ + wc_falcon_free(key); + ret = ALGO_ID_E; + } + } + + if (ret == 0) { + /* Decode as a Falcon private key. */ + ret = wc_falcon_import_private_only(der->buffer, der->length, key); + if (ret == 0) { + /* Get the minimum Falcon key size from SSL or SSL context object. + */ + int minKeySz = ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz; + + /* Format is known. */ + if (*keyFormat == FALCON_LEVEL1k) { + *keyType = falcon_level1_sa_algo; + *keySize = FALCON_LEVEL1_KEY_SIZE; + } + else { + *keyType = falcon_level5_sa_algo; + *keySize = FALCON_LEVEL5_KEY_SIZE; + } + + /* Check that the size of the Falcon key is enough. */ + if (*keySize < minKeySz) { + WOLFSSL_MSG("Falcon private key too small"); + ret = FALCON_KEY_SIZE_E; + } + } + /* Not a Falcon key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not a Falcon key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + /* Free dynamically allocated data in key. */ + wc_falcon_free(key); + } + + /* Dispose of allocated key. */ + XFREE(key, heap, DYNAMIC_TYPE_FALCON); + return ret; +} +#endif + +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_ASN1) +/* See if DER data is an Dilithium private key. + * + * Checks size meets minimum Falcon key size. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] devId Device identifier. + * @param [out] keyType Type of key. + * @param [out] keySize Size of key. + * @return 0 on success or not a Dilithium key and format unknown. + * @return DILITHIUM_KEY_SIZE_E when key size doesn't meet minimum required. + */ +static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize) +{ + int ret; + word32 idx; + dilithium_key* key; + + /* Allocate a Dilithium key to parse into. */ + key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap, + DYNAMIC_TYPE_DILITHIUM); + if (key == NULL) { + return MEMORY_E; + } + + /* Initialize Dilithium key. */ + ret = wc_dilithium_init(key); + if (ret == 0) { + /* Set up key to parse the format specified. */ + if (*keyFormat == DILITHIUM_LEVEL2k) { + ret = wc_dilithium_set_level(key, 2); + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + ret = wc_dilithium_set_level(key, 3); + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + ret = wc_dilithium_set_level(key, 5); + } + else { + /* What if *keyformat is 0? We might want to do something more + * graceful here. */ + /* TODO: get the size of the private key for different formats and + * compare with DER length. */ + wc_dilithium_free(key); + ret = ALGO_ID_E; + } + } + + if (ret == 0) { + /* Decode as a Dilithium private key. */ + idx = 0; + ret = wc_Dilithium_PrivateKeyDecode(der->buffer, &idx, key, der->length); + if (ret == 0) { + /* Get the minimum Dilithium key size from SSL or SSL context + * object. */ + int minKeySz = ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz; + + /* Format is known. */ + if (*keyFormat == DILITHIUM_LEVEL2k) { + *keyType = dilithium_level2_sa_algo; + *keySize = DILITHIUM_LEVEL2_KEY_SIZE; + } + else if (*keyFormat == DILITHIUM_LEVEL3k) { + *keyType = dilithium_level3_sa_algo; + *keySize = DILITHIUM_LEVEL3_KEY_SIZE; + } + else if (*keyFormat == DILITHIUM_LEVEL5k) { + *keyType = dilithium_level5_sa_algo; + *keySize = DILITHIUM_LEVEL5_KEY_SIZE; + } + + /* Check that the size of the Dilithium key is enough. */ + if (*keySize < minKeySz) { + WOLFSSL_MSG("Dilithium private key too small"); + ret = DILITHIUM_KEY_SIZE_E; + } + } + /* Not a Dilithium key but check whether we know what it is. */ + else if (*keyFormat == 0) { + WOLFSSL_MSG("Not a Dilithium key"); + /* Format unknown so keep trying. */ + ret = 0; + } + + /* Free dynamically allocated data in key. */ + wc_dilithium_free(key); + } + + /* Dispose of allocated key. */ + XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM); + return ret; +} +#endif /* HAVE_DILITHIUM */ + +/* Try to decode DER data is a known private key. + * + * Checks size meets minimum for key type. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in, out] keyFormat On in, expected format. 0 means unknown. + * @param [in] heap Dynamic memory allocation hint. + * @param [out] type Type of key: + * PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE. + * @return 0 on success. + * @return BAD_FUNC_ARG when der or keyFormat is NULL. + * @return BAD_FUNC_ARG when ctx and ssl are NULL. + * @return WOLFSSL_BAD_FILE when unable to identify the key format. + */ +static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int* keyFormat, void* heap, int type) +{ + int ret = 0; + int devId = wolfSSL_CTX_GetDevId(ctx, ssl); + byte* keyType = NULL; + int* keySz = NULL; + + (void)heap; + (void)devId; + (void)type; + + /* Validate parameters. */ + if ((der == NULL) || (keyFormat == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Must have an SSL context or SSL object to use. */ + if ((ret == 0) && (ctx == NULL) && (ssl == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Determine where to put key type and size in SSL or context object. */ + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (type == ALT_PRIVATEKEY_TYPE) { + if (ssl != NULL) { + keyType = &ssl->buffers.altKeyType; + keySz = &ssl->buffers.altKeySz; + } + else { + keyType = &ctx->altPrivateKeyType; + keySz = &ctx->altPrivateKeySz; + } + } + else + #endif + /* Type is PRIVATEKEY_TYPE. */ + if (ssl != NULL) { + keyType = &ssl->buffers.keyType; + keySz = &ssl->buffers.keySz; + } + else { + keyType = &ctx->privateKeyType; + keySz = &ctx->privateKeySz; + } + } + +#ifndef NO_RSA + /* Try RSA if key format is RSA or yet unknown. */ + if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == RSAk))) { +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION > 2)) + ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keyFormat, devId, + keyType, keySz); +#else + ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keyFormat, heap, devId, + keyType, keySz); +#endif + } +#endif +#ifdef HAVE_ECC + /* Try ECC if key format is ECDSA or SM2, or yet unknown. */ + if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == ECDSAk) + #ifdef WOLFSSL_SM2 + || (*keyFormat == SM2k) + #endif + )) { + ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keyFormat, heap, devId, + keyType, keySz); + } +#endif /* HAVE_ECC */ +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) + /* Try Ed25519 if key format is Ed25519 or yet unknown. */ + if ((ret == 0) && ((*keyFormat == 0 || *keyFormat == ED25519k))) { + ret = ProcessBufferTryDecodeEd25519(ctx, ssl, der, keyFormat, heap, + devId, keyType, keySz); + } +#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) + /* Try Ed448 if key format is Ed448 or yet unknown. */ + if ((ret == 0) && ((*keyFormat == 0 || *keyFormat == ED448k))) { + ret = ProcessBufferTryDecodeEd448(ctx, ssl, der, keyFormat, heap, devId, + keyType, keySz); + } +#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ +#if defined(HAVE_FALCON) + /* Try Falcon if key format is Falcon level 1k or 5k or yet unknown. */ + if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) || + (*keyFormat == FALCON_LEVEL5k))) { + ret = ProcessBufferTryDecodeFalcon(ctx, ssl, der, keyFormat, heap, + keyType, keySz); + } +#endif /* HAVE_FALCON */ +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_ASN1) + /* Try Falcon if key format is Dilithium level 2k, 3k or 5k or yet unknown. + */ + if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == DILITHIUM_LEVEL2k) || + (*keyFormat == DILITHIUM_LEVEL3k) || + (*keyFormat == DILITHIUM_LEVEL5k))) { + ret = ProcessBufferTryDecodeDilithium(ctx, ssl, der, keyFormat, heap, + keyType, keySz); + } +#endif /* HAVE_DILITHIUM */ + + /* Check we know the format. */ + if ((ret == 0) && (*keyFormat == 0)) { + WOLFSSL_MSG("Not a supported key type"); + /* Not supported key format. */ + ret = WOLFSSL_BAD_FILE; + } + + return ret; +} + +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) +/* Decrypt PKCS#8 private key. + * + * @param [in] info Encryption information. + * @param [in] der DER encoded data. + * @param [in] heap Dynamic memory allocation hint. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int ProcessBufferPrivPkcs8Dec(EncryptedInfo* info, DerBuffer* der, + void* heap) +{ + int ret = 0; + word32 algId; + int passwordSz = NAME_SZ; +#ifndef WOLFSSL_SMALL_STACK + char password[NAME_SZ]; +#else + char* password; +#endif + + (void)heap; +#ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for password. */ + password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING); + if (password == NULL) { + ret = MEMORY_E; + } +#endif + + if (ret == 0) { + /* Get password. */ + ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ, + info->passwd_userdata); + } + if (ret >= 0) { + /* Returned value is password size. */ + passwordSz = ret; + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("ProcessBuffer password", password, passwordSz); + #endif + + /* Decrypt PKCS#8 private key inline and get algorithm id. */ + ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz, + &algId); + } + if (ret >= 0) { + /* Zero out encrypted data not overwritten. */ + ForceZero(der->buffer + ret, der->length - ret); + /* Set decrypted data length. */ + der->length = (word32)ret; + } + + /* Ensure password is zeroized. */ + ForceZero(password, (word32)passwordSz); +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of password memory. */ + XFREE(password, heap, DYNAMIC_TYPE_STRING); +#elif defined(WOLFSSL_CHECK_MEM_ZERO) + wc_MemZero_Check(password, NAME_SZ); +#endif + return ret; +} +#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + +/* Put the DER into the SSL or SSL context object. + * + * Precondition: ctx or ssl is not NULL. + * Precondition: Must be a private key type. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @return 0 on success. + */ +static int ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer** der, int type) +{ + int ret = 0; + + (void)type; + +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (type == ALT_PRIVATEKEY_TYPE) { + /* Put in alternate private key fields of objects. */ + if (ssl != NULL) { + /* Dispose of previous key if not context's. */ + if (ssl->buffers.weOwnAltKey) { + FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif + } + ssl->buffers.altKeyId = 0; + ssl->buffers.altKeyLabel = 0; + ssl->buffers.altKeyDevId = INVALID_DEVID; + /* Store key by reference and own it. */ + ssl->buffers.altKey = *der; + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("SSL Buffers key", (*der)->buffer, (*der)->length); + #endif + ssl->buffers.weOwnAltKey = 1; + } + else if (ctx != NULL) { + /* Dispose of previous key. */ + FreeDer(&ctx->altPrivateKey); + ctx->altPrivateKeyId = 0; + ctx->altPrivateKeyLabel = 0; + ctx->altPrivateKeyDevId = INVALID_DEVID; + /* Store key by reference. */ + ctx->altPrivateKey = *der; + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length); + #endif + } + } + else +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + if (ssl != NULL) { + /* Dispose of previous key if not context's. */ + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif + } + ssl->buffers.keyId = 0; + ssl->buffers.keyLabel = 0; + ssl->buffers.keyDevId = INVALID_DEVID; + /* Store key by reference and own it. */ + ssl->buffers.key = *der; + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("SSL Buffers key", (*der)->buffer, (*der)->length); + #endif + ssl->buffers.weOwnKey = 1; + } + else if (ctx != NULL) { + /* Dispose of previous key. */ + FreeDer(&ctx->privateKey); + ctx->privateKeyId = 0; + ctx->privateKeyLabel = 0; + ctx->privateKeyDevId = INVALID_DEVID; + /* Store key by reference. */ + ctx->privateKey = *der; + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length); + #endif + } + + return ret; +} + +/* Decode private key. + * + * Precondition: ctx or ssl is not NULL. + * Precondition: Must be a private key type. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoding. + * @param [in] format Original format of data. + * @param [in] info Encryption information. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] type Type of data: + * PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE. + * @param [in] algId Algorithm id of key. + * @return 0 on success. + * @return WOLFSSL_BAD_FILE when not able to decode. + */ +static int ProcessBufferPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int format, EncryptedInfo* info, void* heap, int type, + int algId) +{ + int ret; +#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \ + defined(HAVE_PKCS8) + word32 p8AlgId = 0; +#endif + + (void)info; + (void)format; + +#ifdef HAVE_PKCS8 + /* Try and remove PKCS8 header and get algorithm id. */ + ret = ToTraditional_ex(der->buffer, der->length, &p8AlgId); + if (ret > 0) { + /* Header stripped inline. */ + der->length = (word32)ret; + algId = p8AlgId; + } +#endif + + /* Put the data into the SSL or SSL context object. */ + ret = ProcessBufferPrivKeyHandleDer(ctx, ssl, &der, type); + if (ret == 0) { + /* Try to decode the DER data. */ + ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type); + } + +#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) + /* If private key type PKCS8 header wasn't already removed (algId == 0). */ + if (((ret != 0) || (algId == 0)) && (format != WOLFSSL_FILETYPE_PEM) && + (info->passwd_cb != NULL) && (algId == 0)) { + /* Try to decrypt DER data as a PKCS#8 private key. */ + ret = ProcessBufferPrivPkcs8Dec(info, der, heap); + if (ret >= 0) { + /* Try to decode decrypted data. */ + ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type); + } + } +#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */ + +#ifdef WOLFSSL_BLIND_PRIVATE_KEY +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (type == ALT_PRIVATEKEY_TYPE) { + if (ssl != NULL) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey, + &ssl->buffers.altKeyMask); + } + else { + ret = wolfssl_priv_der_blind(NULL, ctx->altPrivateKey, + &ctx->altPrivateKeyMask); + } + } + else +#endif + if (ssl != NULL) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + ret = wolfssl_priv_der_blind(NULL, ctx->privateKey, + &ctx->privateKeyMask); + } +#endif + + /* Check if we were able to determine algorithm id. */ + if ((ret == 0) && (algId == 0)) { + #ifdef OPENSSL_EXTRA + /* Decryption password is probably wrong. */ + if (info->passwd_cb) { + EVPerr(0, EVP_R_BAD_DECRYPT); + } + #endif + WOLFSSL_ERROR(WOLFSSL_BAD_FILE); + /* Unable to decode DER data. */ + ret = WOLFSSL_BAD_FILE; + } + + return ret; +} + +/* Use the key OID to determine have options. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] keyOID OID for public/private key. + */ +static void wolfssl_set_have_from_key_oid(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + int keyOID) +{ + /* Set which private key algorithm available based on key OID. */ + switch (keyOID) { + case ECDSAk: + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) + case SM2k: + #endif + #ifdef HAVE_ED25519 + case ED25519k: + #endif + #ifdef HAVE_ED448 + case ED448k: + #endif + if (ssl != NULL) { + ssl->options.haveECC = 1; + } + else { + ctx->haveECC = 1; + } + break; + #ifndef NO_RSA + case RSAk: + #ifdef WC_RSA_PSS + case RSAPSSk: + #endif + if (ssl != NULL) { + ssl->options.haveRSA = 1; + } + else { + ctx->haveRSA = 1; + } + break; + #endif + #ifdef HAVE_FALCON + case FALCON_LEVEL1k: + case FALCON_LEVEL5k: + if (ssl != NULL) { + ssl->options.haveFalconSig = 1; + } + else { + ctx->haveFalconSig = 1; + } + break; + #endif /* HAVE_FALCON */ + #ifdef HAVE_DILITHIUM + case DILITHIUM_LEVEL2k: + case DILITHIUM_LEVEL3k: + case DILITHIUM_LEVEL5k: + if (ssl != NULL) { + ssl->options.haveDilithiumSig = 1; + } + else { + ctx->haveDilithiumSig = 1; + } + break; + #endif /* HAVE_DILITHIUM */ + default: + WOLFSSL_MSG("Cert key not supported"); + break; + } +} + +/* Set which private key algorithm we have against SSL or SSL context object. + * + * Precondition: ctx or ssl is not NULL. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] cert Decode certificate. + */ +static void ProcessBufferCertSetHave(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DecodedCert* cert) +{ + if (ssl != NULL) { + /* Reset signatures we have in SSL. */ + ssl->options.haveECDSAsig = 0; + ssl->options.haveFalconSig = 0; + ssl->options.haveDilithiumSig = 0; + } + + /* Set which signature we have based on the type in the cert. */ + switch (cert->signatureOID) { + case CTC_SHAwECDSA: + case CTC_SHA256wECDSA: + case CTC_SHA384wECDSA: + case CTC_SHA512wECDSA: + #ifdef HAVE_ED25519 + case CTC_ED25519: + #endif + #ifdef HAVE_ED448 + case CTC_ED448: + #endif + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) + case CTC_SM3wSM2: + #endif + WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature"); + if (ssl) { + ssl->options.haveECDSAsig = 1; + } + else if (ctx) { + ctx->haveECDSAsig = 1; + } + break; + #ifdef HAVE_FALCON + case CTC_FALCON_LEVEL1: + case CTC_FALCON_LEVEL5: + WOLFSSL_MSG("Falcon cert signature"); + if (ssl) { + ssl->options.haveFalconSig = 1; + } + else if (ctx) { + ctx->haveFalconSig = 1; + } + break; + #endif + #ifdef HAVE_DILITHIUM + case CTC_DILITHIUM_LEVEL2: + case CTC_DILITHIUM_LEVEL3: + case CTC_DILITHIUM_LEVEL5: + WOLFSSL_MSG("Dilithium cert signature"); + if (ssl) { + ssl->options.haveDilithiumSig = 1; + } + else if (ctx) { + ctx->haveDilithiumSig = 1; + } + break; + #endif + default: + WOLFSSL_MSG("Cert signature not supported"); + break; + } + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || !defined(NO_RSA) + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) + /* Set the private key curve OID. */ + if (ssl != NULL) { + ssl->pkCurveOID = cert->pkCurveOID; + } + else if (ctx) { + ctx->pkCurveOID = cert->pkCurveOID; + } + #endif +#ifndef WC_STRICT_SIG + wolfssl_set_have_from_key_oid(ctx, ssl, cert->keyOID); +#else + /* Set whether ECC is available based on signature available. */ + if (ssl != NULL) { + ssl->options.haveECC = ssl->options.haveECDSAsig; + } + else if (ctx) { + ctx->haveECC = ctx->haveECDSAsig; + } +#endif /* !WC_STRICT_SIG */ +#endif +} + +/* Check key size is valid. + * + * Precondition: ctx or ssl is not NULL. + * + * @param [in] min Minimum key size. + * @param [in] max Maximum key size. + * @param [in] keySz Key size. + * @param [in] err Error value to return when key size is invalid. + * @return 0 on success. + * @return err when verifying and min is less than 0 or key size is invalid. + */ +#define CHECK_KEY_SZ(min, max, keySz, err) \ + (((min) < 0) || ((keySz) < (min)) || ((keySz) > (max))) ? (err) : 0 + +/* Check public key in certificate. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] cert Certificate object. + * @return 0 on success. + * @return Non-zero when an error occurred. + */ +static int ProcessBufferCertPublicKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DecodedCert* cert, int checkKeySz) +{ + int ret = 0; + byte keyType = 0; + int keySz = 0; +#ifndef NO_RSA + word32 idx; +#endif + + /* Get key size and check unless not verifying. */ + switch (cert->keyOID) { +#ifndef NO_RSA + #ifdef WC_RSA_PSS + case RSAPSSk: + #endif + case RSAk: + keyType = rsa_sa_algo; + /* Determine RSA key size by parsing public key */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx, + cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL); + if ((ret == 0) && checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minRsaKeySz : + ctx->minRsaKeySz, RSA_MAX_SIZE / 8, keySz, RSA_KEY_SIZE_E); + } + break; +#endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + keyType = ecc_dsa_sa_algo; + /* Determine ECC key size based on curve */ + #ifdef WOLFSSL_CUSTOM_CURVES + if ((cert->pkCurveOID == 0) && (cert->pkCurveSize != 0)) { + keySz = cert->pkCurveSize; + } + else + #endif + { + keySz = wc_ecc_get_curve_size_from_id(wc_ecc_get_oid( + cert->pkCurveOID, NULL, NULL)); + } + + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz, + ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ECC */ + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) + case SM2k: + keyType = sm2_sa_algo; + /* Determine ECC key size based on curve */ + keySz = WOLFSSL_SM2_KEY_BITS / 8; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz, + ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED25519 + case ED25519k: + keyType = ed25519_sa_algo; + /* ED25519 is fixed key size */ + keySz = ED25519_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, ED25519_KEY_SIZE, keySz, ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + keyType = ed448_sa_algo; + /* ED448 is fixed key size */ + keySz = ED448_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, ED448_KEY_SIZE, keySz, ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ED448 */ + #if defined(HAVE_FALCON) + case FALCON_LEVEL1k: + keyType = falcon_level1_sa_algo; + /* Falcon is fixed key size */ + keySz = FALCON_LEVEL1_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz, + FALCON_KEY_SIZE_E); + } + break; + case FALCON_LEVEL5k: + keyType = falcon_level5_sa_algo; + /* Falcon is fixed key size */ + keySz = FALCON_LEVEL5_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz, + FALCON_KEY_SIZE_E); + } + break; + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + keyType = dilithium_level2_sa_algo; + /* Dilithium is fixed key size */ + keySz = DILITHIUM_LEVEL2_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz, + DILITHIUM_KEY_SIZE_E); + } + break; + case DILITHIUM_LEVEL3k: + keyType = dilithium_level3_sa_algo; + /* Dilithium is fixed key size */ + keySz = DILITHIUM_LEVEL3_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz, + DILITHIUM_KEY_SIZE_E); + } + break; + case DILITHIUM_LEVEL5k: + keyType = dilithium_level5_sa_algo; + /* Dilithium is fixed key size */ + keySz = DILITHIUM_LEVEL5_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz, + DILITHIUM_KEY_SIZE_E); + } + break; + #endif /* HAVE_DILITHIUM */ + + default: + WOLFSSL_MSG("No key size check done on public key in certificate"); + break; + } + + /* Store the type and key size as there may not be a private key set. */ + if (ssl != NULL) { + ssl->buffers.keyType = keyType; + ssl->buffers.keySz = keySz; + } + else { + ctx->privateKeyType = keyType; + ctx->privateKeySz = keySz; + } + + return ret; +} + +#ifdef WOLFSSL_DUAL_ALG_CERTS +static int ProcessBufferCertAltPublicKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DecodedCert* cert, int checkKeySz) +{ + int ret = 0; + void* heap = WOLFSSL_HEAP(ctx, ssl); + byte keyType = 0; + int keySz = 0; +#ifndef NO_RSA + word32 idx; +#endif + + /* Check alternative key size of cert. */ + switch (cert->sapkiOID) { + /* No OID set. */ + case 0: + if (cert->sapkiLen != 0) { + /* Have the alternative key data but no OID. */ + ret = NOT_COMPILED_IN; + } + break; + +#ifndef NO_RSA + #ifdef WC_RSA_PSS + case RSAPSSk: + #endif + case RSAk: + keyType = rsa_sa_algo; + /* Determine RSA key size by parsing public key */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(cert->sapkiDer, &idx, + cert->sapkiLen, NULL, (word32*)&keySz, NULL, NULL); + if ((ret == 0) && checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minRsaKeySz : + ctx->minRsaKeySz, RSA_MAX_SIZE / 8, keySz, RSA_KEY_SIZE_E); + } + break; +#endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + #ifdef WOLFSSL_SMALL_STACK + ecc_key* temp_key = NULL; + #else + ecc_key temp_key[1]; + #endif + keyType = ecc_dsa_sa_algo; + + #ifdef WOLFSSL_SMALL_STACK + temp_key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, + DYNAMIC_TYPE_ECC); + if (temp_key == NULL) { + ret = MEMORY_E; + } + #endif + + /* Determine ECC key size. We have to decode the sapki for + * that. */ + if (ret == 0) { + ret = wc_ecc_init_ex(temp_key, heap, INVALID_DEVID); + if (ret == 0) { + idx = 0; + ret = wc_EccPublicKeyDecode(cert->sapkiDer, &idx, temp_key, + cert->sapkiLen); + if (ret == 0) { + keySz = wc_ecc_size(temp_key); + } + wc_ecc_free(temp_key); + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(temp_key, heap, DYNAMIC_TYPE_ECC); + #endif + + if ((ret == 0) && checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz, + ECC_KEY_SIZE_E); + } + break; + } + #endif /* HAVE_ECC */ + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) + case SM2k: + keyType = sm2_sa_algo; + /* Determine ECC key size based on curve */ + keySz = WOLFSSL_SM2_KEY_BITS / 8; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz, + ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED25519 + case ED25519k: + keyType = ed25519_sa_algo; + /* ED25519 is fixed key size */ + keySz = ED25519_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, ED25519_KEY_SIZE, keySz, ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + keyType = ed448_sa_algo; + /* ED448 is fixed key size */ + keySz = ED448_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz, ED448_KEY_SIZE, keySz, ECC_KEY_SIZE_E); + } + break; + #endif /* HAVE_ED448 */ + #if defined(HAVE_FALCON) + case FALCON_LEVEL1k: + keyType = falcon_level1_sa_algo; + /* Falcon is fixed key size */ + keySz = FALCON_LEVEL1_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz, + FALCON_KEY_SIZE_E); + } + break; + case FALCON_LEVEL5k: + keyType = falcon_level5_sa_algo; + /* Falcon is fixed key size */ + keySz = FALCON_LEVEL5_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz : + ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz, + FALCON_KEY_SIZE_E); + } + break; + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) + case DILITHIUM_LEVEL2k: + keyType = dilithium_level2_sa_algo; + /* Dilithium is fixed key size */ + keySz = DILITHIUM_LEVEL2_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz, + DILITHIUM_KEY_SIZE_E); + } + break; + case DILITHIUM_LEVEL3k: + keyType = dilithium_level3_sa_algo; + /* Dilithium is fixed key size */ + keySz = DILITHIUM_LEVEL3_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz, + DILITHIUM_KEY_SIZE_E); + } + break; + case DILITHIUM_LEVEL5k: + keyType = dilithium_level5_sa_algo; + /* Dilithium is fixed key size */ + keySz = DILITHIUM_LEVEL5_KEY_SIZE; + if (checkKeySz) { + ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz : + ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz, + DILITHIUM_KEY_SIZE_E); + } + break; + #endif /* HAVE_DILITHIUM */ + + default: + /* In this case, there was an OID that we didn't recognize. + * This is an error. Use not compiled in because likely the + * given algorithm was not enabled. */ + ret = NOT_COMPILED_IN; + WOLFSSL_MSG("No alt key size check done on certificate"); + break; + } + + if (ssl != NULL) { + ssl->buffers.altKeyType = (byte)keyType; + ssl->buffers.altKeySz = keySz; + } + else if (ctx != NULL) { + ctx->altPrivateKeyType = (byte)keyType; + ctx->altPrivateKeySz = keySz; + } + + return ret; +} +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + +/* Parse the certificate and pull out information for TLS handshake. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoded X509 certificate. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return WOLFSSL_BAD_FILE when decoding certificate fails. + */ +static int ProcessBufferCert(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der) +{ + int ret = 0; + void* heap = WOLFSSL_HEAP(ctx, ssl); +#if defined(HAVE_RPK) + RpkState* rpkState = ssl ? &ssl->options.rpkState : &ctx->rpkState; +#endif +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; +#else + DecodedCert cert[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for certificate to be decoded into. */ + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, DYNAMIC_TYPE_DCERT); + if (cert == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) +#endif + { + /* Get device id from SSL context or SSL object. */ + int devId = wolfSSL_CTX_GetDevId(ctx, ssl); + + WOLFSSL_MSG("Checking cert signature type"); + /* Initialize certificate object. */ + InitDecodedCert_ex(cert, der->buffer, der->length, heap, devId); + + /* Decode up to and including public key. */ + if (DecodeToKey(cert, 0) < 0) { + WOLFSSL_MSG("Decode to key failed"); + ret = WOLFSSL_BAD_FILE; + } + if (ret == 0) { + int checkKeySz = 1; + + #if defined(HAVE_RPK) + /* Store whether the crtificate is a raw public key. */ + rpkState->isRPKLoaded = cert->isRPK; + #endif /* HAVE_RPK */ + + /* Set which private key algorithm we have. */ + ProcessBufferCertSetHave(ctx, ssl, cert); + + /* Don't check if verification is disabled for SSL. */ + if ((ssl != NULL) && ssl->options.verifyNone) { + checkKeySz = 0; + } + /* Don't check if no SSL object verification is disabled for SSL + * context. */ + else if ((ssl == NULL) && ctx->verifyNone) { + checkKeySz = 0; + } + + /* Check public key size. */ + ret = ProcessBufferCertPublicKey(ctx, ssl, cert, checkKeySz); + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ret == 0) { + ret = ProcessBufferCertAltPublicKey(ctx, ssl, cert, checkKeySz); + } + #endif + } + } + + /* Dispose of dynamic memory in certificate object. */ + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of certificate object. */ + XFREE(cert, heap, DYNAMIC_TYPE_DCERT); +#endif + return ret; +} + +/* Handle storing the DER encoding of the certificate. + * + * Do not free der outside of this function. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] der DER encoded certificate. + * @param [in] type Type of data: + * CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE. + * @param [in] verify What verification to do. + * @return 0 on success. + * @return BAD_FUNC_ARG when type is CA_TYPE and ctx is NULL. + * @return WOLFSSL_BAD_CERTTYPE when data type is not supported. + */ +static int ProcessBufferCertHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + DerBuffer* der, int type, int verify) +{ + int ret = 0; + + /* CA certificate to verify with. */ + if (type == CA_TYPE) { + /* verify CA unless user set to no verify */ + ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify); + if (ret == 1) { + ret = 0; + } + } +#ifdef WOLFSSL_TRUST_PEER_CERT + /* Trusted certificate to verify peer with. */ + else if (type == TRUSTED_PEER_TYPE) { + WOLFSSL_CERT_MANAGER* cm; + + /* Get certificate manager to add certificate to. */ + if (ctx != NULL) { + cm = ctx->cm; + } + else { + SSL_CM_WARNING(ssl); + cm = SSL_CM(ssl); + } + /* Add certificate as a trusted peer. */ + ret = AddTrustedPeer(cm, &der, verify); + if (ret != 1) { + WOLFSSL_MSG("Error adding trusted peer"); + } + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ + /* Leaf certificate - our certificate. */ + else if (type == CERT_TYPE) { + if (ssl != NULL) { + /* Free previous certificate if we own it. */ + if (ssl->buffers.weOwnCert) { + FreeDer(&ssl->buffers.certificate); + #ifdef KEEP_OUR_CERT + /* Dispose of X509 version of certificate. */ + wolfSSL_X509_free(ssl->ourCert); + ssl->ourCert = NULL; + #endif + } + /* Store certificate as ours. */ + ssl->buffers.certificate = der; + #ifdef KEEP_OUR_CERT + ssl->keepCert = 1; /* hold cert for ssl lifetime */ + #endif + /* We have to free the certificate buffer. */ + ssl->buffers.weOwnCert = 1; + /* ourCert is created on demand. */ + } + else if (ctx != NULL) { + /* Free previous certificate. */ + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + #ifdef KEEP_OUR_CERT + /* Dispose of X509 version of certificate if we own it. */ + if (ctx->ownOurCert) { + wolfSSL_X509_free(ctx->ourCert); + } + ctx->ourCert = NULL; + #endif + /* Store certificate as ours. */ + ctx->certificate = der; + /* ourCert is created on demand. */ + } + } + else { + /* Dispose of DER buffer. */ + FreeDer(&der); + /* Not a certificate type supported. */ + ret = WOLFSSL_BAD_CERTTYPE; + } + + return ret; +} + +/* Process certificate based on type. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] buff Buffer holding original data. + * @param [in] sz Size of data in buffer. + * @param [in] der DER encoding of certificate. + * @param [in] format Format of data. + * @param [in] type Type of data: + * CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE. + * @param [in] verify What verification to do. + * @return 0 on success. + * @return WOLFSSL_FATAL_ERROR on failure. + */ +static int ProcessBufferCertTypes(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const unsigned char* buff, long sz, DerBuffer* der, int format, int type, + int verify) +{ + int ret; + + (void)buff; + (void)sz; + (void)format; + + ret = ProcessBufferCertHandleDer(ctx, ssl, der, type, verify); + if ((ret == 0) && (type == CERT_TYPE)) { + /* Process leaf certificate. */ + ret = ProcessBufferCert(ctx, ssl, der); + } +#if !defined(NO_WOLFSSL_CM_VERIFY) && (!defined(NO_WOLFSSL_CLIENT) || \ + !defined(WOLFSSL_NO_CLIENT_AUTH)) + /* Hand bad CA or user certificate to callback. */ + if ((ret < 0) && ((type == CA_TYPE) || (type == CERT_TYPE))) { + /* Check for verification callback that may override error. */ + if ((ctx != NULL) && (ctx->cm != NULL) && + (ctx->cm->verifyCallback != NULL)) { + /* Verify and use callback. */ + ret = CM_VerifyBuffer_ex(ctx->cm, buff, sz, format, ret); + /* Convert error. */ + if (ret == 0) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 1) { + ret = 0; + } + } + } +#endif /* NO_WOLFSSL_CM_VERIFY */ + + return ret; +} + +/* Reset the cipher suites based on updated private key or certificate. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] type Type of certificate. + * @return 0 on success. + * @return WOLFSSL_FATAL_ERROR when allocation fails. + */ +static int ProcessBufferResetSuites(WOLFSSL_CTX* ctx, WOLFSSL* ssl, int type) +{ + int ret = 0; + + /* Reset suites of SSL object. */ + if (ssl != NULL) { + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Allocate memory for suites. */ + if (AllocateSuites(ssl) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + else { + /* Determine cipher suites based on what we have. */ + InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz, + WOLFSSL_HAVE_RSA, SSL_HAVE_PSK(ssl), ssl->options.haveDH, + ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, + ssl->options.haveStaticECC, ssl->options.haveFalconSig, + ssl->options.haveDilithiumSig, ssl->options.useAnon, TRUE, + ssl->options.side); + } + } + } + /* Reset suites of SSL context object. */ + else if ((type == CERT_TYPE) && (ctx->method->side == WOLFSSL_SERVER_END)) { + /* Allocate memory for suites. */ + if (AllocateCtxSuites(ctx) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + else { + /* Determine cipher suites based on what we have. */ + InitSuites(ctx->suites, ctx->method->version, ctx->privateKeySz, + WOLFSSL_HAVE_RSA, CTX_HAVE_PSK(ctx), ctx->haveDH, + ctx->haveECDSAsig, ctx->haveECC, TRUE, ctx->haveStaticECC, + ctx->haveFalconSig, ctx->haveDilithiumSig, CTX_USE_ANON(ctx), + TRUE, ctx->method->side); + } + } + + return ret; +} + +#ifndef WOLFSSL_DUAL_ALG_CERTS + /* Determine whether the type is for a private key. */ + #define IS_PRIVKEY_TYPE(type) ((type) == PRIVATEKEY_TYPE) +#else + /* Determine whether the type is for a private key. */ + #define IS_PRIVKEY_TYPE(type) (((type) == PRIVATEKEY_TYPE) || \ + ((type) == ALT_PRIVATEKEY_TYPE)) +#endif + +/* Process a buffer of data. + * + * Data type is a private key or a certificate. + * The format can be ASN.1 (DER) or PEM. + * + * @param [in, out] ctx SSL context object. + * @param [in] buff Buffer holding data. + * @param [in] sz Size of data in buffer. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @param [in] type Type of data: + * CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE, + * PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE. + * @param [in, out] ssl SSL object. + * @param [out] used Number of bytes consumed. + * @param [in[ userChain Whether this certificate is for user's chain. + * @param [in] verify How to verify certificate. + * @return 1 on success. + * @return Less than 1 on failure. + */ +int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz, + int format, int type, WOLFSSL* ssl, long* used, int userChain, int verify) +{ + DerBuffer* der = NULL; + int ret = 0; + void* heap = WOLFSSL_HEAP(ctx, ssl); +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + int algId = 0; + + WOLFSSL_ENTER("ProcessBuffer"); + + /* Check data format is supported. */ + if ((format != WOLFSSL_FILETYPE_ASN1) && (format != WOLFSSL_FILETYPE_PEM)) { + ret = WOLFSSL_BAD_FILETYPE; + } + /* Need an object to store certificate into. */ + if ((ret == 0) && (ctx == NULL) && (ssl == NULL)) { + ret = BAD_FUNC_ARG; + } + /* CA certificates go into the SSL context object. */ + if ((ret == 0) && (ctx == NULL) && (type == CA_TYPE)) { + ret = BAD_FUNC_ARG; + } + /* This API does not handle CHAIN_CERT_TYPE */ + if ((ret == 0) && (type == CHAIN_CERT_TYPE)) { + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + if (ret == 0) { + /* Allocate memory for encryption information. */ + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + ret = MEMORY_E; + } + } +#endif + if (ret == 0) { + /* Initialize encryption information. */ + XMEMSET(info, 0, sizeof(EncryptedInfo)); + #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED) + if (ctx != NULL) { + info->passwd_cb = ctx->passwd_cb; + info->passwd_userdata = ctx->passwd_userdata; + } + #endif + + /* Get the DER data for a private key or certificate. */ + ret = DataToDerBuffer(buff, (word32)sz, format, type, info, heap, &der, + &algId); + if (used != NULL) { + /* Update to amount used/consumed. */ + *used = info->consumed; + } + #ifdef WOLFSSL_SMALL_STACK + if (ret != 0) { + /* Info no longer needed as loading failed. */ + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + } + #endif + } + + if ((ret == 0) && IS_PRIVKEY_TYPE(type)) { + /* Process the private key. */ + ret = ProcessBufferPrivateKey(ctx, ssl, der, format, info, heap, type, + algId); + #ifdef WOLFSSL_SMALL_STACK + /* Info no longer needed - keep max memory usage down. */ + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + } + else if (ret == 0) { + /* Processing a cerificate. */ + if (userChain) { + /* Take original buffer and add to user chain to send in TLS + * handshake. */ + ret = ProcessUserChain(ctx, ssl, buff, sz, format, type, used, info, + verify); + /* Additional chain is optional */ + if (ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) { + unsigned long pemErr = 0; + CLEAR_ASN_NO_PEM_HEADER_ERROR(pemErr); + ret = 0; + } + } + + #ifdef WOLFSSL_SMALL_STACK + /* Info no longer needed - keep max memory usage down. */ + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + + if (ret == 0) { + /* Process the different types of certificates. */ + ret = ProcessBufferCertTypes(ctx, ssl, buff, sz, der, format, type, + verify); + } + else { + FreeDer(&der); + } + } + + /* Reset suites if this is a private key or user certificate. */ + if ((ret == 0) && ((type == PRIVATEKEY_TYPE) || (type == CERT_TYPE))) { + ret = ProcessBufferResetSuites(ctx, ssl, type); + } + + /* Convert return code. */ + if (ret == 0) { + ret = 1; + } + else if (ret == WOLFSSL_FATAL_ERROR) { + ret = 0; + } + WOLFSSL_LEAVE("ProcessBuffer", ret); + return ret; +} + +#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL) +/* Try to parse data as a PEM CRL. + * + * @param [in] ctx SSL context object. + * @param [in] buff Buffer containing potential CRL in PEM format. + * @param [in] sz Amount of data in buffer remaining. + * @param [out] consumed Number of bytes in buffer was the CRL. + * @return 0 on success. + */ +static int ProcessChainBufferCRL(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, long* consumed) +{ + int ret; + DerBuffer* der = NULL; + EncryptedInfo info; + + WOLFSSL_MSG("Trying a CRL"); + ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, NULL); + if (ret == 0) { + WOLFSSL_MSG(" Processed a CRL"); + wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, der->length, + WOLFSSL_FILETYPE_ASN1); + FreeDer(&der); + *consumed = info.consumed; + } + + return ret; +} +#endif + +/* Process all chain certificates (and CRLs) in the PEM data. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] buff Buffer containing PEM data. + * @param [in] sz Size of data in buffer. + * @param [in] type Type of data. + * @param [in] verify How to verify certificate. + * @return 1 on success. + * @return 0 on failure. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int ProcessChainBuffer(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const unsigned char* buff, long sz, int type, int verify) +{ + int ret = 0; + long used = 0; + int gotOne = 0; + + WOLFSSL_MSG("Processing CA PEM file"); + /* Keep processing file while no errors and data to parse. */ + while ((ret >= 0) && (used < sz)) { + long consumed = 0; + + /* Process the buffer. */ + ret = ProcessBuffer(ctx, buff + used, sz - used, WOLFSSL_FILETYPE_PEM, + type, ssl, &consumed, 0, verify); + /* Memory allocation failure is fatal. */ + if (ret == WC_NO_ERR_TRACE(MEMORY_E)) { + gotOne = 0; + } + /* Other error parsing. */ + else if (ret < 0) { +#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL) + /* Try parsing a CRL. */ + if (ProcessChainBufferCRL(ctx, buff + used, sz - used, + &consumed) == 0) { + ret = 0; + } + else +#endif + /* Check whether we made progress. */ + if (consumed > 0) { + WOLFSSL_ERROR(ret); + WOLFSSL_MSG("CA Parse failed, with progress in file."); + WOLFSSL_MSG("Search for other certs in file"); + /* Check if we have more data to parse to recover. */ + if (used + consumed < sz) { + ret = 0; + } + } + else { + /* No progress in parsing being made - stop here. */ + WOLFSSL_MSG("CA Parse failed, no progress in file."); + WOLFSSL_MSG("Do not continue search for other certs in file"); + } + } + else { + /* Got a certificate out. */ + WOLFSSL_MSG(" Processed a CA"); + gotOne = 1; + } + /* Update used count. */ + used += consumed; + } + + /* May have other unparsable data but did we get a certificate? */ + if (gotOne) { + WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK"); + ret = 1; + } + return ret; +} + + +/* Get verify settings for AddCA from SSL context. */ +#define GET_VERIFY_SETTING_CTX(ctx) \ + ((ctx) && (ctx)->verifyNone ? NO_VERIFY : VERIFY) +/* Get verify settings for AddCA from SSL. */ +#define GET_VERIFY_SETTING_SSL(ssl) \ + ((ssl)->options.verifyNone ? NO_VERIFY : VERIFY) + +#ifndef NO_FILESYSTEM + +/* Process data from a file as private keys, CRL or certificates. + * + * @param [in, out] ctx SSL context object. + * @param [in] fname Name of file to read. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @param [in] type Type of data: + * CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE, + * PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE. + * @param [in, out] ssl SSL object. + * @param [in] userChain Whether file contains chain of certificates. + * @param [in, out] crl CRL object to load data into. + * @param [in] verify How to verify certificates. + * @return 1 on success. + * @return WOLFSSL_BAD_FILE when reading the file fails. + * @return WOLFSSL_BAD_CERTTYPE when unable to detect certificate type. + */ +int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, + WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify) +{ + int ret = 0; +#ifndef WOLFSSL_SMALL_STACK + byte stackBuffer[FILE_BUFFER_SIZE]; +#endif + StaticBuffer content; + long sz = 0; + void* heap = WOLFSSL_HEAP(ctx, ssl); + + (void)crl; + (void)heap; + +#ifdef WOLFSSL_SMALL_STACK + static_buffer_init(&content); +#else + static_buffer_init(&content, stackBuffer, FILE_BUFFER_SIZE); +#endif + + /* Read file into static buffer. */ + ret = wolfssl_read_file_static(fname, &content, heap, DYNAMIC_TYPE_FILE, + &sz); + if ((ret == 0) && (type == DETECT_CERT_TYPE) && + (format != WOLFSSL_FILETYPE_PEM)) { + WOLFSSL_MSG("Cannot detect certificate type when not PEM"); + ret = WOLFSSL_BAD_CERTTYPE; + } + /* Try to detect type by parsing cert header and footer. */ + if ((ret == 0) && (type == DETECT_CERT_TYPE)) { +#if !defined(NO_CODING) && !defined(WOLFSSL_NO_PEM) + const char* header = NULL; + const char* footer = NULL; + + /* Look for CA header and footer - same as CERT_TYPE. */ + if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)content.buffer, header, (word32)sz) != NULL)) { + type = CA_TYPE; + } +#ifdef HAVE_CRL + /* Look for CRL header and footer. */ + else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)content.buffer, header, (word32)sz) != NULL)) { + type = CRL_TYPE; + } +#endif + /* Look for cert header and footer - same as CA_TYPE. */ + else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && + (XSTRNSTR((char*)content.buffer, header, (word32)sz) != + NULL)) { + type = CERT_TYPE; + } + else +#endif + { + /* Not a header that we support. */ + WOLFSSL_MSG("Failed to detect certificate type"); + ret = WOLFSSL_BAD_CERTTYPE; + } + } + if (ret == 0) { + /* When CA or trusted peer and PEM - process as a chain buffer. */ + if (((type == CA_TYPE) || (type == TRUSTED_PEER_TYPE)) && + (format == WOLFSSL_FILETYPE_PEM)) { + ret = ProcessChainBuffer(ctx, ssl, content.buffer, sz, type, + verify); + } +#ifdef HAVE_CRL + else if (type == CRL_TYPE) { + /* Load the CRL. */ + ret = BufferLoadCRL(crl, content.buffer, sz, format, verify); + } +#endif +#ifdef WOLFSSL_DUAL_ALG_CERTS + else if (type == PRIVATEKEY_TYPE) { + /* When support for dual algorithm certificates is enabled, the + * private key file may contain both the primary and the + * alternative private key. Hence, we have to parse both of them. + */ + long consumed = 0; + + ret = ProcessBuffer(ctx, content.buffer, sz, format, type, ssl, + &consumed, userChain, verify); + if ((ret == 1) && (consumed < sz)) { + ret = ProcessBuffer(ctx, content.buffer + consumed, + sz - consumed, format, ALT_PRIVATEKEY_TYPE, ssl, NULL, 0, + verify); + } + } +#endif + else { + /* Load all other certificate types. */ + ret = ProcessBuffer(ctx, content.buffer, sz, format, type, ssl, + NULL, userChain, verify); + } + } + + /* Dispose of dynamically allocated data. */ + static_buffer_free(&content, heap, DYNAMIC_TYPE_FILE); + return ret; +} + +#ifndef NO_WOLFSSL_DIR +/* Load file when filename is in the path. + * + * @param [in, out] ctx SSL context object. + * @param [in] name Name of file. + * @param [in] verify How to verify a certificate. + * @param [in] flags Flags representing options for loading. + * @param [in, out] failCount Number of files that failed to load. + * @param [in, out] successCount Number of files successfully loaded. + * @return 1 on success. + * @return Not 1 when loading PEM certificate failed. + */ +static int wolfssl_ctx_load_path_file(WOLFSSL_CTX* ctx, const char* name, + int verify, int flags, int* failCount, int* successCount) +{ + int ret; + + /* Attempt to load file as a CA. */ + ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL, + verify); + if (ret != 1) { + /* When ignoring errors or loading PEM only and no PEM. don't fail. */ + if ((flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) || + ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) && + (ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)))) { + unsigned long err = 0; + CLEAR_ASN_NO_PEM_HEADER_ERROR(err); + #if defined(WOLFSSL_QT) + ret = 1; + #endif + } + else { + WOLFSSL_ERROR(ret); + WOLFSSL_MSG("Load CA file failed, continuing"); + /* Add to fail count. */ + (*failCount)++; + } + } + else { + #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) + /* Try loading as a trusted peer certificate. */ + ret = wolfSSL_CTX_trust_peer_cert(ctx, name, WOLFSSL_FILETYPE_PEM); + if (ret != 1) { + WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error. " + "Ignoring this error."); + } + #endif + /* Add to success count. */ + (*successCount)++; + } + + return ret; +} + +/* Load PEM formatted CA files from a path. + * + * @param [in, out] ctx SSL context object. + * @param [in] path Path to directory to read. + * @param [in] flags Flags representing options for loading. + * @param [in] verify How to verify a certificate. + * @param [in] successCount Number of files successfully loaded. + * @return 1 on success. + * @return 0 on failure. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int wolfssl_ctx_load_path(WOLFSSL_CTX* ctx, const char* path, + word32 flags, int verify, int successCount) +{ + int ret = 1; + char* name = NULL; + int fileRet; + int failCount = 0; +#ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx; +#else + ReadDirCtx readCtx[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for directory reading context. */ + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, + DYNAMIC_TYPE_DIRCTX); + if (readCtx == NULL) { + ret = MEMORY_E; + } +#endif + + if (ret == 1) { + /* Get name of first file in path. */ + fileRet = wc_ReadDirFirst(readCtx, path, &name); + /* While getting filename doesn't fail and name returned, process file. + */ + while ((fileRet == 0) && (name != NULL)) { + WOLFSSL_MSG(name); + /* Load file. */ + ret = wolfssl_ctx_load_path_file(ctx, name, verify, (int)flags, + &failCount, &successCount); + /* Get next filenmae. */ + fileRet = wc_ReadDirNext(readCtx, path, &name); + } + /* Cleanup directory reading context. */ + wc_ReadDirClose(readCtx); + + /* When not WOLFSSL_QT, ret is always overwritten. */ + (void)ret; + + /* Return real directory read failure error codes. */ + if (fileRet != WC_READDIR_NOFILE) { + ret = fileRet; + #if defined(WOLFSSL_QT) || defined(WOLFSSL_IGNORE_BAD_CERT_PATH) + /* Ignore bad path error when flag set. */ + if ((ret == WC_NO_ERR_TRACE(BAD_PATH_ERROR)) && + (flags & WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR)) { + /* QSslSocket always loads certs in system folder + * when it is initialized. + * Compliant with OpenSSL when flag set. + */ + ret = 1; + } + else { + /* qssl socket wants to know errors. */ + WOLFSSL_ERROR(ret); + } + #endif + } + /* Report failure if no files successfully loaded or there were + * failures. */ + else if ((successCount == 0) || (failCount > 0)) { + /* Use existing error code if exists. */ + #if defined(WOLFSSL_QT) + /* Compliant with OpenSSL when flag set. */ + if (!(flags & WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE)) + #endif + { + /* Return 0 when no files loaded. */ + ret = 0; + } + } + else { + /* We loaded something so it is a success. */ + ret = 1; + } + + #ifdef WOLFSSL_SMALL_STACK + /* Dispose of dynamically allocated memory. */ + XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX); + #endif + } + + return ret; +} +#endif + +/* Load a file and/or files in path + * + * No c_rehash. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of file to load. May be NULL. + * @param [in] path Path to directory containing PEM CA files. + * May be NULL. + * @param [in] flags Flags representing options for loading. + * @return 1 on success. + * @return 0 on failure. + * @return NOT_COMPILED_IN when directory reading not supported and path is + * not NULL. + * @return Other negative on error. + */ +int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, + const char* path, word32 flags) +{ + int ret = 1; +#ifndef NO_WOLFSSL_DIR + int successCount = 0; +#endif + int verify = WOLFSSL_VERIFY_DEFAULT; + + WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex"); + + /* Validate parameters. */ + if ((ctx == NULL) || ((file == NULL) && (path == NULL))) { + ret = 0; + } + + if (ret == 1) { + /* Get setting on how to verify certificates. */ + verify = GET_VERIFY_SETTING_CTX(ctx); + /* Overwrite setting when flag set. */ + if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) { + verify = VERIFY_SKIP_DATE; + } + + if (file != NULL) { + /* Load the PEM formatted CA file. */ + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, + NULL, verify); + #ifndef NO_WOLFSSL_DIR + if (ret == 1) { + /* Include success in overall count. */ + successCount++; + } + #endif + #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) + /* Load CA as a trusted peer certificate. */ + ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM); + if (ret != 1) { + WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error"); + } + #endif + } + } + + if ((ret == 1) && (path != NULL)) { +#ifndef NO_WOLFSSL_DIR + /* Load CA files form path. */ + ret = wolfssl_ctx_load_path(ctx, path, flags, verify, successCount); +#else + /* Loading a path not supported. */ + ret = NOT_COMPILED_IN; + (void)flags; +#endif + } + + return ret; +} + +/* Load a file and/or files in path + * + * No c_rehash. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of file to load. May be NULL. + * @param [in] path Path to directory containing PEM CA files. + * May be NULL. + * @return 1 on success. + * @return 0 on failure. + */ +WOLFSSL_ABI +int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, + const char* path) +{ + /* Load using default flags/options. */ + int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); + + /* Return 1 on success or 0 on failure. */ + return WS_RETURN_CODE(ret, 0); +} + +#ifdef WOLFSSL_SYS_CA_CERTS + +#ifdef USE_WINDOWS_API + +/* Load CA certificate from Windows store. + * + * Assumes loaded is 0. + * + * @param [in, out] ctx SSL context object. + * @param [out] loaded Whether CA certificates were loaded. + * @return 1 on success. + * @return 0 on failure. + */ +static int LoadSystemCaCertsWindows(WOLFSSL_CTX* ctx, byte* loaded) +{ + int ret = 1; + word32 i; + HANDLE handle = NULL; + PCCERT_CONTEXT certCtx = NULL; + LPCSTR storeNames[2] = {"ROOT", "CA"}; + HCRYPTPROV_LEGACY hProv = (HCRYPTPROV_LEGACY)NULL; + + if ((ctx == NULL) || (loaded == NULL)) { + ret = 0; + } + + for (i = 0; (ret == 1) && (i < sizeof(storeNames)/sizeof(*storeNames)); + ++i) { + handle = CertOpenSystemStoreA(hProv, storeNames[i]); + if (handle != NULL) { + while ((certCtx = CertEnumCertificatesInStore(handle, certCtx)) + != NULL) { + if (certCtx->dwCertEncodingType == X509_ASN_ENCODING) { + if (ProcessBuffer(ctx, certCtx->pbCertEncoded, + certCtx->cbCertEncoded, WOLFSSL_FILETYPE_ASN1, + CA_TYPE, NULL, NULL, 0, + GET_VERIFY_SETTING_CTX(ctx)) == 1) { + /* + * Set "loaded" as long as we've loaded one CA + * cert. + */ + *loaded = 1; + } + } + } + } + else { + WOLFSSL_MSG_EX("Failed to open cert store %s.", storeNames[i]); + } + + if (handle != NULL && !CertCloseStore(handle, 0)) { + WOLFSSL_MSG_EX("Failed to close cert store %s.", storeNames[i]); + ret = 0; + } + } + + return ret; +} + +#elif defined(__APPLE__) + +#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \ + && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) +/* Manually obtains certificates from the system trust store and loads them + * directly into wolfSSL "the old way". + * + * As of MacOS 14.0 we are still able to use this method to access system + * certificates. Accessibility of this API is indicated by the presence of the + * Security/SecTrustSettings.h header. In the likely event that Apple removes + * access to this API on Macs, this function should be removed and the + * DoAppleNativeCertValidation() routine should be used for all devices. + * + * Assumes loaded is 0. + * + * @param [in, out] ctx SSL context object. + * @param [out] loaded Whether CA certificates were loaded. + * @return 1 on success. + * @return 0 on failure. + */ +static int LoadSystemCaCertsMac(WOLFSSL_CTX* ctx, byte* loaded) +{ + int ret = 1; + word32 i; + const unsigned int trustDomains[] = { + kSecTrustSettingsDomainUser, + kSecTrustSettingsDomainAdmin, + kSecTrustSettingsDomainSystem + }; + CFArrayRef certs; + OSStatus stat; + CFIndex numCerts; + CFDataRef der; + CFIndex j; + + if ((ctx == NULL) || (loaded == NULL)) { + ret = 0; + } + + for (i = 0; (ret == 1) && (i < sizeof(trustDomains)/sizeof(*trustDomains)); + ++i) { + stat = SecTrustSettingsCopyCertificates( + (SecTrustSettingsDomain)trustDomains[i], &certs); + if (stat == errSecSuccess) { + numCerts = CFArrayGetCount(certs); + for (j = 0; j < numCerts; ++j) { + der = SecCertificateCopyData((SecCertificateRef) + CFArrayGetValueAtIndex(certs, j)); + if (der != NULL) { + if (ProcessBuffer(ctx, CFDataGetBytePtr(der), + CFDataGetLength(der), WOLFSSL_FILETYPE_ASN1, + CA_TYPE, NULL, NULL, 0, + GET_VERIFY_SETTING_CTX(ctx)) == 1) { + /* + * Set "loaded" as long as we've loaded one CA + * cert. + */ + *loaded = 1; + } + + CFRelease(der); + } + } + + CFRelease(certs); + } + else if (stat == errSecNoTrustSettings) { + WOLFSSL_MSG_EX("No trust settings for domain %d, moving to next " + "domain.", trustDomains[i]); + } + else { + WOLFSSL_MSG_EX("SecTrustSettingsCopyCertificates failed with" + " status %d.", stat); + ret = 0; + break; + } + } + + return ret; +} +#endif /* defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) */ + +#else + +/* Potential system CA certs directories on Linux/Unix distros. */ +static const char* systemCaDirs[] = { +#if defined(__ANDROID__) || defined(ANDROID) + "/system/etc/security/cacerts" /* Android */ +#else + "/etc/ssl/certs", /* Debian, Ubuntu, Gentoo, others */ + "/etc/pki/ca-trust/source/anchors", /* Fedora, RHEL */ + "/etc/pki/tls/certs" /* Older RHEL */ +#endif +}; + +/* Get CA directory list. + * + * @param [out] num Number of CA directories. + * @return CA directory list. + * @return NULL when num is NULL. + */ +const char** wolfSSL_get_system_CA_dirs(word32* num) +{ + const char** ret; + + /* Validate parameters. */ + if (num == NULL) { + ret = NULL; + } + else { + ret = systemCaDirs; + *num = sizeof(systemCaDirs)/sizeof(*systemCaDirs); + } + + return ret; +} + +/* Load CA certificate from default system directories. + * + * Assumes loaded is 0. + * + * @param [in, out] ctx SSL context object. + * @param [out] loaded Whether CA certificates were loaded. + * @return 1 on success. + * @return 0 on failure. + */ +static int LoadSystemCaCertsNix(WOLFSSL_CTX* ctx, byte* loaded) { + int ret = 1; + word32 i; + + if ((ctx == NULL) || (loaded == NULL)) { + ret = 0; + } + + for (i = 0; (ret == 1) && (i < sizeof(systemCaDirs)/sizeof(*systemCaDirs)); + ++i) { + WOLFSSL_MSG_EX("Attempting to load system CA certs from %s.", + systemCaDirs[i]); + /* + * We want to keep trying to load more CA certs even if one cert in + * the directory is bad and can't be used (e.g. if one is expired), + * so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR. + */ + if (wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, systemCaDirs[i], + WOLFSSL_LOAD_FLAG_IGNORE_ERR) != 1) { + WOLFSSL_MSG_EX("Failed to load CA certs from %s, trying " + "next possible location.", systemCaDirs[i]); + } + else { + WOLFSSL_MSG_EX("Loaded CA certs from %s.", + systemCaDirs[i]); + *loaded = 1; + /* Stop searching after we've loaded one directory. */ + break; + } + } + + return ret; +} + +#endif + +/* Load CA certificates from system defined locations. + * + * @param [in, out] ctx SSL context object. + * @return 1 on success. + * @return 0 on failure. + * @return WOLFSSL_BAD_PATH when no error but no certificates loaded. + */ +int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx) +{ + int ret; + byte loaded = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_load_system_CA_certs"); + +#ifdef USE_WINDOWS_API + + ret = LoadSystemCaCertsWindows(ctx, &loaded); + +#elif defined(__APPLE__) + +#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \ + && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) + /* As of MacOS 14.0 we are still able to access system certificates and + * load them manually into wolfSSL "the old way". Accessibility of this API + * is indicated by the presence of the Security/SecTrustSettings.h header */ + ret = LoadSystemCaCertsMac(ctx, &loaded); +#elif defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION) + /* For other Apple devices, Apple has removed the ability to obtain + * certificates from the trust store, so we can't use wolfSSL's built-in + * certificate validation mechanisms anymore. We instead must call into the + * Security Framework APIs to authenticate peer certificates when received. + * (see src/internal.c:DoAppleNativeCertValidation()). + * Thus, there is no CA "loading" required, but to keep behavior consistent + * with the current API (not using system CA certs unless this function has + * been called), we simply set a flag indicating that the new apple trust + * verification routine should be used later */ + ctx->doAppleNativeCertValidationFlag = 1; + ret = 1; + loaded = 1; + +#if FIPS_VERSION_GE(2,0) /* Gate back to cert 3389 FIPS modules */ +#warning "Cryptographic operations may occur outside the FIPS module boundary" \ + "Please review FIPS claims for cryptography on this Apple device" +#endif /* FIPS_VERSION_GE(2,0) */ + +#else +/* HAVE_SECURITY_SECXXX_H macros are set by autotools or CMake when searching + * system for the required SDK headers. If building with user_settings.h, you + * will need to manually define WOLFSSL_APPLE_NATIVE_CERT_VALIDATION + * and ensure the appropriate Security.framework headers and libraries are + * visible to your compiler */ +#error "WOLFSSL_SYS_CA_CERTS on Apple devices requires Security.framework" \ + " header files to be detected, or a manual override with" \ + " WOLFSSL_APPLE_NATIVE_CERT_VALIDATION" +#endif + +#else + + ret = LoadSystemCaCertsNix(ctx, &loaded); + +#endif + + /* If we didn't fail but didn't load then we error out. */ + if ((ret == 1) && (!loaded)) { + ret = WOLFSSL_BAD_PATH; + } + + WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret); + + return ret; +} + +#endif /* WOLFSSL_SYS_CA_CERTS */ + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Load a trusted peer certificate into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of peer certificate file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 when ctx or file is NULL. + */ +int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert"); + + /* Validate parameters. */ + if ((ctx == NULL) || (file == NULL)) { + ret = 0; + } + else { + ret = ProcessFile(ctx, file, format, TRUSTED_PEER_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + } + + return ret; +} + +/* Load a trusted peer certificate into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] file Name of peer certificate file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 when ssl or file is NULL. + */ +int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_trust_peer_cert"); + + /* Validate parameters. */ + if ((ssl == NULL) || (file == NULL)) { + ret = 0; + } + else { + ret = ProcessFile(NULL, file, format, TRUSTED_PEER_TYPE, ssl, 0, NULL, + GET_VERIFY_SETTING_SSL(ssl)); + } + + return ret; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +#ifdef WOLFSSL_DER_LOAD + +/* Load a CA certificate into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of peer certificate file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations"); + + /* Validate parameters. */ + if ((ctx == NULL) || (file == NULL)) { + ret = 0; + } + else { + ret = ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + } + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + +#endif /* WOLFSSL_DER_LOAD */ + + +/* Load a user certificate into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of user certificate file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + */ +WOLFSSL_ABI +int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file"); + + ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + + +/* Load a private key into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of private key file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + */ +WOLFSSL_ABI +int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file"); + + ret = ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + +#ifdef WOLFSSL_DUAL_ALG_CERTS +/* Load an alternative private key into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of private key file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file"); + + ret = ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + + +/* Load a PEM certificate chain into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of PEM certificate chain file. + * @return 1 on success. + * @return 0 on failure. + */ +WOLFSSL_ABI +int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file) +{ + int ret; + + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file"); + + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + +/* Load certificate chain into SSL context. + * + * Processes up to MAX_CHAIN_DEPTH plus subject cert. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of private key file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx, + const char* file, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format"); + + ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL, + GET_VERIFY_SETTING_CTX(ctx)); + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + +#endif /* NO_FILESYSTEM */ + +#ifdef OPENSSL_EXTRA + +/* Load a private key into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] pkey EVP private key. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); + + /* Validate parameters. */ + if ((ssl == NULL) || (pkey == NULL)) { + ret = 0; + } + else { + /* Get DER encoded key data from EVP private key. */ + ret = wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1); + } + + return ret; +} + +/* Load a DER encoded private key in a buffer into SSL. + * + * @param [in] pri Indicates type of private key. Ignored. + * @param [in, out] ssl SSL object. + * @param [in] der Buffer holding DER encoded private key. + * @param [in] derSz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der, + long derSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); + + (void)pri; + + /* Validate parameters. */ + if ((ssl == NULL) || (der == NULL)) { + ret = 0; + } + else { + ret = wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, + WOLFSSL_FILETYPE_ASN1); + } + + return ret; +} + +/* Load a DER encoded private key in a buffer into SSL context. + * + * @param [in] pri Indicates type of private key. Ignored. + * @param [in, out] ctx SSL context object. + * @param [in] der Buffer holding DER encoded private key. + * @param [in] derSz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, + unsigned char* der, long derSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1"); + + (void)pri; + + /* Validate parameters. */ + if ((ctx == NULL) || (der == NULL)) { + ret = 0; + } + else { + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz, + WOLFSSL_FILETYPE_ASN1); + } + + return ret; +} + + +#ifndef NO_RSA +/* Load a DER encoded RSA private key in a buffer into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] der Buffer holding DER encoded RSA private key. + * @param [in] derSz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); + + /* Validate parameters. */ + if ((ssl == NULL) || (der == NULL)) { + ret = 0; + } + else { + ret = wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, + WOLFSSL_FILETYPE_ASN1); + } + + return ret; +} +#endif + +/* Load a certificate into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_certificate"); + + /* Validate parameters. */ + if ((ssl == NULL) || (x509 == NULL) || (x509->derCert == NULL)) { + ret = 0; + } + else { + long idx = 0; + + /* Get DER encoded certificate data from X509 object. */ + ret = ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, + WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0, + GET_VERIFY_SETTING_SSL(ssl)); + } + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + +#endif /* OPENSSL_EXTRA */ + +/* Load a DER encoded certificate in a buffer into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] der Buffer holding DER encoded certificate. + * @param [in] derSz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der, + int derSz) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); + + /* Validate parameters. */ + if ((ssl == NULL) || (der == NULL)) { + ret = 0; + } + else { + long idx = 0; + + ret = ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl)); + } + + /* Return 1 on success or 0 on failure. */ + return WS_RC(ret); +} + +#ifndef NO_FILESYSTEM + +/* Load a certificate from a file into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] file Name of file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +WOLFSSL_ABI +int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_certificate_file"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 0, NULL, + GET_VERIFY_SETTING_SSL(ssl)); + /* Return 1 on success or 0 on failure. */ + ret = WS_RC(ret); + } + + return ret; +} + + +/* Load a private key from a file into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] file Name of file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +WOLFSSL_ABI +int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, ssl, 0, NULL, + GET_VERIFY_SETTING_SSL(ssl)); + /* Return 1 on success or 0 on failure. */ + ret = WS_RC(ret); + } + + return ret; +} + + +/* Load a PEM encoded certificate chain from a file into SSL. + * + * Process up to MAX_CHAIN_DEPTH plus subject cert. + * + * @param [in, out] ssl SSL object. + * @param [in] file Name of file. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +WOLFSSL_ABI +int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, ssl, + 1, NULL, GET_VERIFY_SETTING_SSL(ssl)); + /* Return 1 on success or 0 on failure. */ + ret = WS_RC(ret); + } + + return ret; +} + +/* Load a certificate chain from a file into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] file Name of file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file, + int format) +{ + int ret; + + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, NULL, + GET_VERIFY_SETTING_SSL(ssl)); + /* Return 1 on success or 0 on failure. */ + ret = WS_RC(ret); + } + + return ret; +} + +#endif /* !NO_FILESYSTEM */ + +#ifdef OPENSSL_EXTRA + +#ifndef NO_FILESYSTEM +/* Load an RSA private key from a file into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] file Name of file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file, + int format) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey_file"); + + return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format); +} + +/* Load an RSA private key from a file into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] file Name of file. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +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); +} +#endif /* NO_FILESYSTEM */ + +#endif /* OPENSSL_EXTRA */ + +/* Load a buffer of certificate/s into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding certificate or private key. + * @param [in] sz Length of data in buffer in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @param [in] userChain Whether file contains chain of certificates. + * @param [in] flags Flags representing options for loading. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx, const unsigned char* in, + long sz, int format, int userChain, word32 flags) +{ + int ret; + int verify; + + WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex"); + + /* Get setting on how to verify certificates. */ + verify = GET_VERIFY_SETTING_CTX(ctx); + /* Overwrite setting when flag set. */ + if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) { + verify = VERIFY_SKIP_DATE; + } + + /* When PEM, treat as certificate chain of CA certificates. */ + if (format == WOLFSSL_FILETYPE_PEM) { + ret = ProcessChainBuffer(ctx, NULL, in, sz, CA_TYPE, verify); + } + /* When DER, load the CA certificate. */ + else { + ret = ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL, + userChain, verify); + } +#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS) + if (ret == 1) { + /* Load certificate/s as trusted peer certificate. */ + ret = wolfSSL_CTX_trust_peer_buffer(ctx, in, sz, format); + } +#endif + + WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret); + return ret; +} + +/* Load a buffer of certificate/s into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding certificate or private key. + * @param [in] sz Length of data in buffer in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, + long sz, int format) +{ + return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); +} + +/* Load a buffer of certificate chain into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding certificate chain. + * @param [in] sz Length of data in buffer in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) +{ + return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); +} + + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Load a buffer of certificate/s into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding certificate/s. + * @param [in] sz Length of data in buffer in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ctx or in is NULL, or sz is less than zero. + */ +int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, + long sz, int format) +{ + int ret; + int verify; + + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer"); + + /* Validate parameters. */ + if ((ctx == NULL) || (in == NULL) || (sz < 0)) { + ret = BAD_FUNC_ARG; + } + else { + #if WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY + verify = VERIFY_SKIP_DATE; + #else + verify = GET_VERIFY_SETTING_CTX(ctx); + #endif + + /* When PEM, treat as certificate chain of trusted peer certificates. */ + if (format == WOLFSSL_FILETYPE_PEM) { + ret = ProcessChainBuffer(ctx, NULL, in, sz, TRUSTED_PEER_TYPE, + verify); + } + /* When DER, load the trusted peer certificate. */ + else { + ret = ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL, + NULL, 0, verify); + } + } + + return ret; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + +/* Load a certificate in a buffer into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding certificate. + * @param [in] sz Size of data in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer"); + ret = ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0, + GET_VERIFY_SETTING_CTX(ctx)); + WOLFSSL_LEAVE("wolfSSL_CTX_use_certificate_buffer", ret); + + return ret; +} + +/* Load a private key in a buffer into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding private key. + * @param [in] sz Size of data in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, + long sz, int format) +{ + int ret; + long consumed = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer"); + + ret = ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, &consumed, + 0, GET_VERIFY_SETTING_CTX(ctx)); +#ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ret == 1) && (consumed < sz)) { + /* When support for dual algorithm certificates is enabled, the + * buffer may contain both the primary and the alternative + * private key. Hence, we have to parse both of them. + */ + ret = ProcessBuffer(ctx, in + consumed, sz - consumed, format, + ALT_PRIVATEKEY_TYPE, NULL, NULL, 0, GET_VERIFY_SETTING_CTX(ctx)); + } +#endif + + (void)consumed; + + WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_buffer", ret); + return ret; +} + +#ifdef WOLFSSL_DUAL_ALG_CERTS +int wolfSSL_CTX_use_AltPrivateKey_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_buffer"); + ret = ProcessBuffer(ctx, in, sz, format, ALT_PRIVATEKEY_TYPE, NULL, + NULL, 0, GET_VERIFY_SETTING_CTX(ctx)); + WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_buffer", ret); + + return ret; +} +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + +#ifdef WOLF_PRIVATE_KEY_ID +/* Load the id of a private key into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] id Buffer holding id. + * @param [in] sz Size of data in bytes. + * @param [in] devId Device identifier. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id, + long sz, int devId) +{ + int ret = 1; + + /* Dispose of old private key and allocate and copy in id. */ + FreeDer(&ctx->privateKey); + if (AllocCopyDer(&ctx->privateKey, id, (word32)sz, PRIVATEKEY_TYPE, + ctx->heap) != 0) { + ret = 0; + } + if (ret == 1) { + /* Private key is an id. */ + ctx->privateKeyId = 1; + ctx->privateKeyLabel = 0; + /* Set private key device id to be one passed in or for SSL context. */ + if (devId != INVALID_DEVID) { + ctx->privateKeyDevId = devId; + } + else { + ctx->privateKeyDevId = ctx->devId; + } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Set the ID for the alternative key, too. User can still override that + * afterwards. */ + ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId); + #endif + } + + return ret; +} + +/* Load the id of a private key into SSL context and set key size. + * + * @param [in, out] ctx SSL context object. + * @param [in] id Buffer holding id. + * @param [in] sz Size of data in bytes. + * @param [in] devId Device identifier. + * @param [in] keySz Size of key. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id, + long sz, int devId, long keySz) +{ + int ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId); + if (ret == 1) { + /* Set the key size which normally is calculated during decoding. */ + ctx->privateKeySz = (int)keySz; + } + + return ret; +} + +/* Load the label name of a private key into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] label Buffer holding label. + * @param [in] devId Device identifier. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label, + int devId) +{ + int ret = 1; + word32 sz = (word32)XSTRLEN(label) + 1; + + /* Dispose of old private key and allocate and copy in label. */ + FreeDer(&ctx->privateKey); + if (AllocCopyDer(&ctx->privateKey, (const byte*)label, (word32)sz, + PRIVATEKEY_TYPE, ctx->heap) != 0) { + ret = 0; + } + if (ret == 1) { + /* Private key is a label. */ + ctx->privateKeyId = 0; + ctx->privateKeyLabel = 1; + /* Set private key device id to be one passed in or for SSL context. */ + if (devId != INVALID_DEVID) { + ctx->privateKeyDevId = devId; + } + else { + ctx->privateKeyDevId = ctx->devId; + } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Set the ID for the alternative key, too. User can still override that + * afterwards. */ + ret = wolfSSL_CTX_use_AltPrivateKey_Label(ctx, label, devId); + #endif + } + + return ret; +} + +#ifdef WOLFSSL_DUAL_ALG_CERTS +int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id, + long sz, int devId) +{ + int ret = 1; + + if ((ctx == NULL) || (id == NULL)) { + ret = 0; + } + + if (ret == 1) { + FreeDer(&ctx->altPrivateKey); + if (AllocDer(&ctx->altPrivateKey, (word32)sz, ALT_PRIVATEKEY_TYPE, + ctx->heap) != 0) { + ret = 0; + } + } + if (ret == 1) { + XMEMCPY(ctx->altPrivateKey->buffer, id, sz); + ctx->altPrivateKeyId = 1; + if (devId != INVALID_DEVID) { + ctx->altPrivateKeyDevId = devId; + } + else { + ctx->altPrivateKeyDevId = ctx->devId; + } + } + + return ret; +} + +int wolfSSL_CTX_use_AltPrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id, + long sz, int devId, long keySz) +{ + int ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId); + if (ret == 1) { + ctx->altPrivateKeySz = (word32)keySz; + } + + return ret; +} + +int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label, + int devId) +{ + int ret = 1; + word32 sz; + + if ((ctx == NULL) || (label == NULL)) { + ret = 0; + } + + if (ret == 1) { + sz = (word32)XSTRLEN(label) + 1; + FreeDer(&ctx->altPrivateKey); + if (AllocDer(&ctx->altPrivateKey, (word32)sz, ALT_PRIVATEKEY_TYPE, + ctx->heap) != 0) { + ret = 0; + } + } + if (ret == 1) { + XMEMCPY(ctx->altPrivateKey->buffer, label, sz); + ctx->altPrivateKeyLabel = 1; + if (devId != INVALID_DEVID) { + ctx->altPrivateKeyDevId = devId; + } + else { + ctx->altPrivateKeyDevId = ctx->devId; + } + } + + return ret; +} +#endif /* WOLFSSL_DUAL_ALG_CERTS */ +#endif /* WOLF_PRIVATE_KEY_ID */ + +/* Load a certificate chain in a buffer into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding DER encoded certificate chain. + * @param [in] sz Size of data in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format"); + return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1, + GET_VERIFY_SETTING_CTX(ctx)); +} + +/* Load a PEM encoded certificate chain in a buffer into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] in Buffer holding DER encoded certificate chain. + * @param [in] sz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz) +{ + return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz, + WOLFSSL_FILETYPE_PEM); +} + +/* Load a user certificate in a buffer into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] in Buffer holding user certificate. + * @param [in] sz Size of data in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, const unsigned char* in, + long sz, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_certificate_buffer"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0, + GET_VERIFY_SETTING_SSL(ssl)); + } + + return ret; +} + +/* Load a private key in a buffer into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] in Buffer holding private key. + * @param [in] sz Size of data in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl, const unsigned char* in, + long sz, int format) +{ + int ret; + long consumed = 0; + + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, ssl, + &consumed, 0, GET_VERIFY_SETTING_SSL(ssl)); + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ret == 1) && (consumed < sz)) { + /* When support for dual algorithm certificates is enabled, the + * buffer may contain both the primary and the alternative + * private key. Hence, we have to parse both of them. + */ + ret = ProcessBuffer(ssl->ctx, in + consumed, sz - consumed, format, + ALT_PRIVATEKEY_TYPE, ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl)); + } + #endif + } + + return ret; +} + +#ifdef WOLFSSL_DUAL_ALG_CERTS +int wolfSSL_use_AltPrivateKey_buffer(WOLFSSL* ssl, const unsigned char* in, + long sz, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_AltPrivateKey_buffer"); + ret = ProcessBuffer(ssl->ctx, in, sz, format, ALT_PRIVATEKEY_TYPE, ssl, + NULL, 0, GET_VERIFY_SETTING_SSL(ssl)); + WOLFSSL_LEAVE("wolfSSL_use_AltPrivateKey_buffer", ret); + + return ret; +} +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + +#ifdef WOLF_PRIVATE_KEY_ID +/* Load the id of a private key into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] id Buffer holding id. + * @param [in] sz Size of data in bytes. + * @param [in] devId Device identifier. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, + long sz, int devId) +{ + int ret = 1; + + /* Dispose of old private key if owned and allocate and copy in id. */ + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif + } + if (AllocCopyDer(&ssl->buffers.key, id, (word32)sz, PRIVATEKEY_TYPE, + ssl->heap) != 0) { + ret = 0; + } + if (ret == 1) { + /* Buffer now ours. */ + ssl->buffers.weOwnKey = 1; + /* Private key is an id. */ + ssl->buffers.keyId = 1; + ssl->buffers.keyLabel = 0; + /* Set private key device id to be one passed in or for SSL. */ + if (devId != INVALID_DEVID) { + ssl->buffers.keyDevId = devId; + } + else { + ssl->buffers.keyDevId = ssl->devId; + } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Set the ID for the alternative key, too. User can still override that + * afterwards. */ + ret = wolfSSL_use_AltPrivateKey_Id(ssl, id, sz, devId); + #endif + } + + return ret; +} + +/* Load the id of a private key into SSL and set key size. + * + * @param [in, out] ssl SSL object. + * @param [in] id Buffer holding id. + * @param [in] sz Size of data in bytes. + * @param [in] devId Device identifier. + * @param [in] keySz Size of key. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id, + long sz, int devId, long keySz) +{ + int ret = wolfSSL_use_PrivateKey_Id(ssl, id, sz, devId); + if (ret == 1) { + /* Set the key size which normally is calculated during decoding. */ + ssl->buffers.keySz = (int)keySz; + } + + return ret; +} + +/* Load the label name of a private key into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] label Buffer holding label. + * @param [in] devId Device identifier. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId) +{ + int ret = 1; + word32 sz = (word32)XSTRLEN(label) + 1; + + /* Dispose of old private key if owned and allocate and copy in label. */ + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif + } + if (AllocCopyDer(&ssl->buffers.key, (const byte*)label, (word32)sz, + PRIVATEKEY_TYPE, ssl->heap) != 0) { + ret = 0; + } + if (ret == 1) { + /* Buffer now ours. */ + ssl->buffers.weOwnKey = 1; + /* Private key is a label. */ + ssl->buffers.keyId = 0; + ssl->buffers.keyLabel = 1; + /* Set private key device id to be one passed in or for SSL. */ + if (devId != INVALID_DEVID) { + ssl->buffers.keyDevId = devId; + } + else { + ssl->buffers.keyDevId = ssl->devId; + } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Set the label for the alternative key, too. User can still override + * that afterwards. */ + ret = wolfSSL_use_AltPrivateKey_Label(ssl, label, devId); + #endif + } + + return ret; +} + +#ifdef WOLFSSL_DUAL_ALG_CERTS +int wolfSSL_use_AltPrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, long sz, + int devId) +{ + int ret = 1; + + if ((ssl == NULL) || (id == NULL)) { + ret = 0; + } + + if (ret == 1) { + if (ssl->buffers.weOwnAltKey) { + FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif + } + if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE, + ssl->heap) == 0) { + ret = 0; + } + } + if (ret == 1) { + XMEMCPY(ssl->buffers.altKey->buffer, id, sz); + ssl->buffers.weOwnAltKey = 1; + ssl->buffers.altKeyId = 1; + if (devId != INVALID_DEVID) { + ssl->buffers.altKeyDevId = devId; + } + else { + ssl->buffers.altKeyDevId = ssl->devId; + } + } + + return ret; +} + +int wolfSSL_use_AltPrivateKey_id(WOLFSSL* ssl, const unsigned char* id, long sz, + int devId, long keySz) +{ + int ret = wolfSSL_use_AltPrivateKey_Id(ssl, id, sz, devId); + if (ret == 1) { + ssl->buffers.altKeySz = (word32)keySz; + } + + return ret; +} + +int wolfSSL_use_AltPrivateKey_Label(WOLFSSL* ssl, const char* label, int devId) +{ + int ret = 1; + word32 sz; + + if ((ssl == NULL) || (label == NULL)) { + ret = 0; + } + + if (ret == 1) { + sz = (word32)XSTRLEN(label) + 1; + if (ssl->buffers.weOwnAltKey) { + FreeDer(&ssl->buffers.altKey); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.altKeyMask); + #endif + } + if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE, + ssl->heap) == 0) { + ret = 0; + } + } + if (ret == 1) { + XMEMCPY(ssl->buffers.altKey->buffer, label, sz); + ssl->buffers.weOwnAltKey = 1; + ssl->buffers.altKeyLabel = 1; + if (devId != INVALID_DEVID) { + ssl->buffers.altKeyDevId = devId; + } + else { + ssl->buffers.altKeyDevId = ssl->devId; + } + } + + return ret; +} +#endif /* WOLFSSL_DUAL_ALG_CERTS */ +#endif /* WOLF_PRIVATE_KEY_ID */ + +/* Load a certificate chain in a buffer into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] in Buffer holding DER encoded certificate chain. + * @param [in] sz Size of data in bytes. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ssl is NULL. + */ +int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl, + const unsigned char* in, long sz, int format) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); + + /* Validate parameters. */ + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ret = ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 1, + GET_VERIFY_SETTING_SSL(ssl)); + } + + return ret; +} + +/* Load a PEM encoded certificate chain in a buffer into SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] in Buffer holding DER encoded certificate chain. + * @param [in] sz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + * @return Negative on error. + */ +int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, const unsigned char* in, + long sz) +{ + return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz, + WOLFSSL_FILETYPE_PEM); +} + +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) +/* Add certificate to chain. + * + * @param [in, out] chain Buffer holding encoded certificate for TLS. + * @param [in] weOwn Indicates we need to free chain if repleced. + * @param [in] cert Buffer holding DER encoded certificate. + * @param [in] certSz Size of DER encoded certificate in bytes. + * @param [in] heap Dynamic memory allocation hint. + * @return 1 on success. + * @return 0 on failure. + */ +static int wolfssl_add_to_chain(DerBuffer** chain, int weOwn, const byte* cert, + word32 certSz, void* heap) +{ + int res = 1; + int ret; + DerBuffer* oldChain = *chain; + DerBuffer* newChain = NULL; + word32 len = 0; + + if (oldChain != NULL) { + /* Get length of previous chain. */ + len = oldChain->length; + } + /* Allocate DER buffer bug enough to hold old and new certificates. */ + ret = AllocDer(&newChain, len + CERT_HEADER_SZ + certSz, CERT_TYPE, heap); + if (ret != 0) { + WOLFSSL_MSG("AllocDer error"); + res = 0; + } + + if (res == 1) { + if (oldChain != NULL) { + /* Place old chain in new buffer. */ + XMEMCPY(newChain->buffer, oldChain->buffer, len); + } + /* Append length and DER encoded certificate. */ + c32to24(certSz, newChain->buffer + len); + XMEMCPY(newChain->buffer + len + CERT_HEADER_SZ, cert, certSz); + + /* Dispose of old chain if we own it. */ + if (weOwn) { + FreeDer(chain); + } + /* Replace chain. */ + *chain = newChain; + } + + return res; +} +#endif + +#ifdef OPENSSL_EXTRA + +/* Add a certificate to end of chain sent in TLS handshake. + * + * @param [in, out] ctx SSL context. + * @param [in] der Buffer holding DER encoded certificate. + * @param [in] derSz Size of data in buffer. + * @return 1 on success. + * @return 0 on failure. + */ +static int wolfssl_ctx_add_to_chain(WOLFSSL_CTX* ctx, const byte* der, + int derSz) +{ + int res = 1; + int ret; + DerBuffer* derBuffer = NULL; + + /* Create a DER buffer from DER encoding. */ + ret = AllocCopyDer(&derBuffer, der, (word32)derSz, CERT_TYPE, ctx->heap); + if (ret != 0) { + WOLFSSL_MSG("Memory Error"); + res = 0; + } + if (res == 1) { + /* Add a user CA certificate to the certificate manager. */ + res = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, + GET_VERIFY_SETTING_CTX(ctx)); + if (res != 1) { + res = 0; + } + } + + if (res == 1) { + /* Add chain to DER buffer. */ + res = wolfssl_add_to_chain(&ctx->certChain, 1, der, (word32)derSz, ctx->heap); + #ifdef WOLFSSL_TLS13 + /* Update count of certificates. */ + ctx->certChainCnt++; + #endif + } + + return res; +} + +/* Add a certificate to chain sent in TLS handshake. + * + * @param [in, out] ctx SSL context. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +{ + int ret = 1; + int derSz = 0; + const byte* der = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); + + /* Validate parameters. */ + if ((ctx == NULL) || (x509 == NULL)) { + WOLFSSL_MSG("Bad Argument"); + ret = 0; + } + + if (ret == 1) { + /* Get the DER encoding of the certificate from the X509 object. */ + der = wolfSSL_X509_get_der(x509, &derSz); + /* Validate buffer. */ + if ((der == NULL) || (derSz <= 0)) { + WOLFSSL_MSG("Error getting X509 DER"); + ret = 0; + } + } + + if ((ret == 1) && (ctx->certificate == NULL)) { + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); + + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx)); + if (ret != 1) { + ret = 0; + } + } + else if (ret == 1) { + /* Add certificate to existing chain. */ + ret = wolfssl_ctx_add_to_chain(ctx, der, derSz); + } + + if (ret == 1) { + /* On success WOLFSSL_X509 memory is responsibility of SSL context. */ + wolfSSL_X509_free(x509); + } + + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) +/* Load a certificate into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) +{ + int res = 1; + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); + + /* Validate parameters. */ + if ((ctx == NULL) || (x == NULL) || (x->derCert == NULL)) { + WOLFSSL_MSG("Bad parameter"); + res = 0; + } + + if (res == 1) { + /* Replace certificate buffer with one holding the new certificate. */ + FreeDer(&ctx->certificate); + ret = AllocCopyDer(&ctx->certificate, x->derCert->buffer, + x->derCert->length, CERT_TYPE, ctx->heap); + if (ret != 0) { + res = 0; + } + } + +#ifdef KEEP_OUR_CERT + if (res == 1) { + /* Dispose of our certificate if it is ours. */ + if ((ctx->ourCert != NULL) && ctx->ownOurCert) { + wolfSSL_X509_free(ctx->ourCert); + } + #ifndef WOLFSSL_X509_STORE_CERTS + /* Keep a reference to the new certificate. */ + ctx->ourCert = x; + if (wolfSSL_X509_up_ref(x) != 1) { + res = 0; + } + #else + /* Keep a copy of the new certificate. */ + ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, x->derCert->buffer, + x->derCert->length, ctx->heap); + if (ctx->ourCert == NULL) { + res = 0; + } + #endif + /* Now own our certificate. */ + ctx->ownOurCert = 1; + } +#endif + + if (res == 1) { + /* Set have options based on public key OID. */ + wolfssl_set_have_from_key_oid(ctx, NULL, x->pubKeyOID); + } + + return res; +} + +/* Add the certificate to the chain in the SSL context and own the X509 object. + * + * @param [in, out] ctx SSL context object. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_add0_chain_cert"); + + /* Add certificate to chain and copy or up reference it. */ + ret = wolfSSL_CTX_add1_chain_cert(ctx, x509); + if (ret == 1) { + /* Down reference or free original now as we own certificate. */ + wolfSSL_X509_free(x509); + } + + return ret; +} + +/* Add the certificate to the chain in the SSL context. + * + * X509 object copied or up referenced. + * + * @param [in, out] ctx SSL context object. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_CTX_add1_chain_cert"); + + /* Validate parameters. */ + if ((ctx == NULL) || (x509 == NULL) || (x509->derCert == NULL)) { + ret = 0; + } + + /* Check if we already have set a certificate. */ + if ((ret == 1) && (ctx->certificate == NULL)) { + /* Use the certificate. */ + ret = wolfSSL_CTX_use_certificate(ctx, x509); + } + /* Increate reference count as we will store it. */ + else if ((ret == 1) && ((ret = wolfSSL_X509_up_ref(x509)) == 1)) { + /* Load the DER encoding. */ + ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer, + x509->derCert->length, WOLFSSL_FILETYPE_ASN1); + if (ret == 1) { + /* Add DER encoding to chain. */ + ret = wolfssl_add_to_chain(&ctx->certChain, 1, + x509->derCert->buffer, x509->derCert->length, ctx->heap); + } + /* Store cert in stack to free it later. */ + if ((ret == 1) && (ctx->x509Chain == NULL)) { + /* Create a stack for certificates. */ + ctx->x509Chain = wolfSSL_sk_X509_new_null(); + if (ctx->x509Chain == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_new_null error"); + ret = 0; + } + } + if (ret == 1) { + /* Push the X509 object onto stack. */ + ret = wolfSSL_sk_X509_push(ctx->x509Chain, x509); + } + + if (ret != 1) { + /* Decrease reference count on error as we didn't store it. */ + wolfSSL_X509_free(x509); + } + } + + return WS_RC(ret); +} + +#ifdef KEEP_OUR_CERT +/* Add the certificate to the chain in the SSL and own the X509 object. + * + * @param [in, out] ssl SSL object. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_add0_chain_cert"); + + /* Validate parameters. */ + if ((ssl == NULL) || (ssl->ctx == NULL) || (x509 == NULL) || + (x509->derCert == NULL)) { + ret = 0; + } + + /* Check if we already have set a certificate. */ + if ((ret == 1) && (ssl->buffers.certificate == NULL)) { + /* Use the certificate. */ + ret = wolfSSL_use_certificate(ssl, x509); + if (ret == 1) { + /* Dispose of old certificate if we own it. */ + if (ssl->buffers.weOwnCert) { + wolfSSL_X509_free(ssl->ourCert); + } + /* Store cert to free it later. */ + ssl->ourCert = x509; + ssl->buffers.weOwnCert = 1; + } + } + else if (ret == 1) { + /* Add DER encoding to chain. */ + ret = wolfssl_add_to_chain(&ssl->buffers.certChain, + ssl->buffers.weOwnCertChain, x509->derCert->buffer, + x509->derCert->length, ssl->heap); + if (ret == 1) { + /* We now own cert chain. */ + ssl->buffers.weOwnCertChain = 1; + /* Create a stack to put certificate into. */ + if (ssl->ourCertChain == NULL) { + ssl->ourCertChain = wolfSSL_sk_X509_new_null(); + if (ssl->ourCertChain == NULL) { + WOLFSSL_MSG("wolfSSL_sk_X509_new_null error"); + ret = 0; + } + } + } + if (ret == 1) { + /* Push X509 object onto stack to be freed. */ + ret = wolfSSL_sk_X509_push(ssl->ourCertChain, x509); + if (ret != 1) { + /* Free it now on error. */ + wolfSSL_X509_free(x509); + } + } + } + return WS_RC(ret); +} + +/* Add the certificate to the chain in the SSL. + * + * X509 object is up referenced. + * + * @param [in, out] ssl SSL object. + * @param [in] x509 X509 certificate object. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_add1_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_add1_chain_cert"); + + /* Validate parameters. */ + if ((ssl == NULL) || (ssl->ctx == NULL) || (x509 == NULL) || + (x509->derCert == NULL)) { + ret = 0; + } + + /* Increase reference count on X509 object before adding. */ + if ((ret == 1) && ((ret == wolfSSL_X509_up_ref(x509)) == 1)) { + /* Add this to the chain. */ + if ((ret = wolfSSL_add0_chain_cert(ssl, x509)) != 1) { + /* Decrease reference count on error as not stored. */ + wolfSSL_X509_free(x509); + } + } + + return ret; +} +#endif /* KEEP_OUR_CERT */ +#endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL, + WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY */ + +#ifdef OPENSSL_EXTRA + +/* Load a private key into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] pkey EVP private key. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); + + /* Validate parameters. */ + if ((ctx == NULL) || (pkey == NULL) || (pkey->pkey.ptr == NULL)) { + ret = 0; + } + + if (ret == 1) { + switch (pkey->type) { + #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) + case EVP_PKEY_RSA: + WOLFSSL_MSG("populating RSA key"); + ret = PopulateRSAEvpPkeyDer(pkey); + break; + #endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA */ + #if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \ + defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA) + case EVP_PKEY_DSA: + break; + #endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) && + * !NO_DSA */ + #ifdef HAVE_ECC + case EVP_PKEY_EC: + WOLFSSL_MSG("populating ECC key"); + ret = ECC_populate_EVP_PKEY(pkey, pkey->ecc); + break; + #endif + default: + ret = 0; + } + } + + if (ret == 1) { + /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */ + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, + (const unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, + SSL_FILETYPE_ASN1); + } + + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) +/* Load a DER encoded certificate in a buffer into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] der Buffer holding DER encoded certificate. + * @param [in] derSz Size of data in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz, + const unsigned char *der) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1"); + + /* Validate parameters. */ + if ((ctx == NULL) || (der == NULL)) { + ret = 0; + } + /* Load DER encoded cerificate into SSL context. */ + if ((ret == 1) && (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, + WOLFSSL_FILETYPE_ASN1) != 1)) { + ret = 0; + } + + return ret; +} + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) +/* Load an RSA private key into SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] rsa RSA private key. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ctx or rsa is NULL. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa) +{ + int ret = 1; + int derSize; + unsigned char* der = NULL; + unsigned char* p; + + WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey"); + + /* Validate parameters. */ + if ((ctx == NULL) || (rsa == NULL)) { + WOLFSSL_MSG("one or more inputs were NULL"); + ret = BAD_FUNC_ARG; + } + + /* Get DER encoding size. */ + if ((ret == 1) && ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, NULL)) <= 0)) { + ret = 0; + } + + if (ret == 1) { + /* Allocate memory to hold DER encoding.. */ + der = (unsigned char*)XMALLOC(derSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + WOLFSSL_MSG("Malloc failure"); + ret = MEMORY_E; + } + } + + if (ret == 1) { + /* Pointer passed in is modified.. */ + p = der; + /* Encode the RSA key as DER into buffer and get size. */ + if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &p)) <= 0) { + WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure"); + ret = 0; + } + } + + if (ret == 1) { + /* Load DER encoded cerificate into SSL context. */ + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSize, + SSL_FILETYPE_ASN1); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure"); + ret = 0; + } + } + + /* Dispos of dynamically allocated data. */ + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} +#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ + +#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */ + +#endif /* !NO_CERTS */ + +#ifdef OPENSSL_EXTRA + +/* Use the default paths to look for CA certificate. + * + * This is an OpenSSL compatibility layer function, but it doesn't mirror + * the exact functionality of its OpenSSL counterpart. We don't support the + * notion of an "OpenSSL directory". This function will attempt to load the + * environment variables SSL_CERT_DIR and SSL_CERT_FILE, if either are + * found, they will be loaded. Otherwise, it will act as a wrapper around + * our native wolfSSL_CTX_load_system_CA_certs function. This function does + * conform to OpenSSL's return value conventions. + * + * @param [in] ctx SSL context object. + * @return 1 on success. + * @return 0 on failure. + * @return WOLFSSL_FATAL_ERROR when using a filesystem is not supported. + */ +int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) +{ + int ret; +#ifdef XGETENV + char* certDir; + char* certFile; + word32 flags; +#elif !defined(WOLFSSL_SYS_CA_CERTS) + (void)ctx; +#endif + + WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths"); + +#ifdef XGETENV + certDir = XGETENV("SSL_CERT_DIR"); + certFile = XGETENV("SSL_CERT_FILE"); + flags = WOLFSSL_LOAD_FLAG_PEM_CA_ONLY; + + if ((certDir != NULL) || (certFile != NULL)) { + if (certDir != NULL) { + /* We want to keep trying to load more CA certs even if one cert in + * the directory is bad and can't be used (e.g. if one is + * expired), so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR. + */ + flags |= WOLFSSL_LOAD_FLAG_IGNORE_ERR; + } + + /* Load CA certificates from environment variable locations. */ + ret = wolfSSL_CTX_load_verify_locations_ex(ctx, certFile, certDir, + flags); + if (ret != 1) { + WOLFSSL_MSG_EX("Failed to load CA certs from SSL_CERT_FILE: %s" + " SSL_CERT_DIR: %s. Error: %d", certFile, + certDir, ret); + ret = 0; + } + } + else +#endif + + { + #ifdef NO_FILESYSTEM + WOLFSSL_MSG("wolfSSL_CTX_set_default_verify_paths not supported" + " with NO_FILESYSTEM enabled"); + ret = WOLFSSL_FATAL_ERROR; + #elif defined(WOLFSSL_SYS_CA_CERTS) + /* Load the system CA certificates. */ + ret = wolfSSL_CTX_load_system_CA_certs(ctx); + if (ret == WOLFSSL_BAD_PATH) { + /* OpenSSL doesn't treat the lack of a system CA cert directory as a + * failure. We do the same here. + */ + ret = 1; + } + #else + /* OpenSSL's implementation of this API does not require loading the + system CA cert directory. Allow skipping this without erroring out. */ + ret = 1; + #endif + } + + WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret); + + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_DH + +/* Set the temporary DH parameters against the SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] p Buffer holding prime. + * @param [in] pSz Length of prime in bytes. + * @param [in] g Buffer holding generator. + * @param [in] gSz Length of generator in bytes. + * @return 1 on success. + * @return 0 on failure. + * @return DH_KEY_SIZE_E when the prime is too short or long. + * @return SIDE_ERROR when the SSL is for a client. + */ +static int wolfssl_set_tmp_dh(WOLFSSL* ssl, unsigned char* p, int pSz, + unsigned char* g, int gSz) +{ + int ret = 1; + + /* Check the size of the prime meets the requirements of the SSL. */ + if (((word16)pSz < ssl->options.minDhKeySz) || + ((word16)pSz > ssl->options.maxDhKeySz)) { + ret = DH_KEY_SIZE_E; + } + /* Only able to set DH parameters on server. */ + if ((ret == 1) && (ssl->options.side == WOLFSSL_CLIENT_END)) { + ret = SIDE_ERROR; + } + + if (ret == 1) { + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + /* New DH parameters not tested for validity. */ + ssl->options.dhKeyTested = 0; + /* New DH parameters must be tested for validity before use. */ + ssl->options.dhDoKeyTest = 1; + #endif + + /* Dispose of old DH parameters if we own it. */ + if (ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + + /* Assign the buffers and lengths to SSL. */ + ssl->buffers.serverDH_P.buffer = p; + ssl->buffers.serverDH_G.buffer = g; + ssl->buffers.serverDH_P.length = (unsigned int)pSz; + ssl->buffers.serverDH_G.length = (unsigned int)gSz; + /* We own the buffers. */ + ssl->buffers.weOwnDH = 1; + /* We have a DH parameters to use. */ + ssl->options.haveDH = 1; + } + + /* Allocate space for cipher suites. */ + if ((ret == 1) && (AllocateSuites(ssl) != 0)) { + ssl->buffers.serverDH_P.buffer = NULL; + ssl->buffers.serverDH_G.buffer = NULL; + ret = 0; + } + if (ret == 1) { + /* Reset the cipher suites based on having a DH parameters now. */ + InitSuites(ssl->suites, ssl->version, SSL_KEY_SZ(ssl), + WOLFSSL_HAVE_RSA, SSL_HAVE_PSK(ssl), ssl->options.haveDH, + ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE, + ssl->options.haveStaticECC, ssl->options.haveFalconSig, + ssl->options.haveDilithiumSig, ssl->options.useAnon, TRUE, + ssl->options.side); + } + + return ret; +} + +/* Set the temporary DH parameters against the SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] p Buffer holding prime. + * @param [in] pSz Length of prime in bytes. + * @param [in] g Buffer holding generator. + * @param [in] gSz Length of generator in bytes. + * @return 1 on success. + * @return 0 on failure. + * @return DH_KEY_SIZE_E when the prime is too short or long. + * @return SIDE_ERROR when the SSL is for a client. + * @return MEMORY_E when dynamic memory allocation fails. + */ +int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, + const unsigned char* g, int gSz) +{ + int ret = 1; + byte* pAlloc = NULL; + byte* gAlloc = NULL; + + WOLFSSL_ENTER("wolfSSL_SetTmpDH"); + + /* Validate parameters. */ + if ((ssl == NULL) || (p == NULL) || (g == NULL)) { + ret = 0; + } + + if (ret == 1) { + /* Allocate buffers for p and g to be assigned into SSL. */ + pAlloc = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + gAlloc = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if ((pAlloc == NULL) || (gAlloc == NULL)) { + ret = MEMORY_E; + } + } + if (ret == 1) { + /* Copy p and g into allocated buffers. */ + XMEMCPY(pAlloc, p, pSz); + XMEMCPY(gAlloc, g, gSz); + /* Set the buffers into SSL. */ + ret = wolfssl_set_tmp_dh(ssl, pAlloc, pSz, gAlloc, gSz); + } + + if (ret != 1 && ssl != NULL) { + /* Free the allocated buffers if not assigned into SSL. */ + XFREE(pAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(gAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + + WOLFSSL_LEAVE("wolfSSL_SetTmpDH", ret); + return ret; +} + +#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) +/* Check the DH parameters is valid. + * + * @param [in] p Buffer holding prime. + * @param [in] pSz Length of prime in bytes. + * @param [in] g Buffer holding generator. + * @param [in] gSz Length of generator in bytes. + * @return 1 on success. + * @return DH_CHECK_PUB_E when p is not a prime. + * @return BAD_FUNC_ARG when p or g is NULL, or pSz or gSz is 0. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int wolfssl_check_dh_key(unsigned char* p, int pSz, unsigned char* g, + int gSz) +{ + WC_RNG rng; + int ret = 0; +#ifndef WOLFSSL_SMALL_STACK + DhKey checkKey[1]; +#else + DhKey *checkKey; +#endif + +#ifdef WOLFSSL_SMALL_STACK + checkKey = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); + if (checkKey == NULL) { + ret = MEMORY_E; + } +#endif + /* Initialize a new random number generator. */ + if ((ret == 0) && ((ret = wc_InitRng(&rng)) == 0)) { + /* Initialize a DH object. */ + if ((ret = wc_InitDhKey(checkKey)) == 0) { + /* Check DH parameters. */ + ret = wc_DhSetCheckKey(checkKey, p, (word32)pSz, g, gSz, NULL, 0, 0, &rng); + /* Dispose of DH object. */ + wc_FreeDhKey(checkKey); + } + /* Dispose of random number generator. */ + wc_FreeRng(&rng); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of dynamically allocated data. */ + XFREE(checkKey, NULL, DYNAMIC_TYPE_DH); +#endif + /* Convert wolfCrypt return code to 1 on success and ret on failure. */ + return WC_TO_WS_RC(ret); +} +#endif + +/* Set the temporary DH parameters against the SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] p Buffer holding prime. + * @param [in] pSz Length of prime in bytes. + * @param [in] g Buffer holding generator. + * @param [in] gSz Length of generator in bytes. + * @return 1 on success. + * @return 0 on failure. + * @return DH_KEY_SIZE_E when the prime is too short or long. + * @return SIDE_ERROR when the SSL is for a client. + * @return BAD_FUNC_ARG when ctx, p or g is NULL. + * @return DH_CHECK_PUB_E when p is not a prime. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int wolfssl_ctx_set_tmp_dh(WOLFSSL_CTX* ctx, unsigned char* p, int pSz, + unsigned char* g, int gSz) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH"); + + /* Check the size of the prime meets the requirements of the SSL context. */ + if (((word16)pSz < ctx->minDhKeySz) || ((word16)pSz > ctx->maxDhKeySz)) { + ret = DH_KEY_SIZE_E; + } + +#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + if (ret == 1) { + /* Test DH parameters for validity. */ + ret = wolfssl_check_dh_key(p, pSz, g, gSz); + /* Record as whether tested based on result of validity test. */ + ctx->dhKeyTested = (ret == 1); + } +#endif + + if (ret == 1) { + /* Dispose of old DH parameters. */ + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + /* Assign the buffers and lengths to SSL context. */ + ctx->serverDH_P.buffer = p; + ctx->serverDH_G.buffer = g; + ctx->serverDH_P.length = (unsigned int)pSz; + ctx->serverDH_G.length = (unsigned int)gSz; + /* We have a DH parameters to use. */ + ctx->haveDH = 1; + } + + WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0); + return ret; +} + +/* Set the temporary DH parameters against the SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] p Buffer holding prime. + * @param [in] pSz Length of prime in bytes. + * @param [in] g Buffer holding generator. + * @param [in] gSz Length of generator in bytes. + * @return 1 on success. + * @return 0 on failure. + * @return DH_KEY_SIZE_E when the prime is too short or long. + * @return SIDE_ERROR when the SSL is for a client. + * @return BAD_FUNC_ARG when ctx, p or g is NULL. + * @return DH_CHECK_PUB_E when p is not a prime. + */ +int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, + const unsigned char* g, int gSz) +{ + int ret = 1; + byte* pAlloc = NULL; + byte* gAlloc = NULL; + + /* Validate parameters. */ + if ((ctx == NULL) || (p == NULL) || (g == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 1) { + /* Allocate buffers for p and g to be assigned into SSL context. */ + pAlloc = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + gAlloc = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if ((pAlloc == NULL) || (gAlloc == NULL)) { + XFREE(pAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + pAlloc = NULL; + XFREE(gAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + gAlloc = NULL; + ret = MEMORY_E; + } + } + + if (ret == 1) { + /* Copy p and g into allocated buffers. */ + XMEMCPY(pAlloc, p, pSz); + XMEMCPY(gAlloc, g, gSz); + /* Set the buffers into SSL context. */ + ret = wolfssl_ctx_set_tmp_dh(ctx, pAlloc, pSz, gAlloc, gSz); + } + + if (ret != 1) { + /* Free the allocated buffers if not assigned into SSL context. */ + if (pAlloc) + XFREE(pAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (gAlloc) + XFREE(gAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + return ret; +} + +#ifdef OPENSSL_EXTRA +/* Set the temporary DH parameters against the SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] dh DH object. + * @return 1 on success. + * @return 0 on failure. + * @return WOLFSSL_FATAL_ERROR on failure. + * @return BAD_FUNC_ARG when ssl or dh is NULL. + * @return DH_KEY_SIZE_E when the prime is too short or long. + * @return SIDE_ERROR when the SSL is for a client. + */ +long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) +{ + int ret = 1; + byte* p = NULL; + byte* g = NULL; + int pSz = 0; + int gSz = 0; + + WOLFSSL_ENTER("wolfSSL_set_tmp_dh"); + + /* Validate parameters. */ + if ((ssl == NULL) || (dh == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 1) { + /* Get needed size for p and g. */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + /* Validate p and g size. */ + if ((pSz <= 0) || (gSz <= 0)) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (ret == 1) { + /* Allocate buffers for p and g to be assigned into SSL. */ + p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if ((p == NULL) || (g == NULL)) { + ret = MEMORY_E; + } + } + if (ret == 1) { + /* Encode p and g and get sizes. */ + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + /* Check encoding worked. */ + if ((pSz <= 0) || (gSz <= 0)) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 1) { + /* Set the buffers into SSL. */ + ret = wolfssl_set_tmp_dh(ssl, p, pSz, g, gSz); + } + + if (ret != 1 && ssl != NULL) { + /* Free the allocated buffers if not assigned into SSL. */ + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + return ret; +} + +/* Set the temporary DH parameters object against the SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] dh DH object. + * @return 1 on success. + * @return 0 on failure. + * @return DH_KEY_SIZE_E when the prime is too short or long. + * @return SIDE_ERROR when the SSL is for a client. + * @return BAD_FUNC_ARG when ctx, p or g is NULL. + * @return DH_CHECK_PUB_E when p is not a prime. + */ +long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) +{ + int ret = 1; + int pSz = 0; + int gSz = 0; + byte* p = NULL; + byte* g = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh"); + + /* Validate parameters. */ + if ((ctx == NULL) || (dh == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 1) { + /* Get needed size for p and g. */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + /* Validate p and g size. */ + if ((pSz <= 0) || (gSz <= 0)) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (ret == 1) { + /* Allocate buffers for p and g to be assigned into SSL. */ + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if ((p == NULL) || (g == NULL)) { + ret = MEMORY_E; + } + } + + if (ret == 1) { + /* Encode p and g and get sizes. */ + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + /* Check encoding worked. */ + if ((pSz < 0) && (gSz < 0)) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 1) { + /* Set the buffers into SSL context. */ + ret = wolfssl_ctx_set_tmp_dh(ctx, p, pSz, g, gSz); + } + + if (ret != 1 && ctx != NULL) { + /* Free the allocated buffers if not assigned into SSL. */ + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_CERTS + +/* Set the temporary DH parameters against the SSL context or SSL. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] buf Buffer holding encoded DH parameters. + * @param [in] sz Size of encoded DH parameters. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return 0 on failure. + * @return BAD_FUNC_ARG when ctx and ssl NULL or buf is NULL. + * @return NOT_COMPLED_IN when format is PEM but PEM is not supported. + * @return WOLFSSL_BAD_FILETYPE if format is not supported. + */ +static int ws_ctx_ssl_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const unsigned char* buf, long sz, int format) +{ + DerBuffer* der = NULL; + int res = 1; + int ret; + /* p and g size to allocate set to maximum valid size. */ + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + byte* p = NULL; + byte* g = NULL; + void* heap = WOLFSSL_HEAP(ctx, ssl); + + /* Validate parameters. */ + if (((ctx == NULL) && (ssl == NULL)) || (buf == NULL)) { + res = BAD_FUNC_ARG; + } + /* Check format is supported. */ + if ((res == 1) && (format != WOLFSSL_FILETYPE_ASN1)) { + if (format != WOLFSSL_FILETYPE_PEM) { + res = WOLFSSL_BAD_FILETYPE; + } + #ifndef WOLFSSL_PEM_TO_DER + else { + res = NOT_COMPILED_IN; + } + #endif + } + + /* PemToDer allocates its own DER buffer. */ + if ((res == 1) && (format != WOLFSSL_FILETYPE_PEM)) { + /* Create an empty DER buffer. */ + ret = AllocDer(&der, 0, DH_PARAM_TYPE, heap); + if (ret == 0) { + /* Assign encoded DH parameters to DER buffer. */ + der->buffer = (byte*)buf; + der->length = (word32)sz; + } + else { + res = ret; + } + } + + if (res == 1) { + /* Allocate enough memory to p and g to support valid use cases. */ + p = (byte*)XMALLOC(pSz, heap, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, heap, DYNAMIC_TYPE_PUBLIC_KEY); + if ((p == NULL) || (g == NULL)) { + res = MEMORY_E; + } + } + +#ifdef WOLFSSL_PEM_TO_DER + if ((res == 1) && (format == WOLFSSL_FILETYPE_PEM)) { + /* Convert from PEM to DER. */ + /* Try converting DH parameters from PEM to DER. */ + ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, heap, NULL, NULL); + if (ret < 0) { + /* Otherwise, try converting X9.43 format DH parameters. */ + ret = PemToDer(buf, sz, X942_PARAM_TYPE, &der, heap, NULL, NULL); + } + #if defined(WOLFSSL_WPAS) && !defined(NO_DSA) + if (ret < 0) { + /* Otherwise, try converting DSA parameters. */ + ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, heap, NULL, NULL); + } + #endif /* WOLFSSL_WPAS && !NO_DSA */ + if (ret < 0) { + /* Return error from conversion. */ + res = ret; + } + } +#endif /* WOLFSSL_PEM_TO_DER */ + + if (res == 1) { + /* Get the p and g from the DER encoded parameters. */ + if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) { + res = WOLFSSL_BAD_FILETYPE; + } + else if (ssl != NULL) { + /* Set p and g into SSL. */ + res = wolfssl_set_tmp_dh(ssl, p, (int)pSz, g, gSz); + } + else { + /* Set p and g into SSL context. */ + res = wolfssl_ctx_set_tmp_dh(ctx, p, (int)pSz, g, gSz); + } + } + + /* Dispose of the DER buffer. */ + FreeDer(&der); + if (res != 1) { + /* Free the allocated buffers if not assigned into SSL or context. */ + XFREE(p, heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + return res; +} + + +/* Set the temporary DH parameters against the SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] buf Buffer holding encoded DH parameters. + * @param [in] sz Size of encoded DH parameters. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return BAD_FUNC_ARG when ssl or buf is NULL. + * @return NOT_COMPLED_IN when format is PEM but PEM is not supported. + * @return WOLFSSL_BAD_FILETYPE if format is not supported. + */ +int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz, + int format) +{ + return ws_ctx_ssl_set_tmp_dh(NULL, ssl, buf, sz, format); +} + + +/* Set the temporary DH parameters against the SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] buf Buffer holding encoded DH parameters. + * @param [in] sz Size of encoded DH parameters. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return BAD_FUNC_ARG when ctx or buf is NULL. + * @return NOT_COMPLED_IN when format is PEM but PEM is not supported. + * @return WOLFSSL_BAD_FILETYPE if format is not supported. + */ +int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf, + long sz, int format) +{ + return ws_ctx_ssl_set_tmp_dh(ctx, NULL, buf, sz, format); +} + +#ifndef NO_FILESYSTEM + +/* Set the temporary DH parameters file against the SSL context or SSL. + * + * @param [in, out] ctx SSL context object. + * @param [in, out] ssl SSL object. + * @param [in] fname Name of file to load. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return BAD_FUNC_ARG when ctx and ssl NULL or fname is NULL. + * @return NOT_COMPLED_IN when format is PEM but PEM is not supported. + * @return WOLFSSL_BAD_FILETYPE if format is not supported. + */ +static int ws_ctx_ssl_set_tmp_dh_file(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const char* fname, int format) +{ + int res = 1; + int ret; +#ifndef WOLFSSL_SMALL_STACK + byte stackBuffer[FILE_BUFFER_SIZE]; +#endif + StaticBuffer dhFile; + long sz = 0; + void* heap = WOLFSSL_HEAP(ctx, ssl); + + /* Setup buffer to hold file contents. */ +#ifdef WOLFSSL_SMALL_STACK + static_buffer_init(&dhFile); +#else + static_buffer_init(&dhFile, stackBuffer, FILE_BUFFER_SIZE); +#endif + + /* Validate parameters. */ + if (((ctx == NULL) && (ssl == NULL)) || (fname == NULL)) { + res = BAD_FUNC_ARG; + } + + if (res == 1) { + /* Read file into static buffer. */ + ret = wolfssl_read_file_static(fname, &dhFile, heap, DYNAMIC_TYPE_FILE, + &sz); + if (ret != 0) { + res = ret; + } + } + if (res == 1) { + if (ssl != NULL) { + /* Set encoded DH parameters into SSL. */ + res = wolfSSL_SetTmpDH_buffer(ssl, dhFile.buffer, sz, format); + } + else { + /* Set encoded DH parameters into SSL context. */ + res = wolfSSL_CTX_SetTmpDH_buffer(ctx, dhFile.buffer, sz, format); + } + } + + /* Dispose of any dynamically allocated data. */ + static_buffer_free(&dhFile, heap, DYNAMIC_TYPE_FILE); + return res; +} + +/* Set the temporary DH parameters file against the SSL. + * + * @param [in, out] ssl SSL object. + * @param [in] fname Name of file to load. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return BAD_FUNC_ARG when ssl or fname is NULL. + * @return NOT_COMPLED_IN when format is PEM but PEM is not supported. + * @return WOLFSSL_BAD_FILETYPE if format is not supported. + */ +int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format) +{ + return ws_ctx_ssl_set_tmp_dh_file(NULL, ssl, fname, format); +} + + +/* Set the temporary DH parameters file against the SSL context. + * + * @param [in, out] ctx SSL context object. + * @param [in] fname Name of file to load. + * @param [in] format Format of data: + * WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1. + * @return 1 on success. + * @return BAD_FUNC_ARG when ctx or fname is NULL. + * @return NOT_COMPLED_IN when format is PEM but PEM is not supported. + * @return WOLFSSL_BAD_FILETYPE if format is not supported. + */ +int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) +{ + return ws_ctx_ssl_set_tmp_dh_file(ctx, NULL, fname, format); +} + +#endif /* NO_FILESYSTEM */ + +#endif /* NO_CERTS */ + +#endif /* !NO_DH */ + +#endif /* !WOLFSSL_SSL_LOAD_INCLUDED */ + diff --git a/src/src/ssl_misc.c b/src/src/ssl_misc.c index 9bc42dd..d52c2cd 100644 --- a/src/src/ssl_misc.c +++ b/src/src/ssl_misc.c @@ -24,6 +24,8 @@ #endif #include +#include +#include #if !defined(WOLFSSL_SSL_MISC_INCLUDED) #ifndef WOLFSSL_IGNORE_FILE_WARN @@ -54,7 +56,7 @@ static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data) char* p; /* Allocate buffer to hold a chunk of data. */ - mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = (char*)XMALLOC(READ_BIO_FILE_CHUNK, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (mem == NULL) { WOLFSSL_ERROR_MSG("Memory allocation error"); ret = MEMORY_E; @@ -86,8 +88,8 @@ static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data) } else { /* No space left for more data to be read - add a chunk. */ - p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, bio->heap, - DYNAMIC_TYPE_OPENSSL); + p = (char*)XREALLOC(mem, ret + READ_BIO_FILE_CHUNK, NULL, + DYNAMIC_TYPE_TMP_BUFFER); if (p == NULL) { sz = MEMORY_E; break; @@ -103,7 +105,7 @@ static int wolfssl_read_bio_file(WOLFSSL_BIO* bio, char** data) } if ((sz < 0) || (ret == 0)) { /* Dispose of memory on error or no data read. */ - XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER); mem = NULL; /* Return error. */ ret = sz; @@ -129,14 +131,14 @@ static int wolfssl_read_bio_len(WOLFSSL_BIO* bio, int sz, char** data) char* mem; /* Allocate buffer to hold data. */ - mem = (char*)XMALLOC((size_t)sz, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = (char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (mem == NULL) { WOLFSSL_ERROR_MSG("Memory allocation error"); ret = MEMORY_E; } else if ((ret = wolfSSL_BIO_read(bio, mem, sz)) != sz) { /* Pending data not read. */ - XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER); mem = NULL; ret = MEMORY_E; } @@ -206,9 +208,7 @@ static int wolfssl_read_bio(WOLFSSL_BIO* bio, char** data, int* dataSz, #endif /* OPENSSL_EXTRA && !WOLFCRYPT_ONLY */ #if (defined(OPENSSL_EXTRA) || defined(PERSIST_CERT_CACHE) || \ - (!defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \ - !defined(WOLFSSL_NO_CLIENT_AUTH)))) && !defined(WOLFCRYPT_ONLY) && \ - !defined(NO_FILESYSTEM) + !defined(NO_CERTS)) && !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM) /* Read all the data from a file. * * @param [in] fp File pointer to read with. @@ -299,5 +299,204 @@ static int wolfssl_read_file(XFILE fp, char** data, int* dataSz) } #endif /* (OPENSSL_EXTRA || PERSIST_CERT_CACHE) && !WOLFCRYPT_ONLY && * !NO_FILESYSTEM */ + +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) + +#ifdef WOLFSSL_SMALL_STACK + +/* Buffer and size with no stack buffer. */ +typedef struct { + /* Dynamically allocated buffer. */ + byte* buffer; + /* Size of buffer in bytes. */ + word32 sz; +} StaticBuffer; + +/* Initialize static buffer. + * + * @param [in, out] sb Static buffer. + */ +static void static_buffer_init(StaticBuffer* sb) +{ + sb->buffer = NULL; + sb->sz = 0; +} + +/* Set the size of the buffer. + * + * Can only set size once. + * + * @param [in] sb Static buffer. + * @param [in] len Length required. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] type Type of dynamic memory. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap, + int type) +{ + int ret = 0; + + (void)heap; + (void)type; + + sb->buffer = (byte*)XMALLOC(len, heap, type); + if (sb->buffer == NULL) { + ret = MEMORY_E; + } + else { + sb->sz = len; + } + + return ret; +} + +/* Dispose of dynamically allocated buffer. + * + * @param [in] sb Static buffer. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] type Type of dynamic memory. + */ +static void static_buffer_free(StaticBuffer* sb, void* heap, int type) +{ + (void)heap; + (void)type; + XFREE(sb->buffer, heap, type); +} + +#else + +/* Buffer and size with stack buffer set and option to dynamically allocate. */ +typedef struct { + /* Stack or heap buffer. */ + byte* buffer; + /* Size of buffer in bytes. */ + word32 sz; + /* Indicates whether the buffer was dynamically allocated. */ + int dyn; +} StaticBuffer; + +/* Initialize static buffer. + * + * @param [in, out] sb Static buffer. + * @param [in] stackBuffer Buffer allocated on the stack. + * @param [in] len Length of stack buffer. + */ +static void static_buffer_init(StaticBuffer* sb, byte* stackBuffer, word32 len) +{ + sb->buffer = stackBuffer; + sb->sz = len; + sb->dyn = 0; +} + +/* Set the size of the buffer. + * + * Pre: Buffer on the stack set with its size. + * Can only set size once. + * + * @param [in] sb Static buffer. + * @param [in] len Length required. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] type Type of dynamic memory. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + */ +static int static_buffer_set_size(StaticBuffer* sb, word32 len, void* heap, + int type) +{ + int ret = 0; + + (void)heap; + (void)type; + + if (len > sb->sz) { + byte* buff = (byte*)XMALLOC(len, heap, type); + if (buff == NULL) { + ret = MEMORY_E; + } + else { + sb->buffer = buff; + sb->sz = len; + sb->dyn = 1; + } + } + + return ret; +} + +/* Dispose of dynamically allocated buffer. + * + * @param [in] sb Static buffer. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] type Type of dynamic memory. + */ +static void static_buffer_free(StaticBuffer* sb, void* heap, int type) +{ + (void)heap; + (void)type; + + if (sb->dyn) { + XFREE(sb->buffer, heap, type); + } +} + +#endif /* WOLFSSL_SMALL_STACK */ + +#ifndef NO_FILESYSTEM + +/* Read all the data from a file into content. + * + * @param [in] fname File pointer to read with. + * @param [in, out] content Read data in an allocated buffer. + * @param [in] heap Dynamic memory allocation hint. + * @param [in] type Type of dynamic memory. + * @param [out] size Amount of data read in bytes. + * @return 0 on success. + * @return WOLFSSL_BAD_FILE when reading fails. + * @return MEMORY_E when memory allocation fails. + */ +static int wolfssl_read_file_static(const char* fname, StaticBuffer* content, + void* heap, int type, long* size) +{ + int ret = 0; + XFILE file = XBADFILE; + long sz = 0; + + /* Check filename is usable. */ + if (fname == NULL) { + ret = WOLFSSL_BAD_FILE; + } + /* Open file for reading. */ + if ((ret == 0) && ((file = XFOPEN(fname, "rb")) == XBADFILE)) { + ret = WOLFSSL_BAD_FILE; + } + if (ret == 0) { + /* Get length of file. */ + ret = wolfssl_file_len(file, &sz); + } + if (ret == 0) { + /* Set the buffer to be big enough to hold all data. */ + ret = static_buffer_set_size(content, (word32)sz, heap, type); + } + /* Read data from file. */ + if ((ret == 0) && ((size_t)XFREAD(content->buffer, 1, (size_t)sz, file) != + (size_t)sz)) { + ret = WOLFSSL_BAD_FILE; + } + + /* Close file if opened. */ + if (file != XBADFILE) { + XFCLOSE(file); + } + /* Return size read. */ + *size = sz; + return ret; +} + +#endif /* !NO_FILESYSTEM */ + +#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */ + #endif /* !WOLFSSL_SSL_MISC_INCLUDED */ diff --git a/src/src/ssl_p7p12.c b/src/src/ssl_p7p12.c new file mode 100644 index 0000000..11b6c40 --- /dev/null +++ b/src/src/ssl_p7p12.c @@ -0,0 +1,2123 @@ +/* ssl_p7p12.c + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(OPENSSL_EXTRA) && (defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) + #include +#endif +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) + #include +#endif + +#if !defined(WOLFSSL_SSL_P7P12_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning ssl_p7p12.c does not need to be compiled separately from ssl.c + #endif +#else + +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) + +/******************************************************************************* + * START OF PKCS7 APIs + ******************************************************************************/ +#ifdef HAVE_PKCS7 + +#ifdef OPENSSL_ALL +PKCS7* wolfSSL_PKCS7_new(void) +{ + WOLFSSL_PKCS7* pkcs7; + int ret = 0; + + pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(WOLFSSL_PKCS7), NULL, + DYNAMIC_TYPE_PKCS7); + if (pkcs7 != NULL) { + XMEMSET(pkcs7, 0, sizeof(WOLFSSL_PKCS7)); + ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID); + } + + if (ret != 0 && pkcs7 != NULL) { + XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7); + pkcs7 = NULL; + } + + return (PKCS7*)pkcs7; +} + +/****************************************************************************** +* wolfSSL_PKCS7_SIGNED_new - allocates PKCS7 and initialize it for a signed data +* +* RETURNS: +* returns pointer to the PKCS7 structure on success, otherwise returns NULL +*/ +PKCS7_SIGNED* wolfSSL_PKCS7_SIGNED_new(void) +{ + byte signedData[]= { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02}; + PKCS7* pkcs7 = NULL; + + if ((pkcs7 = wolfSSL_PKCS7_new()) == NULL) + return NULL; + pkcs7->contentOID = SIGNED_DATA; + if ((wc_PKCS7_SetContentType(pkcs7, signedData, sizeof(signedData))) < 0) { + if (pkcs7) { + wolfSSL_PKCS7_free(pkcs7); + return NULL; + } + } + return pkcs7; +} + +void wolfSSL_PKCS7_free(PKCS7* pkcs7) +{ + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (p7 != NULL) { + if (p7->data != NULL) + XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_Free(&p7->pkcs7); + if (p7->certs) + wolfSSL_sk_pop_free(p7->certs, NULL); + XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7); + } +} + +void wolfSSL_PKCS7_SIGNED_free(PKCS7_SIGNED* p7) +{ + wolfSSL_PKCS7_free(p7); + return; +} + +/** + * Convert DER/ASN.1 encoded signedData structure to internal PKCS7 + * structure. Note, does not support detached content. + * + * p7 - pointer to set to address of newly created PKCS7 structure on return + * in - pointer to pointer of DER/ASN.1 data + * len - length of input data, bytes + * + * Returns newly allocated and populated PKCS7 structure or NULL on error. + */ +PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) +{ + return wolfSSL_d2i_PKCS7_ex(p7, in, len, NULL, 0); +} + +/* This internal function is only decoding and setting up the PKCS7 struct. It +* does not verify the PKCS7 signature. +* +* RETURNS: +* returns pointer to a PKCS7 structure on success, otherwise returns NULL +*/ +static PKCS7* wolfSSL_d2i_PKCS7_only(PKCS7** p7, const unsigned char** in, + int len, byte* content, word32 contentSz) +{ + WOLFSSL_PKCS7* pkcs7 = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex"); + + if (in == NULL || *in == NULL || len < 0) + return NULL; + + if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) + return NULL; + + pkcs7->len = len; + pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7->data == NULL) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + XMEMCPY(pkcs7->data, *in, pkcs7->len); + + if (content != NULL) { + pkcs7->pkcs7.content = content; + pkcs7->pkcs7.contentSz = contentSz; + } + + if (p7 != NULL) + *p7 = (PKCS7*)pkcs7; + *in += pkcs7->len; + return (PKCS7*)pkcs7; +} + + +/***************************************************************************** +* wolfSSL_d2i_PKCS7_ex - Converts the given unsigned char buffer of size len +* into a PKCS7 object. Optionally, accepts a byte buffer of content which +* is stored as the PKCS7 object's content, to support detached signatures. +* @param content The content which is signed, in case the signature is +* detached. Ignored if NULL. +* @param contentSz The size of the passed in content. +* +* RETURNS: +* returns pointer to a PKCS7 structure on success, otherwise returns NULL +*/ +PKCS7* wolfSSL_d2i_PKCS7_ex(PKCS7** p7, const unsigned char** in, int len, + byte* content, word32 contentSz) +{ + WOLFSSL_PKCS7* pkcs7 = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_ex"); + + if (in == NULL || *in == NULL || len < 0) + return NULL; + + pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_d2i_PKCS7_only(p7, in, len, content, + contentSz); + if (pkcs7 != NULL) { + if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len) + != 0) { + WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed"); + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + if (p7 != NULL) { + *p7 = NULL; + } + return NULL; + } + } + + return (PKCS7*)pkcs7; +} + + +/** + * This API was added as a helper function for libest. It + * extracts a stack of certificates from the pkcs7 object. + * @param pkcs7 PKCS7 parameter object + * @return WOLFSSL_STACK_OF(WOLFSSL_X509)* + */ +WOLFSSL_STACK* wolfSSL_PKCS7_to_stack(PKCS7* pkcs7) +{ + int i; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_PKCS7_to_stack"); + + if (!p7) { + WOLFSSL_MSG("Bad parameter"); + return NULL; + } + + if (p7->certs) + return p7->certs; + + for (i = 0; i < MAX_PKCS7_CERTS && p7->pkcs7.cert[i]; i++) { + WOLFSSL_X509* x509 = wolfSSL_X509_d2i_ex(NULL, p7->pkcs7.cert[i], + p7->pkcs7.certSz[i], pkcs7->heap); + if (!ret) + ret = wolfSSL_sk_X509_new_null(); + if (x509) { + if (wolfSSL_sk_X509_push(ret, x509) != WOLFSSL_SUCCESS) { + wolfSSL_X509_free(x509); + WOLFSSL_MSG("wolfSSL_sk_X509_push error"); + goto error; + } + } + else { + WOLFSSL_MSG("wolfSSL_X509_d2i error"); + goto error; + } + } + + /* Save stack to free later */ + if (p7->certs) + wolfSSL_sk_pop_free(p7->certs, NULL); + p7->certs = ret; + + return ret; +error: + if (ret) { + wolfSSL_sk_pop_free(ret, NULL); + } + return NULL; +} + +/** + * Return stack of signers contained in PKCS7 cert. + * Notes: + * - Currently only PKCS#7 messages with a single signer cert is supported. + * - Returned WOLFSSL_STACK must be freed by caller. + * + * pkcs7 - PKCS7 struct to retrieve signer certs from. + * certs - currently unused + * flags - flags to control function behavior. + * + * Return WOLFSSL_STACK of signers on success, NULL on error. + */ +WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs, + int flags) +{ + WOLFSSL_X509* x509 = NULL; + WOLFSSL_STACK* signers = NULL; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (p7 == NULL) + return NULL; + + /* Only PKCS#7 messages with a single cert that is the verifying certificate + * is supported. + */ + if (flags & PKCS7_NOINTERN) { + WOLFSSL_MSG("PKCS7_NOINTERN flag not supported"); + return NULL; + } + + signers = wolfSSL_sk_X509_new_null(); + if (signers == NULL) + return NULL; + + if (wolfSSL_d2i_X509(&x509, (const byte**)&p7->pkcs7.singleCert, + p7->pkcs7.singleCertSz) == NULL) { + wolfSSL_sk_X509_pop_free(signers, NULL); + return NULL; + } + + if (wolfSSL_sk_X509_push(signers, x509) != WOLFSSL_SUCCESS) { + wolfSSL_sk_X509_pop_free(signers, NULL); + return NULL; + } + + (void)certs; + + return signers; +} + +#ifndef NO_BIO + +PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7) +{ + WOLFSSL_PKCS7* pkcs7; + int ret; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS7_bio"); + + if (bio == NULL) + return NULL; + + if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) + return NULL; + + pkcs7->len = wolfSSL_BIO_get_len(bio); + pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7->data == NULL) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + + if ((ret = wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len)) <= 0) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + /* pkcs7->len may change if using b64 for example */ + pkcs7->len = ret; + + if (wc_PKCS7_VerifySignedData(&pkcs7->pkcs7, pkcs7->data, pkcs7->len) + != 0) { + WOLFSSL_MSG("wc_PKCS7_VerifySignedData failed"); + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + + if (p7 != NULL) + *p7 = (PKCS7*)pkcs7; + return (PKCS7*)pkcs7; +} + +int wolfSSL_i2d_PKCS7(PKCS7 *p7, unsigned char **out) +{ + byte* output = NULL; + int localBuf = 0; + int len; + WC_RNG rng; + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_i2d_PKCS7"); + + if (!out || !p7) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + if (!p7->rng) { + if (wc_InitRng(&rng) != 0) { + WOLFSSL_MSG("wc_InitRng error"); + return WOLFSSL_FAILURE; + } + p7->rng = &rng; /* cppcheck-suppress autoVariables + */ + } + + if ((len = wc_PKCS7_EncodeSignedData(p7, NULL, 0)) < 0) { + WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error"); + goto cleanup; + } + + if (*out == NULL) { + output = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (!output) { + WOLFSSL_MSG("malloc error"); + goto cleanup; + } + localBuf = 1; + } + else { + output = *out; + } + + if ((len = wc_PKCS7_EncodeSignedData(p7, output, (word32)len)) < 0) { + WOLFSSL_MSG("wc_PKCS7_EncodeSignedData error"); + goto cleanup; + } + + ret = len; +cleanup: + if (p7->rng == &rng) { + wc_FreeRng(&rng); + p7->rng = NULL; + } + if (ret == WOLFSSL_FAILURE && localBuf && output) + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ret != WOLFSSL_FAILURE) + *out = output; + return ret; +} + +int wolfSSL_i2d_PKCS7_bio(WOLFSSL_BIO *bio, PKCS7 *p7) +{ + byte* output = NULL; + int len; + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_i2d_PKCS7_bio"); + + if (!bio || !p7) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + if ((len = wolfSSL_i2d_PKCS7(p7, &output)) == WOLFSSL_FAILURE) { + WOLFSSL_MSG("wolfSSL_i2d_PKCS7 error"); + goto cleanup; + } + + if (wolfSSL_BIO_write(bio, output, len) <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_write error"); + goto cleanup; + } + + ret = WOLFSSL_SUCCESS; +cleanup: + if (output) + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/** + * Creates and returns a PKCS7 signedData structure. + * + * Inner content type is set to DATA to match OpenSSL behavior. + * + * signer - certificate to sign bundle with + * pkey - private key matching signer + * certs - optional additional set of certificates to include + * in - input data to be signed + * flags - optional set of flags to control sign behavior + * + * PKCS7_BINARY - Do not translate input data to MIME canonical + * format (\r\n line endings), thus preventing corruption of + * binary content. + * PKCS7_TEXT - Prepend MIME headers for text/plain to content. + * PKCS7_DETACHED - Set signature detached, omit content from output bundle. + * PKCS7_STREAM - initialize PKCS7 struct for signing, do not read data. + * + * Flags not currently supported: + * PKCS7_NOCERTS - Do not include the signer cert in the output bundle. + * PKCS7_PARTIAL - Allow for PKCS7_sign() to be only partially set up, + * then signers etc to be added separately before + * calling PKCS7_final(). + * + * Returns valid PKCS7 structure pointer, or NULL if an error occurred. + */ +PKCS7* wolfSSL_PKCS7_sign(WOLFSSL_X509* signer, WOLFSSL_EVP_PKEY* pkey, + WOLFSSL_STACK* certs, WOLFSSL_BIO* in, int flags) +{ + int err = 0; + WOLFSSL_PKCS7* p7 = NULL; + WOLFSSL_STACK* cert = certs; + + WOLFSSL_ENTER("wolfSSL_PKCS7_sign"); + + if (flags & PKCS7_NOCERTS) { + WOLFSSL_MSG("PKCS7_NOCERTS flag not yet supported"); + err = 1; + } + + if (flags & PKCS7_PARTIAL) { + WOLFSSL_MSG("PKCS7_PARTIAL flag not yet supported"); + err = 1; + } + + if ((err == 0) && (signer == NULL || signer->derCert == NULL || + signer->derCert->length == 0)) { + WOLFSSL_MSG("Bad function arg, signer is NULL or incomplete"); + err = 1; + } + + if ((err == 0) && (pkey == NULL || pkey->pkey.ptr == NULL || + pkey->pkey_sz <= 0)) { + WOLFSSL_MSG("Bad function arg, pkey is NULL or incomplete"); + err = 1; + } + + if ((err == 0) && (in == NULL) && !(flags & PKCS7_STREAM)) { + WOLFSSL_MSG("input data required unless PKCS7_STREAM used"); + err = 1; + } + + if ((err == 0) && ((p7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL)) { + WOLFSSL_MSG("Error allocating new WOLFSSL_PKCS7"); + err = 1; + } + + /* load signer certificate */ + if (err == 0) { + if (wc_PKCS7_InitWithCert(&p7->pkcs7, signer->derCert->buffer, + signer->derCert->length) != 0) { + WOLFSSL_MSG("Failed to load signer certificate"); + err = 1; + } + } + + /* set signer private key, data types, defaults */ + if (err == 0) { + p7->pkcs7.privateKey = (byte*)pkey->pkey.ptr; + p7->pkcs7.privateKeySz = (word32)pkey->pkey_sz; + p7->pkcs7.contentOID = DATA; /* inner content default is DATA */ + p7->pkcs7.hashOID = SHA256h; /* default to SHA-256 hash type */ + p7->type = SIGNED_DATA; /* PKCS7_final switches on type */ + } + + /* add additional chain certs if provided */ + while (cert && (err == 0)) { + if (cert->data.x509 != NULL && cert->data.x509->derCert != NULL) { + if (wc_PKCS7_AddCertificate(&p7->pkcs7, + cert->data.x509->derCert->buffer, + cert->data.x509->derCert->length) != 0) { + WOLFSSL_MSG("Error in wc_PKCS7_AddCertificate"); + err = 1; + } + } + cert = cert->next; + } + + if ((err == 0) && (flags & PKCS7_DETACHED)) { + if (wc_PKCS7_SetDetached(&p7->pkcs7, 1) != 0) { + WOLFSSL_MSG("Failed to set signature detached"); + err = 1; + } + } + + if ((err == 0) && (flags & PKCS7_STREAM)) { + /* if streaming, return before finalizing */ + return (PKCS7*)p7; + } + + if ((err == 0) && (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1)) { + WOLFSSL_MSG("Error calling wolfSSL_PKCS7_final"); + err = 1; + } + + if ((err != 0) && (p7 != NULL)) { + wolfSSL_PKCS7_free((PKCS7*)p7); + p7 = NULL; + } + + return (PKCS7*)p7; +} + +#ifdef HAVE_SMIME + +#ifndef MAX_MIME_LINE_LEN + #define MAX_MIME_LINE_LEN 1024 +#endif + +/** + * Copy input BIO to output BIO, but convert all line endings to CRLF (\r\n), + * used by PKCS7_final(). + * + * in - input WOLFSSL_BIO to be converted + * out - output WOLFSSL_BIO to hold copy of in, with line endings adjusted + * + * Return 0 on success, negative on error + */ +static int wolfSSL_BIO_to_MIME_crlf(WOLFSSL_BIO* in, WOLFSSL_BIO* out) +{ + int ret = 0; + int lineLen = 0; + word32 canonLineLen = 0; + char* canonLine = NULL; +#ifdef WOLFSSL_SMALL_STACK + char* line = NULL; +#else + char line[MAX_MIME_LINE_LEN]; +#endif + + if (in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + line = (char*)XMALLOC(MAX_MIME_LINE_LEN, in->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (line == NULL) { + return MEMORY_E; + } +#endif + XMEMSET(line, 0, MAX_MIME_LINE_LEN); + + while ((lineLen = wolfSSL_BIO_gets(in, line, MAX_MIME_LINE_LEN)) > 0) { + + if (line[lineLen - 1] == '\r' || line[lineLen - 1] == '\n') { + canonLineLen = (word32)lineLen; + if ((canonLine = wc_MIME_single_canonicalize( + line, &canonLineLen)) == NULL) { + ret = -1; + break; + } + + /* remove trailing null */ + if (canonLineLen >= 1 && canonLine[canonLineLen-1] == '\0') { + canonLineLen--; + } + + if (wolfSSL_BIO_write(out, canonLine, (int)canonLineLen) < 0) { + ret = -1; + break; + } + XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); + canonLine = NULL; + } + else { + /* no line ending in current line, write direct to out */ + if (wolfSSL_BIO_write(out, line, lineLen) < 0) { + ret = -1; + break; + } + } + } + + if (canonLine != NULL) { + XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(line, in->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_SMIME */ + +/* Used by both PKCS7_final() and PKCS7_verify() */ +static const char contTypeText[] = "Content-Type: text/plain\r\n\r\n"; + +/** + * Finalize PKCS7 structure, currently supports signedData only. + * + * Does not generate final bundle (ie: signedData), but finalizes + * the PKCS7 structure in preparation for a output function to be called next. + * + * pkcs7 - initialized PKCS7 structure, populated with signer, etc + * in - input data + * flags - flags to control PKCS7 behavior. Other flags except those noted + * below are ignored: + * + * PKCS7_BINARY - Do not translate input data to MIME canonical + * format (\r\n line endings), thus preventing corruption of + * binary content. + * PKCS7_TEXT - Prepend MIME headers for text/plain to content. + * + * Returns 1 on success, 0 on error + */ +int wolfSSL_PKCS7_final(PKCS7* pkcs7, WOLFSSL_BIO* in, int flags) +{ + int ret = 1; + int memSz = 0; + unsigned char* mem = NULL; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + WOLFSSL_BIO* data = NULL; + + WOLFSSL_ENTER("wolfSSL_PKCS7_final"); + + if (p7 == NULL || in == NULL) { + WOLFSSL_MSG("Bad input args to PKCS7_final"); + ret = 0; + } + + if (ret == 1) { + if ((data = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())) == NULL) { + WOLFSSL_MSG("Error in wolfSSL_BIO_new"); + ret = 0; + } + } + + /* prepend Content-Type header if PKCS7_TEXT */ + if ((ret == 1) && (flags & PKCS7_TEXT)) { + if (wolfSSL_BIO_write(data, contTypeText, + (int)XSTR_SIZEOF(contTypeText)) < 0) { + WOLFSSL_MSG("Error prepending Content-Type header"); + ret = 0; + } + } + + /* convert line endings to CRLF if !PKCS7_BINARY */ + if (ret == 1) { + if (flags & PKCS7_BINARY) { + + /* no CRLF conversion, direct copy content */ + if ((memSz = wolfSSL_BIO_get_len(in)) <= 0) { + ret = 0; + } + if (ret == 1) { + mem = (unsigned char*)XMALLOC(memSz, in->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Failed to allocate memory for input data"); + ret = 0; + } + } + + if (ret == 1) { + if (wolfSSL_BIO_read(in, mem, memSz) != memSz) { + WOLFSSL_MSG("Error reading from input BIO"); + ret = 0; + } + else if (wolfSSL_BIO_write(data, mem, memSz) < 0) { + ret = 0; + } + } + + if (mem != NULL) { + XFREE(mem, in->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } + else { + #ifdef HAVE_SMIME + /* convert content line endings to CRLF */ + if (wolfSSL_BIO_to_MIME_crlf(in, data) != 0) { + WOLFSSL_MSG("Error converting line endings to CRLF"); + ret = 0; + } + else { + p7->pkcs7.contentCRLF = 1; + } + #else + WOLFSSL_MSG("Without PKCS7_BINARY requires wolfSSL to be built " + "with HAVE_SMIME"); + ret = 0; + #endif + } + } + + if ((ret == 1) && ((memSz = wolfSSL_BIO_get_mem_data(data, &mem)) < 0)) { + WOLFSSL_MSG("Error in wolfSSL_BIO_get_mem_data"); + ret = 0; + } + + if (ret == 1) { + if (p7->data != NULL) { + XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); + } + p7->data = (byte*)XMALLOC(memSz, NULL, DYNAMIC_TYPE_PKCS7); + if (p7->data == NULL) { + ret = 0; + } + else { + XMEMCPY(p7->data, mem, memSz); + p7->len = memSz; + } + } + + if (ret == 1) { + p7->pkcs7.content = p7->data; + p7->pkcs7.contentSz = (word32)p7->len; + } + + if (data != NULL) { + wolfSSL_BIO_free(data); + } + + return ret; +} + +int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs, + WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, WOLFSSL_BIO* out, int flags) +{ + int i, ret = 0; + unsigned char* mem = NULL; + int memSz = 0; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + int contTypeLen; + WOLFSSL_X509* signer = NULL; + WOLFSSL_STACK* signers = NULL; + + WOLFSSL_ENTER("wolfSSL_PKCS7_verify"); + + if (pkcs7 == NULL) + return WOLFSSL_FAILURE; + + if (in != NULL) { + if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0) + return WOLFSSL_FAILURE; + + p7->pkcs7.content = mem; + p7->pkcs7.contentSz = (word32)memSz; + } + + /* certs is the list of certificates to find the cert with issuer/serial. */ + (void)certs; + /* store is the certificate store to use to verify signer certificate + * associated with the signers. + */ + (void)store; + + ret = wc_PKCS7_VerifySignedData(&p7->pkcs7, p7->data, p7->len); + if (ret != 0) + return WOLFSSL_FAILURE; + + if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) { + /* Verify signer certificates */ + if (store == NULL || store->cm == NULL) { + WOLFSSL_MSG("No store or store certs, but PKCS7_NOVERIFY not set"); + return WOLFSSL_FAILURE; + } + + signers = wolfSSL_PKCS7_get0_signers(pkcs7, certs, flags); + if (signers == NULL) { + WOLFSSL_MSG("No signers found to verify"); + return WOLFSSL_FAILURE; + } + for (i = 0; i < wolfSSL_sk_X509_num(signers); i++) { + signer = wolfSSL_sk_X509_value(signers, i); + + if (wolfSSL_CertManagerVerifyBuffer(store->cm, + signer->derCert->buffer, + signer->derCert->length, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Failed to verify signer certificate"); + wolfSSL_sk_X509_pop_free(signers, NULL); + return WOLFSSL_FAILURE; + } + } + wolfSSL_sk_X509_pop_free(signers, NULL); + } + + if (flags & PKCS7_TEXT) { + /* strip MIME header for text/plain, otherwise error */ + contTypeLen = XSTR_SIZEOF(contTypeText); + if ((p7->pkcs7.contentSz < (word32)contTypeLen) || + (XMEMCMP(p7->pkcs7.content, contTypeText, contTypeLen) != 0)) { + WOLFSSL_MSG("Error PKCS7 Content-Type not found with PKCS7_TEXT"); + return WOLFSSL_FAILURE; + } + p7->pkcs7.content += contTypeLen; + p7->pkcs7.contentSz -= contTypeLen; + } + + if (out != NULL) { + wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz); + } + + WOLFSSL_LEAVE("wolfSSL_PKCS7_verify", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} + +/** + * This API was added as a helper function for libest. It + * encodes a stack of certificates to pkcs7 format. + * @param pkcs7 PKCS7 parameter object + * @param certs WOLFSSL_STACK_OF(WOLFSSL_X509)* + * @param out Output bio + * @return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs, + WOLFSSL_BIO* out) +{ + int ret; + WOLFSSL_PKCS7* p7; + WOLFSSL_ENTER("wolfSSL_PKCS7_encode_certs"); + + if (!pkcs7 || !certs || !out) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + p7 = (WOLFSSL_PKCS7*)pkcs7; + + /* take ownership of certs */ + p7->certs = certs; + /* TODO: takes ownership even on failure below but not on above failure. */ + + if (pkcs7->certList) { + WOLFSSL_MSG("wolfSSL_PKCS7_encode_certs called multiple times on same " + "struct"); + return WOLFSSL_FAILURE; + } + + if (certs) { + /* Save some of the values */ + int hashOID = pkcs7->hashOID; + byte version = pkcs7->version; + + if (!certs->data.x509 || !certs->data.x509->derCert) { + WOLFSSL_MSG("Missing cert"); + return WOLFSSL_FAILURE; + } + + if (wc_PKCS7_InitWithCert(pkcs7, certs->data.x509->derCert->buffer, + certs->data.x509->derCert->length) != 0) { + WOLFSSL_MSG("wc_PKCS7_InitWithCert error"); + return WOLFSSL_FAILURE; + } + certs = certs->next; + + pkcs7->hashOID = hashOID; + pkcs7->version = version; + } + + /* Add the certs to the PKCS7 struct */ + while (certs) { + if (!certs->data.x509 || !certs->data.x509->derCert) { + WOLFSSL_MSG("Missing cert"); + return WOLFSSL_FAILURE; + } + if (wc_PKCS7_AddCertificate(pkcs7, certs->data.x509->derCert->buffer, + certs->data.x509->derCert->length) != 0) { + WOLFSSL_MSG("wc_PKCS7_AddCertificate error"); + return WOLFSSL_FAILURE; + } + certs = certs->next; + } + + if (wc_PKCS7_SetSignerIdentifierType(pkcs7, DEGENERATE_SID) != 0) { + WOLFSSL_MSG("wc_PKCS7_SetSignerIdentifierType error"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_i2d_PKCS7_bio(out, pkcs7); + + return ret; +} + +/****************************************************************************** +* wolfSSL_PEM_write_bio_PKCS7 - writes the PKCS7 data to BIO +* +* RETURNS: +* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE +*/ +int wolfSSL_PEM_write_bio_PKCS7(WOLFSSL_BIO* bio, PKCS7* p7) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* outputHead; + byte* outputFoot; +#else + byte outputHead[2048]; + byte outputFoot[2048]; +#endif + word32 outputHeadSz = 2048; + word32 outputFootSz = 2048; + word32 outputSz = 0; + byte* output = NULL; + byte* pem = NULL; + int pemSz = -1; + enum wc_HashType hashType; + byte hashBuf[WC_MAX_DIGEST_SIZE]; + word32 hashSz = -1; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PKCS7"); + + if (bio == NULL || p7 == NULL) + return WOLFSSL_FAILURE; + +#ifdef WOLFSSL_SMALL_STACK + outputHead = (byte*)XMALLOC(outputHeadSz, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (outputHead == NULL) + return MEMORY_E; + + outputFoot = (byte*)XMALLOC(outputFootSz, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (outputFoot == NULL) + goto error; + +#endif + + XMEMSET(hashBuf, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(outputHead, 0, outputHeadSz); + XMEMSET(outputFoot, 0, outputFootSz); + + hashType = wc_OidGetHash(p7->hashOID); + hashSz = (word32)wc_HashGetDigestSize(hashType); + if (hashSz > WC_MAX_DIGEST_SIZE) + goto error; + + /* only SIGNED_DATA is supported */ + switch (p7->contentOID) { + case SIGNED_DATA: + break; + default: + WOLFSSL_MSG("Unknown PKCS#7 Type"); + goto error; + }; + + if ((wc_PKCS7_EncodeSignedData_ex(p7, hashBuf, hashSz, + outputHead, &outputHeadSz, outputFoot, &outputFootSz)) != 0) + goto error; + + outputSz = outputHeadSz + p7->contentSz + outputFootSz; + output = (byte*)XMALLOC(outputSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (!output) + goto error; + + XMEMSET(output, 0, outputSz); + outputSz = 0; + XMEMCPY(&output[outputSz], outputHead, outputHeadSz); + outputSz += outputHeadSz; + XMEMCPY(&output[outputSz], p7->content, p7->contentSz); + outputSz += p7->contentSz; + XMEMCPY(&output[outputSz], outputFoot, outputFootSz); + outputSz += outputFootSz; + + /* get PEM size */ + pemSz = wc_DerToPemEx(output, outputSz, NULL, 0, NULL, CERT_TYPE); + if (pemSz < 0) + goto error; + + pemSz++; /* for '\0'*/ + + /* create PEM buffer and convert from DER to PEM*/ + if ((pem = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER)) + == NULL) + goto error; + + XMEMSET(pem, 0, pemSz); + + if (wc_DerToPemEx(output, outputSz, pem, (word32)pemSz, NULL, CERT_TYPE) < 0) { + goto error; + } + if ((wolfSSL_BIO_write(bio, pem, pemSz) == pemSz)) { + XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return WOLFSSL_SUCCESS; + } + +error: +#ifdef WOLFSSL_SMALL_STACK + if (outputHead) { + XFREE(outputHead, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (outputFoot) { + XFREE(outputFoot, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + if (output) { + XFREE(output, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + if (pem) { + XFREE(pem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + return WOLFSSL_FAILURE; +} + +#ifdef HAVE_SMIME +/***************************************************************************** +* wolfSSL_SMIME_read_PKCS7 - Reads the given S/MIME message and parses it into +* a PKCS7 object. In case of a multipart message, stores the signed data in +* bcont. +* +* RETURNS: +* returns pointer to a PKCS7 structure on success, otherwise returns NULL +*/ +PKCS7* wolfSSL_SMIME_read_PKCS7(WOLFSSL_BIO* in, + WOLFSSL_BIO** bcont) +{ + MimeHdr* allHdrs = NULL; + MimeHdr* curHdr = NULL; + MimeParam* curParam = NULL; + int inLen = 0; + byte* bcontMem = NULL; + int bcontMemSz = 0; + int sectionLen = 0; + int ret = -1; + char* section = NULL; + char* canonLine = NULL; + char* canonSection = NULL; + PKCS7* pkcs7 = NULL; + word32 outLen = 0; + word32 canonLineLen = 0; + byte* out = NULL; + byte* outHead = NULL; + + int canonPos = 0; + int lineLen = 0; + int remainLen = 0; + byte isEnd = 0; + size_t canonSize = 0; + size_t boundLen = 0; + char* boundary = NULL; + + static const char kContType[] = "Content-Type"; + static const char kCTE[] = "Content-Transfer-Encoding"; + static const char kMultSigned[] = "multipart/signed"; + static const char kAppPkcsSign[] = "application/pkcs7-signature"; + static const char kAppXPkcsSign[] = "application/x-pkcs7-signature"; + static const char kAppPkcs7Mime[] = "application/pkcs7-mime"; + static const char kAppXPkcs7Mime[] = "application/x-pkcs7-mime"; + + WOLFSSL_ENTER("wolfSSL_SMIME_read_PKCS7"); + + if (in == NULL || bcont == NULL) { + goto error; + } + inLen = wolfSSL_BIO_get_len(in); + if (inLen <= 0) { + goto error; + } + remainLen = wolfSSL_BIO_get_len(in); + if (remainLen <= 0) { + goto error; + } + + section = (char*)XMALLOC(remainLen+1, NULL, DYNAMIC_TYPE_PKCS7); + if (section == NULL) { + goto error; + } + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen <= 0) { + goto error; + } + while (isEnd == 0 && remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], remainLen); + if (lineLen <= 0) { + goto error; + } + /* Line with just newline signals end of headers. */ + if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen], + "\r\n", 2)) || + (lineLen==1 && (section[sectionLen] == '\r' || + section[sectionLen] == '\n'))) { + isEnd = 1; + } + } + section[sectionLen] = '\0'; + ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs); + if (ret < 0) { + WOLFSSL_MSG("Parsing MIME headers failed."); + goto error; + } + isEnd = 0; + section[0] = '\0'; + sectionLen = 0; + + curHdr = wc_MIME_find_header_name(kContType, allHdrs); + if (curHdr && !XSTRNCMP(curHdr->body, kMultSigned, + XSTR_SIZEOF(kMultSigned))) { + curParam = wc_MIME_find_param_attr("protocol", curHdr->params); + if (curParam && (!XSTRNCMP(curParam->value, kAppPkcsSign, + XSTR_SIZEOF(kAppPkcsSign)) || + !XSTRNCMP(curParam->value, kAppXPkcsSign, + XSTR_SIZEOF(kAppXPkcsSign)))) { + curParam = wc_MIME_find_param_attr("boundary", curHdr->params); + if (curParam == NULL) { + goto error; + } + + boundLen = XSTRLEN(curParam->value) + 2; + boundary = (char*)XMALLOC(boundLen+1, NULL, DYNAMIC_TYPE_PKCS7); + if (boundary == NULL) { + goto error; + } + XMEMSET(boundary, 0, (word32)(boundLen+1)); + boundary[0] = boundary[1] = '-'; + XSTRNCPY(&boundary[2], curParam->value, boundLen-2); + + /* Parse up to first boundary, ignore everything here. */ + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen <= 0) { + goto error; + } + while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) && + remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + } + + section[0] = '\0'; + sectionLen = 0; + canonSize = (size_t)remainLen + 1; + canonSection = (char*)XMALLOC(canonSize, NULL, + DYNAMIC_TYPE_PKCS7); + if (canonSection == NULL) { + goto error; + } + + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen < 0) { + goto error; + } + while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) && + remainLen > 0) { + canonLineLen = (word32)lineLen; + canonLine = wc_MIME_single_canonicalize(§ion[sectionLen], + &canonLineLen); + if (canonLine == NULL) { + goto error; + } + /* If line endings were added, the initial length may be + * exceeded. */ + if ((canonPos + canonLineLen) >= canonSize) { + canonSize = canonPos + canonLineLen; + canonSection = (char*)XREALLOC(canonSection, canonSize, + NULL, DYNAMIC_TYPE_PKCS7); + if (canonSection == NULL) { + goto error; + } + } + XMEMCPY(&canonSection[canonPos], canonLine, + (int)canonLineLen - 1); + canonPos += canonLineLen - 1; + XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); + canonLine = NULL; + + sectionLen += lineLen; + remainLen -= lineLen; + + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + } + + if (canonPos > 0) { + canonPos--; + } + + /* Strip the final trailing newline. Support \r, \n or \r\n. */ + if (canonSection[canonPos] == '\n') { + if (canonPos > 0) { + canonPos--; + } + } + + if (canonSection[canonPos] == '\r') { + if (canonPos > 0) { + canonPos--; + } + } + + canonSection[canonPos+1] = '\0'; + + *bcont = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + ret = wolfSSL_BIO_write(*bcont, canonSection, + canonPos + 1); + if (ret != (canonPos+1)) { + goto error; + } + if ((bcontMemSz = wolfSSL_BIO_get_mem_data(*bcont, &bcontMem)) + < 0) { + goto error; + } + XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); + canonSection = NULL; + + wc_MIME_free_hdrs(allHdrs); + allHdrs = NULL; + section[0] = '\0'; + sectionLen = 0; + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + if (lineLen <= 0) { + goto error; + } + while (isEnd == 0 && remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + /* Line with just newline signals end of headers. */ + if ((lineLen==2 && !XSTRNCMP(§ion[sectionLen], + "\r\n", 2)) || + (lineLen==1 && (section[sectionLen] == '\r' || + section[sectionLen] == '\n'))) { + isEnd = 1; + } + } + section[sectionLen] = '\0'; + ret = wc_MIME_parse_headers(section, sectionLen, &allHdrs); + if (ret < 0) { + WOLFSSL_MSG("Parsing MIME headers failed."); + goto error; + } + curHdr = wc_MIME_find_header_name(kContType, allHdrs); + if (curHdr == NULL || (XSTRNCMP(curHdr->body, kAppPkcsSign, + XSTR_SIZEOF(kAppPkcsSign)) && + XSTRNCMP(curHdr->body, kAppXPkcsSign, + XSTR_SIZEOF(kAppXPkcsSign)))) { + WOLFSSL_MSG("S/MIME headers not found inside " + "multipart message.\n"); + goto error; + } + + section[0] = '\0'; + sectionLen = 0; + lineLen = wolfSSL_BIO_gets(in, section, remainLen); + while (XSTRNCMP(§ion[sectionLen], boundary, boundLen) && + remainLen > 0) { + sectionLen += lineLen; + remainLen -= lineLen; + lineLen = wolfSSL_BIO_gets(in, §ion[sectionLen], + remainLen); + if (lineLen <= 0) { + goto error; + } + } + + XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); + boundary = NULL; + } + } + else if (curHdr && (!XSTRNCMP(curHdr->body, kAppPkcs7Mime, + XSTR_SIZEOF(kAppPkcs7Mime)) || + !XSTRNCMP(curHdr->body, kAppXPkcs7Mime, + XSTR_SIZEOF(kAppXPkcs7Mime)))) { + sectionLen = wolfSSL_BIO_get_len(in); + if (sectionLen <= 0) { + goto error; + } + ret = wolfSSL_BIO_read(in, section, sectionLen); + if (ret < 0 || ret != sectionLen) { + WOLFSSL_MSG("Error reading input BIO."); + goto error; + } + } + else { + WOLFSSL_MSG("S/MIME headers not found."); + goto error; + } + + curHdr = wc_MIME_find_header_name(kCTE, allHdrs); + if (curHdr == NULL) { + WOLFSSL_MSG("Content-Transfer-Encoding header not found, " + "assuming base64 encoding."); + } + else if (XSTRNCMP(curHdr->body, "base64", XSTRLEN("base64"))) { + WOLFSSL_MSG("S/MIME encodings other than base64 are not " + "currently supported.\n"); + goto error; + } + + if (section == NULL || sectionLen <= 0) { + goto error; + } + outLen = (word32)((sectionLen*3+3)/4)+1; + out = (byte*)XMALLOC(outLen*sizeof(byte), NULL, DYNAMIC_TYPE_PKCS7); + outHead = out; + if (outHead == NULL) { + goto error; + } + /* Strip trailing newlines. */ + while ((sectionLen > 0) && + (section[sectionLen-1] == '\r' || section[sectionLen-1] == '\n')) { + sectionLen--; + } + section[sectionLen] = '\0'; + ret = Base64_Decode((const byte*)section, (word32)sectionLen, out, &outLen); + if (ret < 0) { + WOLFSSL_MSG("Error base64 decoding S/MIME message."); + goto error; + } + pkcs7 = wolfSSL_d2i_PKCS7_only(NULL, (const unsigned char**)&out, (int)outLen, + bcontMem, (word32)bcontMemSz); + + wc_MIME_free_hdrs(allHdrs); + XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); + + return pkcs7; + +error: + wc_MIME_free_hdrs(allHdrs); + XFREE(boundary, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(outHead, NULL, DYNAMIC_TYPE_PKCS7); + XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); + if (canonSection != NULL) + XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); + if (canonLine != NULL) + XFREE(canonLine, NULL, DYNAMIC_TYPE_PKCS7); + if (bcont) { + wolfSSL_BIO_free(*bcont); + *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */ + } + + return NULL; +} + +/* Convert hash algo OID (from Hash_Sum in asn.h) to SMIME string equivalent. + * Returns hash algorithm string or "unknown" if not found */ +static const char* wolfSSL_SMIME_HashOIDToString(int hashOID) +{ + switch (hashOID) { + case MD5h: + return "md5"; + case SHAh: + return "sha1"; + case SHA224h: + return "sha-224"; + case SHA256h: + return "sha-256"; + case SHA384h: + return "sha-384"; + case SHA512h: + return "sha-512"; + case SHA3_224h: + return "sha3-224"; + case SHA3_384h: + return "sha3-384"; + case SHA3_512h: + return "sha3-512"; + default: + break; + } + + return "unknown"; +} + +/* Convert PKCS#7 type (from PKCS7_TYPES in pkcs7.h) to SMIME string. + * RFC2633 only defines signed-data, enveloped-data, certs-only. + * Returns string on success, NULL on unknown type. */ +static const char* wolfSSL_SMIME_PKCS7TypeToString(int type) +{ + switch (type) { + case SIGNED_DATA: + return "signed-data"; + case ENVELOPED_DATA: + return "enveloped-data"; + default: + break; + } + + return NULL; +} + +/** + * Convert PKCS7 structure to SMIME format, adding necessary headers. + * + * Handles generation of PKCS7 bundle (ie: signedData). PKCS7 structure + * should be set up beforehand with PKCS7_sign/final/etc. Output is always + * Base64 encoded. + * + * out - output BIO for SMIME formatted data to be placed + * pkcs7 - input PKCS7 structure, initialized and set up + * in - input content to be encoded into PKCS7 + * flags - flags to control behavior of PKCS7 generation + * + * Returns 1 on success, 0 or negative on failure + */ +int wolfSSL_SMIME_write_PKCS7(WOLFSSL_BIO* out, PKCS7* pkcs7, WOLFSSL_BIO* in, + int flags) +{ + int i; + int ret = 1; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + byte* p7out = NULL; + int len = 0; + + char boundary[33]; /* 32 chars + \0 */ + byte* sigBase64 = NULL; + word32 sigBase64Len = 0; + const char* p7TypeString = NULL; + + static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + if (out == NULL || p7 == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + if (in != NULL && (p7->pkcs7.content == NULL || p7->pkcs7.contentSz == 0 || + p7->pkcs7.contentCRLF == 0)) { + /* store and adjust content line endings for CRLF if needed */ + if (wolfSSL_PKCS7_final((PKCS7*)p7, in, flags) != 1) { + ret = 0; + } + } + + if (ret > 0) { + /* Generate signedData bundle, DER in output (dynamic) */ + if ((len = wolfSSL_i2d_PKCS7((PKCS7*)p7, &p7out)) == WOLFSSL_FAILURE) { + WOLFSSL_MSG("Error in wolfSSL_i2d_PKCS7"); + ret = 0; + } + } + + /* Base64 encode signedData bundle */ + if (ret > 0) { + if (Base64_Encode(p7out, (word32)len, NULL, &sigBase64Len) != + WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { + ret = 0; + } + else { + sigBase64 = (byte*)XMALLOC(sigBase64Len, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sigBase64 == NULL) { + ret = 0; + } + } + } + + if (ret > 0) { + XMEMSET(sigBase64, 0, sigBase64Len); + if (Base64_Encode(p7out, (word32)len, sigBase64, &sigBase64Len) < 0) { + WOLFSSL_MSG("Error in Base64_Encode of signature"); + ret = 0; + } + } + + /* build up SMIME message */ + if (ret > 0) { + if (flags & PKCS7_DETACHED) { + + /* generate random boundary */ + if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("No RNG to use"); + ret = 0; + } + + /* no need to generate random byte for null terminator (size-1) */ + if ((ret > 0) && (wc_RNG_GenerateBlock(&globalRNG, (byte*)boundary, + sizeof(boundary) - 1 ) != 0)) { + WOLFSSL_MSG("Error in wc_RNG_GenerateBlock"); + ret = 0; + } + + if (ret > 0) { + for (i = 0; i < (int)sizeof(boundary) - 1; i++) { + boundary[i] = + alphanum[boundary[i] % XSTR_SIZEOF(alphanum)]; + } + boundary[sizeof(boundary)-1] = 0; + } + + if (ret > 0) { + /* S/MIME header beginning */ + ret = wolfSSL_BIO_printf(out, + "MIME-Version: 1.0\n" + "Content-Type: multipart/signed; " + "protocol=\"application/x-pkcs7-signature\"; " + "micalg=\"%s\"; " + "boundary=\"----%s\"\n\n" + "This is an S/MIME signed message\n\n" + "------%s\n", + wolfSSL_SMIME_HashOIDToString(p7->pkcs7.hashOID), + boundary, boundary); + } + + if (ret > 0) { + /* S/MIME content */ + ret = wolfSSL_BIO_write(out, + p7->pkcs7.content, p7->pkcs7.contentSz); + } + + if (ret > 0) { + /* S/SMIME header end boundary */ + ret = wolfSSL_BIO_printf(out, + "\n------%s\n", boundary); + } + + if (ret > 0) { + /* Signature and header */ + ret = wolfSSL_BIO_printf(out, + "Content-Type: application/x-pkcs7-signature; " + "name=\"smime.p7s\"\n" + "Content-Transfer-Encoding: base64\n" + "Content-Disposition: attachment; " + "filename=\"smime.p7s\"\n\n" + "%.*s\n" /* Base64 encoded signature */ + "------%s--\n\n", + sigBase64Len, sigBase64, + boundary); + } + } + else { + p7TypeString = wolfSSL_SMIME_PKCS7TypeToString(p7->type); + if (p7TypeString == NULL) { + WOLFSSL_MSG("Unsupported PKCS7 SMIME type"); + ret = 0; + } + + if (ret > 0) { + /* not detached */ + ret = wolfSSL_BIO_printf(out, + "MIME-Version: 1.0\n" + "Content-Disposition: attachment; " + "filename=\"smime.p7m\"\n" + "Content-Type: application/x-pkcs7-mime; " + "smime-type=%s; name=\"smime.p7m\"\n" + "Content-Transfer-Encoding: base64\n\n" + "%.*s\n" /* signature */, + p7TypeString, sigBase64Len, sigBase64); + } + } + } + + if (p7out != NULL) { + XFREE(p7out, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (sigBase64 != NULL) { + XFREE(sigBase64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + if (ret > 0) { + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + +#endif /* HAVE_SMIME */ +#endif /* !NO_BIO */ +#endif /* OPENSSL_ALL */ + +#endif /* HAVE_PKCS7 */ +/******************************************************************************* + * END OF PKCS7 APIs + ******************************************************************************/ + +/******************************************************************************* + * START OF PKCS12 APIs + ******************************************************************************/ +#ifdef OPENSSL_EXTRA + +/* no-op function. Was initially used for adding encryption algorithms available + * for PKCS12 */ +void wolfSSL_PKCS12_PBE_add(void) +{ + WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add"); +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, + WOLFSSL_X509_PKCS12 **pkcs12) +{ + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp"); + return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, + PKCS12_TYPE); +} +#endif /* !NO_FILESYSTEM */ + +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_PKCS12) + +#ifdef OPENSSL_EXTRA + +#if !defined(NO_ASN) && !defined(NO_PWDBASED) + +#ifndef NO_BIO +WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) +{ + WC_PKCS12* localPkcs12 = NULL; + unsigned char* mem = NULL; + long memSz; + int ret = -1; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + memSz = wolfSSL_BIO_get_len(bio); + if (memSz <= 0) { + return NULL; + } + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + return NULL; + } + + if (mem != NULL) { + localPkcs12 = wc_PKCS12_new_ex(bio->heap); + if (localPkcs12 == NULL) { + WOLFSSL_MSG("Memory error"); + } + } + + if (mem != NULL && localPkcs12 != NULL) { + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + ret = wc_d2i_PKCS12(mem, (word32)memSz, localPkcs12); + if (ret < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + } + } + else { + WOLFSSL_MSG("Failed to get data from bio struct"); + } + } + + /* cleanup */ + if (mem != NULL) + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0 && localPkcs12 != NULL) { + wc_PKCS12_free(localPkcs12); + localPkcs12 = NULL; + } + if (pkcs12 != NULL) + *pkcs12 = localPkcs12; + + return localPkcs12; +} + +/* Converts the PKCS12 to DER format and outputs it into bio. + * + * bio is the structure to hold output DER + * pkcs12 structure to create DER from + * + * return 1 for success or 0 if an error occurs + */ +int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12) +{ + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_i2d_PKCS12_bio"); + + if ((bio != NULL) && (pkcs12 != NULL)) { + word32 certSz = 0; + byte *certDer = NULL; + + certSz = (word32)wc_i2d_PKCS12(pkcs12, &certDer, NULL); + if ((certSz > 0) && (certDer != NULL)) { + if (wolfSSL_BIO_write(bio, certDer, (int)certSz) == (int)certSz) { + ret = WOLFSSL_SUCCESS; + } + } + + if (certDer != NULL) { + XFREE(certDer, NULL, DYNAMIC_TYPE_PKCS); + } + } + + return ret; +} +#endif /* !NO_BIO */ + +/* Creates a new WC_PKCS12 structure + * + * pass password to use + * name friendlyName to use + * pkey private key to go into PKCS12 bundle + * cert certificate to go into PKCS12 bundle + * ca extra certificates that can be added to bundle. Can be NULL + * keyNID type of encryption to use on the key (-1 means no encryption) + * certNID type of encryption to use on the certificate + * itt number of iterations with encryption + * macItt number of iterations with mac creation + * keyType flag for signature and/or encryption key + * + * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail + */ +WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey, + WOLFSSL_X509* cert, WOLF_STACK_OF(WOLFSSL_X509)* ca, int keyNID, + int certNID, int itt, int macItt, int keyType) +{ + WC_PKCS12* pkcs12; + WC_DerCertList* list = NULL; + word32 passSz; + byte* keyDer = NULL; + word32 keyDerSz; + byte* certDer; + int certDerSz; + + WOLFSSL_ENTER("wolfSSL_PKCS12_create"); + + if (pass == NULL || pkey == NULL || cert == NULL) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_create", BAD_FUNC_ARG); + return NULL; + } + passSz = (word32)XSTRLEN(pass); + + keyDer = (byte*)pkey->pkey.ptr; + keyDerSz = (word32)pkey->pkey_sz; + + certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz); + if (certDer == NULL) { + return NULL; + } + + if (ca != NULL) { + unsigned long numCerts = ca->num; + WOLFSSL_STACK* sk = ca; + + while (numCerts > 0 && sk != NULL) { + byte* curDer; + WC_DerCertList* cur; + int curDerSz = 0; + + cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL, + DYNAMIC_TYPE_PKCS); + if (cur == NULL) { + wc_FreeCertList(list, NULL); + return NULL; + } + + curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz); + if (curDer == NULL || curDerSz < 0) { + XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); + wc_FreeCertList(list, NULL); + return NULL; + } + + cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS); + if (cur->buffer == NULL) { + XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); + wc_FreeCertList(list, NULL); + return NULL; + } + XMEMCPY(cur->buffer, curDer, curDerSz); + cur->bufferSz = (word32)curDerSz; + cur->next = list; + list = cur; + + sk = sk->next; + numCerts--; + } + } + + pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz, + certDer, (word32)certDerSz, list, keyNID, certNID, itt, macItt, + keyType, NULL); + + if (ca != NULL) { + wc_FreeCertList(list, NULL); + } + + return pkcs12; +} + + +/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */ +int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, + WOLF_STACK_OF(WOLFSSL_X509)** ca) +{ + void* heap = NULL; + int ret; + byte* certData = NULL; + word32 certDataSz; + byte* pk = NULL; + word32 pkSz; + WC_DerCertList* certList = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert *DeCert; +#else + DecodedCert DeCert[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_PKCS12_parse"); + + /* make sure we init return args */ + if (pkey) *pkey = NULL; + if (cert) *cert = NULL; + if (ca) *ca = NULL; + + if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) { + WOLFSSL_MSG("Bad argument value"); + return WOLFSSL_FAILURE; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + if (ca == NULL) { + ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + NULL); + } + else { + ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + &certList); + } + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + DeCert = (DecodedCert *)XMALLOC(sizeof(*DeCert), heap, + DYNAMIC_TYPE_DCERT); + if (DeCert == NULL) { + WOLFSSL_MSG("out of memory"); + return WOLFSSL_FAILURE; + } +#endif + + /* Decode cert and place in X509 stack struct */ + if (certList != NULL) { + WC_DerCertList* current = certList; + + *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_X509)), heap, DYNAMIC_TYPE_X509); + if (*ca == NULL) { + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + /* Free up WC_DerCertList and move on */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + ret = WOLFSSL_FAILURE; + goto out; + } + XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509))); + + /* add list of DER certs as X509's to stack */ + while (current != NULL) { + WC_DerCertList* toFree = current; + WOLFSSL_X509* x509; + + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + InitX509(x509, 1, heap); + InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap); + if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) { + WOLFSSL_MSG("Issue with parsing certificate"); + FreeDecodedCert(DeCert); + wolfSSL_X509_free(x509); + } + else { + if (CopyDecodedToX509(x509, DeCert) != 0) { + WOLFSSL_MSG("Failed to copy decoded cert"); + FreeDecodedCert(DeCert); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + /* Free up WC_DerCertList */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + ret = WOLFSSL_FAILURE; + goto out; + } + FreeDecodedCert(DeCert); + + if (wolfSSL_sk_X509_push(*ca, x509) != 1) { + WOLFSSL_MSG("Failed to push x509 onto stack"); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + + /* Free up WC_DerCertList */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + ret = WOLFSSL_FAILURE; + goto out; + } + } + current = current->next; + XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(toFree, heap, DYNAMIC_TYPE_PKCS); + } + } + + + /* Decode cert and place in X509 struct */ + if (certData != NULL) { + *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + if (*cert == NULL) { + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ca != NULL) { + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + } + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + ret = WOLFSSL_FAILURE; + goto out; + } + InitX509(*cert, 1, heap); + InitDecodedCert(DeCert, certData, certDataSz, heap); + if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL) != 0) { + WOLFSSL_MSG("Issue with parsing certificate"); + } + if (CopyDecodedToX509(*cert, DeCert) != 0) { + WOLFSSL_MSG("Failed to copy decoded cert"); + FreeDecodedCert(DeCert); + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ca != NULL) { + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + } + wolfSSL_X509_free(*cert); *cert = NULL; + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + ret = WOLFSSL_FAILURE; + goto out; + } + FreeDecodedCert(DeCert); + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + + + /* get key type */ + ret = BAD_STATE_E; + if (pk != NULL) { /* decode key if present */ + *pkey = wolfSSL_EVP_PKEY_new_ex(heap); + if (*pkey == NULL) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + } + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + ret = WOLFSSL_FAILURE; + goto out; + } + + #ifndef NO_RSA + { + const unsigned char* pt = pk; + if (wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, pkey, &pt, pkSz) != + NULL) { + ret = 0; + } + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + if (ret != 0) { /* if is in fail state check if ECC key */ + const unsigned char* pt = pk; + if (wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, pkey, &pt, pkSz) != + NULL) { + ret = 0; + } + } + #endif /* HAVE_ECC */ + if (pk != NULL) + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + if (ret != 0) { /* if is in fail state and no PKEY then fail */ + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + WOLFSSL_MSG("Bad PKCS12 key format"); + ret = WOLFSSL_FAILURE; + goto out; + } + + if (pkey != NULL && *pkey != NULL) { + (*pkey)->save_type = 0; + } + } + + (void)ret; + (void)ca; + + ret = WOLFSSL_SUCCESS; + +out: + +#ifdef WOLFSSL_SMALL_STACK + XFREE(DeCert, heap, DYNAMIC_TYPE_DCERT); +#endif + + return ret; +} + +int wolfSSL_PKCS12_verify_mac(WC_PKCS12 *pkcs12, const char *psw, + int pswLen) +{ + WOLFSSL_ENTER("wolfSSL_PKCS12_verify_mac"); + + if (!pkcs12) { + return WOLFSSL_FAILURE; + } + + return wc_PKCS12_verify_ex(pkcs12, (const byte*)psw, (word32)pswLen) == 0 ? + WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} + +#endif /* !NO_ASN && !NO_PWDBASED */ + +#endif /* OPENSSL_EXTRA */ + +#endif /* HAVE_PKCS12 */ +/******************************************************************************* + * END OF PKCS12 APIs + ******************************************************************************/ + +#endif /* !WOLFCRYPT_ONLY && !NO_CERTS */ + +#endif /* !WOLFSSL_SSL_P7P12_INCLUDED */ diff --git a/src/src/ssl_sess.c b/src/src/ssl_sess.c new file mode 100644 index 0000000..43ce1f5 --- /dev/null +++ b/src/src/ssl_sess.c @@ -0,0 +1,4567 @@ +/* ssl_sess.c + * + * Copyright (C) 2006-2024 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if !defined(WOLFSSL_SSL_SESS_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning ssl_sess.c does not need to be compiled separately from ssl.c + #endif +#else + +#ifndef NO_SESSION_CACHE + + /* basic config gives a cache with 33 sessions, adequate for clients and + embedded servers + + TITAN_SESSION_CACHE allows just over 2 million sessions, for servers + with titanic amounts of memory with long session ID timeouts and high + levels of traffic. + + ENABLE_SESSION_CACHE_ROW_LOCK: Allows row level locking for increased + performance with large session caches + + HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load, + allows over 13,000 new sessions per minute or over 200 new sessions per + second + + BIG_SESSION_CACHE yields 20,027 sessions + + MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that + aren't under heavy load, basically allows 200 new sessions per minute + + SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients + or systems where the default of is too much RAM. + SessionCache takes about 2K, ClientCache takes about 3Kbytes + + MICRO_SESSION_CACHE only stores 1 session, good for embedded clients + or systems where memory is at a premium. + SessionCache takes about 400 bytes, ClientCache takes 576 bytes + + default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined) + SessionCache takes about 13K bytes, ClientCache takes 17K bytes + */ + #if defined(TITAN_SESSION_CACHE) + #define SESSIONS_PER_ROW 31 + #define SESSION_ROWS 64937 + #ifndef ENABLE_SESSION_CACHE_ROW_LOCK + #define ENABLE_SESSION_CACHE_ROW_LOCK + #endif + #elif defined(HUGE_SESSION_CACHE) + #define SESSIONS_PER_ROW 11 + #define SESSION_ROWS 5981 + #elif defined(BIG_SESSION_CACHE) + #define SESSIONS_PER_ROW 7 + #define SESSION_ROWS 2861 + #elif defined(MEDIUM_SESSION_CACHE) + #define SESSIONS_PER_ROW 5 + #define SESSION_ROWS 211 + #elif defined(SMALL_SESSION_CACHE) + #define SESSIONS_PER_ROW 2 + #define SESSION_ROWS 3 + #elif defined(MICRO_SESSION_CACHE) + #define SESSIONS_PER_ROW 1 + #define SESSION_ROWS 1 + #else + #define SESSIONS_PER_ROW 3 + #define SESSION_ROWS 11 + #endif + #define INVALID_SESSION_ROW (-1) + + #ifdef NO_SESSION_CACHE_ROW_LOCK + #undef ENABLE_SESSION_CACHE_ROW_LOCK + #endif + + typedef struct SessionRow { + int nextIdx; /* where to place next one */ + int totalCount; /* sessions ever on this row */ +#ifdef SESSION_CACHE_DYNAMIC_MEM + WOLFSSL_SESSION* Sessions[SESSIONS_PER_ROW]; + void* heap; +#else + WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW]; +#endif + + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + /* not included in import/export */ + wolfSSL_RwLock row_lock; + int lock_valid; + #endif + } SessionRow; + #define SIZEOF_SESSION_ROW (sizeof(WOLFSSL_SESSION) + (sizeof(int) * 2)) + + static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS]; + + #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) + static WOLFSSL_GLOBAL word32 PeakSessions; + #endif + + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + #define SESSION_ROW_RD_LOCK(row) wc_LockRwLock_Rd(&(row)->row_lock) + #define SESSION_ROW_WR_LOCK(row) wc_LockRwLock_Wr(&(row)->row_lock) + #define SESSION_ROW_UNLOCK(row) wc_UnLockRwLock(&(row)->row_lock); + #else + static WOLFSSL_GLOBAL wolfSSL_RwLock session_lock; /* SessionCache lock */ + static WOLFSSL_GLOBAL int session_lock_valid = 0; + #define SESSION_ROW_RD_LOCK(row) wc_LockRwLock_Rd(&session_lock) + #define SESSION_ROW_WR_LOCK(row) wc_LockRwLock_Wr(&session_lock) + #define SESSION_ROW_UNLOCK(row) wc_UnLockRwLock(&session_lock); + #endif + + #if !defined(NO_SESSION_CACHE_REF) && defined(NO_CLIENT_CACHE) + #error ClientCache is required when not using NO_SESSION_CACHE_REF + #endif + + #ifndef NO_CLIENT_CACHE + + #ifndef CLIENT_SESSIONS_MULTIPLIER + #ifdef NO_SESSION_CACHE_REF + #define CLIENT_SESSIONS_MULTIPLIER 1 + #else + /* ClientSession objects are lightweight (compared to + * WOLFSSL_SESSION) so to decrease chance that user will reuse + * the wrong session, increase the ClientCache size. This will + * make the entire ClientCache about the size of one + * WOLFSSL_SESSION object. */ + #define CLIENT_SESSIONS_MULTIPLIER 8 + #endif + #endif + #define CLIENT_SESSIONS_PER_ROW \ + (SESSIONS_PER_ROW * CLIENT_SESSIONS_MULTIPLIER) + #define CLIENT_SESSION_ROWS (SESSION_ROWS * CLIENT_SESSIONS_MULTIPLIER) + + #if CLIENT_SESSIONS_PER_ROW > 65535 + #error CLIENT_SESSIONS_PER_ROW too big + #endif + #if CLIENT_SESSION_ROWS > 65535 + #error CLIENT_SESSION_ROWS too big + #endif + + struct ClientSession { + word16 serverRow; /* SessionCache Row id */ + word16 serverIdx; /* SessionCache Idx (column) */ + word32 sessionIDHash; + }; + #ifndef WOLFSSL_CLIENT_SESSION_DEFINED + typedef struct ClientSession ClientSession; + #define WOLFSSL_CLIENT_SESSION_DEFINED + #endif + + typedef struct ClientRow { + int nextIdx; /* where to place next one */ + int totalCount; /* sessions ever on this row */ + ClientSession Clients[CLIENT_SESSIONS_PER_ROW]; + } ClientRow; + + static WOLFSSL_GLOBAL ClientRow ClientCache[CLIENT_SESSION_ROWS]; + /* Client Cache */ + /* uses session mutex */ + + /* ClientCache mutex */ + static WOLFSSL_GLOBAL wolfSSL_Mutex clisession_mutex + WOLFSSL_MUTEX_INITIALIZER_CLAUSE(clisession_mutex); + #ifndef WOLFSSL_MUTEX_INITIALIZER + static WOLFSSL_GLOBAL int clisession_mutex_valid = 0; + #endif + #endif /* !NO_CLIENT_CACHE */ + + void EvictSessionFromCache(WOLFSSL_SESSION* session) + { +#ifdef HAVE_EX_DATA + int save_ownExData = session->ownExData; + session->ownExData = 1; /* Make sure ex_data access doesn't lead back + * into the cache. */ +#endif +#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) + if (session->rem_sess_cb != NULL) { + session->rem_sess_cb(NULL, session); + session->rem_sess_cb = NULL; + } +#endif + ForceZero(session->masterSecret, SECRET_LEN); + XMEMSET(session->sessionID, 0, ID_LEN); + session->sessionIDSz = 0; +#ifdef HAVE_SESSION_TICKET + if (session->ticketLenAlloc > 0) { + XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = session->staticTicket; + session->ticketLen = 0; + session->ticketLenAlloc = 0; + } +#endif +#ifdef HAVE_EX_DATA + session->ownExData = save_ownExData; +#endif + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \ + defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if ((session->ticketNonce.data != NULL) && + (session->ticketNonce.data != session->ticketNonce.dataStatic)) + { + XFREE(session->ticketNonce.data, NULL, DYNAMIC_TYPE_SESSION_TICK); + session->ticketNonce.data = NULL; + } +#endif + } + +WOLFSSL_ABI +WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_session"); + if (ssl) { +#ifdef NO_SESSION_CACHE_REF + return ssl->session; +#else + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* On the client side we want to return a persistent reference for + * backwards compatibility. */ +#ifndef NO_CLIENT_CACHE + if (ssl->clientSession) { + return (WOLFSSL_SESSION*)ssl->clientSession; + } + else { + /* Try to add a ClientCache entry to associate with the current + * session. Ignore any session cache options. */ + int err; + const byte* id = ssl->session->sessionID; + byte idSz = ssl->session->sessionIDSz; + if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; + idSz = ID_LEN; + } + err = AddSessionToCache(ssl->ctx, ssl->session, id, idSz, + NULL, ssl->session->side, + #ifdef HAVE_SESSION_TICKET + ssl->session->ticketLen > 0, + #else + 0, + #endif + &ssl->clientSession); + if (err == 0) { + return (WOLFSSL_SESSION*)ssl->clientSession; + } + } +#endif + } + else { + return ssl->session; + } +#endif + } + + return NULL; +} + +/* The get1 version requires caller to call SSL_SESSION_free */ +WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) +{ + WOLFSSL_SESSION* sess = NULL; + WOLFSSL_ENTER("wolfSSL_get1_session"); + if (ssl != NULL) { + sess = ssl->session; + if (sess != NULL) { + /* increase reference count if allocated session */ + if (sess->type == WOLFSSL_SESSION_TYPE_HEAP) { + if (wolfSSL_SESSION_up_ref(sess) != WOLFSSL_SUCCESS) + sess = NULL; + } + } + } + return sess; +} + +/* session is a private struct, return if it is setup or not */ +WOLFSSL_API int wolfSSL_SessionIsSetup(WOLFSSL_SESSION* session) +{ + if (session != NULL) + return session->isSetup; + return 0; +} + +/* + * Sets the session object to use when establishing a TLS/SSL session using + * the ssl object. Therefore, this function must be called before + * wolfSSL_connect. The session object to use can be obtained in a previous + * TLS/SSL connection using wolfSSL_get_session. + * + * This function rejects the session if it has been expired when this function + * is called. Note that this expiration check is wolfSSL specific and differs + * from OpenSSL return code behavior. + * + * By default, wolfSSL_set_session returns WOLFSSL_SUCCESS on successfully + * setting the session, WOLFSSL_FAILURE on failure due to the session cache + * being disabled, or the session has expired. + * + * To match OpenSSL return code behavior when session is expired, define + * OPENSSL_EXTRA and WOLFSSL_ERROR_CODE_OPENSSL. This behavior will return + * WOLFSSL_SUCCESS even when the session is expired and rejected. + */ +WOLFSSL_ABI +int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("wolfSSL_set_session"); + if (session) + return wolfSSL_SetSession(ssl, session); + + return WOLFSSL_FAILURE; +} + + +#ifndef NO_CLIENT_CACHE + +/* Associate client session with serverID, find existing or store for saving + if newSession flag on, don't reuse existing session + WOLFSSL_SUCCESS on ok */ +int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) +{ + WOLFSSL_SESSION* session = NULL; + byte idHash[SERVER_ID_LEN]; + + WOLFSSL_ENTER("wolfSSL_SetServerID"); + + if (ssl == NULL || id == NULL || len <= 0) + return BAD_FUNC_ARG; + + if (len > SERVER_ID_LEN) { +#if defined(NO_SHA) && !defined(NO_SHA256) + if (wc_Sha256Hash(id, len, idHash) != 0) + return WOLFSSL_FAILURE; +#else + if (wc_ShaHash(id, (word32)len, idHash) != 0) + return WOLFSSL_FAILURE; +#endif + id = idHash; + len = SERVER_ID_LEN; + } + + if (newSession == 0) { + session = wolfSSL_GetSessionClient(ssl, id, len); + if (session) { + if (wolfSSL_SetSession(ssl, session) != WOLFSSL_SUCCESS) { + #ifdef HAVE_EXT_CACHE + wolfSSL_FreeSession(ssl->ctx, session); + #endif + WOLFSSL_MSG("wolfSSL_SetSession failed"); + session = NULL; + } + } + } + + if (session == NULL) { + WOLFSSL_MSG("Valid ServerID not cached already"); + + ssl->session->idLen = (word16)len; + XMEMCPY(ssl->session->serverID, id, len); + } +#ifdef HAVE_EXT_CACHE + else { + wolfSSL_FreeSession(ssl->ctx, session); + } +#endif + + return WOLFSSL_SUCCESS; +} + +#endif /* !NO_CLIENT_CACHE */ + +/* TODO: Add SESSION_CACHE_DYNAMIC_MEM support for PERSIST_SESSION_CACHE. + * Need a count of current sessions to get an accurate memsize (totalCount is + * not decremented when sessions are removed). + * Need to determine ideal layout for mem/filesave. + * Also need mem/filesave checking to ensure not restoring non DYNAMIC_MEM + * cache. + */ +#if defined(PERSIST_SESSION_CACHE) && !defined(SESSION_CACHE_DYNAMIC_MEM) + +/* for persistence, if changes to layout need to increment and modify + save_session_cache() and restore_session_cache and memory versions too */ +#define WOLFSSL_CACHE_VERSION 2 + +/* Session Cache Header information */ +typedef struct { + int version; /* cache layout version id */ + int rows; /* session rows */ + int columns; /* session columns */ + int sessionSz; /* sizeof WOLFSSL_SESSION */ +} cache_header_t; + +/* current persistence layout is: + + 1) cache_header_t + 2) SessionCache + 3) ClientCache + + update WOLFSSL_CACHE_VERSION if change layout for the following + PERSISTENT_SESSION_CACHE functions +*/ + +/* get how big the the session cache save buffer needs to be */ +int wolfSSL_get_session_cache_memsize(void) +{ + int sz = (int)(sizeof(SessionCache) + sizeof(cache_header_t)); +#ifndef NO_CLIENT_CACHE + sz += (int)(sizeof(ClientCache)); +#endif + return sz; +} + + +/* Persist session cache to memory */ +int wolfSSL_memsave_session_cache(void* mem, int sz) +{ + int i; + cache_header_t cache_header; + SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); + + WOLFSSL_ENTER("wolfSSL_memsave_session_cache"); + + if (sz < wolfSSL_get_session_cache_memsize()) { + WOLFSSL_MSG("Memory buffer too small"); + return BUFFER_E; + } + + cache_header.version = WOLFSSL_CACHE_VERSION; + cache_header.rows = SESSION_ROWS; + cache_header.columns = SESSIONS_PER_ROW; + cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); + XMEMCPY(mem, &cache_header, sizeof(cache_header)); + +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_RD_LOCK(row) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + return BAD_MUTEX_E; + } +#endif + for (i = 0; i < cache_header.rows; ++i) { + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_RD_LOCK(&SessionCache[i]) != 0) { + WOLFSSL_MSG("Session row cache mutex lock failed"); + return BAD_MUTEX_E; + } + #endif + + XMEMCPY(row++, &SessionCache[i], SIZEOF_SESSION_ROW); + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[i]); + #endif + } +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(row); +#endif + +#ifndef NO_CLIENT_CACHE + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + return BAD_MUTEX_E; + } + XMEMCPY(row, ClientCache, sizeof(ClientCache)); + wc_UnLockMutex(&clisession_mutex); +#endif + + WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} + + +/* Restore the persistent session cache from memory */ +int wolfSSL_memrestore_session_cache(const void* mem, int sz) +{ + int i; + cache_header_t cache_header; + SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); + + WOLFSSL_ENTER("wolfSSL_memrestore_session_cache"); + + if (sz < wolfSSL_get_session_cache_memsize()) { + WOLFSSL_MSG("Memory buffer too small"); + return BUFFER_E; + } + + XMEMCPY(&cache_header, mem, sizeof(cache_header)); + if (cache_header.version != WOLFSSL_CACHE_VERSION || + cache_header.rows != SESSION_ROWS || + cache_header.columns != SESSIONS_PER_ROW || + cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) { + + WOLFSSL_MSG("Session cache header match failed"); + return CACHE_MATCH_ERROR; + } + +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_WR_LOCK(&SessionCache[0]) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + return BAD_MUTEX_E; + } +#endif + for (i = 0; i < cache_header.rows; ++i) { + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) { + WOLFSSL_MSG("Session row cache mutex lock failed"); + return BAD_MUTEX_E; + } + #endif + + XMEMCPY(&SessionCache[i], row++, SIZEOF_SESSION_ROW); + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[i]); + #endif + } +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[0]); +#endif + +#ifndef NO_CLIENT_CACHE + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + return BAD_MUTEX_E; + } + XMEMCPY(ClientCache, row, sizeof(ClientCache)); + wc_UnLockMutex(&clisession_mutex); +#endif + + WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} + +#if !defined(NO_FILESYSTEM) + +/* Persist session cache to file */ +/* doesn't use memsave because of additional memory use */ +int wolfSSL_save_session_cache(const char *fname) +{ + XFILE file; + int ret; + int rc = WOLFSSL_SUCCESS; + int i; + cache_header_t cache_header; + + WOLFSSL_ENTER("wolfSSL_save_session_cache"); + + file = XFOPEN(fname, "w+b"); + if (file == XBADFILE) { + WOLFSSL_MSG("Couldn't open session cache save file"); + return WOLFSSL_BAD_FILE; + } + cache_header.version = WOLFSSL_CACHE_VERSION; + cache_header.rows = SESSION_ROWS; + cache_header.columns = SESSIONS_PER_ROW; + cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); + + /* cache header */ + ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file); + if (ret != 1) { + WOLFSSL_MSG("Session cache header file write failed"); + XFCLOSE(file); + return FWRITE_ERROR; + } + +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_RD_LOCK(&SessionCache[0]) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } +#endif + /* session cache */ + for (i = 0; i < cache_header.rows; ++i) { + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_RD_LOCK(&SessionCache[i]) != 0) { + WOLFSSL_MSG("Session row cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + #endif + + ret = (int)XFWRITE(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file); + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[i]); + #endif + if (ret != 1) { + WOLFSSL_MSG("Session cache member file write failed"); + rc = FWRITE_ERROR; + break; + } + } +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[0]); +#endif + +#ifndef NO_CLIENT_CACHE + /* client cache */ + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + ret = (int)XFWRITE(ClientCache, sizeof(ClientCache), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file write failed"); + rc = FWRITE_ERROR; + } + wc_UnLockMutex(&clisession_mutex); +#endif /* !NO_CLIENT_CACHE */ + + XFCLOSE(file); + WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc); + + return rc; +} + + +/* Restore the persistent session cache from file */ +/* doesn't use memstore because of additional memory use */ +int wolfSSL_restore_session_cache(const char *fname) +{ + XFILE file; + int rc = WOLFSSL_SUCCESS; + int ret; + int i; + cache_header_t cache_header; + + WOLFSSL_ENTER("wolfSSL_restore_session_cache"); + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) { + WOLFSSL_MSG("Couldn't open session cache save file"); + return WOLFSSL_BAD_FILE; + } + /* cache header */ + ret = (int)XFREAD(&cache_header, sizeof(cache_header), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Session cache header file read failed"); + XFCLOSE(file); + return FREAD_ERROR; + } + if (cache_header.version != WOLFSSL_CACHE_VERSION || + cache_header.rows != SESSION_ROWS || + cache_header.columns != SESSIONS_PER_ROW || + cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) { + + WOLFSSL_MSG("Session cache header match failed"); + XFCLOSE(file); + return CACHE_MATCH_ERROR; + } + +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_WR_LOCK(&SessionCache[0]) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } +#endif + /* session cache */ + for (i = 0; i < cache_header.rows; ++i) { + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) { + WOLFSSL_MSG("Session row cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + #endif + + ret = (int)XFREAD(&SessionCache[i], SIZEOF_SESSION_ROW, 1, file); + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[i]); + #endif + if (ret != 1) { + WOLFSSL_MSG("Session cache member file read failed"); + XMEMSET(SessionCache, 0, sizeof SessionCache); + rc = FREAD_ERROR; + break; + } + } +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[0]); +#endif + +#ifndef NO_CLIENT_CACHE + /* client cache */ + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + ret = (int)XFREAD(ClientCache, sizeof(ClientCache), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file read failed"); + XMEMSET(ClientCache, 0, sizeof ClientCache); + rc = FREAD_ERROR; + } + wc_UnLockMutex(&clisession_mutex); +#endif /* !NO_CLIENT_CACHE */ + + XFCLOSE(file); + WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc); + + return rc; +} + +#endif /* !NO_FILESYSTEM */ +#endif /* PERSIST_SESSION_CACHE && !SESSION_CACHE_DYNAMIC_MEM */ + + +/* on by default if built in but allow user to turn off */ +WOLFSSL_ABI +long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_session_cache_mode"); + + if (ctx == NULL) + return WOLFSSL_FAILURE; + + if (mode == WOLFSSL_SESS_CACHE_OFF) { + ctx->sessionCacheOff = 1; +#ifdef HAVE_EXT_CACHE + ctx->internalCacheOff = 1; + ctx->internalCacheLookupOff = 1; +#endif + } + + if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) + ctx->sessionCacheFlushOff = 1; + +#ifdef HAVE_EXT_CACHE + /* WOLFSSL_SESS_CACHE_NO_INTERNAL activates both if's */ + if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + ctx->internalCacheOff = 1; + if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP) != 0) + ctx->internalCacheLookupOff = 1; +#endif + + return WOLFSSL_SUCCESS; +} + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_MAX_FRAGMENT +/* return the max fragment size set when handshake was negotiated */ +unsigned char wolfSSL_SESSION_get_max_fragment_length(WOLFSSL_SESSION* session) +{ + session = ClientSessionToSession(session); + if (session == NULL) { + return 0; + } + + return session->mfl; +} +#endif + + +/* Get the session cache mode for CTX + * + * ctx WOLFSSL_CTX struct to get cache mode from + * + * Returns a bit mask that has the session cache mode */ +long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) +{ + long m = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_get_session_cache_mode"); + + if (ctx == NULL) { + return m; + } + + if (ctx->sessionCacheOff != 1) { + m |= WOLFSSL_SESS_CACHE_SERVER; + } + + if (ctx->sessionCacheFlushOff == 1) { + m |= WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->internalCacheOff == 1) { + m |= WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE; + } + if (ctx->internalCacheLookupOff == 1) { + m |= WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP; + } +#endif + + return m; +} +#endif /* OPENSSL_EXTRA */ + +#endif /* !NO_SESSION_CACHE */ + +#ifndef NO_SESSION_CACHE + +WOLFSSL_ABI +void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm) +{ + /* static table now, no flushing needed */ + (void)ctx; + (void)tm; +} + +void wolfSSL_CTX_flush_sessions(WOLFSSL_CTX* ctx, long tm) +{ + int i, j; + byte id[ID_LEN]; + + (void)ctx; + XMEMSET(id, 0, ID_LEN); + WOLFSSL_ENTER("wolfSSL_flush_sessions"); + for (i = 0; i < SESSION_ROWS; ++i) { + if (SESSION_ROW_WR_LOCK(&SessionCache[i]) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + return; + } + for (j = 0; j < SESSIONS_PER_ROW; j++) { +#ifdef SESSION_CACHE_DYNAMIC_MEM + WOLFSSL_SESSION* s = SessionCache[i].Sessions[j]; +#else + WOLFSSL_SESSION* s = &SessionCache[i].Sessions[j]; +#endif + if ( +#ifdef SESSION_CACHE_DYNAMIC_MEM + s != NULL && +#endif + XMEMCMP(s->sessionID, id, ID_LEN) != 0 && + s->bornOn + s->timeout < (word32)tm + ) + { + EvictSessionFromCache(s); +#ifdef SESSION_CACHE_DYNAMIC_MEM + XFREE(s, s->heap, DYNAMIC_TYPE_SESSION); + SessionCache[i].Sessions[j] = NULL; +#endif + } + } + SESSION_ROW_UNLOCK(&SessionCache[i]); + } +} + + +/* set ssl session timeout in seconds */ +WOLFSSL_ABI +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 WOLFSSL_SUCCESS; +} + + +/** + * Sets ctx session timeout in seconds. + * The timeout value set here should be reflected in the + * "session ticket lifetime hint" if this API works in the openssl compat-layer. + * Therefore wolfSSL_CTX_set_TicketHint is called internally. + * Arguments: + * - ctx WOLFSSL_CTX object which the timeout is set to + * - to timeout value in second + * Returns: + * WOLFSSL_SUCCESS on success, BAD_FUNC_ARG on failure. + * When WOLFSSL_ERROR_CODE_OPENSSL is defined, returns previous timeout value + * on success, BAD_FUNC_ARG on failure. + */ +WOLFSSL_ABI +int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) +{ + #if defined(WOLFSSL_ERROR_CODE_OPENSSL) + word32 prev_timeout = 0; + #endif + + int ret = WOLFSSL_SUCCESS; + (void)ret; + + if (ctx == NULL) + ret = BAD_FUNC_ARG; + + if (ret == WOLFSSL_SUCCESS) { + #if defined(WOLFSSL_ERROR_CODE_OPENSSL) + prev_timeout = ctx->timeout; + #endif + if (to == 0) { + ctx->timeout = WOLFSSL_SESSION_TIMEOUT; + } + else { + ctx->timeout = to; + } + } +#if defined(OPENSSL_EXTRA) && defined(HAVE_SESSION_TICKET) && \ + !defined(NO_WOLFSSL_SERVER) + if (ret == WOLFSSL_SUCCESS) { + if (to == 0) { + ret = wolfSSL_CTX_set_TicketHint(ctx, SESSION_TICKET_HINT_DEFAULT); + } + else { + ret = wolfSSL_CTX_set_TicketHint(ctx, (int)to); + } + } +#endif /* OPENSSL_EXTRA && HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER */ + +#if defined(WOLFSSL_ERROR_CODE_OPENSSL) + if (ret == WOLFSSL_SUCCESS) { + return (int)prev_timeout; + } + else { + return ret; + } +#else + return ret; +#endif /* WOLFSSL_ERROR_CODE_OPENSSL */ +} + + +#ifndef NO_CLIENT_CACHE + +/* Get Session from Client cache based on id/len, return NULL on failure */ +WOLFSSL_SESSION* wolfSSL_GetSessionClient(WOLFSSL* ssl, const byte* id, int len) +{ + WOLFSSL_SESSION* ret = NULL; + word32 row; + int idx; + int count; + int error = 0; + ClientSession* clSess; + + WOLFSSL_ENTER("wolfSSL_GetSessionClient"); + + if (ssl->ctx->sessionCacheOff) { + WOLFSSL_MSG("Session Cache off"); + return NULL; + } + + if (ssl->options.side == WOLFSSL_SERVER_END) + return NULL; + + len = (int)min(SERVER_ID_LEN, (word32)len); + + /* Do not access ssl->ctx->get_sess_cb from here. It is using a different + * set of ID's */ + + row = HashObject(id, (word32)len, &error) % CLIENT_SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return NULL; + } + + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + return NULL; + } + + /* start from most recently used */ + count = (int)min((word32)ClientCache[row].totalCount, CLIENT_SESSIONS_PER_ROW); + idx = ClientCache[row].nextIdx - 1; + if (idx < 0 || idx >= CLIENT_SESSIONS_PER_ROW) { + /* if back to front, the previous was end */ + idx = CLIENT_SESSIONS_PER_ROW - 1; + } + clSess = ClientCache[row].Clients; + + for (; count > 0; --count) { + WOLFSSL_SESSION* current; + SessionRow* sessRow; + + if (clSess[idx].serverRow >= SESSION_ROWS) { + WOLFSSL_MSG("Client cache serverRow invalid"); + break; + } + + /* lock row */ + sessRow = &SessionCache[clSess[idx].serverRow]; + if (SESSION_ROW_RD_LOCK(sessRow) != 0) { + WOLFSSL_MSG("Session cache row lock failure"); + break; + } + +#ifdef SESSION_CACHE_DYNAMIC_MEM + current = sessRow->Sessions[clSess[idx].serverIdx]; +#else + current = &sessRow->Sessions[clSess[idx].serverIdx]; +#endif + if (current && XMEMCMP(current->serverID, id, len) == 0) { + WOLFSSL_MSG("Found a serverid match for client"); + if (LowResTimer() < (current->bornOn + current->timeout)) { + WOLFSSL_MSG("Session valid"); + ret = current; + SESSION_ROW_UNLOCK(sessRow); + break; + } else { + WOLFSSL_MSG("Session timed out"); /* could have more for id */ + } + } else { + WOLFSSL_MSG("ServerID not a match from client table"); + } + SESSION_ROW_UNLOCK(sessRow); + + idx = idx > 0 ? idx - 1 : CLIENT_SESSIONS_PER_ROW - 1; + } + + wc_UnLockMutex(&clisession_mutex); + + return ret; +} + +#endif /* !NO_CLIENT_CACHE */ + +static int SslSessionCacheOff(const WOLFSSL* ssl, + const WOLFSSL_SESSION* session) +{ + (void)session; + return ssl->options.sessionCacheOff + #if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_FORCE_CACHE_ON_TICKET) + && session->ticketLen == 0 + #endif + ; +} + +#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) +/** + * SessionTicketNoncePrealloc() - prealloc a buffer for ticket nonces + * @output: [in] pointer to WOLFSSL_SESSION object that will soon be a + * destination of a session duplication + * @buf: [out] address of the preallocated buf + * @len: [out] len of the preallocated buf + * + * prealloc a buffer that will likely suffice to contain a ticket nonce. It's + * used when copying session under lock, when syscalls need to be avoided. If + * output already has a dynamic buffer, it's reused. + */ +static int SessionTicketNoncePrealloc(byte** buf, byte* len, void *heap) +{ + (void)heap; + + *buf = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_NONCE_LEN, heap, + DYNAMIC_TYPE_SESSION_TICK); + if (*buf == NULL) { + WOLFSSL_MSG("Failed to preallocate ticket nonce buffer"); + *len = 0; + return 1; + } + + *len = PREALLOC_SESSION_TICKET_NONCE_LEN; + return 0; +} +#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 */ + +static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input, + WOLFSSL_SESSION* output, int avoidSysCalls, byte* ticketNonceBuf, + byte* ticketNonceLen, byte* preallocUsed); + +void TlsSessionCacheUnlockRow(word32 row) +{ + SessionRow* sessRow; + + sessRow = &SessionCache[row]; + (void)sessRow; + SESSION_ROW_UNLOCK(sessRow); +} + +/* Don't use this function directly. Use TlsSessionCacheGetAndRdLock and + * TlsSessionCacheGetAndWrLock to fully utilize compiler const support. */ +static int TlsSessionCacheGetAndLock(const byte *id, + const WOLFSSL_SESSION **sess, word32 *lockedRow, byte readOnly, byte side) +{ + SessionRow *sessRow; + const WOLFSSL_SESSION *s; + word32 row; + int count; + int error; + int idx; + + *sess = NULL; + row = HashObject(id, ID_LEN, &error) % SESSION_ROWS; + if (error != 0) + return error; + sessRow = &SessionCache[row]; + if (readOnly) + error = SESSION_ROW_RD_LOCK(sessRow); + else + error = SESSION_ROW_WR_LOCK(sessRow); + if (error != 0) + return FATAL_ERROR; + + /* start from most recently used */ + count = (int)min((word32)sessRow->totalCount, SESSIONS_PER_ROW); + idx = sessRow->nextIdx - 1; + if (idx < 0 || idx >= SESSIONS_PER_ROW) { + idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ + } + for (; count > 0; --count) { +#ifdef SESSION_CACHE_DYNAMIC_MEM + s = sessRow->Sessions[idx]; +#else + s = &sessRow->Sessions[idx]; +#endif + if (s && XMEMCMP(s->sessionID, id, ID_LEN) == 0 && s->side == side) { + *sess = s; + break; + } + idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; + } + if (*sess == NULL) { + SESSION_ROW_UNLOCK(sessRow); + } + else { + *lockedRow = row; + } + + return 0; +} + +static int CheckSessionMatch(const WOLFSSL* ssl, const WOLFSSL_SESSION* sess) +{ + if (ssl == NULL || sess == NULL) + return 0; +#ifdef OPENSSL_EXTRA + if (ssl->sessionCtxSz > 0 && (ssl->sessionCtxSz != sess->sessionCtxSz || + XMEMCMP(ssl->sessionCtx, sess->sessionCtx, sess->sessionCtxSz) != 0)) + return 0; +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (IsAtLeastTLSv1_3(ssl->version) != IsAtLeastTLSv1_3(sess->version)) + return 0; +#endif + return 1; +} + +int TlsSessionCacheGetAndRdLock(const byte *id, const WOLFSSL_SESSION **sess, + word32 *lockedRow, byte side) +{ + return TlsSessionCacheGetAndLock(id, sess, lockedRow, 1, side); +} + +int TlsSessionCacheGetAndWrLock(const byte *id, WOLFSSL_SESSION **sess, + word32 *lockedRow, byte side) +{ + return TlsSessionCacheGetAndLock(id, (const WOLFSSL_SESSION**)sess, + lockedRow, 0, side); +} + +int wolfSSL_GetSessionFromCache(WOLFSSL* ssl, WOLFSSL_SESSION* output) +{ + const WOLFSSL_SESSION* sess = NULL; + const byte* id = NULL; + word32 row; + int error = 0; +#ifdef HAVE_SESSION_TICKET +#ifndef WOLFSSL_SMALL_STACK + byte tmpTicket[PREALLOC_SESSION_TICKET_LEN]; +#else + byte* tmpTicket = NULL; +#endif +#ifdef WOLFSSL_TLS13 + byte *preallocNonce = NULL; + byte preallocNonceLen = 0; + byte preallocNonceUsed = 0; +#endif /* WOLFSSL_TLS13 */ + byte tmpBufSet = 0; +#endif +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* peer = NULL; +#endif + byte bogusID[ID_LEN]; + byte bogusIDSz = 0; + + WOLFSSL_ENTER("wolfSSL_GetSessionFromCache"); + + if (output == NULL) { + WOLFSSL_MSG("NULL output"); + return WOLFSSL_FAILURE; + } + + if (SslSessionCacheOff(ssl, ssl->session)) + return WOLFSSL_FAILURE; + + if (ssl->options.haveSessionId == 0 && !ssl->session->haveAltSessionID) + return WOLFSSL_FAILURE; + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) + return WOLFSSL_FAILURE; +#endif + + XMEMSET(bogusID, 0, sizeof(bogusID)); + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL + && !ssl->session->haveAltSessionID) + id = ssl->arrays->sessionID; + else if (ssl->session->haveAltSessionID) { + id = ssl->session->altSessionID; + /* We want to restore the bogus ID for TLS compatibility */ + if (output == ssl->session) { + XMEMCPY(bogusID, ssl->session->sessionID, ID_LEN); + bogusIDSz = ssl->session->sessionIDSz; + } + } + else + id = ssl->session->sessionID; + + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + int found = 0; + WOLFSSL_SESSION* extSess; + /* Attempt to retrieve the session from the external cache. */ + WOLFSSL_MSG("Calling external session cache"); + extSess = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if ((extSess != NULL) + && CheckSessionMatch(ssl, extSess) + ) { + WOLFSSL_MSG("Session found in external cache"); + found = 1; + + error = wolfSSL_DupSession(extSess, output, 0); +#ifdef HAVE_EX_DATA + extSess->ownExData = 1; + output->ownExData = 0; +#endif + /* We want to restore the bogus ID for TLS compatibility */ + if (ssl->session->haveAltSessionID && + output == ssl->session) { + XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); + ssl->session->sessionIDSz = bogusIDSz; + } + } + /* If copy not set then free immediately */ + if (extSess != NULL && !copy) + wolfSSL_FreeSession(ssl->ctx, extSess); + if (found) + return error; + WOLFSSL_MSG("Session not found in external cache"); + } + + if (ssl->options.internalCacheLookupOff) { + WOLFSSL_MSG("Internal cache lookup turned off"); + return WOLFSSL_FAILURE; + } +#endif + +#ifdef HAVE_SESSION_TICKET + if (output->ticket == NULL || + output->ticketLenAlloc < PREALLOC_SESSION_TICKET_LEN) { +#ifdef WOLFSSL_SMALL_STACK + tmpTicket = (byte*)XMALLOC(PREALLOC_SESSION_TICKET_LEN, output->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpTicket == NULL) { + WOLFSSL_MSG("tmpTicket malloc failed"); + return WOLFSSL_FAILURE; + } +#endif + if (output->ticketLenAlloc) + XFREE(output->ticket, output->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = tmpTicket; /* cppcheck-suppress autoVariables + */ + output->ticketLenAlloc = PREALLOC_SESSION_TICKET_LEN; + output->ticketLen = 0; + tmpBufSet = 1; + } +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (output->peer != NULL) { + wolfSSL_X509_free(output->peer); + output->peer = NULL; + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && \ + defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (output->ticketNonce.data != output->ticketNonce.dataStatic) { + XFREE(output->ticketNonce.data, output->heap, + DYNAMIC_TYPE_SESSION_TICK); + output->ticketNonce.data = output->ticketNonce.dataStatic; + output->ticketNonce.len = 0; + } + error = SessionTicketNoncePrealloc(&preallocNonce, &preallocNonceLen, + output->heap); + if (error != 0) { + if (tmpBufSet) { + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + } +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return WOLFSSL_FAILURE; + } +#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET*/ + + /* init to avoid clang static analyzer false positive */ + row = 0; + error = TlsSessionCacheGetAndRdLock(id, &sess, &row, + (byte)ssl->options.side); + error = (error == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + if (error != WOLFSSL_SUCCESS || sess == NULL) { + WOLFSSL_MSG("Get Session from cache failed"); + error = WOLFSSL_FAILURE; +#ifdef HAVE_SESSION_TICKET + if (tmpBufSet) { + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + } +#ifdef WOLFSSL_TLS13 + if (preallocNonce != NULL) { + XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK); + preallocNonce = NULL; + } +#endif /* WOLFSSL_TLS13 */ +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) { + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); + tmpTicket = NULL; + } +#endif +#endif + } + else { + if (!CheckSessionMatch(ssl, sess)) { + WOLFSSL_MSG("Invalid session: can't be used in this context"); + TlsSessionCacheUnlockRow(row); + error = WOLFSSL_FAILURE; + } + else if (LowResTimer() >= (sess->bornOn + sess->timeout)) { + WOLFSSL_SESSION* wrSess = NULL; + WOLFSSL_MSG("Invalid session: timed out"); + sess = NULL; + TlsSessionCacheUnlockRow(row); + /* Attempt to get a write lock */ + error = TlsSessionCacheGetAndWrLock(id, &wrSess, &row, + (byte)ssl->options.side); + if (error == 0 && wrSess != NULL) { + EvictSessionFromCache(wrSess); + TlsSessionCacheUnlockRow(row); + } + error = WOLFSSL_FAILURE; + } + } + + /* mollify confused cppcheck nullPointer warning. */ + if (sess == NULL) + error = WOLFSSL_FAILURE; + + if (error == WOLFSSL_SUCCESS) { +#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) + error = wolfSSL_DupSessionEx(sess, output, 1, + preallocNonce, &preallocNonceLen, &preallocNonceUsed); +#else + error = wolfSSL_DupSession(sess, output, 1); +#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 */ +#ifdef HAVE_EX_DATA + output->ownExData = !sess->ownExData; /* Session may own ex_data */ +#endif + TlsSessionCacheUnlockRow(row); + } + + /* We want to restore the bogus ID for TLS compatibility */ + if (ssl->session->haveAltSessionID && + output == ssl->session) { + XMEMCPY(ssl->session->sessionID, bogusID, ID_LEN); + ssl->session->sessionIDSz = bogusIDSz; + } + +#ifdef HAVE_SESSION_TICKET + if (tmpBufSet) { + if (error == WOLFSSL_SUCCESS) { + if (output->ticketLen > SESSION_TICKET_LEN) { + output->ticket = (byte*)XMALLOC(output->ticketLen, output->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (output->ticket == NULL) { + error = WOLFSSL_FAILURE; + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + output->ticketLen = 0; + } + } + else { + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + } + } + else { + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + output->ticketLen = 0; + } + if (error == WOLFSSL_SUCCESS) { + XMEMCPY(output->ticket, tmpTicket, output->ticketLen); + } + } +#ifdef WOLFSSL_SMALL_STACK + if (tmpTicket != NULL) + XFREE(tmpTicket, output->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (error == WOLFSSL_SUCCESS && preallocNonceUsed) { + if (preallocNonceLen < PREALLOC_SESSION_TICKET_NONCE_LEN) { + /* buffer bigger than needed */ +#ifndef XREALLOC + output->ticketNonce.data = (byte*)XMALLOC(preallocNonceLen, + output->heap, DYNAMIC_TYPE_SESSION_TICK); + if (output->ticketNonce.data != NULL) + XMEMCPY(output->ticketNonce.data, preallocNonce, + preallocNonceLen); + XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK); + preallocNonce = NULL; +#else + output->ticketNonce.data = (byte*)XREALLOC(preallocNonce, + preallocNonceLen, output->heap, DYNAMIC_TYPE_SESSION_TICK); + if (output->ticketNonce.data != NULL) { + /* don't free the reallocated pointer */ + preallocNonce = NULL; + } +#endif /* !XREALLOC */ + if (output->ticketNonce.data == NULL) { + output->ticketNonce.data = output->ticketNonce.dataStatic; + output->ticketNonce.len = 0; + error = WOLFSSL_FAILURE; + /* preallocNonce will be free'd after the if */ + } + } + else { + output->ticketNonce.data = preallocNonce; + output->ticketNonce.len = preallocNonceLen; + preallocNonce = NULL; + } + } + if (preallocNonce != NULL) + XFREE(preallocNonce, output->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ + +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (peer != NULL) { + wolfSSL_X509_free(peer); + } +#endif + + return error; +} + +WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) +{ + WOLFSSL_SESSION* ret = NULL; + + (void)restoreSessionCerts; /* Kept for compatibility */ + + if (wolfSSL_GetSessionFromCache(ssl, ssl->session) == WOLFSSL_SUCCESS) { + ret = ssl->session; + } + else { + WOLFSSL_MSG("wolfSSL_GetSessionFromCache did not return a session"); + } + + if (ret != NULL && masterSecret != NULL) + XMEMCPY(masterSecret, ret->masterSecret, SECRET_LEN); + + return ret; +} + +int wolfSSL_SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + SessionRow* sessRow = NULL; + int ret = WOLFSSL_SUCCESS; + + session = ClientSessionToSession(session); + + if (ssl == NULL || session == NULL || !session->isSetup) { + WOLFSSL_MSG("ssl or session NULL or not set up"); + return WOLFSSL_FAILURE; + } + + /* We need to lock the session as the first step if its in the cache */ + if (session->type == WOLFSSL_SESSION_TYPE_CACHE) { + if (session->cacheRow < SESSION_ROWS) { + sessRow = &SessionCache[session->cacheRow]; + if (SESSION_ROW_RD_LOCK(sessRow) != 0) { + WOLFSSL_MSG("Session row lock failed"); + return WOLFSSL_FAILURE; + } + } + } + + if (ret == WOLFSSL_SUCCESS && ssl->options.side != WOLFSSL_NEITHER_END && + (byte)ssl->options.side != session->side) { + WOLFSSL_MSG("Setting session for wrong role"); + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + if (ssl->session == session) { + WOLFSSL_MSG("ssl->session and session same"); + } + else if (session->type != WOLFSSL_SESSION_TYPE_CACHE) { + if (wolfSSL_SESSION_up_ref(session) == WOLFSSL_SUCCESS) { + wolfSSL_FreeSession(ssl->ctx, ssl->session); + ssl->session = session; + } + else + ret = WOLFSSL_FAILURE; + } + else { + ret = wolfSSL_DupSession(session, ssl->session, 0); + if (ret != WOLFSSL_SUCCESS) + WOLFSSL_MSG("Session duplicate failed"); + } + } + + /* Let's copy over the altSessionID for local cache purposes */ + if (ret == WOLFSSL_SUCCESS && session->haveAltSessionID && + ssl->session != session) { + ssl->session->haveAltSessionID = 1; + XMEMCPY(ssl->session->altSessionID, session->altSessionID, ID_LEN); + } + + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + sessRow = NULL; + } + + /* Note: the `session` variable cannot be used below, since the row is + * un-locked */ + + if (ret != WOLFSSL_SUCCESS) + return ret; + +#ifdef WOLFSSL_SESSION_ID_CTX + /* check for application context id */ + if (ssl->sessionCtxSz > 0) { + if (XMEMCMP(ssl->sessionCtx, ssl->session->sessionCtx, + ssl->sessionCtxSz)) { + /* context id did not match! */ + WOLFSSL_MSG("Session context did not match"); + return WOLFSSL_FAILURE; + } + } +#endif /* WOLFSSL_SESSION_ID_CTX */ + + if (LowResTimer() >= (ssl->session->bornOn + ssl->session->timeout)) { +#if !defined(OPENSSL_EXTRA) || !defined(WOLFSSL_ERROR_CODE_OPENSSL) + return WOLFSSL_FAILURE; /* session timed out */ +#else /* defined(OPENSSL_EXTRA) && defined(WOLFSSL_ERROR_CODE_OPENSSL) */ + WOLFSSL_MSG("Session is expired but return success for " + "OpenSSL compatibility"); +#endif + } + ssl->options.resuming = 1; + ssl->options.haveEMS = ssl->session->haveEMS; + +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ssl->version = ssl->session->version; + if (IsAtLeastTLSv1_3(ssl->version)) + ssl->options.tls1_3 = 1; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + ssl->options.cipherSuite0 = ssl->session->cipherSuite0; + ssl->options.cipherSuite = ssl->session->cipherSuite; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = (unsigned long)ssl->session->peerVerifyRet; +#endif + + return WOLFSSL_SUCCESS; +} + + +#ifdef WOLFSSL_SESSION_STATS +static int get_locked_session_stats(word32* active, word32* total, + word32* peak); +#endif + +#ifndef NO_CLIENT_CACHE +ClientSession* AddSessionToClientCache(int side, int row, int idx, + byte* serverID, word16 idLen, const byte* sessionID, word16 useTicket) +{ + int error = -1; + word32 clientRow = 0, clientIdx = 0; + ClientSession* ret = NULL; + + (void)useTicket; + if (side == WOLFSSL_CLIENT_END + && row != INVALID_SESSION_ROW + && (idLen +#ifdef HAVE_SESSION_TICKET + || useTicket == 1 +#endif + || serverID != NULL + )) { + + WOLFSSL_MSG("Trying to add client cache entry"); + + if (idLen) { + clientRow = HashObject(serverID, + idLen, &error) % CLIENT_SESSION_ROWS; + } + else if (serverID != NULL) { + clientRow = HashObject(sessionID, + ID_LEN, &error) % CLIENT_SESSION_ROWS; + } + else { + error = -1; + } + if (error == 0 && wc_LockMutex(&clisession_mutex) == 0) { + clientIdx = (word32)ClientCache[clientRow].nextIdx; + if (clientIdx < CLIENT_SESSIONS_PER_ROW) { + ClientCache[clientRow].Clients[clientIdx].serverRow = + (word16)row; + ClientCache[clientRow].Clients[clientIdx].serverIdx = + (word16)idx; + if (sessionID != NULL) { + word32 sessionIDHash = HashObject(sessionID, ID_LEN, + &error); + if (error == 0) { + ClientCache[clientRow].Clients[clientIdx].sessionIDHash + = sessionIDHash; + } + } + } + else { + error = -1; + ClientCache[clientRow].nextIdx = 0; /* reset index as safety */ + WOLFSSL_MSG("Invalid client cache index! " + "Possible corrupted memory"); + } + if (error == 0) { + WOLFSSL_MSG("Adding client cache entry"); + + ret = &ClientCache[clientRow].Clients[clientIdx]; + + if (ClientCache[clientRow].totalCount < CLIENT_SESSIONS_PER_ROW) + ClientCache[clientRow].totalCount++; + ClientCache[clientRow].nextIdx++; + ClientCache[clientRow].nextIdx %= CLIENT_SESSIONS_PER_ROW; + } + + wc_UnLockMutex(&clisession_mutex); + } + else { + WOLFSSL_MSG("Hash session or lock failed"); + } + } + else { + WOLFSSL_MSG("Skipping client cache"); + } + + return ret; +} +#endif /* !NO_CLIENT_CACHE */ + +/** + * For backwards compatibility, this API needs to be used in *ALL* functions + * that access the WOLFSSL_SESSION members directly. + * + * This API checks if the passed in session is actually a ClientSession object + * and returns the matching session cache object. Otherwise just return the + * input. ClientSession objects only occur in the ClientCache. They are not + * allocated anywhere else. + */ +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("ClientSessionToSession"); +#ifdef NO_SESSION_CACHE_REF + return (WOLFSSL_SESSION*)session; +#else +#ifndef NO_CLIENT_CACHE + if (session == NULL) + return NULL; + /* Check if session points into ClientCache */ + if ((byte*)session >= (byte*)ClientCache && + /* Cast to byte* to make pointer arithmetic work per byte */ + (byte*)session < ((byte*)ClientCache) + sizeof(ClientCache)) { + ClientSession* clientSession = (ClientSession*)session; + SessionRow* sessRow = NULL; + WOLFSSL_SESSION* cacheSession = NULL; + word32 sessionIDHash = 0; + int error = 0; + session = NULL; /* Default to NULL for failure case */ + if (wc_LockMutex(&clisession_mutex) != 0) { + WOLFSSL_MSG("Client cache mutex lock failed"); + return NULL; + } + if (clientSession->serverRow >= SESSION_ROWS || + clientSession->serverIdx >= SESSIONS_PER_ROW) { + WOLFSSL_MSG("Client cache serverRow or serverIdx invalid"); + error = -1; + } + /* Prevent memory access before clientSession->serverRow and + * clientSession->serverIdx are sanitized. */ + XFENCE(); + if (error == 0) { + /* Lock row */ + sessRow = &SessionCache[clientSession->serverRow]; + error = SESSION_ROW_RD_LOCK(sessRow); + if (error != 0) { + WOLFSSL_MSG("Session cache row lock failure"); + sessRow = NULL; + } + } + if (error == 0) { +#ifdef SESSION_CACHE_DYNAMIC_MEM + cacheSession = sessRow->Sessions[clientSession->serverIdx]; +#else + cacheSession = &sessRow->Sessions[clientSession->serverIdx]; +#endif + if (cacheSession && cacheSession->sessionIDSz == 0) { + cacheSession = NULL; + WOLFSSL_MSG("Session cache entry not set"); + error = -1; + } + } + if (error == 0) { + /* Calculate the hash of the session ID */ + sessionIDHash = HashObject(cacheSession->sessionID, ID_LEN, + &error); + } + if (error == 0) { + /* Check the session ID hash matches */ + error = clientSession->sessionIDHash != sessionIDHash; + if (error != 0) + WOLFSSL_MSG("session ID hashes don't match"); + } + if (error == 0) { + /* Hashes match */ + session = cacheSession; + WOLFSSL_MSG("Found session cache matching client session object"); + } + if (sessRow != NULL) { + SESSION_ROW_UNLOCK(sessRow); + } + wc_UnLockMutex(&clisession_mutex); + return (WOLFSSL_SESSION*)session; + } + else { + /* Plain WOLFSSL_SESSION object */ + return (WOLFSSL_SESSION*)session; + } +#else + return (WOLFSSL_SESSION*)session; +#endif +#endif +} + +int AddSessionToCache(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* addSession, + const byte* id, byte idSz, int* sessionIndex, int side, + word16 useTicket, ClientSession** clientCacheEntry) +{ + WOLFSSL_SESSION* cacheSession = NULL; + SessionRow* sessRow = NULL; + word32 idx = 0; +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* cachePeer = NULL; + WOLFSSL_X509* addPeer = NULL; +#endif +#ifdef HAVE_SESSION_TICKET + byte* cacheTicBuff = NULL; + byte ticBuffUsed = 0; + byte* ticBuff = NULL; + int ticLen = 0; +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + byte *preallocNonce = NULL; + byte preallocNonceLen = 0; + byte preallocNonceUsed = 0; + byte *toFree = NULL; +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC */ +#endif /* HAVE_SESSION_TICKET */ + int ret = 0; + int row; + int i; + int overwrite = 0; + (void)ctx; + (void)sessionIndex; + (void)useTicket; + (void)clientCacheEntry; + + WOLFSSL_ENTER("AddSessionToCache"); + + if (idSz == 0) { + WOLFSSL_MSG("AddSessionToCache idSz == 0"); + return BAD_FUNC_ARG; + } + + addSession = ClientSessionToSession(addSession); + if (addSession == NULL) { + WOLFSSL_MSG("AddSessionToCache is NULL"); + return MEMORY_E; + } + +#ifdef HAVE_SESSION_TICKET + ticLen = addSession->ticketLen; + /* Alloc Memory here to avoid syscalls during lock */ + if (ticLen > SESSION_TICKET_LEN) { + ticBuff = (byte*)XMALLOC(ticLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + if (ticBuff == NULL) { + return MEMORY_E; + } + } +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (addSession->ticketNonce.data != addSession->ticketNonce.dataStatic) { + /* use the AddSession->heap even if the buffer maybe saved in + * CachedSession objects. CachedSession heap and AddSession heap should + * be the same */ + preallocNonce = (byte*)XMALLOC(addSession->ticketNonce.len, + addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + if (preallocNonce == NULL) { + if (ticBuff != NULL) + XFREE(ticBuff, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + return MEMORY_E; + } + preallocNonceLen = addSession->ticketNonce.len; + } +#endif /* WOLFSSL_TLS13 && WOLFSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3) */ +#endif /* HAVE_SESSION_TICKET */ + + /* Find a position for the new session in cache and use that */ + /* Use the session object in the cache for external cache if required */ + row = (int)(HashObject(id, ID_LEN, &ret) % SESSION_ROWS); + if (ret != 0) { + WOLFSSL_MSG("Hash session failed"); + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) + XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + #endif + #endif + return ret; + } + + sessRow = &SessionCache[row]; + if (SESSION_ROW_WR_LOCK(sessRow) != 0) { + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) + XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + #endif + #endif + WOLFSSL_MSG("Session row lock failed"); + return BAD_MUTEX_E; + } + + for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { +#ifdef SESSION_CACHE_DYNAMIC_MEM + cacheSession = sessRow->Sessions[i]; +#else + cacheSession = &sessRow->Sessions[i]; +#endif + if (cacheSession && XMEMCMP(id, + cacheSession->sessionID, ID_LEN) == 0 && + cacheSession->side == side) { + WOLFSSL_MSG("Session already exists. Overwriting."); + overwrite = 1; + idx = (word32)i; + break; + } + } + + if (!overwrite) + idx = (word32)sessRow->nextIdx; +#ifdef SESSION_INDEX + if (sessionIndex != NULL) + *sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + +#ifdef SESSION_CACHE_DYNAMIC_MEM + cacheSession = sessRow->Sessions[idx]; + if (cacheSession == NULL) { + cacheSession = (WOLFSSL_SESSION*) XMALLOC(sizeof(WOLFSSL_SESSION), + sessRow->heap, DYNAMIC_TYPE_SESSION); + if (cacheSession == NULL) { + #ifdef HAVE_SESSION_TICKET + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) + XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + #endif + #endif + SESSION_ROW_UNLOCK(sessRow); + return MEMORY_E; + } + XMEMSET(cacheSession, 0, sizeof(WOLFSSL_SESSION)); + sessRow->Sessions[idx] = cacheSession; + } +#else + cacheSession = &sessRow->Sessions[idx]; +#endif + +#ifdef HAVE_EX_DATA + if (overwrite) { + /* Figure out who owns the ex_data */ + if (cacheSession->ownExData) { + /* Prioritize cacheSession copy */ + XMEMCPY(&addSession->ex_data, &cacheSession->ex_data, + sizeof(WOLFSSL_CRYPTO_EX_DATA)); + } + /* else will be copied in wolfSSL_DupSession call */ + } + else if (cacheSession->ownExData) { + crypto_ex_cb_free_data(cacheSession, crypto_ex_cb_ctx_session, + &cacheSession->ex_data); + cacheSession->ownExData = 0; + } +#endif + + if (!overwrite) + EvictSessionFromCache(cacheSession); + + cacheSession->type = WOLFSSL_SESSION_TYPE_CACHE; + cacheSession->cacheRow = row; + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /* Save the peer field to free after unlocking the row */ + if (cacheSession->peer != NULL) + cachePeer = cacheSession->peer; + cacheSession->peer = NULL; +#endif +#ifdef HAVE_SESSION_TICKET + /* If we can reuse the existing buffer in cacheSession then we won't touch + * ticBuff at all making it a very cheap malloc/free. The page on a modern + * OS will most likely not even be allocated to the process. */ + if (ticBuff != NULL && cacheSession->ticketLenAlloc < ticLen) { + /* Save pointer only if separately allocated */ + if (cacheSession->ticket != cacheSession->staticTicket) + cacheTicBuff = cacheSession->ticket; + ticBuffUsed = 1; + cacheSession->ticket = ticBuff; + cacheSession->ticketLenAlloc = (word16) ticLen; + } +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + /* cache entry never used */ + if (cacheSession->ticketNonce.data == NULL) + cacheSession->ticketNonce.data = cacheSession->ticketNonce.dataStatic; + + if (cacheSession->ticketNonce.data != + cacheSession->ticketNonce.dataStatic) { + toFree = cacheSession->ticketNonce.data; + cacheSession->ticketNonce.data = cacheSession->ticketNonce.dataStatic; + cacheSession->ticketNonce.len = 0; + } +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ +#endif +#ifdef SESSION_CERTS + if (overwrite && + addSession->chain.count == 0 && + cacheSession->chain.count > 0) { + /* Copy in the certs from the session */ + addSession->chain.count = cacheSession->chain.count; + XMEMCPY(addSession->chain.certs, cacheSession->chain.certs, + sizeof(x509_buffer) * cacheSession->chain.count); + } +#endif /* SESSION_CERTS */ +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + /* Don't copy the peer cert into cache */ + addPeer = addSession->peer; + addSession->peer = NULL; +#endif + cacheSession->heap = NULL; + /* Copy data into the cache object */ +#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + ret = wolfSSL_DupSessionEx(addSession, cacheSession, 1, preallocNonce, + &preallocNonceLen, &preallocNonceUsed) == WOLFSSL_FAILURE; +#else + ret = wolfSSL_DupSession(addSession, cacheSession, 1) == WOLFSSL_FAILURE; +#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC + && FIPS_VERSION_GE(5,3)*/ +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + addSession->peer = addPeer; +#endif + + if (ret == 0) { + if (!overwrite) { + /* Increment the totalCount and the nextIdx */ + if (sessRow->totalCount < SESSIONS_PER_ROW) + sessRow->totalCount++; + sessRow->nextIdx = (sessRow->nextIdx + 1) % SESSIONS_PER_ROW; + } + if (id != addSession->sessionID) { + /* ssl->session->sessionID may contain the bogus ID or we want the + * ID from the arrays object */ + XMEMCPY(cacheSession->sessionID, id, ID_LEN); + cacheSession->sessionIDSz = ID_LEN; + } +#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) + if (ctx->rem_sess_cb != NULL) + cacheSession->rem_sess_cb = ctx->rem_sess_cb; +#endif +#ifdef HAVE_EX_DATA + /* The session in cache now owns the ex_data */ + addSession->ownExData = 0; + cacheSession->ownExData = 1; +#endif +#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (preallocNonce != NULL && preallocNonceUsed) { + cacheSession->ticketNonce.data = preallocNonce; + cacheSession->ticketNonce.len = preallocNonceLen; + preallocNonce = NULL; + preallocNonceLen = 0; + } +#endif /* HAVE_SESSION_TICKET && WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC + * && FIPS_VERSION_GE(5,3)*/ + } +#ifdef HAVE_SESSION_TICKET + else if (ticBuffUsed) { + /* Error occurred. Need to clean up the ticket buffer. */ + cacheSession->ticket = cacheSession->staticTicket; + cacheSession->ticketLenAlloc = 0; + cacheSession->ticketLen = 0; + } +#endif + SESSION_ROW_UNLOCK(sessRow); + cacheSession = NULL; /* Can't access after unlocked */ + +#ifndef NO_CLIENT_CACHE + if (ret == 0 && clientCacheEntry != NULL) { + ClientSession* clientCache = AddSessionToClientCache(side, row, (int)idx, + addSession->serverID, addSession->idLen, id, useTicket); + if (clientCache != NULL) + *clientCacheEntry = clientCache; + } +#endif + +#ifdef HAVE_SESSION_TICKET + if (ticBuff != NULL && !ticBuffUsed) + XFREE(ticBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); + XFREE(cacheTicBuff, NULL, DYNAMIC_TYPE_SESSION_TICK); +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + XFREE(preallocNonce, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(toFree, addSession->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (cachePeer != NULL) { + wolfSSL_X509_free(cachePeer); + cachePeer = NULL; /* Make sure not use after this point */ + } +#endif + + return ret; +} + +void AddSession(WOLFSSL* ssl) +{ + int error = 0; + const byte* id = NULL; + byte idSz = 0; + WOLFSSL_SESSION* session = ssl->session; + + (void)error; + + WOLFSSL_ENTER("AddSession"); + + if (SslSessionCacheOff(ssl, session)) { + WOLFSSL_MSG("Cache off"); + return; + } + + if (session->haveAltSessionID) { + id = session->altSessionID; + idSz = ID_LEN; + } + else { + id = session->sessionID; + idSz = session->sessionIDSz; + } + + /* Do this only for the client because if the server doesn't have an ID at + * this point, it won't on resumption. */ + if (idSz == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + WC_RNG* rng = NULL; + if (ssl->rng != NULL) + rng = ssl->rng; +#if defined(HAVE_GLOBAL_RNG) && defined(OPENSSL_EXTRA) + else if (initGlobalRNG == 1 || wolfSSL_RAND_Init() == WOLFSSL_SUCCESS) { + rng = &globalRNG; + } +#endif + if (wc_RNG_GenerateBlock(rng, ssl->session->altSessionID, + ID_LEN) != 0) + return; + ssl->session->haveAltSessionID = 1; + id = ssl->session->altSessionID; + idSz = ID_LEN; + } + +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + /* Try to add the session to internal cache or external cache + if a new_sess_cb is set. Its ok if we don't succeed. */ + (void)AddSessionToCache(ssl->ctx, session, id, idSz, +#ifdef SESSION_INDEX + &ssl->sessionIndex, +#else + NULL, +#endif + ssl->options.side, +#ifdef HAVE_SESSION_TICKET + ssl->options.useTicket, +#else + 0, +#endif +#ifdef NO_SESSION_CACHE_REF + NULL +#else + (ssl->options.side == WOLFSSL_CLIENT_END) ? + &ssl->clientSession : NULL +#endif + ); + } + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) { + int cbRet = 0; + wolfSSL_SESSION_up_ref(session); + cbRet = ssl->ctx->new_sess_cb(ssl, session); + if (cbRet == 0) + wolfSSL_FreeSession(ssl->ctx, session); + } +#endif + +#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) + if (error == 0) { + word32 active = 0; + + error = get_locked_session_stats(&active, NULL, NULL); + if (error == WOLFSSL_SUCCESS) { + error = 0; /* back to this function ok */ + + if (PeakSessions < active) { + PeakSessions = active; + } + } + } +#endif /* WOLFSSL_SESSION_STATS && WOLFSSL_PEAK_SESSIONS */ + (void)error; +} + + +#ifdef SESSION_INDEX + +int wolfSSL_GetSessionIndex(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_GetSessionIndex"); + WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex); + return ssl->sessionIndex; +} + + +int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) +{ + int row, col, result = WOLFSSL_FAILURE; + SessionRow* sessRow; + WOLFSSL_SESSION* cacheSession; + + WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); + + session = ClientSessionToSession(session); + + row = idx >> SESSIDX_ROW_SHIFT; + col = idx & SESSIDX_IDX_MASK; + + if (session == NULL || + row < 0 || row >= SESSION_ROWS || col >= SESSIONS_PER_ROW) { + return WOLFSSL_FAILURE; + } + + sessRow = &SessionCache[row]; + if (SESSION_ROW_RD_LOCK(sessRow) != 0) { + return BAD_MUTEX_E; + } + +#ifdef SESSION_CACHE_DYNAMIC_MEM + cacheSession = sessRow->Sessions[col]; +#else + cacheSession = &sessRow->Sessions[col]; +#endif + if (cacheSession) { + XMEMCPY(session, cacheSession, sizeof(WOLFSSL_SESSION)); + result = WOLFSSL_SUCCESS; + } + else { + result = WOLFSSL_FAILURE; + } + + SESSION_ROW_UNLOCK(sessRow); + + WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result); + return result; +} + +#endif /* SESSION_INDEX */ + +#if defined(SESSION_CERTS) + +WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) +{ + WOLFSSL_X509_CHAIN* chain = NULL; + + WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + + session = ClientSessionToSession(session); + + if (session) + chain = &session->chain; + + WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0); + return chain; +} + + +#ifdef OPENSSL_EXTRA +/* gets the peer certificate associated with the session passed in + * returns null on failure, the caller should not free the returned pointer */ +WOLFSSL_X509* wolfSSL_SESSION_get0_peer(WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + + session = ClientSessionToSession(session); + if (session) { + int count; + + count = wolfSSL_get_chain_count(&session->chain); + if (count < 1 || count >= MAX_CHAIN_DEPTH) { + WOLFSSL_MSG("bad count found"); + return NULL; + } + + if (session->peer == NULL) { + session->peer = wolfSSL_get_chain_X509(&session->chain, 0); + } + return session->peer; + } + WOLFSSL_MSG("No session passed in"); + + return NULL; +} +#endif /* OPENSSL_EXTRA */ +#endif /* SESSION_INDEX && SESSION_CERTS */ + + +#ifdef WOLFSSL_SESSION_STATS + +static int get_locked_session_stats(word32* active, word32* total, word32* peak) +{ + int result = WOLFSSL_SUCCESS; + int i; + int count; + int idx; + word32 now = 0; + word32 seen = 0; + word32 ticks = LowResTimer(); + + WOLFSSL_ENTER("get_locked_session_stats"); + +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_RD_LOCK(&SessionCache[0]); +#endif + for (i = 0; i < SESSION_ROWS; i++) { + SessionRow* row = &SessionCache[i]; + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + if (SESSION_ROW_RD_LOCK(row) != 0) { + WOLFSSL_MSG("Session row cache mutex lock failed"); + return BAD_MUTEX_E; + } + #endif + + seen += row->totalCount; + + if (active == NULL) { + SESSION_ROW_UNLOCK(row); + continue; + } + + count = min((word32)row->totalCount, SESSIONS_PER_ROW); + idx = row->nextIdx - 1; + if (idx < 0 || idx >= SESSIONS_PER_ROW) { + idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */ + } + + for (; count > 0; --count) { + /* if not expired then good */ +#ifdef SESSION_CACHE_DYNAMIC_MEM + if (row->Sessions[idx] && + ticks < (row->Sessions[idx]->bornOn + + row->Sessions[idx]->timeout) ) +#else + if (ticks < (row->Sessions[idx].bornOn + + row->Sessions[idx].timeout) ) +#endif + { + now++; + } + + idx = idx > 0 ? idx - 1 : SESSIONS_PER_ROW - 1; + } + + #ifdef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(row); + #endif + } +#ifndef ENABLE_SESSION_CACHE_ROW_LOCK + SESSION_ROW_UNLOCK(&SessionCache[0]); +#endif + + if (active) { + *active = now; + } + if (total) { + *total = seen; + } + +#ifdef WOLFSSL_PEAK_SESSIONS + if (peak) { + *peak = PeakSessions; + } +#else + (void)peak; +#endif + + WOLFSSL_LEAVE("get_locked_session_stats", result); + + return result; +} + + +/* return WOLFSSL_SUCCESS on ok */ +int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, + word32* maxSessions) +{ + int result = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_get_session_stats"); + + if (maxSessions) { + *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS; + + if (active == NULL && total == NULL && peak == NULL) + return result; /* we're done */ + } + + /* user must provide at least one query value */ + if (active == NULL && total == NULL && peak == NULL) { + return BAD_FUNC_ARG; + } + + result = get_locked_session_stats(active, total, peak); + + WOLFSSL_LEAVE("wolfSSL_get_session_stats", result); + + return result; +} + +#endif /* WOLFSSL_SESSION_STATS */ + + + #ifdef PRINT_SESSION_STATS + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_PrintSessionStats(void) + { + word32 totalSessionsSeen = 0; + word32 totalSessionsNow = 0; + word32 peak = 0; + word32 maxSessions = 0; + int i; + int ret; + double E; /* expected freq */ + double chiSquare = 0; + + ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen, + &peak, &maxSessions); + if (ret != WOLFSSL_SUCCESS) + return ret; + printf("Total Sessions Seen = %u\n", totalSessionsSeen); + printf("Total Sessions Now = %u\n", totalSessionsNow); +#ifdef WOLFSSL_PEAK_SESSIONS + printf("Peak Sessions = %u\n", peak); +#endif + printf("Max Sessions = %u\n", maxSessions); + + E = (double)totalSessionsSeen / SESSION_ROWS; + + for (i = 0; i < SESSION_ROWS; i++) { + double diff = SessionCache[i].totalCount - E; + diff *= diff; /* square */ + diff /= E; /* normalize */ + + chiSquare += diff; + } + printf(" chi-square = %5.1f, d.f. = %d\n", chiSquare, + SESSION_ROWS - 1); + #if (SESSION_ROWS == 11) + printf(" .05 p value = 18.3, chi-square should be less\n"); + #elif (SESSION_ROWS == 211) + printf(".05 p value = 244.8, chi-square should be less\n"); + #elif (SESSION_ROWS == 5981) + printf(".05 p value = 6161.0, chi-square should be less\n"); + #elif (SESSION_ROWS == 3) + printf(".05 p value = 6.0, chi-square should be less\n"); + #elif (SESSION_ROWS == 2861) + printf(".05 p value = 2985.5, chi-square should be less\n"); + #endif + printf("\n"); + + return ret; + } + + #endif /* SESSION_STATS */ + +#else /* NO_SESSION_CACHE */ + +WOLFSSL_SESSION* ClientSessionToSession(const WOLFSSL_SESSION* session) +{ + return (WOLFSSL_SESSION*)session; +} + +/* No session cache version */ +WOLFSSL_SESSION* wolfSSL_GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) +{ + (void)ssl; + (void)masterSecret; + (void)restoreSessionCerts; + + return NULL; +} + +#endif /* NO_SESSION_CACHE */ + +#ifdef OPENSSL_EXTRA + + /* 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; + WOLFSSL_MSG("session cache is set at compile time"); + #ifndef NO_SESSION_CACHE + return (long)(SESSIONS_PER_ROW * SESSION_ROWS); + #else + return 0; + #endif + } + + + long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) + { + (void)ctx; + #ifndef NO_SESSION_CACHE + return (long)(SESSIONS_PER_ROW * SESSION_ROWS); + #else + return 0; + #endif + } + +#endif + +#ifndef NO_SESSION_CACHE +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + int error = 0; + const byte* id = NULL; + byte idSz = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + + session = ClientSessionToSession(session); + if (session == NULL) + return WOLFSSL_FAILURE; + + /* Session cache is global */ + (void)ctx; + + if (session->haveAltSessionID) { + id = session->altSessionID; + idSz = ID_LEN; + } + else { + id = session->sessionID; + idSz = session->sessionIDSz; + } + + error = AddSessionToCache(ctx, session, id, idSz, + NULL, session->side, +#ifdef HAVE_SESSION_TICKET + session->ticketLen > 0, +#else + 0, +#endif + NULL); + + return error == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} +#endif + +#if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \ + defined(HAVE_EXT_CACHE)) +/* stunnel 4.28 needs + * + * Callback that is called if a session tries to resume but could not find + * the session to resume it. + */ +void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, + WOLFSSL_SESSION*(*f)(WOLFSSL*, const unsigned char*, int, int*)) +{ + if (ctx == NULL) + return; + +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; +#else + (void)f; +#endif +} + +void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, + int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) +{ + if (ctx == NULL) + return; + +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else + (void)f; +#endif +} + +void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, + WOLFSSL_SESSION*)) +{ + if (ctx == NULL) + return; + +#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) + ctx->rem_sess_cb = f; +#else + (void)f; +#endif +} + + +/* + * + * Note: It is expected that the importing and exporting function have been + * built with the same settings. For example if session tickets was + * enabled with the wolfSSL library exporting a session then it is + * expected to be turned on with the wolfSSL library importing the + * session. + */ +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 + + WOLFSSL_ENTER("wolfSSL_i2d_SSL_SESSION"); + + sess = ClientSessionToSession(sess); + if (sess == NULL) { + return BAD_FUNC_ARG; + } + + /* side | bornOn | timeout | sessionID len | sessionID | masterSecret | + * haveEMS */ + size += OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + + sess->sessionIDSz + SECRET_LEN + OPAQUE8_LEN; + /* altSessionID */ + size += OPAQUE8_LEN + (sess->haveAltSessionID ? ID_LEN : 0); +#ifdef SESSION_CERTS + /* Peer chain */ + size += OPAQUE8_LEN; + for (i = 0; i < sess->chain.count; i++) + size += OPAQUE16_LEN + sess->chain.certs[i].length; +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + /* Protocol version */ + size += OPAQUE16_LEN; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + /* cipher suite */ + size += OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef WOLFSSL_SESSION_ID_CTX + /* session context ID len | session context ID */ + size += OPAQUE8_LEN + sess->sessionCtxSz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + /* peerVerifyRet */ + size += OPAQUE8_LEN; +#endif +#ifdef WOLFSSL_TLS13 + /* namedGroup */ + size += OPAQUE16_LEN; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_32BIT_MILLI_TIME + /* ticketSeen | ticketAdd */ + size += OPAQUE32_LEN + OPAQUE32_LEN; +#else + /* ticketSeen Hi 32 bits | ticketSeen Lo 32 bits | ticketAdd */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE32_LEN; +#endif + /* ticketNonce */ + size += OPAQUE8_LEN + sess->ticketNonce.len; +#endif +#ifdef WOLFSSL_EARLY_DATA + size += OPAQUE32_LEN; +#endif +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len | ticket */ + size += OPAQUE16_LEN + sess->ticketLen; +#endif + + if (p != NULL) { + unsigned char *data; + + if (*p == NULL) + *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); + if (*p == NULL) + return 0; + data = *p; + + data[idx++] = sess->side; + 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++] = (byte)sess->haveEMS; + data[idx++] = sess->haveAltSessionID ? ID_LEN : 0; + if (sess->haveAltSessionID) { + XMEMCPY(data + idx, sess->altSessionID, ID_LEN); + idx += ID_LEN; + } +#ifdef SESSION_CERTS + data[idx++] = (byte)sess->chain.count; + for (i = 0; i < sess->chain.count; i++) { + c16toa((word16)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; + } +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + 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 WOLFSSL_SESSION_ID_CTX + data[idx++] = sess->sessionCtxSz; + XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz); + idx += sess->sessionCtxSz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + data[idx++] = sess->peerVerifyRet; +#endif +#ifdef WOLFSSL_TLS13 + c16toa(sess->namedGroup, data + idx); + idx += OPAQUE16_LEN; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_32BIT_MILLI_TIME + c32toa(sess->ticketSeen, data + idx); + idx += OPAQUE32_LEN; +#else + c32toa((word32)(sess->ticketSeen >> 32), data + idx); + idx += OPAQUE32_LEN; + c32toa((word32)sess->ticketSeen, data + idx); + idx += OPAQUE32_LEN; +#endif + c32toa(sess->ticketAdd, data + idx); + idx += OPAQUE32_LEN; + data[idx++] = sess->ticketNonce.len; + XMEMCPY(data + idx, sess->ticketNonce.data, sess->ticketNonce.len); + idx += sess->ticketNonce.len; +#endif +#ifdef WOLFSSL_EARLY_DATA + c32toa(sess->maxEarlyDataSz, data + idx); + idx += OPAQUE32_LEN; +#endif +#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 + + (void)sess; + (void)p; +#ifdef HAVE_EXT_CACHE + (void)idx; +#endif + + return size; +} + + +/* TODO: no function to free new session. + * + * Note: It is expected that the importing and exporting function have been + * built with the same settings. For example if session tickets was + * enabled with the wolfSSL library exporting a session then it is + * expected to be turned on with the wolfSSL library importing the + * session. + */ +WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, + const unsigned char** p, long i) +{ + WOLFSSL_SESSION* s = NULL; + int ret = 0; +#if defined(HAVE_EXT_CACHE) + int idx = 0; + byte* data; +#ifdef SESSION_CERTS + int j; + word16 length; +#endif +#endif /* HAVE_EXT_CACHE */ + + (void)p; + (void)i; + (void)ret; + (void)sess; + +#ifdef HAVE_EXT_CACHE + if (p == NULL || *p == NULL) + return NULL; + + s = wolfSSL_SESSION_new(); + if (s == NULL) + return NULL; + + idx = 0; + data = (byte*)*p; + + /* side | bornOn | timeout | sessionID len */ + if (i < OPAQUE8_LEN + OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->side = data[idx++]; + ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; + ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; + s->sessionIDSz = data[idx++]; + + /* sessionID | secret | haveEMS | haveAltSessionID */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_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++]; + if (data[idx] != ID_LEN && data[idx] != 0) { + ret = BUFFER_ERROR; + goto end; + } + s->haveAltSessionID = data[idx++] == ID_LEN; + + /* altSessionID */ + if (s->haveAltSessionID) { + if (i - idx < ID_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->altSessionID, data + idx, ID_LEN); idx += ID_LEN; + } + +#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; + } +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + /* Protocol Version */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + /* Cipher suite */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + 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; + + /* ServerID */ + if (i - idx < s->idLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; +#endif +#ifdef WOLFSSL_SESSION_ID_CTX + /* byte for length of session context ID */ + if (i - idx < OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->sessionCtxSz = data[idx++]; + + /* app session context ID */ + if (i - idx < s->sessionCtxSz) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + /* byte for peerVerifyRet */ + if (i - idx < OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->peerVerifyRet = data[idx++]; +#endif +#ifdef WOLFSSL_TLS13 + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->namedGroup); + idx += OPAQUE16_LEN; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13 + if (i - idx < (OPAQUE32_LEN * 2)) { + ret = BUFFER_ERROR; + goto end; + } +#ifdef WOLFSSL_32BIT_MILLI_TIME + ato32(data + idx, &s->ticketSeen); + idx += OPAQUE32_LEN; +#else + { + word32 seenHi, seenLo; + + ato32(data + idx, &seenHi); + idx += OPAQUE32_LEN; + ato32(data + idx, &seenLo); + idx += OPAQUE32_LEN; + s->ticketSeen = ((sword64)seenHi << 32) + seenLo; + } +#endif + ato32(data + idx, &s->ticketAdd); + idx += OPAQUE32_LEN; + if (i - idx < OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->ticketNonce.len = data[idx++]; + + if (i - idx < s->ticketNonce.len) { + ret = BUFFER_ERROR; + goto end; + } +#if defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + ret = SessionTicketNoncePopulate(s, data + idx, s->ticketNonce.len); + if (ret != 0) + goto end; +#else + if (s->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticketNonce.data, data + idx, s->ticketNonce.len); +#endif /* defined(WOLFSSL_TICKET_NONCE_MALLOC) && FIPS_VERSION_GE(5,3) */ + + idx += s->ticketNonce.len; +#endif +#ifdef WOLFSSL_EARLY_DATA + if (i - idx < OPAQUE32_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->maxEarlyDataSz); + idx += OPAQUE32_LEN; +#endif +#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->ticketLenAlloc > 0) { + 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->ticketLenAlloc = (word16)s->ticketLen; + } + + /* ticket */ + if (i - idx < s->ticketLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif + (void)idx; + + if (sess != NULL) { + *sess = s; + } + + s->isSetup = 1; + + *p += idx; + +end: + if (ret != 0 && (sess == NULL || *sess != s)) { + wolfSSL_FreeSession(NULL, s); + s = NULL; + } +#endif /* HAVE_EXT_CACHE */ + return s; +} + +/* Check if there is a session ticket associated with this WOLFSSL_SESSION. + * + * sess - pointer to WOLFSSL_SESSION struct + * + * Returns 1 if has session ticket, otherwise 0 */ +int wolfSSL_SESSION_has_ticket(const WOLFSSL_SESSION* sess) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_has_ticket"); +#ifdef HAVE_SESSION_TICKET + sess = ClientSessionToSession(sess); + if (sess) { + if ((sess->ticketLen > 0) && (sess->ticket != NULL)) { + return WOLFSSL_SUCCESS; + } + } +#else + (void)sess; +#endif + return WOLFSSL_FAILURE; +} + +unsigned long wolfSSL_SESSION_get_ticket_lifetime_hint( + const WOLFSSL_SESSION* sess) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ticket_lifetime_hint"); + sess = ClientSessionToSession(sess); + if (sess) { + return sess->timeout; + } + return 0; +} + +long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) +{ + long timeout = 0; + WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); + sess = ClientSessionToSession(sess); + if (sess) + timeout = sess->timeout; + return timeout; +} + +long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) +{ + word32 tmptime; + + ses = ClientSessionToSession(ses); + if (ses == NULL || t < 0) { + return BAD_FUNC_ARG; + } + + tmptime = t & 0xFFFFFFFF; + ses->timeout = tmptime; + + return WOLFSSL_SUCCESS; +} + +long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) +{ + long bornOn = 0; + WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); + sess = ClientSessionToSession(sess); + if (sess) + bornOn = sess->bornOn; + return bornOn; +} + +long wolfSSL_SESSION_set_time(WOLFSSL_SESSION *ses, long t) +{ + + ses = ClientSessionToSession(ses); + if (ses == NULL || t < 0) { + return 0; + } + ses->bornOn = (word32)t; + return t; +} + +#endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_EX_DATA) + +#if defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE) +static void SESSION_ex_data_cache_update(WOLFSSL_SESSION* session, int idx, + void* data, byte get, void** getRet, int* setRet) +{ + int row; + int i; + int error = 0; + SessionRow* sessRow = NULL; + const byte* id; + byte foundCache = 0; + + if (getRet != NULL) + *getRet = NULL; + if (setRet != NULL) + *setRet = WOLFSSL_FAILURE; + + id = session->sessionID; + if (session->haveAltSessionID) + id = session->altSessionID; + + row = (int)(HashObject(id, ID_LEN, &error) % SESSION_ROWS); + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return; + } + + sessRow = &SessionCache[row]; + if (get) + error = SESSION_ROW_RD_LOCK(sessRow); + else + error = SESSION_ROW_WR_LOCK(sessRow); + if (error != 0) { + WOLFSSL_MSG("Session row lock failed"); + return; + } + + for (i = 0; i < SESSIONS_PER_ROW && i < sessRow->totalCount; i++) { + WOLFSSL_SESSION* cacheSession; +#ifdef SESSION_CACHE_DYNAMIC_MEM + cacheSession = sessRow->Sessions[i]; +#else + cacheSession = &sessRow->Sessions[i]; +#endif + if (cacheSession && + XMEMCMP(id, cacheSession->sessionID, ID_LEN) == 0 + && session->side == cacheSession->side + #if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + && (IsAtLeastTLSv1_3(session->version) == + IsAtLeastTLSv1_3(cacheSession->version)) + #endif + ) { + if (get) { + if (getRet) { + *getRet = wolfSSL_CRYPTO_get_ex_data( + &cacheSession->ex_data, idx); + } + } + else { + if (setRet) { + *setRet = wolfSSL_CRYPTO_set_ex_data( + &cacheSession->ex_data, idx, data); + } + } + foundCache = 1; + break; + } + } + SESSION_ROW_UNLOCK(sessRow); + /* If we don't have a session in cache then clear the ex_data and + * own it */ + if (!foundCache) { + XMEMSET(&session->ex_data, 0, sizeof(WOLFSSL_CRYPTO_EX_DATA)); + session->ownExData = 1; + if (!get) { + *setRet = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, + data); + } + } + +} +#endif + +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) + +#ifndef NO_SESSION_CACHE +int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) +{ +#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) + int rem_called = FALSE; +#endif + + WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + + s = ClientSessionToSession(s); + if (ctx == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_EXT_CACHE + if (!ctx->internalCacheOff) +#endif + { + const byte* id; + WOLFSSL_SESSION *sess = NULL; + word32 row = 0; + int ret; + + id = s->sessionID; + if (s->haveAltSessionID) + id = s->altSessionID; + + ret = TlsSessionCacheGetAndWrLock(id, &sess, &row, ctx->method->side); + if (ret == 0 && sess != NULL) { +#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) + if (sess->rem_sess_cb != NULL) { + rem_called = TRUE; + } +#endif + /* Call this before changing ownExData so that calls to ex_data + * don't try to access the SessionCache again. */ + EvictSessionFromCache(sess); +#ifdef HAVE_EX_DATA + if (sess->ownExData) { + /* Most recent version of ex data is in cache. Copy it + * over so the user can free it. */ + XMEMCPY(&s->ex_data, &sess->ex_data, + sizeof(WOLFSSL_CRYPTO_EX_DATA)); + s->ownExData = 1; + sess->ownExData = 0; + } +#endif +#ifdef SESSION_CACHE_DYNAMIC_MEM + { + /* Find and clear entry. Row is locked so we are good to go. */ + int idx; + for (idx = 0; idx < SESSIONS_PER_ROW; idx++) { + if (sess == SessionCache[row].Sessions[idx]) { + XFREE(sess, sess->heap, DYNAMIC_TYPE_SESSION); + SessionCache[row].Sessions[idx] = NULL; + break; + } + } + } +#endif + TlsSessionCacheUnlockRow(row); + } + } + +#if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA) + if (ctx->rem_sess_cb != NULL && !rem_called) { + ctx->rem_sess_cb(ctx, s); + } +#endif + + /* s cannot be resumed at this point */ + s->timeout = 0; + + return 0; +} + +WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); + + return ssl->session; +} + +#endif /* NO_SESSION_CACHE */ + +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY */ + +#ifdef WOLFSSL_SESSION_EXPORT +/* Used to import a serialized TLS session. + * WARNING: buf contains sensitive information about the state and is best to be + * encrypted before storing if stored. + * + * @param ssl WOLFSSL structure to import the session into + * @param buf serialized session + * @param sz size of buffer 'buf' + * @return the number of bytes read from buffer 'buf' + */ +int wolfSSL_tls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) +{ + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS); +} + + +/* Used to export a serialized TLS session. + * WARNING: buf contains sensitive information about the state and is best to be + * encrypted before storing if stored. + * + * @param ssl WOLFSSL structure to export the session from + * @param buf output of serialized session + * @param sz size in bytes set in 'buf' + * @return the number of bytes written into buffer 'buf' + */ +int wolfSSL_tls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) +{ + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_TLS); +} + +#ifdef WOLFSSL_DTLS +int wolfSSL_dtls_import(WOLFSSL* ssl, const unsigned char* buf, unsigned int sz) +{ + WOLFSSL_ENTER("wolfSSL_session_import"); + + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity checks on buffer and protocol are done in internal function */ + return wolfSSL_session_import_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS); +} + + +/* Sets the function to call for serializing the session. This function is + * called right after the handshake is completed. */ +int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func) +{ + + WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export"); + + /* purposefully allow func to be NULL */ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + ctx->dtls_export = func; + + return WOLFSSL_SUCCESS; +} + +/* Sets the function in WOLFSSL struct to call for serializing the session. This + * function is called right after the handshake is completed. */ +int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func) +{ + + WOLFSSL_ENTER("wolfSSL_dtls_set_export"); + + /* purposefully allow func to be NULL */ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->dtls_export = func; + + return WOLFSSL_SUCCESS; +} + + +/* This function allows for directly serializing a session rather than using + * callbacks. It has less overhead by removing a temporary buffer and gives + * control over when the session gets serialized. When using callbacks the + * session is always serialized immediately after the handshake is finished. + * + * buf is the argument to contain the serialized session + * sz is the size of the buffer passed in + * ssl is the WOLFSSL struct to serialize + * returns the size of serialized session on success, 0 on no action, and + * negative value on error */ +int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) +{ + WOLFSSL_ENTER("wolfSSL_dtls_export"); + + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + + if (buf == NULL) { + *sz = MAX_EXPORT_BUFFER; + return 0; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + WOLFSSL_MSG("Currently only DTLS export is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + return wolfSSL_session_export_internal(ssl, buf, sz, WOLFSSL_EXPORT_DTLS); +} + + +/* This function is similar to wolfSSL_dtls_export but only exports the portion + * of the WOLFSSL structure related to the state of the connection, i.e. peer + * sequence number, epoch, AEAD state etc. + * + * buf is the argument to contain the serialized state, if null then set "sz" to + * buffer size required + * sz is the size of the buffer passed in + * ssl is the WOLFSSL struct to serialize + * returns the size of serialized session on success, 0 on no action, and + * negative value on error */ +int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz) +{ + WOLFSSL_ENTER("wolfSSL_dtls_export_state_only"); + + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + + if (buf == NULL) { + *sz = MAX_EXPORT_STATE_BUFFER; + return 0; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + WOLFSSL_MSG("Currently only DTLS export state is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + return wolfSSL_dtls_export_state_internal(ssl, buf, *sz); +} + + +/* returns 0 on success */ +int wolfSSL_send_session(WOLFSSL* ssl) +{ + int ret; + byte* buf; + word32 bufSz = MAX_EXPORT_BUFFER; + + WOLFSSL_ENTER("wolfSSL_send_session"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return MEMORY_E; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Currently only DTLS export is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + ret = wolfSSL_session_export_internal(ssl, buf, &bufSz, + WOLFSSL_EXPORT_DTLS); + if (ret < 0) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* if no error ret has size of buffer */ + ret = ssl->dtls_export(ssl, buf, ret, NULL); + if (ret != WOLFSSL_SUCCESS) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + +#ifdef OPENSSL_EXTRA + +/* 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; + + ses = ClientSessionToSession(ses); + + 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; +} + +#ifdef WOLFSSL_EARLY_DATA +unsigned int wolfSSL_SESSION_get_max_early_data(const WOLFSSL_SESSION *session) +{ + return session->maxEarlyDataSz; +} +#endif /* WOLFSSL_EARLY_DATA */ + +#endif /* OPENSSL_EXTRA */ + +void SetupSession(WOLFSSL* ssl) +{ + WOLFSSL_SESSION* session = ssl->session; + + WOLFSSL_ENTER("SetupSession"); + + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) { + /* Make sure the session ID is available when the user calls any + * get_session API */ + if (!session->haveAltSessionID) { + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; + } + else { + XMEMCPY(session->sessionID, session->altSessionID, ID_LEN); + session->sessionIDSz = ID_LEN; + } + } + session->side = (byte)ssl->options.side; + if (!IsAtLeastTLSv1_3(ssl->version) && ssl->arrays != NULL) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; +#ifdef WOLFSSL_SESSION_ID_CTX + /* If using compatibility layer then check for and copy over session context + * id. */ + if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { + XMEMCPY(ssl->session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); + session->sessionCtxSz = ssl->sessionCtxSz; + } +#endif + session->timeout = ssl->timeout; +#ifndef NO_ASN_TIME + session->bornOn = LowResTimer(); +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + session->version = ssl->version; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + session->peerVerifyRet = (byte)ssl->peerVerifyRet; +#endif + session->isSetup = 1; +} + +#ifdef WOLFSSL_SESSION_ID_CTX + /* Storing app session context id, this value is inherited by WOLFSSL + * objects created from WOLFSSL_CTX. Any session that is imported with a + * different session context id will be rejected. + * + * ctx structure to set context in + * sid_ctx value of context to set + * sid_ctx_len length of sid_ctx buffer + * + * Returns WOLFSSL_SUCCESS in success case and WOLFSSL_FAILURE when failing + */ + int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx, + const unsigned char* sid_ctx, + unsigned int sid_ctx_len) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_session_id_context"); + + /* No application specific context needed for wolfSSL */ + if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) { + return WOLFSSL_FAILURE; + } + XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len); + ctx->sessionCtxSz = (byte)sid_ctx_len; + + return WOLFSSL_SUCCESS; + } + + + + /* Storing app session context id. Any session that is imported with a + * different session context id will be rejected. + * + * ssl structure to set context in + * id value of context to set + * len length of sid_ctx buffer + * + * Returns WOLFSSL_SUCCESS in success case and WOLFSSL_FAILURE when failing + */ + int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, + unsigned int len) + { + WOLFSSL_ENTER("wolfSSL_set_session_id_context"); + + if (len > ID_LEN || ssl == NULL || id == NULL) { + return WOLFSSL_FAILURE; + } + XMEMCPY(ssl->sessionCtx, id, len); + ssl->sessionCtxSz = (byte)len; + + return WOLFSSL_SUCCESS; + } +#endif + +/* return a new malloc'd session with default settings on success */ +WOLFSSL_SESSION* wolfSSL_NewSession(void* heap) +{ + WOLFSSL_SESSION* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_NewSession"); + + ret = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), heap, + DYNAMIC_TYPE_SESSION); + if (ret != NULL) { + int err; + XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION)); + wolfSSL_RefInit(&ret->ref, &err); + #ifdef WOLFSSL_REFCNT_ERROR_RETURN + if (err != 0) { + WOLFSSL_MSG("Error setting up session reference mutex"); + XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION); + return NULL; + } + #else + (void)err; + #endif +#ifndef NO_SESSION_CACHE + ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */ +#endif + ret->type = WOLFSSL_SESSION_TYPE_HEAP; + ret->heap = heap; +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("SESSION master secret", ret->masterSecret, SECRET_LEN); + wc_MemZero_Add("SESSION id", ret->sessionID, ID_LEN); +#endif + #ifdef HAVE_SESSION_TICKET + ret->ticket = ret->staticTicket; + #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + ret->ticketNonce.data = ret->ticketNonce.dataStatic; + #endif + #endif +#ifdef HAVE_EX_DATA + ret->ownExData = 1; + if (crypto_ex_cb_ctx_session != NULL) { + crypto_ex_cb_setup_new_data(ret, crypto_ex_cb_ctx_session, + &ret->ex_data); + } +#endif + } + return ret; +} + + +WOLFSSL_SESSION* wolfSSL_SESSION_new_ex(void* heap) +{ + return wolfSSL_NewSession(heap); +} + +WOLFSSL_SESSION* wolfSSL_SESSION_new(void) +{ + return wolfSSL_SESSION_new_ex(NULL); +} + +/* add one to session reference count + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */ +int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session) +{ + int ret; + + session = ClientSessionToSession(session); + + if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP) + return WOLFSSL_FAILURE; + + wolfSSL_RefInc(&session->ref, &ret); +#ifdef WOLFSSL_REFCNT_ERROR_RETURN + if (ret != 0) { + WOLFSSL_MSG("Failed to lock session mutex"); + return WOLFSSL_FAILURE; + } +#else + (void)ret; +#endif + + return WOLFSSL_SUCCESS; +} + +/** + * Deep copy the contents from input to output. + * @param input The source of the copy. + * @param output The destination of the copy. + * @param avoidSysCalls If true, then system calls will be avoided or an error + * will be returned if it is not possible to proceed + * without a system call. This is useful for fetching + * sessions from cache. When a cache row is locked, we + * don't want to block other threads with long running + * system calls. + * @param ticketNonceBuf If not null and @avoidSysCalls is true, the copy of the + * ticketNonce will happen in this pre allocated buffer + * @param ticketNonceLen @ticketNonceBuf len as input, used length on output + * @param ticketNonceUsed if @ticketNonceBuf was used to copy the ticket noncet + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on failure + */ +static int wolfSSL_DupSessionEx(const WOLFSSL_SESSION* input, + WOLFSSL_SESSION* output, int avoidSysCalls, byte* ticketNonceBuf, + byte* ticketNonceLen, byte* preallocUsed) +{ +#ifdef HAVE_SESSION_TICKET + int ticLenAlloc = 0; + byte *ticBuff = NULL; +#endif + const size_t copyOffset = OFFSETOF(WOLFSSL_SESSION, heap) + + sizeof(input->heap); + int ret = WOLFSSL_SUCCESS; + + (void)avoidSysCalls; + (void)ticketNonceBuf; + (void)ticketNonceLen; + (void)preallocUsed; + + input = ClientSessionToSession(input); + output = ClientSessionToSession(output); + + if (input == NULL || output == NULL || input == output) { + WOLFSSL_MSG("input or output are null or same"); + return WOLFSSL_FAILURE; + } + +#ifdef HAVE_SESSION_TICKET + if (output->ticket != output->staticTicket) { + ticBuff = output->ticket; + ticLenAlloc = output->ticketLenAlloc; + } +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + /* free the data, it would be better to reuse the buffer but this + * maintain the code simpler. A smart allocator should reuse the free'd + * buffer in the next malloc without much performance penalties. */ + if (output->ticketNonce.data != output->ticketNonce.dataStatic) { + + /* Callers that avoid syscall should never calls this with + * output->tickeNonce.data being a dynamic buffer.*/ + if (avoidSysCalls) { + WOLFSSL_MSG("can't avoid syscalls with dynamic TicketNonce buffer"); + return WOLFSSL_FAILURE; + } + + XFREE(output->ticketNonce.data, + output->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticketNonce.data = output->ticketNonce.dataStatic; + output->ticketNonce.len = 0; + } +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ +#endif /* HAVE_SESSION_TICKET */ + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (output->peer != NULL) { + if (avoidSysCalls) { + WOLFSSL_MSG("Can't free cert when avoiding syscalls"); + return WOLFSSL_FAILURE; + } + wolfSSL_X509_free(output->peer); + output->peer = NULL; + } +#endif + + XMEMCPY((byte*)output + copyOffset, (byte*)input + copyOffset, + sizeof(WOLFSSL_SESSION) - copyOffset); + +#if defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + /* fix pointer to static after the copy */ + output->ticketNonce.data = output->ticketNonce.dataStatic; +#endif + /* Set sane values for copy */ +#ifndef NO_SESSION_CACHE + if (output->type != WOLFSSL_SESSION_TYPE_CACHE) + output->cacheRow = INVALID_SESSION_ROW; +#endif +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (input->peer != NULL && input->peer->dynamicMemory) { + if (wolfSSL_X509_up_ref(input->peer) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Can't increase peer cert ref count"); + output->peer = NULL; + } + } + else if (!avoidSysCalls) + output->peer = wolfSSL_X509_dup(input->peer); + else + /* output->peer is not that important to copy */ + output->peer = NULL; +#endif +#ifdef HAVE_SESSION_TICKET + if (input->ticketLen > SESSION_TICKET_LEN) { + /* Need dynamic buffer */ + if (ticBuff == NULL || ticLenAlloc < input->ticketLen) { + /* allocate new one */ + byte* tmp; + if (avoidSysCalls) { + WOLFSSL_MSG("Failed to allocate memory for ticket when avoiding" + " syscalls"); + output->ticket = ticBuff; + output->ticketLenAlloc = (word16) ticLenAlloc; + output->ticketLen = 0; + ret = WOLFSSL_FAILURE; + } + else { +#ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC(input->ticketLen, + output->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK); + ticBuff = NULL; +#else + tmp = (byte*)XREALLOC(ticBuff, input->ticketLen, + output->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif /* WOLFSSL_NO_REALLOC */ + if (tmp == NULL) { + WOLFSSL_MSG("Failed to allocate memory for ticket"); +#ifndef WOLFSSL_NO_REALLOC + XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK); + ticBuff = NULL; +#endif /* WOLFSSL_NO_REALLOC */ + output->ticket = NULL; + output->ticketLen = 0; + output->ticketLenAlloc = 0; + ret = WOLFSSL_FAILURE; + } + else { + ticBuff = tmp; + ticLenAlloc = input->ticketLen; + } + } + } + if (ticBuff != NULL && ret == WOLFSSL_SUCCESS) { + XMEMCPY(ticBuff, input->ticket, input->ticketLen); + output->ticket = ticBuff; + output->ticketLenAlloc = (word16) ticLenAlloc; + } + } + else { + /* Default ticket to non dynamic */ + if (avoidSysCalls) { + /* Try to use ticBuf if available. Caller can later move it to + * the static buffer. */ + if (ticBuff != NULL) { + if (ticLenAlloc >= input->ticketLen) { + output->ticket = ticBuff; + output->ticketLenAlloc = ticLenAlloc; + } + else { + WOLFSSL_MSG("ticket dynamic buffer too small but we are " + "avoiding system calls"); + ret = WOLFSSL_FAILURE; + output->ticket = ticBuff; + output->ticketLenAlloc = (word16) ticLenAlloc; + output->ticketLen = 0; + } + } + else { + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + } + } + else { + if (ticBuff != NULL) + XFREE(ticBuff, output->heap, DYNAMIC_TYPE_SESSION_TICK); + output->ticket = output->staticTicket; + output->ticketLenAlloc = 0; + } + if (input->ticketLenAlloc > 0 && ret == WOLFSSL_SUCCESS) { + /* Shouldn't happen as session should have placed this in + * the static buffer */ + XMEMCPY(output->ticket, input->ticket, + input->ticketLen); + } + } + ticBuff = NULL; + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (preallocUsed != NULL) + *preallocUsed = 0; + + if (input->ticketNonce.len > MAX_TICKET_NONCE_STATIC_SZ && + ret == WOLFSSL_SUCCESS) { + /* TicketNonce does not fit in the static buffer */ + if (!avoidSysCalls) { + output->ticketNonce.data = (byte*)XMALLOC(input->ticketNonce.len, + output->heap, DYNAMIC_TYPE_SESSION_TICK); + + if (output->ticketNonce.data == NULL) { + WOLFSSL_MSG("Failed to allocate space for ticket nonce"); + output->ticketNonce.data = output->ticketNonce.dataStatic; + output->ticketNonce.len = 0; + ret = WOLFSSL_FAILURE; + } + else { + output->ticketNonce.len = input->ticketNonce.len; + XMEMCPY(output->ticketNonce.data, input->ticketNonce.data, + input->ticketNonce.len); + ret = WOLFSSL_SUCCESS; + } + } + /* we can't do syscalls. Use prealloc buffers if provided from the + * caller. */ + else if (ticketNonceBuf != NULL && + *ticketNonceLen >= input->ticketNonce.len) { + XMEMCPY(ticketNonceBuf, input->ticketNonce.data, + input->ticketNonce.len); + *ticketNonceLen = input->ticketNonce.len; + if (preallocUsed != NULL) + *preallocUsed = 1; + ret = WOLFSSL_SUCCESS; + } + else { + WOLFSSL_MSG("TicketNonce bigger than static buffer, and we can't " + "do syscalls"); + ret = WOLFSSL_FAILURE; + } + } +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ + +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_EX_DATA + if (input->type != WOLFSSL_SESSION_TYPE_CACHE && + output->type != WOLFSSL_SESSION_TYPE_CACHE) { + /* Not called with cache as that passes ownership of ex_data */ + ret = crypto_ex_cb_dup_data(&input->ex_data, &output->ex_data, + crypto_ex_cb_ctx_session); + } +#endif + + return ret; +} + +/** + * Deep copy the contents from input to output. + * @param input The source of the copy. + * @param output The destination of the copy. + * @param avoidSysCalls If true, then system calls will be avoided or an error + * will be returned if it is not possible to proceed + * without a system call. This is useful for fetching + * sessions from cache. When a cache row is locked, we + * don't want to block other threads with long running + * system calls. + * @return WOLFSSL_SUCCESS on success + * WOLFSSL_FAILURE on failure + */ +int wolfSSL_DupSession(const WOLFSSL_SESSION* input, WOLFSSL_SESSION* output, + int avoidSysCalls) +{ + return wolfSSL_DupSessionEx(input, output, avoidSysCalls, NULL, NULL, NULL); +} + +WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session) +{ + WOLFSSL_SESSION* copy; + + WOLFSSL_ENTER("wolfSSL_SESSION_dup"); + + session = ClientSessionToSession(session); + if (session == NULL) + return NULL; + +#ifdef HAVE_SESSION_TICKET + if (session->ticketLenAlloc > 0 && !session->ticket) { + WOLFSSL_MSG("Session dynamic flag is set but ticket pointer is null"); + return NULL; + } +#endif + + copy = wolfSSL_NewSession(session->heap); + if (copy != NULL && + wolfSSL_DupSession(session, copy, 0) != WOLFSSL_SUCCESS) { + wolfSSL_FreeSession(NULL, copy); + copy = NULL; + } + return copy; +} + +void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + session = ClientSessionToSession(session); + if (session == NULL) + return; + + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_FreeSession"); + + if (session->ref.count > 0) { + int ret; + int isZero; + wolfSSL_RefDec(&session->ref, &isZero, &ret); + (void)ret; + if (!isZero) { + return; + } + wolfSSL_RefFree(&session->ref); + } + + WOLFSSL_MSG("wolfSSL_FreeSession full free"); + +#ifdef HAVE_EX_DATA + if (session->ownExData) { + crypto_ex_cb_free_data(session, crypto_ex_cb_ctx_session, + &session->ex_data); + } +#endif + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); +#endif + +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + if (session->peer) { + wolfSSL_X509_free(session->peer); + session->peer = NULL; + } +#endif + +#ifdef HAVE_SESSION_TICKET + if (session->ticketLenAlloc > 0) { + XFREE(session->ticket, session->heap, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = session->staticTicket; + session->ticketLen = 0; + session->ticketLenAlloc = 0; + } +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TICKET_NONCE_MALLOC) && \ + (!defined(HAVE_FIPS) || (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3))) + if (session->ticketNonce.data != session->ticketNonce.dataStatic) { + XFREE(session->ticketNonce.data, session->heap, + DYNAMIC_TYPE_SESSION_TICK); + session->ticketNonce.data = session->ticketNonce.dataStatic; + session->ticketNonce.len = 0; + } +#endif /* WOLFSSL_TLS13 && WOLFSSL_TICKET_NONCE_MALLOC && FIPS_VERSION_GE(5,3)*/ +#endif + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); +#endif + + /* Make sure masterSecret is zeroed. */ + ForceZero(session->masterSecret, SECRET_LEN); + /* Session ID is sensitive information too. */ + ForceZero(session->sessionID, ID_LEN); + + if (session->type == WOLFSSL_SESSION_TYPE_HEAP) { + XFREE(session, session->heap, DYNAMIC_TYPE_SESSION); + } +} + +/* DO NOT use this API internally. Use wolfSSL_FreeSession directly instead + * and pass in the ctx parameter if possible (like from ssl->ctx). */ +void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) +{ + session = ClientSessionToSession(session); + wolfSSL_FreeSession(NULL, session); +} + +#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) + +/** +* set cipher to WOLFSSL_SESSION from WOLFSSL_CIPHER +* @param session a pointer to WOLFSSL_SESSION structure +* @param cipher a function pointer to WOLFSSL_CIPHER +* @return WOLFSSL_SUCCESS on success, otherwise WOLFSSL_FAILURE +*/ +int wolfSSL_SESSION_set_cipher(WOLFSSL_SESSION* session, + const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_cipher"); + + session = ClientSessionToSession(session); + /* sanity check */ + if (session == NULL || cipher == NULL) { + WOLFSSL_MSG("bad argument"); + return WOLFSSL_FAILURE; + } + session->cipherSuite0 = cipher->cipherSuite0; + session->cipherSuite = cipher->cipherSuite; + + WOLFSSL_LEAVE("wolfSSL_SESSION_set_cipher", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} +#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ + +const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* session) +{ + session = ClientSessionToSession(session); + if (session == NULL) { + return NULL; + } + +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) + return GetCipherNameIana(session->cipherSuite0, session->cipherSuite); + #else + return GetCipherNameInternal(session->cipherSuite0, + session->cipherSuite); + #endif +#else + return NULL; +#endif +} + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) +const unsigned char *wolfSSL_SESSION_get0_id_context( + const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length) +{ + return wolfSSL_SESSION_get_id((WOLFSSL_SESSION *)sess, sid_ctx_length); +} +int wolfSSL_SESSION_set1_id(WOLFSSL_SESSION *s, + const unsigned char *sid, unsigned int sid_len) +{ + if (s == NULL) { + return WOLFSSL_FAILURE; + } + if (sid_len > ID_LEN) { + return WOLFSSL_FAILURE; + } + s->sessionIDSz = sid_len; + if (sid != s->sessionID) { + XMEMCPY(s->sessionID, sid, sid_len); + } + return WOLFSSL_SUCCESS; +} + +int wolfSSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, + const unsigned char *sid_ctx, unsigned int sid_ctx_len) +{ + if (s == NULL) { + return WOLFSSL_FAILURE; + } + if (sid_ctx_len > ID_LEN) { + return WOLFSSL_FAILURE; + } + s->sessionCtxSz = sid_ctx_len; + if (sid_ctx != s->sessionCtx) { + XMEMCPY(s->sessionCtx, sid_ctx, sid_ctx_len); + } + + return WOLFSSL_SUCCESS; +} + +#endif + +#ifdef OPENSSL_EXTRA + +/* Return the total number of sessions */ +long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) +{ + word32 total = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_sess_number"); + (void)ctx; + +#if defined(WOLFSSL_SESSION_STATS) && !defined(NO_SESSION_CACHE) + if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting session stats"); + } +#else + WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats"); +#endif + + return (long)total; +} + +#endif + +#ifdef SESSION_CERTS + +/* get session ID */ +WOLFSSL_ABI +const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("wolfSSL_get_sessionID"); + session = ClientSessionToSession(session); + if (session) + return session->sessionID; + + return NULL; +} + +#endif + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ + defined(HAVE_EX_DATA) + +int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) +{ + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); +#ifdef HAVE_EX_DATA + session = ClientSessionToSession(session); + if (session != NULL) { +#ifndef NO_SESSION_CACHE + if (!session->ownExData) { + /* Need to update in cache */ + SESSION_ex_data_cache_update(session, idx, data, 0, NULL, &ret); + } + else +#endif + { + ret = wolfSSL_CRYPTO_set_ex_data(&session->ex_data, idx, data); + } + } +#else + (void)session; + (void)idx; + (void)data; +#endif + return ret; +} + +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS +int wolfSSL_SESSION_set_ex_data_with_cleanup( + WOLFSSL_SESSION* session, + int idx, + void* data, + wolfSSL_ex_data_cleanup_routine_t cleanup_routine) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data_with_cleanup"); + session = ClientSessionToSession(session); + if(session != NULL) { + return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&session->ex_data, idx, + data, cleanup_routine); + } + return WOLFSSL_FAILURE; +} +#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */ + +void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) +{ + void* ret = NULL; + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); +#ifdef HAVE_EX_DATA + session = ClientSessionToSession(session); + if (session != NULL) { +#ifndef NO_SESSION_CACHE + if (!session->ownExData) { + /* Need to retrieve the data from the session cache */ + SESSION_ex_data_cache_update((WOLFSSL_SESSION*)session, idx, NULL, + 1, &ret, NULL); + } + else +#endif + { + ret = wolfSSL_CRYPTO_get_ex_data(&session->ex_data, idx); + } + } +#else + (void)session; + (void)idx; +#endif + return ret; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL || HAVE_EX_DATA */ + +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && \ + (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_LIGHTY) || defined(WOLFSSL_HAPROXY) || \ + defined(WOLFSSL_OPENSSH) || defined(HAVE_SBLIM_SFCB))) +#ifdef HAVE_EX_DATA +int wolfSSL_SESSION_get_ex_new_index(long ctx_l,void* ctx_ptr, + WOLFSSL_CRYPTO_EX_new* new_func, WOLFSSL_CRYPTO_EX_dup* dup_func, + WOLFSSL_CRYPTO_EX_free* free_func) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index"); + return wolfssl_get_ex_new_index(WOLF_CRYPTO_EX_INDEX_SSL_SESSION, ctx_l, + ctx_ptr, new_func, dup_func, free_func); +} +#endif +#endif + + +#if defined(OPENSSL_ALL) || \ + defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +const byte* wolfSSL_SESSION_get_id(const WOLFSSL_SESSION* sess, + unsigned int* idLen) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + sess = ClientSessionToSession(sess); + if (sess == NULL || idLen == NULL) { + WOLFSSL_MSG("Bad func args. Please provide idLen"); + return NULL; + } +#ifdef HAVE_SESSION_TICKET + if (sess->haveAltSessionID) { + *idLen = ID_LEN; + return sess->altSessionID; + } +#endif + *idLen = sess->sessionIDSz; + return sess->sessionID; +} + +#if (defined(HAVE_SESSION_TICKET) || defined(SESSION_CERTS)) && \ + !defined(NO_FILESYSTEM) + +#ifndef NO_BIO + +#if defined(SESSION_CERTS) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) +static const char* wolfSSL_internal_get_version(const ProtocolVersion* version); + +/* returns a pointer to the protocol used by the session */ +static const char* wolfSSL_SESSION_get_protocol(const WOLFSSL_SESSION* in) +{ + in = ClientSessionToSession(in); + return wolfSSL_internal_get_version((ProtocolVersion*)&in->version); +} +#endif + +/* returns true (non 0) if the session has EMS (extended master secret) */ +static int wolfSSL_SESSION_haveEMS(const WOLFSSL_SESSION* in) +{ + in = ClientSessionToSession(in); + if (in == NULL) + return 0; + return in->haveEMS; +} + +#if defined(HAVE_SESSION_TICKET) +/* prints out the ticket to bio passed in + * return WOLFSSL_SUCCESS on success + */ +static int wolfSSL_SESSION_print_ticket(WOLFSSL_BIO* bio, + const WOLFSSL_SESSION* in, const char* tab) +{ + unsigned short i, j, z, sz; + short tag = 0; + byte* pt; + + + in = ClientSessionToSession(in); + if (in == NULL || bio == NULL) { + return BAD_FUNC_ARG; + } + + sz = in->ticketLen; + pt = in->ticket; + + if (wolfSSL_BIO_printf(bio, "%s\n", (sz == 0)? " NONE": "") <= 0) + return WOLFSSL_FAILURE; + + for (i = 0; i < sz;) { + char asc[16]; + XMEMSET(asc, 0, sizeof(asc)); + + if (sz - i < 16) { + if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag + (sz - i)) <= 0) + return WOLFSSL_FAILURE; + } + else { + if (wolfSSL_BIO_printf(bio, "%s%04X -", tab, tag) <= 0) + return WOLFSSL_FAILURE; + } + for (j = 0; i < sz && j < 8; j++,i++) { + asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; + if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + } + + if (i < sz) { + asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; + if (wolfSSL_BIO_printf(bio, "-%02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + j++; + i++; + } + + for (; i < sz && j < 16; j++,i++) { + asc[j] = ((pt[i])&0x6f)>='A'?((pt[i])&0x6f):'.'; + if (wolfSSL_BIO_printf(bio, " %02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + } + + /* pad out spacing */ + for (z = j; z < 17; z++) { + if (wolfSSL_BIO_printf(bio, " ") <= 0) + return WOLFSSL_FAILURE; + } + + for (z = 0; z < j; z++) { + if (wolfSSL_BIO_printf(bio, "%c", asc[z]) <= 0) + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_printf(bio, "\n") <= 0) + return WOLFSSL_FAILURE; + + tag += 16; + } + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + + +/* prints out the session information in human readable form + * return WOLFSSL_SUCCESS on success + */ +int wolfSSL_SESSION_print(WOLFSSL_BIO *bp, const WOLFSSL_SESSION *session) +{ + const unsigned char* pt; + unsigned char buf[SECRET_LEN]; + unsigned int sz = 0, i; + int ret; + + session = ClientSessionToSession(session); + if (session == NULL) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_printf(bp, "%s\n", "SSL-Session:") <= 0) + return WOLFSSL_FAILURE; + +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + if (wolfSSL_BIO_printf(bp, " Protocol : %s\n", + wolfSSL_SESSION_get_protocol(session)) <= 0) + return WOLFSSL_FAILURE; +#endif + + if (wolfSSL_BIO_printf(bp, " Cipher : %s\n", + wolfSSL_SESSION_CIPHER_get_name(session)) <= 0) + return WOLFSSL_FAILURE; + + pt = wolfSSL_SESSION_get_id(session, &sz); + if (wolfSSL_BIO_printf(bp, " Session-ID: ") <= 0) + return WOLFSSL_FAILURE; + + for (i = 0; i < sz; i++) { + if (wolfSSL_BIO_printf(bp, "%02X", pt[i]) <= 0) + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_printf(bp, "\n") <= 0) + return WOLFSSL_FAILURE; + + if (wolfSSL_BIO_printf(bp, " Session-ID-ctx: \n") <= 0) + return WOLFSSL_FAILURE; + + ret = wolfSSL_SESSION_get_master_key(session, buf, sizeof(buf)); + if (wolfSSL_BIO_printf(bp, " Master-Key: ") <= 0) + return WOLFSSL_FAILURE; + + if (ret > 0) { + sz = (unsigned int)ret; + for (i = 0; i < sz; i++) { + if (wolfSSL_BIO_printf(bp, "%02X", buf[i]) <= 0) + return WOLFSSL_FAILURE; + } + } + if (wolfSSL_BIO_printf(bp, "\n") <= 0) + return WOLFSSL_FAILURE; + + /* @TODO PSK identity hint and SRP */ + + if (wolfSSL_BIO_printf(bp, " TLS session ticket:") <= 0) + return WOLFSSL_FAILURE; + +#ifdef HAVE_SESSION_TICKET + if (wolfSSL_SESSION_print_ticket(bp, session, " ") != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; +#endif + +#if !defined(NO_SESSION_CACHE) && (defined(OPENSSL_EXTRA) || \ + defined(HAVE_EXT_CACHE)) + if (wolfSSL_BIO_printf(bp, " Start Time: %ld\n", + wolfSSL_SESSION_get_time(session)) <= 0) + return WOLFSSL_FAILURE; + + if (wolfSSL_BIO_printf(bp, " Timeout : %ld (sec)\n", + wolfSSL_SESSION_get_timeout(session)) <= 0) + return WOLFSSL_FAILURE; +#endif /* !NO_SESSION_CACHE && OPENSSL_EXTRA || HAVE_EXT_CACHE */ + + /* @TODO verify return code print */ + + if (wolfSSL_BIO_printf(bp, " Extended master secret: %s\n", + (wolfSSL_SESSION_haveEMS(session) == 0)? "no" : "yes") <= 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; +} + +#endif /* !NO_BIO */ +#endif /* (HAVE_SESSION_TICKET || SESSION_CERTS) && !NO_FILESYSTEM */ + +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || + * WOLFSSL_HAPROXY */ + +#ifdef OPENSSL_EXTRA +/** + * Determine whether a WOLFSSL_SESSION object can be used for resumption + * @param s a pointer to WOLFSSL_SESSION structure + * @return return 1 if session is resumable, otherwise 0. + */ +int wolfSSL_SESSION_is_resumable(const WOLFSSL_SESSION *s) +{ + s = ClientSessionToSession(s); + if (s == NULL) + return 0; + +#ifdef HAVE_SESSION_TICKET + if (s->ticketLen > 0) + return 1; +#endif + + if (s->sessionIDSz > 0) + return 1; + + return 0; +} +#endif /* OPENSSL_EXTRA */ + +#endif /* !WOLFSSL_SSL_SESS_INCLUDED */ + diff --git a/src/src/tls.c b/src/src/tls.c index a28568c..6529216 100644 --- a/src/src/tls.c +++ b/src/src/tls.c @@ -48,7 +48,7 @@ #ifdef HAVE_CURVE448 #include #endif -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER #include #ifdef WOLFSSL_WC_KYBER #include @@ -212,7 +212,8 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) ret = ssl->ctx->TlsFinishedCb(ssl, side, handshake_hash, hashSz, (byte*)hashes, ctx); } - if (!ssl->ctx->TlsFinishedCb || ret == PROTOCOLCB_UNAVAILABLE) + if (!ssl->ctx->TlsFinishedCb || + ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) #endif { PRIVATE_KEY_UNLOCK(); @@ -300,6 +301,98 @@ ProtocolVersion MakeTLSv1_3(void) } #endif +#if defined(HAVE_SUPPORTED_CURVES) +/* Sets the key exchange groups in rank order on a context. + * + * ctx SSL/TLS context object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) +{ + int ret, i; + + WOLFSSL_ENTER("wolfSSL_CTX_set_groups"); + if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsTLS_ex(ctx->method->version)) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_TLS13 + ctx->numGroups = 0; + #endif + #if !defined(NO_TLS) + TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); + #endif /* !NO_TLS */ + for (i = 0; i < count; i++) { + /* Call to wolfSSL_CTX_UseSupportedCurve also checks if input groups + * are valid */ + if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, (word16)groups[i])) + != WOLFSSL_SUCCESS) { + #if !defined(NO_TLS) + TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); + #endif /* !NO_TLS */ + return ret; + } + #ifdef WOLFSSL_TLS13 + ctx->group[i] = (word16)groups[i]; + #endif + } + #ifdef WOLFSSL_TLS13 + ctx->numGroups = (byte)count; + #endif + + return WOLFSSL_SUCCESS; +} + +/* Sets the key exchange groups in rank order. + * + * ssl SSL/TLS object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) +{ + int ret, i; + + WOLFSSL_ENTER("wolfSSL_set_groups"); + if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsTLS_ex(ssl->version)) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_TLS13 + ssl->numGroups = 0; + #endif + #if !defined(NO_TLS) + TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); + #endif /* !NO_TLS */ + for (i = 0; i < count; i++) { + /* Call to wolfSSL_UseSupportedCurve also checks if input groups + * are valid */ + if ((ret = wolfSSL_UseSupportedCurve(ssl, (word16)groups[i])) + != WOLFSSL_SUCCESS) { + #if !defined(NO_TLS) + TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); + #endif /* !NO_TLS */ + return ret; + } + #ifdef WOLFSSL_TLS13 + ssl->group[i] = (word16)groups[i]; + #endif + } + #ifdef WOLFSSL_TLS13 + ssl->numGroups = (byte)count; + #endif + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_SUPPORTED_CURVES */ + #ifndef WOLFSSL_NO_TLS12 #ifdef HAVE_EXTENDED_MASTER @@ -396,9 +489,10 @@ int DeriveTlsKeys(WOLFSSL* ssl) void* ctx = wolfSSL_GetGenSessionKeyCtx(ssl); ret = ssl->ctx->GenSessionKeyCb(ssl, ctx); } - if (!ssl->ctx->GenSessionKeyCb || ret == PROTOCOLCB_UNAVAILABLE) + if (!ssl->ctx->GenSessionKeyCb || + ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) #endif - ret = _DeriveTlsKeys(key_dig, key_dig_len, + ret = _DeriveTlsKeys(key_dig, (word32)key_dig_len, ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->serverRandom, ssl->arrays->clientRandom, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, @@ -576,7 +670,8 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) void* ctx = wolfSSL_GetGenMasterSecretCtx(ssl); ret = ssl->ctx->GenMasterCb(ssl, ctx); } - if (!ssl->ctx->GenMasterCb || ret == PROTOCOLCB_UNAVAILABLE) + if (!ssl->ctx->GenMasterCb || + ret == WC_NO_ERR_TRACE(PROTOCOLCB_UNAVAILABLE)) #endif { ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, @@ -586,47 +681,13 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) ssl->specs.mac_algorithm, ssl->heap, ssl->devId); } } +#ifdef HAVE_SECRET_CALLBACK + if (ret == 0 && ssl->tlsSecretCb != NULL) { + ret = ssl->tlsSecretCb(ssl, ssl->arrays->masterSecret, + SECRET_LEN, ssl->tlsSecretCtx); + } +#endif /* HAVE_SECRET_CALLBACK */ if (ret == 0) { - #ifdef SHOW_SECRETS - /* Wireshark Pre-Master-Secret Format: - * CLIENT_RANDOM - */ - const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM"; - int i, pmsPos = 0; - char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1]; - - XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ", - CLIENT_RANDOM_LABEL); - pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1; - for (i = 0; i < RAN_LEN; i++) { - XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", - ssl->arrays->clientRandom[i]); - pmsPos += 2; - } - XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " "); - pmsPos += 1; - for (i = 0; i < SECRET_LEN; i++) { - XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", - ssl->arrays->masterSecret[i]); - pmsPos += 2; - } - XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n"); - pmsPos += 1; - - /* print master secret */ - puts(pmsBuf); - - #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) - { - FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a"); - if (f != XBADFILE) { - XFWRITE(pmsBuf, 1, pmsPos, f); - XFCLOSE(f); - } - } - #endif - #endif /* SHOW_SECRETS */ - ret = DeriveTlsKeys(ssl); } @@ -724,7 +785,7 @@ int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, */ static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (hmac->macType) { #ifndef NO_SHA @@ -758,6 +819,7 @@ static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz) #endif /* WOLFSSL_SM3 */ default: + ret = BAD_FUNC_ARG; break; } @@ -772,7 +834,7 @@ static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz) */ static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (hmac->macType) { #ifndef NO_SHA @@ -806,6 +868,7 @@ static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash) #endif /* WOLFSSL_SM3 */ default: + ret = BAD_FUNC_ARG; break; } @@ -820,7 +883,7 @@ static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash) */ static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); wc_HashAlg hash; enum wc_HashType hashType = (enum wc_HashType)hmac->macType; int digestSz = wc_HashGetDigestSize(hashType); @@ -829,12 +892,16 @@ static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) if ((digestSz >= 0) && (blockSz >= 0)) { ret = wc_HashInit(&hash, hashType); } + else { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad, - blockSz); + (word32)blockSz); if (ret == 0) ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash, - digestSz); + (word32)digestSz); if (ret == 0) ret = wc_HashFinal(&hash, hashType, mac); wc_HashFree(&hash, hashType); @@ -942,7 +1009,7 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes); c32toa(realLen << 3, lenBytes + sizeof(word32)); - ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz); + ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, (word32)blockSz); if (ret != 0) return ret; @@ -961,7 +1028,7 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, safeBlocks = 0; XMEMSET(digest, 0, macLen); - k = safeBlocks * blockSz; + k = (unsigned int)(safeBlocks * blockSz); for (i = safeBlocks; i < blocks; i++) { unsigned char hashBlock[WC_MAX_BLOCK_SIZE]; unsigned char isEocBlock = ctMaskEq(i, eocBlock); @@ -989,7 +1056,7 @@ static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, hashBlock[j] = b; } - ret = Hmac_HashUpdate(hmac, hashBlock, blockSz); + ret = Hmac_HashUpdate(hmac, hashBlock, (word32)blockSz); if (ret != 0) return ret; ret = Hmac_HashFinalRaw(hmac, hashBlock); @@ -1099,9 +1166,9 @@ static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in, maxSz &= ~(0 - (maxSz >> 31)); /* Calculate #blocks processed in HMAC for max and real data. */ - blocks = maxSz >> blockBits; + blocks = (int)(maxSz >> blockBits); blocks += ((maxSz + padSz) % blockSz) < padSz; - msgBlocks = realSz >> blockBits; + msgBlocks = (int)(realSz >> blockBits); /* #Extra blocks to process. */ blocks -= msgBlocks + ((((realSz + padSz) % blockSz) < padSz) ? 1 : 0); /* Calculate whole blocks. */ @@ -1110,8 +1177,8 @@ static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in, ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ); if (ret == 0) { /* Fill the rest of the block with any available data. */ - word32 currSz = ctMaskLT(msgSz, blockSz) & msgSz; - currSz |= ctMaskGTE(msgSz, blockSz) & blockSz; + word32 currSz = ctMaskLT((int)msgSz, blockSz) & msgSz; + currSz |= ctMaskGTE((int)msgSz, blockSz) & blockSz; currSz -= WOLFSSL_TLS_HMAC_INNER_SZ; currSz &= ~(0 - (currSz >> 31)); ret = wc_HmacUpdate(hmac, in, currSz); @@ -2349,12 +2416,13 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, #ifndef NO_WOLFSSL_SERVER /** Tells the SNI requested by the client. */ -word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) +word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data, + byte ignoreStatus) { TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); - if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { + if (sni && (ignoreStatus || sni->status != WOLFSSL_SNI_NO_MATCH)) { switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: if (data) { @@ -2929,6 +2997,9 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, const byte* input, word16 length, WOLFSSL_ERROR_VERBOSE(UNKNOWN_MAX_FRAG_LEN_E); return UNKNOWN_MAX_FRAG_LEN_E; } + if (ssl->session != NULL) { + ssl->session->mfl = *input; + } #ifndef NO_WOLFSSL_SERVER if (isRequest) { @@ -3329,7 +3400,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, const byte* input, word16 length, XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); /* Let's not error out the connection if we can't verify our * cert */ - if (ret == ASN_SELF_SIGNED_E || ret == ASN_NO_SIGNER_E) + if (ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) || + ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)) ret = 0; return ret; } @@ -3507,10 +3579,20 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +static void TLSX_CSR2_FreePendingSigners(Signer *s, void* heap) +{ + Signer* next; + while(s) { + next = s->next; + FreeSigner(s, heap); + s = next; + } +} static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap) { CertificateStatusRequestItemV2* next; + TLSX_CSR2_FreePendingSigners(csr2->pendingSigners, heap); for (; csr2; csr2 = next) { next = csr2->next; @@ -3781,6 +3863,83 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, const byte* input, word16 length, return 0; } +static CertificateStatusRequestItemV2* TLSX_CSR2_GetMulti(TLSX *extensions) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + for (; csr2; csr2 = csr2->next) { + if (csr2->status_type == WOLFSSL_CSR2_OCSP_MULTI) + return csr2; + } + return NULL; +} + +int TLSX_CSR2_IsMulti(TLSX *extensions) +{ + return TLSX_CSR2_GetMulti(extensions) != NULL; +} + +int TLSX_CSR2_AddPendingSigner(TLSX *extensions, Signer *s) +{ + CertificateStatusRequestItemV2* csr2; + + csr2 = TLSX_CSR2_GetMulti(extensions); + if (!csr2) + return -1; + + s->next = csr2->pendingSigners; + csr2->pendingSigners = s; + return 0; +} + +Signer* TLSX_CSR2_GetPendingSigners(TLSX *extensions) +{ + CertificateStatusRequestItemV2* csr2; + + csr2 = TLSX_CSR2_GetMulti(extensions); + if (!csr2) + return NULL; + + return csr2->pendingSigners; +} + +int TLSX_CSR2_ClearPendingCA(WOLFSSL *ssl) +{ + CertificateStatusRequestItemV2* csr2; + + csr2 = TLSX_CSR2_GetMulti(ssl->extensions); + if (csr2 == NULL) + return 0; + + TLSX_CSR2_FreePendingSigners(csr2->pendingSigners, SSL_CM(ssl)->heap); + csr2->pendingSigners = NULL; + return 0; +} + +int TLSX_CSR2_MergePendingCA(WOLFSSL* ssl) +{ + CertificateStatusRequestItemV2* csr2; + Signer *s, *next; + int r = 0; + + csr2 = TLSX_CSR2_GetMulti(ssl->extensions); + if (csr2 == NULL) + return 0; + + s = csr2->pendingSigners; + while (s != NULL) { + next = s->next; + r = AddSigner(SSL_CM(ssl), s); + if (r != 0) + FreeSigner(s, SSL_CM(ssl)->heap); + s = next; + } + csr2->pendingSigners = NULL; + return r; +} + int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap) { @@ -3862,10 +4021,10 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: - if (SSL_CM(ssl)->ocspEnabled) { - csr2->request.ocsp[0].ssl = ssl; + if (SSL_CM(ssl)->ocspEnabled && csr2->requests >= 1) { + csr2->request.ocsp[csr2->requests-1].ssl = ssl; return CheckOcspRequest(SSL_CM(ssl)->ocsp, - &csr2->request.ocsp[0], NULL, NULL); + &csr2->request.ocsp[csr2->requests-1], NULL, NULL); } else { WOLFSSL_ERROR_VERBOSE(OCSP_LOOKUP_FAIL); @@ -3963,7 +4122,7 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, #ifdef HAVE_SUPPORTED_CURVES #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \ - && !defined(HAVE_FFDHE) && !defined(HAVE_PQC) + && !defined(HAVE_FFDHE) && !defined(WOLFSSL_HAVE_KYBER) #error Elliptic Curves Extension requires Elliptic Curve Cryptography or liboqs groups. \ Use --enable-ecc and/or --enable-liboqs in the configure script or \ define HAVE_ECC. Alternatively use FFDHE for DH cipher suites. @@ -4031,7 +4190,7 @@ static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap) static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name, void* heap) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); while (list) { if (list->name == name) { @@ -4052,7 +4211,7 @@ static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name, static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); while (list) { if (list->format == format) { @@ -4339,7 +4498,7 @@ int TLSX_SupportedCurve_Parse(const WOLFSSL* ssl, const byte* input, ret = TLSX_UseSupportedCurve(extensions, name, ssl->heap); /* If it is BAD_FUNC_ARG then it is a group we do not support, but * that is fine. */ - if (ret != WOLFSSL_SUCCESS && ret != BAD_FUNC_ARG) { + if (ret != WOLFSSL_SUCCESS && ret != WC_NO_ERR_TRACE(BAD_FUNC_ARG)) { return ret; } } @@ -4709,6 +4868,7 @@ int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, int ephmSuite = 0; word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ int key = 0; /* validate key */ + int foundCurve = 0; /* Found at least one supported curve */ (void)oid; @@ -4870,6 +5030,8 @@ int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, default: continue; /* unsupported curve */ } + foundCurve = 1; + #ifdef HAVE_ECC /* Set default Oid */ if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) { @@ -5014,6 +5176,10 @@ int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, byte second, } } + /* Check we found at least one supported curve */ + if (!foundCurve) + return 0; + *ecdhCurveOID = ssl->ecdhCurveOID; /* Choose the default if it is at the required strength. */ #ifdef HAVE_ECC @@ -5237,7 +5403,7 @@ static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte isRequest) { - int ret = SECURE_RENEGOTIATION_E; + int ret = WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E); if (length >= OPAQUE8_LEN) { if (isRequest) { @@ -5247,7 +5413,7 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, const byte* input, if (ret == WOLFSSL_SUCCESS) ret = 0; } - if (ret != 0 && ret != SECURE_RENEGOTIATION_E) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(SECURE_RENEGOTIATION_E)) { } else if (ssl->secure_renegotiation == NULL) { } @@ -5317,6 +5483,12 @@ static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, const byte* input, } #endif } + else { + ret = SECURE_RENEGOTIATION_E; + } + } + else { + ret = SECURE_RENEGOTIATION_E; } if (ret != 0) { @@ -5510,7 +5682,7 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, const byte* input, WOLFSSL_MSG("Process client ticket rejected, not using"); ssl->options.rejectTicket = 1; ret = 0; /* not fatal */ - } else if (ret == VERSION_ERROR) { + } else if (ret == WC_NO_ERR_TRACE(VERSION_ERROR)) { WOLFSSL_MSG("Process client ticket rejected, bad TLS version"); ssl->options.rejectTicket = 1; ret = 0; /* not fatal */ @@ -5812,7 +5984,7 @@ static void TLSX_UseSRTP_Free(TlsxSrtp *srtp, void* heap) static int TLSX_UseSRTP_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte isRequest) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); word16 profile_len = 0; word16 profile_value = 0; word16 offset = 0; @@ -6120,8 +6292,12 @@ static int TLSX_SupportedVersions_Write(void* data, byte* output, #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { tls13minor = (byte)DTLSv1_3_MINOR; + #ifndef WOLFSSL_NO_TLS12 tls12minor = (byte)DTLSv1_2_MINOR; + #endif + #ifndef NO_OLD_TLS tls11minor = (byte)DTLS_MINOR; + #endif isDtls = 1; } #endif /* WOLFSSL_DTLS13 */ @@ -7181,7 +7357,7 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) kse->pubKey, &kse->pubKeyLen /* public */ ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -7494,7 +7670,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13GenEccKeyPair(ssl, kse); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; } #endif @@ -7511,7 +7687,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) if (ret == 0) { #ifdef WOLFSSL_ASYNC_CRYPT /* Detect when private key generation is done */ - if (ssl->error == WC_PENDING_E && + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) && eccKey->type == ECC_PRIVATEKEY) { ret = 0; /* ECC Key Generation is done */ } @@ -7526,7 +7702,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) } } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif } @@ -7585,7 +7761,7 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) return ret; } -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER static int kyber_id2type(int id, int *type) { int ret = 0; @@ -7689,7 +7865,7 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) findEccPqc(&ecc_group, &oqs_group, kse->group); ret = kyber_id2type(oqs_group, &type); - if (ret == NOT_COMPILED_IN) { + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { WOLFSSL_MSG("Invalid Kyber algorithm specified."); ret = BAD_FUNC_ARG; } @@ -7788,7 +7964,7 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) return ret; } -#endif /* HAVE_PQC */ +#endif /* WOLFSSL_HAVE_KYBER */ /* Generate a secret/key using the key share entry. * @@ -7805,7 +7981,7 @@ int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) ret = TLSX_KeyShare_GenX25519Key(ssl, kse); else if (kse->group == WOLFSSL_ECC_X448) ret = TLSX_KeyShare_GenX448Key(ssl, kse); -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER else if (WOLFSSL_NAMED_GROUP_IS_PQC(kse->group)) ret = TLSX_KeyShare_GenPqcKey(ssl, kse); #endif @@ -7843,7 +8019,7 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) wc_curve448_free((curve448_key*)current->key); #endif } -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER else if (WOLFSSL_NAMED_GROUP_IS_PQC(current->group)) { if (current->key != NULL) { ForceZero((byte*)current->key, current->keyLen); @@ -8050,7 +8226,7 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) NULL, 0 ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -8322,7 +8498,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) } #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13GenSharedSecret(ssl, keyShareEntry); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; } ret = 0; @@ -8364,7 +8540,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ssl->options.side ); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif } @@ -8398,7 +8574,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) return ret; } -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER /* Process the Kyber key share extension on the client side. * * ssl The SSL/TLS object. @@ -8437,7 +8613,7 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) XMEMCPY(ssl->arrays->preMasterSecret, keyShareEntry->ke, keyShareEntry->keLen); ssl->arrays->preMasterSz = keyShareEntry->keLen; - XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_SECRET) + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_SECRET); keyShareEntry->ke = NULL; keyShareEntry->keLen = 0; return 0; @@ -8567,7 +8743,7 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) wc_KyberKey_Free(kem); return ret; } -#endif /* HAVE_PQC */ +#endif /* WOLFSSL_HAVE_KYBER */ /* Process the key share extension on the client side. * @@ -8593,7 +8769,7 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry); else if (keyShareEntry->group == WOLFSSL_ECC_X448) ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry); -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER else if (WOLFSSL_NAMED_GROUP_IS_PQC(keyShareEntry->group)) ret = TLSX_KeyShare_ProcessPqc(ssl, keyShareEntry); #endif @@ -8644,7 +8820,7 @@ static int TLSX_KeyShareEntry_Parse(const WOLFSSL* ssl, const byte* input, if (keLen > length - offset) return BUFFER_ERROR; -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER if (WOLFSSL_NAMED_GROUP_IS_PQC(group) && ssl->options.side == WOLFSSL_SERVER_END) { /* For KEMs, the public key is not stored. Casting away const because @@ -8823,7 +8999,7 @@ int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* Not in list sent if there isn't a private key. */ if (keyShareEntry == NULL || (keyShareEntry->key == NULL - #if !defined(NO_DH) || defined(HAVE_PQC) + #if !defined(NO_DH) || defined(WOLFSSL_HAVE_KYBER) && keyShareEntry->privKey == NULL #endif )) { @@ -8845,7 +9021,7 @@ int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, #ifdef WOLFSSL_ASYNC_CRYPT /* only perform find and clear TLSX if not returning from async */ - if (ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* Check the selected group was supported by ClientHello extensions. */ @@ -8915,7 +9091,7 @@ static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap, return 0; } -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER static int server_generate_pqc_ciphertext(WOLFSSL* ssl, KeyShareEntry* keyShareEntry, byte* data, word16 len) { @@ -9076,7 +9252,7 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, wc_KyberKey_Free(kem); return ret; } -#endif /* HAVE_PQC */ +#endif /* WOLFSSL_HAVE_KYBER */ /* Use the data to create a new key share object in the extensions. * @@ -9125,7 +9301,7 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, } -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER if (WOLFSSL_NAMED_GROUP_IS_PQC(group) && ssl->options.side == WOLFSSL_SERVER_END) { ret = server_generate_pqc_ciphertext((WOLFSSL*)ssl, keyShareEntry, data, @@ -9292,16 +9468,19 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) break; #endif #endif - #ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER #ifdef WOLFSSL_WC_KYBER #ifdef WOLFSSL_KYBER512 case WOLFSSL_KYBER_LEVEL1: + case WOLFSSL_P256_KYBER_LEVEL1: #endif #ifdef WOLFSSL_KYBER768 case WOLFSSL_KYBER_LEVEL3: + case WOLFSSL_P384_KYBER_LEVEL3: #endif #ifdef WOLFSSL_KYBER1024 case WOLFSSL_KYBER_LEVEL5: + case WOLFSSL_P521_KYBER_LEVEL5: #endif break; #elif defined(HAVE_LIBOQS) @@ -9316,7 +9495,7 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) int id; findEccPqc(NULL, &namedGroup, namedGroup); ret = kyber_id2type(namedGroup, &id); - if (ret == NOT_COMPILED_IN) { + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { return 0; } @@ -9329,7 +9508,7 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) case WOLFSSL_KYBER_LEVEL1: break; #endif - #endif /* HAVE_PQC */ +#endif default: return 0; } @@ -9378,12 +9557,15 @@ static const word16 preferredGroup[] = { #ifdef WOLFSSL_WC_KYBER #ifdef WOLFSSL_KYBER512 WOLFSSL_KYBER_LEVEL1, + WOLFSSL_P256_KYBER_LEVEL1, #endif #ifdef WOLFSSL_KYBER768 WOLFSSL_KYBER_LEVEL3, + WOLFSSL_P384_KYBER_LEVEL3, #endif #ifdef WOLFSSL_KYBER1024 WOLFSSL_KYBER_LEVEL5, + WOLFSSL_P521_KYBER_LEVEL5, #endif #elif defined(HAVE_LIBOQS) /* These require a runtime call to TLSX_KeyShare_IsSupported to use */ @@ -9487,7 +9669,7 @@ int TLSX_KeyShare_SetSupported(const WOLFSSL* ssl, TLSX** extensions) kse = (KeyShareEntry*)extension->data; /* We should not be computing keys if we are only going to advertise * our choice here. */ - if (kse != NULL && kse->lastRet == WC_PENDING_E) { + if (kse != NULL && kse->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { WOLFSSL_ERROR_VERBOSE(BAD_KEY_SHARE_DATA); return BAD_KEY_SHARE_DATA; } @@ -9583,7 +9765,7 @@ int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length, case WOLFSSL_CKS_SIGSPEC_EXTERNAL: default: /* All other values (including external) are not. */ - return WOLFSSL_NOT_IMPLEMENTED; + return BAD_FUNC_ARG; } } @@ -9618,7 +9800,7 @@ int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length, for (j = 0; j < length; j++) { if (ssl->sigSpec[i] == input[j]) { /* Got the match, set to this one. */ - ret = wolfSSL_UseCKS(ssl, &ssl->peerSigSpec[i], 1); + ret = wolfSSL_UseCKS(ssl, &ssl->sigSpec[i], 1); if (ret == WOLFSSL_SUCCESS) { ret = TLSX_UseCKS(&ssl->extensions, ssl, ssl->heap); TLSX_SetResponse(ssl, TLSX_CKS); @@ -9659,16 +9841,20 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, if (extension && extension->resp == 1) { /* Outside of the async case this path should not be taken. */ - int ret = INCOMPLETE_DATA; + int ret = WC_NO_ERR_TRACE(INCOMPLETE_DATA); #ifdef WOLFSSL_ASYNC_CRYPT /* in async case make sure key generation is finalized */ KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data; - if (serverKSE && serverKSE->lastRet == WC_PENDING_E) { + if (serverKSE && serverKSE->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) *searched = 1; ret = TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE); } + else #endif + { + ret = INCOMPLETE_DATA; + } return ret; } @@ -9697,7 +9883,7 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, if (!WOLFSSL_NAMED_GROUP_IS_FFHDE(clientKSE->group)) { /* Check max value supported. */ if (clientKSE->group > WOLFSSL_ECC_MAX) { -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER if (!WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group)) #endif continue; @@ -9743,7 +9929,7 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) serverKSE = (KeyShareEntry*)extension->data; if (serverKSE != NULL) { /* in async case make sure key generation is finalized */ - if (serverKSE->lastRet == WC_PENDING_E) + if (serverKSE->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) return TLSX_KeyShare_GenKey((WOLFSSL*)ssl, serverKSE); else if (serverKSE->lastRet == 0) return 0; @@ -9762,7 +9948,7 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) return ret; if (clientKSE->key == NULL) { -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER if (WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group)) { /* Going to need the public key (AKA ciphertext). */ serverKSE->pubKey = clientKSE->pubKey; @@ -9855,7 +10041,7 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, NULL); /* Check for error */ - if (ret != WC_NO_PENDING_E && ret < 0) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E) && ret < 0) { return ret; } #endif @@ -11212,8 +11398,10 @@ static int TLSX_ClientCertificateType_GetSize(WOLFSSL* ssl, byte msgType) ret = (int)(OPAQUE8_LEN + cnt * OPAQUE8_LEN); } else if (msgType == server_hello || msgType == encrypted_extensions) { - /* sever side */ + /* server side */ cnt = ssl->options.rpkState.sending_ClientCertTypeCnt;/* must be one */ + if (cnt != 1) + return SANITY_MSG_E; ret = OPAQUE8_LEN; } else { @@ -11668,7 +11856,7 @@ static int TLSX_ECH_Write(WOLFSSL_ECH* ech, byte* writeBuf, word16* offset) /* get size then write */ ret = GetEchConfigsEx(ech->echConfig, NULL, &configsLen); - if (ret != LENGTH_ONLY_E) + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) return ret; ret = GetEchConfigsEx(ech->echConfig, writeBuf, &configsLen); @@ -11805,7 +11993,7 @@ static int TLSX_ECH_GetSize(WOLFSSL_ECH* ech) /* get the size of the raw configs */ ret = GetEchConfigsEx(ech->echConfig, NULL, &size); - if (ret != LENGTH_ONLY_E) + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) return ret; } else if (ech->type == ECH_TYPE_INNER) @@ -11888,7 +12076,7 @@ static int TLSX_ExtractEch(WOLFSSL_ECH* ech, WOLFSSL_EchConfig* echConfig, if (ret == 0) ret = GetEchConfig(echConfig, NULL, &rawConfigLen); - if (ret == LENGTH_ONLY_E) + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) ret = 0; /* create info */ @@ -12130,7 +12318,7 @@ int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen) /* seal the payload */ ret = wc_HpkeSealBase(ech->hpke, ech->ephemeralKey, receiverPubkey, - info, infoLen, aadCopy, aadLen, ech->innerClientHello, + info, (word32)infoLen, aadCopy, aadLen, ech->innerClientHello, ech->innerClientHelloLen - ech->hpke->Nt, ech->outerClientPayload); @@ -12984,22 +13172,31 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) #endif #endif -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER #ifdef WOLFSSL_WC_KYBER #ifdef WOLFSSL_KYBER512 if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1, + ssl->heap); #endif #ifdef WOLFSSL_KYBER768 if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL3, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3, + ssl->heap); #endif #ifdef WOLFSSL_KYBER768 if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, + ssl->heap); #endif #elif defined(HAVE_LIBOQS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); @@ -13021,7 +13218,7 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) #elif defined(HAVE_PQM4) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); #endif /* HAVE_LIBOQS */ -#endif /* HAVE_PQC */ +#endif /* WOLFSSL_HAVE_KYBER */ (void)ssl; (void)extensions; @@ -13240,7 +13437,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ret = SetCipherSpecs(ssl); if (ret != 0) return ret; - now = TimeNowInMilliseconds(); + now = (word64)TimeNowInMilliseconds(); if (now == 0) return GETTIME_ERROR; #ifdef WOLFSSL_32BIT_MILLI_TIME @@ -13371,7 +13568,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) ssl->arrays->psk_keySz == 0 || #endif (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { #ifndef OPENSSL_EXTRA ret = PSK_KEY_ERROR; #endif @@ -13570,7 +13767,7 @@ static int TLSX_GetSizeWithEch(WOLFSSL* ssl, byte* semaphore, byte msgType, #endif /** Tells the buffered size of extensions to be sent into the client hello. */ -int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength) +int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word32* pLength) { int ret = 0; word16 length = 0; @@ -13800,7 +13997,7 @@ static int TLSX_WriteWithEch(WOLFSSL* ssl, byte* output, byte* semaphore, #endif /** Writes the extensions to be sent into the client hello. */ -int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) +int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word32* pOffset) { int ret = 0; word16 offset = 0; @@ -14294,6 +14491,143 @@ int TLSX_ParseVersion(WOLFSSL* ssl, const byte* input, word16 length, return ret; } #endif +/* Jump Table to check minimum size values for client case in TLSX_Parse */ +#ifndef NO_WOLFSSL_SERVER +static word16 TLSX_GetMinSize_Client(word16* type) +{ + switch (*type) { + case TLSXT_SERVER_NAME: + return WOLFSSL_SNI_MIN_SIZE_CLIENT; + case TLSXT_EARLY_DATA: + return WOLFSSL_EDI_MIN_SIZE_CLIENT; + case TLSXT_MAX_FRAGMENT_LENGTH: + return WOLFSSL_MFL_MIN_SIZE_CLIENT; + case TLSXT_TRUSTED_CA_KEYS: + return WOLFSSL_TCA_MIN_SIZE_CLIENT; + case TLSXT_TRUNCATED_HMAC: + return WOLFSSL_THM_MIN_SIZE_CLIENT; + case TLSXT_STATUS_REQUEST: + return WOLFSSL_CSR_MIN_SIZE_CLIENT; + case TLSXT_SUPPORTED_GROUPS: + return WOLFSSL_EC_MIN_SIZE_CLIENT; + case TLSXT_EC_POINT_FORMATS: + return WOLFSSL_PF_MIN_SIZE_CLIENT; + case TLSXT_SIGNATURE_ALGORITHMS: + return WOLFSSL_SA_MIN_SIZE_CLIENT; + case TLSXT_USE_SRTP: + return WOLFSSL_SRTP_MIN_SIZE_CLIENT; + case TLSXT_APPLICATION_LAYER_PROTOCOL: + return WOLFSSL_ALPN_MIN_SIZE_CLIENT; + case TLSXT_STATUS_REQUEST_V2: + return WOLFSSL_CSR2_MIN_SIZE_CLIENT; + case TLSXT_CLIENT_CERTIFICATE: + return WOLFSSL_CCT_MIN_SIZE_CLIENT; + case TLSXT_SERVER_CERTIFICATE: + return WOLFSSL_SCT_MIN_SIZE_CLIENT; + case TLSXT_ENCRYPT_THEN_MAC: + return WOLFSSL_ETM_MIN_SIZE_CLIENT; + case TLSXT_SESSION_TICKET: + return WOLFSSL_STK_MIN_SIZE_CLIENT; + case TLSXT_PRE_SHARED_KEY: + return WOLFSSL_PSK_MIN_SIZE_CLIENT; + case TLSXT_COOKIE: + return WOLFSSL_CKE_MIN_SIZE_CLIENT; + case TLSXT_PSK_KEY_EXCHANGE_MODES: + return WOLFSSL_PKM_MIN_SIZE_CLIENT; + case TLSXT_CERTIFICATE_AUTHORITIES: + return WOLFSSL_CAN_MIN_SIZE_CLIENT; + case TLSXT_POST_HANDSHAKE_AUTH: + return WOLFSSL_PHA_MIN_SIZE_CLIENT; + case TLSXT_SIGNATURE_ALGORITHMS_CERT: + return WOLFSSL_SA_MIN_SIZE_CLIENT; + case TLSXT_KEY_SHARE: + return WOLFSSL_KS_MIN_SIZE_CLIENT; + case TLSXT_CONNECTION_ID: + return WOLFSSL_CID_MIN_SIZE_CLIENT; + case TLSXT_RENEGOTIATION_INFO: + return WOLFSSL_SCR_MIN_SIZE_CLIENT; + case TLSXT_KEY_QUIC_TP_PARAMS_DRAFT: + return WOLFSSL_QTP_MIN_SIZE_CLIENT; + case TLSXT_ECH: + return WOLFSSL_ECH_MIN_SIZE_CLIENT; + default: + return 0; + } +} + #define TLSX_GET_MIN_SIZE_CLIENT TLSX_GetMinSize_Client +#else + #define TLSX_GET_MIN_SIZE_CLIENT(...) 0 +#endif + + +#ifndef NO_WOLFSSL_CLIENT +/* Jump Table to check minimum size values for server case in TLSX_Parse */ +static word16 TLSX_GetMinSize_Server(const word16 *type) +{ + switch (*type) { + case TLSXT_SERVER_NAME: + return WOLFSSL_SNI_MIN_SIZE_SERVER; + case TLSXT_EARLY_DATA: + return WOLFSSL_EDI_MIN_SIZE_SERVER; + case TLSXT_MAX_FRAGMENT_LENGTH: + return WOLFSSL_MFL_MIN_SIZE_SERVER; + case TLSXT_TRUSTED_CA_KEYS: + return WOLFSSL_TCA_MIN_SIZE_SERVER; + case TLSXT_TRUNCATED_HMAC: + return WOLFSSL_THM_MIN_SIZE_SERVER; + case TLSXT_STATUS_REQUEST: + return WOLFSSL_CSR_MIN_SIZE_SERVER; + case TLSXT_SUPPORTED_GROUPS: + return WOLFSSL_EC_MIN_SIZE_SERVER; + case TLSXT_EC_POINT_FORMATS: + return WOLFSSL_PF_MIN_SIZE_SERVER; + case TLSXT_SIGNATURE_ALGORITHMS: + return WOLFSSL_SA_MIN_SIZE_SERVER; + case TLSXT_USE_SRTP: + return WOLFSSL_SRTP_MIN_SIZE_SERVER; + case TLSXT_APPLICATION_LAYER_PROTOCOL: + return WOLFSSL_ALPN_MIN_SIZE_SERVER; + case TLSXT_STATUS_REQUEST_V2: + return WOLFSSL_CSR2_MIN_SIZE_SERVER; + case TLSXT_CLIENT_CERTIFICATE: + return WOLFSSL_CCT_MIN_SIZE_SERVER; + case TLSXT_SERVER_CERTIFICATE: + return WOLFSSL_SCT_MIN_SIZE_SERVER; + case TLSXT_ENCRYPT_THEN_MAC: + return WOLFSSL_ETM_MIN_SIZE_SERVER; + case TLSXT_SESSION_TICKET: + return WOLFSSL_STK_MIN_SIZE_SERVER; + case TLSXT_PRE_SHARED_KEY: + return WOLFSSL_PSK_MIN_SIZE_SERVER; + case TLSXT_COOKIE: + return WOLFSSL_CKE_MIN_SIZE_SERVER; + case TLSXT_PSK_KEY_EXCHANGE_MODES: + return WOLFSSL_PKM_MIN_SIZE_SERVER; + case TLSXT_CERTIFICATE_AUTHORITIES: + return WOLFSSL_CAN_MIN_SIZE_SERVER; + case TLSXT_POST_HANDSHAKE_AUTH: + return WOLFSSL_PHA_MIN_SIZE_SERVER; + case TLSXT_SIGNATURE_ALGORITHMS_CERT: + return WOLFSSL_SA_MIN_SIZE_SERVER; + case TLSXT_KEY_SHARE: + return WOLFSSL_KS_MIN_SIZE_SERVER; + case TLSXT_CONNECTION_ID: + return WOLFSSL_CID_MIN_SIZE_SERVER; + case TLSXT_RENEGOTIATION_INFO: + return WOLFSSL_SCR_MIN_SIZE_SERVER; + case TLSXT_KEY_QUIC_TP_PARAMS_DRAFT: + return WOLFSSL_QTP_MIN_SIZE_SERVER; + case TLSXT_ECH: + return WOLFSSL_ECH_MIN_SIZE_SERVER; + default: + return 0; + } +} + #define TLSX_GET_MIN_SIZE_SERVER TLSX_GetMinSize_Server +#else + #define TLSX_GET_MIN_SIZE_SERVER(...) 0 +#endif + /** Parses a buffer of TLS extensions. */ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, @@ -14357,6 +14691,29 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, if (length - offset < size) return BUFFER_ERROR; + /* Check minimum size required for TLSX, even if disabled */ + switch (msgType) { + #ifndef NO_WOLFSSL_SERVER + case client_hello: + if (size < TLSX_GET_MIN_SIZE_CLIENT(&type)){ + WOLFSSL_MSG("Minimum TLSX Size Requirement not Satisfied"); + return BUFFER_ERROR; + } + break; + #endif + #ifndef NO_WOLFSSL_CLIENT + case server_hello: + case hello_retry_request: + if (size < TLSX_GET_MIN_SIZE_SERVER(&type)){ + WOLFSSL_MSG("Minimum TLSX Size Requirement not Satisfied"); + return BUFFER_ERROR; + } + break; + #endif + default: + break; + } + switch (type) { #ifdef HAVE_SNI case TLSX_SERVER_NAME: @@ -14914,7 +15271,8 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, } #ifdef HAVE_EXTENDED_MASTER - if (IsAtLeastTLSv1_3(ssl->version) && msgType == hello_retry_request) { + if (IsAtLeastTLSv1_3(ssl->version) && + (msgType == hello_retry_request || msgType == hello_verify_request)) { /* Don't change EMS status until server_hello received. * Second ClientHello must have same extensions. */ @@ -14922,6 +15280,12 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType, else if (!isRequest && ssl->options.haveEMS && !pendingEMS) ssl->options.haveEMS = 0; #endif +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) + if (IsAtLeastTLSv1_3(ssl->version) && msgType == server_hello && + IS_OFF(seenType, TLSX_ToSemaphore(TLSX_KEY_SHARE))) { + ssl->options.noPskDheKe = 1; + } +#endif if (ret == 0) ret = SNI_VERIFY_PARSE(ssl, isRequest); diff --git a/src/src/tls13.c b/src/src/tls13.c index 9a2e240..ef37c29 100644 --- a/src/src/tls13.c +++ b/src/src/tls13.c @@ -189,7 +189,7 @@ static const byte #ifndef NO_CERTS #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448) || defined(HAVE_PQC) + defined(HAVE_ED448) || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash); @@ -205,7 +205,7 @@ static int Tls13HKDFExpandLabel(WOLFSSL* ssl, byte* okm, word32 okmLen, const byte* info, word32 infoLen, int digest) { - int ret = NOT_COMPILED_IN; + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #if defined(HAVE_PK_CALLBACKS) if (ssl->ctx && ssl->ctx->HKDFExpandLabelCb) { @@ -216,7 +216,7 @@ static int Tls13HKDFExpandLabel(WOLFSSL* ssl, byte* okm, word32 okmLen, WOLFSSL_CLIENT_END /* ignored */); } - if (ret != NOT_COMPILED_IN) + if (ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) return ret; #endif (void)ssl; @@ -257,7 +257,7 @@ static int Tls13HKDFExpandKeyLabel(WOLFSSL* ssl, byte* okm, word32 okmLen, info, infoLen, digest, side); } - if (ret != NOT_COMPILED_IN) + if (ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) return ret; #endif @@ -308,14 +308,14 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, const byte* protocol; word32 protocolLen; int digestAlg = -1; - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (hashAlgo) { #ifndef NO_WOLFSSL_SHA256 case sha256_mac: ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, ssl->devId); if (ret == 0) { - ret = wc_Sha256Update(&digest.sha256, msg, msgLen); + ret = wc_Sha256Update(&digest.sha256, msg, (word32)msgLen); if (ret == 0) ret = wc_Sha256Final(&digest.sha256, hash); wc_Sha256Free(&digest.sha256); @@ -328,7 +328,7 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, case sha384_mac: ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, ssl->devId); if (ret == 0) { - ret = wc_Sha384Update(&digest.sha384, msg, msgLen); + ret = wc_Sha384Update(&digest.sha384, msg, (word32)msgLen); if (ret == 0) ret = wc_Sha384Final(&digest.sha384, hash); wc_Sha384Free(&digest.sha384); @@ -341,7 +341,7 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, case sha512_mac: ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, ssl->devId); if (ret == 0) { - ret = wc_Sha512Update(&digest.sha512, msg, msgLen); + ret = wc_Sha512Update(&digest.sha512, msg, (word32)msgLen); if (ret == 0) ret = wc_Sha512Final(&digest.sha512, hash); wc_Sha512Free(&digest.sha512); @@ -354,7 +354,7 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, case sm3_mac: ret = wc_InitSm3(&digest.sm3, ssl->heap, ssl->devId); if (ret == 0) { - ret = wc_Sm3Update(&digest.sm3, msg, msgLen); + ret = wc_Sm3Update(&digest.sm3, msg, (word32)msgLen); if (ret == 0) ret = wc_Sm3Final(&digest.sm3, hash); wc_Sm3Free(&digest.sm3); @@ -364,6 +364,7 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, break; #endif default: + ret = BAD_FUNC_ARG; digestAlg = -1; break; } @@ -392,9 +393,9 @@ static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, return VERSION_ERROR; } if (outputLen == -1) - outputLen = hashSz; + outputLen = (int)hashSz; - ret = Tls13HKDFExpandLabel(ssl, output, outputLen, secret, hashSz, + ret = Tls13HKDFExpandLabel(ssl, output, (word32)outputLen, secret, hashSz, protocol, protocolLen, label, labelLen, hash, hashSz, digestAlg); return ret; @@ -481,7 +482,7 @@ int Tls13DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, #endif /* WOLFSSL_DTLS13 */ if (outputLen == -1) { - outputLen = hashSz; + outputLen = (int)hashSz; } if (includeMsgs) { hashOutSz = hashSz; @@ -496,7 +497,7 @@ int Tls13DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, } PRIVATE_KEY_UNLOCK(); - ret = Tls13HKDFExpandKeyLabel(ssl, output, outputLen, secret, hashSz, + ret = Tls13HKDFExpandKeyLabel(ssl, output, (word32)outputLen, secret, hashSz, protocol, protocolLen, label, labelLen, hash, hashOutSz, digestAlg, side); PRIVATE_KEY_LOCK(); @@ -973,7 +974,7 @@ int Tls13_Exporter(WOLFSSL* ssl, unsigned char *out, size_t outLen, { int ret; enum wc_HashType hashType = WC_HASH_TYPE_NONE; - int hashLen = 0; + word32 hashLen = 0; byte hashOut[WC_MAX_DIGEST_SIZE]; const byte* emptyHash = NULL; byte firstExpand[WC_MAX_DIGEST_SIZE]; @@ -1124,7 +1125,7 @@ static int Tls13_HKDF_Extract(WOLFSSL *ssl, byte* prk, const byte* salt, void *cb_ctx = ssl->HkdfExtractCtx; CallbackHKDFExtract cb = ssl->ctx->HkdfExtractCb; if (cb != NULL) { - ret = cb(prk, salt, saltLen, ikm, ikmLen, digest, cb_ctx); + ret = cb(prk, salt, (word32)saltLen, ikm, (word32)ikmLen, digest, cb_ctx); } else #endif @@ -1137,7 +1138,7 @@ static int Tls13_HKDF_Extract(WOLFSSL *ssl, byte* prk, const byte* salt, { #if !defined(HAVE_FIPS) || \ (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) - ret = wc_Tls13_HKDF_Extract_ex(prk, salt, saltLen, ikm, ikmLen, digest, + ret = wc_Tls13_HKDF_Extract_ex(prk, salt, (word32)saltLen, ikm, (word32)ikmLen, digest, ssl->heap, ssl->devId); #else ret = wc_Tls13_HKDF_Extract(prk, salt, saltLen, ikm, ikmLen, digest); @@ -1161,13 +1162,13 @@ int DeriveEarlySecret(WOLFSSL* ssl) } #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13DeriveEarlySecret(ssl); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; #endif PRIVATE_KEY_UNLOCK(); #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) ret = Tls13_HKDF_Extract(ssl, ssl->arrays->secret, NULL, 0, - ssl->arrays->psk_key, ssl->arrays->psk_keySz, + ssl->arrays->psk_key, (int)ssl->arrays->psk_keySz, mac2hash(ssl->specs.mac_algorithm)); #else ret = Tls13_HKDF_Extract(ssl, ssl->arrays->secret, NULL, 0, @@ -1197,7 +1198,7 @@ int DeriveHandshakeSecret(WOLFSSL* ssl) } #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13DeriveHandshakeSecret(ssl); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; #endif @@ -1210,7 +1211,7 @@ int DeriveHandshakeSecret(WOLFSSL* ssl) PRIVATE_KEY_UNLOCK(); ret = Tls13_HKDF_Extract(ssl, ssl->arrays->preMasterSecret, key, ssl->specs.hash_size, - ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->arrays->preMasterSecret, (int)ssl->arrays->preMasterSz, mac2hash(ssl->specs.mac_algorithm)); PRIVATE_KEY_LOCK(); @@ -1232,7 +1233,7 @@ int DeriveMasterSecret(WOLFSSL* ssl) #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13DeriveMasterSecret(ssl); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; #endif @@ -1355,7 +1356,7 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, #endif int hashType = WC_SHA256; int hashSz = WC_SHA256_DIGEST_SIZE; - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); if (ssl == NULL || key == NULL || hash == NULL) { return BAD_FUNC_ARG; @@ -1392,6 +1393,7 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, break; #endif /* WOLFSSL_SM3 */ default: + ret = BAD_FUNC_ARG; break; } if (ret != 0) @@ -1416,7 +1418,7 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, if (ret == 0) { ret = wc_HmacSetKey(verifyHmac, hashType, key, ssl->specs.hash_size); if (ret == 0) - ret = wc_HmacUpdate(verifyHmac, hash, hashSz); + ret = wc_HmacUpdate(verifyHmac, hash, (word32)hashSz); if (ret == 0) ret = wc_HmacFinal(verifyHmac, hash); wc_HmacFree(verifyHmac); @@ -1432,7 +1434,7 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, #endif if (pHashSz) - *pHashSz = hashSz; + *pHashSz = (word32)hashSz; return ret; } @@ -1466,7 +1468,7 @@ static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; */ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) { - int ret = BAD_FUNC_ARG; /* Assume failure */ + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); /* Assume failure */ int i = 0; #ifdef WOLFSSL_SMALL_STACK byte* key_dig; @@ -1477,10 +1479,10 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13DeriveKeys(ssl, secret, side); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; } - ret = BAD_FUNC_ARG; /* Assume failure */ + ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); /* Assume failure */ #endif #ifdef WOLFSSL_SMALL_STACK @@ -1553,6 +1555,7 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) break; default: + ret = BAD_FUNC_ARG; break; } @@ -1633,7 +1636,7 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) #endif /* WOLFSSL_DTLS13 */ end: - ForceZero(key_dig, i); + ForceZero(key_dig, (word32)i); #ifdef WOLFSSL_SMALL_STACK XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); #elif defined(WOLFSSL_CHECK_MEM_ZERO) @@ -1910,10 +1913,12 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) #elif defined(WOLFSSL_ZEPHYR) word32 TimeNowInMilliseconds(void) { + int64_t t; #if defined(CONFIG_ARCH_POSIX) k_cpu_idle(); #endif - return (word32)k_uptime_get() / 1000; + t = k_uptime_get(); /* returns current uptime in milliseconds */ + return (word32)t; } #else @@ -2201,10 +2206,12 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) #elif defined(WOLFSSL_ZEPHYR) sword64 TimeNowInMilliseconds(void) { + int64_t t; #if defined(CONFIG_ARCH_POSIX) k_cpu_idle(); #endif - return (sword64)k_uptime_get() / 1000; + t = k_uptime_get(); /* returns current uptime in milliseconds */ + return (sword64)t; } #else @@ -2567,13 +2574,13 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, (void)nonceSz; #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->error == WC_PENDING_E) { + if (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E)) { ssl->error = 0; /* clear async */ } #endif #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13AesEncrypt(ssl, output, input, dataSz); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { if (ret > 0) { ret = 0; /* tsip_Tls13AesEncrypt returns output size */ } @@ -2646,7 +2653,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, output + dataSz, macSz, aad, aadSz); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif { @@ -2688,7 +2695,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, output + dataSz, macSz, aad, aadSz); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif { #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ @@ -2750,7 +2757,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, ssl->encrypt.state = CIPHER_STATE_END; #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* if async is not okay, then block */ if (!asyncOkay) { ret = wc_AsyncWait(ret, asyncDev, event_flags); @@ -2952,7 +2959,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13AesDecrypt(ssl, output, input, sz); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { #ifndef WOLFSSL_EARLY_DATA if (ret < 0) { ret = VERIFY_MAC_ERROR; @@ -2965,9 +2972,9 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* check for still pending */ - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; ssl->error = 0; /* clear async */ @@ -3048,7 +3055,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, (byte *)(input + dataSz), macSz, aad, aadSz); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif { @@ -3057,7 +3064,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, input + dataSz, macSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } @@ -3087,14 +3094,14 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, (byte *)(input + dataSz), macSz, aad, aadSz); } - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) #endif { ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, ssl->decrypt.nonce, nonceSz, input + dataSz, macSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); } @@ -3144,7 +3151,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #ifdef WOLFSSL_ASYNC_CRYPT /* If pending, leave now */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -3242,7 +3249,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, args = (BuildMsg13Args*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_buildmsg; @@ -3256,7 +3263,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, /* Reset state */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_NO_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_NO_PENDING_E)) #endif { ret = 0; @@ -3269,7 +3276,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, args->headerSz = Dtls13GetRlHeaderLength(ssl, 1); #endif /* WOLFSSL_DTLS13 */ - args->sz = args->headerSz + inSz; + args->sz = args->headerSz + (word32)inSz; args->idx = args->headerSz; #ifdef WOLFSSL_ASYNC_CRYPT @@ -3299,7 +3306,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, args->sz += ssl->specs.aead_mac_size; if (sizeOnly) - return args->sz; + return (int)args->sz; if (args->sz > (word32)outSz) { WOLFSSL_MSG("Oops, want to write past output buffer size"); @@ -3324,8 +3331,8 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, /* TLS v1.3 can do in place encryption. */ if (input != output + args->idx) - XMEMCPY(output + args->idx, input, inSz); - args->idx += inSz; + XMEMCPY(output + args->idx, input, (size_t)inSz); + args->idx += (word32)inSz; ssl->options.buildMsgState = BUILD_MSG_HASH; } @@ -3334,7 +3341,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, case BUILD_MSG_HASH: { if (hashOutput) { - ret = HashOutput(ssl, output, args->headerSz + inSz, 0); + ret = HashOutput(ssl, output, (int)args->headerSz + inSz, 0); if (ret != 0) goto exit_buildmsg; } @@ -3353,8 +3360,8 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, /* QUIC does not use encryption of the TLS Record Layer. * Return the original length + added headers * and restore it in the record header. */ - AddTls13RecordHeader(output, inSz, type, ssl); - ret = args->headerSz + inSz; + AddTls13RecordHeader(output, (word32)inSz, (byte)type, ssl); + ret = (int)args->headerSz + inSz; goto exit_buildmsg; } #endif @@ -3364,7 +3371,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, byte* mac = output + args->idx; output += args->headerSz; - ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, + ret = ssl->ctx->MacEncryptCb(ssl, mac, output, (unsigned int)inSz, (byte)type, 0, output, output, args->size, ssl->MacEncryptCtx); } else @@ -3376,7 +3383,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, (word16)args->headerSz, asyncOkay); if (ret != 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { /* Zeroize plaintext. */ @@ -3402,7 +3409,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, WOLFSSL_LEAVE("BuildTls13Message", ret); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -3412,7 +3419,7 @@ int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, /* return sz on success */ if (ret == 0) { - ret = args->sz; + ret = (int)args->sz; } else { WOLFSSL_ERROR_VERBOSE(ret); @@ -3950,7 +3957,7 @@ static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk, int clientHello) } if (ssl->arrays->psk_keySz == 0 || (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN && - (int)ssl->arrays->psk_keySz != USE_HW_PSK)) { + (int)ssl->arrays->psk_keySz != WC_NO_ERR_TRACE(USE_HW_PSK))) { WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR); return PSK_KEY_ERROR; } @@ -4019,7 +4026,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) idx - Dtls13GetRlHeaderLength(ssl, 0)); else #endif /* WOLFSSL_DTLS13 */ - ret = HashOutput(ssl, output, idx, 0); + ret = HashOutput(ssl, output, (int)idx, 0); if (ret != 0) return ret; @@ -4167,7 +4174,7 @@ static int EchHashHelloInner(WOLFSSL* ssl, WOLFSSL_ECH* ech) /* hash the body */ if (ret == 0) { ret = HashRaw(ssl, ech->innerClientHello, - ech->innerClientHelloLen - ech->paddingLen - ech->hpke->Nt); + (int)(ech->innerClientHelloLen - ech->paddingLen - ech->hpke->Nt)); } /* swap hsHashes back */ @@ -4234,7 +4241,7 @@ typedef struct Sch13Args { byte* output; word32 idx; int sendSz; - word16 length; + word32 length; #if defined(HAVE_ECH) int clientRandomOffset; int preXLength; @@ -4312,7 +4319,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) args = (Sch13Args*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) return ret; @@ -4419,7 +4426,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) /* set the type to inner */ args->ech->type = ECH_TYPE_INNER; - args->preXLength = args->length; + args->preXLength = (int)args->length; /* get size for inner */ ret = TLSX_GetRequestSize(ssl, client_hello, &args->length); @@ -4430,16 +4437,16 @@ int SendTls13ClientHello(WOLFSSL* ssl) args->ech->type = 0; /* set innerClientHelloLen to ClientHelloInner + padding + tag */ args->ech->paddingLen = 31 - ((args->length - 1) % 32); - args->ech->innerClientHelloLen = args->length + - args->ech->paddingLen + args->ech->hpke->Nt; + args->ech->innerClientHelloLen = (word16)(args->length + + args->ech->paddingLen + args->ech->hpke->Nt); /* set the length back to before we computed ClientHelloInner size */ - args->length = args->preXLength; + args->length = (word32)args->preXLength; } #endif { #ifdef WOLFSSL_DTLS_CH_FRAG - int maxFrag = wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE); + word16 maxFrag = wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE); word16 lenWithoutExts = args->length; #endif @@ -4470,7 +4477,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) } /* Total message size. */ - args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = (int)(args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ); #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) @@ -4510,7 +4517,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN); #if defined(HAVE_ECH) - args->clientRandomOffset = args->idx; + args->clientRandomOffset = (int)args->idx; #endif args->idx += RAN_LEN; @@ -4619,7 +4626,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) if (ssl->options.useEch == 1) { ret = TLSX_FinalizeEch(args->ech, args->output + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ, - args->sendSz - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ)); + (word32)(args->sendSz - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ))); if (ret != 0) return ret; @@ -4653,7 +4660,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) /* compute the outer hash */ if (ret == 0) - ret = HashOutput(ssl, args->output, args->idx, 0); + ret = HashOutput(ssl, args->output, (int)args->idx, 0); } } if (ret != 0) @@ -4680,7 +4687,7 @@ int SendTls13ClientHello(WOLFSSL* ssl) } #endif /* WOLFSSL_DTLS13 */ - ssl->buffers.outputBuffer.length += args->sendSz; + ssl->buffers.outputBuffer.length += (word32)args->sendSz; /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_END; @@ -4817,7 +4824,7 @@ static int EchCheckAcceptance(WOLFSSL* ssl, const byte* input, PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_FIPS) || \ (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) - ret = wc_HKDF_Extract_ex(digestType, zeros, digestSize, + ret = wc_HKDF_Extract_ex(digestType, zeros, (word32)digestSize, ssl->arrays->clientRandomInner, RAN_LEN, expandLabelPrk, ssl->heap, ssl->devId); #else @@ -4831,10 +4838,10 @@ static int EchCheckAcceptance(WOLFSSL* ssl, const byte* input, PRIVATE_KEY_UNLOCK(); ret = Tls13HKDFExpandKeyLabel(ssl, acceptConfirmation, ECH_ACCEPT_CONFIRMATION_SZ, - expandLabelPrk, digestSize, + expandLabelPrk, (word32)digestSize, tls13ProtocolLabel, TLS13_PROTOCOL_LABEL_SZ, echAcceptConfirmationLabel, ECH_ACCEPT_CONFIRMATION_LABEL_SZ, - transcriptEchConf, digestSize, digestType, WOLFSSL_SERVER_END); + transcriptEchConf, (word32)digestSize, digestType, WOLFSSL_SERVER_END); PRIVATE_KEY_LOCK(); } if (ret == 0) { @@ -4955,7 +4962,7 @@ static int EchWriteAcceptance(WOLFSSL* ssl, byte* output, PRIVATE_KEY_UNLOCK(); #if !defined(HAVE_FIPS) || \ (defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,3)) - ret = wc_HKDF_Extract_ex(digestType, zeros, digestSize, + ret = wc_HKDF_Extract_ex(digestType, zeros, (word32)digestSize, ssl->arrays->clientRandom, RAN_LEN, expandLabelPrk, ssl->heap, ssl->devId); #else @@ -4971,10 +4978,10 @@ static int EchWriteAcceptance(WOLFSSL* ssl, byte* output, ret = Tls13HKDFExpandKeyLabel(ssl, output + serverRandomOffset + RAN_LEN - ECH_ACCEPT_CONFIRMATION_SZ, ECH_ACCEPT_CONFIRMATION_SZ, - expandLabelPrk, digestSize, + expandLabelPrk, (word32)digestSize, tls13ProtocolLabel, TLS13_PROTOCOL_LABEL_SZ, echAcceptConfirmationLabel, ECH_ACCEPT_CONFIRMATION_LABEL_SZ, - transcriptEchConf, digestSize, digestType, WOLFSSL_SERVER_END); + transcriptEchConf, (word32)digestSize, digestType, WOLFSSL_SERVER_END); PRIVATE_KEY_LOCK(); } @@ -5055,10 +5062,10 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args = (Dsh13Args*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) { - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_server_hello = 0; } @@ -5169,7 +5176,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Server random - keep for debugging. */ XMEMCPY(ssl->arrays->serverRandom, input + args->idx, RAN_LEN); #if defined(HAVE_ECH) - args->serverRandomOffset = args->idx; + args->serverRandomOffset = (int)args->idx; #endif args->idx += RAN_LEN; @@ -5285,6 +5292,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } ssl->version.minor = args->pv.minor; + ssl->options.tls1_3 = 0; #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { @@ -5318,14 +5326,15 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* restore message type */ *extMsgType = args->extMsgType; - if (args->totalExtSz > 0) { - /* Parse and handle extensions. */ + /* Parse and handle extensions, unless lower than TLS1.3. In that case, + * extensions will be parsed in DoServerHello. */ + if (args->totalExtSz > 0 && IsAtLeastTLSv1_3(ssl->version)) { ret = TLSX_Parse(ssl, input + args->idx, args->totalExtSz, *extMsgType, NULL); if (ret != 0) { #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_server_hello = 0; } @@ -5338,7 +5347,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->msgsReceived.got_hello_retry_request = 1; ssl->msgsReceived.got_server_hello = 0; } + } + if (args->totalExtSz > 0) { args->idx += args->totalExtSz; } @@ -5347,7 +5358,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, DtlsCIDOnExtensionsParsed(ssl); #endif /* WOLFSSL_DTLS_CID */ - *inOutIdx = args->idx; + if (IsAtLeastTLSv1_3(ssl->version)) { + *inOutIdx = args->idx; + } ssl->options.serverState = SERVER_HELLO_COMPLETE; @@ -5386,9 +5399,12 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Force client hello version 1.2 to work for static RSA. */ - ssl->chVersion.minor = TLSv1_2_MINOR; + if (ssl->options.dtls) + ssl->chVersion.minor = DTLSv1_2_MINOR; + else + ssl->chVersion.minor = TLSv1_2_MINOR; /* Complete TLS v1.2 processing of ServerHello. */ - ret = CompleteServerHello(ssl); + ret = DoServerHello(ssl, input, inOutIdx, helloSz); #else WOLFSSL_MSG("Client using higher version, fatal error"); WOLFSSL_ERROR_VERBOSE(VERSION_ERROR); @@ -5457,7 +5473,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_ECH) /* check for acceptConfirmation and HashInput with 8 0 bytes */ if (ssl->options.useEch == 1) { - ret = EchCheckAcceptance(ssl, input, args->serverRandomOffset, helloSz); + ret = EchCheckAcceptance(ssl, input, args->serverRandomOffset, (int)helloSz); if (ret != 0) return ret; } @@ -5724,7 +5740,7 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, #endif ) { if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, - peerSuites.hashSigAlgoSz) != 0) { + peerSuites.hashSigAlgoSz, 0) != 0) { WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER); return INVALID_PARAMETER; } @@ -5847,7 +5863,7 @@ int FindPskSuite(const WOLFSSL* ssl, PreSharedKey* psk, byte* psk_key, } if (*found) { if (*psk_keySz > MAX_PSK_KEY_LEN && - *((int*)psk_keySz) != USE_HW_PSK) { + *((int*)psk_keySz) != WC_NO_ERR_TRACE(USE_HW_PSK)) { WOLFSSL_MSG("Key len too long in FindPsk()"); ret = PSK_KEY_ERROR; WOLFSSL_ERROR_VERBOSE(ret); @@ -6001,7 +6017,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, } #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif @@ -6052,7 +6068,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, return ret; /* Hash data up to binders for deriving binders in PSK extension. */ - ret = HashInput(ssl, input, inputSz); + ret = HashInput(ssl, input, (int)inputSz); if (ret < 0) return ret; @@ -6068,7 +6084,7 @@ static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 inputSz, if (ret != 0) return ret; - ret = HashInput(ssl, input, inputSz); + ret = HashInput(ssl, input, (int)inputSz); if (ret < 0) return ret; @@ -6164,7 +6180,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if (usingPSK) *usingPSK = 0; /* Hash data up to binders for deriving binders in PSK extension. */ - ret = HashInput(ssl, input, helloSz); + ret = HashInput(ssl, input, (int)helloSz); return ret; } @@ -6201,7 +6217,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, if (ret != 0) { #ifdef HAVE_SESSION_TICKET #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif CleanupClientTickets((PreSharedKey*)ext->data); #endif @@ -6231,7 +6247,7 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, else { /* No suitable PSK found, Hash the complete ClientHello, * as caller expect it after we return */ - ret = HashInput(ssl, input, helloSz); + ret = HashInput(ssl, input, (int)helloSz); } if (ret != 0) return ret; @@ -6684,7 +6700,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, args = (Dch13Args*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) { goto exit_dch; @@ -6810,7 +6826,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, realMinor = ssl->version.minor; ssl->version.minor = args->pv.minor; - ret = HashInput(ssl, input + args->begin, helloSz); + ret = HashInput(ssl, input + args->begin, (int)helloSz); ssl->version.minor = realMinor; if (ret == 0) { ret = DoClientHello(ssl, input, inOutIdx, helloSz); @@ -7048,7 +7064,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (!args->usingPSK) { if ((ret = MatchSuite(ssl, args->clSuites)) < 0) { #ifdef WOLFSSL_ASYNC_CRYPT - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif WOLFSSL_MSG("Unsupported cipher suite, ClientHello 1.3"); goto exit_dch; @@ -7065,7 +7081,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) ERROR_OUT(INVALID_PARAMETER, exit_dch); ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) ret = 0; /* for hello_retry return 0 */ } if (ret != 0) @@ -7087,7 +7103,8 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, TLSX* extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension != NULL && extension->resp == 1) { KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data; - if (serverKSE != NULL && serverKSE->lastRet == WC_PENDING_E) { + if (serverKSE != NULL && + serverKSE->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { ret = TLSX_KeyShare_GenKey(ssl, serverKSE); if (ret != 0) goto exit_dch; @@ -7220,7 +7237,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_LEAVE("DoTls13ClientHello", ret); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { ssl->msgsReceived.got_client_hello = 0; return ret; } @@ -7298,7 +7315,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) ret = TLSX_GetResponseSize(ssl, extMsgType, &length); if (ret != 0) return ret; - sendSz = idx + length; + sendSz = (int)(idx + length); /* Check buffers are big enough and grow if needed. */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) @@ -7537,7 +7554,7 @@ static int SendTls13EncryptedExtensions(WOLFSSL* ssl) if (ret != 0) return ret; - sendSz = idx + length; + sendSz = (int)(idx + length); /* Encryption always on. */ sendSz += MAX_MSG_EXTRA; @@ -7622,13 +7639,9 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, int ret; int sendSz; word32 i; - word16 reqSz; + word32 reqSz; word16 hashSigAlgoSz = 0; SignatureAlgorithms* sa; - int haveSig = SIG_RSA | SIG_ECDSA | SIG_FALCON | SIG_DILITHIUM; -#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) - haveSig |= SIG_SM2; -#endif WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND); WOLFSSL_ENTER("SendTls13CertificateRequest"); @@ -7639,12 +7652,12 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, return SIDE_ERROR; /* Get the length of the hashSigAlgo buffer */ - InitSuitesHashSigAlgo_ex2(NULL, haveSig, 1, ssl->buffers.keySz, + InitSuitesHashSigAlgo(NULL, SIG_ALL, 1, ssl->buffers.keySz, &hashSigAlgoSz); sa = TLSX_SignatureAlgorithms_New(ssl, hashSigAlgoSz, ssl->heap); if (sa == NULL) return MEMORY_ERROR; - InitSuitesHashSigAlgo_ex2(sa->hashSigAlgo, haveSig, 1, ssl->buffers.keySz, + InitSuitesHashSigAlgo(sa->hashSigAlgo, SIG_ALL, 1, ssl->buffers.keySz, &hashSigAlgoSz); ret = TLSX_Push(&ssl->extensions, TLSX_SIGNATURE_ALGORITHMS, sa, ssl->heap); if (ret != 0) { @@ -7663,7 +7676,7 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, if (ret != 0) return ret; - sendSz = i + reqSz; + sendSz = (int)(i + reqSz); /* Always encrypted and make room for padding. */ sendSz += MAX_MSG_EXTRA; @@ -7738,7 +7751,7 @@ static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, #ifndef NO_CERTS #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448) || defined(HAVE_PQC) + defined(HAVE_ED448) || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) /* Encode the signature algorithm into buffer. * * hashalgo The hash algorithm. @@ -7783,8 +7796,7 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[1] = hashAlgo; break; #endif -#ifdef HAVE_PQC - #ifdef HAVE_FALCON +#ifdef HAVE_FALCON case falcon_level1_sa_algo: output[0] = FALCON_LEVEL1_SA_MAJOR; output[1] = FALCON_LEVEL1_SA_MINOR; @@ -7793,8 +7805,8 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = FALCON_LEVEL5_SA_MAJOR; output[1] = FALCON_LEVEL5_SA_MINOR; break; - #endif - #ifdef HAVE_DILITHIUM +#endif +#ifdef HAVE_DILITHIUM case dilithium_level2_sa_algo: output[0] = DILITHIUM_LEVEL2_SA_MAJOR; output[1] = DILITHIUM_LEVEL2_SA_MINOR; @@ -7807,7 +7819,6 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) output[0] = DILITHIUM_LEVEL5_SA_MAJOR; output[1] = DILITHIUM_LEVEL5_SA_MINOR; break; - #endif #endif default: break; @@ -7821,9 +7832,19 @@ static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) #define HYBRID_RSA3072_DILITHIUM_LEVEL2_SA_MINOR 0xA2 #define HYBRID_P384_DILITHIUM_LEVEL3_SA_MINOR 0xA4 #define HYBRID_P521_DILITHIUM_LEVEL5_SA_MINOR 0xA6 -#define HYBRID_P256_FALCON_LEVEL1_SA_MINOR 0x0C -#define HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR 0x0D -#define HYBRID_P521_FALCON_LEVEL5_SA_MINOR 0x0F +#define HYBRID_P256_FALCON_LEVEL1_SA_MINOR 0xAF +#define HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR 0xB0 +#define HYBRID_P521_FALCON_LEVEL5_SA_MINOR 0xB2 + +/* Custom defined ones for PQC first */ +#define HYBRID_DILITHIUM_LEVEL2_P256_SA_MINOR 0xD1 +#define HYBRID_DILITHIUM_LEVEL2_RSA3072_SA_MINOR 0xD2 +#define HYBRID_DILITHIUM_LEVEL3_P384_SA_MINOR 0xD3 +#define HYBRID_DILITHIUM_LEVEL5_P521_SA_MINOR 0xD4 +#define HYBRID_FALCON_LEVEL1_P256_SA_MINOR 0xD5 +#define HYBRID_FALCON_LEVEL1_RSA3072_SA_MINOR 0xD6 +#define HYBRID_FALCON_LEVEL5_P521_SA_MINOR 0xD7 + static void EncodeDualSigAlg(byte sigAlg, byte altSigAlg, byte* output) { @@ -7846,15 +7867,46 @@ static void EncodeDualSigAlg(byte sigAlg, byte altSigAlg, byte* output) altSigAlg == dilithium_level5_sa_algo) { output[1] = HYBRID_P521_DILITHIUM_LEVEL5_SA_MINOR; } - else if (sigAlg == ecc_dsa_sa_algo && altSigAlg == falcon_level1_sa_algo) { + else if (sigAlg == ecc_dsa_sa_algo && + altSigAlg == falcon_level1_sa_algo) { output[1] = HYBRID_P256_FALCON_LEVEL1_SA_MINOR; } - else if (sigAlg == rsa_pss_sa_algo && altSigAlg == falcon_level1_sa_algo) { + else if (sigAlg == rsa_pss_sa_algo && + altSigAlg == falcon_level1_sa_algo) { output[1] = HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR; } - else if (sigAlg == ecc_dsa_sa_algo && altSigAlg == falcon_level5_sa_algo) { + else if (sigAlg == ecc_dsa_sa_algo && + altSigAlg == falcon_level5_sa_algo) { output[1] = HYBRID_P521_FALCON_LEVEL5_SA_MINOR; } + else if (sigAlg == dilithium_level2_sa_algo && + altSigAlg == ecc_dsa_sa_algo) { + output[1] = HYBRID_DILITHIUM_LEVEL2_P256_SA_MINOR; + } + else if (sigAlg == dilithium_level2_sa_algo && + altSigAlg == rsa_pss_sa_algo) { + output[1] = HYBRID_DILITHIUM_LEVEL2_RSA3072_SA_MINOR; + } + else if (sigAlg == dilithium_level3_sa_algo && + altSigAlg == ecc_dsa_sa_algo) { + output[1] = HYBRID_DILITHIUM_LEVEL3_P384_SA_MINOR; + } + else if (sigAlg == dilithium_level5_sa_algo && + altSigAlg == ecc_dsa_sa_algo) { + output[1] = HYBRID_DILITHIUM_LEVEL5_P521_SA_MINOR; + } + else if (sigAlg == falcon_level1_sa_algo && + altSigAlg == ecc_dsa_sa_algo) { + output[1] = HYBRID_FALCON_LEVEL1_P256_SA_MINOR; + } + else if (sigAlg == falcon_level1_sa_algo && + altSigAlg == rsa_pss_sa_algo) { + output[1] = HYBRID_FALCON_LEVEL1_RSA3072_SA_MINOR; + } + else if (sigAlg == falcon_level5_sa_algo && + altSigAlg == ecc_dsa_sa_algo) { + output[1] = HYBRID_FALCON_LEVEL5_P521_SA_MINOR; + } if (output[1] != 0x0) { output[0] = HYBRID_SA_MAJOR; @@ -7910,7 +7962,7 @@ static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo, else ret = INVALID_PARAMETER; break; -#ifdef HAVE_PQC +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) case PQC_SA_MAJOR: #if defined(HAVE_FALCON) if (input[1] == FALCON_LEVEL1_SA_MINOR) { @@ -7972,39 +8024,74 @@ static WC_INLINE int DecodeTls13HybridSigAlg(byte* input, byte* hashAlg, if (input[1] == HYBRID_P256_DILITHIUM_LEVEL2_SA_MINOR) { *sigAlg = ecc_dsa_sa_algo; - *hashAlg = 4; /* WC_HASH_TYPE_SHA? Reviewer? */ + *hashAlg = sha256_mac; *altSigAlg = dilithium_level2_sa_algo; } else if (input[1] == HYBRID_RSA3072_DILITHIUM_LEVEL2_SA_MINOR) { *sigAlg = rsa_pss_sa_algo; - *hashAlg = 4; + *hashAlg = sha256_mac; *altSigAlg = dilithium_level2_sa_algo; } else if (input[1] == HYBRID_P384_DILITHIUM_LEVEL3_SA_MINOR) { *sigAlg = ecc_dsa_sa_algo; - *hashAlg = 5; + *hashAlg = sha384_mac; *altSigAlg = dilithium_level3_sa_algo; } else if (input[1] == HYBRID_P521_DILITHIUM_LEVEL5_SA_MINOR) { *sigAlg = ecc_dsa_sa_algo; - *hashAlg = 6; + *hashAlg = sha512_mac; *altSigAlg = dilithium_level5_sa_algo; } else if (input[1] == HYBRID_P256_FALCON_LEVEL1_SA_MINOR) { *sigAlg = ecc_dsa_sa_algo; - *hashAlg = 4; + *hashAlg = sha256_mac; *altSigAlg = falcon_level1_sa_algo; } else if (input[1] == HYBRID_RSA3072_FALCON_LEVEL1_SA_MINOR) { *sigAlg = rsa_pss_sa_algo; - *hashAlg = 4; + *hashAlg = sha256_mac; *altSigAlg = falcon_level1_sa_algo; } else if (input[1] == HYBRID_P521_FALCON_LEVEL5_SA_MINOR) { *sigAlg = ecc_dsa_sa_algo; - *hashAlg = 6; + *hashAlg = sha512_mac; *altSigAlg = falcon_level5_sa_algo; } + else if (input[1] == HYBRID_DILITHIUM_LEVEL2_P256_SA_MINOR) { + *sigAlg = dilithium_level2_sa_algo; + *hashAlg = sha256_mac; + *altSigAlg = ecc_dsa_sa_algo; + } + else if (input[1] == HYBRID_DILITHIUM_LEVEL2_RSA3072_SA_MINOR) { + *sigAlg = dilithium_level2_sa_algo; + *hashAlg = sha256_mac; + *altSigAlg = rsa_pss_sa_algo; + } + else if (input[1] == HYBRID_DILITHIUM_LEVEL3_P384_SA_MINOR) { + *sigAlg = dilithium_level3_sa_algo; + *hashAlg = sha384_mac; + *altSigAlg = ecc_dsa_sa_algo; + } + else if (input[1] == HYBRID_DILITHIUM_LEVEL5_P521_SA_MINOR) { + *sigAlg = dilithium_level5_sa_algo; + *hashAlg = sha512_mac; + *altSigAlg = ecc_dsa_sa_algo; + } + else if (input[1] == HYBRID_FALCON_LEVEL1_P256_SA_MINOR) { + *sigAlg = falcon_level1_sa_algo; + *hashAlg = sha256_mac; + *altSigAlg = ecc_dsa_sa_algo; + } + else if (input[1] == HYBRID_FALCON_LEVEL1_RSA3072_SA_MINOR) { + *sigAlg = falcon_level1_sa_algo; + *hashAlg = sha256_mac; + *altSigAlg = rsa_pss_sa_algo; + } + else if (input[1] == HYBRID_FALCON_LEVEL5_P521_SA_MINOR) { + *sigAlg = falcon_level5_sa_algo; + *hashAlg = sha512_mac; + *altSigAlg = ecc_dsa_sa_algo; + } else { return INVALID_PARAMETER; } @@ -8118,7 +8205,7 @@ int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, { Digest digest; int hashSz = 0; - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); byte* hash; (void)sigAlgo; @@ -8131,7 +8218,7 @@ int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, case sha256_mac: ret = wc_InitSha256(&digest.sha256); if (ret == 0) { - ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + ret = wc_Sha256Update(&digest.sha256, sigData, (word32)sigDataSz); if (ret == 0) ret = wc_Sha256Final(&digest.sha256, hash); wc_Sha256Free(&digest.sha256); @@ -8143,7 +8230,7 @@ int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, case sha384_mac: ret = wc_InitSha384(&digest.sha384); if (ret == 0) { - ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + ret = wc_Sha384Update(&digest.sha384, sigData, (word32)sigDataSz); if (ret == 0) ret = wc_Sha384Final(&digest.sha384, hash); wc_Sha384Free(&digest.sha384); @@ -8155,7 +8242,7 @@ int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, case sha512_mac: ret = wc_InitSha512(&digest.sha512); if (ret == 0) { - ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + ret = wc_Sha512Update(&digest.sha512, sigData, (word32)sigDataSz); if (ret == 0) ret = wc_Sha512Final(&digest.sha512, hash); wc_Sha512Free(&digest.sha512); @@ -8163,6 +8250,10 @@ int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, hashSz = WC_SHA512_DIGEST_SIZE; break; #endif + default: + ret = BAD_FUNC_ARG; + break; + } if (ret != 0) @@ -8184,7 +8275,7 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) { Digest digest; int hashSz = 0; - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); /* Digest the signature data. */ switch (hashAlgo) { @@ -8192,7 +8283,7 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) case sha256_mac: ret = wc_InitSha256(&digest.sha256); if (ret == 0) { - ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + ret = wc_Sha256Update(&digest.sha256, sigData, (word32)sigDataSz); if (ret == 0) ret = wc_Sha256Final(&digest.sha256, sigData); wc_Sha256Free(&digest.sha256); @@ -8204,7 +8295,7 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) case sha384_mac: ret = wc_InitSha384(&digest.sha384); if (ret == 0) { - ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + ret = wc_Sha384Update(&digest.sha384, sigData, (word32)sigDataSz); if (ret == 0) ret = wc_Sha384Final(&digest.sha384, sigData); wc_Sha384Free(&digest.sha384); @@ -8216,7 +8307,7 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) case sha512_mac: ret = wc_InitSha512(&digest.sha512); if (ret == 0) { - ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + ret = wc_Sha512Update(&digest.sha512, sigData, (word32)sigDataSz); if (ret == 0) ret = wc_Sha512Final(&digest.sha512, sigData); wc_Sha512Free(&digest.sha512); @@ -8225,6 +8316,7 @@ static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) break; #endif default: + ret = BAD_FUNC_ARG; break; } @@ -8270,7 +8362,7 @@ static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, sigAlgo, hashAlgo); if (ret < 0) return ret; - sigSz = ret; + sigSz = (word32)ret; ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz, hashType); @@ -8420,7 +8512,7 @@ static int SendTls13Certificate(WOLFSSL* ssl) else { if (!ssl->buffers.certificate) { WOLFSSL_MSG("Send Cert missing certificate buffer"); - return BUFFER_ERROR; + return NO_CERT_ERROR; } /* Certificate Data */ certSz = ssl->buffers.certificate->length; @@ -8468,7 +8560,7 @@ static int SendTls13Certificate(WOLFSSL* ssl) if (ssl->fragOffset != 0) length -= (ssl->fragOffset + headerSz); - maxFragment = wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE); + maxFragment = (word32)wolfSSL_GetMaxFragSize(ssl, MAX_RECORD_SIZE); while (length > 0 && ret == 0) { byte* output = NULL; @@ -8653,7 +8745,8 @@ static int SendTls13Certificate(WOLFSSL* ssl) } #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448) || defined(HAVE_PQC)) && \ + defined(HAVE_ED448) || defined(HAVE_FALCON) || \ + defined(HAVE_DILITHIUM)) && \ (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) typedef struct Scv13Args { byte* output; /* not allocated */ @@ -8668,7 +8761,9 @@ typedef struct Scv13Args { word16 sigDataSz; #ifdef WOLFSSL_DUAL_ALG_CERTS byte altSigAlgo; - word16 altSigLen; /* Only used in the case of both native and alt. */ + word32 altSigLen; /* Only used in the case of both native and alt. */ + byte* altSigData; + word16 altSigDataSz; #endif } Scv13Args; @@ -8682,6 +8777,12 @@ static void FreeScv13Args(WOLFSSL* ssl, void* pArgs) XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); args->sigData = NULL; } +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (args && args->altSigData != NULL) { + XFREE(args->altSigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->altSigData = NULL; + } +#endif } /* handle generation TLS v1.3 certificate_verify (15) */ @@ -8697,7 +8798,10 @@ static void FreeScv13Args(WOLFSSL* ssl, void* pArgs) static int SendTls13CertificateVerify(WOLFSSL* ssl) { int ret = 0; - buffer* sig = &ssl->buffers.sig; +#ifndef NO_RSA + /* Use this as a temporary buffer for RSA signature verification. */ + buffer* rsaSigBuf = &ssl->buffers.sig; +#endif #ifdef WOLFSSL_ASYNC_CRYPT Scv13Args* args = NULL; WOLFSSL_ASSERT_SIZEOF_GE(ssl->async->args, *args); @@ -8712,11 +8816,15 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); WOLFSSL_ENTER("SendTls13CertificateVerify"); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); +#endif + ssl->options.buildingMsg = 1; #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13SendCertVerify(ssl); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { goto exit_scv; } ret = 0; @@ -8742,7 +8850,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) args = (Scv13Args*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_scv; @@ -8764,6 +8872,10 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + wolfssl_priv_der_unblind(ssl->buffers.key, + ssl->buffers.keyMask); + #endif return 0; /* sent blank cert, can't verify */ } @@ -8786,9 +8898,9 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_BUILD: { - int rem = ssl->buffers.outputBuffer.bufferSize + int rem = (int)(ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length - - RECORD_HEADER_SZ - HANDSHAKE_HEADER_SZ; + - RECORD_HEADER_SZ - HANDSHAKE_HEADER_SZ); /* idx is used to track verify pointer offset to output */ args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; @@ -8813,11 +8925,10 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) } else { #ifdef WOLFSSL_DUAL_ALG_CERTS - if (wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && + if (ssl->sigSpec != NULL && *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) { /* In the case of alternative, we swap in the alt. */ - if (ssl->ctx->altPrivateKey == NULL) { + if (ssl->buffers.altKey == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_scv); } ssl->buffers.keyType = ssl->buffers.altKeyType; @@ -8825,26 +8936,29 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) /* If we own it, free key before overriding it. */ if (ssl->buffers.weOwnKey) { FreeDer(&ssl->buffers.key); + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + FreeDer(&ssl->buffers.keyMask); + #endif } - /* Transfer ownership. ssl->ctx always owns the alt private - * key. */ - ssl->buffers.key = ssl->ctx->altPrivateKey; - ssl->ctx->altPrivateKey = NULL; - ssl->buffers.weOwnKey = 1; - ssl->buffers.weOwnAltKey = 0; + /* Swap keys */ + ssl->buffers.key = ssl->buffers.altKey; + #ifdef WOLFSSL_BLIND_PRIVATE_KEY + ssl->buffers.keyMask = ssl->buffers.altKeyMask; + #endif + ssl->buffers.weOwnKey = ssl->buffers.weOwnAltKey; } #endif /* WOLFSSL_DUAL_ALG_CERTS */ - ret = DecodePrivateKey(ssl, &args->length); + ret = DecodePrivateKey(ssl, &args->sigLen); if (ret != 0) goto exit_scv; } - if (rem < 0 || args->length > rem) { + if (rem < 0 || (int)args->sigLen > rem) { ERROR_OUT(BUFFER_E, exit_scv); } - if (args->length == 0) { + if (args->sigLen == 0) { ERROR_OUT(NO_PRIVATE_KEY, exit_scv); } @@ -8872,8 +8986,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) else if (ssl->hsType == DYNAMIC_TYPE_ED448) args->sigAlgo = ed448_sa_algo; #endif - #if defined(HAVE_PQC) - #if defined(HAVE_FALCON) + #if defined(HAVE_FALCON) else if (ssl->hsType == DYNAMIC_TYPE_FALCON) { falcon_key* fkey = (falcon_key*)ssl->hsKey; byte level = 0; @@ -8890,8 +9003,8 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) ERROR_OUT(ALGO_ID_E, exit_scv); } } - #endif /* HAVE_FALCON */ - #if defined(HAVE_DILITHIUM) + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) else if (ssl->hsType == DYNAMIC_TYPE_DILITHIUM) { dilithium_key* fkey = (dilithium_key*)ssl->hsKey; byte level = 0; @@ -8911,13 +9024,12 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) ERROR_OUT(ALGO_ID_E, exit_scv); } } - #endif /* HAVE_DILITHIUM */ - #endif /* HAVE_PQC */ + #endif /* HAVE_DILITHIUM */ else { ERROR_OUT(ALGO_ID_E, exit_scv); } -#ifdef WOLFSSL_DUAL_ALG_CERTS + #ifdef WOLFSSL_DUAL_ALG_CERTS if (ssl->peerSigSpec == NULL) { /* The peer did not respond. We didn't send CKS or they don't * support it. Either way, we do not need to handle dual @@ -8926,8 +9038,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) ssl->sigSpecSz = 0; } - if (wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && + if (ssl->sigSpec != NULL && *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { /* The native was already decoded. Now we need to do the * alternative. Note that no swap was done because this case is @@ -8936,21 +9047,27 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) ERROR_OUT(NO_PRIVATE_KEY, exit_scv); } - if (ssl->buffers.altKeyType == falcon_level1_sa_algo || + /* After this call, args->altSigLen has the length we need for + * the alternative signature. */ + ret = DecodeAltPrivateKey(ssl, &args->altSigLen); + if (ret != 0) + goto exit_scv; + + if (ssl->buffers.altKeyType == ecc_dsa_sa_algo || + ssl->buffers.altKeyType == falcon_level1_sa_algo || ssl->buffers.altKeyType == falcon_level5_sa_algo || ssl->buffers.altKeyType == dilithium_level2_sa_algo || ssl->buffers.altKeyType == dilithium_level3_sa_algo || ssl->buffers.altKeyType == dilithium_level5_sa_algo) { args->altSigAlgo = ssl->buffers.altKeyType; } + else if (ssl->buffers.altKeyType == rsa_sa_algo && + ssl->hsAltType == DYNAMIC_TYPE_RSA) { + args->altSigAlgo = rsa_pss_sa_algo; + } else { ERROR_OUT(ALGO_ID_E, exit_scv); } - /* After this call, args->altSigLen has the length we need for - * the alternative signature. */ - ret = DecodeAltPrivateKey(ssl, &args->altSigLen); - if (ret != 0) - goto exit_scv; EncodeDualSigAlg(args->sigAlgo, args->altSigAlgo, args->verify); if (args->verify[0] == 0) { @@ -8958,57 +9075,79 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) } } else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ + #endif /* WOLFSSL_DUAL_ALG_CERTS */ EncodeSigAlg(ssl->options.hashAlgo, args->sigAlgo, args->verify); if (args->sigData == NULL) { - if (ssl->hsType == DYNAMIC_TYPE_RSA) { - int sigLen = MAX_SIG_DATA_SZ; - if (args->length > MAX_SIG_DATA_SZ) - sigLen = args->length; - args->sigData = (byte*)XMALLOC(sigLen, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); - } - else { - args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); + word32 sigLen = MAX_SIG_DATA_SZ; + if ((ssl->hsType == DYNAMIC_TYPE_RSA) && + (args->sigLen > MAX_SIG_DATA_SZ)) { + /* We store the RSA signature in the sigData buffer + * temporarily, hence its size must be fitting. */ + sigLen = args->sigLen; } + args->sigData = (byte*)XMALLOC(sigLen, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); if (args->sigData == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } } + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ssl->sigSpec != NULL) && + (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) && + (args->altSigData == NULL)) { + word32 sigLen = MAX_SIG_DATA_SZ; + if (ssl->hsAltType == DYNAMIC_TYPE_RSA && + args->altSigLen > MAX_SIG_DATA_SZ) { + /* We store the RSA signature in the sigData buffer + * temporarily, hence its size must be fitting. */ + sigLen = args->altSigLen; + } + args->altSigData = (byte*)XMALLOC(sigLen, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->altSigData == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ + /* Create the data to be signed. */ ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); if (ret != 0) goto exit_scv; + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ssl->sigSpec != NULL) && + (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH)) { + XMEMCPY(args->altSigData, args->sigData, args->sigDataSz); + args->altSigDataSz = args->sigDataSz; + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ + #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { /* build encoded signature buffer */ - sig->length = WC_MAX_DIGEST_SIZE; - sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); - if (sig->buffer == NULL) { + rsaSigBuf->length = WC_MAX_DIGEST_SIZE; + rsaSigBuf->buffer = (byte*)XMALLOC(rsaSigBuf->length, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (rsaSigBuf->buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } - ret = CreateRSAEncodedSig(sig->buffer, args->sigData, + ret = CreateRSAEncodedSig(rsaSigBuf->buffer, args->sigData, args->sigDataSz, args->sigAlgo, ssl->options.hashAlgo); if (ret < 0) goto exit_scv; - sig->length = ret; + rsaSigBuf->length = (unsigned int)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; + args->sigLen = args->sendSz - args->idx - HASH_SIG_SIZE - + VERIFY_HEADER; #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->buffers.keyType != sm2_sa_algo) #endif @@ -9028,7 +9167,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) if (ret < 0) { ERROR_OUT(ret, exit_scv); } - sig->length = ED25519_SIG_SIZE; + args->sigLen = ED25519_SIG_SIZE; } #endif /* HAVE_ED25519 */ #ifdef HAVE_ED448 @@ -9037,22 +9176,57 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) if (ret < 0) { ERROR_OUT(ret, exit_scv); } - sig->length = ED448_SIG_SIZE; + args->sigLen = ED448_SIG_SIZE; } #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) - #if defined(HAVE_FALCON) + #if defined(HAVE_FALCON) if (ssl->hsType == DYNAMIC_TYPE_FALCON) { - sig->length = FALCON_MAX_SIG_SIZE; + args->sigLen = FALCON_MAX_SIG_SIZE; } - #endif - #if defined(HAVE_DILITHIUM) + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) if (ssl->hsType == DYNAMIC_TYPE_DILITHIUM) { - sig->length = DILITHIUM_MAX_SIG_SIZE; + args->sigLen = DILITHIUM_MAX_SIG_SIZE; } - #endif - #endif /* HAVE_PQC */ + #endif /* HAVE_DILITHIUM */ + + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + + #ifndef NO_RSA + if (ssl->hsAltType == DYNAMIC_TYPE_RSA) { + /* build encoded signature buffer */ + rsaSigBuf->length = WC_MAX_DIGEST_SIZE; + rsaSigBuf->buffer = (byte*)XMALLOC(rsaSigBuf->length, + ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (rsaSigBuf->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + ret = CreateRSAEncodedSig(rsaSigBuf->buffer, + args->altSigData, args->altSigDataSz, + args->altSigAlgo, ssl->options.hashAlgo); + if (ret < 0) + goto exit_scv; + rsaSigBuf->length = ret; + ret = 0; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->hsAltType == DYNAMIC_TYPE_ECC) { + ret = CreateECCEncodedSig(args->altSigData, + args->altSigDataSz, ssl->options.hashAlgo); + if (ret < 0) + goto exit_scv; + args->altSigDataSz = (word16)ret; + ret = 0; + } + #endif /* HAVE_ECC */ + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -9061,21 +9235,30 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_DO: { + byte* sigOut = args->verify + HASH_SIG_SIZE + VERIFY_HEADER; + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + /* As we have two signatures in the message, we store + * the length of each before the actual signature. This + * is necessary, as we could have two algorithms with + * variable length signatures. */ + sigOut += OPAQUE16_LEN; + } + #endif #ifdef HAVE_ECC if (ssl->hsType == DYNAMIC_TYPE_ECC) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->buffers.keyType == sm2_sa_algo) { ret = Sm2wSm3Sign(ssl, TLS13_SM2_SIG_ID, TLS13_SM2_SIG_ID_SZ, args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - (word32*)&sig->length, (ecc_key*)ssl->hsKey, NULL); + sigOut, &args->sigLen, (ecc_key*)ssl->hsKey, NULL); } else #endif { ret = EccSign(ssl, args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - (word32*)&sig->length, (ecc_key*)ssl->hsKey, + sigOut, &args->sigLen, (ecc_key*)ssl->hsKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.key #else @@ -9083,127 +9266,60 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) #endif ); } - -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - if (ssl->hsAltType == DYNAMIC_TYPE_DILITHIUM) { - /* note the + sig->length; we are appending. */ - ret = wc_dilithium_sign_msg( - args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + - VERIFY_HEADER + sig->length, - (word32*)&args->altSigLen, - (dilithium_key*)ssl->hsAltKey, ssl->rng); - - } - else if (ssl->hsAltType == DYNAMIC_TYPE_FALCON) { - /* note the sig->length; we are appending. */ - ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + - VERIFY_HEADER + sig->length, - (word32*)&args->altSigLen, - (falcon_key*)ssl->hsAltKey, - ssl->rng); - } - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - args->length = (word16)sig->length; + args->length = (word16)args->sigLen; } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 if (ssl->hsType == DYNAMIC_TYPE_ED25519) { ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - (word32*)&sig->length, (ed25519_key*)ssl->hsKey, + sigOut, &args->sigLen, (ed25519_key*)ssl->hsKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.key #else NULL #endif ); - args->length = (word16)sig->length; + args->length = (word16)args->sigLen; } #endif #ifdef HAVE_ED448 if (ssl->hsType == DYNAMIC_TYPE_ED448) { ret = Ed448Sign(ssl, args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - (word32*)&sig->length, (ed448_key*)ssl->hsKey, + sigOut, &args->sigLen, (ed448_key*)ssl->hsKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.key #else NULL #endif ); - args->length = (word16)sig->length; + args->length = (word16)args->sigLen; } #endif - #if defined(HAVE_PQC) - #if defined(HAVE_FALCON) + #if defined(HAVE_FALCON) if (ssl->hsType == DYNAMIC_TYPE_FALCON) { ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + - VERIFY_HEADER, (word32*)&sig->length, + sigOut, &args->sigLen, (falcon_key*)ssl->hsKey, ssl->rng); - args->length = (word16)sig->length; + args->length = (word16)args->sigLen; } - #endif - #if defined(HAVE_DILITHIUM) + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) if (ssl->hsType == DYNAMIC_TYPE_DILITHIUM) { ret = wc_dilithium_sign_msg(args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + - VERIFY_HEADER, (word32*)&sig->length, + sigOut, &args->sigLen, (dilithium_key*)ssl->hsKey, ssl->rng); - args->length = (word16)sig->length; + args->length = (word16)args->sigLen; } - #endif - #endif /* HAVE_PQC */ + #endif /* HAVE_DILITHIUM */ #ifndef NO_RSA if (ssl->hsType == DYNAMIC_TYPE_RSA) { - ret = RsaSign(ssl, sig->buffer, (word32)sig->length, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, - args->sigAlgo, ssl->options.hashAlgo, - (RsaKey*)ssl->hsKey, - ssl->buffers.key - ); - -#ifdef WOLFSSL_DUAL_ALG_CERTS - /* In the case of RSA, we need to do the CKS both case here - * BEFORE args->sigData is overwritten!! We keep the sig - * separate and then append later so we don't interfere with the - * checks below. */ - if (wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - if (ssl->hsAltType == DYNAMIC_TYPE_DILITHIUM) { - /* note the + args->sigLen; we are appending. */ - ret = wc_dilithium_sign_msg(args->sigData, - args->sigDataSz, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER + - args->sigLen, - (word32*)&args->altSigLen, - (dilithium_key*)ssl->hsAltKey, ssl->rng); - } - else if (ssl->hsAltType == DYNAMIC_TYPE_FALCON) { - /* note the + args->sigLen; we are appending. */ - ret = wc_falcon_sign_msg(args->sigData, args->sigDataSz, - args->verify + HASH_SIG_SIZE + - VERIFY_HEADER + args->sigLen, - (word32*)&args->altSigLen, - (falcon_key*)ssl->hsAltKey, - ssl->rng); - } - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - + ret = RsaSign(ssl, rsaSigBuf->buffer, (word32)rsaSigBuf->length, + sigOut, &args->sigLen, args->sigAlgo, + ssl->options.hashAlgo, (RsaKey*)ssl->hsKey, + ssl->buffers.key); if (ret == 0) { args->length = (word16)args->sigLen; - - XMEMCPY(args->sigData, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - args->sigLen); + XMEMCPY(args->sigData, sigOut, args->sigLen); } } #endif /* !NO_RSA */ @@ -9213,10 +9329,76 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) goto exit_scv; } -#ifdef WOLFSSL_DUAL_ALG_CERTS - /* Add in length of the alt sig which will be appended to the sig */ - args->length += args->altSigLen; -#endif /* WOLFSSL_DUAL_ALG_CERTS */ + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + /* Add signature length for the first signature. */ + c16toa((word16)args->sigLen, sigOut - OPAQUE16_LEN); + args->length += OPAQUE16_LEN; + + /* Advance our pointer to where we store the alt signature. + * We also add additional space for the length field of the + * second signature. */ + sigOut += args->sigLen + OPAQUE16_LEN; + + /* Generate the alternative signature */ + #ifdef HAVE_ECC + if (ssl->hsAltType == DYNAMIC_TYPE_ECC) { + ret = EccSign(ssl, args->altSigData, args->altSigDataSz, + sigOut, &args->altSigLen, + (ecc_key*)ssl->hsAltKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.altKey + #else + NULL + #endif + ); + } + #endif /* HAVE_ECC */ + #ifndef NO_RSA + if (ssl->hsAltType == DYNAMIC_TYPE_RSA) { + ret = RsaSign(ssl, rsaSigBuf->buffer, + (word32)rsaSigBuf->length, sigOut, + &args->altSigLen, args->altSigAlgo, + ssl->options.hashAlgo, (RsaKey*)ssl->hsAltKey, + ssl->buffers.altKey); + + if (ret == 0) { + XMEMCPY(args->altSigData, sigOut, args->altSigLen); + } + } + #endif /* !NO_RSA */ + #if defined(HAVE_FALCON) + if (ssl->hsAltType == DYNAMIC_TYPE_FALCON) { + ret = wc_falcon_sign_msg(args->altSigData, + args->altSigDataSz, sigOut, + &args->altSigLen, + (falcon_key*)ssl->hsAltKey, + ssl->rng); + } + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) + if (ssl->hsAltType == DYNAMIC_TYPE_DILITHIUM) { + ret = wc_dilithium_sign_msg(args->altSigData, + args->altSigDataSz, sigOut, + &args->altSigLen, + (dilithium_key*)ssl->hsAltKey, + ssl->rng); + } + #endif /* HAVE_DILITHIUM */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Add signature length for the alternative signature. */ + c16toa((word16)args->altSigLen, sigOut - OPAQUE16_LEN); + + /* Add length of the alt sig to the total length */ + args->length += args->altSigLen + OPAQUE16_LEN; + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ /* Add signature length. */ c16toa(args->length, args->verify + HASH_SIG_SIZE); @@ -9232,38 +9414,72 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) if (ssl->hsType == DYNAMIC_TYPE_RSA) { /* check for signature faults */ ret = VerifyRsaSign(ssl, args->sigData, args->sigLen, - sig->buffer, (word32)sig->length, args->sigAlgo, + rsaSigBuf->buffer, (word32)rsaSigBuf->length, args->sigAlgo, ssl->options.hashAlgo, (RsaKey*)ssl->hsKey, - ssl->buffers.key - ); + ssl->buffers.key); + } + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH && + ssl->hsAltType == DYNAMIC_TYPE_RSA) { + /* check for signature faults */ + ret = VerifyRsaSign(ssl, args->altSigData, args->altSigLen, + rsaSigBuf->buffer, (word32)rsaSigBuf->length, + args->altSigAlgo, ssl->options.hashAlgo, + (RsaKey*)ssl->hsAltKey, ssl->buffers.altKey); } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ #endif /* !NO_RSA */ #if defined(HAVE_ECC) && defined(WOLFSSL_CHECK_SIG_FAULTS) if (ssl->hsType == DYNAMIC_TYPE_ECC) { + byte* sigOut = args->verify + HASH_SIG_SIZE + VERIFY_HEADER; + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + /* Add our length offset. */ + sigOut += OPAQUE16_LEN; + } + #endif #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->buffers.keyType == sm2_sa_algo) { ret = Sm2wSm3Verify(ssl, TLS13_SM2_SIG_ID, TLS13_SM2_SIG_ID_SZ, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - sig->length, args->sigData, args->sigDataSz, + sigOut, args->sigLen, args->sigData, args->sigDataSz, (ecc_key*)ssl->hsKey, NULL); } else #endif { - ret = EccVerify(ssl, - args->verify + HASH_SIG_SIZE + VERIFY_HEADER, - sig->length, args->sigData, args->sigDataSz, - (ecc_key*)ssl->hsKey, + ret = EccVerify(ssl, sigOut, args->sigLen, + args->sigData, args->sigDataSz, + (ecc_key*)ssl->hsKey, #ifdef HAVE_PK_CALLBACKS - ssl->buffers.key + ssl->buffers.key #else - NULL + NULL #endif - ); + ); } } - #endif + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH && + ssl->hsAltType == DYNAMIC_TYPE_ECC) { + /* check for signature faults */ + byte* sigOut = args->verify + HASH_SIG_SIZE + VERIFY_HEADER + + args->sigLen + OPAQUE16_LEN + OPAQUE16_LEN; + ret = EccVerify(ssl, sigOut, args->altSigLen, + args->altSigData, args->altSigDataSz, + (ecc_key*)ssl->hsAltKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.altKey + #else + NULL + #endif + ); + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ + #endif /* HAVE_ECC && WOLFSSL_CHECK_SIG_FAULTS */ /* Check for error */ if (ret != 0) { @@ -9282,7 +9498,7 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) VERIFY_HEADER, certificate_verify, ssl); args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + - args->length + HASH_SIG_SIZE + VERIFY_HEADER; + args->length + HASH_SIG_SIZE + VERIFY_HEADER; #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) args->sendSz += recordLayerHdrExtra + DTLS_HANDSHAKE_EXTRA; @@ -9346,13 +9562,22 @@ static int SendTls13CertificateVerify(WOLFSSL* ssl) } /* switch(ssl->options.asyncState) */ exit_scv: +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + if (ret == 0) { + ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key, + &ssl->buffers.keyMask); + } + else { + wolfssl_priv_der_unblind(ssl->buffers.key, ssl->buffers.keyMask); + } +#endif WOLFSSL_LEAVE("SendTls13CertificateVerify", ret); WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -9442,8 +9667,8 @@ typedef struct Dcv13Args { #ifdef WOLFSSL_DUAL_ALG_CERTS byte altSigAlgo; byte* altSigData; - word16 altSigDataSz; - word16 altSignatureSz; + word32 altSigDataSz; + word32 altSignatureSz; byte altPeerAuthGood; #endif } Dcv13Args; @@ -9466,6 +9691,59 @@ static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs) } #ifdef WOLFSSL_DUAL_ALG_CERTS +#ifndef NO_RSA +/* ssl->peerCert->sapkiDer is the alternative public key. Hopefully it is a + * RSA public key. Convert it into a usable public key. */ +static int decodeRsaKey(WOLFSSL* ssl) +{ + int keyRet; + word32 tmpIdx = 0; + + if (ssl->peerRsaKeyPresent) + return INVALID_PARAMETER; + + keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + if (keyRet != 0) + return PEER_KEY_ERROR; + + ssl->peerRsaKeyPresent = 1; + keyRet = wc_RsaPublicKeyDecode(ssl->peerCert.sapkiDer, &tmpIdx, + ssl->peerRsaKey, + ssl->peerCert.sapkiLen); + if (keyRet != 0) + return PEER_KEY_ERROR; + + return 0; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/* ssl->peerCert->sapkiDer is the alternative public key. Hopefully it is a + * ECC public key. Convert it into a usable public key. */ +static int decodeEccKey(WOLFSSL* ssl) +{ + int keyRet; + word32 tmpIdx = 0; + + if (ssl->peerEccDsaKeyPresent) + return INVALID_PARAMETER; + + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + if (keyRet != 0) + return PEER_KEY_ERROR; + + ssl->peerEccDsaKeyPresent = 1; + keyRet = wc_EccPublicKeyDecode(ssl->peerCert.sapkiDer, &tmpIdx, + ssl->peerEccDsaKey, + ssl->peerCert.sapkiLen); + if (keyRet != 0) + return PEER_KEY_ERROR; + + return 0; +} +#endif /* HAVE_ECC */ + +#ifdef HAVE_DILITHIUM /* ssl->peerCert->sapkiDer is the alternative public key. Hopefully it is a * dilithium public key. Convert it into a usable public key. */ static int decodeDilithiumKey(WOLFSSL* ssl, int level) @@ -9482,10 +9760,6 @@ static int decodeDilithiumKey(WOLFSSL* ssl, int level) return PEER_KEY_ERROR; ssl->peerDilithiumKeyPresent = 1; - keyRet = wc_dilithium_init(ssl->peerDilithiumKey); - if (keyRet != 0) - return PEER_KEY_ERROR; - keyRet = wc_dilithium_set_level(ssl->peerDilithiumKey, level); if (keyRet != 0) return PEER_KEY_ERROR; @@ -9498,7 +9772,9 @@ static int decodeDilithiumKey(WOLFSSL* ssl, int level) return 0; } +#endif /* HAVE_DILITHIUM */ +#ifdef HAVE_FALCON /* ssl->peerCert->sapkiDer is the alternative public key. Hopefully it is a * falcon public key. Convert it into a usable public key. */ static int decodeFalconKey(WOLFSSL* ssl, int level) @@ -9514,10 +9790,6 @@ static int decodeFalconKey(WOLFSSL* ssl, int level) return PEER_KEY_ERROR; ssl->peerFalconKeyPresent = 1; - keyRet = wc_falcon_init(ssl->peerFalconKey); - if (keyRet != 0) - return PEER_KEY_ERROR; - keyRet = wc_falcon_set_level(ssl->peerFalconKey, level); if (keyRet != 0) return PEER_KEY_ERROR; @@ -9530,7 +9802,8 @@ static int decodeFalconKey(WOLFSSL* ssl, int level) return 0; } -#endif +#endif /* HAVE_FALCON */ +#endif /* WOLFSSL_DUAL_ALG_CERTS */ /* handle processing TLS v1.3 certificate_verify (15) */ /* Parse and handle a TLS v1.3 CertificateVerify message. @@ -9547,7 +9820,11 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz) { int ret = 0; - buffer* sig = &ssl->buffers.sig; + byte* sig = NULL; +#ifndef NO_RSA + /* Use this as a temporary buffer for RSA signature verification. */ + buffer* rsaSigBuf = &ssl->buffers.sig; +#endif #ifdef WOLFSSL_ASYNC_CRYPT Dcv13Args* args = NULL; WOLFSSL_ASSERT_SIZEOF_GE(ssl->async->args, *args); @@ -9560,7 +9837,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #if defined(WOLFSSL_RENESAS_TSIP_TLS) ret = tsip_Tls13CertificateVerify(ssl, input, inOutIdx, totalSz); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { goto exit_dcv; } ret = 0; @@ -9577,7 +9854,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, args = (Dcv13Args*)ssl->async->args; ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) goto exit_dcv; @@ -9634,8 +9911,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, /* If no CKS extension or either native or alternative, then just * get a normal sigalgo. But if BOTH, then get the native and alt * sig algos. */ - if (wolfSSL_is_server(ssl) || - ssl->sigSpec == NULL || + if (ssl->sigSpec == NULL || *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_NATIVE || *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) { #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -9669,8 +9945,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } #ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - (ssl->sigSpec != NULL) && + if ((ssl->sigSpec != NULL) && (*ssl->sigSpec != WOLFSSL_CKS_SIGSPEC_NATIVE)) { word16 sa; @@ -9680,6 +9955,17 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, sa = args->altSigAlgo; switch(sa) { + #ifndef NO_RSA + case rsa_pss_sa_algo: + ret = decodeRsaKey(ssl); + break; + #endif + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + ret = decodeEccKey(ssl); + break; + #endif + #ifdef HAVE_DILITHIUM case dilithium_level2_sa_algo: ret = decodeDilithiumKey(ssl, 2); break; @@ -9689,70 +9975,62 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, case dilithium_level5_sa_algo: ret = decodeDilithiumKey(ssl, 5); break; + #endif + #ifdef HAVE_FALCON case falcon_level1_sa_algo: ret = decodeFalconKey(ssl, 1); break; case falcon_level5_sa_algo: ret = decodeFalconKey(ssl, 5); break; + #endif default: ERROR_OUT(PEER_KEY_ERROR, exit_dcv); - break; } if (ret != 0) ERROR_OUT(ret, exit_dcv); if (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_ALTERNATIVE) { - /* Now swap in the alternative. We only support hybrid certs - * where native is RSA or ECC so check that either of those - * are present and then remove it. */ - if (ssl->peerRsaKeyPresent && - ssl->peerEccDsaKeyPresent) { - /* They shouldn't both be present. */ - ERROR_OUT(PEER_KEY_ERROR, exit_dcv); - } - else if (ssl->peerRsaKeyPresent) { + /* Now swap in the alternative by removing the native. + * sa contains the alternative signature type. */ + #ifndef NO_RSA + if (ssl->peerRsaKeyPresent && sa != rsa_pss_sa_algo) { FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); ssl->peerRsaKeyPresent = 0; } - else if (ssl->peerEccDsaKeyPresent) { + #endif + #ifdef HAVE_ECC + else if (ssl->peerEccDsaKeyPresent && + sa != ecc_dsa_sa_algo) { FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); ssl->peerEccDsaKeyPresent = 0; } - else { - ERROR_OUT(WOLFSSL_NOT_IMPLEMENTED, exit_dcv); + #endif + #ifdef HAVE_DILITHIUM + else if (ssl->peerDilithiumKeyPresent && + sa != dilithium_level2_sa_algo && + sa != dilithium_level3_sa_algo && + sa != dilithium_level5_sa_algo) { + FreeKey(ssl, DYNAMIC_TYPE_DILITHIUM, + (void**)&ssl->peerDilithiumKey); + ssl->peerDilithiumKeyPresent = 0; } - } - else if (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - /* Use alternative public key to figure out the expected - * alt sig size. We only support Post-quantum key as SAPKI. - */ - switch(sa) { - case dilithium_level2_sa_algo: - case dilithium_level3_sa_algo: - case dilithium_level5_sa_algo: - ret = wc_dilithium_sig_size(ssl->peerDilithiumKey); - break; - case falcon_level1_sa_algo: - case falcon_level5_sa_algo: - ret = wc_falcon_sig_size(ssl->peerFalconKey); - break; - default: - ERROR_OUT(PEER_KEY_ERROR, exit_dcv); - break; + #endif + #ifdef HAVE_FALCON + else if (ssl->peerFalconKeyPresent && + sa != falcon_level1_sa_algo && + sa != falcon_level5_sa_algo) { + FreeKey(ssl, DYNAMIC_TYPE_FALCON, + (void**)&ssl->peerFalconKey); + ssl->peerFalconKeyPresent = 0; } - - if (ret <= 0) { + #endif + else { ERROR_OUT(PEER_KEY_ERROR, exit_dcv); } - args->altSignatureSz = ret; - ret = 0; - } - else { - ERROR_OUT(WOLFSSL_NOT_IMPLEMENTED, exit_dcv); } } #endif /* WOLFSSL_DUAL_ALG_CERTS */ @@ -9788,7 +10066,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ssl->peerEccDsaKeyPresent; } #endif - #ifdef HAVE_PQC + #ifdef HAVE_FALCON if (ssl->options.peerSigAlgo == falcon_level1_sa_algo) { WOLFSSL_MSG("Peer sent Falcon Level 1 sig"); validSigAlgo = (ssl->peerFalconKey != NULL) && @@ -9799,6 +10077,8 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, validSigAlgo = (ssl->peerFalconKey != NULL) && ssl->peerFalconKeyPresent; } + #endif + #ifdef HAVE_DILITHIUM if (ssl->options.peerSigAlgo == dilithium_level2_sa_algo) { WOLFSSL_MSG("Peer sent Dilithium Level 2 sig"); validSigAlgo = (ssl->peerDilithiumKey != NULL) && @@ -9831,61 +10111,89 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ERROR_OUT(SIG_VERIFY_E, exit_dcv); } - sig->length = args->sz; + args->sigSz = args->sz; #ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && + if (ssl->sigSpec != NULL && *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - /* If its RSA, we only hybridize with RSA3072 which has a sig - * size of 384. For ECC, this is actually encoded as an RFC5912 - * formatted signature which means we can use the ASN APIs to - * figure out the length. Note that some post-quantum sig algs - * have variable length signatures (Falcon). That is why we - * don't do: - * sig->length -= args->altSignatureSz; */ - #define RSA3072_SIG_LEN 384 - if (ssl->options.peerSigAlgo == rsa_pss_sa_algo) { - sig->length = RSA3072_SIG_LEN; - } - else if (ssl->options.peerSigAlgo == ecc_dsa_sa_algo) { - word32 tmpIdx = args->idx; - sig->length = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, - ssl->peerEccDsaKey, - sizeof(*ssl->peerEccDsaKey)); - if (GetSequence(input, &tmpIdx, (int*)&sig->length, - args->sz) < 0) { - ERROR_OUT(SIG_VERIFY_E, exit_dcv); - } - /* We have to increment by the size of the header. */ - sig->length += tmpIdx - args->idx; - } - else { - ERROR_OUT(WOLFSSL_NOT_IMPLEMENTED, exit_dcv); + /* In case we received two signatures, both of them are encoded + * with their size as 16-bit integeter prior in memory. Hence, + * we can decode both lengths here now. */ + word32 tmpIdx = args->idx; + word16 tmpSz = 0; + ato16(input + tmpIdx, &tmpSz); + args->sigSz = tmpSz; + + tmpIdx += OPAQUE16_LEN + args->sigSz; + ato16(input + tmpIdx, &tmpSz); + args->altSignatureSz = tmpSz; + + if (args->sz != (args->sigSz + args->altSignatureSz + + OPAQUE16_LEN + OPAQUE16_LEN)) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); } } -#endif +#endif /* WOLFSSL_DUAL_ALG_CERTS */ - sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap, + #if !defined(NO_RSA) && defined(WC_RSA_PSS) + /* In case we have to verify an RSA signature, we have to store the + * signature in the 'rsaSigBuf' structure for further processing. + */ + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + word32 sigSz = args->sigSz; + sig = input + args->idx; + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Check if our alternative signature was RSA */ + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + if (ssl->options.peerSigAlgo != rsa_pss_sa_algo) { + /* We have to skip the first signature (length field + * and signature itself) and the length field of the + * alternative signature. */ + sig += OPAQUE16_LEN + OPAQUE16_LEN + args->sigSz; + sigSz = args->altSignatureSz; + } + else { + /* We have to skip the length field */ + sig += OPAQUE16_LEN; + } + } + #endif + rsaSigBuf->buffer = (byte*)XMALLOC(sigSz, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (rsaSigBuf->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + rsaSigBuf->length = sigSz; + XMEMCPY(rsaSigBuf->buffer, sig, rsaSigBuf->length); + } + #endif /* !NO_RSA && WC_RSA_PSS */ - if (sig->buffer == NULL) { + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { ERROR_OUT(MEMORY_E, exit_dcv); } - XMEMCPY(sig->buffer, input + args->idx, sig->length); - #ifdef HAVE_ECC - if (ssl->peerEccDsaKeyPresent) { - WOLFSSL_MSG("Doing ECC peer cert verify"); + ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + if (ret < 0) + goto exit_dcv; - args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ssl->sigSpec != NULL) && + (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH)) { + args->altSigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, DYNAMIC_TYPE_SIGNATURE); - if (args->sigData == NULL) { + if (args->altSigData == NULL) { ERROR_OUT(MEMORY_E, exit_dcv); } + XMEMCPY(args->altSigData, args->sigData, args->sigDataSz); + args->altSigDataSz = args->sigDataSz; + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ - ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); - if (ret != 0) - goto exit_dcv; + #ifdef HAVE_ECC + if ((ssl->options.peerSigAlgo == ecc_dsa_sa_algo) && + (ssl->peerEccDsaKeyPresent)) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->options.peerSigAlgo != sm2_sa_algo) #endif @@ -9898,68 +10206,21 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, ret = 0; } } - #endif - #ifdef HAVE_ED25519 - if (ssl->peerEd25519KeyPresent) { - WOLFSSL_MSG("Doing ED25519 peer cert verify"); - - args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); - if (args->sigData == NULL) { - ERROR_OUT(MEMORY_E, exit_dcv); - } - - ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); - if (ret < 0) - goto exit_dcv; - } - #endif - #ifdef HAVE_ED448 - if (ssl->peerEd448KeyPresent) { - WOLFSSL_MSG("Doing ED448 peer cert verify"); - - args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); - if (args->sigData == NULL) { - ERROR_OUT(MEMORY_E, exit_dcv); - } - - ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); - if (ret < 0) - goto exit_dcv; - } - #endif - #ifdef HAVE_PQC - if (ssl->peerFalconKeyPresent || ssl->peerDilithiumKeyPresent) { - word16 sigDataSz; - byte *sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, - DYNAMIC_TYPE_SIGNATURE); - if (sigData == NULL) { - ERROR_OUT(MEMORY_E, exit_dcv); - } - - ret = CreateSigData(ssl, sigData, &sigDataSz, 1); - if (ret < 0) { - goto exit_dcv; - } -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - /* In this case (BOTH), the pq sig is the alternative. */ - args->altSigData = sigData; - args->altSigDataSz = sigDataSz; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - { - args->sigData = sigData; - args->sigDataSz = sigDataSz; - } - ret = 0; + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ssl->sigSpec != NULL) && + (*ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) && + (args->altSigAlgo == ecc_dsa_sa_algo) && + (ssl->peerEccDsaKeyPresent)) { + ret = CreateECCEncodedSig(args->altSigData, + args->altSigDataSz, ssl->options.peerHashAlgo); + if (ret < 0) + goto exit_dcv; + args->altSigDataSz = (word16)ret; + ret = 0; } - #endif + #endif /* WOLFSSL_DUAL_ALG_CERTS */ + #endif /* HAVE_ECC */ /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_DO; @@ -9968,35 +10229,52 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, case TLS_ASYNC_DO: { + sig = input + args->idx; + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + /* As we have two signatures in the message, we stored + * the length of each before the actual signature. This + * is necessary, as we could have two algorithms with + * variable length signatures. */ + sig += OPAQUE16_LEN; + } + #endif #ifndef NO_RSA - if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { - ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output, - ssl->options.peerSigAlgo, ssl->options.peerHashAlgo, ssl->peerRsaKey, + if ((ssl->options.peerSigAlgo == rsa_pss_sa_algo) && + (ssl->peerRsaKey != NULL) && (ssl->peerRsaKeyPresent != 0)) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + ret = RsaVerify(ssl, rsaSigBuf->buffer, + (word32)rsaSigBuf->length, &args->output, + ssl->options.peerSigAlgo, + ssl->options.peerHashAlgo, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS - &ssl->buffers.peerRsaKey + &ssl->buffers.peerRsaKey #else - NULL + NULL #endif - ); + ); if (ret >= 0) { - args->sendSz = ret; + args->sendSz = (word32)ret; ret = 0; } } #endif /* !NO_RSA */ #ifdef HAVE_ECC - if (ssl->peerEccDsaKeyPresent) { + if ((ssl->options.peerSigAlgo == ecc_dsa_sa_algo) && + (ssl->peerEccDsaKeyPresent)) { #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) if (ssl->options.peerSigAlgo == sm2_sa_algo) { ret = Sm2wSm3Verify(ssl, TLS13_SM2_SIG_ID, - TLS13_SM2_SIG_ID_SZ, input + args->idx, args->sz, + TLS13_SM2_SIG_ID_SZ, sig, args->sigSz, args->sigData, args->sigDataSz, ssl->peerEccDsaKey, NULL); } else #endif { - ret = EccVerify(ssl, input + args->idx, sig->length, + WOLFSSL_MSG("Doing ECC peer cert verify"); + ret = EccVerify(ssl, sig, args->sigSz, args->sigData, args->sigDataSz, ssl->peerEccDsaKey, #ifdef HAVE_PK_CALLBACKS @@ -10004,21 +10282,24 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #else NULL #endif - ); + ); } if (ret >= 0) { /* CLIENT/SERVER: data verified with public key from * certificate. */ ssl->options.peerAuthGood = 1; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); ssl->peerEccDsaKeyPresent = 0; } } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 - if (ssl->peerEd25519KeyPresent) { - ret = Ed25519Verify(ssl, input + args->idx, args->sz, + if ((ssl->options.peerSigAlgo == ed25519_sa_algo) && + (ssl->peerEd25519KeyPresent)) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + ret = Ed25519Verify(ssl, sig, args->sigSz, args->sigData, args->sigDataSz, ssl->peerEd25519Key, #ifdef HAVE_PK_CALLBACKS @@ -10026,7 +10307,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #else NULL #endif - ); + ); if (ret >= 0) { /* CLIENT/SERVER: data verified with public key from @@ -10039,8 +10320,10 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } #endif #ifdef HAVE_ED448 - if (ssl->peerEd448KeyPresent) { - ret = Ed448Verify(ssl, input + args->idx, args->sz, + if ((ssl->options.peerSigAlgo == ed448_sa_algo) && + (ssl->peerEd448KeyPresent)) { + WOLFSSL_MSG("Doing ED448 peer cert verify"); + ret = Ed448Verify(ssl, sig, args->sigSz, args->sigData, args->sigDataSz, ssl->peerEd448Key, #ifdef HAVE_PK_CALLBACKS @@ -10060,104 +10343,159 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, } } #endif - #if defined(HAVE_PQC) && defined(HAVE_FALCON) - if (ssl->peerFalconKeyPresent) { + #if defined(HAVE_FALCON) + if (((ssl->options.peerSigAlgo == falcon_level1_sa_algo) || + (ssl->options.peerSigAlgo == falcon_level5_sa_algo)) && + (ssl->peerFalconKeyPresent)) { int res = 0; - byte *sigIn = input + args->idx; - word32 sigInLen = args->sz; - byte *sigData = args->sigData; - word32 sigDataSz = args->sigDataSz; WOLFSSL_MSG("Doing Falcon peer cert verify"); -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - /* Note: + sig->length; we are skipping the native sig. */ - sigIn = input + args->idx + sig->length; - sigInLen = args->sz - sig->length; - - /* For RSA, something different was verified. */ - if (ssl->peerRsaKeyPresent) { - sigData = args->altSigData; - sigDataSz = args->altSigDataSz; - } - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - ret = wc_falcon_verify_msg(sigIn, sigInLen, - sigData, sigDataSz, + ret = wc_falcon_verify_msg(sig, args->sigSz, + args->sigData, args->sigDataSz, &res, ssl->peerFalconKey); if ((ret >= 0) && (res == 1)) { /* CLIENT/SERVER: data verified with public key from * certificate. */ -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - args->altPeerAuthGood = 1; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - ssl->options.peerAuthGood = 1; + ssl->options.peerAuthGood = 1; FreeKey(ssl, DYNAMIC_TYPE_FALCON, (void**)&ssl->peerFalconKey); ssl->peerFalconKeyPresent = 0; } } - #endif /* HAVE_PQC && HAVE_FALCON */ - #if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) - if (ssl->peerDilithiumKeyPresent) { + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_VERIFY) + if (((ssl->options.peerSigAlgo == dilithium_level2_sa_algo) || + (ssl->options.peerSigAlgo == dilithium_level3_sa_algo) || + (ssl->options.peerSigAlgo == dilithium_level5_sa_algo)) && + (ssl->peerDilithiumKeyPresent)) { int res = 0; - byte *sigIn = input + args->idx; - word32 sigInLen = args->sz; - byte *sigData = args->sigData; - word32 sigDataSz = args->sigDataSz; WOLFSSL_MSG("Doing Dilithium peer cert verify"); -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - /* Go backwards from the end of the signature the size of - * the alt sig to find the beginning of the alt sig. */ - sigIn = input + args->idx + args->sz - args->altSignatureSz; - sigInLen = args->altSignatureSz; - /* For RSA, something different was verified. */ - if (ssl->peerRsaKeyPresent) { - sigData = args->altSigData; - sigDataSz = args->altSigDataSz; - } - } -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - ret = wc_dilithium_verify_msg(sigIn, sigInLen, - sigData, sigDataSz, + ret = wc_dilithium_verify_msg(sig, args->sigSz, + args->sigData, args->sigDataSz, &res, ssl->peerDilithiumKey); if ((ret >= 0) && (res == 1)) { /* CLIENT/SERVER: data verified with public key from * certificate. */ -#ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->sigSpec != NULL && - *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { - args->altPeerAuthGood = 1; - } - else -#endif /* WOLFSSL_DUAL_ALG_CERTS */ - ssl->options.peerAuthGood = 1; + ssl->options.peerAuthGood = 1; FreeKey(ssl, DYNAMIC_TYPE_DILITHIUM, (void**)&ssl->peerDilithiumKey); ssl->peerDilithiumKeyPresent = 0; } } - #endif /* HAVE_PQC && HAVE_DILITHIUM */ + #endif /* HAVE_DILITHIUM */ /* Check for error */ if (ret != 0) { goto exit_dcv; } + #ifdef WOLFSSL_DUAL_ALG_CERTS + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { + /* Move forward to the alternative signature. */ + sig += args->sigSz + OPAQUE16_LEN; + + /* Verify the alternative signature */ + #ifndef NO_RSA + if ((args->altSigAlgo == rsa_pss_sa_algo) && + (ssl->peerRsaKey != NULL) && + (ssl->peerRsaKeyPresent != 0)) { + WOLFSSL_MSG("Doing RSA peer cert alt verify"); + ret = RsaVerify(ssl, rsaSigBuf->buffer, + (word32)rsaSigBuf->length, + &args->output, args->altSigAlgo, + ssl->options.peerHashAlgo, ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if ((args->altSigAlgo == ecc_dsa_sa_algo) && + (ssl->peerEccDsaKeyPresent)) { + WOLFSSL_MSG("Doing ECC peer cert alt verify"); + ret = EccVerify(ssl, sig, args->altSignatureSz, + args->altSigData, args->altSigDataSz, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEccDsaKey + #else + NULL + #endif + ); + + if (ret >= 0) { + /* CLIENT/SERVER: data verified with public key from + * certificate. */ + args->altPeerAuthGood = 1; + + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + } + #endif /* HAVE_ECC */ + #if defined(HAVE_FALCON) + if (((args->altSigAlgo == falcon_level1_sa_algo) || + (args->altSigAlgo == falcon_level5_sa_algo)) && + (ssl->peerFalconKeyPresent)) { + int res = 0; + WOLFSSL_MSG("Doing Falcon peer cert alt verify"); + ret = wc_falcon_verify_msg(sig, args->altSignatureSz, + args->altSigData, args->altSigDataSz, + &res, ssl->peerFalconKey); + + if ((ret >= 0) && (res == 1)) { + /* CLIENT/SERVER: data verified with public key from + * certificate. */ + args->altPeerAuthGood = 1; + + FreeKey(ssl, DYNAMIC_TYPE_FALCON, + (void**)&ssl->peerFalconKey); + ssl->peerFalconKeyPresent = 0; + } + } + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_VERIFY) + if (((args->altSigAlgo == dilithium_level2_sa_algo) || + (args->altSigAlgo == dilithium_level3_sa_algo) || + (args->altSigAlgo == dilithium_level5_sa_algo)) && + (ssl->peerDilithiumKeyPresent)) { + int res = 0; + WOLFSSL_MSG("Doing Dilithium peer cert alt verify"); + ret = wc_dilithium_verify_msg(sig, args->altSignatureSz, + args->altSigData, args->altSigDataSz, + &res, ssl->peerDilithiumKey); + + if ((ret >= 0) && (res == 1)) { + /* CLIENT/SERVER: data verified with public key from + * certificate. */ + args->altPeerAuthGood = 1; + + FreeKey(ssl, DYNAMIC_TYPE_DILITHIUM, + (void**)&ssl->peerDilithiumKey); + ssl->peerDilithiumKeyPresent = 0; + } + } + #endif /* HAVE_DILITHIUM */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcv; + } + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ + /* Advance state and proceed */ ssl->options.asyncState = TLS_ASYNC_VERIFY; } /* case TLS_ASYNC_DO */ @@ -10167,7 +10505,16 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, { #if !defined(NO_RSA) && defined(WC_RSA_PSS) if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { - ret = CheckRSASignature(ssl, ssl->options.peerSigAlgo, + int sigAlgo = ssl->options.peerSigAlgo; + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Check if our alternative signature was RSA */ + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH && + ssl->options.peerSigAlgo != rsa_pss_sa_algo) { + sigAlgo = args->altSigAlgo; + } + #endif + ret = CheckRSASignature(ssl, sigAlgo, ssl->options.peerHashAlgo, args->output, args->sendSz); if (ret != 0) goto exit_dcv; @@ -10176,7 +10523,16 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, * certificate. */ ssl->peerRsaKeyPresent = 0; FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); - ssl->options.peerAuthGood = 1; + #ifdef WOLFSSL_DUAL_ALG_CERTS + /* Check if our alternative signature was RSA */ + if (ssl->sigSpec != NULL && + *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH && + ssl->options.peerSigAlgo != rsa_pss_sa_algo) { + args->altPeerAuthGood = 1; + } + else + #endif + ssl->options.peerAuthGood = 1; } #endif /* !NO_RSA && WC_RSA_PSS */ @@ -10188,8 +10544,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, case TLS_ASYNC_FINALIZE: { #ifdef WOLFSSL_DUAL_ALG_CERTS - if (!wolfSSL_is_server(ssl) && - ssl->options.peerAuthGood && + if (ssl->options.peerAuthGood && ssl->sigSpec != NULL && *ssl->sigSpec == WOLFSSL_CKS_SIGSPEC_BOTH) { ssl->options.peerAuthGood = args->altPeerAuthGood; @@ -10230,7 +10585,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Mark message as not received so it can process again */ ssl->msgsReceived.got_certificate_verify = 0; @@ -10241,7 +10596,7 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, if (ret != 0) { WOLFSSL_ERROR_VERBOSE(ret); - if (ret != INVALID_PARAMETER) { + if (ret != WC_NO_ERR_TRACE(INVALID_PARAMETER)) { SendAlert(ssl, alert_fatal, decrypt_error); } } @@ -10315,11 +10670,11 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.serverState = SERVER_FINISHED_COMPLETE; return ret; } - if (ret == VERIFY_FINISHED_ERROR) { + if (ret == WC_NO_ERR_TRACE(VERIFY_FINISHED_ERROR)) { SendAlert(ssl, alert_fatal, decrypt_error); return ret; } - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { /* other errors */ return ret; } @@ -10487,12 +10842,12 @@ static int SendTls13Finished(WOLFSSL* ssl) input = output + Dtls13GetRlHeaderLength(ssl, 1); #endif /* WOLFSSL_DTLS13 */ - AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + AddTls13HandShakeHeader(input, (word32)finishedSz, 0, finishedSz, finished, ssl); #if defined(WOLFSSL_RENESAS_TSIP_TLS) if (ssl->options.side == WOLFSSL_CLIENT_END) { ret = tsip_Tls13SendFinished(ssl, output, outputSz, input, 1); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return ret; } ret = 0; @@ -10919,7 +11274,7 @@ static int SendTls13EndOfEarlyData(WOLFSSL* ssl) WOLFSSL_ENTER("SendTls13EndOfEarlyData"); length = 0; - sendSz = idx + length + MAX_MSG_EXTRA; + sendSz = (int)(idx + length + MAX_MSG_EXTRA); ssl->options.buildingMsg = 1; /* Check buffers are big enough and grow if needed. */ @@ -11329,7 +11684,7 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) } else #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { ssl->session->ticketNonce.data[0]++; @@ -11375,7 +11730,7 @@ static int SendTls13NewSessionTicket(WOLFSSL* ssl) /* Nonce */ length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ; - sendSz = idx + length + MAX_MSG_EXTRA; + sendSz = (int)(idx + length + MAX_MSG_EXTRA); /* Check buffers are big enough and grow if needed. */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) @@ -12009,7 +12364,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, /* sanity check msg received */ if ((ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { WOLFSSL_MSG("Sanity Check on handshake message type received failed"); - if (ret == VERSION_ERROR) + if (ret == WC_NO_ERR_TRACE(VERSION_ERROR)) SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version); else SendAlert(ssl, alert_fatal, unexpected_message); @@ -12117,7 +12472,8 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif ) { #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) - if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E) && + ret != WC_NO_ERR_TRACE(OCSP_WANT_READ)) #endif { ssl->options.cacheMessages = 0; @@ -12174,7 +12530,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ - defined(HAVE_ED448) || defined(HAVE_PQC) + defined(HAVE_ED448) || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) case certificate_verify: WOLFSSL_MSG("processing certificate verify"); ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); @@ -12206,7 +12562,8 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_ASYNC_IO) /* if async, offset index so this msg will be processed again */ /* NOTE: check this now before other calls can overwrite ret */ - if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) { + if ((ret == WC_NO_ERR_TRACE(WC_PENDING_E) || + ret == WC_NO_ERR_TRACE(OCSP_WANT_READ)) && *inOutIdx > 0) { /* DTLS always stores a message in a buffer when async is enable, so we * don't need to adjust for the extra bytes here (*inOutIdx is always * == 0) */ @@ -12214,13 +12571,15 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } /* make sure async error is cleared */ - if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) { + if (ret == 0 && + (ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) || + ssl->error == WC_NO_ERR_TRACE(OCSP_WANT_READ))) { ssl->error = 0; } #endif if (ret == 0 && type != client_hello && type != session_ticket && type != key_update) { - ret = HashInput(ssl, input + inIdx, size); + ret = HashInput(ssl, input + inIdx, (int)size); } alertType = TranslateErrorToAlert(ret); @@ -12233,7 +12592,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, tmp = SendAlert(ssl, alert_fatal, alertType); /* propagate socket error instead of tls error to be sure the error is * not ignored by DTLS code */ - if (tmp == SOCKET_ERROR_E) + if (tmp == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) ret = SOCKET_ERROR_E; } @@ -12330,7 +12689,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (wolfSSL_connect_TLSv13(ssl) != WOLFSSL_SUCCESS) { ret = ssl->error; - if (ret != WC_PENDING_E) + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) ret = POST_HAND_AUTH_ERROR; } } @@ -12475,7 +12834,7 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, ssl->arrays->pendingMsgSz); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* setup to process fragment again */ ssl->arrays->pendingMsgOffset -= inputLength; *inOutIdx -= inputLength + ssl->keys.padSz; @@ -12808,8 +13167,8 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl) case FIRST_REPLY_THIRD: #if (!defined(NO_CERTS) && (!defined(NO_RSA) || defined(HAVE_ECC) || \ defined(HAVE_ED25519) || defined(HAVE_ED448) || \ - defined(HAVE_PQC))) && (!defined(NO_WOLFSSL_SERVER) || \ - !defined(WOLFSSL_NO_CLIENT_AUTH)) + defined(HAVE_FALCON) || defined(HAVE_DILITHIUM))) && \ + (!defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH)) if (!ssl->options.resuming && ssl->options.sendVerify) { ssl->error = SendTls13CertificateVerify(ssl); if (ssl->error != 0) { @@ -13020,14 +13379,14 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfSSL_AsyncPop(ssl, NULL); - if (ret != WC_NO_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_NO_PENDING_E)) { /* Check for error */ if (ret < 0) return ret; } #endif -#ifdef HAVE_PQC +#if defined(WOLFSSL_HAVE_KYBER) if (WOLFSSL_NAMED_GROUP_IS_PQC(group)) { if (ssl->ctx != NULL && ssl->ctx->method != NULL && @@ -13036,10 +13395,11 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) } if (ssl->options.side == WOLFSSL_SERVER_END) { - /* If I am the server of a KEM connection, do not do keygen because I'm - * going to encapsulate with the client's public key. Note that I might - * be the client and ssl->option.side has not been properly set yet. In - * that case the KeyGen operation will be deferred to connection time. */ + /* If I am the server of a KEM connection, do not do keygen because + * I'm going to encapsulate with the client's public key. Note that + * I might be the client and ssl->option.side has not been properly + * set yet. In that case the KeyGen operation will be deferred to + * connection time. */ return WOLFSSL_SUCCESS; } } @@ -13389,86 +13749,6 @@ int wolfSSL_preferred_group(WOLFSSL* ssl) } #endif -#if defined(HAVE_SUPPORTED_CURVES) -/* Sets the key exchange groups in rank order on a context. - * - * ctx SSL/TLS context object. - * groups Array of groups. - * count Number of groups in array. - * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or - * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. - */ -int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) -{ - int ret, i; - - WOLFSSL_ENTER("wolfSSL_CTX_set_groups"); - if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) - return BAD_FUNC_ARG; - if (!IsAtLeastTLSv1_3(ctx->method->version)) - return BAD_FUNC_ARG; - - ctx->numGroups = 0; - #if !defined(NO_TLS) - TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); - #endif /* !NO_TLS */ - for (i = 0; i < count; i++) { - /* Call to wolfSSL_CTX_UseSupportedCurve also checks if input groups - * are valid */ - if ((ret = wolfSSL_CTX_UseSupportedCurve(ctx, (word16)groups[i])) - != WOLFSSL_SUCCESS) { - #if !defined(NO_TLS) - TLSX_Remove(&ctx->extensions, TLSX_SUPPORTED_GROUPS, ctx->heap); - #endif /* !NO_TLS */ - return ret; - } - ctx->group[i] = (word16)groups[i]; - } - ctx->numGroups = (byte)count; - - return WOLFSSL_SUCCESS; -} - -/* Sets the key exchange groups in rank order. - * - * ssl SSL/TLS object. - * groups Array of groups. - * count Number of groups in array. - * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or - * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. - */ -int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) -{ - int ret, i; - - WOLFSSL_ENTER("wolfSSL_set_groups"); - if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) - return BAD_FUNC_ARG; - if (!IsAtLeastTLSv1_3(ssl->version)) - return BAD_FUNC_ARG; - - ssl->numGroups = 0; - #if !defined(NO_TLS) - TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); - #endif /* !NO_TLS */ - for (i = 0; i < count; i++) { - /* Call to wolfSSL_UseSupportedCurve also checks if input groups - * are valid */ - if ((ret = wolfSSL_UseSupportedCurve(ssl, (word16)groups[i])) - != WOLFSSL_SUCCESS) { - #if !defined(NO_TLS) - TLSX_Remove(&ssl->extensions, TLSX_SUPPORTED_GROUPS, ssl->heap); - #endif /* !NO_TLS */ - return ret; - } - ssl->group[i] = (word16)groups[i]; - } - ssl->numGroups = (byte)count; - - return WOLFSSL_SUCCESS; -} -#endif /* HAVE_SUPPORTED_CURVES */ - #ifndef NO_PSK /* Set the PSK callback, that is passed the cipher suite, for a client to use * against context object. @@ -14030,7 +14310,8 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl) case TLS13_CERT_SENT : #if !defined(NO_CERTS) && (!defined(NO_RSA) || defined(HAVE_ECC) || \ - defined(HAVE_ED25519) || defined(HAVE_ED448) || defined(HAVE_PQC)) + defined(HAVE_ED25519) || defined(HAVE_ED448) || defined(HAVE_FALCON) || \ + defined(HAVE_DILITHIUM)) if (!ssl->options.resuming && ssl->options.sendVerify) { if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); @@ -14314,7 +14595,7 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) return SIDE_ERROR; if (ssl->options.handShakeState == NULL_STATE) { - if (ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) ssl->earlyData = expecting_early_data; ret = wolfSSL_connect_TLSv13(ssl); if (ret != WOLFSSL_SUCCESS) @@ -14378,7 +14659,7 @@ int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) return SIDE_ERROR; if (ssl->options.handShakeState == NULL_STATE) { - if (ssl->error != WC_PENDING_E) + if (ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E)) ssl->earlyData = expecting_early_data; /* this used to be: ret = wolfSSL_accept_TLSv13(ssl); * However, wolfSSL_accept_TLSv13() expects a certificate to @@ -14474,6 +14755,7 @@ int tls13ShowSecrets(WOLFSSL* ssl, int id, const unsigned char* secret, if (clientRandomSz <= 0) { printf("Error getting server random %d\n", clientRandomSz); + return BAD_FUNC_ARG; } #if 0 diff --git a/src/src/wolfio.c b/src/src/wolfio.c index 041e0b7..52e61a5 100644 --- a/src/src/wolfio.c +++ b/src/src/wolfio.c @@ -78,11 +78,15 @@ #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) \ && !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_WICED) \ && !defined(WOLFSSL_GNRC) && !defined(WOLFSSL_RIOT_OS) - #include + #ifdef HAVE_NETDB_H + #include + #endif #ifdef __PPU #include #else - #include + #ifdef HAVE_SYS_IOCTL_H + #include + #endif #endif #endif #endif @@ -149,6 +153,11 @@ static WC_INLINE int TranslateReturnCode(int old, int sd) if (errno == RTCSERR_TCP_TIMED_OUT) errno = SOCKET_EAGAIN; } +#elif defined(WOLFSSL_EMNET) + if (old < 0) { /* SOCKET_ERROR */ + /* Get the real socket error */ + IP_SOCK_getsockopt(sd, SOL_SOCKET, SO_ERROR, &old, (int)sizeof(old)); + } #endif return old; @@ -162,7 +171,7 @@ static WC_INLINE int wolfSSL_LastError(int err) return WSAGetLastError(); #elif defined(EBSNET) return xn_getlasterror(); -#elif defined(WOLFSSL_LINUXKM) +#elif defined(WOLFSSL_LINUXKM) || defined(WOLFSSL_EMNET) return err; /* Return provided error value */ #elif defined(FUSION_RTOS) #include @@ -554,7 +563,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) start = LowResTimer(); } else { - dtls_timeout -= LowResTimer() - start; + dtls_timeout -= (int) (LowResTimer() - start); start = LowResTimer(); if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX) return WOLFSSL_CBIO_ERR_TIMEOUT; @@ -604,7 +613,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) } #endif /* !NO_ASN_TIME */ - recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, + recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags, (SOCKADDR*)peer, peer != NULL ? &peerSz : NULL); /* From the RECV(2) man page @@ -712,7 +721,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) #endif } - sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, sz, ssl->wflags, + sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, (size_t)sz, ssl->wflags, (const SOCKADDR*)peer, peerSz); sent = TranslateReturnCode(sent, sd); @@ -739,7 +748,7 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedReceiveFromMcast"); - recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL); + recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags, NULL, NULL); recvd = TranslateReturnCode(recvd, sd); @@ -783,7 +792,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) if (sz > WC_SHA256_DIGEST_SIZE) sz = WC_SHA256_DIGEST_SIZE; - XMEMCPY(buf, digest, sz); + XMEMCPY(buf, digest, (size_t)sz); return sz; } @@ -977,7 +986,7 @@ int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) { int recvd; - recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags); + recvd = (int)RECV_FUNCTION(sd, buf, (size_t)sz, rdFlags); recvd = TranslateReturnCode(recvd, (int)sd); return recvd; @@ -987,7 +996,7 @@ int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) { int sent; - sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags); + sent = (int)SEND_FUNCTION(sd, buf, (size_t)sz, wrFlags); sent = TranslateReturnCode(sent, (int)sd); return sent; @@ -1079,9 +1088,9 @@ int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) } #endif /* HAVE_IO_TIMEOUT */ -static int wolfIO_Word16ToString(char* d, word16 number) +static word32 wolfIO_Word16ToString(char* d, word16 number) { - int i = 0; + word32 i = 0; word16 order = 10000; word16 digit; @@ -1096,7 +1105,7 @@ static int wolfIO_Word16ToString(char* d, word16 number) if (i > 0 || digit != 0) d[i++] = (char)digit + '0'; if (digit != 0) - number %= digit * order; + number = (word16) (number % (digit * order)); order = (order > 1) ? order / 10 : 0; } @@ -1111,7 +1120,7 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) #ifdef HAVE_SOCKADDR int ret = 0; SOCKADDR_S addr; - int sockaddr_len; + socklen_t sockaddr_len; #if defined(HAVE_GETADDRINFO) /* use getaddrinfo */ ADDRINFO hints; @@ -1175,7 +1184,7 @@ int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) } sockaddr_len = answer->ai_addrlen; - XMEMCPY(&addr, answer->ai_addr, sockaddr_len); + XMEMCPY(&addr, answer->ai_addr, (size_t)sockaddr_len); freeaddrinfo(answer); #elif defined(WOLFSSL_USE_POPEN_HOST) && !defined(WOLFSSL_IPV6) { @@ -1338,7 +1347,7 @@ int wolfIO_TcpBind(SOCKET_T* sockfd, word16 port) #ifdef HAVE_SOCKADDR int ret = 0; SOCKADDR_S addr; - int sockaddr_len = sizeof(SOCKADDR_IN); + socklen_t sockaddr_len = sizeof(SOCKADDR_IN); SOCKADDR_IN *sin = (SOCKADDR_IN *)&addr; if (sockfd == NULL || port < 1) { @@ -1469,7 +1478,7 @@ int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath, for (j = 0; j < i; j++) { if (port[j] < '0' || port[j] > '9') return -1; - bigPort = (bigPort * 10) + (port[j] - '0'); + bigPort = (bigPort * 10) + (word32)(port[j] - '0'); } if (outPort) *outPort = (word16)bigPort; @@ -1524,7 +1533,7 @@ static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, return MEMORY_E; } - newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType); + newRecvBuf = (byte*)XMALLOC((size_t)newRecvSz, heap, dynType); if (newRecvBuf == NULL) { WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed"); return MEMORY_E; @@ -1532,7 +1541,7 @@ static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, /* if buffer already exists, then we are growing it */ if (*recvBuf) { - XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz); + XMEMCPY(&newRecvBuf[pos], *recvBuf, (size_t) *recvBufSz); XFREE(*recvBuf, heap, dynType); pos += *recvBufSz; *recvBuf = NULL; @@ -1541,7 +1550,7 @@ static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, /* copy the remainder of the httpBuf into the respBuf */ if (len != 0) { if (pos + len <= newRecvSz) { - XMEMCPY(&newRecvBuf[pos], start, len); + XMEMCPY(&newRecvBuf[pos], start, (size_t)len); pos += len; } else { @@ -1603,6 +1612,11 @@ int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, /* read data if no \r\n or first time */ if ((start == NULL) || (end == NULL)) { + if (httpBufSz < len + 1) { + return BUFFER_ERROR; /* can't happen, but Coverity thinks it + * can. + */ + } result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); if (result > 0) { len += result; @@ -1625,7 +1639,7 @@ int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, /* handle incomplete rx */ if (end == NULL) { if (len != 0) - XMEMMOVE(httpBuf, start, len); + XMEMMOVE(httpBuf, start, (size_t)len); start = end = NULL; } /* when start is "\r\n" */ @@ -1751,7 +1765,7 @@ int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName, return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize); } - int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName, +int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName, const char *path, int pathLen, int reqSz, const char *contentType, const char *exHdrs, byte *buf, int bufSize) { @@ -1793,7 +1807,7 @@ int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName, maxLen = reqTypeLen + blankStrLen + - pathLen + + (word32)pathLen + http11StrLen + hostStrLen + domainNameLen + @@ -1804,46 +1818,46 @@ int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName, singleCrLfStrLen + exHdrsLen + doubleCrLfStrLen + - 1 /* null term */; + (word32)1 /* null term */; if (maxLen > (word32)bufSize) return 0; - XSTRNCPY((char*)buf, reqType, bufSize); - buf += reqTypeLen; bufSize -= reqTypeLen; - XSTRNCPY((char*)buf, blankStr, bufSize); - buf += blankStrLen; bufSize -= blankStrLen; - XSTRNCPY((char*)buf, path, bufSize); - buf += pathLen; bufSize -= pathLen; - XSTRNCPY((char*)buf, http11Str, bufSize); - buf += http11StrLen; bufSize -= http11StrLen; + XSTRNCPY((char*)buf, reqType, (size_t)bufSize); + buf += reqTypeLen; bufSize -= (int)reqTypeLen; + XSTRNCPY((char*)buf, blankStr, (size_t)bufSize); + buf += blankStrLen; bufSize -= (int)blankStrLen; + XSTRNCPY((char*)buf, path, (size_t)bufSize); + buf += pathLen; bufSize -= (int)pathLen; + XSTRNCPY((char*)buf, http11Str, (size_t)bufSize); + buf += http11StrLen; bufSize -= (int)http11StrLen; if (domainNameLen > 0) { - XSTRNCPY((char*)buf, hostStr, bufSize); - buf += hostStrLen; bufSize -= hostStrLen; - XSTRNCPY((char*)buf, domainName, bufSize); - buf += domainNameLen; bufSize -= domainNameLen; + XSTRNCPY((char*)buf, hostStr, (size_t)bufSize); + buf += hostStrLen; bufSize -= (int)hostStrLen; + XSTRNCPY((char*)buf, domainName, (size_t)bufSize); + buf += domainNameLen; bufSize -= (int)domainNameLen; } if (reqSz > 0 && reqSzStrLen > 0) { - XSTRNCPY((char*)buf, contentLenStr, bufSize); - buf += contentLenStrLen; bufSize -= contentLenStrLen; - XSTRNCPY((char*)buf, reqSzStr, bufSize); - buf += reqSzStrLen; bufSize -= reqSzStrLen; + XSTRNCPY((char*)buf, contentLenStr, (size_t)bufSize); + buf += contentLenStrLen; bufSize -= (int)contentLenStrLen; + XSTRNCPY((char*)buf, reqSzStr, (size_t)bufSize); + buf += reqSzStrLen; bufSize -= (int)reqSzStrLen; } if (contentTypeLen > 0) { - XSTRNCPY((char*)buf, contentTypeStr, bufSize); - buf += contentTypeStrLen; bufSize -= contentTypeStrLen; - XSTRNCPY((char*)buf, contentType, bufSize); - buf += contentTypeLen; bufSize -= contentTypeLen; + XSTRNCPY((char*)buf, contentTypeStr, (size_t)bufSize); + buf += contentTypeStrLen; bufSize -= (int)contentTypeStrLen; + XSTRNCPY((char*)buf, contentType, (size_t)bufSize); + buf += contentTypeLen; bufSize -= (int)contentTypeLen; } if (exHdrsLen > 0) { - XSTRNCPY((char *)buf, singleCrLfStr, bufSize); + XSTRNCPY((char *)buf, singleCrLfStr, (size_t)bufSize); buf += singleCrLfStrLen; - bufSize -= singleCrLfStrLen; - XSTRNCPY((char *)buf, exHdrs, bufSize); + bufSize -= (int)singleCrLfStrLen; + XSTRNCPY((char *)buf, exHdrs, (size_t)bufSize); buf += exHdrsLen; - bufSize -= exHdrsLen; + bufSize -= (int)exHdrsLen; } - XSTRNCPY((char*)buf, doubleCrLfStr, bufSize); + XSTRNCPY((char*)buf, doubleCrLfStr, (size_t)bufSize); buf += doubleCrLfStrLen; #ifdef WOLFIO_DEBUG @@ -1920,7 +1934,7 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, /* Note, the library uses the EmbedOcspRespFree() callback to * free this buffer. */ int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; - byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP); + byte* httpBuf = (byte*)XMALLOC((size_t)httpBufSz, ctx, DYNAMIC_TYPE_OCSP); if (httpBuf == NULL) { WOLFSSL_MSG("Unable to create OCSP response buffer"); @@ -2027,7 +2041,7 @@ int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) } else { int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; - byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap, + byte* httpBuf = (byte*)XMALLOC((size_t)httpBufSz, crl->heap, DYNAMIC_TYPE_CRL); if (httpBuf == NULL) { WOLFSSL_MSG("Unable to create CRL response buffer"); diff --git a/src/src/x509.c b/src/src/x509.c index eefa69c..72a4f37 100644 --- a/src/src/x509.c +++ b/src/src/x509.c @@ -177,19 +177,19 @@ int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert) goto out; } - if (GetLength(input, &idx, &length, sz) < 0) { + if (GetLength(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: invalid length"); goto out; } } - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); goto out; } while (idx < (word32)sz) { - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); FreeDecodedCert(cert); return WOLFSSL_FAILURE; @@ -643,7 +643,7 @@ static int wolfssl_dns_entry_othername_to_gn(DNS_entry* dns, wolfSSL_ASN1_OBJECT_free(obj); goto err; } - wolfSSL_ASN1_STRING_set(str, p, (word32)len); + wolfSSL_ASN1_STRING_set(str, p, (int)len); /* Wrap string in a WOLFSSL_ASN1_TYPE. */ type = wolfSSL_ASN1_TYPE_new(); @@ -839,7 +839,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) return NULL; } - if (GetLength(input, &idx, &length, sz) < 0) { + if (GetLength(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: invalid length"); wolfSSL_X509_EXTENSION_free(ext); FreeDecodedCert(cert); @@ -850,7 +850,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) } } - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); wolfSSL_X509_EXTENSION_free(ext); FreeDecodedCert(cert); @@ -863,7 +863,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) while (idx < (word32)sz) { oid = 0; - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); wolfSSL_X509_EXTENSION_free(ext); FreeDecodedCert(cert); @@ -874,7 +874,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) } tmpIdx = idx; - ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz); + ret = GetObjectId(input, &idx, &oid, oidCertExtType, (word32)sz); if (ret < 0) { WOLFSSL_MSG("\tfail: OBJECT ID"); wolfSSL_X509_EXTENSION_free(ext); @@ -895,11 +895,11 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) } /* extCount == loc. Now get the extension. */ /* Check if extension has been set */ - isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, nid); + isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, (int)nid); - if (wolfSSL_OBJ_nid2ln(nid) != NULL) { + if (wolfSSL_OBJ_nid2ln((int)nid) != NULL) { /* This is NOT an unknown OID. */ - ext->obj = wolfSSL_OBJ_nid2obj(nid); + ext->obj = wolfSSL_OBJ_nid2obj((int)nid); if (ext->obj == NULL) { WOLFSSL_MSG("\tfail: Invalid OBJECT"); wolfSSL_X509_EXTENSION_free(ext); @@ -912,7 +912,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) } if (ext->obj) { - ext->obj->nid = nid; + ext->obj->nid = (int)nid; } switch (oid) { @@ -929,7 +929,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) #endif return NULL; } - a->length = x509->pathLength; + a->length = (int)x509->pathLength; /* Save ASN1_INTEGER in x509 extension */ ext->obj->pathlen = a; @@ -972,7 +972,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) return NULL; } obj->obj = (byte*)x509->authInfoCaIssuer; - obj->objSz = x509->authInfoCaIssuerSz; + obj->objSz = (unsigned int)x509->authInfoCaIssuerSz; obj->grp = oidCertAuthInfoType; obj->nid = NID_ad_ca_issuers; @@ -1007,7 +1007,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) return NULL; } obj->obj = x509->authInfo; - obj->objSz = x509->authInfoSz; + obj->objSz = (unsigned int)x509->authInfoSz; obj->grp = oidCertAuthInfoType; obj->nid = NID_ad_OCSP; @@ -1132,7 +1132,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) * parsed oid for access in later function calls */ /* Get OID from input */ - if (GetASNObjectId(input, &idx, &length, sz) != 0) { + if (GetASNObjectId(input, &idx, &length, (word32)sz) != 0) { WOLFSSL_MSG("Failed to Get ASN Object Id"); wolfSSL_X509_EXTENSION_free(ext); FreeDecodedCert(cert); @@ -1171,7 +1171,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) } } - ext->obj->objSz = objSz; + ext->obj->objSz = (unsigned int)objSz; if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || (ext->obj->obj == NULL)) { ext->obj->obj =(byte*)XREALLOC((byte*)ext->obj->obj, @@ -1215,7 +1215,7 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) tmpIdx++; - if (GetLength(input, &tmpIdx, &length, sz) <= 0) { + if (GetLength(input, &tmpIdx, &length, (word32)sz) <= 0) { WOLFSSL_MSG("Error: Invalid Input Length."); wolfSSL_ASN1_OBJECT_free(ext->obj); wolfSSL_X509_EXTENSION_free(ext); @@ -1283,7 +1283,7 @@ static int asn1_string_copy_to_buffer(WOLFSSL_ASN1_STRING* str, byte** buf, WOLFSSL_MSG("malloc error"); return WOLFSSL_FAILURE; } - *len = str->length; + *len = (word32)str->length; XMEMCPY(*buf, str->data, str->length); } @@ -1418,7 +1418,7 @@ int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int lo x509->isCa = (byte)ext->obj->ca; x509->basicConstCrit = (byte)ext->crit; if (ext->obj->pathlen) - x509->pathLength = ext->obj->pathlen->length; + x509->pathLength = (word32)ext->obj->pathlen->length; x509->basicConstSet = 1; } break; @@ -1545,7 +1545,7 @@ int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, WOLFSSL_MSG("Memory error"); return rc; } - valLen = XSNPRINTF(val, len, "%*s%s", indent, "", + valLen = XSNPRINTF(val, (size_t)len, "%*s%s", indent, "", str->strData); if ((valLen < 0) || (valLen >= len) || ((tmpLen + valLen) >= tmpSz)) { @@ -2108,13 +2108,13 @@ int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) goto out; } - if (GetLength(input, &idx, &length, sz) < 0) { + if (GetLength(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: invalid length"); goto out; } } - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); goto out; } @@ -2122,13 +2122,13 @@ int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) while (idx < (word32)sz) { oid = 0; - if (GetSequence(input, &idx, &length, sz) < 0) { + if (GetSequence(input, &idx, &length, (word32)sz) < 0) { WOLFSSL_MSG("\tfail: should be a SEQUENCE"); goto out; } tmpIdx = idx; - ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz); + ret = GetObjectId(input, &idx, &oid, oidCertExtType, (word32)sz); if (ret < 0) { WOLFSSL_MSG("\tfail: OBJECT ID"); goto out; @@ -2138,7 +2138,7 @@ int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) if (extCount >= loc) { /* extCount >= loc. Now check if extension has been set */ - isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, foundNID); + isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, (int)foundNID); if (isSet && ((word32)nid == foundNID)) { found = 1; @@ -2218,7 +2218,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, wolfSSL_BASIC_CONSTRAINTS_free(bc); return NULL; } - a->length = x509->pathLength; + a->length = (int)x509->pathLength; #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \ defined(WOLFSSL_APACHE_HTTPD) @@ -2395,7 +2395,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, obj->type = AUTH_INFO_OID; obj->grp = oidCertExtType; obj->obj = x509->authInfo; - obj->objSz = x509->authInfoSz; + obj->objSz = (unsigned int)x509->authInfoSz; } else { WOLFSSL_MSG("No Auth Info set"); @@ -2684,7 +2684,7 @@ int wolfSSL_X509_add_altname_ex(WOLFSSL_X509* x509, const char* name, newAltName->next = x509->altNames; newAltName->type = type; - newAltName->len = nameSz; + newAltName->len = (int)nameSz; newAltName->name = nameCopy; x509->altNames = newAltName; @@ -3296,7 +3296,7 @@ char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) return NULL; } - copySz = min(sz, name->sz); + copySz = (int)min((word32)sz, (word32)name->sz); WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline"); if (!name->sz) return in; @@ -3362,7 +3362,7 @@ static unsigned long X509NameHash(WOLFSSL_X509_NAME* name, ((unsigned long)digest[1] << 8) | ((unsigned long)digest[0])); } - else if (rc == HASH_TYPE_E) { + else if (rc == WC_NO_ERR_TRACE(HASH_TYPE_E)) { WOLFSSL_ERROR_MSG("Hash function not compiled in"); } else { @@ -3500,7 +3500,7 @@ char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) WOLFSSL_MSG("Memory error"); return NULL; } - if ((strLen = XSNPRINTF(str, strSz, "%s=%s, ", sn, buf)) + if ((strLen = XSNPRINTF(str, (size_t)strSz, "%s=%s, ", sn, buf)) >= strSz) { WOLFSSL_MSG("buffer overrun"); @@ -3518,7 +3518,7 @@ char* wolfSSL_X509_get_name_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) WOLFSSL_MSG("Memory error"); return NULL; } - if ((strLen = XSNPRINTF(str, strSz, "%s=%s", sn, buf)) >= strSz) { + if ((strLen = XSNPRINTF(str, (size_t)strSz, "%s=%s", sn, buf)) >= strSz) { WOLFSSL_MSG("buffer overrun"); XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); return NULL; @@ -3608,11 +3608,11 @@ static WOLFSSL_X509* d2i_X509orX509REQ(WOLFSSL_X509** x509, return NULL; #endif - InitDecodedCert(cert, (byte*)in, len, heap); + InitDecodedCert(cert, (byte*)in, (word32)len, heap); #ifdef WOLFSSL_CERT_REQ cert->isCSR = (byte)req; #endif - if (ParseCertRelative(cert, type, 0, NULL) == 0) { + if (ParseCertRelative(cert, type, 0, NULL, NULL) == 0) { newX509 = wolfSSL_X509_new_ex(heap); if (newX509 != NULL) { if (CopyDecodedToX509(newX509, cert) != 0) { @@ -3732,7 +3732,7 @@ int wolfSSL_X509_get_signature(WOLFSSL_X509* x509, if (buf != NULL) XMEMCPY(buf, x509->sig.buffer, x509->sig.length); - *bufSz = x509->sig.length; + *bufSz = (int)x509->sig.length; return WOLFSSL_SUCCESS; } @@ -3780,7 +3780,7 @@ int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509* x509, der = wolfSSL_X509_get_der(x509, &derSz); if (der != NULL) { - InitDecodedCert(cert, der, derSz, NULL); + InitDecodedCert(cert, der, (word32)derSz, NULL); ret = wc_GetPubX509(cert, 0, &badDate); if (ret >= 0) { word32 idx = cert->srcIdx; @@ -3938,12 +3938,12 @@ const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509* x509, int* outSz) return NULL; } - if (GetSequence(der, &idx, &len, sz) < 0) { + if (GetSequence(der, &idx, &len, (word32)sz) < 0) { return NULL; } tbs = der + idx; tmpIdx = idx; - if (GetSequence(der, &idx, &len, sz) < 0) { + if (GetSequence(der, &idx, &len, (word32)sz) < 0) { return NULL; } *outSz = len + (idx - tmpIdx); @@ -5119,7 +5119,7 @@ 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, 1, sz, file); + int ret = (int)XFREAD(fileBuffer, 1, (size_t)sz, file); if (ret == sz) { newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); } @@ -5189,7 +5189,7 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) dynamic = 1; } - ret = (int)XFREAD(fileBuffer, 1, sz, file); + ret = (int)XFREAD(fileBuffer, 1, (size_t)sz, file); if (ret != sz) { XFCLOSE(file); if (dynamic) @@ -5254,7 +5254,7 @@ static WOLFSSL_X509* loadX509orX509REQFromBuffer( #endif { InitDecodedCert(cert, der->buffer, der->length, NULL); - ret = ParseCertRelative(cert, type, 0, NULL); + ret = ParseCertRelative(cert, type, 0, NULL, NULL); if (ret == 0) { x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, DYNAMIC_TYPE_X509); @@ -5451,7 +5451,7 @@ int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, /* buf is not NULL from above */ if (text != NULL) { - textSz = min(textSz + 1, len); /* + 1 to account for null char */ + textSz = (int)min((word32)textSz + 1, (word32)len); /* + 1 to account for null char */ if (textSz > 0) { XMEMCPY(buf, text, textSz - 1); buf[textSz - 1] = '\0'; @@ -5495,7 +5495,7 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) return NULL; } XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length); - key->pkey_sz = x509->pubKey.length; + key->pkey_sz = (int)x509->pubKey.length; #ifdef HAVE_ECC key->pkey_curve = (int)x509->pkCurveOID; @@ -5735,8 +5735,8 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) if (x509 != NULL) { if (x509->authKeyIdSet) { - copySz = min(dstLen != NULL ? *dstLen : 0, - (int)x509->authKeyIdSz); + copySz = (int)min(dstLen != NULL ? (word32)*dstLen : 0, + x509->authKeyIdSz); id = x509->authKeyId; } @@ -5762,8 +5762,8 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) if (x509 != NULL) { if (x509->subjKeyIdSet) { - copySz = min(dstLen != NULL ? *dstLen : 0, - (int)x509->subjKeyIdSz); + copySz = (int)min(dstLen != NULL ? (word32) *dstLen : 0, + x509->subjKeyIdSz); id = x509->subjKeyId; } @@ -7079,7 +7079,7 @@ void wolfSSL_X509_get0_signature(const WOLFSSL_ASN1_BIT_STRING **psig, #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) const char* wolfSSL_X509_verify_cert_error_string(long err) { - return wolfSSL_ERR_reason_error_string(err); + return wolfSSL_ERR_reason_error_string((unsigned long)err); } #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ @@ -7526,11 +7526,24 @@ int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out) int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) { int ret = 0; WOLFSSL_X509 *x = NULL; + byte certOwnsAltNames = 0; + byte certIsCSR = 0; if ((cert == NULL) || (der == NULL) || (derSz <= 0)) { return BAD_FUNC_ARG; } + /* The call to CopyDecodedToX509() transfers ownership of the altNames in + * the DecodedCert to the temporary X509 object, causing the list to be + * freed in wolfSSL_X509_free(). As this is an unintended side-effect, we + * have to save the ownerFlag here and transfer ownership back to the + * DecodedCert prior to freeing the X509 object. */ + certOwnsAltNames = cert->weOwnAltNames; + +#ifdef WOLFSSL_CERT_REQ + certIsCSR = cert->isCSR; +#endif + x = wolfSSL_X509_new(); if (x == NULL) { ret = MEMORY_E; @@ -7539,21 +7552,27 @@ int wc_GeneratePreTBS(DecodedCert* cert, byte *der, int derSz) { ret = CopyDecodedToX509(x, cert); } + /* CopyDecodedToX509() clears cert->weOwnAltNames. Restore it. */ + cert->weOwnAltNames = certOwnsAltNames; + if (ret == 0) { /* Remove the altsigval extension. */ XFREE(x->altSigValDer, x->heap, DYNAMIC_TYPE_X509_EXT); x->altSigValDer = NULL; - x->altSigValDer = 0; + x->altSigValLen = 0; /* Remove sigOID so it won't be encoded. */ x->sigOID = 0; /* We now have a PreTBS. Encode it. */ - ret = wolfssl_x509_make_der(x, 0, der, &derSz, 0); + ret = wolfssl_x509_make_der(x, certIsCSR, der, &derSz, 0); if (ret == WOLFSSL_SUCCESS) { ret = derSz; } } if (x != NULL) { + /* Safe the altNames list from being freed unitentionally. */ + x->altNames = NULL; + wolfSSL_X509_free(x); } @@ -7683,11 +7702,11 @@ static int verifyX509orX509REQ(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, int r #ifdef WOLFSSL_CERT_REQ if (req) - ret = CheckCSRSignaturePubKey(der, derSz, x509->heap, + ret = CheckCSRSignaturePubKey(der, (word32)derSz, x509->heap, (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type); else #endif - ret = CheckCertSignaturePubKey(der, derSz, x509->heap, + ret = CheckCertSignaturePubKey(der, (word32)derSz, x509->heap, (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type); if (ret == 0) { return WOLFSSL_SUCCESS; @@ -7739,7 +7758,7 @@ static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); if (fileBuffer != NULL) { - if ((long)XFREAD(fileBuffer, 1, sz, file) != sz) { + if ((long)XFREAD(fileBuffer, 1, (size_t)sz, file) != sz) { WOLFSSL_MSG("File read failed"); goto err_exit; } @@ -7761,7 +7780,7 @@ static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) if ((newx509 = wc_PKCS12_new()) == NULL) { goto err_exit; } - if (wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0) { + if (wc_d2i_PKCS12(fileBuffer, (word32)sz, (WC_PKCS12*)newx509) < 0) { goto err_exit; } } @@ -8217,7 +8236,8 @@ int wolfSSL_X509_CRL_get_signature(WOLFSSL_X509_CRL* crl, { WOLFSSL_ENTER("wolfSSL_X509_CRL_get_signature"); - if (crl == NULL || crl->crlList == NULL || bufSz == NULL) + if (crl == NULL || crl->crlList == NULL || + crl->crlList->signature == NULL || bufSz == NULL) return BAD_FUNC_ARG; if (buf != NULL) @@ -8408,7 +8428,7 @@ static int X509CRLPrintExtensions(WOLFSSL_BIO* bio, WOLFSSL_X509_CRL* crl, } tmp[0] = '\0'; } - if (XSNPRINTF(val, valSz, ":%02X", crl->crlList->extAuthKeyId[i]) + if (XSNPRINTF(val, (size_t)valSz, ":%02X", crl->crlList->extAuthKeyId[i]) >= valSz) { WOLFSSL_MSG("buffer overrun"); @@ -8794,7 +8814,7 @@ static int wolfSSL_X509_VERIFY_PARAM_inherit(WOLFSSL_X509_VERIFY_PARAM *to, if (isOverWrite || (from->hostName[0] != 0 && (to->hostName[0] == 0 || isDefault))) { if (!(ret = wolfSSL_X509_VERIFY_PARAM_set1_host(to, from->hostName, - (int)XSTRLEN(from->hostName)))) + (unsigned int)XSTRLEN(from->hostName)))) return ret; to->hostFlags = from->hostFlags; } @@ -9196,7 +9216,7 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) wolfSSL_ASN1_INTEGER_free(a); return NULL; } - a->dataMax = x509->serialSz + 2; + a->dataMax = (unsigned int)x509->serialSz + 2; a->isDynamic = 1; } else { /* Use array instead of dynamic memory */ @@ -9722,7 +9742,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( if (ret > 0) { /* strip off sequence, this gets added on certificate creation */ - ret = GetSequence(der, &idx, &length, ret); + ret = GetSequence(der, &idx, &length, (word32)ret); } if (ret > 0) { @@ -9765,7 +9785,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( #ifdef WOLFSSL_CERT_EXT if (req->subjKeyIdSz != 0) { XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz); - cert->skidSz = req->subjKeyIdSz; + cert->skidSz = (int)req->subjKeyIdSz; } if (req->keyUsageSet) cert->keyUsage = req->keyUsage; @@ -9847,7 +9867,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( } out[0] = (byte) t->type; - sz = SetLength(t->length, out + 1) + 1; /* gen tag */ + sz = (int)SetLength((word32)t->length, out + 1) + 1; /* gen tag */ for (i = 0; i < t->length; i++) { out[sz + i] = t->data[i]; } @@ -10171,6 +10191,15 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( #endif #ifndef NO_DSA DsaKey* dsa = NULL; + #endif + #if defined(HAVE_FALCON) + falcon_key* falcon = NULL; + #endif + #if defined(HAVE_DILITHIUM) + dilithium_key* dilithium = NULL; + #endif + #if defined(HAVE_SPHINCS) + sphincs_key* sphincs = NULL; #endif WC_RNG rng; word32 idx = 0; @@ -10297,6 +10326,148 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( } key = (void*)dsa; } + #endif + #if defined(HAVE_FALCON) + if ((x509->pubKeyOID == FALCON_LEVEL1k) || + (x509->pubKeyOID == FALCON_LEVEL5k)) { + falcon = (falcon_key*)XMALLOC(sizeof(falcon_key), NULL, + DYNAMIC_TYPE_FALCON); + if (falcon == NULL) { + WOLFSSL_MSG("Failed to allocate memory for falcon_key"); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return WOLFSSL_FAILURE; + } + + ret = wc_falcon_init(falcon); + if (ret != 0) { + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return ret; + } + + if (x509->pubKeyOID == FALCON_LEVEL1k) { + type = FALCON_LEVEL1_TYPE; + wc_falcon_set_level(falcon, 1); + } + else if (x509->pubKeyOID == FALCON_LEVEL5k) { + type = FALCON_LEVEL5_TYPE; + wc_falcon_set_level(falcon, 5); + } + + ret = wc_Falcon_PublicKeyDecode(x509->pubKey.buffer, &idx, falcon, + x509->pubKey.length); + if (ret != 0) { + WOLFSSL_ERROR_VERBOSE(ret); + wc_falcon_free(falcon); + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return ret; + } + key = (void*)falcon; + } + #endif + #if defined(HAVE_DILITHIUM) + if ((x509->pubKeyOID == DILITHIUM_LEVEL2k) || + (x509->pubKeyOID == DILITHIUM_LEVEL3k) || + (x509->pubKeyOID == DILITHIUM_LEVEL5k)) { + dilithium = (dilithium_key*)XMALLOC(sizeof(dilithium_key), NULL, + DYNAMIC_TYPE_DILITHIUM); + if (dilithium == NULL) { + WOLFSSL_MSG("Failed to allocate memory for dilithium_key"); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return WOLFSSL_FAILURE; + } + + ret = wc_dilithium_init(dilithium); + if (ret != 0) { + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return ret; + } + + if (x509->pubKeyOID == DILITHIUM_LEVEL2k) { + type = DILITHIUM_LEVEL2_TYPE; + wc_dilithium_set_level(dilithium, 2); + } + else if (x509->pubKeyOID == DILITHIUM_LEVEL3k) { + type = DILITHIUM_LEVEL3_TYPE; + wc_dilithium_set_level(dilithium, 3); + } + else if (x509->pubKeyOID == DILITHIUM_LEVEL5k) { + type = DILITHIUM_LEVEL5_TYPE; + wc_dilithium_set_level(dilithium, 5); + } + + ret = wc_Dilithium_PublicKeyDecode(x509->pubKey.buffer, &idx, + dilithium, x509->pubKey.length); + if (ret != 0) { + WOLFSSL_ERROR_VERBOSE(ret); + wc_dilithium_free(dilithium); + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return ret; + } + key = (void*)dilithium; + } + #endif + #if defined(HAVE_SPHINCS) + if ((x509->pubKeyOID == SPHINCS_FAST_LEVEL1k) || + (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) || + (x509->pubKeyOID == SPHINCS_FAST_LEVEL5k) || + (x509->pubKeyOID == SPHINCS_SMALL_LEVEL1k) || + (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) || + (x509->pubKeyOID == SPHINCS_SMALL_LEVEL5k)) { + sphincs = (sphincs_key*)XMALLOC(sizeof(sphincs_key), NULL, + DYNAMIC_TYPE_SPHINCS); + if (sphincs == NULL) { + WOLFSSL_MSG("Failed to allocate memory for sphincs_key"); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return WOLFSSL_FAILURE; + } + + ret = wc_sphincs_init(sphincs); + if (ret != 0) { + XFREE(sphincs, NULL, DYNAMIC_TYPE_SPHINCS); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return ret; + } + + if (x509->pubKeyOID == SPHINCS_FAST_LEVEL1k) { + type = SPHINCS_FAST_LEVEL1_TYPE; + wc_sphincs_set_level_and_optim(sphincs, 1, FAST_VARIANT); + } + else if (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) { + type = SPHINCS_FAST_LEVEL3_TYPE; + wc_sphincs_set_level_and_optim(sphincs, 3, FAST_VARIANT); + } + else if (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) { + type = SPHINCS_FAST_LEVEL5_TYPE; + wc_sphincs_set_level_and_optim(sphincs, 5, FAST_VARIANT); + } + else if (x509->pubKeyOID == SPHINCS_SMALL_LEVEL1k) { + type = SPHINCS_SMALL_LEVEL1_TYPE; + wc_sphincs_set_level_and_optim(sphincs, 1, SMALL_VARIANT); + } + else if (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) { + type = SPHINCS_SMALL_LEVEL3_TYPE; + wc_sphincs_set_level_and_optim(sphincs, 3, SMALL_VARIANT); + } + else if (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) { + type = SPHINCS_SMALL_LEVEL5_TYPE; + wc_sphincs_set_level_and_optim(sphincs, 5, SMALL_VARIANT); + } + + ret = wc_Sphincs_PublicKeyDecode(x509->pubKey.buffer, &idx, sphincs, + x509->pubKey.length); + if (ret != 0) { + WOLFSSL_ERROR_VERBOSE(ret); + wc_sphincs_free(sphincs); + XFREE(sphincs, NULL, DYNAMIC_TYPE_SPHINCS); + XFREE(cert, NULL, DYNAMIC_TYPE_CERT); + return ret; + } + key = (void*)sphincs; + } #endif if (key == NULL) { WOLFSSL_MSG("No public key found for certificate"); @@ -10397,6 +10568,32 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( wc_FreeDsaKey(dsa); XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); } + #endif + #if defined(HAVE_FALCON) + if ((x509->pubKeyOID == FALCON_LEVEL1k) || + (x509->pubKeyOID == FALCON_LEVEL5k)) { + wc_falcon_free(falcon); + XFREE(falcon, NULL, DYNAMIC_TYPE_FALCON); + } + #endif + #if defined(HAVE_DILITHIUM) + if ((x509->pubKeyOID == DILITHIUM_LEVEL2k) || + (x509->pubKeyOID == DILITHIUM_LEVEL3k) || + (x509->pubKeyOID == DILITHIUM_LEVEL5k)) { + wc_dilithium_free(dilithium); + XFREE(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); + } + #endif + #if defined(HAVE_SPHINCS) + if ((x509->pubKeyOID == SPHINCS_FAST_LEVEL1k) || + (x509->pubKeyOID == SPHINCS_FAST_LEVEL3k) || + (x509->pubKeyOID == SPHINCS_FAST_LEVEL5k) || + (x509->pubKeyOID == SPHINCS_SMALL_LEVEL1k) || + (x509->pubKeyOID == SPHINCS_SMALL_LEVEL3k) || + (x509->pubKeyOID == SPHINCS_SMALL_LEVEL5k)) { + wc_sphincs_free(sphincs); + XFREE(sphincs, NULL, DYNAMIC_TYPE_SPHINCS); + } #endif XFREE(cert, NULL, DYNAMIC_TYPE_CERT); @@ -10449,7 +10646,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( ret = wc_InitRng(&rng); if (ret != 0) return ret; - ret = wc_SignCert_ex(certBodySz, sigType, der, derSz, type, key, &rng); + ret = wc_SignCert_ex(certBodySz, sigType, der, (word32)derSz, type, key, &rng); wc_FreeRng(&rng); if (ret < 0) { WOLFSSL_LEAVE("wolfSSL_X509_resign_cert", ret); @@ -10463,20 +10660,20 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( int len = 0; /* Read top level sequence */ - if (GetSequence(der, &idx, &len, derSz) < 0) { + if (GetSequence(der, &idx, &len, (word32)derSz) < 0) { WOLFSSL_MSG("GetSequence error"); return WOLFSSL_FATAL_ERROR; } /* Move idx to signature */ idx += certBodySz; /* Read signature algo sequence */ - if (GetSequence(der, &idx, &len, derSz) < 0) { + if (GetSequence(der, &idx, &len, (word32)derSz) < 0) { WOLFSSL_MSG("GetSequence error"); return WOLFSSL_FATAL_ERROR; } idx += len; /* Read signature bit string */ - if (CheckBitString(der, &idx, &len, derSz, 0, NULL) != 0) { + if (CheckBitString(der, &idx, &len, (word32)derSz, 0, NULL) != 0) { WOLFSSL_MSG("CheckBitString error"); return WOLFSSL_FATAL_ERROR; } @@ -10495,7 +10692,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( return WOLFSSL_FATAL_ERROR; } XMEMCPY(x509->sig.buffer, der + idx, len); - x509->sig.length = len; + x509->sig.length = (unsigned int)len; } /* Put in the new certificate encoding into the x509 object. */ @@ -10506,10 +10703,10 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( type = CERTREQ_TYPE; } #endif - if (AllocDer(&x509->derCert, derSz, type, NULL) != 0) + if (AllocDer(&x509->derCert, (word32)derSz, type, NULL) != 0) return WOLFSSL_FATAL_ERROR; XMEMCPY(x509->derCert->buffer, der, derSz); - x509->derCert->length = derSz; + x509->derCert->length = (word32)derSz; return ret; } @@ -10833,7 +11030,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) } /* header */ - idx = SetSequence(totalBytes, temp); + idx = (int)SetSequence((word32)totalBytes, temp); if (totalBytes + idx > ASN_NAME_MAX) { #ifdef WOLFSSL_SMALL_STACK XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -10861,7 +11058,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) } output = *out; - idx = SetSequence(totalBytes, output); + idx = (int)SetSequence((word32)totalBytes, output); totalBytes += idx; for (i = 0; i < MAX_NAME_ENTRIES; i++) { if (names[i].used) { @@ -10982,7 +11179,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) _x = (x->name && *x->name) ? x->name : x->staticName; _y = (y->name && *y->name) ? y->name : y->staticName; - return XSTRNCMP(_x, _y, x->sz); /* y sz is the same */ + return XSTRNCASECMP(_x, _y, x->sz); /* y sz is the same */ } #ifndef NO_BIO @@ -11085,6 +11282,27 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) return loadX509orX509REQFromPemBio(bp, x, cb, u, CERT_TYPE); } + /* + * 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, wc_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 + * readability and does not support extra trusted/rejected uses for + * root CA. */ + return wolfSSL_PEM_read_bio_X509(bp, x, cb, u); + } + #ifdef WOLFSSL_CERT_REQ WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, wc_pem_password_cb *cb, void *u) @@ -11158,7 +11376,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) { goto err; } - derSz = der->length; + derSz = (int)der->length; if((crl = wolfSSL_d2i_X509_CRL(x, der->buffer, derSz)) == NULL) { goto err; } @@ -11231,7 +11449,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) if (pem == NULL) return NULL; - if ((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz) + if ((int)XFREAD((char *)pem, 1, (size_t)pemSz, fp) != pemSz) goto err_exit; switch (type) { @@ -11244,7 +11462,7 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) case CRL_TYPE: if ((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) goto err_exit; - derSz = der->length; + derSz = (int)der->length; newx509 = (void*)wolfSSL_d2i_X509_CRL((WOLFSSL_X509_CRL **)x, (const unsigned char *)der->buffer, derSz); if (newx509 == NULL) @@ -11480,8 +11698,9 @@ int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) "-----BEGIN X509 CRL-----")) { /* We have a crl */ WOLFSSL_MSG("Parsing crl"); - if((PemToDer((const unsigned char*) header, footerEnd - header, - CRL_TYPE, &der, NULL, NULL, NULL)) < 0) { + if((PemToDer((const unsigned char*) header, + (long)(footerEnd - header), CRL_TYPE, &der, NULL, NULL, + NULL)) < 0) { WOLFSSL_MSG("PemToDer error"); goto err; } @@ -11895,7 +12114,6 @@ WOLFSSL_ASN1_OBJECT* wolfSSL_X509_NAME_ENTRY_get_object( static int RebuildFullName(WOLFSSL_X509_NAME* name) { int totalLen = 0, i, idx, entryCount = 0; - char* fullName; if (name == NULL) return BAD_FUNC_ARG; @@ -11915,23 +12133,26 @@ WOLFSSL_ASN1_OBJECT* wolfSSL_X509_NAME_ENTRY_get_object( } } - fullName = (char*)XMALLOC(totalLen + 1, name->heap, DYNAMIC_TYPE_X509); - if (fullName == NULL) - return MEMORY_E; + if (name->dynamicName) { + XFREE(name->name, name->heap, DYNAMIC_TYPE_X509); + name->name = name->staticName; + name->dynamicName = 0; + } + + if (totalLen >= ASN_NAME_MAX) { + name->name = (char*)XMALLOC(totalLen + 1, name->heap, + DYNAMIC_TYPE_X509); + if (name->name == NULL) + return MEMORY_E; + name->dynamicName = 1; + } idx = 0; - entryCount = AddAllEntry(name, fullName, totalLen, &idx); - if (entryCount < 0) { - XFREE(fullName, name->heap, DYNAMIC_TYPE_X509); + entryCount = AddAllEntry(name, name->name, totalLen, &idx); + if (entryCount < 0) return entryCount; - } - if (name->dynamicName) { - XFREE(name->name, name->heap, DYNAMIC_TYPE_X509); - } - fullName[idx] = '\0'; - name->name = fullName; - name->dynamicName = 1; + name->name[idx] = '\0'; name->sz = idx + 1; /* size includes null terminator */ name->entrySz = entryCount; @@ -12208,7 +12429,7 @@ int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) } /* get PEM size */ - pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE); + pemSz = wc_DerToPemEx(der, (word32)derSz, NULL, 0, NULL, CERTREQ_TYPE); if (pemSz < 0) { return WOLFSSL_FAILURE; } @@ -12218,7 +12439,7 @@ int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) if (pem == NULL) { return WOLFSSL_FAILURE; } - if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) { + if (wc_DerToPemEx(der, (word32)derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) { XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); return WOLFSSL_FAILURE; } @@ -12258,7 +12479,7 @@ int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) } /* get PEM size */ - pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE); + pemSz = wc_DerToPemEx(der, (word32)derSz, NULL, 0, NULL, CERT_TYPE); if (pemSz < 0) { return WOLFSSL_FAILURE; } @@ -12268,7 +12489,7 @@ int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) if (pem == NULL) { return WOLFSSL_FAILURE; } - if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + if (wc_DerToPemEx(der, (word32)derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); return WOLFSSL_FAILURE; } @@ -12306,7 +12527,7 @@ int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) } /* get PEM size */ - pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE); + pemSz = wc_DerToPemEx(der, (word32)derSz, NULL, 0, NULL, CERT_TYPE); if (pemSz < 0) { goto error; } @@ -12316,7 +12537,7 @@ int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) if (pem == NULL) { goto error; } - if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + if (wc_DerToPemEx(der, (word32)derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { goto error; } @@ -12631,6 +12852,7 @@ WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( if (name == NULL || WOLFSSL_SUCCESS != wolfSSL_sk_X509_NAME_push(copy, name)) { WOLFSSL_MSG("Memory error"); wolfSSL_sk_X509_NAME_pop_free(copy, wolfSSL_X509_NAME_free); + wolfSSL_X509_NAME_free(name); return NULL; } } @@ -12752,6 +12974,14 @@ static int get_dn_attr_by_nid(int n, const char** buf) str = "UID"; len = 3; break; + case NID_serialNumber: + str = "serialNumber"; + len = 12; + break; + case NID_title: + str = "title"; + len = 5; + break; default: WOLFSSL_MSG("Attribute type not found"); str = NULL; @@ -12816,7 +13046,7 @@ static int wolfSSL_EscapeString_RFC2253(char* in, word32 inSz, } out[outIdx] = '\0'; - return outIdx; + return (int)outIdx; } /* @@ -12831,6 +13061,7 @@ static int wolfSSL_EscapeString_RFC2253(char* in, word32 inSz, * RFC22523 currently implemented. * XN_FLAG_DN_REV - print name reversed. Automatically done by * XN_FLAG_RFC2253. + * XN_FLAG_SPC_EQ - spaces before and after '=' character * * Returns WOLFSSL_SUCCESS (1) on success, WOLFSSL_FAILURE (0) on failure. */ @@ -12838,6 +13069,8 @@ int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, int indent, unsigned long flags) { int i, count = 0, nameStrSz = 0, escapeSz = 0; + int eqSpace = 0; + char eqStr[4]; char* tmp = NULL; char* nameStr = NULL; const char *buf = NULL; @@ -12850,6 +13083,15 @@ int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, if ((name == NULL) || (name->sz == 0) || (bio == NULL)) return WOLFSSL_FAILURE; + XMEMSET(eqStr, 0, sizeof(eqStr)); + if (flags & XN_FLAG_SPC_EQ) { + eqSpace = 2; + XSTRNCPY(eqStr, " = ", 4); + } + else { + XSTRNCPY(eqStr, "=", 4); + } + for (i = 0; i < indent; i++) { if (wolfSSL_BIO_write(bio, " ", 1) != 1) return WOLFSSL_FAILURE; @@ -12894,14 +13136,15 @@ int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, if (len == 0 || buf == NULL) return WOLFSSL_FAILURE; - tmpSz = nameStrSz + len + 4; /* + 4 for '=', comma space and '\0'*/ + /* + 4 for '=', comma space and '\0'*/ + tmpSz = nameStrSz + len + 4 + eqSpace; tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { return WOLFSSL_FAILURE; } if (i < count - 1) { - if (XSNPRINTF(tmp, tmpSz, "%s=%s, ", buf, nameStr) + if (XSNPRINTF(tmp, (size_t)tmpSz, "%s%s%s, ", buf, eqStr, nameStr) >= tmpSz) { WOLFSSL_MSG("buffer overrun"); @@ -12909,17 +13152,17 @@ int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, return WOLFSSL_FAILURE; } - tmpSz = len + nameStrSz + 3; /* 3 for '=', comma space */ + tmpSz = len + nameStrSz + 3 + eqSpace; /* 3 for '=', comma space */ } else { - if (XSNPRINTF(tmp, tmpSz, "%s=%s", buf, nameStr) + if (XSNPRINTF(tmp, (size_t)tmpSz, "%s%s%s", buf, eqStr, nameStr) >= tmpSz) { WOLFSSL_MSG("buffer overrun"); XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); return WOLFSSL_FAILURE; } - tmpSz = len + nameStrSz + 1; /* 1 for '=' */ + tmpSz = len + nameStrSz + 1 + eqSpace; /* 1 for '=' */ if (bio->type != WOLFSSL_BIO_FILE && bio->type != WOLFSSL_BIO_MEMORY) ++tmpSz; /* include the terminating null when not writing to a * file. @@ -13123,6 +13366,7 @@ int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, size_t chklen, unsigned int flags, char **peername) { int ret; + size_t i; #ifdef WOLFSSL_SMALL_STACK DecodedCert *dCert; #else @@ -13159,11 +13403,27 @@ int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, size_t chklen, #endif InitDecodedCert(dCert, x->derCert->buffer, x->derCert->length, NULL); - ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL); + ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL, NULL); if (ret != 0) { goto out; } + /* Replicate openssl behavior for checklen */ + if (chklen == 0) { + chklen = (size_t)(XSTRLEN(chk)); + } + else { + for (i = 0; i < (chklen > 1 ? chklen - 1 : chklen); i++) { + if (chk[i] == '\0') { + ret = -1; + goto out; + } + } + } + if (chklen > 1 && (chk[chklen - 1] == '\0')) { + chklen--; + } + ret = CheckHostName(dCert, (char *)chk, chklen); out: @@ -13214,7 +13474,7 @@ int wolfSSL_X509_check_ip_asc(WOLFSSL_X509 *x, const char *ipasc, if (ret == WOLFSSL_SUCCESS) { InitDecodedCert(dCert, x->derCert->buffer, x->derCert->length, NULL); - ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL); + ret = ParseCertRelative(dCert, CERT_TYPE, 0, NULL, NULL); if (ret != 0) { ret = WOLFSSL_FAILURE; } @@ -13353,7 +13613,7 @@ static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, /* Use existing CA retrieval APIs that use DecodedCert. */ InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, cm->heap); - if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0 + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL, NULL) == 0 && !cert->selfSigned) { #ifndef NO_SKID if (cert->extAuthKeyIdSet) @@ -13516,7 +13776,7 @@ int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509 *x) if (x == NULL) return 0; - return oid2nid(x->sigOID, oidSigType); + return oid2nid((word32)x->sigOID, oidSigType); } #endif /* OPENSSL_EXTRA */ @@ -13700,6 +13960,16 @@ int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t) return WOLFSSL_SUCCESS; } +int wolfSSL_X509_set1_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME *t) +{ + return wolfSSL_X509_set_notAfter(x509, t); +} + +int wolfSSL_X509_set1_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME *t) +{ + return wolfSSL_X509_set_notBefore(x509, t); +} + int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s) { WOLFSSL_ENTER("wolfSSL_X509_set_serialNumber"); @@ -13748,7 +14018,7 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) if (p == NULL) return WOLFSSL_FAILURE; - if ((derSz = wc_RsaKeyToPublicDer(rsa, p, derSz)) <= 0) { + if ((derSz = wc_RsaKeyToPublicDer(rsa, p, (word32)derSz)) <= 0) { XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); return WOLFSSL_FAILURE; } @@ -13772,7 +14042,7 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) if (p == NULL) return WOLFSSL_FAILURE; - if ((derSz = wc_DsaKeyToPublicDer(dsa, p, derSz)) <= 0) { + if ((derSz = wc_DsaKeyToPublicDer(dsa, p, (word32)derSz)) <= 0) { XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); return WOLFSSL_FAILURE; } @@ -13797,7 +14067,7 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) if (p == NULL) return WOLFSSL_FAILURE; - if ((derSz = wc_EccPublicKeyToDer(ecc, p, derSz, 1)) <= 0) { + if ((derSz = wc_EccPublicKeyToDer(ecc, p, (word32)derSz, 1)) <= 0) { XFREE(p, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); return WOLFSSL_FAILURE; } @@ -13809,7 +14079,7 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) return WOLFSSL_FAILURE; } cert->pubKey.buffer = p; - cert->pubKey.length = derSz; + cert->pubKey.length = (unsigned int)derSz; return WOLFSSL_SUCCESS; } @@ -14014,7 +14284,7 @@ static int regenX509REQDerBuffer(WOLFSSL_X509* x509) if (wolfssl_x509_make_der(x509, 1, der, &derSz, 0) == WOLFSSL_SUCCESS) { FreeDer(&x509->derCert); - if (AllocDer(&x509->derCert, derSz, CERT_TYPE, x509->heap) == 0) { + if (AllocDer(&x509->derCert, (word32)derSz, CERT_TYPE, x509->heap) == 0) { XMEMCPY(x509->derCert->buffer, der, derSz); ret = WOLFSSL_SUCCESS; } @@ -14353,7 +14623,7 @@ void wolfSSL_X509_ATTRIBUTE_free(WOLFSSL_X509_ATTRIBUTE* attr) } #endif -#endif /* !NO_CERT */ +#endif /* !NO_CERTS */ #endif /* !WOLFCRYPT_ONLY */ diff --git a/src/src/x509_str.c b/src/src/x509_str.c index a38f93b..f5c5c2a 100644 --- a/src/src/x509_str.c +++ b/src/src/x509_str.c @@ -40,27 +40,59 @@ * START OF X509_STORE_CTX APIs ******************************************************************************/ -#ifdef OPENSSL_EXTRA - -WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void) +/* This API is necessary outside of OPENSSL_EXTRA because it is used in + * SetupStoreCtxCallback */ +WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new_ex(void* heap) { WOLFSSL_X509_STORE_CTX* ctx; - WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_new"); + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_new_ex"); - ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), NULL, + ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), heap, DYNAMIC_TYPE_X509_CTX); if (ctx != NULL) { - ctx->param = NULL; + XMEMSET(ctx, 0, sizeof(WOLFSSL_X509_STORE_CTX)); + ctx->heap = heap; +#ifdef OPENSSL_EXTRA if (wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL) != WOLFSSL_SUCCESS) { - XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); + XFREE(ctx, heap, DYNAMIC_TYPE_X509_CTX); ctx = NULL; } +#endif } return ctx; } +/* This API is necessary outside of OPENSSL_EXTRA because it is used in + * SetupStoreCtxCallback */ +/* free's extra data */ +void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_free"); + if (ctx != NULL) { +#ifdef HAVE_EX_DATA_CLEANUP_HOOKS + wolfSSL_CRYPTO_cleanup_ex_data(&ctx->ex_data); +#endif + +#ifdef OPENSSL_EXTRA + if (ctx->param != NULL) { + XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); + ctx->param = NULL; + } +#endif + + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_X509_CTX); + } +} + +#ifdef OPENSSL_EXTRA + +WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_new"); + return wolfSSL_X509_STORE_CTX_new_ex(NULL); +} int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, @@ -134,11 +166,12 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, if (ctx->param == NULL) { ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( sizeof(WOLFSSL_X509_VERIFY_PARAM), - NULL, DYNAMIC_TYPE_OPENSSL); + ctx->heap, DYNAMIC_TYPE_OPENSSL); if (ctx->param == NULL){ WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed"); return WOLFSSL_FAILURE; } + XMEMSET(ctx->param, 0, sizeof(*ctx->param)); } return WOLFSSL_SUCCESS; @@ -146,25 +179,6 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, return WOLFSSL_FAILURE; } - -/* free's extra data */ -void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) -{ - WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_free"); - if (ctx != NULL) { -#ifdef HAVE_EX_DATA_CLEANUP_HOOKS - wolfSSL_CRYPTO_cleanup_ex_data(&ctx->ex_data); -#endif - - if (ctx->param != NULL) { - XFREE(ctx->param, NULL, DYNAMIC_TYPE_OPENSSL); - ctx->param = NULL; - } - - XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); - } -} - /* Its recommended to use a full free -> init cycle of all the objects * because wolfSSL_X509_STORE_CTX_init may modify the store too which doesn't * get reset here. */ @@ -173,7 +187,7 @@ void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx) if (ctx != NULL) { if (ctx->param != NULL) { - XFREE(ctx->param, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); ctx->param = NULL; } @@ -194,24 +208,27 @@ void wolfSSL_X509_STORE_CTX_trusted_stack(WOLFSSL_X509_STORE_CTX *ctx, WOLF_STAC int GetX509Error(int e) { switch (e) { - case ASN_BEFORE_DATE_E: + case WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E): return WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID; - case ASN_AFTER_DATE_E: + case WC_NO_ERR_TRACE(ASN_AFTER_DATE_E): return WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED; - case ASN_NO_SIGNER_E: /* get issuer error if no CA found locally */ + case WC_NO_ERR_TRACE(ASN_NO_SIGNER_E): + /* get issuer error if no CA found locally */ return WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; - case ASN_SELF_SIGNED_E: + case WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E): return WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - case ASN_PATHLEN_INV_E: - case ASN_PATHLEN_SIZE_E: + case WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E): + case WC_NO_ERR_TRACE(ASN_PATHLEN_SIZE_E): return WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED; - case ASN_SIG_OID_E: - case ASN_SIG_CONFIRM_E: - case ASN_SIG_HASH_E: - case ASN_SIG_KEY_E: + case WC_NO_ERR_TRACE(ASN_SIG_OID_E): + case WC_NO_ERR_TRACE(ASN_SIG_CONFIRM_E): + case WC_NO_ERR_TRACE(ASN_SIG_HASH_E): + case WC_NO_ERR_TRACE(ASN_SIG_KEY_E): return WOLFSSL_X509_V_ERR_CERT_SIGNATURE_FAILURE; - case CRL_CERT_REVOKED: + case WC_NO_ERR_TRACE(CRL_CERT_REVOKED): return WOLFSSL_X509_V_ERR_CERT_REVOKED; + case WC_NO_ERR_TRACE(CRL_MISSING): + return X509_V_ERR_UNABLE_TO_GET_CRL; case 0: case 1: return 0; @@ -254,7 +271,8 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) SetupStoreCtxError(ctx, ret); #ifndef NO_ASN_TIME - if (ret != ASN_BEFORE_DATE_E && ret != ASN_AFTER_DATE_E) { + if (ret != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) && + ret != WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { /* wolfSSL_CertManagerVerifyBuffer only returns ASN_AFTER_DATE_E or ASN_BEFORE_DATE_E if there are no additional errors found in the cert. Therefore, check if the cert is expired or not yet valid @@ -504,39 +522,19 @@ WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) /* if chain is null but sesChain is available then populate stack */ if (ctx->chain == NULL && ctx->sesChain != NULL) { int i; + int error = 0; WOLFSSL_X509_CHAIN* c = ctx->sesChain; - WOLFSSL_STACK* sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), - NULL, DYNAMIC_TYPE_X509); + WOLFSSL_STACK* sk = wolfSSL_sk_new_node(ctx->heap); - if (sk == NULL) { + if (sk == NULL) return NULL; - } - - XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); - - for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) { - WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i); - - if (x509 == NULL) { - WOLFSSL_MSG("Unable to get x509 from chain"); - wolfSSL_sk_X509_pop_free(sk, NULL); - return NULL; - } - - if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Unable to load x509 into stack"); - wolfSSL_sk_X509_pop_free(sk, NULL); - wolfSSL_X509_free(x509); - return NULL; - } - } #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) /* add CA used to verify top of chain to the list */ if (c->count > 0) { WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1); + WOLFSSL_X509* issuer = NULL; if (x509 != NULL) { - WOLFSSL_X509* issuer = NULL; if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509) == WOLFSSL_SUCCESS) { /* check that the certificate being looked up is not self @@ -545,24 +543,47 @@ WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) &x509->subject) != 0) { if (wolfSSL_sk_X509_push(sk, issuer) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Unable to load CA x509 into stack"); - wolfSSL_sk_X509_pop_free(sk, NULL); - wolfSSL_X509_free(issuer); - return NULL; + error = 1; } } else { WOLFSSL_MSG("Certificate is self signed"); - if (issuer != NULL) - wolfSSL_X509_free(issuer); + wolfSSL_X509_free(issuer); } } else { - wolfSSL_X509_free(x509); WOLFSSL_MSG("Could not find CA for certificate"); } } + wolfSSL_X509_free(x509); + if (error) { + wolfSSL_sk_X509_pop_free(sk, NULL); + wolfSSL_X509_free(issuer); + return NULL; + } } #endif + + for (i = c->count - 1; i >= 0; i--) { + WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i); + + if (x509 == NULL) { + WOLFSSL_MSG("Unable to get x509 from chain"); + error = 1; + break; + } + + if (wolfSSL_sk_X509_push(sk, x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to load x509 into stack"); + wolfSSL_X509_free(x509); + error = 1; + break; + } + } + if (error) { + wolfSSL_sk_X509_pop_free(sk, NULL); + return NULL; + } ctx->chain = sk; } #endif /* SESSION_CERTS */ @@ -611,6 +632,14 @@ int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, } #endif +WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_CTX_get0_param( + WOLFSSL_X509_STORE_CTX *ctx) +{ + if (ctx == NULL) + return NULL; + + return ctx->param; +} #endif /* OPENSSL_EXTRA */ @@ -935,14 +964,33 @@ int wolfSSL_X509_STORE_set_ex_data_with_cleanup( #ifdef OPENSSL_EXTRA #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, - WOLFSSL_X509_STORE_CTX_verify_cb verify_cb) - { - WOLFSSL_ENTER("wolfSSL_X509_STORE_set_verify_cb"); - if (st != NULL) { - st->verify_cb = verify_cb; - } +void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_verify_cb"); + if (st != NULL) { + st->verify_cb = verify_cb; } +} + +void wolfSSL_X509_STORE_set_get_crl(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_get_crl_cb get_cb) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_get_crl"); + if (st != NULL) { + st->get_crl_cb = get_cb; + } +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_X509_STORE_set_check_crl(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_check_crl_cb check_crl) +{ + (void)st; + (void)check_crl; + WOLFSSL_STUB("wolfSSL_X509_STORE_set_check_crl (not implemented)"); +} +#endif #endif /* WOLFSSL_QT || OPENSSL_ALL */ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, @@ -1328,6 +1376,17 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( } #endif /* OPENSSL_ALL */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \ + defined(WOLFSSL_WPAS_SMALL) +WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_get0_param( + const WOLFSSL_X509_STORE *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->param; +} +#endif + /******************************************************************************* * END OF X509_STORE APIs ******************************************************************************/ diff --git a/src/user_settings.h b/src/user_settings.h index d102ea8..52c4e7d 100644 --- a/src/user_settings.h +++ b/src/user_settings.h @@ -23,7 +23,7 @@ */ /* Define a macro to display user settings version in example code: */ -#define WOLFSSL_USER_SETTINGS_ID "Arduino user_settings.h v5.7.0" +#define WOLFSSL_USER_SETTINGS_ID "Arduino user_settings.h v5.7.2" /* Due to limited build control, we'll ignore file warnings. */ /* See https://github.com/arduino/arduino-cli/issues/631 */ diff --git a/src/wolfcrypt/src/aes.c b/src/wolfcrypt/src/aes.c index e9716bc..8418fb0 100644 --- a/src/wolfcrypt/src/aes.c +++ b/src/wolfcrypt/src/aes.c @@ -39,15 +39,13 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits /* Tip: Locate the software cipher modes by searching for "Software AES" */ -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) - +#if FIPS_VERSION3_GE(2,0,0) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$g") - #pragma const_seg(".fipsB$g") + #pragma code_seg(".fipsA$b") + #pragma const_seg(".fipsB$b") #endif #endif @@ -97,7 +95,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #endif -#ifndef WOLFSSL_ARMASM +#if !defined(WOLFSSL_ARMASM) && !defined(WOLFSSL_RISCV_ASM) #ifdef WOLFSSL_IMX6_CAAM_BLOB /* case of possibly not using hardware acceleration for AES but using key @@ -114,6 +112,15 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #pragma warning(disable: 4127) #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_aes_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000002 }; + int wolfCrypt_FIPS_AES_sanity(void) + { + return 0; + } +#endif + /* Define AES implementation includes and functions */ #if defined(STM32_CRYPTO) /* STM32F2/F4/F7/L4/L5/H7/WB55 hardware AES support for ECB, CBC, CTR and GCM modes */ @@ -720,7 +727,8 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits return MEMORY_E; #endif - if (AES_set_encrypt_key_AESNI(userKey,bits,temp_key) == BAD_FUNC_ARG) { + if (AES_set_encrypt_key_AESNI(userKey,bits,temp_key) + == WC_NO_ERR_TRACE(BAD_FUNC_ARG)) { #ifdef WOLFSSL_SMALL_STACK XFREE(temp_key, aes->heap, DYNAMIC_TYPE_AES); #endif @@ -960,6 +968,9 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) /* implemented in wolfcrypt/src/port/psa/psa_aes.c */ +#elif defined(WOLFSSL_RISCV_ASM) +/* implemented in wolfcrypt/src/port/risc-v/riscv-64-aes.c */ + #else /* using wolfCrypt software implementation */ @@ -1908,6 +1919,7 @@ static word32 GetTable8_4(const byte* t, byte o0, byte o1, byte o2, byte o3) ((word32)(t)[o2] << 8) | ((word32)(t)[o3] << 0)) #endif +#ifndef HAVE_CUDA /* Encrypt a block using AES. * * @param [in] aes AES object. @@ -1922,7 +1934,7 @@ static void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, word32 t0, t1, t2, t3; const word32* rk; -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK rk = aes->key_C_fallback; #else rk = aes->key; @@ -2208,6 +2220,11 @@ static void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz) } } #endif +#else +extern void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, + word32 r); +extern void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz); +#endif /* HAVE_CUDA */ #else @@ -2703,6 +2720,7 @@ static void bs_encrypt(bs_word* state, bs_word* rk, word32 r) bs_inv_transpose(state, trans); } +#ifndef HAVE_CUDA /* Encrypt a block using AES. * * @param [in] aes AES object. @@ -2754,6 +2772,11 @@ static void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz) } } #endif +#else +extern void AesEncrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, + word32 r); +extern void AesEncryptBlocks_C(Aes* aes, const byte* in, byte* out, word32 sz); +#endif /* HAVE_CUDA */ #endif /* !WC_AES_BITSLICED */ @@ -2926,7 +2949,7 @@ static void AesDecrypt_C(Aes* aes, const byte* inBlock, byte* outBlock, word32 t0, t1, t2, t3; const word32* rk; -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK rk = aes->key_C_fallback; #else rk = aes->key; @@ -4066,7 +4089,7 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( */ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) { -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK word32* rk = aes->key_C_fallback; #else word32* rk = aes->key; @@ -4227,7 +4250,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) if (dir == AES_DECRYPTION) { unsigned int j; -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK rk = aes->key_C_fallback; #else rk = aes->key; @@ -4298,6 +4321,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) #endif /* NEED_AES_TABLES */ +#ifndef WOLFSSL_RISCV_ASM /* Software AES - SetKey */ static WARN_UNUSED_RESULT int wc_AesSetKeyLocal( Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir, @@ -4436,11 +4460,11 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) if (ret != 0) return ret; -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK #ifdef NEED_AES_TABLES AesSetKey_C(aes, userKey, keylen, dir); #endif /* NEED_AES_TABLES */ -#endif /* WC_AES_C_DYNAMIC_FALLBACK */ +#endif /* WC_C_DYNAMIC_FALLBACK */ #ifdef WOLFSSL_AESNI aes->use_aesni = 0; @@ -4469,13 +4493,13 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) if (ret == 0) aes->use_aesni = 1; else { -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK ret = 0; #endif } return ret; } else { -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK return 0; #else return ret; @@ -4611,6 +4635,7 @@ static void AesSetKey_C(Aes* aes, const byte* key, word32 keySz, int dir) return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir, 1); } /* wc_AesSetKey() */ +#endif #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) /* AES-CTR and AES-DIRECT need to use this for key setup */ @@ -4661,7 +4686,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #ifdef WOLFSSL_AESNI -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK #define VECTOR_REGISTERS_PUSH { \ int orig_use_aesni = aes->use_aesni; \ @@ -5490,7 +5515,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) #endif { int crypto_cb_ret = wc_CryptoCb_AesCbcEncrypt(aes, out, in, sz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -5659,7 +5684,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) #endif { int crypto_cb_ret = wc_CryptoCb_AesCbcDecrypt(aes, out, in, sz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -6037,6 +6062,8 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) int ret = 0; word32 processed; + XMEMSET(scratch, 0, sizeof(scratch)); + if (aes == NULL || out == NULL || in == NULL) { return BAD_FUNC_ARG; } @@ -6047,7 +6074,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) #endif { int crypto_cb_ret = wc_CryptoCb_AesCtrEncrypt(aes, out, in, sz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -6144,13 +6171,13 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return BAD_FUNC_ARG; } - return wc_AesSetKeyLocal(aes, key, len, iv, dir, 0); + return wc_AesSetKey(aes, key, len, iv, dir); } #endif /* NEED_AES_CTR_SOFT */ #endif /* WOLFSSL_AES_COUNTER */ -#endif /* !WOLFSSL_ARMASM */ +#endif /* !WOLFSSL_ARMASM && ! WOLFSSL_RISCV_ASM */ /* @@ -6200,6 +6227,9 @@ static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) #ifdef WOLFSSL_ARMASM /* implementation is located in wolfcrypt/src/port/arm/armv8-aes.c */ +#elif defined(WOLFSSL_RISCV_ASM) + /* implemented in wolfcrypt/src/port/risc-v/riscv-64-aes.c */ + #elif defined(WOLFSSL_AFALG) /* implemented in wolfcrypt/src/port/afalg/afalg_aes.c */ @@ -6381,7 +6411,7 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) if (!((len == 16) || (len == 24) || (len == 32))) return BAD_FUNC_ARG; - if (aes == NULL) { + if (aes == NULL || key == NULL) { #ifdef WOLFSSL_IMX6_CAAM_BLOB ForceZero(local, sizeof(local)); #endif @@ -8295,7 +8325,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, int crypto_cb_ret = wc_CryptoCb_AesGcmEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, authIn, authInSz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -8838,7 +8868,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, { int ret; #ifdef WOLFSSL_AESNI - int res = AES_GCM_AUTH_E; + int res = WC_NO_ERR_TRACE(AES_GCM_AUTH_E); #endif /* argument checks */ @@ -8859,7 +8889,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, int crypto_cb_ret = wc_CryptoCb_AesGcmDecrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, authIn, authInSz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -10457,6 +10487,9 @@ int wc_AesCcmCheckTagSize(int sz) #ifdef WOLFSSL_ARMASM /* implementation located in wolfcrypt/src/port/arm/armv8-aes.c */ +#elif defined(WOLFSSL_RISCV_ASM) + /* implementation located in wolfcrypt/src/port/risc-v/riscv-64-aes.c */ + #elif defined(HAVE_COLDFIRE_SEC) #error "Coldfire SEC doesn't currently support AES-CCM mode" @@ -10728,6 +10761,11 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; + /* Sanity check on authIn to prevent segfault in xorbuf() where + * variable 'in' is dereferenced as the mask 'm' in misc.c */ + if (authIn == NULL && authInSz > 0) + return BAD_FUNC_ARG; + /* sanity check on tag size */ if (wc_AesCcmCheckTagSize((int)authTagSz) != 0) { return BAD_FUNC_ARG; @@ -10741,7 +10779,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, int crypto_cb_ret = wc_CryptoCb_AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -10870,6 +10908,11 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; + /* Sanity check on authIn to prevent segfault in xorbuf() where + * variable 'in' is dereferenced as the mask 'm' in misc.c */ + if (authIn == NULL && authInSz > 0) + return BAD_FUNC_ARG; + /* sanity check on tag size */ if (wc_AesCcmCheckTagSize((int)authTagSz) != 0) { return BAD_FUNC_ARG; @@ -10883,7 +10926,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, int crypto_cb_ret = wc_CryptoCb_AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, authIn, authInSz); - if (crypto_cb_ret != CRYPTOCB_UNAVAILABLE) + if (crypto_cb_ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return crypto_cb_ret; /* fall-through when unavailable */ } @@ -11354,6 +11397,9 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize) #elif defined(WOLFSSL_DEVCRYPTO_AES) /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ +#elif defined(WOLFSSL_RISCV_ASM) + /* implemented in wolfcrypt/src/port/riscv/riscv-64-aes.c */ + #elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_AES) /* Software AES - ECB */ @@ -11388,7 +11434,7 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt( #endif { ret = wc_CryptoCb_AesEcbEncrypt(aes, out, in, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; ret = 0; /* fall-through when unavailable */ @@ -11428,6 +11474,7 @@ static WARN_UNUSED_RESULT int _AesEcbEncrypt( return ret; } +#ifdef HAVE_AES_DECRYPT static WARN_UNUSED_RESULT int _AesEcbDecrypt( Aes* aes, byte* out, const byte* in, word32 sz) { @@ -11439,7 +11486,7 @@ static WARN_UNUSED_RESULT int _AesEcbDecrypt( #endif { ret = wc_CryptoCb_AesEcbDecrypt(aes, out, in, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; ret = 0; /* fall-through when unavailable */ @@ -11478,6 +11525,7 @@ static WARN_UNUSED_RESULT int _AesEcbDecrypt( return ret; } +#endif int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { @@ -11490,6 +11538,7 @@ int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) return _AesEcbEncrypt(aes, out, in, sz); } +#ifdef HAVE_AES_DECRYPT int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { if ((in == NULL) || (out == NULL) || (aes == NULL)) @@ -11500,6 +11549,7 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) return _AesEcbDecrypt(aes, out, in, sz); } +#endif /* HAVE_AES_DECRYPT */ #endif #endif /* HAVE_AES_ECB */ @@ -11863,7 +11913,7 @@ static WARN_UNUSED_RESULT int wc_AesFeedbackCFB1( } if (ret == 0) { - if (bit > 0 && bit < 7) { + if (bit >= 0 && bit < 7) { out[0] = cur; } } @@ -12313,12 +12363,16 @@ int wc_AesXtsSetKeyNoInit(XtsAes* aes, const byte* key, word32 len, int dir) return BAD_FUNC_ARG; } - keySz = len/2; - if (keySz != AES_128_KEY_SIZE && keySz != AES_256_KEY_SIZE) { + if ((len != (AES_128_KEY_SIZE*2)) && + (len != (AES_192_KEY_SIZE*2)) && + (len != (AES_256_KEY_SIZE*2))) + { WOLFSSL_MSG("Unsupported key size"); return WC_KEY_SIZE_E; } + keySz = len/2; + #ifdef HAVE_FIPS if (XMEMCMP(key, key + keySz, keySz) == 0) { WOLFSSL_MSG("FIPS AES-XTS main and tweak keys must differ"); @@ -12350,7 +12404,7 @@ int wc_AesXtsSetKeyNoInit(XtsAes* aes, const byte* key, word32 len, int dir) #ifdef WOLFSSL_AESNI if (ret == 0) { - /* With WC_AES_C_DYNAMIC_FALLBACK, the main and tweak keys could have + /* With WC_C_DYNAMIC_FALLBACK, the main and tweak keys could have * conflicting _aesni status, but the AES-XTS asm implementations need * them to all be AESNI. If any aren't, disable AESNI on all. */ @@ -12363,7 +12417,7 @@ int wc_AesXtsSetKeyNoInit(XtsAes* aes, const byte* key, word32 len, int dir) (dir == AES_ENCRYPTION_AND_DECRYPTION)) && (aes->aes_decrypt.use_aesni != aes->tweak.use_aesni))) { - #ifdef WC_AES_C_DYNAMIC_FALLBACK + #ifdef WC_C_DYNAMIC_FALLBACK aes->aes.use_aesni = 0; aes->aes_decrypt.use_aesni = 0; aes->tweak.use_aesni = 0; @@ -12373,7 +12427,7 @@ int wc_AesXtsSetKeyNoInit(XtsAes* aes, const byte* key, word32 len, int dir) } #else /* !WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS */ if (aes->aes.use_aesni != aes->tweak.use_aesni) { - #ifdef WC_AES_C_DYNAMIC_FALLBACK + #ifdef WC_C_DYNAMIC_FALLBACK aes->aes.use_aesni = 0; aes->tweak.use_aesni = 0; #else @@ -12502,12 +12556,28 @@ void AES_XTS_encrypt_aesni(const unsigned char *in, unsigned char *out, word32 s const unsigned char* i, const unsigned char* key, const unsigned char* key2, int nr) XASM_LINK("AES_XTS_encrypt_aesni"); +#ifdef WOLFSSL_AESXTS_STREAM +void AES_XTS_init_aesni(unsigned char* i, const unsigned char* tweak_key, + int tweak_nr) + XASM_LINK("AES_XTS_init_aesni"); +void AES_XTS_encrypt_update_aesni(const unsigned char *in, unsigned char *out, word32 sz, + const unsigned char* key, unsigned char *i, int nr) + XASM_LINK("AES_XTS_encrypt_update_aesni"); +#endif #ifdef HAVE_INTEL_AVX1 void AES_XTS_encrypt_avx1(const unsigned char *in, unsigned char *out, - word32 sz, const unsigned char* i, - const unsigned char* key, const unsigned char* key2, - int nr) - XASM_LINK("AES_XTS_encrypt_avx1"); + word32 sz, const unsigned char* i, + const unsigned char* key, const unsigned char* key2, + int nr) + XASM_LINK("AES_XTS_encrypt_avx1"); +#ifdef WOLFSSL_AESXTS_STREAM +void AES_XTS_init_avx1(unsigned char* i, const unsigned char* tweak_key, + int tweak_nr) + XASM_LINK("AES_XTS_init_avx1"); +void AES_XTS_encrypt_update_avx1(const unsigned char *in, unsigned char *out, word32 sz, + const unsigned char* key, unsigned char *i, int nr) + XASM_LINK("AES_XTS_encrypt_update_avx1"); +#endif #endif /* HAVE_INTEL_AVX1 */ #ifdef HAVE_AES_DECRYPT @@ -12515,12 +12585,22 @@ void AES_XTS_decrypt_aesni(const unsigned char *in, unsigned char *out, word32 s const unsigned char* i, const unsigned char* key, const unsigned char* key2, int nr) XASM_LINK("AES_XTS_decrypt_aesni"); +#ifdef WOLFSSL_AESXTS_STREAM +void AES_XTS_decrypt_update_aesni(const unsigned char *in, unsigned char *out, word32 sz, + const unsigned char* key, unsigned char *i, int nr) + XASM_LINK("AES_XTS_decrypt_update_aesni"); +#endif #ifdef HAVE_INTEL_AVX1 void AES_XTS_decrypt_avx1(const unsigned char *in, unsigned char *out, - word32 sz, const unsigned char* i, - const unsigned char* key, const unsigned char* key2, - int nr) - XASM_LINK("AES_XTS_decrypt_avx1"); + word32 sz, const unsigned char* i, + const unsigned char* key, const unsigned char* key2, + int nr) + XASM_LINK("AES_XTS_decrypt_avx1"); +#ifdef WOLFSSL_AESXTS_STREAM +void AES_XTS_decrypt_update_avx1(const unsigned char *in, unsigned char *out, word32 sz, + const unsigned char* key, unsigned char *i, int nr) + XASM_LINK("AES_XTS_decrypt_update_avx1"); +#endif #endif /* HAVE_INTEL_AVX1 */ #endif /* HAVE_AES_DECRYPT */ @@ -12558,16 +12638,24 @@ static WARN_UNUSED_RESULT int _AesXtsHelper( } xorbuf(out, in, totalSz); +#ifndef WOLFSSL_RISCV_ASM if (dir == AES_ENCRYPTION) { return _AesEcbEncrypt(aes, out, out, totalSz); } else { return _AesEcbDecrypt(aes, out, out, totalSz); } +#else + if (dir == AES_ENCRYPTION) { + return wc_AesEcbEncrypt(aes, out, out, totalSz); + } + else { + return wc_AesEcbDecrypt(aes, out, out, totalSz); + } +#endif } #endif /* HAVE_AES_ECB */ - /* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing. * * xaes AES keys to use for block encrypt/decrypt @@ -12579,27 +12667,63 @@ static WARN_UNUSED_RESULT int _AesXtsHelper( * returns 0 on success */ /* Software AES - XTS Encrypt */ + +static int AesXtsEncryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in, + word32 sz, + byte *i); static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, const byte* i) { - int ret = 0; - word32 blocks = (sz / AES_BLOCK_SIZE); - Aes *aes = &xaes->aes; - Aes *tweak = &xaes->tweak; - byte tmp[AES_BLOCK_SIZE]; - - XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES - * key setup passed to encrypt direct*/ - - ret = wc_AesEncryptDirect(tweak, tmp, i); + int ret; + byte tweak_block[AES_BLOCK_SIZE]; + ret = wc_AesEncryptDirect(&xaes->tweak, tweak_block, i); if (ret != 0) return ret; + return AesXtsEncryptUpdate_sw(xaes, out, in, sz, tweak_block); +} + +#ifdef WOLFSSL_AESXTS_STREAM + +/* Block-streaming AES-XTS tweak setup. + * + * xaes AES keys to use for block encrypt/decrypt + * i readwrite value to use for tweak + * + * returns 0 on success + */ +static int AesXtsInitTweak_sw(XtsAes* xaes, byte* i) { + return wc_AesEncryptDirect(&xaes->tweak, i, i); +} + +#endif /* WOLFSSL_AESXTS_STREAM */ + +/* Block-streaming AES-XTS. + * + * Supply block-aligned input data with successive calls. Final call need not + * be block aligned. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold cipher text + * in input plain text buffer to encrypt + * sz size of both out and in buffers + * + * returns 0 on success + */ +/* Software AES - XTS Encrypt */ +static int AesXtsEncryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in, + word32 sz, + byte *i) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes = &xaes->aes; + #ifdef HAVE_AES_ECB /* encrypt all of buffer at once when possible */ if (in != out) { /* can not handle inline */ - XMEMCPY(out, tmp, AES_BLOCK_SIZE); + XMEMCPY(out, i, AES_BLOCK_SIZE); if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) return ret; } @@ -12616,23 +12740,23 @@ static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, byte buf[AES_BLOCK_SIZE]; XMEMCPY(buf, in, AES_BLOCK_SIZE); - xorbuf(buf, tmp, AES_BLOCK_SIZE); + xorbuf(buf, i, AES_BLOCK_SIZE); ret = wc_AesEncryptDirect(aes, out, buf); if (ret != 0) return ret; } - xorbuf(out, tmp, AES_BLOCK_SIZE); + xorbuf(out, i, AES_BLOCK_SIZE); /* multiply by shift left and propagate carry */ for (j = 0; j < AES_BLOCK_SIZE; j++) { byte tmpC; - tmpC = (tmp[j] >> 7) & 0x01; - tmp[j] = (byte)((tmp[j] << 1) + carry); + tmpC = (i[j] >> 7) & 0x01; + i[j] = (byte)((i[j] << 1) + carry); carry = tmpC; } if (carry) { - tmp[0] ^= GF_XTS; + i[0] ^= GF_XTS; } in += AES_BLOCK_SIZE; @@ -12661,10 +12785,10 @@ static int AesXtsEncrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, XMEMCPY(out, buf2, sz); } - xorbuf(buf, tmp, AES_BLOCK_SIZE); + xorbuf(buf, i, AES_BLOCK_SIZE); ret = wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf); if (ret == 0) - xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE); + xorbuf(out - AES_BLOCK_SIZE, i, AES_BLOCK_SIZE); } return ret; @@ -12693,6 +12817,17 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, return BAD_FUNC_ARG; } +#if FIPS_VERSION3_GE(6,0,0) + /* SP800-38E - Restrict data unit to 2^20 blocks per key. A block is + * AES_BLOCK_SIZE or 16-bytes (128-bits). So each key may only be used to + * protect up to 1,048,576 blocks of AES_BLOCK_SIZE (16,777,216 bytes) + */ + if (sz > FIPS_AES_XTS_MAX_BYTES_PER_TWEAK) { + WOLFSSL_MSG("Request exceeds allowed bytes per SP800-38E"); + return BAD_FUNC_ARG; + } +#endif + aes = &xaes->aes; if (aes->keylen == 0) { @@ -12711,19 +12846,8 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, { #ifdef WOLFSSL_AESNI -#ifdef WC_AES_C_DYNAMIC_FALLBACK - int orig_use_aesni = aes->use_aesni; -#endif - - if (aes->use_aesni && ((ret = SAVE_VECTOR_REGISTERS2()) != 0)) { -#ifdef WC_AES_C_DYNAMIC_FALLBACK - aes->use_aesni = 0; - xaes->tweak.use_aesni = 0; -#else - return ret; -#endif - } if (aes->use_aesni) { + SAVE_VECTOR_REGISTERS(return _svr_ret;); #if defined(HAVE_INTEL_AVX1) if (IS_INTEL_AVX1(intel_flags)) { AES_XTS_encrypt_avx1(in, out, sz, i, @@ -12741,28 +12865,212 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, (int)aes->rounds); ret = 0; } + RESTORE_VECTOR_REGISTERS(); } else #endif { ret = AesXtsEncrypt_sw(xaes, out, in, sz, i); } + } + + return ret; +} + +#ifdef WOLFSSL_AESXTS_STREAM + +/* Block-streaming AES-XTS. + * + * xaes AES keys to use for block encrypt/decrypt + * i readwrite value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +int wc_AesXtsEncryptInit(XtsAes* xaes, const byte* i, word32 iSz, + struct XtsAesStreamData *stream) +{ + int ret; + Aes *aes; + + if ((xaes == NULL) || (i == NULL) || (stream == NULL)) { + return BAD_FUNC_ARG; + } + + if (iSz < AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + + if (aes->keylen == 0) { + WOLFSSL_MSG("wc_AesXtsEncrypt called with unset encryption key."); + return BAD_FUNC_ARG; + } + + XMEMCPY(stream->tweak_block, i, AES_BLOCK_SIZE); + stream->bytes_crypted_with_this_tweak = 0; + + { #ifdef WOLFSSL_AESNI - if (aes->use_aesni) + if (aes->use_aesni) { + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + AES_XTS_init_avx1(stream->tweak_block, + (const byte*)xaes->tweak.key, + (int)xaes->tweak.rounds); + ret = 0; + } + else +#endif + { + AES_XTS_init_aesni(stream->tweak_block, + (const byte*)xaes->tweak.key, + (int)xaes->tweak.rounds); + ret = 0; + } RESTORE_VECTOR_REGISTERS(); -#ifdef WC_AES_C_DYNAMIC_FALLBACK - else if (orig_use_aesni) { - aes->use_aesni = orig_use_aesni; - xaes->tweak.use_aesni = orig_use_aesni; } + else +#endif /* WOLFSSL_AESNI */ + { + ret = AesXtsInitTweak_sw(xaes, stream->tweak_block); + } + } + + return ret; +} + +/* Block-streaming AES-XTS + * + * Note that sz must be >= AES_BLOCK_SIZE in each call, and must be a multiple + * of AES_BLOCK_SIZE in each call to wc_AesXtsEncryptUpdate(). + * wc_AesXtsEncryptFinal() can handle any length >= AES_BLOCK_SIZE. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold cipher text + * in input plain text buffer to encrypt + * sz size of both out and in buffers -- must be >= AES_BLOCK_SIZE. + * i value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +static int AesXtsEncryptUpdate(XtsAes* xaes, byte* out, const byte* in, word32 sz, + struct XtsAesStreamData *stream) +{ + int ret; + +#ifdef WOLFSSL_AESNI + Aes *aes; #endif + + if (xaes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_AESNI + aes = &xaes->aes; #endif + + if (sz < AES_BLOCK_SIZE) { + WOLFSSL_MSG("Plain text input too small for encryption"); + return BAD_FUNC_ARG; + } + + if (stream->bytes_crypted_with_this_tweak & ((word32)AES_BLOCK_SIZE - 1U)) + { + WOLFSSL_MSG("Call to AesXtsEncryptUpdate after previous finalizing call"); + return BAD_FUNC_ARG; + } + +#ifndef WC_AESXTS_STREAM_NO_REQUEST_ACCOUNTING + (void)WC_SAFE_SUM_WORD32(stream->bytes_crypted_with_this_tweak, sz, + stream->bytes_crypted_with_this_tweak); +#endif +#if FIPS_VERSION3_GE(6,0,0) + /* SP800-38E - Restrict data unit to 2^20 blocks per key. A block is + * AES_BLOCK_SIZE or 16-bytes (128-bits). So each key may only be used to + * protect up to 1,048,576 blocks of AES_BLOCK_SIZE (16,777,216 bytes) + */ + if (stream->bytes_crypted_with_this_tweak > + FIPS_AES_XTS_MAX_BYTES_PER_TWEAK) + { + WOLFSSL_MSG("Request exceeds allowed bytes per SP800-38E"); + return BAD_FUNC_ARG; + } +#endif + { +#ifdef WOLFSSL_AESNI + if (aes->use_aesni) { + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + AES_XTS_encrypt_update_avx1(in, out, sz, + (const byte*)aes->key, + stream->tweak_block, + (int)aes->rounds); + ret = 0; + } + else +#endif + { + AES_XTS_encrypt_update_aesni(in, out, sz, + (const byte*)aes->key, + stream->tweak_block, + (int)aes->rounds); + ret = 0; + } + RESTORE_VECTOR_REGISTERS(); + } + else +#endif /* WOLFSSL_AESNI */ + { + ret = AesXtsEncryptUpdate_sw(xaes, out, in, sz, stream->tweak_block); + } } return ret; } +int wc_AesXtsEncryptUpdate(XtsAes* xaes, byte* out, const byte* in, word32 sz, + struct XtsAesStreamData *stream) +{ + if (stream == NULL) + return BAD_FUNC_ARG; + if (sz & ((word32)AES_BLOCK_SIZE - 1U)) + return BAD_FUNC_ARG; + return AesXtsEncryptUpdate(xaes, out, in, sz, stream); +} + +int wc_AesXtsEncryptFinal(XtsAes* xaes, byte* out, const byte* in, word32 sz, + struct XtsAesStreamData *stream) +{ + int ret; + if (stream == NULL) + return BAD_FUNC_ARG; + if (sz > 0) + ret = AesXtsEncryptUpdate(xaes, out, in, sz, stream); + else + ret = 0; + /* force the count odd, to assure error on attempt to AesXtsEncryptUpdate() + * after finalization. + */ + stream->bytes_crypted_with_this_tweak |= 1U; + ForceZero(stream->tweak_block, AES_BLOCK_SIZE); +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(stream->tweak_block, AES_BLOCK_SIZE); +#endif + return ret; +} + +#endif /* WOLFSSL_AESXTS_STREAM */ + + /* Same process as encryption but use aes_decrypt key. * * xaes AES keys to use for block encrypt/decrypt @@ -12774,8 +13082,41 @@ int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, * returns 0 on success */ /* Software AES - XTS Decrypt */ + +static int AesXtsDecryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in, + word32 sz, byte *i); + static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, const byte* i) +{ + int ret; + byte tweak_block[AES_BLOCK_SIZE]; + + ret = wc_AesEncryptDirect(&xaes->tweak, tweak_block, i); + if (ret != 0) + return ret; + + return AesXtsDecryptUpdate_sw(xaes, out, in, sz, tweak_block); +} + +/* Block-streaming AES-XTS. + * + * Same process as encryption but use decrypt key. + * + * Supply block-aligned input data with successive calls. Final call need not + * be block aligned. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold plain text + * in input cipher text buffer to decrypt + * sz size of both out and in buffers + * i value to use for tweak + * + * returns 0 on success + */ +/* Software AES - XTS Decrypt */ +static int AesXtsDecryptUpdate_sw(XtsAes* xaes, byte* out, const byte* in, + word32 sz, byte *i) { int ret = 0; word32 blocks = (sz / AES_BLOCK_SIZE); @@ -12784,19 +13125,10 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, #else Aes *aes = &xaes->aes; #endif - Aes *tweak = &xaes->tweak; word32 j; byte carry = 0; - byte tmp[AES_BLOCK_SIZE]; byte stl = (sz % AES_BLOCK_SIZE); - XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES - * key setup passed to decrypt direct*/ - - ret = wc_AesEncryptDirect(tweak, tmp, i); - if (ret != 0) - return ret; - /* if Stealing then break out of loop one block early to handle special * case */ if (stl > 0) { @@ -12806,7 +13138,7 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, #ifdef HAVE_AES_ECB /* decrypt all of buffer at once when possible */ if (in != out) { /* can not handle inline */ - XMEMCPY(out, tmp, AES_BLOCK_SIZE); + XMEMCPY(out, i, AES_BLOCK_SIZE); if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) return ret; } @@ -12820,23 +13152,23 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, byte buf[AES_BLOCK_SIZE]; XMEMCPY(buf, in, AES_BLOCK_SIZE); - xorbuf(buf, tmp, AES_BLOCK_SIZE); + xorbuf(buf, i, AES_BLOCK_SIZE); ret = wc_AesDecryptDirect(aes, out, buf); if (ret != 0) return ret; } - xorbuf(out, tmp, AES_BLOCK_SIZE); + xorbuf(out, i, AES_BLOCK_SIZE); /* multiply by shift left and propagate carry */ for (j = 0; j < AES_BLOCK_SIZE; j++) { byte tmpC; - tmpC = (tmp[j] >> 7) & 0x01; - tmp[j] = (byte)((tmp[j] << 1) + carry); + tmpC = (i[j] >> 7) & 0x01; + i[j] = (byte)((i[j] << 1) + carry); carry = tmpC; } if (carry) { - tmp[0] ^= GF_XTS; + i[0] ^= GF_XTS; } carry = 0; @@ -12855,8 +13187,8 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, for (j = 0; j < AES_BLOCK_SIZE; j++) { byte tmpC; - tmpC = (tmp[j] >> 7) & 0x01; - tmp2[j] = (byte)((tmp[j] << 1) + carry); + tmpC = (i[j] >> 7) & 0x01; + tmp2[j] = (byte)((i[j] << 1) + carry); carry = tmpC; } if (carry) { @@ -12884,11 +13216,11 @@ static int AesXtsDecrypt_sw(XtsAes* xaes, byte* out, const byte* in, word32 sz, XMEMCPY(buf, in, sz); XMEMCPY(out, tmp2, sz); - xorbuf(buf, tmp, AES_BLOCK_SIZE); + xorbuf(buf, i, AES_BLOCK_SIZE); ret = wc_AesDecryptDirect(aes, tmp2, buf); if (ret != 0) return ret; - xorbuf(tmp2, tmp, AES_BLOCK_SIZE); + xorbuf(tmp2, i, AES_BLOCK_SIZE); XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE); } @@ -12923,6 +13255,14 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, aes = &xaes->aes; #endif +/* FIPS TODO: SP800-38E - Restrict data unit to 2^20 blocks per key. A block is + * AES_BLOCK_SIZE or 16-bytes (128-bits). So each key may only be used to + * protect up to 1,048,576 blocks of AES_BLOCK_SIZE (16,777,216 bytes or + * 134,217,728-bits) Add helpful printout and message along with BAD_FUNC_ARG + * return whenever sz / AES_BLOCK_SIZE > 1,048,576 or equal to that and sz is + * not a sequence of complete blocks. + */ + if (aes->keylen == 0) { WOLFSSL_MSG("wc_AesXtsDecrypt called with unset decryption key."); return BAD_FUNC_ARG; @@ -12939,19 +13279,8 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, { #ifdef WOLFSSL_AESNI -#ifdef WC_AES_C_DYNAMIC_FALLBACK - int orig_use_aesni = aes->use_aesni; -#endif - - if (aes->use_aesni && ((ret = SAVE_VECTOR_REGISTERS2() != 0))) { -#ifdef WC_AES_C_DYNAMIC_FALLBACK - aes->use_aesni = 0; - xaes->tweak.use_aesni = 0; -#else - return ret; -#endif - } if (aes->use_aesni) { + SAVE_VECTOR_REGISTERS(return _svr_ret;); #if defined(HAVE_INTEL_AVX1) if (IS_INTEL_AVX1(intel_flags)) { AES_XTS_decrypt_avx1(in, out, sz, i, @@ -12969,6 +13298,7 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, (int)aes->rounds); ret = 0; } + RESTORE_VECTOR_REGISTERS(); } else #endif @@ -12976,20 +13306,198 @@ int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, ret = AesXtsDecrypt_sw(xaes, out, in, sz, i); } + return ret; + } +} + +#ifdef WOLFSSL_AESXTS_STREAM + +/* Same process as encryption but Aes key is AES_DECRYPTION type. + * + * xaes AES keys to use for block encrypt/decrypt + * i readwrite value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +int wc_AesXtsDecryptInit(XtsAes* xaes, const byte* i, word32 iSz, + struct XtsAesStreamData *stream) +{ + int ret; + Aes *aes; + + if (xaes == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS + aes = &xaes->aes_decrypt; +#else + aes = &xaes->aes; +#endif + + if (aes->keylen == 0) { + WOLFSSL_MSG("wc_AesXtsDecrypt called with unset decryption key."); + return BAD_FUNC_ARG; + } + + if (iSz < AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + XMEMCPY(stream->tweak_block, i, AES_BLOCK_SIZE); + stream->bytes_crypted_with_this_tweak = 0; + + { #ifdef WOLFSSL_AESNI - if (aes->use_aesni) + if (aes->use_aesni) { + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + AES_XTS_init_avx1(stream->tweak_block, + (const byte*)xaes->tweak.key, + (int)xaes->tweak.rounds); + ret = 0; + } + else +#endif + { + AES_XTS_init_aesni(stream->tweak_block, + (const byte*)xaes->tweak.key, + (int)xaes->tweak.rounds); + ret = 0; + } RESTORE_VECTOR_REGISTERS(); -#ifdef WC_AES_C_DYNAMIC_FALLBACK - else if (orig_use_aesni) { - aes->use_aesni = orig_use_aesni; - xaes->tweak.use_aesni = orig_use_aesni; } + else +#endif /* WOLFSSL_AESNI */ + { + ret = AesXtsInitTweak_sw(xaes, stream->tweak_block); + } + + } + + return ret; +} + +/* Block-streaming AES-XTS + * + * Note that sz must be >= AES_BLOCK_SIZE in each call, and must be a multiple + * of AES_BLOCK_SIZE in each call to wc_AesXtsDecryptUpdate(). + * wc_AesXtsDecryptFinal() can handle any length >= AES_BLOCK_SIZE. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold plain text + * in input cipher text buffer to decrypt + * sz size of both out and in buffers + * i tweak buffer of size AES_BLOCK_SIZE. + * + * returns 0 on success + */ +static int AesXtsDecryptUpdate(XtsAes* xaes, byte* out, const byte* in, word32 sz, + struct XtsAesStreamData *stream) +{ + int ret; +#ifdef WOLFSSL_AESNI + Aes *aes; +#endif + + if (xaes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_AESNI +#ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS + aes = &xaes->aes_decrypt; +#else + aes = &xaes->aes; #endif #endif - return ret; + if (sz < AES_BLOCK_SIZE) { + WOLFSSL_MSG("Cipher text input too small for decryption"); + return BAD_FUNC_ARG; + } + + if (stream->bytes_crypted_with_this_tweak & ((word32)AES_BLOCK_SIZE - 1U)) + { + WOLFSSL_MSG("Call to AesXtsDecryptUpdate after previous finalizing call"); + return BAD_FUNC_ARG; + } + +#ifndef WC_AESXTS_STREAM_NO_REQUEST_ACCOUNTING + (void)WC_SAFE_SUM_WORD32(stream->bytes_crypted_with_this_tweak, sz, + stream->bytes_crypted_with_this_tweak); +#endif + + { +#ifdef WOLFSSL_AESNI + if (aes->use_aesni) { + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + AES_XTS_decrypt_update_avx1(in, out, sz, + (const byte*)aes->key, + stream->tweak_block, + (int)aes->rounds); + ret = 0; + } + else +#endif + { + AES_XTS_decrypt_update_aesni(in, out, sz, + (const byte*)aes->key, + stream->tweak_block, + (int)aes->rounds); + ret = 0; + } + RESTORE_VECTOR_REGISTERS(); + } + else +#endif /* WOLFSSL_AESNI */ + { + ret = AesXtsDecryptUpdate_sw(xaes, out, in, sz, + stream->tweak_block); + } } + + return ret; +} + +int wc_AesXtsDecryptUpdate(XtsAes* xaes, byte* out, const byte* in, word32 sz, + struct XtsAesStreamData *stream) +{ + if (stream == NULL) + return BAD_FUNC_ARG; + if (sz & ((word32)AES_BLOCK_SIZE - 1U)) + return BAD_FUNC_ARG; + return AesXtsDecryptUpdate(xaes, out, in, sz, stream); +} + +int wc_AesXtsDecryptFinal(XtsAes* xaes, byte* out, const byte* in, word32 sz, + struct XtsAesStreamData *stream) +{ + int ret; + if (stream == NULL) + return BAD_FUNC_ARG; + if (sz > 0) + ret = AesXtsDecryptUpdate(xaes, out, in, sz, stream); + else + ret = 0; + ForceZero(stream->tweak_block, AES_BLOCK_SIZE); + /* force the count odd, to assure error on attempt to AesXtsEncryptUpdate() + * after finalization. + */ + stream->bytes_crypted_with_this_tweak |= 1U; +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(stream->tweak_block, AES_BLOCK_SIZE); +#endif + return ret; } + +#endif /* WOLFSSL_AESXTS_STREAM */ + #endif /* !WOLFSSL_ARMASM || WOLFSSL_ARMASM_NO_HW_CRYPTO */ /* Same as wc_AesXtsEncryptSector but the sector gets incremented by one every diff --git a/src/wolfcrypt/src/asn.c b/src/wolfcrypt/src/asn.c index ac50995..778d3e7 100644 --- a/src/wolfcrypt/src/asn.c +++ b/src/wolfcrypt/src/asn.c @@ -166,16 +166,14 @@ ASN Options: #include #endif -#ifdef HAVE_PQC - #if defined(HAVE_FALCON) +#if defined(HAVE_FALCON) #include - #endif - #if defined(HAVE_DILITHIUM) +#endif +#if defined(HAVE_DILITHIUM) #include - #endif - #if defined(HAVE_SPHINCS) +#endif +#if defined(HAVE_SPHINCS) #include - #endif #endif #ifdef WOLFSSL_QNX_CAAM @@ -1203,14 +1201,14 @@ static int GetASN_ObjectId(const byte* input, word32 idx, int length) /* OID data must be at least 3 bytes. */ if (length < 3) { #ifdef WOLFSSL_DEBUG_ASN_TEMPLATE - WOLFSSL_MSG_VSNPRINTF("OID length must be 3 or more: %d", len); + WOLFSSL_MSG_VSNPRINTF("OID length must be 3 or more: %d", length); #else WOLFSSL_MSG("OID length less than 3"); #endif ret = ASN_PARSE_E; } - /* Last octet of a subidentifier has bit 8 clear. Last octet must be last - * of a subidentifier. Ensure last octet hasn't got top bit set indicating. + /* Last octet of a sub-identifier has bit 8 clear. Last octet must be last + * of a subidentifier. Ensure last octet hasn't got top bit set. */ else if ((input[(int)idx + length - 1] & 0x80) != 0x00) { WOLFSSL_MSG("OID last octet has top bit set"); @@ -3496,7 +3494,7 @@ int CheckBitString(const byte* input, word32* inOutIdx, int* len, #else ASNGetData dataASN[bitStringASN_Length]; int ret; - int bits; + int bits = 0; /* Parse BIT_STRING and check validity of unused bits. */ XMEMSET(dataASN, 0, sizeof(dataASN)); @@ -3534,7 +3532,7 @@ int CheckBitString(const byte* input, word32* inOutIdx, int* len, ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || \ defined(OPENSSL_EXTRA))) || \ - (defined(WC_ENABLE_ASYM_KEY_EXPORT) && !defined(NO_CERT)) || \ + (defined(WC_ENABLE_ASYM_KEY_EXPORT) && !defined(NO_CERTS)) || \ (!defined(NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN)) || \ (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) @@ -4200,7 +4198,6 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef HAVE_ED448 static const byte sigEd448Oid[] = {43, 101, 113}; #endif /* HAVE_ED448 */ -#ifdef HAVE_PQC #ifdef HAVE_FALCON /* Falcon Level 1: 1 3 9999 3 6 */ static const byte sigFalcon_Level1Oid[] = {43, 206, 15, 3, 6}; @@ -4209,17 +4206,17 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte sigFalcon_Level5Oid[] = {43, 206, 15, 3, 9}; #endif /* HAVE_FACON */ #ifdef HAVE_DILITHIUM - /* Dilithium Level 2: 1.3.6.1.4.1.2.267.7.4.4 */ + /* Dilithium Level 2: 1.3.6.1.4.1.2.267.12.4.4 */ static const byte sigDilithium_Level2Oid[] = - {43, 6, 1, 4, 1, 2, 130, 11, 7, 4, 4}; + {43, 6, 1, 4, 1, 2, 130, 11, 12, 4, 4}; - /* Dilithium Level 3: 1.3.6.1.4.1.2.267.7.6.5 */ + /* Dilithium Level 3: 1.3.6.1.4.1.2.267.12.6.5 */ static const byte sigDilithium_Level3Oid[] = - {43, 6, 1, 4, 1, 2, 130, 11, 7, 6, 5}; + {43, 6, 1, 4, 1, 2, 130, 11, 12, 6, 5}; - /* Dilithium Level 5: 1.3.6.1.4.1.2.267.7.8.7 */ + /* Dilithium Level 5: 1.3.6.1.4.1.2.267.12.8.7 */ static const byte sigDilithium_Level5Oid[] = - {43, 6, 1, 4, 1, 2, 130, 11, 7, 8, 7}; + {43, 6, 1, 4, 1, 2, 130, 11, 12, 8, 7}; #endif /* HAVE_DILITHIUM */ #ifdef HAVE_SPHINCS /* Sphincs Fast Level 1: 1 3 9999 6 7 4 */ @@ -4246,7 +4243,6 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte sigSphincsSmall_Level5Oid[] = {43, 206, 15, 6, 9, 7}; #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ /* keyType */ #ifndef NO_DSA @@ -4276,7 +4272,6 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifndef NO_DH static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1}; #endif /* !NO_DH */ -#ifdef HAVE_PQC #ifdef HAVE_FALCON /* Falcon Level 1: 1 3 9999 3 6 */ static const byte keyFalcon_Level1Oid[] = {43, 206, 15, 3, 6}; @@ -4285,17 +4280,17 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte keyFalcon_Level5Oid[] = {43, 206, 15, 3, 9}; #endif /* HAVE_FALCON */ #ifdef HAVE_DILITHIUM - /* Dilithium Level 2: 1.3.6.1.4.1.2.267.7.4.4 */ + /* Dilithium Level 2: 1.3.6.1.4.1.2.267.12.4.4 */ static const byte keyDilithium_Level2Oid[] = - {43, 6, 1, 4, 1, 2, 130, 11, 7, 4, 4}; + {43, 6, 1, 4, 1, 2, 130, 11, 12, 4, 4}; - /* Dilithium Level 3: 1.3.6.1.4.1.2.267.7.6.5 */ + /* Dilithium Level 3: 1.3.6.1.4.1.2.267.12.6.5 */ static const byte keyDilithium_Level3Oid[] = - {43, 6, 1, 4, 1, 2, 130, 11, 7, 6, 5}; + {43, 6, 1, 4, 1, 2, 130, 11, 12, 6, 5}; - /* Dilithium Level 5: 1.3.6.1.4.1.2.267.7.8.7 */ + /* Dilithium Level 5: 1.3.6.1.4.1.2.267.12.8.7 */ static const byte keyDilithium_Level5Oid[] = - {43, 6, 1, 4, 1, 2, 130, 11, 7, 8, 7}; + {43, 6, 1, 4, 1, 2, 130, 11, 12, 8, 7}; #endif /* HAVE_DILITHIUM */ #ifdef HAVE_SPHINCS /* Sphincs Fast Level 1: 1 3 9999 6 7 4 */ @@ -4322,7 +4317,6 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte keySphincsSmall_Level5Oid[] = {43, 206, 15, 6, 9, 7}; #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ /* curveType */ #ifdef HAVE_ECC @@ -4830,7 +4824,6 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(sigEd448Oid); break; #endif - #ifdef HAVE_PQC #ifdef HAVE_FALCON case CTC_FALCON_LEVEL1: oid = sigFalcon_Level1Oid; @@ -4881,7 +4874,6 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(sigSphincsSmall_Level5Oid); break; #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ default: break; } @@ -4943,7 +4935,6 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keyDhOid); break; #endif /* !NO_DH */ - #ifdef HAVE_PQC #ifdef HAVE_FALCON case FALCON_LEVEL1k: oid = keyFalcon_Level1Oid; @@ -4994,7 +4985,6 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(keySphincsSmall_Level5Oid); break; #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ default: break; } @@ -5875,7 +5865,7 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, const byte* checkOid = NULL; word32 checkOidSz; #endif /* NO_VERIFY_OID */ -#ifdef HAVE_PQC +#if defined(HAVE_SPHINCS) word32 found_collision = 0; #endif (void)oidType; @@ -5887,7 +5877,7 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, actualOidSz = (word32)length; #endif /* NO_VERIFY_OID */ -#if defined(HAVE_PQC) && defined(HAVE_LIBOQS) && defined(HAVE_SPHINCS) +#if defined(HAVE_SPHINCS) /* Since we are summing it up, there could be collisions...and indeed there * are: SPHINCS_FAST_LEVEL1 and SPHINCS_FAST_LEVEL3. * @@ -5901,7 +5891,7 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, sizeof(sigSphincsFast_Level3Oid)) == 0) { found_collision = SPHINCS_FAST_LEVEL3k; } -#endif /* HAVE_PQC */ +#endif /* HAVE_SPHINCS */ /* Sum it up for now. */ while (length--) { @@ -5910,11 +5900,11 @@ static int GetOID(const byte* input, word32* inOutIdx, word32* oid, idx++; } -#ifdef HAVE_PQC +#ifdef HAVE_SPHINCS if (found_collision) { *oid = found_collision; } -#endif /* HAVE_PQC */ +#endif /* HAVE_SPHINCS */ /* Return the index after the OID data. */ *inOutIdx = idx; @@ -6933,7 +6923,7 @@ int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, ret = GetOctetString(input, &idx, &length, sz); if (ret < 0) { - if (ret == BUFFER_E) + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) return ASN_PARSE_E; /* Some private keys don't expect an octet string */ WOLFSSL_MSG("Couldn't find Octet string"); @@ -7227,7 +7217,7 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, return (int)(tmpSz + sz); #else DECL_ASNSETDATA(dataASN, pkcs8KeyASN_Length); - int sz; + int sz = 0; int ret = 0; word32 keyIdx = 0; word32 tmpAlgId = 0; @@ -7565,7 +7555,6 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, } else #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT && !NO_ASN_CRYPT */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) if ((ks == FALCON_LEVEL1k) || (ks == FALCON_LEVEL5k)) { #ifdef WOLFSSL_SMALL_STACK @@ -7627,7 +7616,8 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, } else #endif /* HAVE_FALCON */ - #if defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) if ((ks == DILITHIUM_LEVEL2k) || (ks == DILITHIUM_LEVEL3k) || (ks == DILITHIUM_LEVEL5k)) { @@ -7685,7 +7675,7 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, #endif } else - #endif /* HAVE_DILITHIUM */ +#endif /* HAVE_DILITHIUM && !WOLFSSL_DILITHIUM_VERIFY_ONLY */ #if defined(HAVE_SPHINCS) if ((ks == SPHINCS_FAST_LEVEL1k) || (ks == SPHINCS_FAST_LEVEL3k) || @@ -7757,7 +7747,6 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, } else #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ { ret = 0; } @@ -7770,17 +7759,59 @@ int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, * return 1 (true) on match * return 0 or negative value on failure/error * - * key : buffer holding DER format key - * keySz : size of key buffer - * der : a initialized and parsed DecodedCert holding a certificate */ -int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der) + * key : buffer holding DER format key + * keySz : size of key buffer + * der : a initialized and parsed DecodedCert holding a certificate + * checkAlt : indicate if we check primary or alternative key + */ +int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der, + int checkAlt) { + int ret = 0; + if (key == NULL || der == NULL) { return BAD_FUNC_ARG; } - return wc_CheckPrivateKey(key, keySz, der->publicKey, - der->pubKeySize, (enum Key_Sum) der->keyOID); +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (checkAlt && der->sapkiDer != NULL) { + /* We have to decode the public key first */ + word32 idx = 0; + /* Dilithium has the largest public key at the moment */ + word32 pubKeyLen = DILITHIUM_MAX_PUB_KEY_SIZE; + byte* decodedPubKey = (byte*)XMALLOC(pubKeyLen, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (decodedPubKey == NULL) { + ret = MEMORY_E; + } + if (ret == 0) { + if (der->sapkiOID == RSAk || der->sapkiOID == ECDSAk) { + /* Simply copy the data */ + XMEMCPY(decodedPubKey, der->sapkiDer, der->sapkiLen); + pubKeyLen = der->sapkiLen; + } + else { + ret = DecodeAsymKeyPublic(der->sapkiDer, &idx, der->sapkiLen, + decodedPubKey, &pubKeyLen, + der->sapkiOID); + } + } + if (ret == 0) { + ret = wc_CheckPrivateKey(key, keySz, decodedPubKey, pubKeyLen, + (enum Key_Sum) der->sapkiOID); + } + XFREE(decodedPubKey, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + } + else +#endif + { + ret = wc_CheckPrivateKey(key, keySz, der->publicKey, + der->pubKeySize, (enum Key_Sum) der->keyOID); + } + + (void)checkAlt; + + return ret; } #endif /* HAVE_PKCS12 || !NO_CHECK_PRIVATE_KEY */ @@ -8060,7 +8091,6 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, XFREE(ed448, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT && !NO_ASN_CRYPT */ -#if defined(HAVE_PQC) #if defined(HAVE_FALCON) if (*algoID == 0) { falcon_key *falcon = (falcon_key *)XMALLOC(sizeof(*falcon), heap, @@ -8096,7 +8126,8 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, XFREE(falcon, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* HAVE_FALCON */ -#if defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) if (*algoID == 0) { dilithium_key *dilithium = (dilithium_key *)XMALLOC(sizeof(*dilithium), heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -8142,7 +8173,7 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, } XFREE(dilithium, heap, DYNAMIC_TYPE_TMP_BUFFER); } -#endif /* HAVE_DILITHIUM */ +#endif /* HAVE_DILITHIUM && !WOLFSSL_DILITHIUM_VERIFY_ONLY */ #if defined(HAVE_SPHINCS) if (*algoID == 0) { sphincs_key *sphincs = (sphincs_key *)XMALLOC(sizeof(*sphincs), @@ -8220,7 +8251,6 @@ int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, XFREE(sphincs, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ /* if flag is not set then this is not a key that we understand. */ if (*algoID == 0) { @@ -8605,7 +8635,7 @@ int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, if (ret == 0) { ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid, curveOidSz); - if (ret == LENGTH_ONLY_E) + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) ret = 0; } if (ret == 0) { @@ -8861,7 +8891,7 @@ int DecryptContent(byte* input, word32 sz, const char* password, int passwordSz) DECL_ASNGETDATA(dataASN, pbes2ParamsASN_Length); int ret = 0; int id = 0; - int version; + int version = 0; word32 idx = 0; word32 pIdx = 0; word32 iterations = 0; @@ -9915,7 +9945,7 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) #if !defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)) /* If ASN_DH_KEY_E: Check if input started at beginning of key */ - if (ret == ASN_DH_KEY_E) { + if (ret == WC_NO_ERR_TRACE(ASN_DH_KEY_E)) { *inOutIdx = temp; /* the version (0) - private only (for public skip) */ @@ -10076,7 +10106,7 @@ int wc_DhKeyToDer(DhKey* key, byte* output, word32* outSz, int exportPriv) /* DH Parameters sequence with P and G */ total = 0; ret = wc_DhParamsToDer(key, NULL, &total); - if (ret != LENGTH_ONLY_E) + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) return ret; idx += total; @@ -10725,7 +10755,7 @@ int wc_DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, } } /* An alternate pass if default certificate fails parsing */ - if (ret == ASN_PARSE_E) { + if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E)) { *inOutIdx = (word32)temp; if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) return ASN_PARSE_E; @@ -11366,6 +11396,47 @@ DNS_entry* AltNameNew(void* heap) return ret; } +DNS_entry* AltNameDup(DNS_entry* from, void* heap) +{ + DNS_entry* ret; + + ret = AltNameNew(heap); + if (ret == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return NULL; + } + + ret->type = from->type; + ret->len = from->len; + + + ret->name = CopyString(from->name, from->len, heap, DYNAMIC_TYPE_ALTNAME); +#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) + ret->ipString = CopyString(from->ipString, 0, heap, DYNAMIC_TYPE_ALTNAME); +#endif +#ifdef OPENSSL_ALL + ret->ridString = CopyString(from->ridString, 0, heap, DYNAMIC_TYPE_ALTNAME); +#endif + if (ret->name == NULL +#if defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME) + || (from->ipString != NULL && ret->ipString == NULL) +#endif +#ifdef OPENSSL_ALL + || (from->ridString != NULL && ret->ridString == NULL) +#endif + ) { + WOLFSSL_MSG("\tOut of Memory"); + FreeAltNames(ret, heap); + return NULL; + } + +#ifdef WOLFSSL_FPKI + ret->oidSum = from->oidSum; +#endif + + return ret; +} + #ifndef IGNORE_NAME_CONSTRAINTS @@ -11471,8 +11542,8 @@ static int GetCertHeader(DecodedCert* cert) } #endif -#if defined(HAVE_ED25519) || defined(HAVE_ED448) || (defined(HAVE_PQC) && \ - defined(HAVE_LIBOQS)) +#if defined(HAVE_ED25519) || defined(HAVE_ED448) || defined(HAVE_FALCON) || \ + defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS) /* Store the key data under the BIT_STRING in dynamically allocated data. * * @param [in, out] cert Certificate object. @@ -11717,7 +11788,7 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int outLen, #endif PRIVATE_KEY_LOCK(); /* LENGTH_ONLY_E on success. */ - if (ret == LENGTH_ONLY_E) { + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { ret = 0; } } @@ -12545,7 +12616,6 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx, ret = StoreKey(cert, source, &srcIdx, maxIdx); break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) && defined(HAVE_LIBOQS) #ifdef HAVE_FALCON case FALCON_LEVEL1k: cert->pkCurveOID = FALCON_LEVEL1k; @@ -12596,7 +12666,6 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx, ret = StoreKey(cert, source, &srcIdx, maxIdx); break; #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ #ifndef NO_DSA case DSAk: cert->publicKey = source + pubIdx; @@ -13834,6 +13903,18 @@ static int GetCertName(DecodedCert* cert, char* full, byte* hash, int nameType, return ASN_PARSE_E; } + #ifndef WOLFSSL_NO_ASN_STRICT + /* RFC 5280 section 4.1.2.4 lists a DirecotryString as being + * 1..MAX in length */ + if (strLen < 1) { + WOLFSSL_MSG("Non conforming DirectoryString of length 0 was" + " found"); + WOLFSSL_MSG("Use WOLFSSL_NO_ASN_STRICT if wanting to allow" + " empty DirectoryString's"); + return ASN_PARSE_E; + } + #endif + if (id == ASN_COMMON_NAME) { if (nameType == SUBJECT) { cert->subjectCN = (char *)&input[srcIdx]; @@ -14388,7 +14469,7 @@ static int GetCertName(DecodedCert* cert, char* full, byte* hash, int nameType, DECL_ASNGETDATA(dataASN, rdnASN_Length); int ret = 0; word32 idx = 0; - int len; + int len = 0; word32 srcIdx = *inOutIdx; #ifdef WOLFSSL_X509_NAME_AVAILABLE WOLFSSL_X509_NAME* dName = NULL; @@ -14464,6 +14545,18 @@ static int GetCertName(DecodedCert* cert, char* full, byte* hash, int nameType, /* Get string reference. */ GetASN_GetRef(&dataASN[RDNASN_IDX_ATTR_VAL], &str, &strLen); + #ifndef WOLFSSL_NO_ASN_STRICT + /* RFC 5280 section 4.1.2.4 lists a DirecotryString as being + * 1..MAX in length */ + if (ret == 0 && strLen < 1) { + WOLFSSL_MSG("Non conforming DirectoryString of length 0 was" + " found"); + WOLFSSL_MSG("Use WOLFSSL_NO_ASN_STRICT if wanting to allow" + " empty DirectoryString's"); + ret = ASN_PARSE_E; + } + #endif + /* Convert BER tag to a OpenSSL type. */ switch (tag) { case CTC_UTF8: @@ -15585,8 +15678,15 @@ int DecodeToKey(DecodedCert* cert, int verify) int ret; int badDate = 0; +#ifdef WOLFSSL_DUAL_ALG_CERTS + /* Call internal version and decode completely to also handle extensions. + * This is required to parse a potential alternative public key in the + * SubjectAlternativeKey extension. */ + ret = DecodeCertInternal(cert, verify, NULL, &badDate, 0, 0); +#else /* Call internal version and stop after public key. */ ret = DecodeCertInternal(cert, verify, NULL, &badDate, 0, 1); +#endif /* Always return date errors. */ if (ret == 0) { ret = badDate; @@ -15893,7 +15993,6 @@ static WC_INLINE int IsSigAlgoECC(word32 algoOID) #ifdef HAVE_CURVE448 || (algoOID == X448k) #endif - #ifdef HAVE_PQC #ifdef HAVE_FACON || (algoOID == FALCON_LEVEL1k) || (algoOID == FALCON_LEVEL5k) @@ -15911,7 +16010,6 @@ static WC_INLINE int IsSigAlgoECC(word32 algoOID) || (algoOID == SPHINCS_SMALL_LEVEL3k) || (algoOID == SPHINCS_SMALL_LEVEL5k) #endif - #endif /* HAVE_PQC */ ); } @@ -16090,7 +16188,7 @@ word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, #else DECL_ASNSETDATA(dataASN, digestInfoASN_Length); int ret = 0; - int sz; + int sz = 0; unsigned char dgst[WC_MAX_DIGEST_SIZE]; CALLOC_ASNSETDATA(dataASN, digestInfoASN_Length, ret, NULL); @@ -16229,7 +16327,6 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) sigCtx->key.ed448 = NULL; break; #endif /* HAVE_ED448 */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: @@ -16262,7 +16359,6 @@ void FreeSignatureCtx(SignatureCtx* sigCtx) sigCtx->key.sphincs = NULL; break; #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ default: break; } /* switch (keyOID) */ @@ -16408,7 +16504,6 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, */ break; #endif - #ifdef HAVE_PQC #ifdef HAVE_FALCON case CTC_FALCON_LEVEL1: case CTC_FALCON_LEVEL5: @@ -16432,7 +16527,6 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, /* Hashes done in signing operation. */ break; #endif - #endif /* HAVE_PQC */ default: ret = HASH_TYPE_E; @@ -16812,7 +16906,6 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case FALCON_LEVEL1k: { @@ -16869,7 +16962,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_FALCON */ - #if defined(HAVE_DILITHIUM) + #if defined(HAVE_DILITHIUM) && \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_NO_ASN1) case DILITHIUM_LEVEL2k: { word32 idx = 0; @@ -17110,7 +17205,6 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ default: WOLFSSL_MSG("Verify Key type unknown"); ret = ASN_UNKNOWN_OID_E; @@ -17162,7 +17256,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, !defined(WOLFSSL_RENESAS_TSIP_TLS) else #else - if (!sigCtx->pkCbRsa || ret == CRYPTOCB_UNAVAILABLE) + if (!sigCtx->pkCbRsa || + ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) #endif /* WOLFSSL_RENESAS_FSPSM_TLS */ #endif /* HAVE_PK_CALLBACKS */ { @@ -17236,7 +17331,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx, !defined(WOLFSSL_RENESAS_TSIP_TLS) else #else - if (!sigCtx->pkCbEcc || ret == CRYPTOCB_UNAVAILABLE) + if (!sigCtx->pkCbEcc || + ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) #endif /* WOLFSSL_RENESAS_FSPSM_TLS */ #endif /* HAVE_PK_CALLBACKS */ { @@ -17264,7 +17360,6 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) case FALCON_LEVEL1k: case FALCON_LEVEL5k: @@ -17275,7 +17370,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_FALCON */ - #if defined(HAVE_DILITHIUM) + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_VERIFY) case DILITHIUM_LEVEL2k: case DILITHIUM_LEVEL3k: case DILITHIUM_LEVEL5k: @@ -17300,13 +17395,12 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ default: break; } /* switch (keyOID) */ #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { goto exit_cs; } #endif @@ -17453,7 +17547,6 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_ED448 */ - #ifdef HAVE_PQC #ifdef HAVE_FALCON case FALCON_LEVEL1k: { @@ -17583,7 +17676,6 @@ static int ConfirmSignature(SignatureCtx* sigCtx, break; } #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ default: break; } /* switch (keyOID) */ @@ -17605,7 +17697,7 @@ static int ConfirmSignature(SignatureCtx* sigCtx, WOLFSSL_LEAVE("ConfirmSignature", ret); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) return ret; #endif @@ -18202,6 +18294,7 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag, } #endif /* WOLFSSL_QT || OPENSSL_ALL */ + #ifdef OPENSSL_ALL /* GeneralName choice: registeredID */ else if (tag == (ASN_CONTEXT_SPECIFIC | ASN_RID_TYPE)) { ret = SetDNSEntry(cert, (const char*)(input + idx), len, @@ -18210,6 +18303,7 @@ static int DecodeGeneralName(const byte* input, word32* inOutIdx, byte tag, idx += (word32)len; } } + #endif #endif /* IGNORE_NAME_CONSTRAINTS */ #if defined(WOLFSSL_SEP) || defined(WOLFSSL_FPKI) /* GeneralName choice: otherName */ @@ -18852,6 +18946,7 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert) word32 idx = 0; int length = 0; int ret = 0; + word32 numNames = 0; WOLFSSL_ENTER("DecodeAltNames"); @@ -18884,6 +18979,13 @@ static int DecodeAltNames(const byte* input, word32 sz, DecodedCert* cert) while ((ret == 0) && (idx < sz)) { ASNGetData dataASN[altNameASN_Length]; + numNames++; + if (numNames > WOLFSSL_MAX_ALT_NAMES) { + WOLFSSL_MSG("\tToo many subject alternative names"); + ret = ASN_ALT_NAME_E; + break; + } + /* Clear dynamic data items. */ XMEMSET(dataASN, 0, sizeof(dataASN)); /* Parse GeneralName with the choices supported. */ @@ -19751,7 +19853,7 @@ static int DecodeExtKeyUsage(const byte* input, word32 sz, DecodedCert* cert) while (idx < (word32)sz) { ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz); - if (ret == ASN_UNKNOWN_OID_E) + if (ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E)) continue; else if (ret < 0) return ret; @@ -19831,7 +19933,7 @@ static int DecodeExtKeyUsage(const byte* input, word32 sz, DecodedCert* cert) ret = GetASN_Items(keyPurposeIdASN, dataASN, keyPurposeIdASN_Length, 0, input, &idx, sz); /* Skip unknown OIDs. */ - if (ret == ASN_UNKNOWN_OID_E) { + if (ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E)) { ret = 0; } else if (ret == 0) { @@ -19994,13 +20096,16 @@ static int DecodeSubtreeGeneralName(const byte* input, word32 sz, byte tag, * @param [in] input Buffer holding data. * @param [in] sz Size of data in buffer. * @param [in, out] head Linked list of subtree names. + * @param [in] limit If > 0, limit on number of tree + * entries to process, exceeding + * is an error. * @param [in] heap Dynamic memory hint. * @return 0 on success. * @return MEMORY_E when dynamic memory allocation fails. * @return ASN_PARSE_E when SEQUENCE is not found as expected. */ static int DecodeSubtree(const byte* input, word32 sz, Base_entry** head, - void* heap) + word32 limit, void* heap) { #ifndef WOLFSSL_ASN_TEMPLATE word32 idx = 0; @@ -20078,6 +20183,7 @@ static int DecodeSubtree(const byte* input, word32 sz, Base_entry** head, DECL_ASNGETDATA(dataASN, subTreeASN_Length); word32 idx = 0; int ret = 0; + word32 cnt = 0; (void)heap; @@ -20087,6 +20193,14 @@ static int DecodeSubtree(const byte* input, word32 sz, Base_entry** head, while ((ret == 0) && (idx < (word32)sz)) { byte minVal = 0; byte maxVal = 0; + if (limit > 0) { + cnt++; + if (cnt > limit) { + WOLFSSL_MSG("too many name constraints"); + ret = ASN_NAME_INVALID_E; + break; + } + } /* Clear dynamic data and set choice for GeneralName and location to * store minimum and maximum. @@ -20185,7 +20299,7 @@ static int DecodeNameConstraints(const byte* input, word32 sz, } if (DecodeSubtree(input + idx, (word32)length, subtree, - cert->heap) < 0) { + WOLFSSL_MAX_NAME_CONSTRAINTS, cert->heap) < 0) { WOLFSSL_MSG("\terror parsing subtree"); return ASN_PARSE_E; } @@ -20212,7 +20326,8 @@ static int DecodeNameConstraints(const byte* input, word32 sz, ret = DecodeSubtree( dataASN[NAMECONSTRAINTSASN_IDX_PERMIT].data.ref.data, dataASN[NAMECONSTRAINTSASN_IDX_PERMIT].data.ref.length, - &cert->permittedNames, cert->heap); + &cert->permittedNames, WOLFSSL_MAX_NAME_CONSTRAINTS, + cert->heap); } } if (ret == 0) { @@ -20221,7 +20336,8 @@ static int DecodeNameConstraints(const byte* input, word32 sz, ret = DecodeSubtree( dataASN[NAMECONSTRAINTSASN_IDX_EXCLUDE].data.ref.data, dataASN[NAMECONSTRAINTSASN_IDX_EXCLUDE].data.ref.length, - &cert->excludedNames, cert->heap); + &cert->excludedNames, WOLFSSL_MAX_NAME_CONSTRAINTS, + cert->heap); } } @@ -21072,7 +21188,13 @@ static int DecodeExtensionType(const byte* input, word32 length, word32 oid, ret = ASN_PARSE_E; } #else - WOLFSSL_MSG("Certificate Policy extension not supported yet."); + WOLFSSL_MSG("Certificate Policy extension not supported."); + #ifndef WOLFSSL_NO_ASN_STRICT + if (critical) { + WOLFSSL_ERROR_VERBOSE(ASN_CRIT_EXT_E); + ret = ASN_CRIT_EXT_E; + } + #endif #endif break; @@ -21335,7 +21457,7 @@ static int DecodeCertExtensions(DecodedCert* cert) ret = DecodeExtensionType(input + idx, (word32)length, oid, critical, cert, NULL); - if (ret == ASN_CRIT_EXT_E) { + if (ret == WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) { ret = 0; criticalFail = 1; } @@ -21425,7 +21547,7 @@ static int DecodeCertExtensions(DecodedCert* cert) } /* Don't fail criticality until all other extensions have been checked. */ - if (ret == ASN_CRIT_EXT_E) { + if (ret == WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) { criticalRet = ASN_CRIT_EXT_E; ret = 0; } @@ -21670,9 +21792,9 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt, DECL_ASNGETDATA(dataASN, x509CertASN_Length); int ret = 0; int badDate = 0; - byte version; + byte version = 0; word32 idx; - word32 serialSz; + word32 serialSz = 0; const unsigned char* issuer = NULL; word32 issuerSz = 0; const unsigned char* subject = NULL; @@ -21755,6 +21877,19 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt, /* Set fields extracted from data. */ cert->version = version; cert->serialSz = (int)serialSz; + + #if !defined(WOLFSSL_NO_ASN_STRICT) && !defined(WOLFSSL_PYTHON) + /* RFC 5280 section 4.1.2.2 states that non-conforming CAs may issue + * a negative or zero serial number and should be handled gracefully. + * Since it is a non-conforming CA that issues a serial of 0 then we + * treat it as an error here. */ + if (cert->serialSz == 1 && cert->serial[0] == 0) { + WOLFSSL_MSG("Error serial number of 0, use WOLFSSL_NO_ASN_STRICT " + "if wanted"); + ret = ASN_PARSE_E; + } + #endif + cert->signatureOID = dataASN[X509CERTASN_IDX_TBS_ALGOID_OID].data.oid.sum; cert->keyOID = dataASN[X509CERTASN_IDX_TBS_SPUBKEYINFO_ALGO_OID].data.oid.sum; cert->certBegin = dataASN[X509CERTASN_IDX_TBS_SEQ].offset; @@ -21948,7 +22083,7 @@ static int DecodeCertInternal(DecodedCert* cert, int verify, int* criticalExt, /* Decode the extension data starting at [3]. */ ret = DecodeCertExtensions(cert); if (criticalExt != NULL) { - if (ret == ASN_CRIT_EXT_E) { + if (ret == WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) { /* Return critical extension not recognized. */ *criticalExt = ret; ret = 0; @@ -22139,7 +22274,7 @@ static int DecodeCertReqAttrValue(DecodedCert* cert, int* criticalExt, /* Decode and validate extensions. */ ret = DecodeCertExtensions(cert); - if (ret == ASN_CRIT_EXT_E) { + if (ret == WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) { /* Return critical extension not recognized. */ *criticalExt = ret; ret = 0; @@ -22366,7 +22501,7 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) char* ptr; #endif - ret = ParseCertRelative(cert, type, verify, cm); + ret = ParseCertRelative(cert, type, verify, cm, NULL); if (ret < 0) return ret; @@ -23119,9 +23254,7 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, #endif /* WOLFSSL_ASN_TEMPLATE */ } -#ifdef OPENSSL_EXTRA -/* Call CheckCertSignature_ex using a public key buffer for verification - */ +/* Call CheckCertSignature_ex using a public key buffer for verification */ int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID) { @@ -23129,6 +23262,7 @@ int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, pubKey, pubKeySz, pubKeyOID, 0); } +/* Call CheckCertSignature_ex using a public key and oid */ int wc_CheckCertSigPubKey(const byte* cert, word32 certSz, void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID) { @@ -23144,15 +23278,12 @@ int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, void* heap, pubKey, pubKeySz, pubKeyOID, 1); } #endif /* WOLFSSL_CERT_REQ */ -#endif /* OPENSSL_EXTRA */ -#ifdef WOLFSSL_SMALL_CERT_VERIFY -/* Call CheckCertSignature_ex using a certificate manager (cm) - */ -int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm) + +/* Call CheckCertSignature_ex using a certificate manager (cm) */ +int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm) { return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0, 0); } -#endif /* WOLFSSL_SMALL_CERT_VERIFY */ #endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */ #if (defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) || \ @@ -23257,8 +23388,18 @@ int wc_CertGetPubKey(const byte* cert, word32 certSz, return ret; } #endif +Signer* findSignerByName(Signer *list, byte *hash) +{ + Signer *s; + for (s = list; s != NULL; s = s->next) { + if (XMEMCMP(s->subjectNameHash, hash, SIGNER_DIGEST_SIZE) == 0) { + return s; + } + } + return NULL; +} -int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) +int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm, Signer *extraCAList) { int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE @@ -23271,6 +23412,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) int idx = 0; #endif byte* sce_tsip_encRsaKeyIdx; + (void)extraCAList; if (cert == NULL) { return BAD_FUNC_ARG; @@ -23286,7 +23428,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) cert->badDate = 0; cert->criticalExt = 0; if ((ret = DecodeToKey(cert, verify)) < 0) { - if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { + if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) || + ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { cert->badDate = ret; if (verify == VERIFY_SKIP_DATE) ret = 0; @@ -23449,7 +23592,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) cert->extensionsIdx = cert->srcIdx; /* for potential later use */ if ((ret = DecodeCertExtensions(cert)) < 0) { - if (ret == ASN_CRIT_EXT_E) { + if (ret == WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) { cert->criticalExt = ret; } else { @@ -23483,7 +23626,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) cert->extensionsIdx = cert->srcIdx; /* for potential later use */ if ((ret = DecodeCertExtensions(cert)) < 0) { - if (ret == ASN_CRIT_EXT_E) + if (ret == WC_NO_ERR_TRACE(ASN_CRIT_EXT_E)) cert->criticalExt = ret; else return ret; @@ -23536,7 +23679,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) #endif { ret = DecodeCert(cert, verify, &cert->criticalExt); - if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) { + if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) || + ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { cert->badDate = ret; if (verify == VERIFY_SKIP_DATE) ret = 0; @@ -23587,8 +23731,13 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (!cert->selfSigned || (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE)) { cert->ca = NULL; +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (extraCAList != NULL) { + cert->ca = findSignerByName(extraCAList, cert->issuerHash); + } +#endif #ifndef NO_SKID - if (cert->extAuthKeyIdSet) { + if (cert->ca == NULL && cert->extAuthKeyIdSet) { cert->ca = GetCA(cm, cert->extAuthKeyId); #ifdef WOLFSSL_AKID_NAME if (cert->ca == NULL) { @@ -23733,13 +23882,19 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (cert->ca) { if (verify == VERIFY || verify == VERIFY_OCSP || verify == VERIFY_SKIP_DATE) { + word32 keyOID = cert->ca->keyOID; + #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3) + if (cert->selfSigned && (cert->signatureOID == CTC_SM3wSM2)) { + keyOID = SM2k; + } + #endif /* try to confirm/verify signature */ 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, + keyOID, cert->signature, cert->sigLength, + cert->signatureOID, #ifdef WC_RSA_PSS cert->source + cert->sigParamsIndex, cert->sigParamsLength, @@ -23747,12 +23902,50 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) NULL, 0, #endif sce_tsip_encRsaKeyIdx)) != 0) { - if (ret != WC_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) { WOLFSSL_MSG("Confirm signature failed"); } WOLFSSL_ERROR_VERBOSE(ret); return ret; } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ret == 0) && cert->extAltSigAlgSet && + cert->extAltSigValSet) { + #ifndef WOLFSSL_SMALL_STACK + byte der[MAX_CERT_VERIFY_SZ]; + #else + byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, cert->heap, + DYNAMIC_TYPE_DCERT); + if (der == NULL) { + ret = MEMORY_E; + } else + #endif /* ! WOLFSSL_SMALL_STACK */ + { + ret = wc_GeneratePreTBS(cert, der, MAX_CERT_VERIFY_SZ); + + if (ret > 0) { + ret = ConfirmSignature(&cert->sigCtx, der, ret, + cert->ca->sapkiDer, cert->ca->sapkiLen, + cert->ca->sapkiOID, cert->altSigValDer, + cert->altSigValLen, cert->altSigAlgOID, + NULL, 0, NULL); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(der, cert->heap, DYNAMIC_TYPE_DCERT); + #endif /* WOLFSSL_SMALL_STACK */ + + if (ret != 0) { + WOLFSSL_MSG("Confirm alternative signature failed"); + WOLFSSL_ERROR_VERBOSE(ret); + return ret; + } + else { + WOLFSSL_MSG("Alt signature has been verified!"); + } + } + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ } #ifndef IGNORE_NAME_CONSTRAINTS if (verify == VERIFY || verify == VERIFY_OCSP || @@ -23769,6 +23962,7 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) } #ifdef WOLFSSL_CERT_REQ else if (type == CERTREQ_TYPE) { + /* try to confirm/verify signature */ if ((ret = ConfirmSignature(&cert->sigCtx, cert->source + cert->certBegin, cert->sigIndex - cert->certBegin, @@ -23781,12 +23975,50 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) NULL, 0, #endif sce_tsip_encRsaKeyIdx)) != 0) { - if (ret != WC_PENDING_E) { + if (ret != WC_NO_ERR_TRACE(WC_PENDING_E)) { WOLFSSL_MSG("Confirm signature failed"); } WOLFSSL_ERROR_VERBOSE(ret); return ret; } + + #ifdef WOLFSSL_DUAL_ALG_CERTS + if ((ret == 0) && cert->extAltSigAlgSet && + cert->extAltSigValSet) { + #ifndef WOLFSSL_SMALL_STACK + byte der[MAX_CERT_VERIFY_SZ]; + #else + byte *der = (byte*)XMALLOC(MAX_CERT_VERIFY_SZ, cert->heap, + DYNAMIC_TYPE_DCERT); + if (der == NULL) { + ret = MEMORY_E; + } else + #endif /* ! WOLFSSL_SMALL_STACK */ + { + ret = wc_GeneratePreTBS(cert, der, MAX_CERT_VERIFY_SZ); + + if (ret > 0) { + ret = ConfirmSignature(&cert->sigCtx, der, ret, + cert->sapkiDer, cert->sapkiLen, + cert->sapkiOID, cert->altSigValDer, + cert->altSigValLen, cert->altSigAlgOID, + NULL, 0, NULL); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(der, cert->heap, DYNAMIC_TYPE_DCERT); + #endif /* WOLFSSL_SMALL_STACK */ + + if (ret != 0) { + WOLFSSL_MSG("Confirm alternative signature failed"); + WOLFSSL_ERROR_VERBOSE(ret); + return ret; + } + else { + WOLFSSL_MSG("Alt signature has been verified!"); + } + } + } + #endif /* WOLFSSL_DUAL_ALG_CERTS */ } #endif else { @@ -23824,6 +24056,89 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) return ret; } +int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der) +{ + int ret = 0; + + if (signer == NULL || cert == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_DUAL_ALG_CERTS + if (ret == 0 && signer != NULL) { + if (cert->extSapkiSet && cert->sapkiLen > 0) { + /* Allocated space for alternative public key. */ + signer->sapkiDer = (byte*)XMALLOC(cert->sapkiLen, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (signer->sapkiDer == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(signer->sapkiDer, cert->sapkiDer, cert->sapkiLen); + signer->sapkiLen = cert->sapkiLen; + signer->sapkiOID = cert->sapkiOID; + } + } + } +#endif /* WOLFSSL_DUAL_ALG_CERTS */ + +#if defined(WOLFSSL_AKID_NAME) || defined(HAVE_CRL) + if (ret == 0 && signer != NULL) + ret = CalcHashId(cert->serial, (word32)cert->serialSz, + signer->serialHash); +#endif + if (ret == 0 && signer != NULL) { + #ifdef WOLFSSL_SIGNER_DER_CERT + ret = AllocDer(&signer->derCert, der->length, der->type, NULL); + } + if (ret == 0 && signer != NULL) { + XMEMCPY(signer->derCert->buffer, der->buffer, der->length); + #else + (void)der; + #endif + signer->keyOID = cert->keyOID; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } + signer->maxPathLen = cert->maxPathLen; + signer->selfSigned = cert->selfSigned; + #ifndef IGNORE_NAME_CONSTRAINTS + signer->permittedNames = cert->permittedNames; + signer->excludedNames = cert->excludedNames; + #endif + #ifndef NO_SKID + XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(signer->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + XMEMCPY(signer->issuerNameHash, cert->issuerHash, + SIGNER_DIGEST_SIZE); + #endif + #ifdef HAVE_OCSP + XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, + KEYID_SIZE); + #endif + signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage + : 0xFFFF; + signer->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->publicKey = 0; /* in case lock fails don't free here. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + signer->type = (byte)type; + } + return ret; +} + /* Create and init an new signer */ Signer* MakeSigner(void* heap) { @@ -23852,6 +24167,9 @@ void FreeSigner(Signer* signer, void* heap) (void)heap; XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN); XFREE((void*)signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); +#ifdef WOLFSSL_DUAL_ALG_CERTS + XFREE(signer->sapkiDer, heap, DYNAMIC_TYPE_PUBLIC_KEY); +#endif #ifndef IGNORE_NAME_CONSTRAINTS if (signer->permittedNames) FreeNameSubtrees(signer->permittedNames, heap); @@ -24080,7 +24398,7 @@ int wc_GetSerialNumber(const byte* input, word32* inOutIdx, int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); if (pDer) { int dynType = 0; DerBuffer* der; @@ -24111,18 +24429,31 @@ int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) der->buffer = (byte*)der + sizeof(DerBuffer); der->length = length; ret = 0; /* Success */ + } else { + ret = BAD_FUNC_ARG; } return ret; } +int AllocCopyDer(DerBuffer** pDer, const unsigned char* buff, word32 length, + int type, void* heap) +{ + int ret = AllocDer(pDer, length, type, heap); + if (ret == 0) { + XMEMCPY((*pDer)->buffer, buff, length); + } + + return ret; +} + void FreeDer(DerBuffer** pDer) { - if (pDer && *pDer) - { + if (pDer && *pDer) { DerBuffer* der = (DerBuffer*)*pDer; /* ForceZero private keys */ - if (der->type == PRIVATEKEY_TYPE && der->buffer != NULL) { + if (((der->type == PRIVATEKEY_TYPE) || + (der->type == ALT_PRIVATEKEY_TYPE)) && der->buffer != NULL) { ForceZero(der->buffer, der->length); } der->buffer = NULL; @@ -24198,7 +24529,6 @@ wcchar END_PUB_KEY = "-----END PUBLIC KEY-----"; wcchar BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; wcchar END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; #endif -#if defined(HAVE_PQC) #if defined(HAVE_FALCON) wcchar BEGIN_FALCON_LEVEL1_PRIV = "-----BEGIN FALCON_LEVEL1 PRIVATE KEY-----"; wcchar END_FALCON_LEVEL1_PRIV = "-----END FALCON_LEVEL1 PRIVATE KEY-----"; @@ -24228,7 +24558,6 @@ wcchar END_PUB_KEY = "-----END PUBLIC KEY-----"; wcchar BEGIN_SPHINCS_SMALL_LEVEL5_PRIV = "-----BEGIN SPHINCS_SMALL_LEVEL5 PRIVATE KEY-----"; wcchar END_SPHINCS_SMALL_LEVEL5_PRIV = "-----END SPHINCS_SMALL_LEVEL5 PRIVATE KEY-----"; #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ const int pem_struct_min_sz = XSTR_SIZEOF("-----BEGIN X509 CRL-----" "-----END X509 CRL-----"); @@ -24248,7 +24577,7 @@ static WC_INLINE const char* SkipEndOfLineChars(const char* line, int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (type) { case CA_TYPE: /* same as below */ @@ -24336,7 +24665,6 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) ret = 0; break; #endif -#ifdef HAVE_PQC #ifdef HAVE_FALCON case FALCON_LEVEL1_TYPE: if (header) *header = BEGIN_FALCON_LEVEL1_PRIV; @@ -24398,7 +24726,6 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) ret = 0; break; #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ case PUBLICKEY_TYPE: case ECC_PUBLICKEY_TYPE: if (header) *header = BEGIN_PUB_KEY; @@ -24424,6 +24751,7 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) ret = 0; break; default: + ret = BAD_FUNC_ARG; break; } return ret; @@ -24726,7 +25054,7 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, #endif outLen = 0; if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen)) - != LENGTH_ONLY_E) { + != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_ERROR_VERBOSE(err); return err; } @@ -25670,7 +25998,7 @@ static DNS_entry* FindAltName(struct DecodedCert* cert, int nameType, /* returns 0 on success */ int wc_GetUUIDFromCert(struct DecodedCert* cert, byte* uuid, word32* uuidSz) { - int ret = ALT_NAME_E; + int ret = WC_NO_ERR_TRACE(ALT_NAME_E); DNS_entry* id = NULL; do { @@ -25707,7 +26035,7 @@ int wc_GetUUIDFromCert(struct DecodedCert* cert, byte* uuid, word32* uuidSz) /* returns 0 on success */ int wc_GetFASCNFromCert(struct DecodedCert* cert, byte* fascn, word32* fascnSz) { - int ret = ALT_NAME_E; + int ret = WC_NO_ERR_TRACE(ALT_NAME_E); DNS_entry* id = NULL; do { @@ -25917,6 +26245,7 @@ int wc_RsaKeyToPublicDer_ex(RsaKey* key, byte* output, word32 inLen, #endif /* !NO_RSA && (WOLFSSL_CERT_GEN || WOLFSSL_KCAPI_RSA || ((OPENSSL_EXTRA || WOLFSSL_KEY_GEN))) */ +#endif /* NO_CERTS */ #if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || \ defined(WOLFSSL_KCAPI_RSA) || defined(WOLFSSL_SE050)) && \ @@ -25937,11 +26266,16 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) { #ifndef WOLFSSL_ASN_TEMPLATE int ret = 0, i; + int mpSz; word32 seqSz = 0, verSz = 0, intTotalLen = 0, outLen = 0; word32 sizes[RSA_INTS]; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; + mp_int* keyInt; +#ifndef WOLFSSL_NO_MALLOC + word32 rawLen; byte* tmps[RSA_INTS]; +#endif if (key == NULL) return BAD_FUNC_ARG; @@ -25949,18 +26283,18 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) if (key->type != RSA_PRIVATE) return BAD_FUNC_ARG; +#ifndef WOLFSSL_NO_MALLOC for (i = 0; i < RSA_INTS; i++) tmps[i] = NULL; +#endif /* write all big ints from key to DER tmps */ for (i = 0; i < RSA_INTS; i++) { - mp_int* keyInt = GetRsaInt(key, i); - int mpSz; - word32 rawLen; - + keyInt = GetRsaInt(key, i); ret = mp_unsigned_bin_size(keyInt); if (ret < 0) - return ret; + break; +#ifndef WOLFSSL_NO_MALLOC rawLen = (word32)ret + 1; ret = 0; if (output != NULL) { @@ -25971,8 +26305,11 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) break; } } - mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]); +#else + ret = 0; + mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, NULL); +#endif if (mpSz < 0) { ret = mpSz; break; @@ -26004,15 +26341,33 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) j += verSz; for (i = 0; i < RSA_INTS; i++) { +/* copy from tmps if we have malloc, otherwise re-export with buffer */ +#ifndef WOLFSSL_NO_MALLOC XMEMCPY(output + j, tmps[i], sizes[i]); j += sizes[i]; +#else + keyInt = GetRsaInt(key, i); + ret = mp_unsigned_bin_size(keyInt); + if (ret < 0) + break; + ret = 0; + /* This won't overrun output due to the outLen check above */ + mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, output + j); + if (mpSz < 0) { + ret = mpSz; + break; + } + j += mpSz; +#endif } } +#ifndef WOLFSSL_NO_MALLOC for (i = 0; i < RSA_INTS; i++) { if (tmps[i]) XFREE(tmps[i], key->heap, DYNAMIC_TYPE_RSA); } +#endif if (ret == 0) ret = (int)outLen; @@ -26061,6 +26416,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) #endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA */ +#ifndef NO_CERTS #ifdef WOLFSSL_CERT_GEN @@ -26321,7 +26677,7 @@ static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz, InitDecodedCert_ex((DecodedCert*)cert->decodedCert, der, derSz, cert->heap, devId); ret = ParseCertRelative((DecodedCert*)cert->decodedCert, - CERT_TYPE, 0, NULL); + CERT_TYPE, 0, NULL, NULL); if (ret >= 0) { cert->der = (byte*)der; } @@ -27565,6 +27921,17 @@ static int EncodeName(EncodedName* name, const char* nameStr, ret = BAD_FUNC_ARG; } +#ifdef WOLFSSL_CUSTOM_OID + if (ret == 0 && type == ASN_CUSTOM_NAME) { + if (cname == NULL || cname->custom.oidSz == 0) { + name->used = 0; + return 0; + } + } +#else + (void)cname; +#endif + CALLOC_ASNSETDATA(dataASN, rdnASN_Length, ret, NULL); if (ret == 0) { nameSz = (word32)XSTRLEN(nameStr); @@ -28164,7 +28531,8 @@ int SetName(byte* output, word32 outputSz, CertName* name) static int EncodePublicKey(int keyType, byte* output, int outLen, RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, ed448_key* ed448Key, - DsaKey* dsaKey) + DsaKey* dsaKey, falcon_key* falconKey, + dilithium_key* dilithiumKey, sphincs_key* sphincsKey) { int ret = 0; @@ -28174,6 +28542,9 @@ static int EncodePublicKey(int keyType, byte* output, int outLen, (void)ed25519Key; (void)ed448Key; (void)dsaKey; + (void)falconKey; + (void)dilithiumKey; + (void)sphincsKey; switch (keyType) { #ifndef NO_RSA @@ -28209,6 +28580,41 @@ static int EncodePublicKey(int keyType, byte* output, int outLen, } break; #endif + #if defined(HAVE_FALCON) + case FALCON_LEVEL1_KEY: + case FALCON_LEVEL5_KEY: + ret = wc_Falcon_PublicKeyToDer(falconKey, output, + (word32)outLen, 1); + if (ret <= 0) { + ret = PUBLIC_KEY_E; + } + break; + #endif /* HAVE_FALCON */ + #if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) + case DILITHIUM_LEVEL2_KEY: + case DILITHIUM_LEVEL3_KEY: + case DILITHIUM_LEVEL5_KEY: + ret = wc_Dilithium_PublicKeyToDer(dilithiumKey, output, + (word32)outLen, 1); + if (ret <= 0) { + ret = PUBLIC_KEY_E; + } + break; + #endif /* HAVE_DILITHIUM */ + #if defined(HAVE_SPHINCS) + case SPHINCS_FAST_LEVEL1_KEY: + case SPHINCS_FAST_LEVEL3_KEY: + case SPHINCS_FAST_LEVEL5_KEY: + case SPHINCS_SMALL_LEVEL1_KEY: + case SPHINCS_SMALL_LEVEL3_KEY: + case SPHINCS_SMALL_LEVEL5_KEY: + ret = wc_Sphincs_PublicKeyToDer(sphincsKey, output, + (word32)outLen, 1); + if (ret <= 0) { + ret = PUBLIC_KEY_E; + } + break; + #endif /* HAVE_SPHINCS */ default: ret = PUBLIC_KEY_E; break; @@ -28997,7 +29403,6 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, } #endif -#if defined(HAVE_PQC) #if defined(HAVE_FALCON) if ((cert->keyType == FALCON_LEVEL1_KEY) || (cert->keyType == FALCON_LEVEL5_KEY)) { @@ -29009,7 +29414,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, (word32)sizeof(der->publicKey), 1); } #endif /* HAVE_FALCON */ -#if defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) if ((cert->keyType == DILITHIUM_LEVEL2_KEY) || (cert->keyType == DILITHIUM_LEVEL3_KEY) || (cert->keyType == DILITHIUM_LEVEL5_KEY)) { @@ -29036,7 +29441,6 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, (word32)sizeof(der->publicKey), 1); } #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ if (der->publicKeySz <= 0) return PUBLIC_KEY_E; @@ -29542,7 +29946,6 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, word32 sz, } #endif /* HAVE_ED448 && HAVE_ED448_SIGN */ - #if defined(HAVE_PQC) #if defined(HAVE_FALCON) if (!rsaKey && !eccKey && !ed25519Key && !ed448Key && falconKey) { word32 outSz = sigSz; @@ -29569,7 +29972,6 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, word32 sz, ret = outSz; } #endif /* HAVE_SPHINCS */ - #endif /* HAVE_PQC */ break; } @@ -29577,7 +29979,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, word32 sz, exit_ms: #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { return ret; } #endif @@ -29786,7 +30188,6 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, cert->keyType = ED25519_KEY; else if (ed448Key) cert->keyType = ED448_KEY; -#ifdef HAVE_PQC #ifdef HAVE_FALCON else if ((falconKey != NULL) && (falconKey->level == 1)) cert->keyType = FALCON_LEVEL1_KEY; @@ -29821,7 +30222,6 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, && (sphincsKey->optim == SMALL_VARIANT)) cert->keyType = SPHINCS_SMALL_LEVEL5_KEY; #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ else return BAD_FUNC_ARG; @@ -29881,7 +30281,6 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key) { cert->keyType = ED448_KEY; } -#ifdef HAVE_PQC #ifdef HAVE_FALCON else if ((falconKey != NULL) && (falconKey->level == 1)) { cert->keyType = FALCON_LEVEL1_KEY; @@ -29927,7 +30326,6 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, cert->keyType = SPHINCS_SMALL_LEVEL5_KEY; } #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ else { ret = BAD_FUNC_ARG; } @@ -29975,7 +30373,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, if (ret >= 0) { /* Calculate public key encoding size. */ ret = EncodePublicKey(cert->keyType, NULL, 0, rsaKey, - eccKey, ed25519Key, ed448Key, dsaKey); + eccKey, ed25519Key, ed448Key, dsaKey, falconKey, + dilithiumKey, sphincsKey); publicKeySz = (word32)ret; } if (ret >= 0) { @@ -30155,7 +30554,8 @@ static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, .data.buffer.data, (int)dataASN[X509CERTASN_IDX_TBS_SPUBKEYINFO_SEQ] .data.buffer.length, - rsaKey, eccKey, ed25519Key, ed448Key, dsaKey); + rsaKey, eccKey, ed25519Key, ed448Key, dsaKey, + falconKey, dilithiumKey, sphincsKey); } if ((ret >= 0) && (!dataASN[X509CERTASN_IDX_TBS_EXT_SEQ].noOut)) { /* Encode extensions into buffer. */ @@ -30236,6 +30636,7 @@ int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, NULL, NULL, NULL, NULL); } + #ifdef WOLFSSL_CERT_REQ #ifndef WOLFSSL_ASN_TEMPLATE @@ -30499,7 +30900,6 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, (word32)sizeof(der->publicKey), 1); } #endif -#if defined(HAVE_PQC) #if defined(HAVE_FALCON) if ((cert->keyType == FALCON_LEVEL1_KEY) || (cert->keyType == FALCON_LEVEL5_KEY)) { @@ -30509,7 +30909,7 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, der->publicKey, (word32)sizeof(der->publicKey), 1); } #endif -#if defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) if ((cert->keyType == DILITHIUM_LEVEL2_KEY) || (cert->keyType == DILITHIUM_LEVEL3_KEY) || (cert->keyType == DILITHIUM_LEVEL5_KEY)) { @@ -30532,7 +30932,6 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, der->publicKey, (word32)sizeof(der->publicKey), 1); } #endif -#endif /* HAVE_PQC */ if (der->publicKeySz <= 0) return PUBLIC_KEY_E; @@ -30858,7 +31257,6 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, cert->keyType = ED25519_KEY; else if (ed448Key) cert->keyType = ED448_KEY; -#ifdef HAVE_PQC #ifdef HAVE_FALCON else if ((falconKey != NULL) && (falconKey->level == 1)) cert->keyType = FALCON_LEVEL1_KEY; @@ -30893,7 +31291,6 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, && (sphincsKey->optim == SMALL_VARIANT)) cert->keyType = SPHINCS_SMALL_LEVEL5_KEY; #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ else return BAD_FUNC_ARG; @@ -30954,7 +31351,6 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, else if (ed448Key != NULL) { cert->keyType = ED448_KEY; } -#ifdef HAVE_PQC #ifdef HAVE_FALCON else if ((falconKey != NULL) && (falconKey->level == 1)) { cert->keyType = FALCON_LEVEL1_KEY; @@ -31000,7 +31396,6 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, cert->keyType = SPHINCS_SMALL_LEVEL5_KEY; } #endif /* HAVE_SPHINCS */ -#endif /* HAVE_PQC */ else { ret = BAD_FUNC_ARG; } @@ -31022,7 +31417,8 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, if (ret >= 0) { /* Determine encode public key size. */ ret = EncodePublicKey(cert->keyType, NULL, 0, rsaKey, - eccKey, ed25519Key, ed448Key, dsaKey); + eccKey, ed25519Key, ed448Key, dsaKey, falconKey, + dilithiumKey, sphincsKey); publicKeySz = (word32)ret; } if (ret >= 0) { @@ -31136,7 +31532,8 @@ static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, ret = EncodePublicKey(cert->keyType, (byte*)dataASN[CERTREQBODYASN_IDX_SPUBKEYINFO_SEQ].data.buffer.data, (int)dataASN[CERTREQBODYASN_IDX_SPUBKEYINFO_SEQ].data.buffer.length, - rsaKey, eccKey, ed25519Key, ed448Key, dsaKey); + rsaKey, eccKey, ed25519Key, ed448Key, dsaKey, falconKey, + dilithiumKey, sphincsKey); } if ((ret >= 0 && derBuffer != NULL) && (!dataASN[CERTREQBODYASN_IDX_EXT_BODY].noOut)) { @@ -31266,7 +31663,7 @@ static int SignCert(int requestSz, int sType, byte* buf, word32 buffSz, MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, falconKey, dilithiumKey, sphincsKey, rng, (word32)sType, heap); #ifdef WOLFSSL_ASYNC_CRYPT - if (sigSz == WC_PENDING_E) { + if (sigSz == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Not free'ing certSignCtx->sig here because it could still be in use * with async operations. */ return sigSz; @@ -31379,7 +31776,7 @@ int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf, MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, ed448Key, falconKey, dilithiumKey, sphincsKey, rng, (word32)sType, heap); #ifdef WOLFSSL_ASYNC_CRYPT - if (ret == WC_PENDING_E) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { /* Not free'ing certSignCtx->sig here because it could still be in use * with async operations. */ return ret; @@ -31387,6 +31784,8 @@ int wc_MakeSigWithBitStr(byte *sig, int sigSz, int sType, byte* buf, #endif if (ret <= 0) { + XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->sig = NULL; return ret; } @@ -31460,6 +31859,7 @@ int wc_SignCert(int requestSz, int sType, byte* buf, word32 buffSz, NULL, NULL, NULL, rng); } + WOLFSSL_ABI int wc_MakeSelfCert(Cert* cert, byte* buf, word32 buffSz, RsaKey* key, WC_RNG* rng) @@ -31536,14 +31936,13 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, bufferSz = wc_Ed448PublicKeyToDer(ed448Key, buf, MAX_PUBLIC_KEY_SZ, 0); } #endif -#if defined(HAVE_PQC) #if defined(HAVE_FALCON) if (falconKey != NULL) { bufferSz = wc_Falcon_PublicKeyToDer(falconKey, buf, MAX_PUBLIC_KEY_SZ, 0); } #endif -#if defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_ASN1) if (dilithiumKey != NULL) { bufferSz = wc_Dilithium_PublicKeyToDer(dilithiumKey, buf, MAX_PUBLIC_KEY_SZ, 0); @@ -31555,7 +31954,6 @@ static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, MAX_PUBLIC_KEY_SZ, 0); } #endif -#endif /* HAVE_PQC */ if (bufferSz <= 0) { XFREE(buf, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -32023,7 +32421,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz, #endif InitDecodedCert_ex(decoded, der, (word32)derSz, NULL, devId); - ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); + ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0, NULL); if (ret < 0) { WOLFSSL_MSG("ParseCertRelative error"); @@ -32222,7 +32620,7 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz, int devId) #endif InitDecodedCert_ex(decoded, der, (word32)derSz, NULL, devId); - ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); + ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0, NULL); if (ret < 0) { WOLFSSL_MSG("ParseCertRelative error"); @@ -34075,7 +34473,7 @@ int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_x963(key, NULL, &pubSz); PRIVATE_KEY_LOCK(); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { #ifndef WOLFSSL_NO_MALLOC XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -34173,7 +34571,8 @@ int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, return (int)totalSz; #else DECL_ASNSETDATA(dataASN, eccKeyASN_Length); - word32 privSz, pubSz; + word32 privSz = 0; + word32 pubSz = 0; int sz = 0; int ret = 0; int curveIdSz = 0; @@ -34198,7 +34597,7 @@ int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_x963(key, NULL, &pubSz); PRIVATE_KEY_LOCK(); - if (ret == LENGTH_ONLY_E) + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) ret = 0; } } @@ -34300,7 +34699,7 @@ int wc_EccKeyDerSize(ecc_key* key, int pub) ret = wc_BuildEccKeyDer(key, NULL, &sz, pub, 1); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return ret; } return (int)sz; @@ -34367,7 +34766,7 @@ static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, /* get pkcs8 expected output size */ ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID, curveOID, oidSz); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { #ifndef WOLFSSL_NO_MALLOC XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -34467,13 +34866,11 @@ enum { || (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) \ || (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) \ || (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) \ - || (defined(HAVE_PQC) && defined(HAVE_FALCON)) \ - || (defined(HAVE_PQC) && defined(HAVE_DILITHIUM)) \ - || (defined(HAVE_PQC) && defined(HAVE_SPHINCS))) + || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)) -int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, - byte* privKey, word32* privKeyLen, - byte* pubKey, word32* pubKeyLen, int keyType) +int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, word32 inSz, + const byte** privKey, word32* privKeyLen, + const byte** pubKey, word32* pubKeyLen, int keyType) { #ifndef WOLFSSL_ASN_TEMPLATE word32 oid; @@ -34528,12 +34925,9 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, endKeyIdx = (int)*inOutIdx; } - if ((word32)privSz > *privKeyLen) - return BUFFER_E; - if (endKeyIdx == (int)*inOutIdx) { *privKeyLen = (word32)privSz; - XMEMCPY(privKey, priv, *privKeyLen); + *privKey = priv; if (pubKeyLen != NULL) *pubKeyLen = 0; } @@ -34547,17 +34941,14 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, return ASN_PARSE_E; } - if ((word32)pubSz > *pubKeyLen) - return BUFFER_E; - pub = input + *inOutIdx; *inOutIdx += (word32)pubSz; *privKeyLen = (word32)privSz; - XMEMCPY(privKey, priv, *privKeyLen); + *privKey = priv; *pubKeyLen = (word32)pubSz; if (pubKey != NULL) - XMEMCPY(pubKey, pub, *pubKeyLen); + *pubKey = pub; } if (endKeyIdx != (int)*inOutIdx) return ASN_PARSE_E; @@ -34581,33 +34972,22 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, } } } - /* Check the private value length is correct. */ - if ((ret == 0) && dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length - > *privKeyLen) { - ret = ASN_PARSE_E; + if (ret == 0) { + /* Import private value. */ + *privKeyLen = dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length; + *privKey = dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.data; } if ((ret == 0) && dataASN[EDKEYASN_IDX_PUBKEY].tag == 0) { - *privKeyLen = dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length; - XMEMCPY(privKey, dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.data, - *privKeyLen); + /* Set public length to 0 as not seen. */ if (pubKeyLen != NULL) *pubKeyLen = 0; } - else if ((ret == 0) && - (pubKeyLen != NULL) && - (dataASN[EDKEYASN_IDX_PUBKEY].data.ref.length > *pubKeyLen)) { - ret = ASN_PARSE_E; - } else if (ret == 0) { - /* Import private and public value. */ - *privKeyLen = dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.length; - XMEMCPY(privKey, dataASN[EDKEYASN_IDX_PKEY_CURVEPKEY].data.ref.data, - *privKeyLen); + /* Import public value. */ if (pubKeyLen != NULL) *pubKeyLen = dataASN[EDKEYASN_IDX_PUBKEY].data.ref.length; if (pubKey != NULL && pubKeyLen != NULL) - XMEMCPY(pubKey, dataASN[EDKEYASN_IDX_PUBKEY].data.ref.data, - *pubKeyLen); + *pubKey = dataASN[EDKEYASN_IDX_PUBKEY].data.ref.data; } FREE_ASNGETDATA(dataASN, NULL); @@ -34615,8 +34995,46 @@ int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, #endif /* WOLFSSL_ASN_TEMPLATE */ } -int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, +int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, + byte* privKey, word32* privKeyLen, byte* pubKey, word32* pubKeyLen, int keyType) +{ + int ret = 0; + const byte* privKeyPtr = NULL; + const byte* pubKeyPtr = NULL; + word32 privKeyPtrLen = 0; + word32 pubKeyPtrLen = 0; + + if (privKey == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, &privKeyPtr, + &privKeyPtrLen, &pubKeyPtr, &pubKeyPtrLen, keyType); + } + if ((ret == 0) && (privKeyPtrLen > *privKeyLen)) { + ret = BUFFER_E; + } + if ((ret == 0) && (pubKeyLen != NULL) && (pubKeyPtrLen > *pubKeyLen)) { + ret = BUFFER_E; + } + if ((ret == 0) && (privKeyPtr != NULL)) { + XMEMCPY(privKey, privKeyPtr, privKeyPtrLen); + *privKeyLen = privKeyPtrLen; + } + if ((ret == 0) && (pubKey != NULL) && (pubKeyPtr != NULL)) { + XMEMCPY(pubKey, pubKeyPtr, pubKeyPtrLen); + } + if ((ret == 0) && (pubKeyLen != NULL)) { + *pubKeyLen = pubKeyPtrLen; + } + + return ret; +} + +int DecodeAsymKeyPublic_Assign(const byte* input, word32* inOutIdx, word32 inSz, + const byte** pubKey, word32* pubKeyLen, int keyType) { int ret = 0; #ifndef WOLFSSL_ASN_TEMPLATE @@ -34649,17 +35067,13 @@ int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, if (ret != 0) return ret; - /* check that the value found is not too large for pubKey buffer */ - if ((word32)length > *pubKeyLen) - return ASN_PARSE_E; - /* check that input buffer is exhausted */ if (*inOutIdx + (word32)length != inSz) return ASN_PARSE_E; /* This is the raw point data compressed or uncompressed. */ *pubKeyLen = (word32)length; - XMEMCPY(pubKey, input + *inOutIdx, *pubKeyLen); + *pubKey = input + *inOutIdx; #else len = inSz - *inOutIdx; @@ -34680,11 +35094,6 @@ int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, if (*inOutIdx != inSz) ret = ASN_PARSE_E; } - /* Check the public value length is correct. */ - if ((ret == 0) && - (dataASN[EDPUBKEYASN_IDX_PUBKEY].data.ref.length > *pubKeyLen)) { - ret = ASN_PARSE_E; - } /* Check that the all the buffer was used. */ if ((ret == 0) && (GetASNItem_Length(dataASN[EDPUBKEYASN_IDX_SEQ], input) != len)) { @@ -34692,14 +35101,39 @@ int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, } if (ret == 0) { *pubKeyLen = dataASN[EDPUBKEYASN_IDX_PUBKEY].data.ref.length; - XMEMCPY(pubKey, dataASN[EDPUBKEYASN_IDX_PUBKEY].data.ref.data, - *pubKeyLen); + *pubKey = dataASN[EDPUBKEYASN_IDX_PUBKEY].data.ref.data; } FREE_ASNGETDATA(dataASN, NULL); #endif /* WOLFSSL_ASN_TEMPLATE */ return ret; } + +int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, + byte* pubKey, word32* pubKeyLen, int keyType) +{ + int ret = 0; + const byte* pubKeyPtr = NULL; + word32 pubKeyPtrLen = 0; + + if (pubKey == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + ret = DecodeAsymKeyPublic_Assign(input, inOutIdx, inSz, &pubKeyPtr, + &pubKeyPtrLen, keyType); + } + if ((ret == 0) && (pubKeyPtrLen > *pubKeyLen)) { + ret = BUFFER_E; + } + if ((ret == 0) && (pubKeyPtr != NULL)) { + XMEMCPY(pubKey, pubKeyPtr, pubKeyPtrLen); + *pubKeyLen = pubKeyPtrLen; + } + + return ret; +} #endif #endif /* WC_ENABLE_ASYM_KEY_IMPORT */ @@ -35135,7 +35569,7 @@ int wc_Curve448PublicKeyToDer(curve448_key* key, byte* output, word32 inLen, byte pubKey[CURVE448_PUB_KEY_SIZE]; word32 pubKeyLen = (word32)sizeof(pubKey); - if (key == NULL || output == NULL) { + if (key == NULL) { return BAD_FUNC_ARG; } @@ -36125,7 +36559,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, /* Don't verify if we don't have access to Cert Manager. */ ret = ParseCertRelative(cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY_OCSP_CERT, - cm); + cm, resp->pendingCAs); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); break; @@ -36184,7 +36618,11 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, #else ca = GetCA(cm, resp->single->issuerHash); #endif - +#if defined(HAVE_CERTIFICATE_STATUS_V2) + if (ca == NULL && resp->pendingCAs != NULL) { + ca = findSignerByName(resp->pendingCAs, resp->single->issuerHash); + } +#endif if (ca) { SignatureCtx sigCtx; InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); @@ -36282,7 +36720,7 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, /* Parse the certificate and don't verify if we don't have access to * Cert Manager. */ ret = ParseCertRelative(cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY, - cm); + cm, resp->pendingCAs); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); } @@ -36321,6 +36759,13 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, #else ca = GetCA(cm, resp->single->issuerHash); #endif + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ca == NULL && resp->pendingCAs != NULL) { + ca = findSignerByName(resp->pendingCAs, resp->single->issuerHash); + } + #endif + if (ca) { SignatureCtx sigCtx; @@ -36378,6 +36823,7 @@ void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status, resp->source = source; resp->maxIdx = inSz; resp->heap = heap; + resp->pendingCAs = NULL; } void FreeOcspResponse(OcspResponse* resp) @@ -37413,7 +37859,7 @@ int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, InitSignatureCtx(sigCtx, heap, INVALID_DEVID); if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, ca->pubKeySize, ca->keyOID, signature, sigSz, - signatureOID, sigParams, sigParamsSz, NULL) != 0) { + signatureOID, sigParams, (word32)sigParamsSz, NULL) != 0) { WOLFSSL_MSG("CRL Confirm signature failed"); WOLFSSL_ERROR_VERBOSE(ASN_CRL_CONFIRM_E); return ASN_CRL_CONFIRM_E; @@ -38137,7 +38583,7 @@ int ParseCRL(RevokedCert* rcert, DecodedCRL* dcrl, const byte* buff, word32 sz, buff); dcrl->sigParamsIndex = dataASN[CRLASN_IDX_SIGALGO_PARAMS].offset; - dcrl->sigParamsLength = sigParamsSz; + dcrl->sigParamsLength = (word32)sigParamsSz; } #endif @@ -39011,7 +39457,7 @@ static void PrintObjectIdText(Asn1* asn1, Asn1PrintOptions* opts) /* Get the OID value for the OBJECT_ID. */ if (GetObjectId(asn1->data + asn1->offset, &i, &oid, oidIgnoreType, - asn1->item.len + 2) == ASN_PARSE_E) { + asn1->item.len + 2) == WC_NO_ERR_TRACE(ASN_PARSE_E)) { known = 0; } else diff --git a/src/wolfcrypt/src/bio.c b/src/wolfcrypt/src/bio.c index 2dab43e..340cbfd 100644 --- a/src/wolfcrypt/src/bio.c +++ b/src/wolfcrypt/src/bio.c @@ -50,7 +50,7 @@ */ static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) { - word32 frmtSz = len; + word32 frmtSz = (word32)len; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read"); @@ -77,6 +77,8 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (buf == NULL || len == 0) return 0; + /* default no retry */ + bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY); sz1 = wolfSSL_BIO_nread(bio, &pt, len); if (sz1 > 0) { XMEMCPY(buf, pt, sz1); @@ -91,8 +93,10 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } } } - if (sz1 == 0) + if (sz1 == 0) { + bio->flags |= WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY; sz1 = -1; + } return sz1; } @@ -175,7 +179,7 @@ static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len) WOLFSSL_MSG("wolfSSL_BUF_MEM_resize error"); return WOLFSSL_BIO_ERROR; } - bio->mem_buf->length = bio->wrSz; + bio->mem_buf->length = (size_t)bio->wrSz; bio->ptr = bio->mem_buf->data; } } @@ -233,13 +237,13 @@ static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) { if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, - sz) != WOLFSSL_SUCCESS) + (unsigned int)sz) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } } else { - if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, sz) + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, (size_t)sz) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } @@ -305,12 +309,12 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) case WOLFSSL_BIO_FILE: #ifndef NO_FILESYSTEM if (bio->ptr) { - ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); + ret = (int)XFREAD(buf, 1, (size_t)len, (XFILE)bio->ptr); } else { - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + #if defined(XREAD) && !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - ret = (int)XREAD(bio->num, buf, len); + ret = (int)XREAD(bio->num, buf, (size_t)len); #else WOLFSSL_MSG("No file pointer and XREAD not enabled"); ret = NOT_COMPILED_IN; @@ -399,7 +403,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, /* get the encoded length */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, - &sz) != LENGTH_ONLY_E) { + &sz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Error with base64 get length"); return WOLFSSL_FATAL_ERROR; } @@ -448,7 +452,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, (void)heap; - return inLen; + return (int)inLen; } #endif /* WOLFSSL_BASE64_ENCODE */ @@ -502,8 +506,11 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, if (bio == NULL || data == NULL || len == 0) return 0; + /* default no retry */ + bio->flags &= ~(WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY); sz1 = wolfSSL_BIO_nwrite(bio, &buf, len); if (sz1 == 0) { + bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY; WOLFSSL_MSG("No room left to write"); return WOLFSSL_BIO_ERROR; } @@ -521,6 +528,8 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, if (sz2 > 0) { XMEMCPY(buf, data, sz2); sz1 += sz2; + if (len > sz2) + bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY; } } @@ -591,12 +600,12 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, - len) != WOLFSSL_SUCCESS) { + (unsigned int)len) != WOLFSSL_SUCCESS) { ret = WOLFSSL_BIO_ERROR; } } else { - if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, len) + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, (size_t)len) != WOLFSSL_SUCCESS) { ret = WOLFSSL_BIO_ERROR; } @@ -652,7 +661,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) if (ret > 0) { /* change so that data is formatted buffer */ data = frmt; - len = frmtSz; + len = (int)frmtSz; } #else WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without " @@ -670,12 +679,12 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) case WOLFSSL_BIO_FILE: #ifndef NO_FILESYSTEM if (bio->ptr) { - ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); + ret = (int)XFWRITE(data, 1, (size_t)len, (XFILE)bio->ptr); } else { - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + #if defined(XWRITE) && !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - ret = (int)XWRITE(bio->num, data, len); + ret = (int)XWRITE(bio->num, data, (size_t)len); #else WOLFSSL_MSG("No file pointer and XWRITE not enabled"); ret = NOT_COMPILED_IN; @@ -972,7 +981,7 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz) ret = wolfSSL_EVP_DigestFinal((WOLFSSL_EVP_MD_CTX*)bio->ptr, (unsigned char*)buf, &szOut); if (ret == WOLFSSL_SUCCESS) { - ret = szOut; + ret = (int)szOut; } } break; @@ -1257,8 +1266,8 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) bio->rdIdx = 0; if (bio->mem_buf != NULL) { bio->mem_buf->data = (char*)bio->ptr; - bio->mem_buf->length = bio->num; - bio->mem_buf->max = bio->num; + bio->mem_buf->length = (size_t)bio->num; + bio->mem_buf->max = (size_t)bio->num; } return WOLFSSL_SUCCESS; @@ -1608,7 +1617,12 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) XFCLOSE((XFILE)bio->ptr); } - bio->ptr = XFOPEN(name, "w"); + /* 'b' flag is ignored on POSIX targets, but on Windows it assures + * inhibition of LF<->CRLF rewriting, so that there is consistency + * between the size and contents of the representation in memory and on + * disk. + */ + bio->ptr = XFOPEN(name, "wb"); if (((XFILE)bio->ptr) == XBADFILE) { return WOLFSSL_FAILURE; } @@ -2637,7 +2651,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) len = (int)XSTRLEN((const char*)buf) + 1; } - if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, len) == 0) { + if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, (size_t)len) == 0) { wolfSSL_BIO_free(bio); return NULL; } diff --git a/src/wolfcrypt/src/chacha.c b/src/wolfcrypt/src/chacha.c index c84829b..f497560 100644 --- a/src/wolfcrypt/src/chacha.c +++ b/src/wolfcrypt/src/chacha.c @@ -72,6 +72,10 @@ Public domain. #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) #undef NO_AVX2_SUPPORT #endif + #if defined(_MSC_VER) && (_MSC_VER <= 1900) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif #ifndef NO_AVX2_SUPPORT #define HAVE_INTEL_AVX2 diff --git a/src/wolfcrypt/src/cmac.c b/src/wolfcrypt/src/cmac.c index c1edfc3..b77cc33 100644 --- a/src/wolfcrypt/src/cmac.c +++ b/src/wolfcrypt/src/cmac.c @@ -39,8 +39,8 @@ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$n") - #pragma const_seg(".fipsB$n") + #pragma code_seg(".fipsA$c") + #pragma const_seg(".fipsB$c") #endif #endif @@ -59,6 +59,15 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_cmac_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000003 }; + int wolfCrypt_FIPS_CMAC_sanity(void) + { + return 0; + } +#endif + #ifdef WOLFSSL_HASH_KEEP /* Some hardware have issues with update, this function stores the data to be * hashed into an array. Once ready, the Final operation is called on all of the @@ -125,7 +134,7 @@ int wc_InitCmac_ex(Cmac* cmac, const byte* key, word32 keySz, ret = wc_CryptoCb_Cmac(cmac, key, keySz, NULL, 0, NULL, NULL, type, unused); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -193,7 +202,7 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz) { ret = wc_CryptoCb_Cmac(cmac, NULL, 0, in, inSz, NULL, NULL, 0, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -202,7 +211,7 @@ int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz) /* Clear CRYPTOCB_UNAVAILABLE return code */ ret = 0; - while (inSz != 0) { + while ((ret == 0) && (inSz != 0)) { word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz); XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add); @@ -261,7 +270,7 @@ int wc_CmacFinalNoFree(Cmac* cmac, byte* out, word32* outSz) #endif { ret = wc_CryptoCb_Cmac(cmac, NULL, 0, NULL, 0, out, outSz, 0, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -331,7 +340,7 @@ int wc_AesCmacGenerate_ex(Cmac* cmac, ret = wc_CryptoCb_Cmac(cmac, key, keySz, in, inSz, out, outSz, WC_CMAC_AES, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* Clear CRYPTOCB_UNAVAILABLE return code */ @@ -440,10 +449,8 @@ int wc_AesCmacVerify_ex(Cmac* cmac, devId); if (ret == 0) { compareRet = ConstantCompare(check, a, (int)min(checkSz, aSz)); - } - - if (ret == 0) ret = compareRet ? 1 : 0; + } return ret; } diff --git a/src/wolfcrypt/src/coding.c b/src/wolfcrypt/src/coding.c index be5f418..2509948 100644 --- a/src/wolfcrypt/src/coding.c +++ b/src/wolfcrypt/src/coding.c @@ -181,7 +181,7 @@ int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) byte e1, e2, e3, e4; if ((ret = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (ret == BUFFER_E) { + if (ret == WC_NO_ERR_TRACE(BUFFER_E)) { /* Running out of buffer here is not an error */ break; } diff --git a/src/wolfcrypt/src/cryptocb.c b/src/wolfcrypt/src/cryptocb.c index 07b37f1..06b9ebe 100644 --- a/src/wolfcrypt/src/cryptocb.c +++ b/src/wolfcrypt/src/cryptocb.c @@ -260,9 +260,9 @@ static CryptoCb* wc_CryptoCb_FindDeviceByIndex(int startIdx) static WC_INLINE int wc_CryptoCb_TranslateErrorCode(int ret) { - if (ret == NOT_COMPILED_IN) { + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { /* backwards compatibility for older NOT_COMPILED_IN syntax */ - ret = CRYPTOCB_UNAVAILABLE; + ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); } return ret; } @@ -344,8 +344,8 @@ int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx) /* Success. Update dev->ctx */ dev->ctx = info.cmd.ctx; } - else if ((rc == CRYPTOCB_UNAVAILABLE) || - (rc == NOT_COMPILED_IN)) { + else if ((rc == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) || + (rc == WC_NO_ERR_TRACE(NOT_COMPILED_IN))) { /* Not implemented. Return success*/ rc = 0; } @@ -391,7 +391,7 @@ void wc_CryptoCb_UnRegisterDevice(int devId) int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -421,7 +421,7 @@ int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, #ifdef WOLFSSL_KEY_GEN int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -449,7 +449,7 @@ int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) int wc_CryptoCb_RsaCheckPrivKey(RsaKey* key, const byte* pubKey, word32 pubKeySz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -474,7 +474,7 @@ int wc_CryptoCb_RsaCheckPrivKey(RsaKey* key, const byte* pubKey, int wc_CryptoCb_RsaGetSize(const RsaKey* key, int* keySize) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -500,7 +500,7 @@ int wc_CryptoCb_RsaGetSize(const RsaKey* key, int* keySize) #ifdef HAVE_ECC int wc_CryptoCb_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -527,7 +527,7 @@ int wc_CryptoCb_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId) int wc_CryptoCb_Ecdh(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (private_key == NULL) @@ -554,7 +554,7 @@ int wc_CryptoCb_Ecdh(ecc_key* private_key, ecc_key* public_key, int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, word32 *outlen, WC_RNG* rng, ecc_key* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -583,7 +583,7 @@ int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, const byte* hash, word32 hashlen, int* res, ecc_key* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -612,7 +612,7 @@ int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, int wc_CryptoCb_EccCheckPrivKey(ecc_key* key, const byte* pubKey, word32 pubKeySz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -640,7 +640,7 @@ int wc_CryptoCb_EccCheckPrivKey(ecc_key* key, const byte* pubKey, int wc_CryptoCb_Curve25519Gen(WC_RNG* rng, int keySize, curve25519_key* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -666,7 +666,7 @@ int wc_CryptoCb_Curve25519Gen(WC_RNG* rng, int keySize, int wc_CryptoCb_Curve25519(curve25519_key* private_key, curve25519_key* public_key, byte* out, word32* outlen, int endian) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (private_key == NULL) @@ -696,7 +696,7 @@ int wc_CryptoCb_Curve25519(curve25519_key* private_key, int wc_CryptoCb_Ed25519Gen(WC_RNG* rng, int keySize, ed25519_key* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -723,7 +723,7 @@ int wc_CryptoCb_Ed25519Sign(const byte* in, word32 inLen, byte* out, word32 *outLen, ed25519_key* key, byte type, const byte* context, byte contextLen) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -755,7 +755,7 @@ int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, ed25519_key* key, byte type, const byte* context, byte contextLen) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (key == NULL) @@ -785,7 +785,7 @@ int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, } #endif /* HAVE_ED25519 */ -#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) +#if defined(WOLFSSL_HAVE_KYBER) int wc_CryptoCb_PqcKemGetDevId(int type, void* key) { int devId = INVALID_DEVID; @@ -794,18 +794,16 @@ int wc_CryptoCb_PqcKemGetDevId(int type, void* key) return devId; /* get devId */ -#if defined(WOLFSSL_HAVE_KYBER) if (type == WC_PQC_KEM_TYPE_KYBER) { devId = ((KyberKey*) key)->devId; } -#endif return devId; } int wc_CryptoCb_MakePqcKemKey(WC_RNG* rng, int type, int keySize, void* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -839,7 +837,7 @@ int wc_CryptoCb_PqcEncapsulate(byte* ciphertext, word32 ciphertextLen, byte* sharedSecret, word32 sharedSecretLen, WC_RNG* rng, int type, void* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -875,7 +873,7 @@ int wc_CryptoCb_PqcEncapsulate(byte* ciphertext, word32 ciphertextLen, int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, word32 ciphertextLen, byte* sharedSecret, word32 sharedSecretLen, int type, void* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -906,9 +904,9 @@ int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, word32 ciphertextLen, return wc_CryptoCb_TranslateErrorCode(ret); } -#endif /* HAVE_PQC && WOLFSSL_HAVE_KYBER */ +#endif /* WOLFSSL_HAVE_KYBER */ -#if defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) int wc_CryptoCb_PqcSigGetDevId(int type, void* key) { int devId = INVALID_DEVID; @@ -934,7 +932,7 @@ int wc_CryptoCb_PqcSigGetDevId(int type, void* key) int wc_CryptoCb_MakePqcSignatureKey(WC_RNG* rng, int type, int keySize, void* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -967,7 +965,7 @@ int wc_CryptoCb_MakePqcSignatureKey(WC_RNG* rng, int type, int keySize, int wc_CryptoCb_PqcSign(const byte* in, word32 inlen, byte* out, word32 *outlen, WC_RNG* rng, int type, void* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -1003,7 +1001,7 @@ int wc_CryptoCb_PqcSign(const byte* in, word32 inlen, byte* out, word32 *outlen, int wc_CryptoCb_PqcVerify(const byte* sig, word32 siglen, const byte* msg, word32 msglen, int* res, int type, void* key) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -1039,7 +1037,7 @@ int wc_CryptoCb_PqcVerify(const byte* sig, word32 siglen, const byte* msg, int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, const byte* pubKey, word32 pubKeySz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); int devId = INVALID_DEVID; CryptoCb* dev; @@ -1068,7 +1066,7 @@ int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, return wc_CryptoCb_TranslateErrorCode(ret); } -#endif /* HAVE_PQC && (HAVE_FALCON || HAVE_DILITHIUM) */ +#endif /* HAVE_FALCON || HAVE_DILITHIUM */ #ifndef NO_AES #ifdef HAVE_AESGCM @@ -1078,7 +1076,7 @@ int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1119,7 +1117,7 @@ int wc_CryptoCb_AesGcmDecrypt(Aes* aes, byte* out, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1162,7 +1160,7 @@ int wc_CryptoCb_AesCcmEncrypt(Aes* aes, byte* out, byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1203,7 +1201,7 @@ int wc_CryptoCb_AesCcmDecrypt(Aes* aes, byte* out, const byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1243,7 +1241,7 @@ int wc_CryptoCb_AesCcmDecrypt(Aes* aes, byte* out, int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1275,7 +1273,7 @@ int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1308,7 +1306,7 @@ int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1341,7 +1339,7 @@ int wc_CryptoCb_AesCtrEncrypt(Aes* aes, byte* out, int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1373,7 +1371,7 @@ int wc_CryptoCb_AesEcbEncrypt(Aes* aes, byte* out, int wc_CryptoCb_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1408,7 +1406,7 @@ int wc_CryptoCb_AesEcbDecrypt(Aes* aes, byte* out, int wc_CryptoCb_Des3Encrypt(Des3* des3, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1440,7 +1438,7 @@ int wc_CryptoCb_Des3Encrypt(Des3* des3, byte* out, int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, const byte* in, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1474,7 +1472,7 @@ int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, word32 inSz, byte* digest) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1507,7 +1505,7 @@ int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, int wc_CryptoCb_Sha256Hash(wc_Sha256* sha256, const byte* in, word32 inSz, byte* digest) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1540,7 +1538,7 @@ int wc_CryptoCb_Sha256Hash(wc_Sha256* sha256, const byte* in, int wc_CryptoCb_Sha384Hash(wc_Sha384* sha384, const byte* in, word32 inSz, byte* digest) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1576,7 +1574,7 @@ int wc_CryptoCb_Sha384Hash(wc_Sha384* sha384, const byte* in, int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in, word32 inSz, byte* digest) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1608,11 +1606,45 @@ int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in, } #endif /* WOLFSSL_SHA512 */ +#if defined(WOLFSSL_SHA3) && (!defined(HAVE_FIPS) || FIPS_VERSION_GE(6, 0)) +int wc_CryptoCb_Sha3Hash(wc_Sha3* sha3, int type, const byte* in, + word32 inSz, byte* digest) +{ + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + CryptoCb* dev; + + /* locate registered callback */ + if (sha3) { + dev = wc_CryptoCb_FindDevice(sha3->devId, WC_ALGO_TYPE_HASH); + } + else + { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; + cryptoInfo.hash.type = type; + cryptoInfo.hash.sha3 = sha3; + cryptoInfo.hash.in = in; + cryptoInfo.hash.inSz = inSz; + cryptoInfo.hash.digest = digest; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* WOLFSSL_SHA3 && (!HAVE_FIPS || FIPS_VERSION_GE(6, 0)) */ + #ifndef NO_HMAC int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, byte* digest) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; if (hmac == NULL) @@ -1640,7 +1672,7 @@ int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, #ifndef WC_NO_RNG int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1668,7 +1700,7 @@ int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz) int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ @@ -1692,7 +1724,7 @@ int wc_CryptoCb_Cmac(Cmac* cmac, const byte* key, word32 keySz, const byte* in, word32 inSz, byte* out, word32* outSz, int type, void* ctx) { - int ret = CRYPTOCB_UNAVAILABLE; + int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; /* locate registered callback */ diff --git a/src/wolfcrypt/src/curve25519.c b/src/wolfcrypt/src/curve25519.c index 2c967dd..4cd29c4 100644 --- a/src/wolfcrypt/src/curve25519.c +++ b/src/wolfcrypt/src/curve25519.c @@ -238,7 +238,7 @@ int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) #ifdef WOLF_CRYPTO_CB if (key->devId != INVALID_DEVID) { ret = wc_CryptoCb_Curve25519Gen(rng, keysize, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -299,7 +299,7 @@ int wc_curve25519_shared_secret_ex(curve25519_key* private_key, if (private_key->devId != INVALID_DEVID) { ret = wc_CryptoCb_Curve25519(private_key, public_key, out, outlen, endian); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } diff --git a/src/wolfcrypt/src/des3.c b/src/wolfcrypt/src/des3.c index 650c33a..e66a33d 100644 --- a/src/wolfcrypt/src/des3.c +++ b/src/wolfcrypt/src/des3.c @@ -38,8 +38,8 @@ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$i") - #pragma const_seg(".fipsB$i") + #pragma code_seg(".fipsA$d") + #pragma const_seg(".fipsB$d") #endif #endif @@ -1602,7 +1602,7 @@ #ifdef WOLF_CRYPTO_CB if (des->devId != INVALID_DEVID) { int ret = wc_CryptoCb_Des3Encrypt(des, out, in, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1653,7 +1653,7 @@ #ifdef WOLF_CRYPTO_CB if (des->devId != INVALID_DEVID) { int ret = wc_CryptoCb_Des3Decrypt(des, out, in, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } diff --git a/src/wolfcrypt/src/dh.c b/src/wolfcrypt/src/dh.c index 6b68601..28ed197 100644 --- a/src/wolfcrypt/src/dh.c +++ b/src/wolfcrypt/src/dh.c @@ -35,8 +35,8 @@ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$m") - #pragma const_seg(".fipsB$m") + #pragma code_seg(".fipsA$e") + #pragma const_seg(".fipsB$e") #endif #endif @@ -55,6 +55,15 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_dh_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000004 }; + int wolfCrypt_FIPS_DH_sanity(void) + { + return 0; + } +#endif + #if defined(WOLFSSL_LINUXKM) && !defined(WOLFSSL_SP_ASM) /* force off unneeded vector register save/restore. */ #undef SAVE_VECTOR_REGISTERS @@ -2931,6 +2940,14 @@ int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh) if (ret == 0) { /* modulus size in bytes */ modSz /= WOLFSSL_BIT_SIZE; + + if ((word32)modSz < groupSz) { + WOLFSSL_MSG("DH modSz was too small"); + ret = BAD_FUNC_ARG; + } + } + + if (ret == 0) { bufSz = (word32)modSz - groupSz; /* allocate ram */ diff --git a/src/wolfcrypt/src/dilithium.c b/src/wolfcrypt/src/dilithium.c index f8968c5..f3a6f01 100644 --- a/src/wolfcrypt/src/dilithium.c +++ b/src/wolfcrypt/src/dilithium.c @@ -19,86 +19,6568 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* Based on ed448.c and Reworked for Dilithium by Anthony Hu. */ +/* Based on ed448.c and Reworked for Dilithium by Anthony Hu. + * WolfSSL implementation by Sean Parkinson. + */ + +/* Possible Dilithium/ML-DSA options: + * + * HAVE_DILITHIUM Default: OFF + * Enables the code in this file to be compiled. + * WOLFSSL_WC_DILITHIUM Default: OFF + * Compiles the wolfSSL implementation of dilithium. + * + * WOLFSSL_NO_ML_DSA_44 Default: OFF + * Does not compile in parameter set ML-DSA-44 and any code specific to that + * parameter set. + * WOLFSSL_NO_ML_DSA_65 Default: OFF + * Does not compile in parameter set ML-DSA-65 and any code specific to that + * parameter set. + * WOLFSSL_NO_ML_DSA_87 Default: OFF + * Does not compile in parameter set ML-DSA-87 and any code specific to that + * parameter set. + * + * WOLFSSL_DILITHIUM_NO_LARGE_CODE Default: OFF + * Compiles smaller, fast code with speed trade-off. + * WOLFSSL_DILITHIUM_SMALL Default: OFF + * Compiles to small code size with a speed trade-off. + * WOLFSSL_DILITHIUM_VERIFY_ONLY Default: OFF + * Compiles in only the verification and public key operations. + * WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM Default: OFF + * Compiles verification implementation that uses smaller amounts of memory. + * WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC Default: OFF + * Only works with WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM. + * Don't allocate memory with XMALLOC. Memory is pinned against key. + * WOLFSSL_DILITHIUM_ASSIGN_KEY Default: OFF + * Key data is assigned into Dilithium key rather than copied. + * Life of key data passed in is tightly coupled to life of Dilithium key. + * Cannot be used when make key is enabled. + * WOLFSSL_DILITHIUM_SIGN_SMALL_MEM Default: OFF + * Compiles signature implementation that uses smaller amounts of memory but + * is considerably slower. + * + * WOLFSSL_DILITHIUM_ALIGNMENT Default: 8 + * Use to indicate whether loading and storing of words needs to be aligned. + * Default is to use WOLFSSL_GENERAL_ALIGNMENT - should be 4 on some ARM CPUs. + * Set this value explicitly if specific Dilithium implementation alignment is + * needed. + * + * WOLFSSL_DILITHIUM_NO_ASN1 Default: OFF + * Disables any ASN.1 encoding or decoding code. + * + * WC_DILITHIUM_CACHE_MATRIX_A Default: OFF + * Enable caching of the A matrix on import. + * Less work is required in sign and verify operations. + * WC_DILITHIUM_CACHE_PRIV_VECTORS Default: OFF + * Enable caching of private key vectors on import. + * Enables WC_DILITHIUM_CACHE_MATRIX_A. + * Less work is required in sign operations. + * WC_DILITHIUM_CACHE_PUB_VECTORS Default: OFF + * Enable caching of public key vectors on import. + * Enables WC_DILITHIUM_CACHE_MATRIX_A. + * Less work is required in sign operations. + * + * WOLFSSL_DILITHIUM_SIGN_CHECK_Y Default: OFF + * Check vector y is in required range as an early check on valid vector z. + * Falsely reports invalid in approximately 1-2% of checks. + * All valid reports are true. + * Fast fail gives faster signing times on average. + * DO NOT enable this if implementation must be conformant to FIPS 204. + * WOLFSSL_DILITHIUM_SIGN_CHECK_W0 Default: OFF + * Check vector w0 is in required range as an early check on valid vector r0. + * Falsely reports invalid in approximately 3-5% of checks. + * All valid reports are true. + * Fast fail gives faster signing times on average. + * DO NOT enable this if implementation must be conformant to FIPS 204. + * + * DILITHIUM_MUL_SLOW Default: OFF + * Define when multiplying by Q / 44 is slower than masking. + * Only applies to ML-DSA-44. + * DILITHIUM_MUL_44_SLOW Default: OFF + * Define when multiplying by 44 is slower than by 11. + * Only applies to ML-DSA-44. + * DILITHIUM_MUL_11_SLOW Default: OFF + * Define when multiplying by 11 is slower than adding and shifting. + * Only applies to ML-DSA-44. + * DILITHIUM_MUL_QINV_SLOW Default: OFF + * Define when multiplying by QINV 0x3802001 is slower than add, subtract and + * shift equivalent. + * DILITHIUM_MUL_Q_SLOW Default: OFF + * Define when multiplying by Q 0x7fe001 is slower than add, subtract and + * shift equivalent. + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set HAVE_PQC there */ +#include + +#ifndef WOLFSSL_DILITHIUM_NO_ASN1 +#include +#endif + +#if defined(HAVE_DILITHIUM) + +#ifdef HAVE_LIBOQS +#include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFSSL_WC_DILITHIUM + +#ifdef DEBUG_DILITHIUM +void print_polys(const char* name, const sword32* a, int d1, int d2); +void print_polys(const char* name, const sword32* a, int d1, int d2) +{ + int i; + int j; + int k; + + fprintf(stderr, "%s\n", name); + for (i = 0; i < d1; i++) { + for (j = 0; j < d2; j++) { + for (k = 0; k < 256; k++) { + fprintf(stderr, "%9d,", a[(i*d2*256) + (j*256) + k]); + if ((k % 8) == 7) fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + } + } +} + +void print_data(const char* name, const byte* d, int len); +void print_data(const char* name, const byte* d, int len) +{ + int i; + + fprintf(stderr, "%s\n", name); + for (i = 0; i < len; i++) { + fprintf(stderr, "0x%02x,", d[i]); + if ((i % 16) == 15) fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); +} +#endif + +#if defined(WOLFSSL_NO_ML_DSA_44) && defined(WOLFSSL_NO_ML_DSA_65) && \ + defined(WOLFSSL_NO_ML_DSA_87) + #error "No Dilithium parameters chosen" +#endif + +#if defined(WOLFSSL_DILITHIUM_ASSIGN_KEY) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) + #error "Cannot use assign key when making keys" +#endif + + +/* Number of bytes from first block to use for sign. */ +#define DILITHIUM_SIGN_BYTES 8 + + +/* Length of seed in bytes when generating y. */ +#define DILITHIUM_Y_SEED_SZ (DILITHIUM_PRIV_RAND_SEED_SZ + 2) + + +/* Length of seed in bytes used in generating matrix a. */ +#define DILITHIUM_GEN_A_SEED_SZ (DILITHIUM_PUB_SEED_SZ + 2) +/* Length of seed in bytes used in generating vectors s1 and s2. */ +#define DILITHIUM_GEN_S_SEED_SZ (DILITHIUM_PRIV_SEED_SZ + 2) + + +/* MAX: (256 * 8 / (17 + 1)) = 576, or ((256 * 8 / (19 + 1)) = 640 + * but need blocks of 17 * 8 bytes: 5 * 17 * 8 = 680 */ +#define DILITHIUM_MAX_V_BLOCKS 5 +/* Maximum number of bytes to generate into v to make y. */ +#define DILITHIUM_MAX_V (DILITHIUM_MAX_V_BLOCKS * 8 * 17) + + +/* 2 blocks, each block 136 bytes = 272 bytes. + * ETA 2: Min req is 128 but reject rate is 2 in 16 so we need 146.3 on average. + * ETA 4: Min req is 128 but reject rate is 7 in 16 so we need 227.6 on average. + */ +#define DILITHIUM_GEN_S_NBLOCKS 2 +/* Number of bytes to generate with SHAKE-256 when generating s1 and s2. */ +#define DILITHIUM_GEN_S_BYTES \ + (DILITHIUM_GEN_S_NBLOCKS * WC_SHA3_256_COUNT * 8) +/* Number of bytes to a block of SHAKE-256 when generating s1 and s2. */ +#define DILITHIUM_GEN_S_BLOCK_BYTES (WC_SHA3_256_COUNT * 8) + + +/* The ML-DSA parameters sets. */ +static const wc_dilithium_params dilithium_params[] = { +#ifndef WOLFSSL_NO_ML_DSA_44 + { WC_ML_DSA_44, PARAMS_ML_DSA_44_K, PARAMS_ML_DSA_44_L, + PARAMS_ML_DSA_44_ETA, PARAMS_ML_DSA_44_ETA_BITS, + PARAMS_ML_DSA_44_TAU, PARAMS_ML_DSA_44_BETA, PARAMS_ML_DSA_44_OMEGA, + PARAMS_ML_DSA_44_LAMBDA, + PARAMS_ML_DSA_44_GAMMA1_BITS, PARAMS_ML_DSA_44_GAMMA2, + PARAMS_ML_DSA_44_W1_ENC_SZ, PARAMS_ML_DSA_44_A_SIZE, + PARAMS_ML_DSA_44_S1_SIZE, PARAMS_ML_DSA_44_S1_ENC_SIZE, + PARAMS_ML_DSA_44_S2_SIZE, PARAMS_ML_DSA_44_S2_ENC_SIZE, + PARAMS_ML_DSA_44_Z_ENC_SIZE, + PARAMS_ML_DSA_44_PK_SIZE, PARAMS_ML_DSA_44_SIG_SIZE }, +#endif +#ifndef WOLFSSL_NO_ML_DSA_65 + { WC_ML_DSA_65, PARAMS_ML_DSA_65_K, PARAMS_ML_DSA_65_L, + PARAMS_ML_DSA_65_ETA, PARAMS_ML_DSA_65_ETA_BITS, + PARAMS_ML_DSA_65_TAU, PARAMS_ML_DSA_65_BETA, PARAMS_ML_DSA_65_OMEGA, + PARAMS_ML_DSA_65_LAMBDA, + PARAMS_ML_DSA_65_GAMMA1_BITS, PARAMS_ML_DSA_65_GAMMA2, + PARAMS_ML_DSA_65_W1_ENC_SZ, PARAMS_ML_DSA_65_A_SIZE, + PARAMS_ML_DSA_65_S1_SIZE, PARAMS_ML_DSA_65_S1_ENC_SIZE, + PARAMS_ML_DSA_65_S2_SIZE, PARAMS_ML_DSA_65_S2_ENC_SIZE, + PARAMS_ML_DSA_65_Z_ENC_SIZE, + PARAMS_ML_DSA_65_PK_SIZE, PARAMS_ML_DSA_65_SIG_SIZE }, +#endif +#ifndef WOLFSSL_NO_ML_DSA_87 + { WC_ML_DSA_87, PARAMS_ML_DSA_87_K, PARAMS_ML_DSA_87_L, + PARAMS_ML_DSA_87_ETA, PARAMS_ML_DSA_87_ETA_BITS, + PARAMS_ML_DSA_87_TAU, PARAMS_ML_DSA_87_BETA, PARAMS_ML_DSA_87_OMEGA, + PARAMS_ML_DSA_87_LAMBDA, + PARAMS_ML_DSA_87_GAMMA1_BITS, PARAMS_ML_DSA_87_GAMMA2, + PARAMS_ML_DSA_87_W1_ENC_SZ, PARAMS_ML_DSA_87_A_SIZE, + PARAMS_ML_DSA_87_S1_SIZE, PARAMS_ML_DSA_87_S1_ENC_SIZE, + PARAMS_ML_DSA_87_S2_SIZE, PARAMS_ML_DSA_87_S2_ENC_SIZE, + PARAMS_ML_DSA_87_Z_ENC_SIZE, + PARAMS_ML_DSA_87_PK_SIZE, PARAMS_ML_DSA_87_SIG_SIZE }, +#endif +}; +/* Number of ML-DSA parameter sets compiled in. */ +#define DILITHIUM_PARAMS_CNT \ + ((unsigned int)(sizeof(dilithium_params) / sizeof(wc_dilithium_params))) + +/* Get the ML-DSA parameters that match the level. + * + * @param [in] level Level required. + * @param [out] params Parameter set. + * @return 0 on success. + * @return NOT_COMPILED_IN when parameters at level are not compiled in. + */ +static int dilithium_get_params(int level, const wc_dilithium_params** params) +{ + unsigned int i; + int ret = NOT_COMPILED_IN; + + for (i = 0; i < DILITHIUM_PARAMS_CNT; i++) { + if (dilithium_params[i].level == level) { + *params = &dilithium_params[i]; + ret = 0; + } + } + + return ret; +} + +/****************************************************************************** + * Hash operations + ******************************************************************************/ + +/* 256-bit hash using SHAKE-256. + * + * FIPS 204. 8.3: H(v,d) <- SHAKE256(v,d) + * + * @param [in, out] shake256 SHAKE-256 object. + * @param [in] data Buffer holding data to hash. + * @param [in] dataLen Length of data to hash in bytes. + * @param [out] hash Buffer to hold hash result. + * @param [in] hashLen Number of bytes of hash to return. + * @return 0 on success. + * @return Negative on error. + */ +static int dilithium_shake256(wc_Shake* shake256, const byte* data, + word32 dataLen, byte* hash, word32 hashLen) +{ + int ret; + + /* Initialize SHAKE-256 operation. */ + ret = wc_InitShake256(shake256, NULL, INVALID_DEVID); + if (ret == 0) { + /* Update with data. */ + ret = wc_Shake256_Update(shake256, data, dataLen); + } + if (ret == 0) { + /* Compute hash of data. */ + ret = wc_Shake256_Final(shake256, hash, hashLen); + } + + return ret; +} + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +/* 256-bit hash using SHAKE-256. + * + * FIPS 204. 8.3: H(v,d) <- SHAKE256(v,d) + * + * @param [in, out] shake256 SHAKE-256 object. + * @param [in] data1 First block of data to hash. + * @param [in] data1Len Length of first block in bytes. + * @param [in] data2 Second block of data to hash. + * @param [in] data2Len Length of second block in bytes. + * @param [out] hash Buffer to hold hash result. + * @param [in] hashLen Number of bytes of hash to return. + * @return 0 on success. + * @return Negative on error. + */ +static int dilithium_hash256(wc_Shake* shake256, const byte* data1, + word32 data1Len, const byte* data2, word32 data2Len, byte* hash, + word32 hashLen) +{ + int ret; + + /* Initialize SHAKE-256 operation. */ + ret = wc_InitShake256(shake256, NULL, INVALID_DEVID); + if (ret == 0) { + /* Update with first data. */ + ret = wc_Shake256_Update(shake256, data1, data1Len); + } + if (ret == 0) { + /* Update with second data. */ + ret = wc_Shake256_Update(shake256, data2, data2Len); + } + if (ret == 0) { + /* Compute hash of data. */ + ret = wc_Shake256_Final(shake256, hash, hashLen); + } + + return ret; +} +#endif + +#ifndef WOLFSSL_DILITHIUM_SMALL +/* 128-bit hash using SHAKE-128. + * + * FIPS 204. 8.3: H128(v,d) <- SHAKE128(v,d) + * + * @param [in, out] shake128 SHAKE-128 object. + * @param [in] in Block of data to hash. + * @param [in] inLen Length of data in bytes. + * @param [out] out Buffer to hold hash result. + * @param [in] outLen Number of hash blocks to return. + * @return 0 on success. + * @return Negative on error. + */ +static int dilithium_squeeze128(wc_Shake* shake128, const byte* in, + word32 inLen, byte* out, word32 outBlocks) +{ + int ret; + + /* Initialize SHAKE-128 operation. */ + ret = wc_InitShake128(shake128, NULL, INVALID_DEVID); + if (ret == 0) { + /* Absorb data - update plus final. */ + ret = wc_Shake128_Absorb(shake128, in, inLen); + } + if (ret == 0) { + /* Squeeze out hash data. */ + ret = wc_Shake128_SqueezeBlocks(shake128, out, outBlocks); + } + + return ret; +} +#endif /* WOLFSSL_DILITHIUM_SMALL */ + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || \ + (!defined(WOLFSSL_DILITHIUM_SMALL) && \ + !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY)) +/* 256-bit hash using SHAKE-256. + * + * FIPS 204. 8.3: H(v,d) <- SHAKE256(v,d) + * Using SqueezeBlocks interface to get larger amounts of output. + * + * @param [in, out] shake256 SHAKE-256 object. + * @param [in] in Block of data to hash. + * @param [in] inLen Length of data in bytes. + * @param [out] out Buffer to hold hash result. + * @param [in] outLen Number of hash blocks to return. + * @return 0 on success. + * @return Negative on hash error. + */ +static int dilithium_squeeze256(wc_Shake* shake256, const byte* in, + word32 inLen, byte* out, word32 outBlocks) +{ + int ret; + + /* Initialize SHAKE-256 operation. */ + ret = wc_InitShake256(shake256, NULL, INVALID_DEVID); + if (ret == 0) { + /* Absorb data - update plus final. */ + ret = wc_Shake256_Absorb(shake256, in, inLen); + } + if (ret == 0) { + /* Squeeze out hash data. */ + ret = wc_Shake256_SqueezeBlocks(shake256, out, outBlocks); + } + + return ret; +} +#endif + +/****************************************************************************** + * Encode/Decode operations + ******************************************************************************/ + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY +/* Encode vector of polynomials with range -ETA..ETA. + * + * FIPS 204. 8.2: Algorithm 18 skEncode(rho, K, tr, s1, s2, t0) + * ... + * 2: for i from 0 to l - 1 do + * 3: sk <- sk || BitPack(s1[i], eta, eta) + * 4: end for + * ... + * OR + * ... + * 5: for i from 0 to k - 1 do + * 6: sk <- sk || BitPack(s2[i], eta, eta) + * 7: end for + * ... + * + * FIPS 204. 8.2: Algorithm 11 BitPack(w, a, b) + * 1: z <- () + * 2: for i from 0 to 255 do + * 3: z <- z||IntegerToBits(b - wi, bitlen(a + b)) + * 4: end for + * 5: return BitsToBytes(z) + * + * IntegerToBits makes bit array with width specified from integer. + * BitToBytes make a byte array from a bit array. + * + * @param [in] s Vector of polynomials to encode. + * @param [in] d Dimension of vector. + * @param [in] eta Range specifier of each value. + * @param [out] p Buffer to encode into. + */ +static void dilthium_vec_encode_eta_bits(const sword32* s, byte d, byte eta, + byte* p) +{ + unsigned int i; + unsigned int j; + +#if !defined(WOLFSSL_NO_ML_DSA_44) || !defined(WOLFSSL_NO_ML_DSA_87) + /* -2..2 */ + if (eta == DILITHIUM_ETA_2) { + /* Setp 2 or 5: For each polynomial of vector. */ + for (i = 0; i < d; i++) { + /* Step 3 or 6. + * 3 bits to encode each number. + * 8 numbers become 3 bytes. (8 * 3 bits = 3 * 8 bits) */ + for (j = 0; j < DILITHIUM_N; j += 8) { + /* Make value a positive integer. */ + byte s0 = 2 - s[j + 0]; + byte s1 = 2 - s[j + 1]; + byte s2 = 2 - s[j + 2]; + byte s3 = 2 - s[j + 3]; + byte s4 = 2 - s[j + 4]; + byte s5 = 2 - s[j + 5]; + byte s6 = 2 - s[j + 6]; + byte s7 = 2 - s[j + 7]; + + /* Pack 8 3-bit values into 3 bytes. */ + p[0] = (s0 >> 0) | (s1 << 3) | (s2 << 6); + p[1] = (s2 >> 2) | (s3 << 1) | (s4 << 4) | (s5 << 7); + p[2] = (s5 >> 1) | (s6 << 2) | (s7 << 5); + /* Move to next place to encode into. */ + p += DILITHIUM_ETA_2_BITS; + } + /* Next polynomial. */ + s += DILITHIUM_N; + } + } + else +#endif +#ifndef WOLFSSL_NO_ML_DSA_65 + /* -4..4 */ + if (eta == DILITHIUM_ETA_4) { + for (i = 0; i < d; i++) { + #ifdef WOLFSSL_DILITHIUM_SMALL + /* Step 3 or 6. + * 4 bits to encode each number. + * 2 numbers become 1 bytes. (2 * 4 bits = 1 * 8 bits) */ + for (j = 0; j < DILITHIUM_N / 2; j++) { + /* Make values positive and pack 2 4-bit values into 1 byte. */ + p[j] = (((byte)(4 - s[j * 2 + 0])) << 0) | + (((byte)(4 - s[j * 2 + 1])) << 4); + } + #else + /* Step 3 or 6. + * 4 bits to encode each number. + * 8 numbers become 4 bytes. (8 * 4 bits = 4 * 8 bits) */ + for (j = 0; j < DILITHIUM_N / 2; j += 4) { + /* Make values positive and pack 2 4-bit values into 1 byte. */ + p[j + 0] = (((byte)(4 - s[j * 2 + 0])) << 0) | + (((byte)(4 - s[j * 2 + 1])) << 4); + p[j + 1] = (((byte)(4 - s[j * 2 + 2])) << 0) | + (((byte)(4 - s[j * 2 + 3])) << 4); + p[j + 2] = (((byte)(4 - s[j * 2 + 4])) << 0) | + (((byte)(4 - s[j * 2 + 5])) << 4); + p[j + 3] = (((byte)(4 - s[j * 2 + 6])) << 0) | + (((byte)(4 - s[j * 2 + 7])) << 4); + } + #endif + /* Move to next place to encode into. */ + p += DILITHIUM_N / 2; + /* Next polynomial. */ + s += DILITHIUM_N; + } + } + else +#endif + { + } +} +#endif /* !WOLFSSL_DILITHIUM_NO_MAKE_KEY */ + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || defined(WOLFSSL_DILITHIUM_CHECK_KEY) + +#if !defined(WOLFSSL_NO_ML_DSA_44) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Decode polynomial with range -2..2. + * + * FIPS 204. 8.2: Algorithm 19 skDecode(sk) + * ... + * 5: for i from 0 to l - 1 do + * 6: s1[i] <- BitUnpack(yi, eta, eta) + * 7: end for + * ... + * OR + * ... + * 8: for i from 0 to k - 1 do + * 9: s2[i] <- BitUnpack(zi, eta, eta) + * 10: end for + * ... + * Where y and z are arrays of bit arrays. + * + * @param [in] p Buffer of data to decode. + * @param [in] s Vector of decoded polynomials. + */ +static void dilithium_decode_eta_2_bits(const byte* p, sword32* s) +{ + unsigned int j; + + /* Step 6 or 9. + * 3 bits to encode each number. + * 8 numbers from 3 bytes. (8 * 3 bits = 3 * 8 bits) */ + for (j = 0; j < DILITHIUM_N; j += 8) { + /* Get 3 bits and put in range of -2..2. */ + s[j + 0] = 2 - ((p[0] >> 0) & 0x7 ); + s[j + 1] = 2 - ((p[0] >> 3) & 0x7 ); + s[j + 2] = 2 - ((p[0] >> 6) | ((p[1] << 2) & 0x7)); + s[j + 3] = 2 - ((p[1] >> 1) & 0x7 ); + s[j + 4] = 2 - ((p[1] >> 4) & 0x7 ); + s[j + 5] = 2 - ((p[1] >> 7) | ((p[2] << 1) & 0x7)); + s[j + 6] = 2 - ((p[2] >> 2) & 0x7 ); + s[j + 7] = 2 - ((p[2] >> 5) & 0x7 ); + /* Move to next place to decode from. */ + p += DILITHIUM_ETA_2_BITS; + } +} +#endif +#ifndef WOLFSSL_NO_ML_DSA_65 +/* Decode polynomial with range -4..4. + * + * FIPS 204. 8.2: Algorithm 19 skDecode(sk) + * ... + * 5: for i from 0 to l - 1 do + * 6: s1[i] <- BitUnpack(yi, eta, eta) + * 7: end for + * ... + * OR + * ... + * 8: for i from 0 to k - 1 do + * 9: s2[i] <- BitUnpack(zi, eta, eta) + * 10: end for + * ... + * Where y and z are arrays of bit arrays. + * + * @param [in] p Buffer of data to decode. + * @param [in] s Vector of decoded polynomials. + */ +static void dilithium_decode_eta_4_bits(const byte* p, sword32* s) +{ + unsigned int j; + +#ifdef WOLFSSL_DILITHIUM_SMALL + /* Step 6 or 9. + * 4 bits to encode each number. + * 2 numbers from 1 bytes. (2 * 4 bits = 1 * 8 bits) */ + for (j = 0; j < DILITHIUM_N / 2; j++) { + /* Get 4 bits and put in range of -4..4. */ + s[j * 2 + 0] = 4 - (p[j] & 0xf); + s[j * 2 + 1] = 4 - (p[j] >> 4); + } +#else + /* Step 6 or 9. + * 4 bits to encode each number. + * 8 numbers from 4 bytes. (8 * 4 bits = 4 * 8 bits) */ + for (j = 0; j < DILITHIUM_N / 2; j += 4) { + /* Get 4 bits and put in range of -4..4. */ + s[j * 2 + 0] = 4 - (p[j + 0] & 0xf); + s[j * 2 + 1] = 4 - (p[j + 0] >> 4); + s[j * 2 + 2] = 4 - (p[j + 1] & 0xf); + s[j * 2 + 3] = 4 - (p[j + 1] >> 4); + s[j * 2 + 4] = 4 - (p[j + 2] & 0xf); + s[j * 2 + 5] = 4 - (p[j + 2] >> 4); + s[j * 2 + 6] = 4 - (p[j + 3] & 0xf); + s[j * 2 + 7] = 4 - (p[j + 3] >> 4); + } +#endif /* WOLFSSL_DILITHIUM_SMALL */ +} +#endif + +#if defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + (defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) || \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM))) +/* Decode vector of polynomials with range -ETA..ETA. + * + * FIPS 204. 8.2: Algorithm 19 skDecode(sk) + * ... + * 5: for i from 0 to l - 1 do + * 6: s1[i] <- BitUnpack(yi, eta, eta) + * 7: end for + * ... + * OR + * ... + * 8: for i from 0 to k - 1 do + * 9: s2[i] <- BitUnpack(zi, eta, eta) + * 10: end for + * ... + * Where y and z are arrays of bit arrays. + * + * @param [in] p Buffer of data to decode. + * @param [in] eta Range specifier of each value. + * @param [in] s Vector of decoded polynomials. + * @param [in] d Dimension of vector. + */ +static void dilithium_vec_decode_eta_bits(const byte* p, byte eta, sword32* s, + byte d) +{ + unsigned int i; + +#if !defined(WOLFSSL_NO_ML_DSA_44) || !defined(WOLFSSL_NO_ML_DSA_87) + /* -2..2 */ + if (eta == DILITHIUM_ETA_2) { + /* Step 5 or 8: For each polynomial of vector */ + for (i = 0; i < d; i++) { + dilithium_decode_eta_2_bits(p, s); + /* Move to next place to decode from. */ + p += DILITHIUM_ETA_2_BITS * DILITHIUM_N / 8; + /* Next polynomial. */ + s += DILITHIUM_N; + } + } + else +#endif +#ifndef WOLFSSL_NO_ML_DSA_65 + /* -4..4 */ + if (eta == DILITHIUM_ETA_4) { + /* Step 5 or 8: For each polynomial of vector */ + for (i = 0; i < d; i++) { + dilithium_decode_eta_4_bits(p, s); + /* Move to next place to decode from. */ + p += DILITHIUM_N / 2; + /* Next polynomial. */ + s += DILITHIUM_N; + } + } + else +#endif + { + } +} +#endif +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN || WOLFSSL_DILITHIUM_CHECK_KEY */ + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY +/* Encode t into t0 and t1. + * + * FIPS 204. 8.4: Algorithm 29 Power2Round(r) + * 1: r+ <- r mod q + * 2: r0 <- r+ mod +/- 2^d + * 3: return ((r+ - r0) / 2^d, r0) + * + * FIPS 204. 8.2: Algorithm 18 skEncode(rho, K, tr, s1, s2, t0) + * ... + * 8: for i form 0 to k - 1 do + * 9: sk <- sk || BitPack(t0[i], s^(d-1) - 1, 2^(d-1)) + * 10: end for + * + * FIPS 204. 8.2: Algorithm 16 pkEncode(rho, t1) + * ... + * 2: for i from 0 to k - 1 do + * 3: pk <- pk || SimpleBitPack(t1[i], 2^bitlen(q-1) - d - 1) + * 4: end for + * + * @param [in] t Vector of polynomials. + * @param [in] d Dimension of vector. + * @param [out] t0 Buffer to encode bottom part of value of t into. + * @param [out] t1 Buffer to encode top part of value of t into. + */ +static void dilithium_vec_encode_t0_t1(sword32* t, byte d, byte* t0, byte* t1) +{ + unsigned int i; + unsigned int j; + + /* Alg 18, Step 8 and Alg 16, Step 2. For each polynomial of vector. */ + for (i = 0; i < d; i++) { + /* Alg 18, Step 9 and Alg 16, Step 3. + * Do all polynomial values - 8 at a time. */ + for (j = 0; j < DILITHIUM_N; j += 8) { + /* Take 8 values of t and take top bits and make positive. */ + word16 n1_0 = (t[j + 0] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_1 = (t[j + 1] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_2 = (t[j + 2] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_3 = (t[j + 3] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_4 = (t[j + 4] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_5 = (t[j + 5] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_6 = (t[j + 6] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + word16 n1_7 = (t[j + 7] + DILITHIUM_D_MAX_HALF - 1) >> DILITHIUM_D; + /* Take 8 values of t and take bottom bits and make positive. */ + word16 n0_0 = DILITHIUM_D_MAX_HALF - + (t[j + 0] - (n1_0 << DILITHIUM_D)); + word16 n0_1 = DILITHIUM_D_MAX_HALF - + (t[j + 1] - (n1_1 << DILITHIUM_D)); + word16 n0_2 = DILITHIUM_D_MAX_HALF - + (t[j + 2] - (n1_2 << DILITHIUM_D)); + word16 n0_3 = DILITHIUM_D_MAX_HALF - + (t[j + 3] - (n1_3 << DILITHIUM_D)); + word16 n0_4 = DILITHIUM_D_MAX_HALF - + (t[j + 4] - (n1_4 << DILITHIUM_D)); + word16 n0_5 = DILITHIUM_D_MAX_HALF - + (t[j + 5] - (n1_5 << DILITHIUM_D)); + word16 n0_6 = DILITHIUM_D_MAX_HALF - + (t[j + 6] - (n1_6 << DILITHIUM_D)); + word16 n0_7 = DILITHIUM_D_MAX_HALF - + (t[j + 7] - (n1_7 << DILITHIUM_D)); + + /* 13 bits per number. + * 8 numbers become 13 bytes. (8 * 13 bits = 13 * 8 bits) */ + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 2) + word32* tp; + #endif + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + tp = (word32*)t0; + tp[0] = (n0_0 ) | ((word32)n0_1 << 13) | ((word32)n0_2 << 26); + tp[1] = (n0_2 >> 6) | ((word32)n0_3 << 7) | ((word32)n0_4 << 20); + tp[2] = (n0_4 >> 12) | ((word32)n0_5 << 1) | + ((word32)n0_6 << 14) | ((word32)n0_7 << 27); + #else + t0[ 0] = (n0_0 << 0); + t0[ 1] = (n0_0 >> 8) | (n0_1 << 5); + t0[ 2] = (n0_1 >> 3) ; + t0[ 3] = (n0_1 >> 11) | (n0_2 << 2); + t0[ 4] = (n0_2 >> 6) | (n0_3 << 7); + t0[ 5] = (n0_3 >> 1) ; + t0[ 6] = (n0_3 >> 9) | (n0_4 << 4); + t0[ 7] = (n0_4 >> 4) ; + t0[ 8] = (n0_4 >> 12) | (n0_5 << 1); + t0[ 9] = (n0_5 >> 7) | (n0_6 << 6); + t0[10] = (n0_6 >> 2) ; + t0[11] = (n0_6 >> 10) | (n0_7 << 3); + #endif + t0[12] = (n0_7 >> 5) ; + + /* 10 bits per number. + * 8 bytes become 10 bytes. (8 * 10 bits = 10 * 8 bits) */ + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 2) + tp = (word32*)t1; + tp[0] = (n1_0 ) | ((word32)n1_1 << 10) | + ((word32)n1_2 << 20) | ((word32)n1_3 << 30); + tp[1] = (n1_3 >> 2) | ((word32)n1_4 << 8) | + ((word32)n1_5 << 18) | ((word32)n1_6 << 28); + #else + t1[0] = (n1_0 << 0); + t1[1] = (n1_0 >> 8) | (n1_1 << 2); + t1[2] = (n1_1 >> 6) | (n1_2 << 4); + t1[3] = (n1_2 >> 4) | (n1_3 << 6); + t1[4] = (n1_3 >> 2) ; + t1[5] = (n1_4 << 0); + t1[6] = (n1_4 >> 8) | (n1_5 << 2); + t1[7] = (n1_5 >> 6) | (n1_6 << 4); + #endif + t1[8] = (n1_6 >> 4) | (n1_7 << 6); + t1[9] = (n1_7 >> 2) ; + + /* Move to next place to encode bottom bits to. */ + t0 += DILITHIUM_D; + /* Move to next place to encode top bits to. */ + t1 += DILITHIUM_U; + } + /* Next polynomial. */ + t += DILITHIUM_N; + } +} +#endif /* !WOLFSSL_DILITHIUM_NO_MAKE_KEY */ + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || defined(WOLFSSL_DILITHIUM_CHECK_KEY) +/* Decode bottom D bits of t as t0. + * + * FIPS 204. 8.2: Algorithm 19 skDecode(sk) + * ... + * 12: t0[i] <- BitUnpack(wi, 2^(d-1) - 1, 2^(d-1) + * ... + * + * @param [in] t0 Encoded values of t0. + * @param [in] d Dimensions of vector t0. + * @param [out] t Vector of polynomials. + */ +static void dilithium_decode_t0(const byte* t0, sword32* t) +{ + unsigned int j; + + /* Step 12. Get 13 bits and convert to range (2^(d-1)-1)..2^(d-1). */ + for (j = 0; j < DILITHIUM_N; j += 8) { + /* 13 bits used per number. + * 8 numbers from 13 bytes. (8 * 13 bits = 13 * 8 bits) */ +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + word32 t32_2 = ((const word32*)t0)[2]; + #ifdef WC_64BIT_CPU + word64 t64 = *(const word64*)t0; + t[j + 0] = DILITHIUM_D_MAX_HALF - ( t64 & 0x1fff); + t[j + 1] = DILITHIUM_D_MAX_HALF - ((t64 >> 13) & 0x1fff); + t[j + 2] = DILITHIUM_D_MAX_HALF - ((t64 >> 26) & 0x1fff); + t[j + 3] = DILITHIUM_D_MAX_HALF - ((t64 >> 39) & 0x1fff); + t[j + 4] = DILITHIUM_D_MAX_HALF - + ((t64 >> 52) | ((t32_2 & 0x0001) << 12)); + #else + word32 t32_0 = ((const word32*)t0)[0]; + word32 t32_1 = ((const word32*)t0)[1]; + t[j + 0] = DILITHIUM_D_MAX_HALF - + ( t32_0 & 0x1fff); + t[j + 1] = DILITHIUM_D_MAX_HALF - + ((t32_0 >> 13) & 0x1fff); + t[j + 2] = DILITHIUM_D_MAX_HALF - + (( t32_0 >> 26 ) | ((t32_1 & 0x007f) << 6)); + t[j + 3] = DILITHIUM_D_MAX_HALF - + ((t32_1 >> 7) & 0x1fff); + t[j + 4] = DILITHIUM_D_MAX_HALF - + (( t32_1 >> 20 ) | ((t32_2 & 0x0001) << 12)); + #endif + t[j + 5] = DILITHIUM_D_MAX_HALF - + ((t32_2 >> 1) & 0x1fff); + t[j + 6] = DILITHIUM_D_MAX_HALF - + ((t32_2 >> 14) & 0x1fff); + t[j + 7] = DILITHIUM_D_MAX_HALF - + (( t32_2 >> 27 ) | ((word32)t0[12] ) << 5 ); +#else + t[j + 0] = DILITHIUM_D_MAX_HALF - + ((t0[ 0] ) | (((word16)(t0[ 1] & 0x1f)) << 8)); + t[j + 1] = DILITHIUM_D_MAX_HALF - + ((t0[ 1] >> 5) | (((word16)(t0[ 2] )) << 3) | + (((word16)(t0[ 3] & 0x03)) << 11)); + t[j + 2] = DILITHIUM_D_MAX_HALF - + ((t0[ 3] >> 2) | (((word16)(t0[ 4] & 0x7f)) << 6)); + t[j + 3] = DILITHIUM_D_MAX_HALF - + ((t0[ 4] >> 7) | (((word16)(t0[ 5] )) << 1) | + (((word16)(t0[ 6] & 0x0f)) << 9)); + t[j + 4] = DILITHIUM_D_MAX_HALF - + ((t0[ 6] >> 4) | (((word16)(t0[ 7] )) << 4) | + (((word16)(t0[ 8] & 0x01)) << 12)); + t[j + 5] = DILITHIUM_D_MAX_HALF - + ((t0[ 8] >> 1) | (((word16)(t0[ 9] & 0x3f)) << 7)); + t[j + 6] = DILITHIUM_D_MAX_HALF - + ((t0[ 9] >> 6) | (((word16)(t0[10] )) << 2) | + (((word16)(t0[11] & 0x07)) << 10)); + t[j + 7] = DILITHIUM_D_MAX_HALF - + ((t0[11] >> 3) | (((word16)(t0[12] )) << 5)); +#endif + /* Move to next place to decode from. */ + t0 += DILITHIUM_D; + } +} + +#if defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + (defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) || \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM))) +/* Decode bottom D bits of t as t0. + * + * FIPS 204. 8.2: Algorithm 19 skDecode(sk) + * ... + * 11: for i from 0 to k - 1 do + * 12: t0[i] <- BitUnpack(wi, 2^(d-1) - 1, 2^(d-1) + * 13: end for + * ... + * + * @param [in] t0 Encoded values of t0. + * @param [in] d Dimensions of vector t0. + * @param [out] t Vector of polynomials. + */ +static void dilithium_vec_decode_t0(const byte* t0, byte d, sword32* t) +{ + unsigned int i; + + /* Step 11. For each polynomial of vector. */ + for (i = 0; i < d; i++) { + dilithium_decode_t0(t0, t); + t0 += DILITHIUM_D * DILITHIUM_N / 8; + /* Next polynomial. */ + t += DILITHIUM_N; + } +} +#endif +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN || WOLFSSL_DILITHIUM_CHECK_KEY */ + +#if !defined(WOLFSSL_DILITHIUM_NO_VERIFY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) +/* Decode top bits of t as t1. + * + * FIPS 204. 8.2: Algorithm 17 pkDecode(pk) + * ... + * 4: t1[i] <- SimpleBitUnpack(zi, 2^(bitlen(q-1)-d) - 1) + * ... + * + * @param [in] t1 Encoded values of t1. + * @param [out] t Polynomials. + */ +static void dilithium_decode_t1(const byte* t1, sword32* t) +{ + unsigned int j; + /* Step 4. Get 10 bits as a number. */ + for (j = 0; j < DILITHIUM_N; j += 8) { + /* 10 bits used per number. + * 8 numbers from 10 bytes. (8 * 10 bits = 10 * 8 bits) */ +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + #ifdef WC_64BIT_CPU + word64 t64 = *(const word64*) t1; + word16 t16 = *(const word16*)(t1 + 8); + t[j+0] = (sword32)( ( t64 & 0x03ff) << DILITHIUM_D); + t[j+1] = (sword32)( ((t64 >> 10) & 0x03ff) << DILITHIUM_D); + t[j+2] = (sword32)( ((t64 >> 20) & 0x03ff) << DILITHIUM_D); + t[j+3] = (sword32)( ((t64 >> 30) & 0x03ff) << DILITHIUM_D); + t[j+4] = (sword32)( ((t64 >> 40) & 0x03ff) << DILITHIUM_D); + t[j+5] = (sword32)( ((t64 >> 50) & 0x03ff) << DILITHIUM_D); + t[j+6] = (sword32)((((t64 >> 60)| (t16 << 4)) & 0x03ff) << DILITHIUM_D); + t[j+7] = (sword32)( ((t16 >> 6) & 0x03ff) << DILITHIUM_D); + #else + word32 t32 = *((const word32*)t1); + t[j + 0] = ( t32 & 0x03ff ) << + DILITHIUM_D; + t[j + 1] = ((t32 >> 10) & 0x03ff ) << + DILITHIUM_D; + t[j + 2] = ((t32 >> 20) & 0x03ff ) << + DILITHIUM_D; + t[j + 3] = ((t32 >> 30) | (((word16)t1[4]) << 2)) << + DILITHIUM_D; + t32 = *((const word32*)(t1 + 5)); + t[j + 4] = ( t32 & 0x03ff ) << + DILITHIUM_D; + t[j + 5] = ((t32 >> 10) & 0x03ff ) << + DILITHIUM_D; + t[j + 6] = ((t32 >> 20) & 0x03ff ) << + DILITHIUM_D; + t[j + 7] = ((t32 >> 30) | (((word16)t1[9]) << 2)) << + DILITHIUM_D; + #endif +#else + t[j + 0] = (sword32)((t1[0] >> 0) | (((word16)(t1[1] & 0x03)) << 8)) + << DILITHIUM_D; + t[j + 1] = (sword32)((t1[1] >> 2) | (((word16)(t1[2] & 0x0f)) << 6)) + << DILITHIUM_D; + t[j + 2] = (sword32)((t1[2] >> 4) | (((word16)(t1[3] & 0x3f)) << 4)) + << DILITHIUM_D; + t[j + 3] = (sword32)((t1[3] >> 6) | (((word16)(t1[4] )) << 2)) + << DILITHIUM_D; + t[j + 4] = (sword32)((t1[5] >> 0) | (((word16)(t1[6] & 0x03)) << 8)) + << DILITHIUM_D; + t[j + 5] = (sword32)((t1[6] >> 2) | (((word16)(t1[7] & 0x0f)) << 6)) + << DILITHIUM_D; + t[j + 6] = (sword32)((t1[7] >> 4) | (((word16)(t1[8] & 0x3f)) << 4)) + << DILITHIUM_D; + t[j + 7] = (sword32)((t1[8] >> 6) | (((word16)(t1[9] )) << 2)) + << DILITHIUM_D; +#endif + /* Move to next place to decode from. */ + t1 += DILITHIUM_U; + } +} +#endif + +#if (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) +/* Decode top bits of t as t1. + * + * FIPS 204. 8.2: Algorithm 17 pkDecode(pk) + * ... + * 3: for i from 0 to k - 1 do + * 4: t1[i] <- SimpleBitUnpack(zi, 2^(bitlen(q-1)-d) - 1) + * 5: end for + * ... + * + * @param [in] t1 Encoded values of t1. + * @param [in] d Dimensions of vector t1. + * @param [out] t Vector of polynomials. + */ +static void dilithium_vec_decode_t1(const byte* t1, byte d, sword32* t) +{ + unsigned int i; + + /* Step 3. For each polynomial of vector. */ + for (i = 0; i < d; i++) { + dilithium_decode_t1(t1, t); + /* Next polynomial. */ + t1 += DILITHIUM_U * DILITHIUM_N / 8; + t += DILITHIUM_N; + } +} +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN + +#ifndef WOLFSSL_NO_ML_DSA_44 +/* Encode z with range of -(GAMMA1-1)...GAMMA1 + * + * FIPS 204. 8.2: Algorithm 20 sigEncode(c_tilde, z, h) + * ... + * 3: sigma <- sigma || BitPack(z[i], GAMMA1 - 1, GAMMA1) + * ... + * + * @param [in] z Polynomial to encode. + * @param [out] s Buffer to encode into. + */ +static void dilithium_encode_gamma1_17_bits(const sword32* z, byte* s) +{ + unsigned int j; + + /* Step 3. Get 18 bits as a number. */ + for (j = 0; j < DILITHIUM_N; j += 4) { + word32 z0 = DILITHIUM_GAMMA1_17 - z[j + 0]; + word32 z1 = DILITHIUM_GAMMA1_17 - z[j + 1]; + word32 z2 = DILITHIUM_GAMMA1_17 - z[j + 2]; + word32 z3 = DILITHIUM_GAMMA1_17 - z[j + 3]; + + /* 18 bits per number. + * 8 numbers become 9 bytes. (8 * 9 bits = 9 * 8 bits) */ +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + #ifdef WC_64BIT_CPU + word64* s64p = (word64*)s; + s64p[0] = z0 | ((word64)z1 << 18) | + ((word64)z2 << 36) | ((word64)z3 << 54); + #else + word32* s32p = (word32*)s; + s32p[0] = z0 | (z1 << 18) ; + s32p[1] = (z1 >> 14) | (z2 << 4) | (z3 << 22); + #endif +#else + s[0] = z0 ; + s[1] = z0 >> 8 ; + s[2] = (z0 >> 16) | (z1 << 2); + s[3] = z1 >> 6 ; + s[4] = (z1 >> 14) | (z2 << 4); + s[5] = z2 >> 4 ; + s[6] = (z2 >> 12) | (z3 << 6); + s[7] = z3 >> 2 ; +#endif + s[8] = z3 >> 10 ; + /* Move to next place to encode to. */ + s += DILITHIUM_GAMMA1_17_ENC_BITS / 2; + } +} +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Encode z with range of -(GAMMA1-1)...GAMMA1 + * + * FIPS 204. 8.2: Algorithm 20 sigEncode(c_tilde, z, h) + * ... + * 3: sigma <- sigma || BitPack(z[i], GAMMA1 - 1, GAMMA1) + * ... + * + * @param [in] z Polynomial to encode. + * @param [out] s Buffer to encode into. + */ +static void dilithium_encode_gamma1_19_bits(const sword32* z, byte* s) +{ + unsigned int j; + + /* Step 3. Get 20 bits as a number. */ + for (j = 0; j < DILITHIUM_N; j += 4) { + sword32 z0 = DILITHIUM_GAMMA1_19 - z[j + 0]; + sword32 z1 = DILITHIUM_GAMMA1_19 - z[j + 1]; + sword32 z2 = DILITHIUM_GAMMA1_19 - z[j + 2]; + sword32 z3 = DILITHIUM_GAMMA1_19 - z[j + 3]; + + /* 20 bits per number. + * 4 numbers become 10 bytes. (4 * 20 bits = 10 * 8 bits) */ +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 2) + word16* s16p = (word16*)s; + #ifdef WC_64BIT_CPU + word64* s64p = (word64*)s; + s64p[0] = z0 | ((word64)z1 << 20) | + ((word64)z2 << 40) | ((word64)z3 << 60); + #else + word32* s32p = (word32*)s; + s32p[0] = z0 | (z1 << 20) ; + s32p[1] = (z1 >> 12) | (z2 << 8) | (z3 << 28); + #endif + s16p[4] = (z3 >> 4) ; +#else + s[0] = z0 ; + s[1] = (z0 >> 8) ; + s[2] = (z0 >> 16) | (z1 << 4); + s[3] = (z1 >> 4) ; + s[4] = (z1 >> 12) ; + s[5] = z2 ; + s[6] = (z2 >> 8) ; + s[7] = (z2 >> 16) | (z3 << 4); + s[8] = (z3 >> 4) ; + s[9] = (z3 >> 12) ; +#endif + /* Move to next place to encode to. */ + s += DILITHIUM_GAMMA1_19_ENC_BITS / 2; + } +} +#endif + +#ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM +/* Encode z with range of -(GAMMA1-1)...GAMMA1 + * + * FIPS 204. 8.2: Algorithm 20 sigEncode(c_tilde, z, h) + * ... + * 2: for i form 0 to l - 1 do + * 3: sigma <- sigma || BitPack(z[i], GAMMA1 - 1, GAMMA1) + * 4: end for + * ... + * + * @param [in] z Vector of polynomials to encode. + * @param [in] l Dimension of vector. + * @param [in] bits Number of bits used in encoding - GAMMA1 bits. + * @param [out] s Buffer to encode into. + */ +static void dilithium_vec_encode_gamma1(const sword32* z, byte l, int bits, + byte* s) +{ + unsigned int i; + + (void)l; + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (bits == DILITHIUM_GAMMA1_BITS_17) { + /* Step 2. For each polynomial of vector. */ + for (i = 0; i < PARAMS_ML_DSA_44_L; i++) { + dilithium_encode_gamma1_17_bits(z, s); + /* Move to next place to encode to. */ + s += DILITHIUM_GAMMA1_17_ENC_BITS / 2 * DILITHIUM_N / 4; + /* Next polynomial. */ + z += DILITHIUM_N; + } + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (bits == DILITHIUM_GAMMA1_BITS_19) { + /* Step 2. For each polynomial of vector. */ + for (i = 0; i < l; i++) { + dilithium_encode_gamma1_19_bits(z, s); + /* Move to next place to encode to. */ + s += DILITHIUM_GAMMA1_19_ENC_BITS / 2 * DILITHIUM_N / 4; + /* Next polynomial. */ + z += DILITHIUM_N; + } + } + else +#endif + { + } +} +#endif /* WOLFSSL_DILITHIUM_SIGN_SMALL_MEM */ + +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +/* Decode polynomial with range -(GAMMA1-1)..GAMMA1. + * + * FIPS 204. 8.2: Algorithm 21 sigDecode(sigma) + * ... + * 4: z[i] <- BitUnpack(xi, GAMMA1 - 1, GAMMA1) + * ... + * + * @param [in] s Encoded values of z. + * @param [in] bits Number of bits used in encoding - GAMMA1 bits. + * @param [out] z Polynomial to fill. + */ +static void dilithium_decode_gamma1(const byte* s, int bits, sword32* z) +{ + unsigned int i; + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (bits == DILITHIUM_GAMMA1_BITS_17) { +#if defined(WOLFSSL_DILITHIUM_NO_LARGE_CODE) || defined(WOLFSSL_DILITHIUM_SMALL) + /* Step 4: Get 18 bits as a number. */ + for (i = 0; i < DILITHIUM_N; i += 4) { + /* 18 bits per number. + * 4 numbers from 9 bytes. (4 * 18 bits = 9 * 8 bits) */ + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + #ifdef WC_64BIT_CPU + word64 s64_0 = *(const word64*)(s+0); + z[i+0] = (word32)DILITHIUM_GAMMA1_17 - + ( s64_0 & 0x3ffff ); + z[i+1] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_0 >> 18) & 0x3ffff ); + z[i+2] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_0 >> 36) & 0x3ffff ); + z[i+3] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_0 >> 54) | (((word32)s[8]) << 10)); + #else + word32 s32_0 = ((const word32*)(s+0))[0]; + word32 s32_1 = ((const word32*)(s+0))[1]; + z[i+0] = (word32)DILITHIUM_GAMMA1_17 - + ( s32_0 & 0x3ffff ); + z[i+1] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_0 >> 18) | (((s32_1 & 0x0000f) << 14))); + z[i+2] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_1 >> 4) & 0x3ffff); + z[i+3] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_1 >> 22) | (((word32)s[8]) << 10 )); + #endif + #else + z[i+0] = DILITHIUM_GAMMA1_17 - + ( s[ 0] | ((sword32)(s[ 1] << 8) | + (sword32)(s[ 2] & 0x03) << 16)); + z[i+1] = DILITHIUM_GAMMA1_17 - + ((s[ 2] >> 2) | ((sword32)(s[ 3] << 6) | + (sword32)(s[ 4] & 0x0f) << 14)); + z[i+2] = DILITHIUM_GAMMA1_17 - + ((s[ 4] >> 4) | ((sword32)(s[ 5] << 4) | + (sword32)(s[ 6] & 0x3f) << 12)); + z[i+3] = DILITHIUM_GAMMA1_17 - + ((s[ 6] >> 6) | ((sword32)(s[ 7] << 2) | + (sword32)(s[ 8] ) << 10)); + #endif + /* Move to next place to decode from. */ + s += DILITHIUM_GAMMA1_17_ENC_BITS / 2; + } +#else + /* Step 4: Get 18 bits as a number. */ + for (i = 0; i < DILITHIUM_N; i += 8) { + /* 18 bits per number. + * 8 numbers from 9 bytes. (8 * 18 bits = 18 * 8 bits) */ + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + #ifdef WC_64BIT_CPU + word64 s64_0 = *(const word64*)(s+0); + word64 s64_1 = *(const word64*)(s+9); + z[i+0] = (word32)DILITHIUM_GAMMA1_17 - + ( s64_0 & 0x3ffff ); + z[i+1] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_0 >> 18) & 0x3ffff ); + z[i+2] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_0 >> 36) & 0x3ffff ); + z[i+3] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_0 >> 54) | (((word32)s[8]) << 10)); + z[i+4] = (word32)DILITHIUM_GAMMA1_17 - + ( s64_1 & 0x3ffff ); + z[i+5] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_1 >> 18) & 0x3ffff ); + z[i+6] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_1 >> 36) & 0x3ffff ); + z[i+7] = (word32)DILITHIUM_GAMMA1_17 - + ((s64_1 >> 54) | (((word32)s[17]) << 10)); + #else + word32 s32_0 = ((const word32*)(s+0))[0]; + word32 s32_1 = ((const word32*)(s+0))[1]; + word32 s32_2 = ((const word32*)(s+9))[0]; + word32 s32_3 = ((const word32*)(s+9))[1]; + z[i+0] = (word32)DILITHIUM_GAMMA1_17 - + ( s32_0 & 0x3ffff ); + z[i+1] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_0 >> 18) | (((s32_1 & 0x0000f) << 14))); + z[i+2] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_1 >> 4) & 0x3ffff); + z[i+3] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_1 >> 22) | (((word32)s[8]) << 10 )); + z[i+4] = (word32)DILITHIUM_GAMMA1_17 - + ( s32_2 & 0x3ffff ); + z[i+5] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_2 >> 18) | (((s32_3 & 0x0000f) << 14))); + z[i+6] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_3 >> 4) & 0x3ffff); + z[i+7] = (word32)DILITHIUM_GAMMA1_17 - + ((s32_3 >> 22) | (((word32)s[17]) << 10 )); + #endif + #else + z[i+0] = DILITHIUM_GAMMA1_17 - + ( s[ 0] | ((sword32)(s[ 1] << 8) | + (sword32)(s[ 2] & 0x03) << 16)); + z[i+1] = DILITHIUM_GAMMA1_17 - + ((s[ 2] >> 2) | ((sword32)(s[ 3] << 6) | + (sword32)(s[ 4] & 0x0f) << 14)); + z[i+2] = DILITHIUM_GAMMA1_17 - + ((s[ 4] >> 4) | ((sword32)(s[ 5] << 4) | + (sword32)(s[ 6] & 0x3f) << 12)); + z[i+3] = DILITHIUM_GAMMA1_17 - + ((s[ 6] >> 6) | ((sword32)(s[ 7] << 2) | + (sword32)(s[ 8] ) << 10)); + z[i+4] = DILITHIUM_GAMMA1_17 - + ( s[ 9] | ((sword32)(s[10] << 8) | + (sword32)(s[11] & 0x03) << 16)); + z[i+5] = DILITHIUM_GAMMA1_17 - + ((s[11] >> 2) | ((sword32)(s[12] << 6) | + (sword32)(s[13] & 0x0f) << 14)); + z[i+6] = DILITHIUM_GAMMA1_17 - + ((s[13] >> 4) | ((sword32)(s[14] << 4) | + (sword32)(s[15] & 0x3f) << 12)); + z[i+7] = DILITHIUM_GAMMA1_17 - + ((s[15] >> 6) | ((sword32)(s[16] << 2) | + (sword32)(s[17] ) << 10)); + #endif + /* Move to next place to decode from. */ + s += DILITHIUM_GAMMA1_17_ENC_BITS; + } +#endif + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (bits == DILITHIUM_GAMMA1_BITS_19) { +#if defined(WOLFSSL_DILITHIUM_NO_LARGE_CODE) || defined(WOLFSSL_DILITHIUM_SMALL) + /* Step 4: Get 20 bits as a number. */ + for (i = 0; i < DILITHIUM_N; i += 4) { + /* 20 bits per number. + * 4 numbers from 10 bytes. (4 * 20 bits = 10 * 8 bits) */ + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 2) + word16 s16_0 = ((const word16*)s)[4]; + #ifdef WC_64BIT_CPU + word64 s64_0 = *(const word64*)s; + z[i+0] = DILITHIUM_GAMMA1_19 - ( s64_0 & 0xfffff) ; + z[i+1] = DILITHIUM_GAMMA1_19 - ( (s64_0 >> 20) & 0xfffff) ; + z[i+2] = DILITHIUM_GAMMA1_19 - ( (s64_0 >> 40) & 0xfffff) ; + z[i+3] = DILITHIUM_GAMMA1_19 - (((s64_0 >> 60) & 0xfffff) | + ((sword32)s16_0 << 4)); + #else + word32 s32_0 = ((const word32*)s)[0]; + word32 s32_1 = ((const word32*)s)[1]; + z[i+0] = DILITHIUM_GAMMA1_19 - ( s32_0 & 0xfffff); + z[i+1] = DILITHIUM_GAMMA1_19 - (( s32_0 >> 20) | + ((s32_1 & 0x000ff) << 12)); + z[i+2] = DILITHIUM_GAMMA1_19 - ( (s32_1 >> 8) & 0xfffff); + z[i+3] = DILITHIUM_GAMMA1_19 - (( s32_1 >> 28) | + ((sword32)s16_0 << 4)); + #endif + #else + z[i+0] = DILITHIUM_GAMMA1_19 - ( s[0] | ((sword32)s[1] << 8) | + ((sword32)(s[2] & 0x0f) << 16)); + z[i+1] = DILITHIUM_GAMMA1_19 - ((s[2] >> 4) | ((sword32)s[3] << 4) | + ((sword32)(s[4] ) << 12)); + z[i+2] = DILITHIUM_GAMMA1_19 - ( s[5] | ((sword32)s[6] << 8) | + ((sword32)(s[7] & 0x0f) << 16)); + z[i+3] = DILITHIUM_GAMMA1_19 - ((s[7] >> 4) | ((sword32)s[8] << 4) | + ((sword32)(s[9] ) << 12)); + #endif + /* Move to next place to decode from. */ + s += DILITHIUM_GAMMA1_19_ENC_BITS / 2; + } +#else + /* Step 4: Get 20 bits as a number. */ + for (i = 0; i < DILITHIUM_N; i += 8) { + /* 20 bits per number. + * 8 numbers from 10 bytes. (8 * 20 bits = 20 * 8 bits) */ + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 2) + word16 s16_0 = ((const word16*)s)[4]; + word16 s16_1 = ((const word16*)s)[9]; + #ifdef WC_64BIT_CPU + word64 s64_0 = *(const word64*)(s+0); + word64 s64_1 = *(const word64*)(s+10); + z[i+0] = DILITHIUM_GAMMA1_19 - ( s64_0 & 0xfffff) ; + z[i+1] = DILITHIUM_GAMMA1_19 - ( (s64_0 >> 20) & 0xfffff) ; + z[i+2] = DILITHIUM_GAMMA1_19 - ( (s64_0 >> 40) & 0xfffff) ; + z[i+3] = DILITHIUM_GAMMA1_19 - (((s64_0 >> 60) & 0xfffff) | + ((sword32)s16_0 << 4)); + z[i+4] = DILITHIUM_GAMMA1_19 - ( s64_1 & 0xfffff) ; + z[i+5] = DILITHIUM_GAMMA1_19 - ( (s64_1 >> 20) & 0xfffff) ; + z[i+6] = DILITHIUM_GAMMA1_19 - ( (s64_1 >> 40) & 0xfffff) ; + z[i+7] = DILITHIUM_GAMMA1_19 - (((s64_1 >> 60) & 0xfffff) | + ((sword32)s16_1 << 4)); + #else + word32 s32_0 = ((const word32*)(s+ 0))[0]; + word32 s32_1 = ((const word32*)(s+ 0))[1]; + word32 s32_2 = ((const word32*)(s+10))[0]; + word32 s32_3 = ((const word32*)(s+10))[1]; + z[i+0] = DILITHIUM_GAMMA1_19 - ( s32_0 & 0xfffff); + z[i+1] = DILITHIUM_GAMMA1_19 - (( s32_0 >> 20) | + ((s32_1 & 0x000ff) << 12)); + z[i+2] = DILITHIUM_GAMMA1_19 - ( (s32_1 >> 8) & 0xfffff); + z[i+3] = DILITHIUM_GAMMA1_19 - (( s32_1 >> 28) | + ((sword32)s16_0 << 4)); + z[i+4] = DILITHIUM_GAMMA1_19 - ( s32_2 & 0xfffff); + z[i+5] = DILITHIUM_GAMMA1_19 - (( s32_2 >> 20) | + ((s32_3 & 0x000ff) << 12)); + z[i+6] = DILITHIUM_GAMMA1_19 - ( (s32_3 >> 8) & 0xfffff); + z[i+7] = DILITHIUM_GAMMA1_19 - (( s32_3 >> 28) | + ((sword32)s16_1 << 4)); + #endif + #else + z[i+0] = DILITHIUM_GAMMA1_19 - ( s[ 0] | + ((sword32)s[ 1] << 8) | + ((sword32)(s[ 2] & 0x0f) << 16)); + z[i+1] = DILITHIUM_GAMMA1_19 - ((s[ 2] >> 4) | + ((sword32) s[ 3] << 4) | + ((sword32)(s[ 4] ) << 12)); + z[i+2] = DILITHIUM_GAMMA1_19 - ( s[ 5] | + ((sword32) s[ 6] << 8) | + ((sword32)(s[ 7] & 0x0f) << 16)); + z[i+3] = DILITHIUM_GAMMA1_19 - ((s[ 7] >> 4) | + ((sword32) s[ 8] << 4) | + ((sword32)(s[ 9] ) << 12)); + z[i+4] = DILITHIUM_GAMMA1_19 - ( s[10] | + ((sword32) s[11] << 8) | + ((sword32)(s[12] & 0x0f) << 16)); + z[i+5] = DILITHIUM_GAMMA1_19 - ((s[12] >> 4) | + ((sword32) s[13] << 4) | + ((sword32)(s[14] ) << 12)); + z[i+6] = DILITHIUM_GAMMA1_19 - ( s[15] | + ((sword32) s[16] << 8) | + ((sword32)(s[17] & 0x0f) << 16)); + z[i+7] = DILITHIUM_GAMMA1_19 - ((s[17] >> 4) | + ((sword32) s[18] << 4) | + ((sword32)(s[19] ) << 12)); + #endif + /* Move to next place to decode from. */ + s += DILITHIUM_GAMMA1_19_ENC_BITS; + } +#endif + } + else +#endif + { + } +} +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY +/* Decode polynomial with range -(GAMMA1-1)..GAMMA1. + * + * FIPS 204. 8.2: Algorithm 21 sigDecode(sigma) + * ... + * 3: for i from 0 to l - 1 do + * 4: z[i] <- BitUnpack(xi, GAMMA1 - 1, GAMMA1) + * 5: end for + * ... + * + * @param [in] x Encoded values of t0. + * @param [in] l Dimensions of vector z. + * @param [in] bits Number of bits used in encoding - GAMMA1 bits. + * @param [out] z Vector of polynomials. + */ +static void dilithium_vec_decode_gamma1(const byte* x, byte l, int bits, + sword32* z) +{ + unsigned int i; + + /* Step 3: For each polynomial of vector. */ + for (i = 0; i < l; i++) { + /* Step 4: Unpack a polynomial. */ + dilithium_decode_gamma1(x, bits, z); + /* Move pointers on to next polynomial. */ + x += DILITHIUM_N / 8 * (bits + 1); + z += DILITHIUM_N; + } +} +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +#ifndef WOLFSSL_NO_ML_DSA_44 +/* Encode w1 with range of 0..((q-1)/(2*GAMMA2)-1). + * + * FIPS 204. 8.2: Algorithm 22 w1Encode(w1) + * ... + * 3: w1_tilde <- w1_tilde || + * ByteToBits(SimpleBitPack(w1[i], (q-1)/(2*GAMMA2)-1)) + * ... + * + * @param [in] w1 Vector of polynomials to encode. + * @param [in] gamma2 Maximum value in range. + * @param [out] w1e Buffer to encode into. + */ +static void dilithium_encode_w1_88(const sword32* w1, byte* w1e) +{ + unsigned int j; + + /* Step 3: Encode a polynomial values 6 bits at a time. */ + for (j = 0; j < DILITHIUM_N; j += 16) { + /* 6 bits per number. + * 16 numbers in 12 bytes. (16 * 6 bits = 12 * 8 bits) */ +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 4) + word32* w1e32 = (word32*)w1e; + w1e32[0] = w1[j+ 0] | (w1[j+ 1] << 6) | + (w1[j+ 2] << 12) | (w1[j+ 3] << 18) | + (w1[j+ 4] << 24) | (w1[j+ 5] << 30); + w1e32[1] = (w1[j+ 5] >> 2) | (w1[j+ 6] << 4) | + (w1[j+ 7] << 10) | (w1[j+ 8] << 16) | + (w1[j+ 9] << 22) | (w1[j+10] << 28); + w1e32[2] = (w1[j+10] >> 4) | (w1[j+11] << 2) | + (w1[j+12] << 8) | (w1[j+13] << 14) | + (w1[j+14] << 20) | (w1[j+15] << 26); +#else + w1e[ 0] = w1[j+ 0] | (w1[j+ 1] << 6); + w1e[ 1] = (w1[j+ 1] >> 2) | (w1[j+ 2] << 4); + w1e[ 2] = (w1[j+ 2] >> 4) | (w1[j+ 3] << 2); + w1e[ 3] = w1[j+ 4] | (w1[j+ 5] << 6); + w1e[ 4] = (w1[j+ 5] >> 2) | (w1[j+ 6] << 4); + w1e[ 5] = (w1[j+ 6] >> 4) | (w1[j+ 7] << 2); + w1e[ 6] = w1[j+ 8] | (w1[j+ 9] << 6); + w1e[ 7] = (w1[j+ 9] >> 2) | (w1[j+10] << 4); + w1e[ 8] = (w1[j+10] >> 4) | (w1[j+11] << 2); + w1e[ 9] = w1[j+12] | (w1[j+13] << 6); + w1e[10] = (w1[j+13] >> 2) | (w1[j+14] << 4); + w1e[11] = (w1[j+14] >> 4) | (w1[j+15] << 2); +#endif + /* Move to next place to encode to. */ + w1e += DILITHIUM_Q_HI_88_ENC_BITS * 2; + } +} +#endif /* !WOLFSSL_NO_ML_DSA_44 */ + +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Encode w1 with range of 0..((q-1)/(2*GAMMA2)-1). + * + * FIPS 204. 8.2: Algorithm 22 w1Encode(w1) + * ... + * 3: w1_tilde <- w1_tilde || + * ByteToBits(SimpleBitPack(w1[i], (q-1)/(2*GAMMA2)-1)) + * ... + * + * @param [in] w1 Vector of polynomials to encode. + * @param [in] gamma2 Maximum value in range. + * @param [out] w1e Buffer to encode into. + */ +static void dilithium_encode_w1_32(const sword32* w1, byte* w1e) +{ + unsigned int j; + + /* Step 3: Encode a polynomial values 4 bits at a time. */ + for (j = 0; j < DILITHIUM_N; j += 16) { + /* 4 bits per number. + * 16 numbers in 8 bytes. (16 * 4 bits = 8 * 8 bits) */ +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT <= 8) + word32* w1e32 = (word32*)w1e; + w1e32[0] = (w1[j + 0] << 0) | (w1[j + 1] << 4) | + (w1[j + 2] << 8) | (w1[j + 3] << 12) | + (w1[j + 4] << 16) | (w1[j + 5] << 20) | + (w1[j + 6] << 24) | (w1[j + 7] << 28); + w1e32[1] = (w1[j + 8] << 0) | (w1[j + 9] << 4) | + (w1[j + 10] << 8) | (w1[j + 11] << 12) | + (w1[j + 12] << 16) | (w1[j + 13] << 20) | + (w1[j + 14] << 24) | (w1[j + 15] << 28); +#else + w1e[0] = w1[j + 0] | (w1[j + 1] << 4); + w1e[1] = w1[j + 2] | (w1[j + 3] << 4); + w1e[2] = w1[j + 4] | (w1[j + 5] << 4); + w1e[3] = w1[j + 6] | (w1[j + 7] << 4); + w1e[4] = w1[j + 8] | (w1[j + 9] << 4); + w1e[5] = w1[j + 10] | (w1[j + 11] << 4); + w1e[6] = w1[j + 12] | (w1[j + 13] << 4); + w1e[7] = w1[j + 14] | (w1[j + 15] << 4); +#endif + /* Move to next place to encode to. */ + w1e += DILITHIUM_Q_HI_32_ENC_BITS * 2; + } +} +#endif +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) +/* Encode w1 with range of 0..((q-1)/(2*GAMMA2)-1). + * + * FIPS 204. 8.2: Algorithm 22 w1Encode(w1) + * 1: w1_tilde = () + * 2: for i form 0 to k - 1 do + * 3: w1_tilde <- w1_tilde || + * ByteToBits(SimpleBitPack(w1[i], (q-1)/(2*GAMMA2)-1)) + * 4: end for + * 5: return w1_tilde + * + * @param [in] w1 Vector of polynomials to encode. + * @param [in] k Dimension of vector. + * @param [in] gamma2 Maximum value in range. + * @param [out] w1e Buffer to encode into. + */ +static void dilithium_vec_encode_w1(const sword32* w1, byte k, sword32 gamma2, + byte* w1e) +{ + unsigned int i; + + (void)k; + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (gamma2 == DILITHIUM_Q_LOW_88) { + /* Step 2. For each polynomial of vector. */ + for (i = 0; i < PARAMS_ML_DSA_44_K; i++) { + dilithium_encode_w1_88(w1, w1e); + /* Next polynomial. */ + w1 += DILITHIUM_N; + w1e += DILITHIUM_Q_HI_88_ENC_BITS * 2 * DILITHIUM_N / 16; + } + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (gamma2 == DILITHIUM_Q_LOW_32) { + /* Step 2. For each polynomial of vector. */ + for (i = 0; i < k; i++) { + dilithium_encode_w1_32(w1, w1e); + /* Next polynomial. */ + w1 += DILITHIUM_N; + w1e += DILITHIUM_Q_HI_32_ENC_BITS * 2 * DILITHIUM_N / 16; + } + } + else +#endif + { + } +} +#endif + +/****************************************************************************** + * Expand operations + ******************************************************************************/ + +/* Generate a random polynomial by rejection. + * + * FIPS 204. 8.3: Algorithm 24 RejNTTPoly(rho) + * 1: j <- 0 + * 2: c <- 0 + * 3: while j < 256 do + * 4: a_hat[j] <- CoeffFromThreeBytes(H128(rho)[[c]], H128(rho)[[c+1]], + * H128(rho)[[c+2]]) + * 5: c <- c + 3 + * 6: if a_hat[j] != falsam then + * 7: j <- j + 1 + * 8: end if + * 9: end while + * 10: return a_hat + * + * FIPS 204. 8.1: Algorithm 8 CoeffFromThreeBytes(b0,b1,b2) + * 1: if b2 > 127 then + * 2: b2 <- b2 - 128 + * 3. end if + * 4. z <- 2^16.b2 + s^8.b1 + b0 + * 5. if z < q then return z + * 6. else return falsam + * 7. end if + * + * @param [in, out] shake128 SHAKE-128 object. + * @param [in] seed Seed to hash to generate values. + * @param [out] a Polynomial. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Negative on hash error. + */ +static int dilithium_rej_ntt_poly(wc_Shake* shake128, byte* seed, sword32* a, + byte* key_h) +{ +#ifdef WOLFSSL_DILITHIUM_SMALL + int ret = 0; + int j = 0; +#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) + byte* h = NULL; +#else + byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; +#endif + + (void)key_h; + +#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + h = key_h; +#elif defined(WOLFSSL_SMALL_STACK) + h = (byte*)XMALLOC(DILITHIUM_REJ_NTT_POLY_H_SIZE, NULL, + DYNAMIC_TYPE_DILITHIUM); + if (h == NULL) { + ret = MEMORY_E; + } +#endif /* WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC */ + + if (ret == 0) { + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Reading 4 bytes for 3 so need to set 1 past for last read. */ + h[DILITHIUM_GEN_A_BLOCK_BYTES] = 0; + #endif + + /* Initialize SHAKE-128 object for new hash. */ + ret = wc_InitShake128(shake128, NULL, INVALID_DEVID); + } + if (ret == 0) { + /* Absorb the seed. */ + ret = wc_Shake128_Absorb(shake128, seed, DILITHIUM_GEN_A_SEED_SZ); + } + /* Keep generating more blocks and using triplets until we have enough. + */ + while ((ret == 0) && (j < DILITHIUM_N)) { + /* Squeeze out a block - 168 bytes = 56 values. */ + ret = wc_Shake128_SqueezeBlocks(shake128, h, 1); + if (ret == 0) { + int c; + /* Use triplets until run out or have enough for polynomial. */ + for (c = 0; c < DILITHIUM_GEN_A_BLOCK_BYTES; c += 3) { + #if defined(LITTLE_ENDIAN_ORDER) && \ + (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Load 32-bit value and mask out 23 bits. */ + sword32 t = *((sword32*)(h + c)) & 0x7fffff; + #else + /* Load 24-bit value and mask out 23 bits. */ + sword32 t = (h[c] + ((sword32)h[c+1] << 8) + + ((sword32)h[c+2] << 16)) & 0x7fffff; + #endif + /* Check if value is in valid range. */ + if (t < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. + */ + a[j++] = t; + /* Check we whether we have enough yet. */ + if (j == DILITHIUM_N) { + break; + } + } + } + } + } + +#if !defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && defined(WOLFSSL_SMALL_STACK) + XFREE(h, NULL, DYNAMIC_TYPE_DILITHIUM); +#endif + return ret; +#else + int ret = 0; + unsigned int j = 0; + unsigned int c; +#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) + byte* h = NULL; +#else + byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; +#endif + + (void)key_h; + +#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + h = key_h; +#elif defined(WOLFSSL_SMALL_STACK) + h = (byte*)XMALLOC(DILITHIUM_REJ_NTT_POLY_H_SIZE, NULL, + DYNAMIC_TYPE_DILITHIUM); + if (h == NULL) { + ret = MEMORY_E; + } +#endif /* WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC */ + + if (ret == 0) { + /* Generate enough SHAKE-128 output blocks to give high probability of + * being able to get 256 valid 3-byte, 23-bit values from it. */ + ret = dilithium_squeeze128(shake128, seed, DILITHIUM_GEN_A_SEED_SZ, h, + DILITHIUM_GEN_A_NBLOCKS); + } + if (ret == 0) { + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Reading 4 bytes for 3 so need to set 1 past for last read. */ + h[DILITHIUM_GEN_A_BYTES] = 0; + #endif + + /* Use the first 256 triplets and know we won't exceed required. */ +#ifdef WOLFSSL_DILITHIUM_NO_LARGE_CODE + for (c = 0; c < (DILITHIUM_N - 1) * 3; c += 3) { + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Load 32-bit value and mask out 23 bits. */ + sword32 t = *((sword32*)(h + c)) & 0x7fffff; + #else + /* Load 24-bit value and mask out 23 bits. */ + sword32 t = (h[c] + ((sword32)h[c+1] << 8) + + ((sword32)h[c+2] << 16)) & 0x7fffff; + #endif + /* Check if value is in valid range. */ + if (t < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t; + } + } + /* Use the remaining triplets, checking we have enough. */ + for (; c < DILITHIUM_GEN_A_BYTES; c += 3) { + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Load 32-bit value and mask out 23 bits. */ + sword32 t = *((sword32*)(h + c)) & 0x7fffff; + #else + /* Load 24-bit value and mask out 23 bits. */ + sword32 t = (h[c] + ((sword32)h[c+1] << 8) + + ((sword32)h[c+2] << 16)) & 0x7fffff; + #endif + /* Check if value is in valid range. */ + if (t < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t; + /* Check we whether we have enough yet. */ + if (j == DILITHIUM_N) { + break; + } + } + } +#else + /* Do 15 bytes at a time: 255 * 3 / 15 = 51 */ + for (c = 0; c < DILITHIUM_N * 3; c += 24) { + #if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Load 32-bit value and mask out 23 bits. */ + sword32 t0 = *((sword32*)(h + c + 0)) & 0x7fffff; + sword32 t1 = *((sword32*)(h + c + 3)) & 0x7fffff; + sword32 t2 = *((sword32*)(h + c + 6)) & 0x7fffff; + sword32 t3 = *((sword32*)(h + c + 9)) & 0x7fffff; + sword32 t4 = *((sword32*)(h + c + 12)) & 0x7fffff; + sword32 t5 = *((sword32*)(h + c + 15)) & 0x7fffff; + sword32 t6 = *((sword32*)(h + c + 18)) & 0x7fffff; + sword32 t7 = *((sword32*)(h + c + 21)) & 0x7fffff; + #else + /* Load 24-bit value and mask out 23 bits. */ + sword32 t0 = (h[c + 0] + ((sword32)h[c + 1] << 8) + + ((sword32)h[c + 2] << 16)) & 0x7fffff; + sword32 t1 = (h[c + 3] + ((sword32)h[c + 4] << 8) + + ((sword32)h[c + 5] << 16)) & 0x7fffff; + sword32 t2 = (h[c + 6] + ((sword32)h[c + 7] << 8) + + ((sword32)h[c + 8] << 16)) & 0x7fffff; + sword32 t3 = (h[c + 9] + ((sword32)h[c + 10] << 8) + + ((sword32)h[c + 11] << 16)) & 0x7fffff; + sword32 t4 = (h[c + 12] + ((sword32)h[c + 13] << 8) + + ((sword32)h[c + 14] << 16)) & 0x7fffff; + sword32 t5 = (h[c + 15] + ((sword32)h[c + 16] << 8) + + ((sword32)h[c + 17] << 16)) & 0x7fffff; + sword32 t6 = (h[c + 18] + ((sword32)h[c + 19] << 8) + + ((sword32)h[c + 20] << 16)) & 0x7fffff; + sword32 t7 = (h[c + 21] + ((sword32)h[c + 22] << 8) + + ((sword32)h[c + 23] << 16)) & 0x7fffff; + #endif + /* Check if value is in valid range. */ + if (t0 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t0; + } + /* Check if value is in valid range. */ + if (t1 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t1; + } + /* Check if value is in valid range. */ + if (t2 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t2; + } + /* Check if value is in valid range. */ + if (t3 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t3; + } + /* Check if value is in valid range. */ + if (t4 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t4; + } + /* Check if value is in valid range. */ + if (t5 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t5; + } + /* Check if value is in valid range. */ + if (t6 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t6; + } + /* Check if value is in valid range. */ + if (t7 < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. */ + a[j++] = t7; + } + } + if (j < DILITHIUM_N) { + /* Use the remaining triplets, checking we have enough. */ + for (; c < DILITHIUM_GEN_A_BYTES; c += 3) { + #if defined(LITTLE_ENDIAN_ORDER) && \ + (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Load 32-bit value and mask out 23 bits. */ + sword32 t = *((sword32*)(h + c)) & 0x7fffff; + #else + /* Load 24-bit value and mask out 23 bits. */ + sword32 t = (h[c] + ((sword32)h[c+1] << 8) + + ((sword32)h[c+2] << 16)) & 0x7fffff; + #endif + /* Check if value is in valid range. */ + if (t < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. + */ + a[j++] = t; + /* Check we whether we have enough yet. */ + if (j == DILITHIUM_N) { + break; + } + } + } + } +#endif + /* Keep generating more blocks and using triplets until we have enough. + */ + while (j < DILITHIUM_N) { + /* Squeeze out a block - 168 bytes = 56 values. */ + ret = wc_Shake128_SqueezeBlocks(shake128, h, 1); + if (ret != 0) { + break; + } + /* Use triplets until run out or have enough for polynomial. */ + for (c = 0; c < DILITHIUM_GEN_A_BLOCK_BYTES; c += 3) { + #if defined(LITTLE_ENDIAN_ORDER) && \ + (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* Load 32-bit value and mask out 23 bits. */ + sword32 t = *((sword32*)(h + c)) & 0x7fffff; + #else + /* Load 24-bit value and mask out 23 bits. */ + sword32 t = (h[c] + ((sword32)h[c+1] << 8) + + ((sword32)h[c+2] << 16)) & 0x7fffff; + #endif + /* Check if value is in valid range. */ + if (t < DILITHIUM_Q) { + /* Store value in polynomial and increment count of values. + */ + a[j++] = t; + /* Check we whether we have enough yet. */ + if (j == DILITHIUM_N) { + break; + } + } + } + } + } + +#if !defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && defined(WOLFSSL_SMALL_STACK) + XFREE(h, NULL, DYNAMIC_TYPE_DILITHIUM); +#endif + return ret; +#endif +} + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + (!defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM) || \ + defined(WC_DILITHIUM_CACHE_MATRIX_A))) +/* Expand the seed to create matrix a. + * + * FIPS 204. 8.3: Algorithm 26 ExpandA(rho) + * 1: for r from 0 to k - 1 do + * 2: for s from 0 to l - 1 do + * 3: A_hat[r,s] <- RejNTTPoly(rho||IntegerToBits(s,8)|| + * IntegerToBits(r,8)) + * 4: end for + * 5: end for + * 6: return A_hat + * + * @param [in, out] shake128 SHAKE-128 object. + * @param [in] pub_seed Seed to generate stream of data. + * @param [in] k First dimension of matrix a. + * @param [in] l Second dimension of matrix a. + * @param [out] a Matrix of polynomials. + * @return 0 on success. + * @return Negative on hash error. + */ +static int dilithium_expand_a(wc_Shake* shake128, const byte* pub_seed, byte k, + byte l, sword32* a) +{ + int ret = 0; + byte r; + byte s; + byte seed[DILITHIUM_GEN_A_SEED_SZ]; + + /* Copy the seed into a buffer that has space for s and r. */ + XMEMCPY(seed, pub_seed, DILITHIUM_PUB_SEED_SZ); + /* Step 1: Loop over first dimension of matrix. */ + for (r = 0; (ret == 0) && (r < k); r++) { + /* Put r into buffer to be hashed. */ + seed[DILITHIUM_PUB_SEED_SZ + 1] = r; + /* Step 2: Loop over second dimension of matrix. */ + for (s = 0; (ret == 0) && (s < l); s++) { + /* Put s into buffer to be hashed. */ + seed[DILITHIUM_PUB_SEED_SZ + 0] = s; + /* Step 3: Create polynomial from hashing seed. */ + ret = dilithium_rej_ntt_poly(shake128, seed, a, NULL); + /* Next polynomial. */ + a += DILITHIUM_N; + } + } + + return ret; +} +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY + +#if !defined(WOLFSSL_NO_ML_DSA_44) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Check random value is in valid range. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 1: if b < 15 + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 2 - unused. + * @return 1 when value less than 9. + * @return 0 when value greater than or equal to 9. + */ +#define DILITHIUM_COEFF_S_VALID_ETA2(b) \ + ((b) < DILITHIUM_ETA_2_MOD) + +static const byte dilithium_coeff_eta2[] = { + 2, 1, 0, -1, -2, + 2, 1, 0, -1, -2, + 2, 1, 0, -1, -2 +}; +/* Convert random value 0..15 to a value in range of -2..2. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 1: return 2 - (b mod 5) + * + * @param [in] b Random half-byte (nibble) value. + * @return Value in range of -2..2 on success. + */ +#define DILITHIUM_COEFF_S_ETA2(b) \ + (dilithium_coeff_eta2[b]) +#endif + +#ifndef WOLFSSL_NO_ML_DSA_65 +/* Check random value is in valid range. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 3: if b < 9 + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 4 - unused. + * @return 1 when value less than 9. + * @return 0 when value greater than or equal to 9. + */ +#define DILITHIUM_COEFF_S_VALID_ETA4(b) \ + ((b) < DILITHIUM_ETA_4_MOD) + +/* Convert random value 0..15 to a value in range of -4..4. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 3: return 4 - b + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 4 - unused. + * @return Value in range of -4..4 on success. + */ +#define DILITHIUM_COEFF_S_ETA4(b) \ + (4 - (b)) +#endif + +#if !defined(WOLFSSL_NO_ML_DSA_44) || !defined(WOLFSSL_NO_ML_DSA_87) +#ifndef WOLFSSL_NO_ML_DSA_65 + +/* Check random value is in valid range. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 1: if eta = 2 and b < 15 + * 2: else + * 3: if eta = 4 and b < 9 + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. + * @return Value in range of -ETA..ETA on success. + */ +#define DILITHIUM_COEFF_S_VALID(b, eta) \ + (((eta) == DILITHIUM_ETA_2) ? DILITHIUM_COEFF_S_VALID_ETA2(b) : \ + DILITHIUM_COEFF_S_VALID_ETA4(b)) + +/* Convert random value 0..15 to a value in range of -ETA..ETA. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 1: if eta = 2 then return 2 - (b mod 5) + * 2: else + * 3: if eta = 4 then return 4 - b + * ... + * 6: end if + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. + * @return Value in range of -ETA..ETA on success. + */ +#define DILITHIUM_COEFF_S(b, eta) \ + (((eta) == DILITHIUM_ETA_2) ? DILITHIUM_COEFF_S_ETA2(b) \ + : DILITHIUM_COEFF_S_ETA4(b)) + +#else + +/* Check random value is in valid range. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 1: if b < 15 + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 2 - unused. + * @return 1 when value less than 9. + * @return 0 when value greater than or equal to 9. + */ +#define DILITHIUM_COEFF_S_VALID(b, eta) \ + DILITHIUM_COEFF_S_VALID_ETA2(b) + +/* Convert random value 0..15 to a value in range of -2..2. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 1: return 2 - (b mod 5) + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 2 - unused. + * @return Value in range of -2..2 on success. + */ +#define DILITHIUM_COEFF_S(b, eta) \ + DILITHIUM_COEFF_S_ETA2(b) + +#endif /* WOLFSSL_NO_ML_DSA_65 */ + +#else + +/* Check random value is in valid range. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 3: if b < 9 + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 4 - unused. + * @return 1 when value less than 9. + * @return 0 when value greater than or equal to 9. + */ +#define DILITHIUM_COEFF_S_VALID(b, eta) \ + DILITHIUM_COEFF_S_VALID_ETA4(b) + +/* Convert random value 0..15 to a value in range of -4..4. + * + * FIPS 204. 8.1: Algorithm 9 CoeffFromHalfByte(b) + * 3: return 4 - b + * + * @param [in] b Random half-byte (nibble) value. + * @param [in] eta Range specifier of result. Will always be 4 - unused. + * @return Value in range of -4..4 on success. + */ +#define DILITHIUM_COEFF_S(b, eta) \ + DILITHIUM_COEFF_S_ETA4(b) + +#endif /* !WOLFSSL_NO_ML_DSA_44 || !WOLFSSL_NO_ML_DSA_87 */ + +/* Extract a coefficient from a nibble of z. + * + * Breaks out of loop when we have enough coefficients. + * + * @param [in] z A random value. + * @param [in] rs Amount to shift right. + * @param [in] t Temporary result. + * @param [in] eta ETA value from parameters. + * @return Value in range -eta..eta on success. + * @return Falsam (0x10) when random value out of range. + */ +#define EXTRACT_COEFF_NIBBLE_CHECK_J(z, rs, t, eta) \ + (t) = (sword8)(((z) >> (rs)) & 0xf); \ + /* Step 7: Check we have a valid coefficient. */ \ + if (DILITHIUM_COEFF_S_VALID(t, eta)) { \ + (t) = DILITHIUM_COEFF_S(t, eta); \ + /* Step 8: Store coefficient as next polynomial value. \ + * Step 9: Increment count of polynomial values set. */ \ + s[j++] = (sword32)(t); \ + if (j == DILITHIUM_N) { \ + break; \ + } \ + } + +/* Extract a coefficient from a nibble of z. + * + * @param [in] z A random value. + * @param [in] rs Amount to shift right. + * @param [in] t Temporary result. + * @param [in] eta ETA value from parameters. + * @return Value in range -eta..eta on success. + * @return Falsam (0x10) when random value out of range. + */ +#define EXTRACT_COEFF_NIBBLE(z, rs, t, eta) \ + (t) = (sword8)(((z) >> (rs)) & 0xf); \ + /* Step 7: Check we have a valid coefficient. */ \ + if (DILITHIUM_COEFF_S_VALID(t, eta)) { \ + (t) = DILITHIUM_COEFF_S(t, eta); \ + /* Step 8: Store coefficient as next polynomial value. \ + * Step 9: Increment count of polynomial values set. */ \ + s[j++] = (sword32)(t); \ + } + + +/* Extract coefficients from hash - z. + * + * FIPS 204. 8.3: Algorithm 25 RejBoundedPoly(rho) + * 2: c <- 0 + * 5: z0 <- CoeffFromHalfByte(z mod 16, eta) + * 6: z1 <- CoeffFromHalfByte(lower(z / 16), eta) + * 7: if z0 != falsam then + * 8: aj <- z0 + * 9: j <- j + 1 + * 10: end if + * 11: if z1 != falsam then + * 12: aj <- z1 + * 13: j <- j + 1 + * 14: end if + * 15: c <- c + 1 + * + * @param [in] z Hash data to extract coefficients from. + * @param [in] zLen Length of z in bytes. + * @param [in] eta Range specifier of each value. + * @param [out] s Polynomial to fill with coefficients. + * @param [in, out] cnt Current count of coefficients in polynomial. + */ +static void dilithium_extract_coeffs(byte* z, unsigned int zLen, byte eta, + sword32* s, unsigned int* cnt) +{ +#ifdef WOLFSSL_DILITHIUM_NO_LARGE_CODE + unsigned int j = *cnt; + unsigned int c; + + (void)eta; + + /* Extract values from the squeezed data. */ + for (c = 0; c < zLen; c++) { + sword8 t; + + /* Step 5: Get coefficient from bottom nibble. */ + EXTRACT_COEFF_NIBBLE_CHECK_J(z[c], 0, t, eta); + /* Step 6: Get coefficient from top nibble. */ + EXTRACT_COEFF_NIBBLE_CHECK_J(z[c], 4, t, eta); + } + + *cnt = j; +#else + unsigned int j = *cnt; + unsigned int c; + unsigned int min = (DILITHIUM_N - j) / 2; + + (void)eta; + +#if defined(LITTLE_ENDIAN_ORDER) +#ifdef WC_64BIT_CPU + min &= ~(unsigned int)7; + /* Extract values from the squeezed data. */ + for (c = 0; c < min; c += 8) { + word64 z64 = *(word64*)(z + c); + sword8 t; + + /* Do each nibble from lowest to highest 16 at a time. */ + EXTRACT_COEFF_NIBBLE(z64, 0, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 4, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 8, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 12, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 16, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 20, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 24, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 28, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 32, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 36, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 40, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 44, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 48, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 52, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 56, t, eta); + EXTRACT_COEFF_NIBBLE(z64, 60, t, eta); + } +#else + min &= ~(unsigned int)3; + /* Extract values from the squeezed data. */ + for (c = 0; c < min; c += 4) { + word32 z32 = *(word32*)(z + c); + sword8 t; + + /* Do each nibble from lowest to highest 8 at a time. */ + EXTRACT_COEFF_NIBBLE(z32, 0, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 4, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 8, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 12, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 16, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 20, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 24, t, eta); + EXTRACT_COEFF_NIBBLE(z32, 28, t, eta); + } +#endif +#else + /* Extract values from the squeezed data. */ + for (c = 0; c < min; c++) { + sword8 t; + + /* Step 5: Get coefficient from bottom nibble. */ + EXTRACT_COEFF_NIBBLE(z[c], 0, t, eta); + EXTRACT_COEFF_NIBBLE(z[c], 4, t, eta); + } +#endif + if (j != DILITHIUM_N) { + /* Extract values from the squeezed data. */ + for (; c < zLen; c++) { + sword8 t; + + EXTRACT_COEFF_NIBBLE_CHECK_J(z[c], 0, t, eta); + EXTRACT_COEFF_NIBBLE_CHECK_J(z[c], 4, t, eta); + } + } + + *cnt = j; +#endif +} + +/* Create polynomial from hashing the seed with bounded values. + * + * FIPS 204. 8.3: Algorithm 25 RejBoundedPoly(rho) + * 1: j <- 0 + * ... + * 3: while j < 256 do + * 4: z <- H(rho)[[c]] + * ... [Extract coefficients into polynomial from z] + * 16: end while + * 17: return a + * + * @param [in, out] shake256 SHAKE-256 object. + * @param [in] seed Seed, rho, to hash to generate values. + * @param [in] eta Range specifier of each value. + * @return 0 on success. + * @return Negative on hash error. + */ +static int dilithium_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s, + byte eta) +{ +#ifdef WOLFSSL_DILITHIUM_SMALL + int ret; + unsigned int j = 0; + byte z[DILITHIUM_GEN_S_BLOCK_BYTES]; + + /* Initialize SHAKE-256 object for new hash. */ + ret = wc_InitShake256(shake256, NULL, INVALID_DEVID); + if (ret == 0) { + /* Absorb the seed. */ + ret = wc_Shake256_Absorb(shake256, seed, DILITHIUM_GEN_S_SEED_SZ); + } + if (ret == 0) { + do { + /* Squeeze out another block. */ + ret = wc_Shake256_SqueezeBlocks(shake256, z, 1); + if (ret != 0) { + break; + } + /* Extract up to the 256 valid coefficients for polynomial. */ + dilithium_extract_coeffs(z, DILITHIUM_GEN_S_BLOCK_BYTES, eta, s, + &j); + } + /* Check we got enough values to fill polynomial. */ + while (j < DILITHIUM_N); + } + + return ret; +#else + int ret; + unsigned int j = 0; + byte z[DILITHIUM_GEN_S_BYTES]; + + /* Absorb seed and squeeze out some blocks. */ + ret = dilithium_squeeze256(shake256, seed, DILITHIUM_GEN_S_SEED_SZ, z, + DILITHIUM_GEN_S_NBLOCKS); + if (ret == 0) { + /* Extract up to 256 valid coefficients for polynomial. */ + dilithium_extract_coeffs(z, DILITHIUM_GEN_S_BYTES, eta, s, &j); + /* Check we got enough values to fill polynomial. */ + while (j < DILITHIUM_N) { + /* Squeeze out another block. */ + ret = wc_Shake256_SqueezeBlocks(shake256, z, 1); + if (ret != 0) { + break; + } + /* Extract up to the 256 valid coefficients for polynomial. */ + dilithium_extract_coeffs(z, DILITHIUM_GEN_S_BLOCK_BYTES, eta, s, + &j); + } + } + + return ret; +#endif +} + +/* Expand private seed into vectors s1 and s2. + * + * FIPS 204. 8.3: Algorithm 27 ExpandS(rho) + * 1: for r from 0 to l - 1 do + * 2: s1[r] <- RejBoundedPoly(rho||IntegerToBits(r,16)) + * 3: end for + * 4: for r from 0 to k - 1 do + * 5: s2[r] <- RejBoundedPoly(rho||IntegerToBits(r + l,16)) + * 6: end for + * 7: return (s1,s2) + * + * @param [in, out] shake256 SHAKE-256 object. + * @param [in] priv_seed Private seed, rho, to expand. + * @param [in] eta Range specifier of each value. + * @param [out] s1 First vector of polynomials. + * @param [in] s1Len Dimension of first vector. + * @param [out] s2 Second vector of polynomials. + * @param [in] s2Len Dimension of second vector. + * @return 0 on success. + * @return Negative on hash error. + */ +static int dilithium_expand_s(wc_Shake* shake256, byte* priv_seed, byte eta, + sword32* s1, byte s1Len, sword32* s2, byte s2Len) +{ + int ret = 0; + byte r; + byte seed[DILITHIUM_GEN_S_SEED_SZ]; + + /* Copy the seed into a buffer that has space for r. */ + XMEMCPY(seed, priv_seed, DILITHIUM_PRIV_SEED_SZ); + /* Set top 8-bits of r in buffer to 0. */ + seed[DILITHIUM_PRIV_SEED_SZ + 1] = 0; + /* Step 1: Each polynomial in s1. */ + for (r = 0; (ret == 0) && (r < s1Len); r++) { + /* Set bottom 8-bits of r into buffer - little endian. */ + seed[DILITHIUM_PRIV_SEED_SZ] = r; + + /* Step 2: Generate polynomial for s1. */ + ret = dilithium_rej_bound_poly(shake256, seed, s1, eta); + /* Next polynomial in s1. */ + s1 += DILITHIUM_N; + } + /* Step 4: Each polynomial in s2. */ + for (r = 0; (ret == 0) && (r < s2Len); r++) { + /* Set bottom 8-bits of r + l into buffer - little endian. */ + seed[DILITHIUM_PRIV_SEED_SZ] = r + s1Len; + /* Step 5: Generate polynomial for s1. */ + ret = dilithium_rej_bound_poly(shake256, seed, s2, eta); + /* Next polynomial in s2. */ + s2 += DILITHIUM_N; + } + + return ret; +} + +#endif /* !WOLFSSL_DILITHIUM_NO_MAKE_KEY */ + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN +/* Expand the private random seed into vector y. + * + * FIPS 204. 8.3: Algorithm 28 ExpandMask(rho, mu) + * 1: c <- 1 + bitlen(GAMMA1 - 1) + * 2: for r from 0 to l - 1 do + * 3: n <- IntegerToBits(mu + r, 16) + * 4: v <- (H(rho||n)[[32rc]], H(rho||n)[[32rc + 1]], ..., + * H(rho||n)[[32rc + 32c - 1]]) + * 5: s[r] <- BitUnpack(v, GAMMA-1, GAMMA1) + * 6: end for + * 7: return s + * + * @param [in, out] shake256 SHAKE-256 object. + * @param [in, out] seed Buffer containing seed to expand. + * Has space for two bytes to be appended. + * @param [in] kappa Base value to append to seed. + * @param [in] gamma1_bits Number of bits per value. + * @param [out] y Vector of polynomials. + * @param [in] l Dimension of vector. + * @return 0 on success. + * @return Negative on hash error. + */ +static int dilithium_vec_expand_mask(wc_Shake* shake256, byte* seed, + word16 kappa, byte gamma1_bits, sword32* y, byte l) +{ + int ret = 0; + byte r; + byte v[DILITHIUM_MAX_V]; + + /* Step 2: For each polynomial of vector. */ + for (r = 0; (ret == 0) && (r < l); r++) { + /* Step 3: Calculate value to append to seed. */ + word16 n = kappa + r; + + /* Step 4: Append to seed and squeeze out data. */ + seed[DILITHIUM_PRIV_RAND_SEED_SZ + 0] = n; + seed[DILITHIUM_PRIV_RAND_SEED_SZ + 1] = n >> 8; + ret = dilithium_squeeze256(shake256, seed, DILITHIUM_Y_SEED_SZ, v, + DILITHIUM_MAX_V_BLOCKS); + if (ret == 0) { + /* Decode v into polynomial. */ + dilithium_decode_gamma1(v, gamma1_bits, y); + /* Next polynomial. */ + y += DILITHIUM_N; + } + } + + return ret; +} +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +/* Expand commit to a polynomial. + * + * FIPS 204. 8.3: Algorithm 23 SampleInBall(rho) + * 1: c <- 0 + * 2: k <- 8 + * 3: for i from 256 - TAU to 255 do + * 4: while H(rho)[[k]] > i do + * 5: k <- k + 1 + * 6: end while + * 7: j <- H(rho)[[k]] + * 8: c[i] <- c[j] + * 9: c[j] <- (-1)^H(rho)[i+TAU-256] + * 10: k <- k + 1 + * 11: end for + * 12: return c + * + * @param [in] shake256 SHAKE-256 object. + * @param [in] seed Buffer containing seed to expand. + * @param [in] tau Number of +/- 1s in polynomial. + * @param [out] c Commit polynomial. + * @param [in] key_block Memory to use for block from key. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Negative on hash error. + */ +static int dilithium_sample_in_ball(wc_Shake* shake256, const byte* seed, + byte tau, sword32* c, byte* key_block) +{ + int ret = 0; + unsigned int k; + unsigned int i; + unsigned int s; +#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) + byte* block = NULL; +#else + byte block[DILITHIUM_GEN_C_BLOCK_BYTES]; +#endif + byte signs[DILITHIUM_SIGN_BYTES]; + + (void)key_block; + +#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + block = key_block; +#elif defined(WOLFSSL_SMALL_STACK) + block = (byte*)XMALLOC(DILITHIUM_GEN_C_BLOCK_BYTES, NULL, + DYNAMIC_TYPE_DILITHIUM); + if (block == NULL) { + ret = MEMORY_E; + } +#endif + + if (ret == 0) { + /* Set polynomial to all zeros. */ + XMEMSET(c, 0, DILITHIUM_POLY_SIZE); + + /* Generate a block of data from seed. */ + ret = dilithium_shake256(shake256, seed, DILITHIUM_SEED_SZ, block, + DILITHIUM_GEN_C_BLOCK_BYTES); + } + if (ret == 0) { + /* Copy first 8 bytes of first hash block as random sign bits. */ + XMEMCPY(signs, block, DILITHIUM_SIGN_BYTES); + /* Step 1: Initialize sign bit index. */ + s = 0; + /* Step 2: First 8 bytes are used for sign. */ + k = DILITHIUM_SIGN_BYTES; + } + + /* Step 3: Put in TAU +/- 1s. */ + for (i = DILITHIUM_N - tau; (ret == 0) && (i < DILITHIUM_N); i++) { + unsigned int j; + do { + /* Check whether block is exhausted. */ + if (k == DILITHIUM_GEN_C_BLOCK_BYTES) { + /* Generate a new block. */ + ret = wc_Shake256_SqueezeBlocks(shake256, block, 1); + /* Restart hash block index. */ + k = 0; + } + /* Step 7: Get random byte from block as index. + * Step 5 and 10: Increment hash block index. + */ + j = block[k++]; + } + /* Step 4: Get another random if random index is a future swap index. */ + while ((ret == 0) && (j > i)); + + /* Step 8: Move value from random index to current index. */ + c[i] = c[j]; + /* Step 9: Set value at random index to +/- 1. */ + c[j] = 1 - ((((signs[s >> 3]) >> (s & 0x7)) & 0x1) << 1); + /* Next sign bit index. */ + s++; + } + +#if !defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && defined(WOLFSSL_SMALL_STACK) + XFREE(block, NULL, DYNAMIC_TYPE_DILITHIUM); +#endif + return ret; +} +#endif + +/****************************************************************************** + * Decompose operations + ******************************************************************************/ + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +#ifndef WOLFSSL_NO_ML_DSA_44 +/* Decompose value into high and low based on GAMMA2 being ((q-1) / 88). + * + * FIPS 204. 8.4: Algorithm 30 Decompose(r) + * 1: r+ <- r mod q + * 2: r0 <- r+ mod+/- (2 * GAMMA2) + * 3: if r+ - r0 = q - 1 then + * 4: r1 <- 0 + * 5: r0 <- r0 - 1 + * 6: else r1 <- (r+ - r0) / (2 * GAMMA2) + * 7: end if + * 8: return (r1, r0) + * + * DILITHIUM_Q_LOW_88_2 = 0x2e800 = 0b101110100000000000 + * t1 * DILITHIUM_Q_LOW_88_2 = (t1 << 18) - (t1 << 16) - (t1 << 12) - (t1 << 11) + * = ((93 * t1) << 11) + * Nothing faster than straight multiply. + * + * Implementation using Barrett Reduction. + * + * @param [in] r Value to decompose. + * @param [out] r0 Low bits. + * @param [out] r1 High bits. + */ +static void dilithium_decompose_q88(sword32 r, sword32* r0, sword32* r1) +{ + sword32 t0; + sword32 t1; +#ifdef DILITHIUM_MUL_SLOW + sword32 t2; +#endif + + /* Roundup r and calculate approx high value. */ +#if !defined(DILITHIUM_MUL_44_SLOW) + t1 = ((r * 44) + ((DILITHIUM_Q_LOW_88 - 1) * 44)) >> 23; +#elif !defined(DILITHIUM_MUL_11_SLOW) + t1 = ((r * 11) + ((DILITHIUM_Q_LOW_88 - 1) * 11)) >> 21; +#else + t0 = r + DILITHIUM_Q_LOW_88 - 1; + t1 = ((t0 << 3) + (t0 << 1) + t0) >> 21; +#endif + /* Calculate approx low value. */ + t0 = r - (t1 * DILITHIUM_Q_LOW_88_2); +#ifndef DILITHIUM_MUL_SLOW + /* Calculate real high value, When t0 > modulus, +1 to approx high value. */ + t1 += ((word32)(DILITHIUM_Q_LOW_88 - t0)) >> 31; + /* Calculate real low value. */ + t0 = r - (t1 * DILITHIUM_Q_LOW_88_2); +#else + /* Calculate real high value, When t0 > modulus, +1 to approx high value. */ + t2 = ((word32)(DILITHIUM_Q_LOW_88 - t0)) >> 31; + t1 += t2; + /* Calculate real low value. */ + t0 -= (0 - t2) & DILITHIUM_Q_LOW_88_2; +#endif + /* -1 from low value if high value is 44. Was 43 but low is negative. */ + t0 -= ((word32)(43 - t1)) >> 31; + /* When high value is 44, too large, set to 0. */ + t1 &= 0 - (((word32)(t1 - 44)) >> 31); + + *r0 = t0; + *r1 = t1; +} +#endif + +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Decompose value into high and low based on GAMMA2 being ((q-1) / 32). + * + * FIPS 204. 8.4: Algorithm 30 Decompose(r) + * 1: r+ <- r mod q + * 2: r0 <- r+ mod+/- (2 * GAMMA2) + * 3: if r+ - r0 = q - 1 then + * 4: r1 <- 0 + * 5: r0 <- r0 - 1 + * 6: else r1 <- (r+ - r0) / (2 * GAMMA2) + * 7: end if + * 8: return (r1, r0) + * + * DILITHIUM_Q_LOW_32_2 = 0x7fe00 = 0b1111111111000000000 + * t1 * DILITHIUM_Q_LOW_32_2 = (t1 << 19) - (t1 << 9) + * + * Implementation using Barrett Reduction. + * + * @param [in] r Value to decompose. + * @param [out] r0 Low bits. + * @param [out] r1 High bits. + */ +static void dilithium_decompose_q32(sword32 r, sword32* r0, sword32* r1) +{ + sword32 t0; + sword32 t1; + + /* Roundup r and calculate approx high value. */ + t1 = (r + DILITHIUM_Q_LOW_32 - 1) >> 19; + /* Calculate approx low value. */ + t0 = r - (t1 << 19) + (t1 << 9); + /* Calculate real high value, When t0 > modulus, +1 to approx high value. */ + t1 += ((word32)(DILITHIUM_Q_LOW_32 - t0)) >> 31; + /* Calculate real low value. */ + t0 = r - (t1 << 19) + (t1 << 9); + /* -1 from low value if high value is 16. Was 15 but low is negative. */ + t0 -= t1 >> 4; + /* When high value is 16, too large, set to 0. */ + t1 &= 0xf; + + *r0 = t0; + *r1 = t1; +} +#endif +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN + +#ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM +/* Decompose vector of polynomials into high and low based on GAMMA2. + * + * @param [in] r Vector of polynomials to decompose. + * @param [in] k Dimension of vector. + * @param [in] gamma2 Low-order rounding range, GAMMA2. + * @param [out] r0 Low parts in vector of polynomials. + * @param [out] r1 High parts in vector of polynomials. + */ +static void dilithium_vec_decompose(const sword32* r, byte k, sword32 gamma2, + sword32* r0, sword32* r1) +{ + unsigned int i; + unsigned int j; + + (void)k; + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (gamma2 == DILITHIUM_Q_LOW_88) { + /* For each polynomial of vector. */ + for (i = 0; i < PARAMS_ML_DSA_44_K; i++) { + /* For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + /* Decompose value into two vectors. */ + dilithium_decompose_q88(r[j], &r0[j], &r1[j]); + } + /* Next polynomial of vectors. */ + r += DILITHIUM_N; + r0 += DILITHIUM_N; + r1 += DILITHIUM_N; + } + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (gamma2 == DILITHIUM_Q_LOW_32) { + /* For each polynomial of vector. */ + for (i = 0; i < k; i++) { + /* For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + /* Decompose value into two vectors. */ + dilithium_decompose_q32(r[j], &r0[j], &r1[j]); + } + /* Next polynomial of vectors. */ + r += DILITHIUM_N; + r0 += DILITHIUM_N; + r1 += DILITHIUM_N; + } + } + else +#endif + { + } +} +#endif + +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +/****************************************************************************** + * Range check operation + ******************************************************************************/ + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +/* Check that the values of the polynomial are in range. + * + * Many places in FIPS 204. One example from Algorithm 2: + * 23: if ||z||inf >= GAMMA1 - BETA or ..., then (z, h) = falsam + * + * @param [in] a Polynomial. + * @param [in] hi Largest value in range. + */ +static int dilithium_check_low(const sword32* a, sword32 hi) +{ + int ret = 1; + unsigned int j; + /* Calculate lowest range value. */ + sword32 nhi = -hi; + + /* For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + /* Check range is -(hi-1)..(hi-1). */ + if ((a[j] <= nhi) || (a[j] >= hi)) { + /* Check failed. */ + ret = 0; + break; + } + } + + return ret; +} + +#if (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) +/* Check that the values of the vector are in range. + * + * Many places in FIPS 204. One example from Algorithm 2: + * 23: if ||z||inf >= GAMMA1 - BETA or ..., then (z, h) = falsam + * + * @param [in] a Vector of polynomials. + * @param [in] l Dimension of vector. + * @param [in] hi Largest value in range. + */ +static int dilithium_vec_check_low(const sword32* a, byte l, sword32 hi) +{ + int ret = 1; + unsigned int i; + + /* For each polynomial of vector. */ + for (i = 0; (ret == 1) && (i < l); i++) { + ret = dilithium_check_low(a, hi); + if (ret == 0) { + break; + } + /* Next polynomial. */ + a += DILITHIUM_N; + } + + return ret; +} +#endif +#endif + +/****************************************************************************** + * Hint operations + ******************************************************************************/ + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN + +#ifndef WOLFSSL_NO_ML_DSA_44 +/* Compute hints indicating whether adding ct0 to w alters high bits of w. + * + * FIPS 204. 6: Algorithm 2 ML-DSA.Sign(sk, M) + * ... + * 26: h <- MakeHint(-<>, w - <> + <>) + * 27: if ... or the number of 1's in h is greater than OMEGA, then + * (z, h) <- falsam + * ... + * 32: sigma <- sigEncode(c_tilda, z mod+/- q, h) + * ... + * + * FIPS 204. 8.4: Algorithm 33 MakeHint(z, r) + * 1: r1 <- HighBits(r) + * 2: v1 <- HightBits(r+z) + * 3: return [[r1 != v1]] + * + * FIPS 204. 8.2: Algorithm 20 sigEncode(c_tilde, z, h) + * ... + * 5: sigma <- sigma || HintBitPack(h) + * ... + * + * FIPS 204. 8.1: Algorithm 14 HintBitPack(h) + * ... + * 4: for j from 0 to 255 do + * 5: if h[i]j != 0 then + * 6: y[Index] <- j + * 7: Index <- Index + 1 + * 8: end if + * 9: end for + * ... + * + * @param [in] s Vector of polynomials that is sum of ct0 and w0. + * @param [in] w1 Vector of polynomials that is high part of w. + * @param [out] h Encoded hints. + * @param [in, out] idxp Index to write next hint into. + * return Number of hints on success. + * return Falsam of -1 when too many hints. + */ +static int dilithium_make_hint_88(const sword32* s, const sword32* w1, byte* h, + byte *idxp) +{ + unsigned int j; + byte idx = *idxp; + + /* Alg 14, Step 3: For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + /* Alg 14, Step 4: Check whether hint is required. + * Did sum end up greater than low modulus or + * sum end up less than the negative of low modulus or + * sum is the negative of the low modulus and w1 is not zero, + * then w1 will be modified. + */ + if ((s[j] > (sword32)DILITHIUM_Q_LOW_88) || + (s[j] < -(sword32)DILITHIUM_Q_LOW_88) || + ((s[j] == -(sword32)DILITHIUM_Q_LOW_88) && + (w1[j] != 0))) { + /* Alg 14, Step 6, 7: Put index as hint modifier. */ + h[idx++] = (byte)j; + /* Alg 2, Step 27: If there are too many hints, return + * falsam of -1. */ + if (idx > PARAMS_ML_DSA_44_OMEGA) { + return -1; + } + } + } + + *idxp = idx; + return 0; +} +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Compute hints indicating whether adding ct0 to w alters high bits of w. + * + * FIPS 204. 6: Algorithm 2 ML-DSA.Sign(sk, M) + * ... + * 26: h <- MakeHint(-<>, w - <> + <>) + * 27: if ... or the number of 1's in h is greater than OMEGA, then + * (z, h) <- falsam + * ... + * 32: sigma <- sigEncode(c_tilda, z mod+/- q, h) + * ... + * + * FIPS 204. 8.4: Algorithm 33 MakeHint(z, r) + * 1: r1 <- HighBits(r) + * 2: v1 <- HightBits(r+z) + * 3: return [[r1 != v1]] + * + * FIPS 204. 8.2: Algorithm 20 sigEncode(c_tilde, z, h) + * ... + * 5: sigma <- sigma || HintBitPack(h) + * ... + * + * FIPS 204. 8.1: Algorithm 14 HintBitPack(h) + * ... + * 4: for j from 0 to 255 do + * 5: if h[i]j != 0 then + * 6: y[Index] <- j + * 7: Index <- Index + 1 + * 8: end if + * 9: end for + * ... + * + * @param [in] s Vector of polynomials that is sum of ct0 and w0. + * @param [in] w1 Vector of polynomials that is high part of w. + * @param [in] omega Maximum number of hints allowed. + * @param [out] h Encoded hints. + * @param [in, out] idxp Index to write next hint into. + * return Number of hints on success. + * return Falsam of -1 when too many hints. + */ +static int dilithium_make_hint_32(const sword32* s, const sword32* w1, + byte omega, byte* h, byte *idxp) +{ + unsigned int j; + byte idx = *idxp; + + (void)omega; + + /* Alg 14, Step 3: For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + /* Alg 14, Step 4: Check whether hint is required. + * Did sum end up greater than low modulus or + * sum end up less than the negative of low modulus or + * sum is the negative of the low modulus and w1 is not zero, + * then w1 will be modified. + */ + if ((s[j] > (sword32)DILITHIUM_Q_LOW_32) || + (s[j] < -(sword32)DILITHIUM_Q_LOW_32) || + ((s[j] == -(sword32)DILITHIUM_Q_LOW_32) && + (w1[j] != 0))) { + /* Alg 14, Step 6, 7: Put index as hint modifier. */ + h[idx++] = (byte)j; + /* Alg 2, Step 27: If there are too many hints, return + * falsam of -1. */ + if (idx > omega) { + return -1; + } + } + } + + *idxp = idx; + return 0; +} +#endif + +#ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM +/* Compute hints indicating whether adding ct0 to w alters high bits of w. + * + * FIPS 204. 6: Algorithm 2 ML-DSA.Sign(sk, M) + * ... + * 26: h <- MakeHint(-<>, w - <> + <>) + * 27: if ... or the number of 1's in h is greater than OMEGA, then + * (z, h) <- falsam + * ... + * 32: sigma <- sigEncode(c_tilda, z mod+/- q, h) + * ... + * + * FIPS 204. 8.4: Algorithm 33 MakeHint(z, r) + * 1: r1 <- HighBits(r) + * 2: v1 <- HightBits(r+z) + * 3: return [[r1 != v1]] + * + * FIPS 204. 8.2: Algorithm 20 sigEncode(c_tilde, z, h) + * ... + * 5: sigma <- sigma || HintBitPack(h) + * ... + * + * FIPS 204. 8.1: Algorithm 14 HintBitPack(h) + * ... + * 2: Index <- 0 + * 3. for i from 0 to k - 1 do + * 4: for j from 0 to 255 do + * 5: if h[i]j != 0 then + * 6: y[Index] <- j + * 7: Index <- Index + 1 + * 8: end if + * 9: end for + * 10: y[OMEGA + i] <- Index + * 11: end for + * 12: return y + * + * @param [in] s Vector of polynomials that is sum of ct0 and w0. + * @param [in] w1 Vector of polynomials that is high part of w. + * @param [in] k Dimension of vectors. + * @param [in] gamma2 Low-order rounding range, GAMMA2. + * @param [in] omega Maximum number of hints allowed. + * @param [out] h Encoded hints. + * return Number of hints on success. + * return Falsam of -1 when too many hints. + */ +static int dilithium_make_hint(const sword32* s, const sword32* w1, byte k, + word32 gamma2, byte omega, byte* h) +{ + unsigned int i; + byte idx = 0; + + (void)k; + (void)omega; + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (gamma2 == DILITHIUM_Q_LOW_88) { + /* Alg 14, Step 2: For each polynomial of vector. */ + for (i = 0; i < PARAMS_ML_DSA_44_K; i++) { + if (dilithium_make_hint_88(s, w1, h, &idx) == -1) { + return -1; + } + /* Alg 14, Step 10: Store count of hints for polynomial at end of + * list. */ + h[PARAMS_ML_DSA_44_OMEGA + i] = idx; + /* Next polynomial. */ + s += DILITHIUM_N; + w1 += DILITHIUM_N; + } + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (gamma2 == DILITHIUM_Q_LOW_32) { + /* Alg 14, Step 2: For each polynomial of vector. */ + for (i = 0; i < k; i++) { + if (dilithium_make_hint_32(s, w1, omega, h, &idx) == -1) { + return -1; + } + /* Alg 14, Step 10: Store count of hints for polynomial at end of + * list. */ + h[omega + i] = idx; + /* Next polynomial. */ + s += DILITHIUM_N; + w1 += DILITHIUM_N; + } + } + else +#endif + { + } + + /* Set remaining hints to zero. */ + XMEMSET(h + idx, 0, omega - idx); + return idx; +} +#endif /* !WOLFSSL_DILITHIUM_SIGN_SMALL_MEM */ + +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY +/* Check that the hints are valid. + * + * @param [in] h Hints to check + * @param [in] k Dimension of vector. + * @param [in] omega Maximum number of hints. Hint counts after this index. + * @return 0 when hints valid. + * @return SIG_VERIFY_E when hints invalid. + */ +static int dilithium_check_hint(const byte* h, byte k, byte omega) +{ + int ret = 0; + unsigned int o = 0; + unsigned int i; + + /* Skip polynomial index while count is 0. */ + while ((h[omega + o] == 0) && (o < k)) { + o++; + } + /* Check all possible hints. */ + for (i = 1; i < omega; i++) { + /* Done with polynomial if index equals count of hints. */ + if (i == h[omega + o]) { + /* Next polynomial index while count is index. */ + do { + o++; + } + while ((o < k) && (i == h[omega + o])); + /* Stop if hints for all polynomials checked. */ + if (o == k) { + break; + } + } + /* Ensure the last hint is less than the current hint. */ + else if (h[i - 1] > h[i]) { + ret = SIG_VERIFY_E; + break; + } + } + if (ret == 0) { + /* Use up any sizes that are the last element. */ + while ((o < k) && (i == h[omega + o])) { + o++; + } + /* Ensure all sizes were used. */ + if (o != k) { + ret = SIG_VERIFY_E; + } + } + /* Check remaining hints are 0. */ + for (; (ret == 0) && (i < omega); i++) { + if (h[i] != 0) { + ret = SIG_VERIFY_E; + } + } + + return ret; +} + +#ifndef WOLFSSL_NO_ML_DSA_44 +/* Use hints to modify w1. + * + * FIPS 204. 8.4: Algorithm 34 UseHint(h, r) + * 1: m <- (q - 1) / (2 * GAMMA2) + * 2: (r1, r0) <- Decompose(r) + * 3: if h == 1 and r0 > 0 return (r1 + 1) mod m + * 4: if h == 1 and r0 <= 0 return (r1 - 1) mod m + * 5: return r1 + * + * @param [in, out] w1 Vector of polynomials needing hints applied to. + * @param [in] h Hints to apply. In signature encoding. + * @param [in] i Dimension index. + * @param [in, out] op Pointer to current offset into hints. + */ +static void dilithium_use_hint_88(sword32* w1, const byte* h, unsigned int i, + byte* op) +{ + byte o = *op; + unsigned int j; + + /* For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + sword32 r; + sword32 r0; + sword32 r1; +#ifdef DILITHIUM_USE_HINT_CT + /* Hint is 1 when index is next in hint list. */ + sword32 hint = ((o < h[PARAMS_ML_DSA_44_OMEGA + i]) & + (h[o] == (byte)j)); + + /* Increment hint offset if this index has hint. */ + o += hint; + /* Convert value to positive only range. */ + r = w1[j] + ((0 - (((word32)w1[j]) >> 31)) & DILITHIUM_Q); + /* Decompose value into low and high parts. */ + dilithium_decompose_q88(r, &r0, &r1); + /* Make hint positive or negative based on sign of r0. */ + hint = (1 - (2 * (((word32)r0) >> 31))) & (0 - hint); + /* Make w1 only the top part plus the hint. */ + w1[j] = r1 + hint; + + /* Fix up w1 to not be 44 but 0. */ + w1[j] &= 0 - (((word32)(w1[j] - 44)) >> 31); + /* Hint may have reduced 0 to -1 which is actually 43. */ + w1[j] += (0 - (((word32)w1[j]) >> 31)) & 44; +#else + /* Convert value to positive only range. */ + r = w1[j] + ((0 - (((word32)w1[j]) >> 31)) & DILITHIUM_Q); + /* Decompose value into low and high parts. */ + dilithium_decompose_q88(r, &r0, &r1); + /* Check for hint. */ + if ((o < h[PARAMS_ML_DSA_44_OMEGA + i]) && (h[o] == (byte)j)) { + /* Add or subtrac hint based on sign of r0. */ + r1 += 1 - (2 * (((word32)r0) >> 31)); + /* Go to next hint offset. */ + o++; + } + /* Fix up w1 to not be 44 but 0. */ + r1 &= 0 - (((word32)(r1 - 44)) >> 31); + /* Hint may have reduced 0 to -1 which is actually 43. */ + r1 += (0 - (((word32)r1) >> 31)) & 44; + /* Make w1 only the top part plus any hint. */ + w1[j] = r1; +#endif + } + *op = o; +} +#endif /* !WOLFSSL_NO_ML_DSA_44 */ + +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) +/* Use hints to modify w1. + * + * FIPS 204. 8.4: Algorithm 34 UseHint(h, r) + * 1: m <- (q - 1) / (2 * GAMMA2) + * 2: (r1, r0) <- Decompose(r) + * 3: if h == 1 and r0 > 0 return (r1 + 1) mod m + * 4: if h == 1 and r0 <= 0 return (r1 - 1) mod m + * 5: return r1 + * + * @param [in, out] w1 Vector of polynomials needing hints applied to. + * @param [in] h Hints to apply. In signature encoding. + * @param [in] omega Max number of hints. Hint counts after this index. + * @param [in] i Dimension index. + * @param [in, out] op Pointer to current offset into hints. + */ +static void dilithium_use_hint_32(sword32* w1, const byte* h, byte omega, + unsigned int i, byte* op) +{ + byte o = *op; + unsigned int j; + + /* For each value of polynomial. */ + for (j = 0; j < DILITHIUM_N; j++) { + sword32 r; + sword32 r0; + sword32 r1; +#ifdef DILITHIUM_USE_HINT_CT + /* Hint is 1 when index is next in hint list. */ + sword32 hint = ((o < h[omega + i]) & (h[o] == (byte)j)); + + /* Increment hint offset if this index has hint. */ + o += hint; + /* Convert value to positive only range. */ + r = w1[j] + ((0 - (((word32)w1[j]) >> 31)) & DILITHIUM_Q); + /* Decompose value into low and high parts. */ + dilithium_decompose_q32(r, &r0, &r1); + /* Make hint positive or negative based on sign of r0. */ + hint = (1 - (2 * (((word32)r0) >> 31))) & (0 - hint); + /* Make w1 only the top part plus the hint. */ + w1[j] = r1 + hint; + + /* Fix up w1 not be 16 (-> 0) or -1 (-> 15). */ + w1[j] &= 0xf; +#else + /* Convert value to positive only range. */ + r = w1[j] + ((0 - (((word32)w1[j]) >> 31)) & DILITHIUM_Q); + /* Decompose value into low and high parts. */ + dilithium_decompose_q32(r, &r0, &r1); + /* Check for hint. */ + if ((o < h[omega + i]) && (h[o] == (byte)j)) { + /* Add or subtract hint based on sign of r0. */ + r1 += 1 - (2 * (((word32)r0) >> 31)); + /* Go to next hint offset. */ + o++; + } + /* Fix up w1 not be 16 (-> 0) or -1 (-> 15). */ + w1[j] = r1 & 0xf; +#endif + } + *op = o; +} +#endif + +#ifndef WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM +/* Use hints to modify w1. + * + * FIPS 204. 8.4: Algorithm 34 UseHint(h, r) + * 1: m <- (q - 1) / (2 * GAMMA2) + * 2: (r1, r0) <- Decompose(r) + * 3: if h == 1 and r0 > 0 return (r1 + 1) mod m + * 4: if h == 1 and r0 <= 0 return (r1 - 1) mod m + * 5: return r1 + * + * @param [in, out] w1 Vector of polynomials needing hints applied to. + * @param [in] k Dimension of vector. + * @param [in] gamma2 Low-order rounding range, GAMMA2. + * @param [in] omega Max number of hints. Hint counts after this index. + * @param [in] h Hints to apply. In signature encoding. + */ +static void dilithium_vec_use_hint(sword32* w1, byte k, word32 gamma2, + byte omega, const byte* h) +{ + unsigned int i; + byte o = 0; + + (void)k; + (void)omega; + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (gamma2 == DILITHIUM_Q_LOW_88) { + /* For each polynomial of vector. */ + for (i = 0; i < PARAMS_ML_DSA_44_K; i++) { + dilithium_use_hint_88(w1, h, i, &o); + w1 += DILITHIUM_N; + } + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (gamma2 == DILITHIUM_Q_LOW_32) { + /* For each polynomial of vector. */ + for (i = 0; i < k; i++) { + dilithium_use_hint_32(w1, h, omega, i, &o); + w1 += DILITHIUM_N; + } + } + else +#endif + { + } +} +#endif +#endif /* !WOLFSSL_DILITHIUM_NO_VERIFY */ + +/****************************************************************************** + * Maths operations + ******************************************************************************/ + +/* q^-1 mod 2^32 (inverse of 8380417 mod 2^32 = 58728449 = 0x3802001) */ +#define DILITHIUM_QINV 58728449 + +/* Montgomery reduce a. + * + * @param [in] a 64-bit value to be reduced. + * @return Montgomery reduction result. + */ +static sword32 dilithium_mont_red(sword64 a) +{ +#ifndef DILITHIUM_MUL_QINV_SLOW + sword64 t = (sword32)((sword32)a * (sword32)DILITHIUM_QINV); +#else + sword64 t = (sword32)((sword32)a + (sword32)((sword32)a << 13) - + (sword32)((sword32)a << 23) + (sword32)((sword32)a << 26)); +#endif +#ifndef DILITHIUM_MUL_Q_SLOW + return (sword32)((a - ((sword32)t * (sword64)DILITHIUM_Q)) >> 32); +#else + return (sword32)((a - (t << 23) + (t << 13) - t) >> 32); +#endif +} + +#if !defined(WOLFSSL_DILITHIUM_SMALL) || !defined(WOLFSSL_DILITHIUM_NO_SIGN) + +/* Reduce 32-bit a modulo q. r = a mod q. + * + * @param [in] a 32-bit value to be reduced to range of q. + * @return Modulo result. + */ +static sword32 dilithium_red(sword32 a) +{ + sword32 t = (sword32)((a + (1 << 22)) >> 23); +#ifndef DILITHIUM_MUL_Q_SLOW + return (sword32)(a - (t * DILITHIUM_Q)); +#else + return (sword32)(a - (t << 23) + (t << 13) - t); +#endif +} + +#endif /* !WOLFSSL_DILITHIUM_SMALL || !WOLFSSL_DILITHIUM_NO_SIGN */ + +/* Zetas for NTT. */ +static const sword32 zetas[DILITHIUM_N] = { + -41978, 25847, -2608894, -518909, 237124, -777960, -876248, 466468, + 1826347, 2353451, -359251, -2091905, 3119733, -2884855, 3111497, 2680103, + 2725464, 1024112, -1079900, 3585928, -549488, -1119584, 2619752, -2108549, + -2118186, -3859737, -1399561, -3277672, 1757237, -19422, 4010497, 280005, + 2706023, 95776, 3077325, 3530437, -1661693, -3592148, -2537516, 3915439, + -3861115, -3043716, 3574422, -2867647, 3539968, -300467, 2348700, -539299, + -1699267, -1643818, 3505694, -3821735, 3507263, -2140649, -1600420, 3699596, + 811944, 531354, 954230, 3881043, 3900724, -2556880, 2071892, -2797779, + -3930395, -1528703, -3677745, -3041255, -1452451, 3475950, 2176455, -1585221, + -1257611, 1939314, -4083598, -1000202, -3190144, -3157330, -3632928, 126922, + 3412210, -983419, 2147896, 2715295, -2967645, -3693493, -411027, -2477047, + -671102, -1228525, -22981, -1308169, -381987, 1349076, 1852771, -1430430, + -3343383, 264944, 508951, 3097992, 44288, -1100098, 904516, 3958618, + -3724342, -8578, 1653064, -3249728, 2389356, -210977, 759969, -1316856, + 189548, -3553272, 3159746, -1851402, -2409325, -177440, 1315589, 1341330, + 1285669, -1584928, -812732, -1439742, -3019102, -3881060, -3628969, 3839961, + 2091667, 3407706, 2316500, 3817976, -3342478, 2244091, -2446433, -3562462, + 266997, 2434439, -1235728, 3513181, -3520352, -3759364, -1197226, -3193378, + 900702, 1859098, 909542, 819034, 495491, -1613174, -43260, -522500, + -655327, -3122442, 2031748, 3207046, -3556995, -525098, -768622, -3595838, + 342297, 286988, -2437823, 4108315, 3437287, -3342277, 1735879, 203044, + 2842341, 2691481, -2590150, 1265009, 4055324, 1247620, 2486353, 1595974, + -3767016, 1250494, 2635921, -3548272, -2994039, 1869119, 1903435, -1050970, + -1333058, 1237275, -3318210, -1430225, -451100, 1312455, 3306115, -1962642, + -1279661, 1917081, -2546312, -1374803, 1500165, 777191, 2235880, 3406031, + -542412, -2831860, -1671176, -1846953, -2584293, -3724270, 594136, -3776993, + -2013608, 2432395, 2454455, -164721, 1957272, 3369112, 185531, -1207385, + -3183426, 162844, 1616392, 3014001, 810149, 1652634, -3694233, -1799107, + -3038916, 3523897, 3866901, 269760, 2213111, -975884, 1717735, 472078, + -426683, 1723600, -1803090, 1910376, -1667432, -1104333, -260646, -3833893, + -2939036, -2235985, -420899, -2286327, 183443, -976891, 1612842, -3545687, + -554416, 3919660, -48306, -1362209, 3937738, 1400424, -846154, 1976782 +}; + +#ifndef WOLFSSL_DILITHIUM_SMALL +/* Zetas for inverse NTT. */ +static const sword32 zetas_inv[DILITHIUM_N] = { + -1976782, 846154, -1400424, -3937738, 1362209, 48306, -3919660, 554416, + 3545687, -1612842, 976891, -183443, 2286327, 420899, 2235985, 2939036, + 3833893, 260646, 1104333, 1667432, -1910376, 1803090, -1723600, 426683, + -472078, -1717735, 975884, -2213111, -269760, -3866901, -3523897, 3038916, + 1799107, 3694233, -1652634, -810149, -3014001, -1616392, -162844, 3183426, + 1207385, -185531, -3369112, -1957272, 164721, -2454455, -2432395, 2013608, + 3776993, -594136, 3724270, 2584293, 1846953, 1671176, 2831860, 542412, + -3406031, -2235880, -777191, -1500165, 1374803, 2546312, -1917081, 1279661, + 1962642, -3306115, -1312455, 451100, 1430225, 3318210, -1237275, 1333058, + 1050970, -1903435, -1869119, 2994039, 3548272, -2635921, -1250494, 3767016, + -1595974, -2486353, -1247620, -4055324, -1265009, 2590150, -2691481, -2842341, + -203044, -1735879, 3342277, -3437287, -4108315, 2437823, -286988, -342297, + 3595838, 768622, 525098, 3556995, -3207046, -2031748, 3122442, 655327, + 522500, 43260, 1613174, -495491, -819034, -909542, -1859098, -900702, + 3193378, 1197226, 3759364, 3520352, -3513181, 1235728, -2434439, -266997, + 3562462, 2446433, -2244091, 3342478, -3817976, -2316500, -3407706, -2091667, + -3839961, 3628969, 3881060, 3019102, 1439742, 812732, 1584928, -1285669, + -1341330, -1315589, 177440, 2409325, 1851402, -3159746, 3553272, -189548, + 1316856, -759969, 210977, -2389356, 3249728, -1653064, 8578, 3724342, + -3958618, -904516, 1100098, -44288, -3097992, -508951, -264944, 3343383, + 1430430, -1852771, -1349076, 381987, 1308169, 22981, 1228525, 671102, + 2477047, 411027, 3693493, 2967645, -2715295, -2147896, 983419, -3412210, + -126922, 3632928, 3157330, 3190144, 1000202, 4083598, -1939314, 1257611, + 1585221, -2176455, -3475950, 1452451, 3041255, 3677745, 1528703, 3930395, + 2797779, -2071892, 2556880, -3900724, -3881043, -954230, -531354, -811944, + -3699596, 1600420, 2140649, -3507263, 3821735, -3505694, 1643818, 1699267, + 539299, -2348700, 300467, -3539968, 2867647, -3574422, 3043716, 3861115, + -3915439, 2537516, 3592148, 1661693, -3530437, -3077325, -95776, -2706023, + -280005, -4010497, 19422, -1757237, 3277672, 1399561, 3859737, 2118186, + 2108549, -2619752, 1119584, 549488, -3585928, 1079900, -1024112, -2725464, + -2680103, -3111497, 2884855, -3119733, 2091905, 359251, -2353451, -1826347, + -466468, 876248, 777960, -237124, 518909, 2608894, -25847, 41978 +}; +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_MAKE) && defined(WOLFSSL_DILITHIUM_SMALL)) + +/* One iteration of Number-Theoretic Transform. + * + * @param [in] len Length of sequence. + */ +#define NTT(len) \ +do { \ + for (start = 0; start < DILITHIUM_N; start += 2 * (len)) { \ + zeta = zetas[++k]; \ + for (j = 0; j < (len); ++j) { \ + sword32 t = \ + dilithium_mont_red((sword64)zeta * r[start + j + (len)]); \ + sword32 rj = r[start + j]; \ + r[start + j + (len)] = rj - t; \ + r[start + j] = rj + t; \ + } \ + } \ +} \ +while (0) + +/* Number-Theoretic Transform. + * + * @param [in, out] r Polynomial to transform. + */ +static void dilithium_ntt(sword32* r) +{ +#ifdef WOLFSSL_DILITHIUM_SMALL + unsigned int len; + unsigned int k; + unsigned int j; + + k = 0; + for (len = DILITHIUM_N / 2; len >= 1; len >>= 1) { + unsigned int start; + for (start = 0; start < DILITHIUM_N; start = j + len) { + sword32 zeta = zetas[++k]; + for (j = start; j < start + len; ++j) { + sword32 t = dilithium_mont_red((sword64)zeta * r[j + len]); + sword32 rj = r[j]; + r[j + len] = rj - t; + r[j] = rj + t; + } + } + } +#elif defined(WOLFSSL_DILITHIUM_NO_LARGE_CODE) + unsigned int j; + unsigned int k; + unsigned int start; + sword32 zeta; + + zeta = zetas[1]; + for (j = 0; j < DILITHIUM_N / 2; j++) { + sword32 t = + dilithium_mont_red((sword64)zeta * r[j + DILITHIUM_N / 2]); + sword32 rj = r[j]; + r[j + DILITHIUM_N / 2] = rj - t; + r[j] = rj + t; + } + + k = 1; + NTT(64); + NTT(32); + NTT(16); + NTT(8); + NTT(4); + NTT(2); + + for (j = 0; j < DILITHIUM_N; j += 2) { + sword32 t = dilithium_mont_red((sword64)zetas[++k] * r[j + 1]); + sword32 rj = r[j]; + r[j + 1] = rj - t; + r[j] = rj + t; + } +#elif defined(WC_32BIT_CPU) + unsigned int j; + unsigned int k; + sword32 t0; + sword32 t2; + + sword32 zeta128 = zetas[1]; + sword32 zeta640 = zetas[2]; + sword32 zeta641 = zetas[3]; + for (j = 0; j < DILITHIUM_N / 4; j++) { + sword32 r0 = r[j + 0]; + sword32 r2 = r[j + 64]; + sword32 r4 = r[j + 128]; + sword32 r6 = r[j + 192]; + + t0 = dilithium_mont_red((sword64)zeta128 * r4); + t2 = dilithium_mont_red((sword64)zeta128 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zeta640 * r2); + t2 = dilithium_mont_red((sword64)zeta641 * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + 0] = r0; + r[j + 64] = r2; + r[j + 128] = r4; + r[j + 192] = r6; + } + + for (j = 0; j < DILITHIUM_N; j += 64) { + int i; + sword32 zeta32 = zetas[ 4 + j / 64 + 0]; + sword32 zeta160 = zetas[ 8 + j / 32 + 0]; + sword32 zeta161 = zetas[ 8 + j / 32 + 1]; + for (i = 0; i < 16; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r2 = r[j + i + 16]; + sword32 r4 = r[j + i + 32]; + sword32 r6 = r[j + i + 48]; + + t0 = dilithium_mont_red((sword64)zeta32 * r4); + t2 = dilithium_mont_red((sword64)zeta32 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zeta160 * r2); + t2 = dilithium_mont_red((sword64)zeta161 * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + i + 0] = r0; + r[j + i + 16] = r2; + r[j + i + 32] = r4; + r[j + i + 48] = r6; + } + } + + for (j = 0; j < DILITHIUM_N; j += 16) { + int i; + sword32 zeta8 = zetas[16 + j / 16]; + sword32 zeta40 = zetas[32 + j / 8 + 0]; + sword32 zeta41 = zetas[32 + j / 8 + 1]; + for (i = 0; i < 4; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r2 = r[j + i + 4]; + sword32 r4 = r[j + i + 8]; + sword32 r6 = r[j + i + 12]; + + t0 = dilithium_mont_red((sword64)zeta8 * r4); + t2 = dilithium_mont_red((sword64)zeta8 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zeta40 * r2); + t2 = dilithium_mont_red((sword64)zeta41 * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + i + 0] = r0; + r[j + i + 4] = r2; + r[j + i + 8] = r4; + r[j + i + 12] = r6; + } + } + + k = 128; + for (j = 0; j < DILITHIUM_N; j += 4) { + sword32 zeta2 = zetas[64 + j / 4]; + sword32 r0 = r[j + 0]; + sword32 r2 = r[j + 1]; + sword32 r4 = r[j + 2]; + sword32 r6 = r[j + 3]; + + t0 = dilithium_mont_red((sword64)zeta2 * r4); + t2 = dilithium_mont_red((sword64)zeta2 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zetas[k++] * r2); + t2 = dilithium_mont_red((sword64)zetas[k++] * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + 0] = r0; + r[j + 1] = r2; + r[j + 2] = r4; + r[j + 3] = r6; + } +#else + unsigned int j; + unsigned int k; + sword32 t0; + sword32 t1; + sword32 t2; + sword32 t3; + + sword32 zeta128 = zetas[1]; + sword32 zeta640 = zetas[2]; + sword32 zeta641 = zetas[3]; + for (j = 0; j < DILITHIUM_N / 8; j++) { + sword32 r0 = r[j + 0]; + sword32 r1 = r[j + 32]; + sword32 r2 = r[j + 64]; + sword32 r3 = r[j + 96]; + sword32 r4 = r[j + 128]; + sword32 r5 = r[j + 160]; + sword32 r6 = r[j + 192]; + sword32 r7 = r[j + 224]; + + t0 = dilithium_mont_red((sword64)zeta128 * r4); + t1 = dilithium_mont_red((sword64)zeta128 * r5); + t2 = dilithium_mont_red((sword64)zeta128 * r6); + t3 = dilithium_mont_red((sword64)zeta128 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = dilithium_mont_red((sword64)zeta640 * r2); + t1 = dilithium_mont_red((sword64)zeta640 * r3); + t2 = dilithium_mont_red((sword64)zeta641 * r6); + t3 = dilithium_mont_red((sword64)zeta641 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + r[j + 0] = r0; + r[j + 32] = r1; + r[j + 64] = r2; + r[j + 96] = r3; + r[j + 128] = r4; + r[j + 160] = r5; + r[j + 192] = r6; + r[j + 224] = r7; + } + + for (j = 0; j < DILITHIUM_N; j += 64) { + int i; + sword32 zeta32 = zetas[ 4 + j / 64 + 0]; + sword32 zeta160 = zetas[ 8 + j / 32 + 0]; + sword32 zeta161 = zetas[ 8 + j / 32 + 1]; + sword32 zeta80 = zetas[16 + j / 16 + 0]; + sword32 zeta81 = zetas[16 + j / 16 + 1]; + sword32 zeta82 = zetas[16 + j / 16 + 2]; + sword32 zeta83 = zetas[16 + j / 16 + 3]; + for (i = 0; i < 8; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r1 = r[j + i + 8]; + sword32 r2 = r[j + i + 16]; + sword32 r3 = r[j + i + 24]; + sword32 r4 = r[j + i + 32]; + sword32 r5 = r[j + i + 40]; + sword32 r6 = r[j + i + 48]; + sword32 r7 = r[j + i + 56]; + + t0 = dilithium_mont_red((sword64)zeta32 * r4); + t1 = dilithium_mont_red((sword64)zeta32 * r5); + t2 = dilithium_mont_red((sword64)zeta32 * r6); + t3 = dilithium_mont_red((sword64)zeta32 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = dilithium_mont_red((sword64)zeta160 * r2); + t1 = dilithium_mont_red((sword64)zeta160 * r3); + t2 = dilithium_mont_red((sword64)zeta161 * r6); + t3 = dilithium_mont_red((sword64)zeta161 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + t0 = dilithium_mont_red((sword64)zeta80 * r1); + t1 = dilithium_mont_red((sword64)zeta81 * r3); + t2 = dilithium_mont_red((sword64)zeta82 * r5); + t3 = dilithium_mont_red((sword64)zeta83 * r7); + r1 = r0 - t0; + r3 = r2 - t1; + r5 = r4 - t2; + r7 = r6 - t3; + r0 += t0; + r2 += t1; + r4 += t2; + r6 += t3; + + r[j + i + 0] = r0; + r[j + i + 8] = r1; + r[j + i + 16] = r2; + r[j + i + 24] = r3; + r[j + i + 32] = r4; + r[j + i + 40] = r5; + r[j + i + 48] = r6; + r[j + i + 56] = r7; + } + } + + k = 128; + for (j = 0; j < DILITHIUM_N; j += 8) { + sword32 zeta4 = zetas[32 + j / 8 + 0]; + sword32 zeta20 = zetas[64 + j / 4 + 0]; + sword32 zeta21 = zetas[64 + j / 4 + 1]; + sword32 r0 = r[j + 0]; + sword32 r1 = r[j + 1]; + sword32 r2 = r[j + 2]; + sword32 r3 = r[j + 3]; + sword32 r4 = r[j + 4]; + sword32 r5 = r[j + 5]; + sword32 r6 = r[j + 6]; + sword32 r7 = r[j + 7]; + + t0 = dilithium_mont_red((sword64)zeta4 * r4); + t1 = dilithium_mont_red((sword64)zeta4 * r5); + t2 = dilithium_mont_red((sword64)zeta4 * r6); + t3 = dilithium_mont_red((sword64)zeta4 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = dilithium_mont_red((sword64)zeta20 * r2); + t1 = dilithium_mont_red((sword64)zeta20 * r3); + t2 = dilithium_mont_red((sword64)zeta21 * r6); + t3 = dilithium_mont_red((sword64)zeta21 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + t0 = dilithium_mont_red((sword64)zetas[k++] * r1); + t1 = dilithium_mont_red((sword64)zetas[k++] * r3); + t2 = dilithium_mont_red((sword64)zetas[k++] * r5); + t3 = dilithium_mont_red((sword64)zetas[k++] * r7); + r1 = r0 - t0; + r3 = r2 - t1; + r5 = r4 - t2; + r7 = r6 - t3; + r0 += t0; + r2 += t1; + r4 += t2; + r6 += t3; + + r[j + 0] = r0; + r[j + 1] = r1; + r[j + 2] = r2; + r[j + 3] = r3; + r[j + 4] = r4; + r[j + 5] = r5; + r[j + 6] = r6; + r[j + 7] = r7; + } +#endif +} + +#if !defined(WOLFSSL_DILITHIUM_NO_VERIFY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + (defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) || \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM))) +/* Number-Theoretic Transform. + * + * @param [in, out] r Vector of polynomials to transform. + * @param [in] l Dimension of polynomial. + */ +static void dilithium_vec_ntt(sword32* r, byte l) +{ + unsigned int i; + + for (i = 0; i < l; i++) { + dilithium_ntt(r); + r += DILITHIUM_N; + } +} +#endif +#endif + +#ifndef WOLFSSL_DILITHIUM_SMALL + +/* Number-Theoretic Transform with small initial values. + * + * @param [in, out] r Polynomial to transform. + */ +static void dilithium_ntt_small(sword32* r) +{ + unsigned int k; + unsigned int j; +#ifdef WOLFSSL_DILITHIUM_NO_LARGE_CODE + unsigned int start; + sword32 zeta; + + for (j = 0; j < DILITHIUM_N / 2; ++j) { + sword32 t = dilithium_red((sword32)-3572223 * r[j + DILITHIUM_N / 2]); + sword32 rj = r[j]; + r[j + DILITHIUM_N / 2] = rj - t; + r[j] = rj + t; + } + + k = 1; + NTT(64); + NTT(32); + NTT(16); + NTT(8); + NTT(4); + NTT(2); + + for (j = 0; j < DILITHIUM_N; j += 2) { + sword32 t = dilithium_mont_red((sword64)zetas[++k] * r[j + 1]); + sword32 rj = r[j]; + r[j + 1] = rj - t; + r[j] = rj + t; + } +#elif defined(WC_32BIT_CPU) + sword32 t0; + sword32 t2; + + sword32 zeta640 = zetas[2]; + sword32 zeta641 = zetas[3]; + for (j = 0; j < DILITHIUM_N / 4; j++) { + sword32 r0 = r[j + 0]; + sword32 r2 = r[j + 64]; + sword32 r4 = r[j + 128]; + sword32 r6 = r[j + 192]; + + t0 = dilithium_red((sword32)-3572223 * r4); + t2 = dilithium_red((sword32)-3572223 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zeta640 * r2); + t2 = dilithium_mont_red((sword64)zeta641 * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + 0] = r0; + r[j + 64] = r2; + r[j + 128] = r4; + r[j + 192] = r6; + } + + for (j = 0; j < DILITHIUM_N; j += 64) { + int i; + sword32 zeta32 = zetas[ 4 + j / 64 + 0]; + sword32 zeta160 = zetas[ 8 + j / 32 + 0]; + sword32 zeta161 = zetas[ 8 + j / 32 + 1]; + for (i = 0; i < 16; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r2 = r[j + i + 16]; + sword32 r4 = r[j + i + 32]; + sword32 r6 = r[j + i + 48]; + + t0 = dilithium_mont_red((sword64)zeta32 * r4); + t2 = dilithium_mont_red((sword64)zeta32 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zeta160 * r2); + t2 = dilithium_mont_red((sword64)zeta161 * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + i + 0] = r0; + r[j + i + 16] = r2; + r[j + i + 32] = r4; + r[j + i + 48] = r6; + } + } + + for (j = 0; j < DILITHIUM_N; j += 16) { + int i; + sword32 zeta8 = zetas[16 + j / 16]; + sword32 zeta40 = zetas[32 + j / 8 + 0]; + sword32 zeta41 = zetas[32 + j / 8 + 1]; + for (i = 0; i < 4; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r2 = r[j + i + 4]; + sword32 r4 = r[j + i + 8]; + sword32 r6 = r[j + i + 12]; + + t0 = dilithium_mont_red((sword64)zeta8 * r4); + t2 = dilithium_mont_red((sword64)zeta8 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zeta40 * r2); + t2 = dilithium_mont_red((sword64)zeta41 * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + i + 0] = r0; + r[j + i + 4] = r2; + r[j + i + 8] = r4; + r[j + i + 12] = r6; + } + } + + k = 128; + for (j = 0; j < DILITHIUM_N; j += 4) { + sword32 zeta2 = zetas[64 + j / 4]; + sword32 r0 = r[j + 0]; + sword32 r2 = r[j + 1]; + sword32 r4 = r[j + 2]; + sword32 r6 = r[j + 3]; + + t0 = dilithium_mont_red((sword64)zeta2 * r4); + t2 = dilithium_mont_red((sword64)zeta2 * r6); + r4 = r0 - t0; + r6 = r2 - t2; + r0 += t0; + r2 += t2; + + t0 = dilithium_mont_red((sword64)zetas[k++] * r2); + t2 = dilithium_mont_red((sword64)zetas[k++] * r6); + r2 = r0 - t0; + r6 = r4 - t2; + r0 += t0; + r4 += t2; + + r[j + 0] = r0; + r[j + 1] = r2; + r[j + 2] = r4; + r[j + 3] = r6; + } +#else + sword32 t0; + sword32 t1; + sword32 t2; + sword32 t3; + sword32 zeta640 = zetas[2]; + sword32 zeta641 = zetas[3]; + for (j = 0; j < DILITHIUM_N / 8; j++) { + sword32 r0 = r[j + 0]; + sword32 r1 = r[j + 32]; + sword32 r2 = r[j + 64]; + sword32 r3 = r[j + 96]; + sword32 r4 = r[j + 128]; + sword32 r5 = r[j + 160]; + sword32 r6 = r[j + 192]; + sword32 r7 = r[j + 224]; + + t0 = dilithium_red((sword32)-3572223 * r4); + t1 = dilithium_red((sword32)-3572223 * r5); + t2 = dilithium_red((sword32)-3572223 * r6); + t3 = dilithium_red((sword32)-3572223 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = dilithium_mont_red((sword64)zeta640 * r2); + t1 = dilithium_mont_red((sword64)zeta640 * r3); + t2 = dilithium_mont_red((sword64)zeta641 * r6); + t3 = dilithium_mont_red((sword64)zeta641 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + r[j + 0] = r0; + r[j + 32] = r1; + r[j + 64] = r2; + r[j + 96] = r3; + r[j + 128] = r4; + r[j + 160] = r5; + r[j + 192] = r6; + r[j + 224] = r7; + } + + for (j = 0; j < DILITHIUM_N; j += 64) { + int i; + sword32 zeta32 = zetas[ 4 + j / 64 + 0]; + sword32 zeta160 = zetas[ 8 + j / 32 + 0]; + sword32 zeta161 = zetas[ 8 + j / 32 + 1]; + sword32 zeta80 = zetas[16 + j / 16 + 0]; + sword32 zeta81 = zetas[16 + j / 16 + 1]; + sword32 zeta82 = zetas[16 + j / 16 + 2]; + sword32 zeta83 = zetas[16 + j / 16 + 3]; + for (i = 0; i < 8; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r1 = r[j + i + 8]; + sword32 r2 = r[j + i + 16]; + sword32 r3 = r[j + i + 24]; + sword32 r4 = r[j + i + 32]; + sword32 r5 = r[j + i + 40]; + sword32 r6 = r[j + i + 48]; + sword32 r7 = r[j + i + 56]; + + t0 = dilithium_mont_red((sword64)zeta32 * r4); + t1 = dilithium_mont_red((sword64)zeta32 * r5); + t2 = dilithium_mont_red((sword64)zeta32 * r6); + t3 = dilithium_mont_red((sword64)zeta32 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = dilithium_mont_red((sword64)zeta160 * r2); + t1 = dilithium_mont_red((sword64)zeta160 * r3); + t2 = dilithium_mont_red((sword64)zeta161 * r6); + t3 = dilithium_mont_red((sword64)zeta161 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + t0 = dilithium_mont_red((sword64)zeta80 * r1); + t1 = dilithium_mont_red((sword64)zeta81 * r3); + t2 = dilithium_mont_red((sword64)zeta82 * r5); + t3 = dilithium_mont_red((sword64)zeta83 * r7); + r1 = r0 - t0; + r3 = r2 - t1; + r5 = r4 - t2; + r7 = r6 - t3; + r0 += t0; + r2 += t1; + r4 += t2; + r6 += t3; + + r[j + i + 0] = r0; + r[j + i + 8] = r1; + r[j + i + 16] = r2; + r[j + i + 24] = r3; + r[j + i + 32] = r4; + r[j + i + 40] = r5; + r[j + i + 48] = r6; + r[j + i + 56] = r7; + } + } + + k = 128; + for (j = 0; j < DILITHIUM_N; j += 8) { + sword32 zeta4 = zetas[32 + j / 8 + 0]; + sword32 zeta20 = zetas[64 + j / 4 + 0]; + sword32 zeta21 = zetas[64 + j / 4 + 1]; + sword32 r0 = r[j + 0]; + sword32 r1 = r[j + 1]; + sword32 r2 = r[j + 2]; + sword32 r3 = r[j + 3]; + sword32 r4 = r[j + 4]; + sword32 r5 = r[j + 5]; + sword32 r6 = r[j + 6]; + sword32 r7 = r[j + 7]; + + t0 = dilithium_mont_red((sword64)zeta4 * r4); + t1 = dilithium_mont_red((sword64)zeta4 * r5); + t2 = dilithium_mont_red((sword64)zeta4 * r6); + t3 = dilithium_mont_red((sword64)zeta4 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = dilithium_mont_red((sword64)zeta20 * r2); + t1 = dilithium_mont_red((sword64)zeta20 * r3); + t2 = dilithium_mont_red((sword64)zeta21 * r6); + t3 = dilithium_mont_red((sword64)zeta21 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + t0 = dilithium_mont_red((sword64)zetas[k++] * r1); + t1 = dilithium_mont_red((sword64)zetas[k++] * r3); + t2 = dilithium_mont_red((sword64)zetas[k++] * r5); + t3 = dilithium_mont_red((sword64)zetas[k++] * r7); + r1 = r0 - t0; + r3 = r2 - t1; + r5 = r4 - t2; + r7 = r6 - t3; + r0 += t0; + r2 += t1; + r4 += t2; + r6 += t3; + + r[j + 0] = r0; + r[j + 1] = r1; + r[j + 2] = r2; + r[j + 3] = r3; + r[j + 4] = r4; + r[j + 5] = r5; + r[j + 6] = r6; + r[j + 7] = r7; + } +#endif +} + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + (defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) || \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM))) +/* Number-Theoretic Transform with small initial values. + * + * @param [in, out] r Vector of polynomials to transform. + * @param [in] l Dimension of polynomial. + */ +static void dilithium_vec_ntt_small(sword32* r, byte l) +{ + unsigned int i; + + for (i = 0; i < l; i++) { + dilithium_ntt_small(r); + r += DILITHIUM_N; + } +} +#endif /* !WOLFSSL_DILITHIUM_VERIFY_ONLY */ + +#else + +/* Number-Theoretic Transform with small initial values. + * + * @param [in, out] r Polynomial to transform. + */ +#define dilithium_ntt_small dilithium_ntt +/* Number-Theoretic Transform with small initial values. + * + * @param [in, out] r Vector of polynomials to transform. + * @param [in] l Dimension of polynomial. + */ +#define dilithium_vec_ntt_small dilithium_vec_ntt + +#endif /* WOLFSSL_DILITHIUM_SMALL */ + + +/* One iteration of Inverse Number-Theoretic Transform. + * + * @param [in] len Length of sequence. + */ +#define INVNTT(len) \ +do { \ + for (start = 0; start < DILITHIUM_N; start += 2 * (len)) { \ + zeta = zetas_inv[k++]; \ + for (j = 0; j < (len); ++j) { \ + sword32 rj = r[start + j]; \ + sword32 rjl = r[start + j + (len)]; \ + sword32 t = rj + rjl; \ + r[start + j] = t; \ + rjl = rj - rjl; \ + r[start + j + (len)] = dilithium_mont_red((sword64)zeta * rjl); \ + } \ + } \ +} \ +while (0) + +/* Inverse Number-Theoretic Transform. + * + * @param [in, out] r Polynomial to transform. + */ +static void dilithium_invntt(sword32* r) +{ +#ifdef WOLFSSL_DILITHIUM_SMALL + unsigned int len; + unsigned int k; + unsigned int j; + sword32 zeta; + + k = 256; + for (len = 1; len <= DILITHIUM_N / 2; len <<= 1) { + unsigned int start; + for (start = 0; start < DILITHIUM_N; start = j + len) { + zeta = -zetas[--k]; + for (j = start; j < start + len; ++j) { + sword32 rj = r[j]; + sword32 rjl = r[j + len]; + sword32 t = rj + rjl; + r[j] = t; + rjl = rj - rjl; + r[j + len] = dilithium_mont_red((sword64)zeta * rjl); + } + } + } + + zeta = -zetas[0]; + for (j = 0; j < DILITHIUM_N; ++j) { + r[j] = dilithium_mont_red((sword64)zeta * r[j]); + } +#elif defined(WOLFSSL_DILITHIUM_NO_LARGE_CODE) + unsigned int j; + unsigned int k = 0; + unsigned int start; + sword32 zeta; + + for (j = 0; j < DILITHIUM_N; j += 2) { + sword32 rj = r[j]; + sword32 rjl = r[j + 1]; + sword32 t = rj + rjl; + r[j] = t; + rjl = rj - rjl; + r[j + 1] = dilithium_mont_red((sword64)zetas_inv[k++] * rjl); + } + + INVNTT(2); + INVNTT(4); + INVNTT(8); + INVNTT(16); + INVNTT(32); + INVNTT(64); + INVNTT(128); + + zeta = zetas_inv[255]; + for (j = 0; j < DILITHIUM_N; ++j) { + r[j] = dilithium_mont_red((sword64)zeta * r[j]); + } +#elif defined(WC_32BIT_CPU) + unsigned int j; + unsigned int k = 0; + sword32 t0; + sword32 t2; + + sword32 zeta640; + sword32 zeta641; + sword32 zeta128; + sword32 zeta256; + for (j = 0; j < DILITHIUM_N; j += 4) { + sword32 zeta2 = zetas_inv[128 + j / 4]; + sword32 r0 = r[j + 0]; + sword32 r2 = r[j + 1]; + sword32 r4 = r[j + 2]; + sword32 r6 = r[j + 3]; + + t0 = dilithium_mont_red((sword64)zetas_inv[k++] * (r0 - r2)); + t2 = dilithium_mont_red((sword64)zetas_inv[k++] * (r4 - r6)); + r0 += r2; + r4 += r6; + r2 = t0; + r6 = t2; + + t0 = dilithium_mont_red((sword64)zeta2 * (r0 - r4)); + t2 = dilithium_mont_red((sword64)zeta2 * (r2 - r6)); + r0 += r4; + r2 += r6; + r4 = t0; + r6 = t2; + + r[j + 0] = r0; + r[j + 1] = r2; + r[j + 2] = r4; + r[j + 3] = r6; + } + + for (j = 0; j < DILITHIUM_N; j += 16) { + int i; + sword32 zeta40 = zetas_inv[192 + j / 8 + 0]; + sword32 zeta41 = zetas_inv[192 + j / 8 + 1]; + sword32 zeta8 = zetas_inv[224 + j / 16 + 0]; + for (i = 0; i < 4; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r2 = r[j + i + 4]; + sword32 r4 = r[j + i + 8]; + sword32 r6 = r[j + i + 12]; + + t0 = dilithium_mont_red((sword64)zeta40 * (r0 - r2)); + t2 = dilithium_mont_red((sword64)zeta41 * (r4 - r6)); + r0 += r2; + r4 += r6; + r2 = t0; + r6 = t2; + + t0 = dilithium_mont_red((sword64)zeta8 * (r0 - r4)); + t2 = dilithium_mont_red((sword64)zeta8 * (r2 - r6)); + r0 += r4; + r2 += r6; + r4 = t0; + r6 = t2; + + r[j + i + 0] = r0; + r[j + i + 4] = r2; + r[j + i + 8] = r4; + r[j + i + 12] = r6; + } + } + + for (j = 0; j < DILITHIUM_N; j += 64) { + int i; + sword32 zeta160 = zetas_inv[240 + j / 32 + 0]; + sword32 zeta161 = zetas_inv[240 + j / 32 + 1]; + sword32 zeta32 = zetas_inv[248 + j / 64 + 0]; + for (i = 0; i < 16; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r2 = r[j + i + 16]; + sword32 r4 = r[j + i + 32]; + sword32 r6 = r[j + i + 48]; + + t0 = dilithium_mont_red((sword64)zeta160 * (r0 - r2)); + t2 = dilithium_mont_red((sword64)zeta161 * (r4 - r6)); + r0 += r2; + r4 += r6; + r2 = t0; + r6 = t2; + + t0 = dilithium_mont_red((sword64)zeta32 * (r0 - r4)); + t2 = dilithium_mont_red((sword64)zeta32 * (r2 - r6)); + r0 += r4; + r2 += r6; + r4 = t0; + r6 = t2; + + r[j + i + 0] = r0; + r[j + i + 16] = r2; + r[j + i + 32] = r4; + r[j + i + 48] = r6; + } + } + + zeta640 = zetas_inv[252]; + zeta641 = zetas_inv[253]; + zeta128 = zetas_inv[254]; + zeta256 = zetas_inv[255]; + for (j = 0; j < DILITHIUM_N / 4; j++) { + sword32 r0 = r[j + 0]; + sword32 r2 = r[j + 64]; + sword32 r4 = r[j + 128]; + sword32 r6 = r[j + 192]; + + t0 = dilithium_mont_red((sword64)zeta640 * (r0 - r2)); + t2 = dilithium_mont_red((sword64)zeta641 * (r4 - r6)); + r0 += r2; + r4 += r6; + r2 = t0; + r6 = t2; + + t0 = dilithium_mont_red((sword64)zeta128 * (r0 - r4)); + t2 = dilithium_mont_red((sword64)zeta128 * (r2 - r6)); + r0 += r4; + r2 += r6; + r4 = t0; + r6 = t2; + + r0 = dilithium_mont_red((sword64)zeta256 * r0); + r2 = dilithium_mont_red((sword64)zeta256 * r2); + r4 = dilithium_mont_red((sword64)zeta256 * r4); + r6 = dilithium_mont_red((sword64)zeta256 * r6); + + r[j + 0] = r0; + r[j + 64] = r2; + r[j + 128] = r4; + r[j + 192] = r6; + } +#else + unsigned int j; + unsigned int k = 0; + sword32 t0; + sword32 t1; + sword32 t2; + sword32 t3; + + sword32 zeta640; + sword32 zeta641; + sword32 zeta128; + sword32 zeta256; + for (j = 0; j < DILITHIUM_N; j += 8) { + sword32 zeta20 = zetas_inv[128 + j / 4 + 0]; + sword32 zeta21 = zetas_inv[128 + j / 4 + 1]; + sword32 zeta4 = zetas_inv[192 + j / 8 + 0]; + sword32 r0 = r[j + 0]; + sword32 r1 = r[j + 1]; + sword32 r2 = r[j + 2]; + sword32 r3 = r[j + 3]; + sword32 r4 = r[j + 4]; + sword32 r5 = r[j + 5]; + sword32 r6 = r[j + 6]; + sword32 r7 = r[j + 7]; + + t0 = dilithium_mont_red((sword64)zetas_inv[k++] * (r0 - r1)); + t1 = dilithium_mont_red((sword64)zetas_inv[k++] * (r2 - r3)); + t2 = dilithium_mont_red((sword64)zetas_inv[k++] * (r4 - r5)); + t3 = dilithium_mont_red((sword64)zetas_inv[k++] * (r6 - r7)); + r0 += r1; + r2 += r3; + r4 += r5; + r6 += r7; + r1 = t0; + r3 = t1; + r5 = t2; + r7 = t3; + + t0 = dilithium_mont_red((sword64)zeta20 * (r0 - r2)); + t1 = dilithium_mont_red((sword64)zeta20 * (r1 - r3)); + t2 = dilithium_mont_red((sword64)zeta21 * (r4 - r6)); + t3 = dilithium_mont_red((sword64)zeta21 * (r5 - r7)); + r0 += r2; + r1 += r3; + r4 += r6; + r5 += r7; + r2 = t0; + r3 = t1; + r6 = t2; + r7 = t3; + + t0 = dilithium_mont_red((sword64)zeta4 * (r0 - r4)); + t1 = dilithium_mont_red((sword64)zeta4 * (r1 - r5)); + t2 = dilithium_mont_red((sword64)zeta4 * (r2 - r6)); + t3 = dilithium_mont_red((sword64)zeta4 * (r3 - r7)); + r0 += r4; + r1 += r5; + r2 += r6; + r3 += r7; + r4 = t0; + r5 = t1; + r6 = t2; + r7 = t3; + + r[j + 0] = r0; + r[j + 1] = r1; + r[j + 2] = r2; + r[j + 3] = r3; + r[j + 4] = r4; + r[j + 5] = r5; + r[j + 6] = r6; + r[j + 7] = r7; + } + + for (j = 0; j < DILITHIUM_N; j += 64) { + int i; + sword32 zeta80 = zetas_inv[224 + j / 16 + 0]; + sword32 zeta81 = zetas_inv[224 + j / 16 + 1]; + sword32 zeta82 = zetas_inv[224 + j / 16 + 2]; + sword32 zeta83 = zetas_inv[224 + j / 16 + 3]; + sword32 zeta160 = zetas_inv[240 + j / 32 + 0]; + sword32 zeta161 = zetas_inv[240 + j / 32 + 1]; + sword32 zeta32 = zetas_inv[248 + j / 64 + 0]; + for (i = 0; i < 8; i++) { + sword32 r0 = r[j + i + 0]; + sword32 r1 = r[j + i + 8]; + sword32 r2 = r[j + i + 16]; + sword32 r3 = r[j + i + 24]; + sword32 r4 = r[j + i + 32]; + sword32 r5 = r[j + i + 40]; + sword32 r6 = r[j + i + 48]; + sword32 r7 = r[j + i + 56]; + + t0 = dilithium_mont_red((sword64)zeta80 * (r0 - r1)); + t1 = dilithium_mont_red((sword64)zeta81 * (r2 - r3)); + t2 = dilithium_mont_red((sword64)zeta82 * (r4 - r5)); + t3 = dilithium_mont_red((sword64)zeta83 * (r6 - r7)); + r0 += r1; + r2 += r3; + r4 += r5; + r6 += r7; + r1 = t0; + r3 = t1; + r5 = t2; + r7 = t3; + + t0 = dilithium_mont_red((sword64)zeta160 * (r0 - r2)); + t1 = dilithium_mont_red((sword64)zeta160 * (r1 - r3)); + t2 = dilithium_mont_red((sword64)zeta161 * (r4 - r6)); + t3 = dilithium_mont_red((sword64)zeta161 * (r5 - r7)); + r0 += r2; + r1 += r3; + r4 += r6; + r5 += r7; + r2 = t0; + r3 = t1; + r6 = t2; + r7 = t3; + + t0 = dilithium_mont_red((sword64)zeta32 * (r0 - r4)); + t1 = dilithium_mont_red((sword64)zeta32 * (r1 - r5)); + t2 = dilithium_mont_red((sword64)zeta32 * (r2 - r6)); + t3 = dilithium_mont_red((sword64)zeta32 * (r3 - r7)); + r0 += r4; + r1 += r5; + r2 += r6; + r3 += r7; + r4 = t0; + r5 = t1; + r6 = t2; + r7 = t3; + + r[j + i + 0] = r0; + r[j + i + 8] = r1; + r[j + i + 16] = r2; + r[j + i + 24] = r3; + r[j + i + 32] = r4; + r[j + i + 40] = r5; + r[j + i + 48] = r6; + r[j + i + 56] = r7; + } + } + + zeta640 = zetas_inv[252]; + zeta641 = zetas_inv[253]; + zeta128 = zetas_inv[254]; + zeta256 = zetas_inv[255]; + for (j = 0; j < DILITHIUM_N / 8; j++) { + sword32 r0 = r[j + 0]; + sword32 r1 = r[j + 32]; + sword32 r2 = r[j + 64]; + sword32 r3 = r[j + 96]; + sword32 r4 = r[j + 128]; + sword32 r5 = r[j + 160]; + sword32 r6 = r[j + 192]; + sword32 r7 = r[j + 224]; + + t0 = dilithium_mont_red((sword64)zeta640 * (r0 - r2)); + t1 = dilithium_mont_red((sword64)zeta640 * (r1 - r3)); + t2 = dilithium_mont_red((sword64)zeta641 * (r4 - r6)); + t3 = dilithium_mont_red((sword64)zeta641 * (r5 - r7)); + r0 += r2; + r1 += r3; + r4 += r6; + r5 += r7; + r2 = t0; + r3 = t1; + r6 = t2; + r7 = t3; + + t0 = dilithium_mont_red((sword64)zeta128 * (r0 - r4)); + t1 = dilithium_mont_red((sword64)zeta128 * (r1 - r5)); + t2 = dilithium_mont_red((sword64)zeta128 * (r2 - r6)); + t3 = dilithium_mont_red((sword64)zeta128 * (r3 - r7)); + r0 += r4; + r1 += r5; + r2 += r6; + r3 += r7; + r4 = t0; + r5 = t1; + r6 = t2; + r7 = t3; + + r0 = dilithium_mont_red((sword64)zeta256 * r0); + r1 = dilithium_mont_red((sword64)zeta256 * r1); + r2 = dilithium_mont_red((sword64)zeta256 * r2); + r3 = dilithium_mont_red((sword64)zeta256 * r3); + r4 = dilithium_mont_red((sword64)zeta256 * r4); + r5 = dilithium_mont_red((sword64)zeta256 * r5); + r6 = dilithium_mont_red((sword64)zeta256 * r6); + r7 = dilithium_mont_red((sword64)zeta256 * r7); + + r[j + 0] = r0; + r[j + 32] = r1; + r[j + 64] = r2; + r[j + 96] = r3; + r[j + 128] = r4; + r[j + 160] = r5; + r[j + 192] = r6; + r[j + 224] = r7; + } +#endif +} + + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) +/* Inverse Number-Theoretic Transform. + * + * @param [in, out] r Vector of polynomials to transform. + * @param [in] l Dimension of polynomial. + */ +static void dilithium_vec_invntt(sword32* r, byte l) +{ + unsigned int i; + + for (i = 0; i < l; i++) { + dilithium_invntt(r); + r += DILITHIUM_N; + } +} +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) +/* Matrix multiplication. + * + * @param [out] r Vector of polynomials that is result. + * @param [in] m Matrix of polynomials. + * @param [in] v Vector of polynomials. + * @param [in] k First dimension of matrix and dimension of result. + * @param [in] l Second dimension of matrix and dimension of v. + */ +static void dilithium_matrix_mul(sword32* r, const sword32* m, const sword32* v, + byte k, byte l) +{ + byte i; + + for (i = 0; i < k; i++) { + byte j; + unsigned int e; + const sword32* vt = v; + +#ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + r[e] = dilithium_mont_red((sword64)m[e] * vt[e]); + } + m += DILITHIUM_N; + vt += DILITHIUM_N; + for (j = 1; j < l; j++) { + for (e = 0; e < DILITHIUM_N; e++) { + r[e] += dilithium_mont_red((sword64)m[e] * vt[e]); + } + m += DILITHIUM_N; + vt += DILITHIUM_N; + } +#elif defined(WOLFSSL_DILITHIUM_NO_LARGE_CODE) + (void)j; + if (l == 4) { + for (e = 0; e < DILITHIUM_N; e++) { + sword64 t = ((sword64)m[e + 0 * 256] * vt[e + 0 * 256]) + + ((sword64)m[e + 1 * 256] * vt[e + 1 * 256]) + + ((sword64)m[e + 2 * 256] * vt[e + 2 * 256]) + + ((sword64)m[e + 3 * 256] * vt[e + 3 * 256]); + r[e] = dilithium_mont_red(t); + } + m += DILITHIUM_N * 4; + } + else if (l == 5) { + for (e = 0; e < DILITHIUM_N; e++) { + sword64 t = ((sword64)m[e + 0 * 256] * vt[e + 0 * 256]) + + ((sword64)m[e + 1 * 256] * vt[e + 1 * 256]) + + ((sword64)m[e + 2 * 256] * vt[e + 2 * 256]) + + ((sword64)m[e + 3 * 256] * vt[e + 3 * 256]) + + ((sword64)m[e + 4 * 256] * vt[e + 4 * 256]); + r[e] = dilithium_mont_red(t); + } + m += DILITHIUM_N * 5; + } + else if (l == 7) { + for (e = 0; e < DILITHIUM_N; e++) { + sword64 t = ((sword64)m[e + 0 * 256] * vt[e + 0 * 256]) + + ((sword64)m[e + 1 * 256] * vt[e + 1 * 256]) + + ((sword64)m[e + 2 * 256] * vt[e + 2 * 256]) + + ((sword64)m[e + 3 * 256] * vt[e + 3 * 256]) + + ((sword64)m[e + 4 * 256] * vt[e + 4 * 256]) + + ((sword64)m[e + 5 * 256] * vt[e + 5 * 256]) + + ((sword64)m[e + 6 * 256] * vt[e + 6 * 256]); + r[e] = dilithium_mont_red(t); + } + m += DILITHIUM_N * 7; + } +#else + sword64 t0; + sword64 t1; +#if !defined(WOLFSSL_NO_ML_DSA_44) || !defined(WOLFSSL_NO_ML_DSA_65) + sword64 t2; + sword64 t3; +#endif + + (void)j; +#ifndef WOLFSSL_NO_ML_DSA_44 + if (l == 4) { + for (e = 0; e < DILITHIUM_N; e += 4) { + t0 = ((sword64)m[e + 0 + 0 * 256] * vt[e + 0 + 0 * 256]) + + ((sword64)m[e + 0 + 1 * 256] * vt[e + 0 + 1 * 256]) + + ((sword64)m[e + 0 + 2 * 256] * vt[e + 0 + 2 * 256]) + + ((sword64)m[e + 0 + 3 * 256] * vt[e + 0 + 3 * 256]); + t1 = ((sword64)m[e + 1 + 0 * 256] * vt[e + 1 + 0 * 256]) + + ((sword64)m[e + 1 + 1 * 256] * vt[e + 1 + 1 * 256]) + + ((sword64)m[e + 1 + 2 * 256] * vt[e + 1 + 2 * 256]) + + ((sword64)m[e + 1 + 3 * 256] * vt[e + 1 + 3 * 256]); + t2 = ((sword64)m[e + 2 + 0 * 256] * vt[e + 2 + 0 * 256]) + + ((sword64)m[e + 2 + 1 * 256] * vt[e + 2 + 1 * 256]) + + ((sword64)m[e + 2 + 2 * 256] * vt[e + 2 + 2 * 256]) + + ((sword64)m[e + 2 + 3 * 256] * vt[e + 2 + 3 * 256]); + t3 = ((sword64)m[e + 3 + 0 * 256] * vt[e + 3 + 0 * 256]) + + ((sword64)m[e + 3 + 1 * 256] * vt[e + 3 + 1 * 256]) + + ((sword64)m[e + 3 + 2 * 256] * vt[e + 3 + 2 * 256]) + + ((sword64)m[e + 3 + 3 * 256] * vt[e + 3 + 3 * 256]); + r[e + 0] = dilithium_mont_red(t0); + r[e + 1] = dilithium_mont_red(t1); + r[e + 2] = dilithium_mont_red(t2); + r[e + 3] = dilithium_mont_red(t3); + } + m += DILITHIUM_N * 4; + } + else +#endif +#ifndef WOLFSSL_NO_ML_DSA_65 + if (l == 5) { + for (e = 0; e < DILITHIUM_N; e += 4) { + t0 = ((sword64)m[e + 0 + 0 * 256] * vt[e + 0 + 0 * 256]) + + ((sword64)m[e + 0 + 1 * 256] * vt[e + 0 + 1 * 256]) + + ((sword64)m[e + 0 + 2 * 256] * vt[e + 0 + 2 * 256]) + + ((sword64)m[e + 0 + 3 * 256] * vt[e + 0 + 3 * 256]) + + ((sword64)m[e + 0 + 4 * 256] * vt[e + 0 + 4 * 256]); + t1 = ((sword64)m[e + 1 + 0 * 256] * vt[e + 1 + 0 * 256]) + + ((sword64)m[e + 1 + 1 * 256] * vt[e + 1 + 1 * 256]) + + ((sword64)m[e + 1 + 2 * 256] * vt[e + 1 + 2 * 256]) + + ((sword64)m[e + 1 + 3 * 256] * vt[e + 1 + 3 * 256]) + + ((sword64)m[e + 1 + 4 * 256] * vt[e + 1 + 4 * 256]); + t2 = ((sword64)m[e + 2 + 0 * 256] * vt[e + 2 + 0 * 256]) + + ((sword64)m[e + 2 + 1 * 256] * vt[e + 2 + 1 * 256]) + + ((sword64)m[e + 2 + 2 * 256] * vt[e + 2 + 2 * 256]) + + ((sword64)m[e + 2 + 3 * 256] * vt[e + 2 + 3 * 256]) + + ((sword64)m[e + 2 + 4 * 256] * vt[e + 2 + 4 * 256]); + t3 = ((sword64)m[e + 3 + 0 * 256] * vt[e + 3 + 0 * 256]) + + ((sword64)m[e + 3 + 1 * 256] * vt[e + 3 + 1 * 256]) + + ((sword64)m[e + 3 + 2 * 256] * vt[e + 3 + 2 * 256]) + + ((sword64)m[e + 3 + 3 * 256] * vt[e + 3 + 3 * 256]) + + ((sword64)m[e + 3 + 4 * 256] * vt[e + 3 + 4 * 256]); + r[e + 0] = dilithium_mont_red(t0); + r[e + 1] = dilithium_mont_red(t1); + r[e + 2] = dilithium_mont_red(t2); + r[e + 3] = dilithium_mont_red(t3); + } + m += DILITHIUM_N * 5; + } + else +#endif +#ifndef WOLFSSL_NO_ML_DSA_87 + if (l == 7) { + for (e = 0; e < DILITHIUM_N; e += 2) { + t0 = ((sword64)m[e + 0 + 0 * 256] * vt[e + 0 + 0 * 256]) + + ((sword64)m[e + 0 + 1 * 256] * vt[e + 0 + 1 * 256]) + + ((sword64)m[e + 0 + 2 * 256] * vt[e + 0 + 2 * 256]) + + ((sword64)m[e + 0 + 3 * 256] * vt[e + 0 + 3 * 256]) + + ((sword64)m[e + 0 + 4 * 256] * vt[e + 0 + 4 * 256]) + + ((sword64)m[e + 0 + 5 * 256] * vt[e + 0 + 5 * 256]) + + ((sword64)m[e + 0 + 6 * 256] * vt[e + 0 + 6 * 256]); + t1 = ((sword64)m[e + 1 + 0 * 256] * vt[e + 1 + 0 * 256]) + + ((sword64)m[e + 1 + 1 * 256] * vt[e + 1 + 1 * 256]) + + ((sword64)m[e + 1 + 2 * 256] * vt[e + 1 + 2 * 256]) + + ((sword64)m[e + 1 + 3 * 256] * vt[e + 1 + 3 * 256]) + + ((sword64)m[e + 1 + 4 * 256] * vt[e + 1 + 4 * 256]) + + ((sword64)m[e + 1 + 5 * 256] * vt[e + 1 + 5 * 256]) + + ((sword64)m[e + 1 + 6 * 256] * vt[e + 1 + 6 * 256]); + r[e + 0] = dilithium_mont_red(t0); + r[e + 1] = dilithium_mont_red(t1); + } + m += DILITHIUM_N * 7; + } + else +#endif + { + } +#endif + r += DILITHIUM_N; + } +} +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) +/* Polynomial multiplication. + * + * @param [out] r Polynomial result. + * @param [in] a Polynomial + * @param [in] b Polynomial. + */ +static void dilithium_mul(sword32* r, sword32* a, sword32* b) +{ + unsigned int e; +#ifdef WOLFSSL_DILITHIUM_SMALL + for (e = 0; e < DILITHIUM_N; e++) { + r[e] = dilithium_mont_red((sword64)a[e] * b[e]); + } +#elif defined(WOLFSSL_DILITHIUM_NO_LARGE_CODE) + for (e = 0; e < DILITHIUM_N; e += 8) { + r[e+0] = dilithium_mont_red((sword64)a[e+0] * b[e+0]); + r[e+1] = dilithium_mont_red((sword64)a[e+1] * b[e+1]); + r[e+2] = dilithium_mont_red((sword64)a[e+2] * b[e+2]); + r[e+3] = dilithium_mont_red((sword64)a[e+3] * b[e+3]); + r[e+4] = dilithium_mont_red((sword64)a[e+4] * b[e+4]); + r[e+5] = dilithium_mont_red((sword64)a[e+5] * b[e+5]); + r[e+6] = dilithium_mont_red((sword64)a[e+6] * b[e+6]); + r[e+7] = dilithium_mont_red((sword64)a[e+7] * b[e+7]); + } +#else + for (e = 0; e < DILITHIUM_N; e += 16) { + r[e+ 0] = dilithium_mont_red((sword64)a[e+ 0] * b[e+ 0]); + r[e+ 1] = dilithium_mont_red((sword64)a[e+ 1] * b[e+ 1]); + r[e+ 2] = dilithium_mont_red((sword64)a[e+ 2] * b[e+ 2]); + r[e+ 3] = dilithium_mont_red((sword64)a[e+ 3] * b[e+ 3]); + r[e+ 4] = dilithium_mont_red((sword64)a[e+ 4] * b[e+ 4]); + r[e+ 5] = dilithium_mont_red((sword64)a[e+ 5] * b[e+ 5]); + r[e+ 6] = dilithium_mont_red((sword64)a[e+ 6] * b[e+ 6]); + r[e+ 7] = dilithium_mont_red((sword64)a[e+ 7] * b[e+ 7]); + r[e+ 8] = dilithium_mont_red((sword64)a[e+ 8] * b[e+ 8]); + r[e+ 9] = dilithium_mont_red((sword64)a[e+ 9] * b[e+ 9]); + r[e+10] = dilithium_mont_red((sword64)a[e+10] * b[e+10]); + r[e+11] = dilithium_mont_red((sword64)a[e+11] * b[e+11]); + r[e+12] = dilithium_mont_red((sword64)a[e+12] * b[e+12]); + r[e+13] = dilithium_mont_red((sword64)a[e+13] * b[e+13]); + r[e+14] = dilithium_mont_red((sword64)a[e+14] * b[e+14]); + r[e+15] = dilithium_mont_red((sword64)a[e+15] * b[e+15]); + } +#endif +} + +#if (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) +/* Vector multiplication. + * + * @param [out] r Vector of polynomials that is result. + * @param [in] a Polynomials + * @param [in] b Vector of polynomials. + * @param [in] l Dimension of vectors. + */ +static void dilithium_vec_mul(sword32* r, sword32* a, sword32* b, byte l) +{ + byte i; + + for (i = 0; i < l; i++) { + dilithium_mul(r, a, b); + r += DILITHIUM_N; + b += DILITHIUM_N; + } +} +#endif +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN +/* Modulo reduce values in polynomial. Range (-2^31)..(2^31-1). + * + * @param [in, out] a Polynomial. + */ +static void dilithium_poly_red(sword32* a) +{ + word16 j; +#ifdef WOLFSSL_DILITHIUM_SMALL + for (j = 0; j < DILITHIUM_N; j++) { + a[j] = dilithium_red(a[j]); + } +#else + for (j = 0; j < DILITHIUM_N; j += 8) { + a[j+0] = dilithium_red(a[j+0]); + a[j+1] = dilithium_red(a[j+1]); + a[j+2] = dilithium_red(a[j+2]); + a[j+3] = dilithium_red(a[j+3]); + a[j+4] = dilithium_red(a[j+4]); + a[j+5] = dilithium_red(a[j+5]); + a[j+6] = dilithium_red(a[j+6]); + a[j+7] = dilithium_red(a[j+7]); + } +#endif +} + +#ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM +/* Modulo reduce values in polynomials of vector. Range (-2^31)..(2^31-1). + * + * @param [in, out] a Vector of polynomials. + * @param [in] l Dimension of vector. + */ +static void dilithium_vec_red(sword32* a, byte l) +{ + byte i; + + for (i = 0; i < l; i++) { + dilithium_poly_red(a); + a += DILITHIUM_N; + } +} +#endif /* WOLFSSL_DILITHIUM_SIGN_SMALL_MEM*/ +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#if (!defined(WOLFSSL_DILITHIUM_NO_SIGN) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM))) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) +/* Subtract polynomials a from r. r -= a. + * + * @param [out] r Polynomial to subtract from. + * @param [in] a Polynomial to subtract. + */ +static void dilithium_sub(sword32* r, const sword32* a) +{ + word16 j; +#ifdef WOLFSSL_DILITHIUM_SMALL + for (j = 0; j < DILITHIUM_N; j++) { + r[j] -= a[j]; + } +#else + for (j = 0; j < DILITHIUM_N; j += 8) { + r[j+0] -= a[j+0]; + r[j+1] -= a[j+1]; + r[j+2] -= a[j+2]; + r[j+3] -= a[j+3]; + r[j+4] -= a[j+4]; + r[j+5] -= a[j+5]; + r[j+6] -= a[j+6]; + r[j+7] -= a[j+7]; + } +#endif +} + +#if defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM)) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) +/* Subtract vector a from r. r -= a. + * + * @param [out] r Vector of polynomials that is result. + * @param [in] a Vector of polynomials to subtract. + * @param [in] l Dimension of vectors. + */ +static void dilithium_vec_sub(sword32* r, const sword32* a, byte l) +{ + byte i; + + for (i = 0; i < l; i++) { + dilithium_sub(r, a); + r += DILITHIUM_N; + a += DILITHIUM_N; + } +} +#endif +#endif + +#ifndef WOLFSSL_DILITHIUM_VERIFY_ONLY +/* Add polynomials a to r. r += a. + * + * @param [out] r Polynomial to add to. + * @param [in] a Polynomial to add. + */ +static void dilithium_add(sword32* r, const sword32* a) +{ + word16 j; +#ifdef WOLFSSL_DILITHIUM_SMALL + for (j = 0; j < DILITHIUM_N; j++) { + r[j] += a[j]; + } +#else + for (j = 0; j < DILITHIUM_N; j += 8) { + r[j+0] += a[j+0]; + r[j+1] += a[j+1]; + r[j+2] += a[j+2]; + r[j+3] += a[j+3]; + r[j+4] += a[j+4]; + r[j+5] += a[j+5]; + r[j+6] += a[j+6]; + r[j+7] += a[j+7]; + } +#endif +} + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) +/* Add vector a to r. r += a. + * + * @param [out] r Vector of polynomials that is result. + * @param [in] a Vector of polynomials to add. + * @param [in] l Dimension of vectors. + */ +static void dilithium_vec_add(sword32* r, const sword32* a, byte l) +{ + byte i; + + for (i = 0; i < l; i++) { + dilithium_add(r, a); + r += DILITHIUM_N; + a += DILITHIUM_N; + } +} +#endif + +/* Make values in polynomial be in positive range. + * + * @param [in, out] a Polynomial. + */ +static void dilithium_make_pos(sword32* a) +{ + word16 j; +#ifdef WOLFSSL_DILITHIUM_SMALL + for (j = 0; j < DILITHIUM_N; j++) { + a[j] += (0 - (((word32)a[j]) >> 31)) & DILITHIUM_Q; + } +#else + for (j = 0; j < DILITHIUM_N; j += 8) { + a[j+0] += (0 - (((word32)a[j+0]) >> 31)) & DILITHIUM_Q; + a[j+1] += (0 - (((word32)a[j+1]) >> 31)) & DILITHIUM_Q; + a[j+2] += (0 - (((word32)a[j+2]) >> 31)) & DILITHIUM_Q; + a[j+3] += (0 - (((word32)a[j+3]) >> 31)) & DILITHIUM_Q; + a[j+4] += (0 - (((word32)a[j+4]) >> 31)) & DILITHIUM_Q; + a[j+5] += (0 - (((word32)a[j+5]) >> 31)) & DILITHIUM_Q; + a[j+6] += (0 - (((word32)a[j+6]) >> 31)) & DILITHIUM_Q; + a[j+7] += (0 - (((word32)a[j+7]) >> 31)) & DILITHIUM_Q; + } +#endif +} + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + defined(WOLFSSL_DILITHIUM_CHECK_KEY) || \ + (!defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM)) +/* Make values in polynomials of vector be in positive range. + * + * @param [in, out] a Vector of polynomials. + * @param [in] l Dimension of vector. + */ +static void dilithium_vec_make_pos(sword32* a, byte l) +{ + byte i; + + for (i = 0; i < l; i++) { + dilithium_make_pos(a); + a += DILITHIUM_N; + } +} +#endif + +#endif /* !WOLFSSL_DILITHIUM_VERIFY_ONLY */ + +/******************************************************************************/ + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY + +/* Make a key from a random seed. + * + * xi is seed passed in. + * FIPS 204. 5: Algorithm 1 ML-DSA.KeyGen() + * ... + * 2: (rho, rho', K) E {0,1}256 x {0,1}512 x {0,1}256 <- H(xi, 1024) + * 3: A_circum <- ExpandA(rho) + * 4: (s1,s2) <- ExpandS(rho') + * 5: t <- NTT-1(A_circum o NTT(s1)) + s2 + * 6: (t1, t0) <- Power2Round(t, d) + * 7: pk <- pkEncode(rho, t1) + * 8: tr <- H(BytesToBits(pk), 512) + * 9: sk <- skEncode(rho, K, tr, s1, s2, t0) + * 10: return (pk, sk) + * + * FIPS 204. 8.2: Algorithm 16 pkEncode(rho, t1) + * 1: pk <- BitsToBytes(rho) + * 2: for i from 0 to l - 1 do + * 3: pk <- pk || SimpleBitPack(t1[i], 2^(bitlen(q-1)-d) - 1) + * 4: end for + * 5: return pk + * + * FIPS 204. 8.2: Algorithm 18 skEncode(rho, K, tr, s, s2, t0) + * 1: sk <- BitsToBytes(rho) || BitsToBytes(K) || BitsToBytes(tr) + * 2: for i from 0 to l - 1 do + * 3: sk <- sk || BitPack(s1[i], eta, eta) + * 4: end for + * 5: for i from 0 to k - 1 do + * 6: sk <- sk || BitPack(s2[i], eta, eta) + * 7: end for + * 8: for i from 0 to k - 1 do + * 9: sk <- sk || BitPack(t0[i], 2^(d-1)-1, 2^(d-1)) + * 10: end for + * 11: return sk + * + * Public and private key store in key. + * + * @param [in, out] key Dilithium key. + * @param [in] seed Seed to hash to generate values. + * @return 0 on success. + * @return MEMORY_E when memory allocation fails. + * @return Other negative when an error occurs. + */ +static int dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) +{ + int ret = 0; + const wc_dilithium_params* params = key->params; + sword32* a = NULL; + sword32* s1 = NULL; + sword32* s2 = NULL; + sword32* t = NULL; + byte* pub_seed = key->k; + + /* Allocate memory for large intermediates. */ +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + if (key->a == NULL) { + key->a = (sword32*)XMALLOC(params->aSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (key->a == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + a = key->a; + } +#endif +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + if ((ret == 0) && (key->s1 == NULL)) { + key->s1 = (sword32*)XMALLOC(params->aSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (key->s1 == NULL) { + ret = MEMORY_E; + } + else { + key->s2 = key->s1 + params->s1Sz / sizeof(*s1); + key->t0 = key->s2 + params->s2Sz / sizeof(*s2); + } + } + if (ret == 0) { + s1 = key->s1; + s2 = key->s2; + t = key->t0; + } +#else + if (ret == 0) { + unsigned int allocSz; + + allocSz = params->s1Sz + params->s2Sz + params->s2Sz; +#ifndef WC_DILITHIUM_CACHE_MATRIX_A + allocSz += params->aSz; +#endif + + /* s1, s2, t, a */ + s1 = (sword32*)XMALLOC(allocSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (s1 == NULL) { + ret = MEMORY_E; + } + else { + s2 = s1 + params->s1Sz / sizeof(*s1); + t = s2 + params->s2Sz / sizeof(*s2); +#ifndef WC_DILITHIUM_CACHE_MATRIX_A + a = t + params->s2Sz / sizeof(*s2); +#endif + } + } +#endif + + if (ret == 0) { + /* Step 2: Create public seed, private seed and K from seed. + * Step 9; Alg 18, Step 1: Public seed is placed into private key. */ + ret = dilithium_shake256(&key->shake, seed, DILITHIUM_SEED_SZ, pub_seed, + DILITHIUM_SEEDS_SZ); + } + if (ret == 0) { + /* Step 7; Alg 16 Step 1: Copy public seed into public key. */ + XMEMCPY(key->p, pub_seed, DILITHIUM_PUB_SEED_SZ); + + /* Step 3: Expand public seed into a matrix of polynomials. */ + ret = dilithium_expand_a(&key->shake, pub_seed, params->k, params->l, + a); + } + if (ret == 0) { + byte* priv_seed = key->k + DILITHIUM_PUB_SEED_SZ; + + /* Step 4: Expand private seed into to vectors of polynomials. */ + ret = dilithium_expand_s(&key->shake, priv_seed, params->eta, s1, + params->l, s2, params->k); + } + if (ret == 0) { + byte* k = pub_seed + DILITHIUM_PUB_SEED_SZ; + byte* tr = k + DILITHIUM_K_SZ; + byte* s1p = tr + DILITHIUM_TR_SZ; + byte* s2p = s1p + params->s1EncSz; + byte* t0 = s2p + params->s2EncSz; + byte* t1 = key->p + DILITHIUM_PUB_SEED_SZ; + + /* Step 9: Move k down to after public seed. */ + XMEMCPY(k, k + DILITHIUM_PRIV_SEED_SZ, DILITHIUM_K_SZ); + /* Step 9. Alg 18 Steps 2-4: Encode s1 into private key. */ + dilthium_vec_encode_eta_bits(s1, params->l, params->eta, s1p); + /* Step 9. Alg 18 Steps 5-7: Encode s2 into private key. */ + dilthium_vec_encode_eta_bits(s2, params->k, params->eta, s2p); + + /* Step 5: t <- NTT-1(A_circum o NTT(s1)) + s2 */ + dilithium_vec_ntt_small(s1, params->l); + dilithium_matrix_mul(t, a, s1, params->k, params->l); + dilithium_vec_invntt(t, params->k); + dilithium_vec_add(t, s2, params->k); + + /* Make positive for decomposing. */ + dilithium_vec_make_pos(t, params->k); + /* Step 6, Step 7, Step 9. Alg 16 Steps 2-4, Alg 18 Steps 8-10. + * Decompose t in t0 and t1 and encode into public and private key. + */ + dilithium_vec_encode_t0_t1(t, params->k, t0, t1); + /* Step 8. Alg 18, Step 1: Hash public key into private key. */ + ret = dilithium_shake256(&key->shake, key->p, params->pkSz, tr, + DILITHIUM_TR_SZ); + } + if (ret == 0) { + /* Public key and private key are available. */ + key->prvKeySet = 1; + key->pubKeySet = 1; +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + /* Matrix A is available. */ + key->aSet = 1; +#endif +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + /* Private vectors are not available as they were overwritten. */ + key->privVecsSet = 0; +#endif +#ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + /* Public vector, t1, is not available as it was not created. */ + key->pubVecSet = 0; +#endif + } + +#ifndef WC_DILITHIUM_CACHE_PRIV_VECTORS + XFREE(s1, NULL, DYNAMIC_TYPE_DILITHIUM); +#endif + return ret; +} + +/* Make a key from a random seed. + * + * FIPS 204. 5: Algorithm 1 ML-DSA.KeyGen() + * 1: xi <- {0,1}256 [Choose random seed] + * ... + * + * @param [in, out] key Dilithium key. + * @param [in] rng Random number generator. + * @return 0 on success. + * @return MEMORY_E when memory allocation fails. + * @return Other negative when an error occurs. + */ +static int dilithium_make_key(dilithium_key* key, WC_RNG* rng) +{ + int ret; + byte seed[DILITHIUM_SEED_SZ]; + + /* Generate a 256-bit random seed. */ + ret = wc_RNG_GenerateBlock(rng, seed, DILITHIUM_SEED_SZ); + if (ret == 0) { + /* Make key with random seed. */ + ret = wc_dilithium_make_key_from_seed(key, seed); + } + + return ret; +} +#endif /* !WOLFSSL_DILITHIUM_NO_MAKE_KEY */ + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN + +#if !defined(WOLFSSL_DILITHIUM_SIGN_SMALL_MEM) || \ + defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) +/* Decode, from private key, and NTT private key vectors s1, s2, and t0. + * + * FIPS 204. 6: Algorithm 2 MD-DSA.Sign(sk, M) + * 1: (rho, K, tr, s1, s2, t0) <- skDecode(sk) + * 2: s1_circum <- NTT(s1) + * 3: s2_circum <- NTT(s2) + * 4: t0_circum <- NTT(t0) + * + * @param [in, out] key Dilithium key. + * @param [out] s1 Vector of polynomials s1. + * @param [out] s2 Vector of polynomials s2. + * @param [out] t0 Vector of polynomials t0. + */ +static void dilithium_make_priv_vecs(dilithium_key* key, sword32* s1, + sword32* s2, sword32* t0) +{ + const wc_dilithium_params* params = key->params; + const byte* pubSeed = key->k; + const byte* k = pubSeed + DILITHIUM_PUB_SEED_SZ; + const byte* tr = k + DILITHIUM_K_SZ; + const byte* s1p = tr + DILITHIUM_TR_SZ; + const byte* s2p = s1p + params->s1EncSz; + const byte* t0p = s2p + params->s2EncSz; + + /* Step 1: Decode s1, s2, t0. */ + dilithium_vec_decode_eta_bits(s1p, params->eta, s1, params->l); + dilithium_vec_decode_eta_bits(s2p, params->eta, s2, params->k); + dilithium_vec_decode_t0(t0p, params->k, t0); + + /* Step 2: NTT s1. */ + dilithium_vec_ntt_small(s1, params->l); + /* Step 3: NTT s2. */ + dilithium_vec_ntt_small(s2, params->k); + /* Step 4: NTT t0. */ + dilithium_vec_ntt(t0, params->k); + +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + /* Private key vectors have been created. */ + key->privVecsSet = 1; +#endif +} +#endif + +/* Sign a message with the key and a seed. + * + * FIPS 204. 6: Algorithm 2 MD-DSA.Sign(sk, M) + * 1: (rho, K, tr, s1, s2, t0) <- skDecode(sk) + * 2: s1_circum <- NTT(s1) + * 3: s2_circum <- NTT(s2) + * 4: t0_circum <- NTT(t0) + * 5: A_circum <- ExpandA(rho) + * 6: mu <- H(tr||M, 512) + * 7: rnd <- {0,1}256 + * 8: rho' <- H(K||rnd||mu, 512) + * 9: kappa <- 0 + * 10: (z, h) <- falsam + * 11: while (z, h) = falsam do + * 12: y <- ExpandMask(rho', kappa) + * 13: w <- NTT-1(A_circum o NTT(y)) + * 14: w1 <- HighBits(w) + * 15: c_tilde E {0,1}2*lambda <- H(mu|w1Encode(w1), 2 * lambda) + * 16: (c1_tilde, c2_tilde) E {0,1}256 x {0,1}2*lambda-256 <- c_tilde + * 17: c < SampleInBall(c1_tilde) + * 18: c_circum <- NTT(c) + * 19: <> <- NTT-1(c_circum o s1_circum) + * 20: <> <- NTT-1(c_circum o s2_circum) + * 21: z <- y + <> + * 22: r0 <- LowBits(w - <> + * 23: if ||z||inf >= GAMMA1 - BETA or ||r0||inf GAMMA2 - BETA then + * (z, h) <- falsam + * 24: else + * 25: <> <- NTT-1(c_circum o t0_circum) + * 26: h < MakeHint(-<>, w - <> + <>) + * 27: if (||<>||inf >= GAMMMA1 or + * the number of 1's in h is greater than OMEGA, then + * (z, h) <- falsam + * 28: end if + * 29: end if + * 30: kappa <- kappa + l + * 31: end while + * 32: sigma <- sigEncode(c_tilde, z mod +/- q, h) + * 33: return sigma + * + * @param [in, out] key Dilithium key. + * @param [in, out] seed Random seed. + * @param [in] msg Message data to sign. + * @param [in] msgLen Length of message data in bytes. + * @param [out] sig Buffer to hold signature. + * @param [in, out] sigLen On in, length of buffer in bytes. + * On out, the length of the signature in bytes. + * @return 0 on success. + * @return BUFFER_E when the signature buffer is too small. + * @return MEMORY_E when memory allocation fails. + * @return Other negative when an error occurs. + */ +static int dilithium_sign_msg_with_seed(dilithium_key* key, const byte* seed, + const byte* msg, word32 msgLen, byte* sig, word32 *sigLen) +{ +#ifndef WOLFSSL_DILITHIUM_SIGN_SMALL_MEM + int ret = 0; + const wc_dilithium_params* params = key->params; + byte* pub_seed = key->k; + byte* k = pub_seed + DILITHIUM_PUB_SEED_SZ; + byte* tr = k + DILITHIUM_K_SZ; + sword32* a = NULL; + sword32* s1 = NULL; + sword32* s2 = NULL; + sword32* t0 = NULL; + sword32* y = NULL; + sword32* w0 = NULL; + sword32* w1 = NULL; + sword32* c = NULL; + sword32* z = NULL; + sword32* ct0 = NULL; + byte data[DILITHIUM_RND_SZ + DILITHIUM_MU_SZ]; + byte* mu = data + DILITHIUM_RND_SZ; + byte priv_rand_seed[DILITHIUM_Y_SEED_SZ]; + byte* h = sig + params->lambda * 2 + params->zEncSz; + + /* Check the signature buffer isn't too small. */ + if ((ret == 0) && (*sigLen < params->sigSz)) { + ret = BUFFER_E; + } + if (ret == 0) { + /* Return the size of the signature. */ + *sigLen = params->sigSz; + } + + /* Allocate memory for large intermediates. */ +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + if ((ret == 0) && (key->a == NULL)) { + a = (sword32*)XMALLOC(params->aSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (a == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + a = key->a; + } +#endif +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + if ((ret == 0) && (key->s1 == NULL)) { + key->s1 = (sword32*)XMALLOC(params->aSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (key->s1 == NULL) { + ret = MEMORY_E; + } + else { + key->s2 = key->s1 + params->s1Sz / sizeof(*s1); + key->t0 = key->s2 + params->s2Sz / sizeof(*s2); + } + } + if (ret == 0) { + s1 = key->s1; + s2 = key->s2; + t0 = key->t0; + } +#endif + if (ret == 0) { + unsigned int allocSz; + + /* y-l, w0-k, w1-k, c-1, z-l, ct0-k */ + allocSz = params->s1Sz + params->s2Sz + params->s2Sz + + DILITHIUM_POLY_SIZE + params->s1Sz + params->s2Sz; +#ifndef WC_DILITHIUM_CACHE_PRIV_VECTORS + /* s1-l, s2-k, t0-k */ + allocSz += params->s1Sz + params->s2Sz + params->s2Sz; +#endif +#ifndef WC_DILITHIUM_CACHE_MATRIX_A + /* A */ + allocSz += params->aSz; +#endif + y = (sword32*)XMALLOC(allocSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (y == NULL) { + ret = MEMORY_E; + } + else { + w0 = y + params->s1Sz / sizeof(*y); + w1 = w0 + params->s2Sz / sizeof(*w0); + c = w1 + params->s2Sz / sizeof(*w1); + z = c + DILITHIUM_N; + ct0 = z + params->s1Sz / sizeof(*z); +#ifndef WC_DILITHIUM_CACHE_PRIV_VECTORS + s1 = ct0 + params->s2Sz / sizeof(*ct0); + s2 = s1 + params->s1Sz / sizeof(*s1); + t0 = s2 + params->s2Sz / sizeof(*s2); +#endif +#ifndef WC_DILITHIUM_CACHE_MATRIX_A + a = t0 + params->s2Sz / sizeof(*s2); +#endif + } + } + + if (ret == 0) { +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + /* Check that we haven't already cached the private vectors. */ + if (!key->privVecsSet) +#endif + { + /* Steps 1-4: Decode and NTT vectors s1, s2, and t0. */ + dilithium_make_priv_vecs(key, s1, s2, t0); + } + +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + /* Check that we haven't already cached the matrix A. */ + if (!key->aSet) +#endif + { + /* Step 5: Create the matrix A from the public seed. */ + ret = dilithium_expand_a(&key->shake, pub_seed, params->k, + params->l, a); +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + key->aSet = (ret == 0); +#endif + } + } + if (ret == 0) { + /* Step 6: Compute the hash of tr, public key hash, and message. */ + ret = dilithium_hash256(&key->shake, tr, DILITHIUM_TR_SZ, msg, msgLen, + mu, DILITHIUM_MU_SZ); + } + if (ret == 0) { + /* Step 7: Copy random into buffer for hashing. */ + XMEMCPY(data, seed, DILITHIUM_RND_SZ); + } + if (ret == 0) { + /* Step 9: Compute private random using hash. */ + ret = dilithium_hash256(&key->shake, k, DILITHIUM_K_SZ, data, + DILITHIUM_RND_SZ + DILITHIUM_MU_SZ, priv_rand_seed, + DILITHIUM_PRIV_RAND_SEED_SZ); + } + if (ret == 0) { + word16 kappa = 0; + int valid = 0; + + /* Step 11: Start rejection sampling loop */ + do { + byte w1e[DILITHIUM_MAX_W1_ENC_SZ]; + sword32* w = w1; + sword32* y_ntt = z; + sword32* cs2 = ct0; + byte* commit = sig; + + /* Step 12: Compute vector y from private random seed and kappa. */ + dilithium_vec_expand_mask(&key->shake, priv_rand_seed, kappa, + params->gamma1_bits, y, params->l); + #ifdef WOLFSSL_DILITHIUM_SIGN_CHECK_Y + valid = dilithium_vec_check_low(y, params->l, + (1 << params->gamma1_bits) - params->beta); + if (valid) + #endif + { + /* Step 13: NTT-1(A o NTT(y)) */ + XMEMCPY(y_ntt, y, params->s1Sz); + dilithium_vec_ntt(y_ntt, params->l); + dilithium_matrix_mul(w, a, y_ntt, params->k, params->l); + dilithium_vec_invntt(w, params->k); + /* Step 14, Step 22: Make values positive and decompose. */ + dilithium_vec_make_pos(w, params->k); + dilithium_vec_decompose(w, params->k, params->gamma2, w0, w1); + #ifdef WOLFSSL_DILITHIUM_SIGN_CHECK_W0 + valid = dilithium_vec_check_low(w0, params->k, + params->gamma2 - params->beta); + } + if (valid) { + #endif + /* Step 15: Encode w1. */ + dilithium_vec_encode_w1(w1, params->k, params->gamma2, w1e); + /* Step 15: Hash mu and encoded w1. + * Step 32: Hash is stored in signature. */ + ret = dilithium_hash256(&key->shake, mu, DILITHIUM_MU_SZ, + w1e, params->w1EncSz, commit, 2 * params->lambda); + if (ret == 0) { + /* Step 17: Compute c from first 256 bits of commit. */ + ret = dilithium_sample_in_ball(&key->shake, commit, + params->tau, c, NULL); + } + if (ret == 0) { + sword32 hi; + + /* Step 18: NTT(c). */ + dilithium_ntt_small(c); + /* Step 20: cs2 = NTT-1(c o s2) */ + dilithium_vec_mul(cs2, c, s2, params->k); + dilithium_vec_invntt(cs2, params->k); + /* Step 22: w0 - cs2 */ + dilithium_vec_sub(w0, cs2, params->k); + dilithium_vec_red(w0, params->k); + /* Step 23: Check w0 - cs2 has low enough values. */ + hi = params->gamma2 - params->beta; + valid = dilithium_vec_check_low(w0, params->k, hi); + if (valid) { + /* Step 19: cs1 = NTT-1(c o s1) */ + dilithium_vec_mul(z, c, s1, params->l); + dilithium_vec_invntt(z, params->l); + /* Step 21: z = y + cs1 */ + dilithium_vec_add(z, y, params->l); + dilithium_vec_red(z, params->l); + /* Step 23: Check z has low enough values. */ + hi = (1 << params->gamma1_bits) - params->beta; + valid = dilithium_vec_check_low(z, params->l, hi); + } + if (valid) { + /* Step 25: ct0 = NTT-1(c o t0) */ + dilithium_vec_mul(ct0, c, t0, params->k); + dilithium_vec_invntt(ct0, params->k); + /* Step 27: Check ct0 has low enough values. */ + hi = params->gamma2; + valid = dilithium_vec_check_low(ct0, params->k, hi); + } + if (valid) { + /* Step 26: ct0 = ct0 + w0 */ + dilithium_vec_add(ct0, w0, params->k); + dilithium_vec_red(ct0, params->k); + /* Step 26, 27: Make hint from ct0 and w1 and check + * number of hints is valid. + * Step 32: h is encoded into signature. + */ + valid = (dilithium_make_hint(ct0, w1, params->k, + params->gamma2, params->omega, h) >= 0); + } + } + } + + if (!valid) { + /* Too many attempts - something wrong with implementation. */ + if ((kappa > (word16)(kappa + params->l))) { + ret = BAD_COND_E; + } + + /* Step 30: increment value to append to seed to unique value. + */ + kappa += params->l; + } + } + /* Step 11: Check we have a valid signature. */ + while ((ret == 0) && (!valid)); + } + if (ret == 0) { + byte* ze = sig + params->lambda * 2; + /* Step 32: Encode z into signature. + * Commit (c) and h already encoded into signature. */ + dilithium_vec_encode_gamma1(z, params->l, params->gamma1_bits, ze); + } + + XFREE(y, NULL, DYNAMIC_TYPE_DILITHIUM); + return ret; +#else + int ret = 0; + const wc_dilithium_params* params = key->params; + byte* pub_seed = key->k; + byte* k = pub_seed + DILITHIUM_PUB_SEED_SZ; + byte* tr = k + DILITHIUM_K_SZ; + const byte* s1p = tr + DILITHIUM_TR_SZ; + const byte* s2p = s1p + params->s1EncSz; + const byte* t0p = s2p + params->s2EncSz; + sword32* a = NULL; + sword32* s1 = NULL; + sword32* s2 = NULL; + sword32* t0 = NULL; + sword32* y = NULL; + sword32* y_ntt = NULL; + sword32* w0 = NULL; + sword32* w1 = NULL; + sword32* c = NULL; + sword32* z = NULL; + sword32* ct0 = NULL; + byte data[DILITHIUM_RND_SZ + DILITHIUM_MU_SZ]; + byte* mu = data + DILITHIUM_RND_SZ; + byte priv_rand_seed[DILITHIUM_Y_SEED_SZ]; + byte* h = sig + params->lambda * 2 + params->zEncSz; + + /* Check the signature buffer isn't too small. */ + if ((ret == 0) && (*sigLen < params->sigSz)) { + ret = BUFFER_E; + } + if (ret == 0) { + /* Return the size of the signature. */ + *sigLen = params->sigSz; + } + + /* Allocate memory for large intermediates. */ + if (ret == 0) { + unsigned int allocSz; + + /* y-l, w0-k, w1-k, c-1, s1-1, A-1 */ + allocSz = params->s1Sz + params->s2Sz + params->s2Sz + + DILITHIUM_POLY_SIZE + DILITHIUM_POLY_SIZE + DILITHIUM_POLY_SIZE; + y = (sword32*)XMALLOC(allocSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (y == NULL) { + ret = MEMORY_E; + } + else { + w0 = y + params->s1Sz / sizeof(*y_ntt); + w1 = w0 + params->s2Sz / sizeof(*w0); + c = w1 + params->s2Sz / sizeof(*w1); + s1 = c + DILITHIUM_N; + a = s1 + DILITHIUM_N; + s2 = s1; + t0 = s1; + ct0 = s1; + z = s1; + y_ntt = s1; + } + } + + if (ret == 0) { + /* Step 7: Copy random into buffer for hashing. */ + XMEMCPY(data, seed, DILITHIUM_RND_SZ); + + /* Step 6: Compute the hash of tr, public key hash, and message. */ + ret = dilithium_hash256(&key->shake, tr, DILITHIUM_TR_SZ, msg, msgLen, + mu, DILITHIUM_MU_SZ); + } + if (ret == 0) { + /* Step 9: Compute private random using hash. */ + ret = dilithium_hash256(&key->shake, k, DILITHIUM_K_SZ, data, + DILITHIUM_RND_SZ + DILITHIUM_MU_SZ, priv_rand_seed, + DILITHIUM_PRIV_RAND_SEED_SZ); + } + if (ret == 0) { + word16 kappa = 0; + int valid; + + /* Step 11: Start rejection sampling loop */ + do { + byte w1e[DILITHIUM_MAX_W1_ENC_SZ]; + sword32* w = w1; + byte* commit = sig; + byte r; + byte s; + byte aseed[DILITHIUM_GEN_A_SEED_SZ]; + sword32 hi; + sword32* at = a; + sword32* wt = w; + sword32* w0t = w0; + sword32* w1t = w1; + + valid = 1; + /* Step 12: Compute vector y from private random seed and kappa. */ + dilithium_vec_expand_mask(&key->shake, priv_rand_seed, kappa, + params->gamma1_bits, y, params->l); + #ifdef WOLFSSL_DILITHIUM_SIGN_CHECK_Y + valid = dilithium_vec_check_low(y, params->l, + (1 << params->gamma1_bits) - params->beta); + #endif + + /* Step 5: Create the matrix A from the public seed. */ + /* Copy the seed into a buffer that has space for s and r. */ + XMEMCPY(aseed, pub_seed, DILITHIUM_PUB_SEED_SZ); + /* Alg 26. Step 1: Loop over first dimension of matrix. */ + for (r = 0; (ret == 0) && valid && (r < params->k); r++) { + unsigned int e; + sword32* yt = y; + + /* Put r/i into buffer to be hashed. */ + aseed[DILITHIUM_PUB_SEED_SZ + 1] = r; + /* Alg 26. Step 2: Loop over second dimension of matrix. */ + for (s = 0; (ret == 0) && (s < params->l); s++) { + /* Put s into buffer to be hashed. */ + aseed[DILITHIUM_PUB_SEED_SZ + 0] = s; + /* Alg 26. Step 3: Create polynomial from hashing seed. */ + ret = dilithium_rej_ntt_poly(&key->shake, aseed, at, + NULL); + if (ret != 0) { + break; + } + XMEMCPY(y_ntt, yt, DILITHIUM_POLY_SIZE); + dilithium_ntt(y_ntt); + /* Matrix multiply. */ + if (s == 0) { + for (e = 0; e < DILITHIUM_N; e++) { + wt[e] = dilithium_mont_red((sword64)at[e] * + y_ntt[e]); + } + } + else { + for (e = 0; e < DILITHIUM_N; e++) { + wt[e] += dilithium_mont_red((sword64)at[e] * + y_ntt[e]); + } + } + /* Next polynomial. */ + yt += DILITHIUM_N; + } + dilithium_invntt(wt); + /* Step 14, Step 22: Make values positive and decompose. */ + dilithium_make_pos(wt); + #ifndef WOLFSSL_NO_ML_DSA_44 + if (params->gamma2 == DILITHIUM_Q_LOW_88) { + /* For each value of polynomial. */ + for (e = 0; e < DILITHIUM_N; e++) { + /* Decompose value into two vectors. */ + dilithium_decompose_q88(wt[e], &w0t[e], &w1t[e]); + } + } + #endif + #if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (params->gamma2 == DILITHIUM_Q_LOW_32) { + /* For each value of polynomial. */ + for (e = 0; e < DILITHIUM_N; e++) { + /* Decompose value into two vectors. */ + dilithium_decompose_q32(wt[e], &w0t[e], &w1t[e]); + } + } + #endif + #ifdef WOLFSSL_DILITHIUM_SIGN_CHECK_W0 + valid = dilithium_vec_check_low(w0t, + params->gamma2 - params->beta); + #endif + wt += DILITHIUM_N; + w0t += DILITHIUM_N; + w1t += DILITHIUM_N; + } + if ((ret == 0) && valid) { + sword32* yt = y; + const byte* s1pt = s1p; + byte* ze = sig + params->lambda * 2; + + /* Step 15: Encode w1. */ + dilithium_vec_encode_w1(w1, params->k, params->gamma2, w1e); + /* Step 15: Hash mu and encoded w1. + * Step 32: Hash is stored in signature. */ + ret = dilithium_hash256(&key->shake, mu, DILITHIUM_MU_SZ, + w1e, params->w1EncSz, commit, 2 * params->lambda); + if (ret == 0) { + /* Step 17: Compute c from first 256 bits of commit. */ + ret = dilithium_sample_in_ball(&key->shake, commit, + params->tau, c, NULL); + } + if (ret == 0) { + /* Step 18: NTT(c). */ + dilithium_ntt_small(c); + } + + for (s = 0; (ret == 0) && valid && (s < params->l); s++) { + #if !defined(WOLFSSL_NO_ML_DSA_44) || \ + !defined(WOLFSSL_NO_ML_DSA_87) + /* -2..2 */ + if (params->eta == DILITHIUM_ETA_2) { + dilithium_decode_eta_2_bits(s1pt, s1); + s1pt += DILITHIUM_ETA_2_BITS * DILITHIUM_N / 8; + } + #endif + #ifndef WOLFSSL_NO_ML_DSA_65 + /* -4..4 */ + if (params->eta == DILITHIUM_ETA_4) { + dilithium_decode_eta_4_bits(s1pt, s1); + s1pt += DILITHIUM_N / 2; + } + #endif + dilithium_ntt_small(s1); + dilithium_mul(z, c, s1); + /* Step 19: cs1 = NTT-1(c o s1) */ + dilithium_invntt(z); + /* Step 21: z = y + cs1 */ + dilithium_add(z, yt); + dilithium_poly_red(z); + /* Step 23: Check z has low enough values. */ + hi = (1 << params->gamma1_bits) - params->beta; + valid = dilithium_check_low(z, hi); + if (valid) { + /* Step 32: Encode z into signature. + * Commit (c) and h already encoded into signature. */ + #if !defined(WOLFSSL_NO_ML_DSA_44) + if (params->gamma1_bits == DILITHIUM_GAMMA1_BITS_17) { + dilithium_encode_gamma1_17_bits(z, ze); + /* Move to next place to encode to. */ + ze += DILITHIUM_GAMMA1_17_ENC_BITS / 2 * + DILITHIUM_N / 4; + } + else + #endif + #if !defined(WOLFSSL_NO_ML_DSA_65) || \ + !defined(WOLFSSL_NO_ML_DSA_87) + if (params->gamma1_bits == DILITHIUM_GAMMA1_BITS_19) { + dilithium_encode_gamma1_19_bits(z, ze); + /* Move to next place to encode to. */ + ze += DILITHIUM_GAMMA1_19_ENC_BITS / 2 * + DILITHIUM_N / 4; + } + #endif + } + + yt += DILITHIUM_N; + } + } + if ((ret == 0) && valid) { + const byte* t0pt = t0p; + const byte* s2pt = s2p; + sword32* cs2 = ct0; + w0t = w0; + w1t = w1; + byte idx = 0; + + for (r = 0; valid && (r < params->k); r++) { + #if !defined(WOLFSSL_NO_ML_DSA_44) || \ + !defined(WOLFSSL_NO_ML_DSA_87) + /* -2..2 */ + if (params->eta == DILITHIUM_ETA_2) { + dilithium_decode_eta_2_bits(s2pt, s2); + s2pt += DILITHIUM_ETA_2_BITS * DILITHIUM_N / 8; + } + #endif + #ifndef WOLFSSL_NO_ML_DSA_65 + /* -4..4 */ + if (params->eta == DILITHIUM_ETA_4) { + dilithium_decode_eta_4_bits(s2pt, s2); + s2pt += DILITHIUM_N / 2; + } + #endif + dilithium_ntt_small(s2); + /* Step 20: cs2 = NTT-1(c o s2) */ + dilithium_mul(cs2, c, s2); + dilithium_invntt(cs2); + /* Step 22: w0 - cs2 */ + dilithium_sub(w0t, cs2); + dilithium_poly_red(w0t); + /* Step 23: Check w0 - cs2 has low enough values. */ + hi = params->gamma2 - params->beta; + valid = dilithium_check_low(w0t, hi); + if (valid) { + dilithium_decode_t0(t0pt, t0); + dilithium_ntt(t0); + + /* Step 25: ct0 = NTT-1(c o t0) */ + dilithium_mul(ct0, c, t0); + dilithium_invntt(ct0); + /* Step 27: Check ct0 has low enough values. */ + valid = dilithium_check_low(ct0, params->gamma2); + } + if (valid) { + /* Step 26: ct0 = ct0 + w0 */ + dilithium_add(ct0, w0t); + dilithium_poly_red(ct0); + + /* Step 26, 27: Make hint from ct0 and w1 and check + * number of hints is valid. + * Step 32: h is encoded into signature. + */ + #ifndef WOLFSSL_NO_ML_DSA_44 + if (params->gamma2 == DILITHIUM_Q_LOW_88) { + valid = (dilithium_make_hint_88(ct0, w1t, h, + &idx) == 0); + /* Alg 14, Step 10: Store count of hints for + * polynomial at end of list. */ + h[PARAMS_ML_DSA_44_OMEGA + r] = idx; + } + #endif + #if !defined(WOLFSSL_NO_ML_DSA_65) || \ + !defined(WOLFSSL_NO_ML_DSA_87) + if (params->gamma2 == DILITHIUM_Q_LOW_32) { + valid = (dilithium_make_hint_32(ct0, w1t, + params->omega, h, &idx) == 0); + /* Alg 14, Step 10: Store count of hints for + * polynomial at end of list. */ + h[params->omega + r] = idx; + } + #endif + } + + t0pt += DILITHIUM_D * DILITHIUM_N / 8; + w0t += DILITHIUM_N; + w1t += DILITHIUM_N; + } + /* Set remaining hints to zero. */ + XMEMSET(h + idx, 0, params->omega - idx); + } + + if (!valid) { + /* Too many attempts - something wrong with implementation. */ + if ((kappa > (word16)(kappa + params->l))) { + ret = BAD_COND_E; + } + + /* Step 30: increment value to append to seed to unique value. + */ + kappa += params->l; + } + } + /* Step 11: Check we have a valid signature. */ + while ((ret == 0) && (!valid)); + } + + XFREE(y, NULL, DYNAMIC_TYPE_DILITHIUM); + return ret; +#endif +} + +/* Sign a message with the key and a random number generator. + * + * FIPS 204. 6: Algorithm 2 MD-DSA.Sign(sk, M) + * ... + * 7: rnd <- {0,1}256 [Randomly generated.] + * ... + * + * @param [in, out] key Dilithium key. + * @param [in, out] rng Random number generator. + * @param [in] msg Message data to sign. + * @param [in] msgLen Length of message data in bytes. + * @param [out] sig Buffer to hold signature. + * @param [in, out] sigLen On in, length of buffer in bytes. + * On out, the length of the signature in bytes. + * @return 0 on success. + * @return BUFFER_E when the signature buffer is too small. + * @return MEMORY_E when memory allocation fails. + * @return Other negative when an error occurs. + */ +static int dilithium_sign_msg(dilithium_key* key, WC_RNG* rng, const byte* msg, + word32 msgLen, byte* sig, word32 *sigLen) +{ + int ret = 0; + byte rnd[DILITHIUM_RND_SZ]; + + /* Must have a random number generator. */ + if (rng == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Step 7: Generate random seed. */ + ret = wc_RNG_GenerateBlock(rng, rnd, DILITHIUM_RND_SZ); + } + if (ret == 0) { + /* Sign with random seed. */ + ret = dilithium_sign_msg_with_seed(key, rnd, msg, msgLen, sig, + sigLen); + } + + return ret; +} + +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY + +#ifndef WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM +static void dilithium_make_pub_vec(dilithium_key* key, sword32* t1) +{ + const wc_dilithium_params* params = key->params; + const byte* t1p = key->p + DILITHIUM_PUB_SEED_SZ; + + dilithium_vec_decode_t1(t1p, params->k, t1); + dilithium_vec_ntt(t1, params->k); + +#ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + key->pubVecSet = 1; +#endif +} +#endif + +/* Verify signature of message using public key. + * + * FIPS 204. 6: Algorithm 3 ML-DSA.Verify(pk, M, sigma) + * 1: (rho, t1) <- pkDecode(pk) + * 2: (c_tilde, z, h) <- sigDecode(sigma) + * 3: if h = falsam then return false + * 4: end if + * 5: A_circum <- ExpandS(rho) + * 6: tr <- H(BytesToBits(pk), 512) + * 7: mu <- H(tr||M, 512) + * 8: (c1_tilde, c2_tilde) E {0,1}256 x {0,1)2*lambda-256 <- c_tilde + * 9: c <- SampleInBall(c1_tilde) + * 10: w'approx <- NTT-1(A_circum o NTT(z) - NTT(c) o NTT(t1.s^d)) + * 11: w1' <- UseHint(h, w'approx) + * 12: c'_tilde < H(mu||w1Encode(w1'), 2*lambda) + * 13: return [[ ||z||inf < GAMMA1 - BETA]] and [[c_tilde = c'_tilde]] and + * [[number of 1's in h is <= OMEGA + * + * @param [in, out] key Dilithium key. + * @param [in] msg Message to verify. + * @param [in] msgLen Length of message in bytes. + * @param [in] sig Signature to verify message. + * @param [in] sigLen Length of message in bytes. + * @param [out] res Result of verification. + * @return 0 on success. + * @return SIG_VERIFY_E when hint is malformed. + * @return BUFFER_E when the length of the signature does not match + * parameters. + * @return MEMORY_E when memory allocation fails. + * @return Other negative when an error occurs. + */ +static int dilithium_verify_msg(dilithium_key* key, const byte* msg, + word32 msgLen, const byte* sig, word32 sigLen, int* res) +{ +#ifndef WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM + int ret = 0; + const wc_dilithium_params* params = key->params; + const byte* pub_seed = key->p; + const byte* commit = sig; + const byte* ze = sig + params->lambda * 2; + const byte* h = ze + params->zEncSz; + sword32* a = NULL; + sword32* t1 = NULL; + sword32* c = NULL; + sword32* z = NULL; + sword32* w = NULL; + sword32* t1c = NULL; + byte tr[DILITHIUM_TR_SZ]; + byte* mu = tr; + byte* w1e = NULL; + byte* commit_calc = tr; + int valid = 0; + sword32 hi; + + /* Ensure the signature is the right size for the parameters. */ + if (sigLen != params->sigSz) { + ret = BUFFER_E; + } + if (ret == 0) { + /* Step 13: Verify the hint is well-formed. */ + ret = dilithium_check_hint(h, params->k, params->omega); + } + + /* Allocate memory for large intermediates. */ +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + if ((ret == 0) && (key->a == NULL)) { + key->a = (sword32*)XMALLOC(params->aSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (key->a == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + a = key->a; + } +#endif +#ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + if ((ret == 0) && (key->t1 == NULL)) { + key->t1 = (sword32*)XMALLOC(params->s2Sz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (key->t1 == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + t1 = key->t1; + } +#endif + if (ret == 0) { + unsigned int allocSz; + + /* z, c, w, t1/t1c */ + allocSz = DILITHIUM_POLY_SIZE + params->s1Sz + params->s2Sz + + params->s2Sz; +#ifndef WC_DILITHIUM_CACHE_MATRIX_A + /* a */ + allocSz += params->aSz; +#endif -#ifdef HAVE_CONFIG_H - #include + z = (sword32*)XMALLOC(allocSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (z == NULL) { + ret = MEMORY_E; + } + else { + c = z + params->s1Sz / sizeof(*z); + w = c + DILITHIUM_N; +#ifndef WC_DILITHIUM_CACHE_PUB_VECTORS + t1 = w + params->s2Sz / sizeof(*w); + t1c = t1; +#else + t1c = w + params->s2Sz / sizeof(*w); +#endif +#ifndef WC_DILITHIUM_CACHE_MATRIX_A + a = t1 + params->s2Sz / sizeof(*t1); #endif + w1e = (byte*)c; + } + } -/* in case user set HAVE_PQC there */ -#include + if (ret == 0) { + /* Step 2: Decode z from signature. */ + dilithium_vec_decode_gamma1(ze, params->l, params->gamma1_bits, z); + /* Step 13: Check z is valid - values are low enough. */ + hi = (1 << params->gamma1_bits) - params->beta; + valid = dilithium_vec_check_low(z, params->l, hi); + } + if ((ret == 0) && valid) { +#ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + /* Check that we haven't already cached the public vector. */ + if (!key->pubVecSet) +#endif + { + /* Step 1: Decode and NTT vector t1. */ + dilithium_make_pub_vec(key, t1); + } -#include +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + /* Check that we haven't already cached the matrix A. */ + if (!key->aSet) +#endif + { + /* Step 5: Expand pub seed to compute matrix A. */ + ret = dilithium_expand_a(&key->shake, pub_seed, params->k, + params->l, a); +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + /* Whether we have cached A is dependent on success of operation. */ + key->aSet = (ret == 0); +#endif + } + } + if ((ret == 0) && valid) { + /* Step 6: Hash public key. */ + ret = dilithium_shake256(&key->shake, key->p, params->pkSz, tr, + DILITHIUM_TR_SZ); + } + if ((ret == 0) && valid) { + /* Step 7: Hash hash of public key and message. */ + ret = dilithium_hash256(&key->shake, tr, DILITHIUM_TR_SZ, msg, msgLen, + mu, DILITHIUM_MU_SZ); + } + if ((ret == 0) && valid) { + /* Step 9: Compute c from first 256 bits of commit. */ + ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, + NULL); + } + if ((ret == 0) && valid) { + /* Step 10: w = NTT-1(A o NTT(z) - NTT(c) o NTT(t1)) */ + dilithium_vec_ntt(z, params->l); + dilithium_matrix_mul(w, a, z, params->k, params->l); + dilithium_ntt_small(c); + dilithium_vec_mul(t1c, c, t1, params->k); + dilithium_vec_sub(w, t1c, params->k); + dilithium_vec_invntt(w, params->k); + /* Step 11: Use hint to give full w1. */ + dilithium_vec_use_hint(w, params->k, params->gamma2, params->omega, h); + /* Step 12: Encode w1. */ + dilithium_vec_encode_w1(w, params->k, params->gamma2, w1e); + /* Step 12: Hash mu and encoded w1. */ + ret = dilithium_hash256(&key->shake, mu, DILITHIUM_MU_SZ, w1e, + params->w1EncSz, commit_calc, 2 * params->lambda); + } + if ((ret == 0) && valid) { + /* Step 13: Compare commit. */ + valid = (XMEMCMP(commit, commit_calc, 2 * params->lambda) == 0); + } -#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) + *res = valid; + XFREE(z, NULL, DYNAMIC_TYPE_DILITHIUM); + return ret; +#else + int ret = 0; + const wc_dilithium_params* params = key->params; + const byte* pub_seed = key->p; + const byte* t1p = pub_seed + DILITHIUM_PUB_SEED_SZ; + const byte* commit = sig; + const byte* ze = sig + params->lambda * 2; + const byte* h = ze + params->zEncSz; + sword32* t1 = NULL; + sword32* a = NULL; + sword32* c = NULL; + sword32* z = NULL; + sword32* w = NULL; + byte tr[DILITHIUM_TR_SZ]; + byte* mu = tr; + byte* w1e = NULL; + byte* commit_calc = tr; + int valid = 0; + sword32 hi; + byte i; + unsigned int j; + byte o; + byte* encW1; + byte* seed = tr; + + /* Ensure the signature is the right size for the parameters. */ + if (sigLen != params->sigSz) { + ret = BUFFER_E; + } + if (ret == 0) { + /* Step 13: Verify the hint is well-formed. */ + ret = dilithium_check_hint(h, params->k, params->omega); + } -#ifdef HAVE_LIBOQS -#include +#ifndef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + /* Allocate memory for large intermediates. */ + if (ret == 0) { + /* z, c, w, t1, w1e. */ + z = (sword32*)XMALLOC(params->s1Sz + 3 * DILITHIUM_POLY_SIZE + + DILITHIUM_MAX_W1_ENC_SZ, NULL, DYNAMIC_TYPE_DILITHIUM); + if (z == NULL) { + ret = MEMORY_E; + } + else { + c = z + params->s1Sz / sizeof(*t1); + w = c + DILITHIUM_N; + t1 = w + DILITHIUM_N; + w1e = (byte*)(t1 + DILITHIUM_N); + a = t1; + } + } +#else + if (ret == 0) { + z = key->z; + c = key->c; + w = key->w; + t1 = key->t1; + w1e = key->w1e; + a = t1; + } #endif -#include -#include -#ifdef NO_INLINE - #include + if (ret == 0) { + /* Step 2: Decode z from signature. */ + dilithium_vec_decode_gamma1(ze, params->l, params->gamma1_bits, z); + /* Step 13: Check z is valid - values are low enough. */ + hi = (1 << params->gamma1_bits) - params->beta; + valid = dilithium_vec_check_low(z, params->l, hi); + } + if ((ret == 0) && valid) { + /* Step 10: NTT(z) */ + dilithium_vec_ntt(z, params->l); + + /* Step 9: Compute c from first 256 bits of commit. */ +#ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, + key->block); #else - #define WOLFSSL_MISC_INCLUDED - #include + ret = dilithium_sample_in_ball(&key->shake, commit, params->tau, c, + NULL); +#endif + } + if ((ret == 0) && valid) { + dilithium_ntt_small(c); + + o = 0; + encW1 = w1e; + + /* Copy the seed into a buffer that has space for s and r. */ + XMEMCPY(seed, pub_seed, DILITHIUM_PUB_SEED_SZ); + /* Step 1: Loop over first dimension of matrix. */ + for (i = 0; (ret == 0) && (i < params->k); i++) { + byte s; + const sword32* zt = z; + + /* Step 1: Decode and NTT vector t1. */ + dilithium_decode_t1(t1p, w); + /* Next polynomial. */ + t1p += DILITHIUM_U * DILITHIUM_N / 8; + + /* Step 10: - NTT(c) o NTT(t1)) */ + dilithium_ntt(w); +#ifdef WOLFSSL_DILITHIUM_SMALL + for (j = 0; j < DILITHIUM_N; j++) { + w[j] = -dilithium_mont_red((sword64)c[j] * w[j]); + } +#else + for (j = 0; j < DILITHIUM_N; j += 8) { + w[j+0] = -dilithium_mont_red((sword64)c[j+0] * w[j+0]); + w[j+1] = -dilithium_mont_red((sword64)c[j+1] * w[j+1]); + w[j+2] = -dilithium_mont_red((sword64)c[j+2] * w[j+2]); + w[j+3] = -dilithium_mont_red((sword64)c[j+3] * w[j+3]); + w[j+4] = -dilithium_mont_red((sword64)c[j+4] * w[j+4]); + w[j+5] = -dilithium_mont_red((sword64)c[j+5] * w[j+5]); + w[j+6] = -dilithium_mont_red((sword64)c[j+6] * w[j+6]); + w[j+7] = -dilithium_mont_red((sword64)c[j+7] * w[j+7]); + } #endif -/* Sign the message using the dilithium private key. - * - * in [in] Message to sign. - * inLen [in] Length of the message in bytes. - * out [in] Buffer to write signature into. - * outLen [in/out] On in, size of buffer. - * On out, the length of the signature in bytes. - * key [in] Dilithium key to use when signing - * returns BAD_FUNC_ARG when a parameter is NULL or public key not set, - * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_SIG_SIZE, - * 0 otherwise. - */ -int wc_dilithium_sign_msg(const byte* in, word32 inLen, - byte* out, word32 *outLen, - dilithium_key* key, WC_RNG* rng) + /* Step 5: Expand pub seed to compute matrix A. */ + /* Put r into buffer to be hashed. */ + seed[DILITHIUM_PUB_SEED_SZ + 1] = i; + for (s = 0; (ret == 0) && (s < params->l); s++) { + /* Put s into buffer to be hashed. */ + seed[DILITHIUM_PUB_SEED_SZ + 0] = s; + /* Step 3: Create polynomial from hashing seed. */ + #ifdef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + ret = dilithium_rej_ntt_poly(&key->shake, seed, a, key->h); + #else + ret = dilithium_rej_ntt_poly(&key->shake, seed, a, NULL); + #endif + + /* Step 10: w = A o NTT(z) - NTT(c) o NTT(t1) */ +#ifdef WOLFSSL_DILITHIUM_SMALL + for (j = 0; j < DILITHIUM_N; j++) { + w[j] += dilithium_mont_red((sword64)a[j] * zt[j]); + } +#else + for (j = 0; j < DILITHIUM_N; j += 8) { + w[j+0] += dilithium_mont_red((sword64)a[j+0] * zt[j+0]); + w[j+1] += dilithium_mont_red((sword64)a[j+1] * zt[j+1]); + w[j+2] += dilithium_mont_red((sword64)a[j+2] * zt[j+2]); + w[j+3] += dilithium_mont_red((sword64)a[j+3] * zt[j+3]); + w[j+4] += dilithium_mont_red((sword64)a[j+4] * zt[j+4]); + w[j+5] += dilithium_mont_red((sword64)a[j+5] * zt[j+5]); + w[j+6] += dilithium_mont_red((sword64)a[j+6] * zt[j+6]); + w[j+7] += dilithium_mont_red((sword64)a[j+7] * zt[j+7]); + } +#endif + /* Next polynomial. */ + zt += DILITHIUM_N; + } + + /* Step 10: w = NTT-1(A o NTT(z) - NTT(c) o NTT(t1)) */ + dilithium_invntt(w); + +#ifndef WOLFSSL_NO_ML_DSA_44 + if (params->gamma2 == DILITHIUM_Q_LOW_88) { + /* Step 11: Use hint to give full w1. */ + dilithium_use_hint_88(w, h, i, &o); + /* Step 12: Encode w1. */ + dilithium_encode_w1_88(w, encW1); + encW1 += DILITHIUM_Q_HI_88_ENC_BITS * 2 * DILITHIUM_N / 16; + } + else +#endif +#if !defined(WOLFSSL_NO_ML_DSA_65) || !defined(WOLFSSL_NO_ML_DSA_87) + if (params->gamma2 == DILITHIUM_Q_LOW_32) { + /* Step 11: Use hint to give full w1. */ + dilithium_use_hint_32(w, h, params->omega, i, &o); + /* Step 12: Encode w1. */ + dilithium_encode_w1_32(w, encW1); + encW1 += DILITHIUM_Q_HI_32_ENC_BITS * 2 * DILITHIUM_N / 16; + } + else +#endif + { + } + } + } + if ((ret == 0) && valid) { + /* Step 6: Hash public key. */ + ret = dilithium_shake256(&key->shake, key->p, params->pkSz, tr, + DILITHIUM_TR_SZ); + } + if ((ret == 0) && valid) { + /* Step 7: Hash hash of public key and message. */ + ret = dilithium_hash256(&key->shake, tr, DILITHIUM_TR_SZ, msg, msgLen, + mu, DILITHIUM_MU_SZ); + } + if ((ret == 0) && valid) { + /* Step 12: Hash mu and encoded w1. */ + ret = dilithium_hash256(&key->shake, mu, DILITHIUM_MU_SZ, w1e, + params->w1EncSz, commit_calc, 2 * params->lambda); + } + if ((ret == 0) && valid) { + /* Step 13: Compare commit. */ + valid = (XMEMCMP(commit, commit_calc, 2 * params->lambda) == 0); + } + + *res = valid; +#ifndef WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC + XFREE(z, NULL, DYNAMIC_TYPE_DILITHIUM); +#endif + return ret; +#endif /* !WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM */ +} + +#endif /* WOLFSSL_DILITHIUM_NO_VERIFY */ + +#elif defined(HAVE_LIBOQS) + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY +static int oqs_dilithium_make_key(dilithium_key* key, WC_RNG* rng) { int ret = 0; + OQS_SIG *oqssig = NULL; - /* sanity check on arguments */ - if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL)) { - return BAD_FUNC_ARG; + if (key->level == 2) { + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_44_ipd); + } + else if (key->level == 3) { + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65_ipd); + } + else if (key->level == 5) { + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_87_ipd); + } + else { + ret = SIG_TYPE_E; } -#ifdef WOLF_CRYPTO_CB - #ifndef WOLF_CRYPTO_CB_FIND - if (key->devId != INVALID_DEVID) - #endif - { - ret = wc_CryptoCb_PqcSign(in, inLen, out, outLen, rng, - WC_PQC_SIG_TYPE_DILITHIUM, key); - if (ret != CRYPTOCB_UNAVAILABLE) - return ret; - /* fall-through when unavailable */ - ret = 0; + if (ret == 0) { + ret = wolfSSL_liboqsRngMutexLock(rng); + if (ret == 0) { + if (OQS_SIG_keypair(oqssig, key->p, key->k) != OQS_SUCCESS) { + ret = BUFFER_E; + } + } + wolfSSL_liboqsRngMutexUnlock(); + } + if (ret == 0) { + key->prvKeySet = 1; + key->pubKeySet = 1; } -#endif -#ifdef HAVE_LIBOQS + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } + + return ret; +} +#endif /* WOLFSSL_DILITHIUM_NO_MAKE_KEY */ + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN +static int oqs_dilithium_sign_msg(const byte* msg, word32 msgLen, byte* sig, + word32 *sigLen, dilithium_key* key, WC_RNG* rng) +{ + int ret = 0; OQS_SIG *oqssig = NULL; size_t localOutLen = 0; - if ((ret == 0) && (!key->prvKeySet)) { + if (!key->prvKeySet) { ret = BAD_FUNC_ARG; } if (ret == 0) { if (key->level == 2) { - oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2); + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_44_ipd); } else if (key->level == 3) { - oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3); + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65_ipd); } else if (key->level == 5) { - oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5); + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_87_ipd); } else { ret = SIG_TYPE_E; @@ -111,19 +6593,19 @@ int wc_dilithium_sign_msg(const byte* in, word32 inLen, /* check and set up out length */ if (ret == 0) { - if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_SIG_SIZE)) { - *outLen = DILITHIUM_LEVEL2_SIG_SIZE; + if ((key->level == 2) && (*sigLen < DILITHIUM_LEVEL2_SIG_SIZE)) { + *sigLen = DILITHIUM_LEVEL2_SIG_SIZE; ret = BUFFER_E; } - else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_SIG_SIZE)) { - *outLen = DILITHIUM_LEVEL3_SIG_SIZE; + else if ((key->level == 3) && (*sigLen < DILITHIUM_LEVEL3_SIG_SIZE)) { + *sigLen = DILITHIUM_LEVEL3_SIG_SIZE; ret = BUFFER_E; } - else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_SIG_SIZE)) { - *outLen = DILITHIUM_LEVEL5_SIG_SIZE; + else if ((key->level == 5) && (*sigLen < DILITHIUM_LEVEL5_SIG_SIZE)) { + *sigLen = DILITHIUM_LEVEL5_SIG_SIZE; ret = BUFFER_E; } - localOutLen = *outLen; + localOutLen = *sigLen; } if (ret == 0) { @@ -131,13 +6613,13 @@ int wc_dilithium_sign_msg(const byte* in, word32 inLen, } if ((ret == 0) && - (OQS_SIG_sign(oqssig, out, &localOutLen, in, inLen, key->k) + (OQS_SIG_sign(oqssig, sig, &localOutLen, msg, msgLen, key->k) == OQS_ERROR)) { ret = BAD_FUNC_ARG; } if (ret == 0) { - *outLen = (word32)localOutLen; + *sigLen = (word32)localOutLen; } wolfSSL_liboqsRngMutexUnlock(); @@ -145,63 +6627,30 @@ int wc_dilithium_sign_msg(const byte* in, word32 inLen, if (oqssig != NULL) { OQS_SIG_free(oqssig); } -#else - ret = NOT_COMPILED_IN; -#endif return ret; } +#endif -/* Verify the message using the dilithium public key. - * - * sig [in] Signature to verify. - * sigLen [in] Size of signature in bytes. - * msg [in] Message to verify. - * msgLen [in] Length of the message in bytes. - * res [out] *res is set to 1 on successful verification. - * key [in] Dilithium key to use to verify. - * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and - * BUFFER_E when sigLen is less than DILITHIUM_LEVEL2_SIG_SIZE, - * 0 otherwise. - */ -int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, - word32 msgLen, int* res, dilithium_key* key) +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY +static int oqs_dilithium_verify_msg(const byte* sig, word32 sigLen, + const byte* msg, word32 msgLen, int* res, dilithium_key* key) { int ret = 0; - - if (key == NULL || sig == NULL || msg == NULL || res == NULL) { - return BAD_FUNC_ARG; - } - -#ifdef WOLF_CRYPTO_CB - #ifndef WOLF_CRYPTO_CB_FIND - if (key->devId != INVALID_DEVID) - #endif - { - ret = wc_CryptoCb_PqcVerify(sig, sigLen, msg, msgLen, res, - WC_PQC_SIG_TYPE_DILITHIUM, key); - if (ret != CRYPTOCB_UNAVAILABLE) - return ret; - /* fall-through when unavailable */ - ret = 0; - } -#endif - -#ifdef HAVE_LIBOQS OQS_SIG *oqssig = NULL; - if ((ret == 0) && (!key->pubKeySet)) { + if (!key->pubKeySet) { ret = BAD_FUNC_ARG; } if (ret == 0) { if (key->level == 2) { - oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_2); + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_44_ipd); } else if (key->level == 3) { - oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_3); + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_65_ipd); } else if (key->level == 5) { - oqssig = OQS_SIG_new(OQS_SIG_alg_dilithium_5); + oqssig = OQS_SIG_new(OQS_SIG_alg_ml_dsa_87_ipd); } else { ret = SIG_TYPE_E; @@ -219,18 +6668,233 @@ int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, } if (ret == 0) { - *res = 1; + *res = 1; + } + + if (oqssig != NULL) { + OQS_SIG_free(oqssig); + } + return ret; +} +#endif /* WOLFSSL_DILITHIUM_NO_VERIFY */ + +#else + #error "No dilithium implementation chosen." +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY +int wc_dilithium_make_key(dilithium_key* key, WC_RNG* rng) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (rng == NULL)) { + ret = BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_MakePqcSignatureKey(rng, + WC_PQC_SIG_TYPE_DILITHIUM, key->level, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + + if (ret == 0) { +#ifdef WOLFSSL_WC_DILITHIUM + /* Check the level or parameters have been set. */ + if (key->params == NULL) { + ret = BAD_STATE_E; + } + else { + /* Make the key. */ + ret = dilithium_make_key(key, rng); + } +#elif defined(HAVE_LIBOQS) + /* Make the key. */ + ret = oqs_dilithium_make_key(key, rng); +#endif + } + + return ret; +} + +int wc_dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (seed == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { +#ifdef WOLFSSL_WC_DILITHIUM + /* Check the level or parameters have been set. */ + if (key->params == NULL) { + ret = BAD_STATE_E; + } + else { + /* Make the key. */ + ret = dilithium_make_key_from_seed(key, seed); + } +#elif defined(HAVE_LIBOQS) + /* Make the key. */ + ret = NOT_COMPILED_IN; +#endif + } + + return ret; +} +#endif + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN +/* Sign the message using the dilithium private key. + * + * msg [in] Message to sign. + * msgLen [in] Length of the message in bytes. + * sig [out] Buffer to write signature into. + * sigLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Dilithium key to use when signing + * returns BAD_FUNC_ARG when a parameter is NULL or public key not set, + * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_SIG_SIZE, + * 0 otherwise. + */ +int wc_dilithium_sign_msg(const byte* msg, word32 msgLen, byte* sig, + word32 *sigLen, dilithium_key* key, WC_RNG* rng) +{ + int ret = 0; + + /* Validate parameters. */ + if ((msg == NULL) || (sig == NULL) || (sigLen == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcSign(msg, msgLen, sig, sigLen, rng, + WC_PQC_SIG_TYPE_DILITHIUM, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + ret = 0; + } + } +#endif + + if (ret == 0) { + /* Sign message. */ + #ifdef WOLFSSL_WC_DILITHIUM + ret = dilithium_sign_msg(key, rng, msg, msgLen, sig, sigLen); + #elif defined(HAVE_LIBOQS) + ret = oqs_dilithium_sign_msg(msg, msgLen, sig, sigLen, key, rng); + #endif + } + + return ret; +} + +/* Sign the message using the dilithium private key. + * + * msg [in] Message to sign. + * msgLen [in] Length of the message in bytes. + * sig [out] Buffer to write signature into. + * sigLen [in/out] On in, size of buffer. + * On out, the length of the signature in bytes. + * key [in] Dilithium key to use when signing + * returns BAD_FUNC_ARG when a parameter is NULL or public key not set, + * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_SIG_SIZE, + * 0 otherwise. + */ +int wc_dilithium_sign_msg_with_seed(const byte* msg, word32 msgLen, byte* sig, + word32 *sigLen, dilithium_key* key, byte* seed) +{ + int ret = 0; + + /* Validate parameters. */ + if ((msg == NULL) || (sig == NULL) || (sigLen == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Sign message. */ + #ifdef WOLFSSL_WC_DILITHIUM + ret = dilithium_sign_msg_with_seed(key, seed, msg, msgLen, sig, sigLen); + #elif defined(HAVE_LIBOQS) + ret = NOT_COMPILED_IN; + (void)msgLen; + (void)seed; + #endif + } + + return ret; +} +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY +/* Verify the message using the dilithium public key. + * + * sig [in] Signature to verify. + * sigLen [in] Size of signature in bytes. + * msg [in] Message to verify. + * msgLen [in] Length of the message in bytes. + * res [out] *res is set to 1 on successful verification. + * key [in] Dilithium key to use to verify. + * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and + * BUFFER_E when sigLen is less than DILITHIUM_LEVEL2_SIG_SIZE, + * 0 otherwise. + */ +int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, dilithium_key* key) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (sig == NULL) || (msg == NULL) || (res == NULL)) { + ret = BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (ret == 0) { + #ifndef WOLF_CRYPTO_CB_FIND + if (key->devId != INVALID_DEVID) + #endif + { + ret = wc_CryptoCb_PqcVerify(sig, sigLen, msg, msgLen, res, + WC_PQC_SIG_TYPE_DILITHIUM, key); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + ret = 0; + } } + #endif - if (oqssig != NULL) { - OQS_SIG_free(oqssig); + if (ret == 0) { + /* Verify message with signature. */ + #ifdef WOLFSSL_WC_DILITHIUM + ret = dilithium_verify_msg(key, msg, msgLen, sig, sigLen, res); + #elif defined(HAVE_LIBOQS) + ret = oqs_dilithium_verify_msg(sig, sigLen, msg, msgLen, res, key); + #endif } -#else - ret = NOT_COMPILED_IN; -#endif return ret; } +#endif /* WOLFSSL_DILITHIUM_NO_VERIFY */ /* Initialize the dilithium private/public key. * @@ -251,73 +6915,85 @@ int wc_dilithium_init(dilithium_key* key) */ int wc_dilithium_init_ex(dilithium_key* key, void* heap, int devId) { + int ret = 0; + + (void)heap; + (void)devId; + + /* Validate parameters. */ if (key == NULL) { - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; } - ForceZero(key, sizeof(*key)); - -#ifdef WOLF_CRYPTO_CB - key->devCtx = NULL; - key->devId = devId; -#endif -#ifdef WOLF_PRIVATE_KEY_ID - key->idLen = 0; - key->labelLen = 0; -#endif + if (ret == 0) { + /* Ensure all fields reset. */ + XMEMSET(key, 0, sizeof(*key)); - (void) heap; - (void) devId; + #ifdef WOLF_CRYPTO_CB + key->devCtx = NULL; + key->devId = devId; + #endif + #ifdef WOLF_PRIVATE_KEY_ID + key->idLen = 0; + key->labelLen = 0; + #endif + } - return 0; + return ret; } #ifdef WOLF_PRIVATE_KEY_ID int wc_dilithium_init_id(dilithium_key* key, const unsigned char* id, int len, - void* heap, int devId) + void* heap, int devId) { int ret = 0; - if (key == NULL) + if (key == NULL) { ret = BAD_FUNC_ARG; - if (ret == 0 && (len < 0 || len > DILITHIUM_MAX_ID_LEN)) + } + if ((ret == 0) && ((len < 0) || (len > DILITHIUM_MAX_ID_LEN))) { ret = BUFFER_E; + } - if (ret == 0) + if (ret == 0) { ret = wc_dilithium_init_ex(key, heap, devId); - if (ret == 0 && id != NULL && len != 0) { + } + if ((ret == 0) && (id != NULL) && (len != 0)) { XMEMCPY(key->id, id, (size_t)len); key->idLen = len; } - /* Set the maxiumum level here */ + /* Set the maximum level here */ wc_dilithium_set_level(key, 5); return ret; } int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, - int devId) + int devId) { int ret = 0; int labelLen = 0; - if (key == NULL || label == NULL) + if ((key == NULL) || (label == NULL)) { ret = BAD_FUNC_ARG; + } if (ret == 0) { labelLen = (int)XSTRLEN(label); - if (labelLen == 0 || labelLen > DILITHIUM_MAX_LABEL_LEN) + if ((labelLen == 0) || (labelLen > DILITHIUM_MAX_LABEL_LEN)) { ret = BUFFER_E; + } } - if (ret == 0) + if (ret == 0) { ret = wc_dilithium_init_ex(key, heap, devId); + } if (ret == 0) { XMEMCPY(key->label, label, (size_t)labelLen); key->labelLen = labelLen; } - /* Set the maxiumum level here */ + /* Set the maximum level here */ wc_dilithium_set_level(key, 5); return ret; @@ -332,18 +7008,49 @@ int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, */ int wc_dilithium_set_level(dilithium_key* key, byte level) { + int ret = 0; + + /* Validate parameters. */ if (key == NULL) { - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (level != 2) && (level != 3) && (level != 5)) { + ret = BAD_FUNC_ARG; } - if (level != 2 && level != 3 && level != 5) { - return BAD_FUNC_ARG; + if (ret == 0) { +#ifdef WOLFSSL_WC_DILITHIUM + /* Get the parameters for level into key. */ + ret = dilithium_get_params(level, &key->params); } + if (ret == 0) { + /* Clear any cached items. */ + #ifdef WC_DILITHIUM_CACHE_MATRIX_A + XFREE(key->a, NULL, WOLFSSL_WC_DILITHIUM); + key->a = NULL; + key->aSet = 0; + #endif + #ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + XFREE(key->s1, NULL, WOLFSSL_WC_DILITHIUM); + key->s1 = NULL; + key->s2 = NULL; + key->t0 = NULL; + key->privVecsSet = 0; + #endif + #ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + XFREE(key->t1, NULL, WOLFSSL_WC_DILITHIUM); + key->t1 = NULL; + key->pubVecSet = 0; + #endif +#endif /* WOLFSSL_WC_DILITHIUM */ - key->level = level; - key->pubKeySet = 0; - key->prvKeySet = 0; - return 0; + /* Store level and indicate public and private key are not set. */ + key->level = level; + key->pubKeySet = 0; + key->prvKeySet = 0; + } + + return ret; } /* Get the level of the dilithium private/public key. @@ -354,16 +7061,23 @@ int wc_dilithium_set_level(dilithium_key* key, byte level) */ int wc_dilithium_get_level(dilithium_key* key, byte* level) { - if (key == NULL || level == NULL) { - return BAD_FUNC_ARG; + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (level == NULL)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (key->level != 2) && (key->level != 3) && + (key->level != 5)) { + ret = BAD_FUNC_ARG; } - if (key->level != 2 && key->level != 3 && key->level != 5) { - return BAD_FUNC_ARG; + if (ret == 0) { + /* Return level. */ + *level = key->level; } - *level = key->level; - return 0; + return ret; } /* Clears the dilithium key data @@ -373,687 +7087,1055 @@ int wc_dilithium_get_level(dilithium_key* key, byte* level) void wc_dilithium_free(dilithium_key* key) { if (key != NULL) { +#ifdef WOLFSSL_WC_DILITHIUM + /* Dispose of cached items. */ + #ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + XFREE(key->t1, NULL, WOLFSSL_WC_DILITHIUM); + #endif + #ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + XFREE(key->s1, NULL, WOLFSSL_WC_DILITHIUM); + #endif + #ifdef WC_DILITHIUM_CACHE_MATRIX_A + XFREE(key->a, NULL, WOLFSSL_WC_DILITHIUM); + #endif + /* Free the SHAKE-128/256 object. */ + wc_Shake256_Free(&key->shake); +#endif + /* Ensure all private data is zeroized. */ ForceZero(key, sizeof(*key)); } } -/* Export the dilithium public key. +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY +/* Returns the size of a dilithium private key. * - * key [in] Dilithium public key. - * out [in] Array to hold public key. - * outLen [in/out] On in, the number of bytes in array. - * On out, the number bytes put into array. - * returns BAD_FUNC_ARG when a parameter is NULL, - * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PUB_KEY_SIZE, - * 0 otherwise. + * @param [in] key Dilithium private/public key. + * @return Private key size on success for set level. + * @return BAD_FUNC_ARG when key is NULL or level not set, */ -int wc_dilithium_export_public(dilithium_key* key, - byte* out, word32* outLen) +int wc_dilithium_size(dilithium_key* key) { - /* sanity check on arguments */ - if ((key == NULL) || (out == NULL) || (outLen == NULL)) { - return BAD_FUNC_ARG; - } + int ret = BAD_FUNC_ARG; - if ((key->level != 1) && (key->level != 5)) { - return BAD_FUNC_ARG; + if (key != NULL) { + if (key->level == 2) { + ret = DILITHIUM_LEVEL2_KEY_SIZE; + } + else if (key->level == 3) { + ret = DILITHIUM_LEVEL3_KEY_SIZE; + } + else if (key->level == 5) { + ret = DILITHIUM_LEVEL5_KEY_SIZE; + } } - if (!key->pubKeySet) { - return BAD_FUNC_ARG; - } + return ret; +} - /* check and set up out length */ - if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_PUB_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; - return BUFFER_E; - } - else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_PUB_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; - return BUFFER_E; - } - else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; - return BUFFER_E; - } +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY +/* Returns the size of a dilithium private plus public key. + * + * @param [in] key Dilithium private/public key. + * @return Private key size on success for set level. + * @return BAD_FUNC_ARG when key is NULL or level not set, + */ +int wc_dilithium_priv_size(dilithium_key* key) +{ + int ret = BAD_FUNC_ARG; - if (key->level == 2) { - *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; - XMEMCPY(out, key->p, DILITHIUM_LEVEL2_PUB_KEY_SIZE); - } - else if (key->level == 3) { - *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; - XMEMCPY(out, key->p, DILITHIUM_LEVEL3_PUB_KEY_SIZE); - } - else if (key->level == 5) { - *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; - XMEMCPY(out, key->p, DILITHIUM_LEVEL5_PUB_KEY_SIZE); + if (key != NULL) { + if (key->level == 2) { + ret = DILITHIUM_LEVEL2_PRV_KEY_SIZE; + } + else if (key->level == 3) { + ret = DILITHIUM_LEVEL3_PRV_KEY_SIZE; + } + else if (key->level == 5) { + ret = DILITHIUM_LEVEL5_PRV_KEY_SIZE; + } } - return 0; + return ret; } -/* Import a dilithium public key from a byte array. - * Public key encoded in big-endian. +/* Returns the size of a dilithium private plus public key. * - * in [in] Array holding public key. - * inLen [in] Number of bytes of data in array. - * key [in] Dilithium public key. - * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported, - * 0 otherwise. + * @param [in] key Dilithium private/public key. + * @param [out] len Private key size for set level. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL or level not set, */ -int wc_dilithium_import_public(const byte* in, word32 inLen, - dilithium_key* key) +int wc_MlDsaKey_GetPrivLen(MlDsaKey* key, int* len) { - /* sanity check on arguments */ - if ((in == NULL) || (key == NULL)) { - return BAD_FUNC_ARG; - } - - if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { - return BAD_FUNC_ARG; - } + int ret = 0; - if ((key->level == 2) && (inLen != DILITHIUM_LEVEL2_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; - } - else if ((key->level == 3) && (inLen != DILITHIUM_LEVEL3_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; + *len = wc_dilithium_priv_size(key); + if (*len < 0) { + ret = *len; } - else if ((key->level == 5) && (inLen != DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; - } - - XMEMCPY(key->p, in, inLen); - key->pubKeySet = 1; - return 0; + return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ -static int parse_private_key(const byte* priv, word32 privSz, - byte** out, word32 *outSz, - dilithium_key* key) { - word32 idx = 0; - int ret = 0; - int length = 0; +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY +/* Returns the size of a dilithium public key. + * + * @param [in] key Dilithium private/public key. + * @return Public key size on success for set level. + * @return BAD_FUNC_ARG when key is NULL or level not set, + */ +int wc_dilithium_pub_size(dilithium_key* key) +{ + int ret = BAD_FUNC_ARG; - /* sanity check on arguments */ - if ((priv == NULL) || (key == NULL)) { - return BAD_FUNC_ARG; + if (key != NULL) { + if (key->level == 2) { + ret = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + } + else if (key->level == 3) { + ret = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + } + else if (key->level == 5) { + ret = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + } } - if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { - return BAD_FUNC_ARG; - } + return ret; +} - /* At this point, it is still a PKCS8 private key. */ - if ((ret = ToTraditionalInline(priv, &idx, privSz)) < 0) { - return ret; - } +/* Returns the size of a dilithium public key. + * + * @param [in] key Dilithium private/public key. + * @param [out] len Public key size for set level. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL or level not set, + */ +int wc_MlDsaKey_GetPubLen(MlDsaKey* key, int* len) +{ + int ret = 0; - /* Now it is a octet_string(concat(priv,pub)) */ - if ((ret = GetOctetString(priv, &idx, &length, privSz)) < 0) { - return ret; + *len = wc_dilithium_pub_size(key); + if (*len < 0) { + ret = *len; } - *out = (byte *)priv + idx; - *outSz = privSz - idx; + return ret; +} +#endif - /* And finally it is concat(priv,pub). Key size check. */ - if ((key->level == 2) && (*outSz != DILITHIUM_LEVEL2_KEY_SIZE + - DILITHIUM_LEVEL2_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; - } - else if ((key->level == 3) && (*outSz != DILITHIUM_LEVEL3_KEY_SIZE + - DILITHIUM_LEVEL3_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; - } - else if ((key->level == 5) && (*outSz != DILITHIUM_LEVEL5_KEY_SIZE + - DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) +/* Returns the size of a dilithium signature. + * + * @param [in] key Dilithium private/public key. + * @return Signature size on success for set level. + * @return BAD_FUNC_ARG when key is NULL or level not set, + */ +int wc_dilithium_sig_size(dilithium_key* key) +{ + int ret = BAD_FUNC_ARG; + + if (key != NULL) { + if (key->level == 2) { + ret = DILITHIUM_LEVEL2_SIG_SIZE; + } + else if (key->level == 3) { + ret = DILITHIUM_LEVEL3_SIG_SIZE; + } + else if (key->level == 5) { + ret = DILITHIUM_LEVEL5_SIG_SIZE; + } } - return 0; + return ret; } -/* Import a dilithium private key from a byte array. +/* Returns the size of a dilithium signature. * - * priv [in] Array holding private key. - * privSz [in] Number of bytes of data in array. - * key [in] Dilithium private key. - * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than - * DILITHIUM_LEVEL2_KEY_SIZE, - * 0 otherwise. + * @param [in] key Dilithium private/public key. + * @param [out] len Signature size for set level. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL or level not set, */ -int wc_dilithium_import_private_only(const byte* priv, word32 privSz, - dilithium_key* key) +int wc_MlDsaKey_GetSigLen(MlDsaKey* key, int* len) { int ret = 0; - byte *newPriv = NULL; - word32 newPrivSz = 0; - if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key)) - != 0) { - return ret; + *len = wc_dilithium_sig_size(key); + if (*len < 0) { + ret = *len; } - XMEMCPY(key->k, newPriv, newPrivSz); - key->prvKeySet = 1; - - return 0; + return ret; } +#endif -/* Import a dilithium private and public keys from byte array(s). +#ifdef WOLFSSL_DILITHIUM_CHECK_KEY +/* Check the public key of the dilithium key matches the private key. * - * priv [in] Array holding private key or private+public keys - * privSz [in] Number of bytes of data in private key array. - * pub [in] Array holding public key (or NULL). - * pubSz [in] Number of bytes of data in public key array (or 0). - * key [in] Dilithium private/public key. - * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid - * combination of keys/lengths is supplied, 0 otherwise. + * @param [in] key Dilithium private/public key. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL or no private key available, + * @return PUBLIC_KEY_E when the public key is not set or doesn't match, + * @return MEMORY_E when dynamic memory allocation fails. */ -int wc_dilithium_import_private_key(const byte* priv, word32 privSz, - const byte* pub, word32 pubSz, - dilithium_key* key) +int wc_dilithium_check_key(dilithium_key* key) { int ret = 0; - byte *newPriv = NULL; - word32 newPrivSz = 0; +#ifdef WOLFSSL_WC_DILITHIUM + const wc_dilithium_params* params; + sword32* a = NULL; + sword32* s1 = NULL; + sword32* s2 = NULL; + sword32* t = NULL; + sword32* t0 = NULL; + sword32* t1 = NULL; + + /* Validate parameter. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (!key->prvKeySet)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (!key->pubKeySet)) { + ret = PUBLIC_KEY_E; + } + + /* Any value in public key are valid. + * Public seed is hashed to generate matrix A. + * t1 is the top 10 bits of a number in range of 0..(Q-1). + * Q >> 13 = 0x3ff so all encoded values are valid. + */ + + if (ret == 0) { + params = key->params; + unsigned int allocSz; + + /* s1-L, s2-K, t0-K, t-K, t1-K */ + allocSz = params->s1Sz + 4 * params->s2Sz; +#if !defined(WC_DILITHIUM_CACHE_MATRIX_A) + /* A-KxL */ + allocSz += params->aSz; +#endif + + /* Allocate memory for large intermediates. */ + s1 = (sword32*)XMALLOC(allocSz, NULL, DYNAMIC_TYPE_DILITHIUM); + if (s1 == NULL) { + ret = MEMORY_E; + } + else { + s2 = s1 + params->s1Sz / sizeof(*s1); + t0 = s2 + params->s2Sz / sizeof(*s2); + t = t0 + params->s2Sz / sizeof(*t0); + t1 = t + params->s2Sz / sizeof(*t); +#if !defined(WC_DILITHIUM_CACHE_MATRIX_A) + a = t1 + params->s2Sz / sizeof(*t1); +#else + a = key->a; +#endif + } + } + + if (ret == 0) { +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + /* Check that we haven't already cached the matrix A. */ + if (!key->aSet) +#endif + { + const byte* pub_seed = key->p; + + ret = dilithium_expand_a(&key->shake, pub_seed, params->k, + params->l, a); +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + key->aSet = (ret == 0); +#endif + } + } + if (ret == 0) { + const byte* s1p = key->k + DILITHIUM_PUB_SEED_SZ + DILITHIUM_K_SZ + + DILITHIUM_TR_SZ; + const byte* s2p = s1p + params->s1EncSz; + const byte* t0p = s2p + params->s2EncSz; + const byte* t1p = key->p + DILITHIUM_PUB_SEED_SZ; + sword32* tt = t; + unsigned int i; + unsigned int j; + sword32 x = 0; + + /* Get s1, s2 and t0 from private key. */ + dilithium_vec_decode_eta_bits(s1p, params->eta, s1, params->l); + dilithium_vec_decode_eta_bits(s2p, params->eta, s2, params->k); + dilithium_vec_decode_t0(t0p, params->k, t0); + + /* Get t1 from public key. */ + dilithium_vec_decode_t1(t1p, params->k, t1); + + /* Calcaluate t = NTT-1(A o NTT(s1)) + s2 */ + dilithium_vec_ntt_small(s1, params->l); + dilithium_matrix_mul(t, a, s1, params->k, params->l); + dilithium_vec_invntt(t, params->k); + dilithium_vec_add(t, s2, params->k); + /* Subtract t0 from t. */ + dilithium_vec_sub(t, t0, params->k); + /* Make t positive to match t1. */ + dilithium_vec_make_pos(t, params->k); + + /* Check t - t0 and t1 are the same. */ + for (i = 0; i < params->k; i++) { + for (j = 0; j < DILITHIUM_N; j++) { + x |= tt[j] ^ t1[j]; + } + tt += DILITHIUM_N; + t1 += DILITHIUM_N; + } + /* Check the public seed is the same in private and public key. */ + for (i = 0; i < DILITHIUM_PUB_SEED_SZ; i++) { + x |= key->p[i] ^ key->k[i]; + } - if ((ret = parse_private_key(priv, privSz, &newPriv, &newPrivSz, key)) - != 0) { - return ret; + if ((ret == 0) && (x != 0)) { + ret = PUBLIC_KEY_E; + } + } + + /* Dispose of allocated memory. */ + XFREE(s1, NULL, DYNAMIC_TYPE_DILITHIUM); +#else + /* Validate parameter. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (!key->prvKeySet)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (!key->pubKeySet)) { + ret = PUBLIC_KEY_E; } - if (pub == NULL) { - if (pubSz != 0) { - return BAD_FUNC_ARG; + if (ret == 0) { + int i; + sword32 x = 0; + + /* Check the public seed is the same in private and public key. */ + for (i = 0; i < 32; i++) { + x |= key->p[i] ^ key->k[i]; } - if ((newPrivSz != DILITHIUM_LEVEL2_PRV_KEY_SIZE) && - (newPrivSz != DILITHIUM_LEVEL3_PRV_KEY_SIZE) && - (newPrivSz != DILITHIUM_LEVEL5_PRV_KEY_SIZE)) { - return BAD_FUNC_ARG; + if (x != 0) { + ret = PUBLIC_KEY_E; } + } +#endif /* WOLFSSL_WC_DILITHIUM */ + return ret; +} +#endif /* WOLFSSL_DILITHIUM_CHECK_KEY */ + +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY + +/* Export the dilithium public key. + * + * @param [in] key Dilithium public key. + * @param [out] out Array to hold public key. + * @param [in, out] outLen On in, the number of bytes in array. + * On out, the number bytes put into array. + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PUB_KEY_SIZE. + */ +int wc_dilithium_export_public(dilithium_key* key, byte* out, word32* outLen) +{ + int ret = 0; + word32 inLen; + /* Validate parameters */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + /* Get length passed in for checking. */ + inLen = *outLen; if (key->level == 2) { - pub = newPriv + DILITHIUM_LEVEL2_KEY_SIZE; - pubSz = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + /* Set out length. */ + *outLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + /* Validate length passed in. */ + if (inLen < DILITHIUM_LEVEL2_PUB_KEY_SIZE) { + ret = BUFFER_E; + } } else if (key->level == 3) { - pub = newPriv + DILITHIUM_LEVEL3_KEY_SIZE; - pubSz = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + /* Set out length. */ + *outLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + /* Validate length passed in. */ + if (inLen < DILITHIUM_LEVEL3_PUB_KEY_SIZE) { + ret = BUFFER_E; + } } else if (key->level == 5) { - pub = newPriv + DILITHIUM_LEVEL5_KEY_SIZE; - pubSz = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + /* Set out length. */ + *outLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + /* Validate length passed in. */ + if (inLen < DILITHIUM_LEVEL5_PUB_KEY_SIZE) { + ret = BUFFER_E; + } + } + else { + /* Level not set. */ + ret = BAD_FUNC_ARG; } - } - else if ((pubSz != DILITHIUM_LEVEL2_PUB_KEY_SIZE) && - (pubSz != DILITHIUM_LEVEL3_PUB_KEY_SIZE) && - (pubSz != DILITHIUM_LEVEL5_PUB_KEY_SIZE)) { - return BAD_FUNC_ARG; } - /* import public key */ - ret = wc_dilithium_import_public(pub, pubSz, key); + /* Check public key available. */ + if ((ret == 0) && (!key->pubKeySet)) { + ret = BAD_FUNC_ARG; + } if (ret == 0) { - /* make the private key (priv + pub) */ - XMEMCPY(key->k, newPriv, newPrivSz); - key->prvKeySet = 1; + /* Copy public key out. */ + XMEMCPY(out, key->p, *outLen); } return ret; } -/* Export the dilithium private key. +/* Import a dilithium public key from a byte array. + * + * Public key encoded in big-endian. * - * key [in] Dilithium private key. - * out [in] Array to hold private key. - * outLen [in/out] On in, the number of bytes in array. - * On out, the number bytes put into array. - * returns BAD_FUNC_ARG when a parameter is NULL, - * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_KEY_SIZE, - * 0 otherwise. + * @param [in] in Array holding public key. + * @param [in] inLen Number of bytes of data in array. + * @param [in, out] key Dilithium public key. + * @return 0 on success. + * @return BAD_FUNC_ARG when in or key is NULL or key format is not supported. */ -int wc_dilithium_export_private_only(dilithium_key* key, byte* out, - word32* outLen) +int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key) { - /* sanity checks on arguments */ - if ((key == NULL) || (out == NULL) || (outLen == NULL)) { - return BAD_FUNC_ARG; - } - - if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { - return BAD_FUNC_ARG; - } + int ret = 0; - /* check and set up out length */ - if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL2_KEY_SIZE; - return BUFFER_E; - } - else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL3_KEY_SIZE; - return BUFFER_E; + /* Validate parameters. */ + if ((in == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; } - else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL5_KEY_SIZE; - return BUFFER_E; + if (ret == 0) { + if (key->level == 2) { + /* Check length. */ + if (inLen != DILITHIUM_LEVEL2_PUB_KEY_SIZE) { + ret = BAD_FUNC_ARG; + } + } + else if (key->level == 3) { + /* Check length. */ + if (inLen != DILITHIUM_LEVEL3_PUB_KEY_SIZE) { + ret = BAD_FUNC_ARG; + } + } + else if (key->level == 5) { + /* Check length. */ + if (inLen != DILITHIUM_LEVEL5_PUB_KEY_SIZE) { + ret = BAD_FUNC_ARG; + } + } + else { + /* Level not set. */ + ret = BAD_FUNC_ARG; + } } - if (key->level == 2) { - *outLen = DILITHIUM_LEVEL2_KEY_SIZE; + if (ret == 0) { + /* Copy the private key data in or copy pointer. */ + #ifndef WOLFSSL_DILITHIUM_ASSIGN_KEY + XMEMCPY(key->p, in, inLen); + #else + key->p = in; + #endif + + #ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + /* Allocate t1 if required. */ + if (key->t1 == NULL) { + key->t1 = (sword32*)XMALLOC(key->params->s2Sz, NULL, + DYNAMIC_TYPE_DILITHIUM); + if (key->t1 == NULL) { + ret = MEMORY_E; + } + } } - else if (key->level == 3) { - *outLen = DILITHIUM_LEVEL3_KEY_SIZE; + if (ret == 0) { + /* Compute t1 from public key data. */ + dilithium_make_pub_vec(key, key->t1); + #endif + #ifdef WC_DILITHIUM_CACHE_MATRIX_A + /* Allocate matrix a if required. */ + if (key->a == NULL) { + key->a = (sword32*)XMALLOC(key->params->aSz, NULL, + DYNAMIC_TYPE_DILITHIUM); + if (key->a == NULL) { + ret = MEMORY_E; + } + } } - else if (key->level == 5) { - *outLen = DILITHIUM_LEVEL5_KEY_SIZE; + if (ret == 0) { + /* Compute matrix a from public key data. */ + ret = dilithium_expand_a(&key->shake, key->p, key->params->k, + key->params->l, key->a); + if (ret == 0) { + key->aSet = 1; + } + } + if (ret == 0) { + #endif + /* Public key is set. */ + key->pubKeySet = 1; } - XMEMCPY(out, key->k, *outLen); - - return 0; + return ret; } -/* Export the dilithium private and public key. +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ + +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + +/* Set the private key data into key. * - * key [in] Dilithium private/public key. - * out [in] Array to hold private and public key. - * outLen [in/out] On in, the number of bytes in array. - * On out, the number bytes put into array. - * returns BAD_FUNC_ARG when a parameter is NULL, - * BUFFER_E when outLen is less than DILITHIUM_LEVEL2_PRV_KEY_SIZE, - * 0 otherwise. + * @param [in] priv Private key data. + * @param [in] privSz Size of private key data in bytes. + * @param in, out] key Dilithium key to set into. + * @return 0 on success. + * @return BAD_FUNC_ARG when private key size is invalid. + * @return MEMORY_E when dynamic memory allocation fails. + * @return Other negative on hash error. */ -int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen) +static int dilithium_set_priv_key(const byte* priv, word32 privSz, + dilithium_key* key) { - /* sanity checks on arguments */ - if ((key == NULL) || (out == NULL) || (outLen == NULL)) { - return BAD_FUNC_ARG; + int ret = 0; +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + const wc_dilithium_params* params = key->params; +#endif + + /* Validate parameters. */ + if ((privSz != DILITHIUM_LEVEL2_KEY_SIZE) && + (privSz != DILITHIUM_LEVEL3_KEY_SIZE) && + (privSz != DILITHIUM_LEVEL5_KEY_SIZE)) { + ret = BAD_FUNC_ARG; } - if ((key->level != 2) && (key->level != 3) && (key->level != 5)) { - return BAD_FUNC_ARG; + if (ret == 0) { + /* Copy the private key data in or copy pointer. */ + #ifndef WOLFSSL_DILITHIUM_ASSIGN_KEY + XMEMCPY(key->k, priv, privSz); + #else + key->k = priv; + #endif } - if ((key->level == 2) && (*outLen < DILITHIUM_LEVEL2_PRV_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE; - return BUFFER_E; + /* Allocate and create cached values. */ +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + if (ret == 0) { + /* Allocate matrix a if required. */ + if (key->a == NULL) { + key->a = (sword32*)XMALLOC(params->aSz, NULL, + DYNAMIC_TYPE_DILITHIUM); + if (key->a == NULL) { + ret = MEMORY_E; + } + } } - else if ((key->level == 3) && (*outLen < DILITHIUM_LEVEL3_PRV_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE; - return BUFFER_E; + if (ret == 0) { + /* Compute matrix a from private key data. */ + ret = dilithium_expand_a(&key->shake, key->k, params->k, params->l, + key->a); + if (ret == 0) { + key->aSet = 1; + } } - else if ((key->level == 5) && (*outLen < DILITHIUM_LEVEL5_PRV_KEY_SIZE)) { - *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE; - return BUFFER_E; +#endif +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + if ((ret == 0) && (key->s1 == NULL)) { + /* Allocate L vector s1, K vector s2 and K vector t0 if required. */ + key->s1 = (sword32*)XMALLOC(params->s1Sz + params->s2Sz + params->s2Sz, + NULL, DYNAMIC_TYPE_DILITHIUM); + if (key->s1 == NULL) { + ret = MEMORY_E; + } } + if (ret == 0) { + /* Set pointers into allocated memory. */ + key->s2 = key->s1 + params->s1Sz / sizeof(*key->s1); + key->t0 = key->s2 + params->s2Sz / sizeof(*key->s2); - - if (key->level == 2) { - *outLen = DILITHIUM_LEVEL2_PRV_KEY_SIZE; - XMEMCPY(out, key->k, DILITHIUM_LEVEL2_KEY_SIZE); - XMEMCPY(out + DILITHIUM_LEVEL2_KEY_SIZE, key->p, - DILITHIUM_LEVEL2_PUB_KEY_SIZE); - } - else if (key->level == 3) { - *outLen = DILITHIUM_LEVEL3_PRV_KEY_SIZE; - XMEMCPY(out, key->k, DILITHIUM_LEVEL3_KEY_SIZE); - XMEMCPY(out + DILITHIUM_LEVEL3_KEY_SIZE, key->p, - DILITHIUM_LEVEL3_PUB_KEY_SIZE); + /* Compute vectors from private key. */ + dilithium_make_priv_vecs(key, key->s1, key->s2, key->t0); } - else if (key->level == 5) { - *outLen = DILITHIUM_LEVEL5_PRV_KEY_SIZE; - XMEMCPY(out, key->k, DILITHIUM_LEVEL5_KEY_SIZE); - XMEMCPY(out + DILITHIUM_LEVEL5_KEY_SIZE, key->p, - DILITHIUM_LEVEL5_PUB_KEY_SIZE); +#endif + if (ret == 0) { + /* Private key is set. */ + key->prvKeySet = 1; } - return 0; + return ret; } -/* Export the dilithium private and public key. +/* Import a dilithium private key from a byte array. * - * key [in] Dilithium private/public key. - * priv [in] Array to hold private key. - * privSz [in/out] On in, the number of bytes in private key array. - * pub [in] Array to hold public key. - * pubSz [in/out] On in, the number of bytes in public key array. - * On out, the number bytes put into array. - * returns BAD_FUNC_ARG when a parameter is NULL, - * BUFFER_E when privSz is less than DILITHIUM_LEVEL2_PRV_KEY_SIZE or pubSz is less - * than DILITHIUM_LEVEL2_PUB_KEY_SIZE, - * 0 otherwise. + * @param [in] priv Array holding private key. + * @param [in] privSz Number of bytes of data in array. + * @param [in, out] key Dilithium private key. + * @return 0 otherwise. + * @return BAD_FUNC_ARG when a parameter is NULL or privSz is less than size + * required for level, */ -int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, - byte* pub, word32 *pubSz) +int wc_dilithium_import_private(const byte* priv, word32 privSz, + dilithium_key* key) { int ret = 0; - /* export private part */ - ret = wc_dilithium_export_private(key, priv, privSz); + /* Validate parameters. */ + if ((priv == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (key->level != 2) && (key->level != 3) && + (key->level != 5)) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { - /* export public part */ - ret = wc_dilithium_export_public(key, pub, pubSz); + /* Set the private key data. */ + ret = dilithium_set_priv_key(priv, privSz, key); } return ret; } -/* Check the public key of the dilithium key matches the private key. +#if defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) +/* Import a dilithium private and public keys from byte array(s). * - * key [in] Dilithium private/public key. - * returns BAD_FUNC_ARG when key is NULL, - * PUBLIC_KEY_E when the public key is not set or doesn't match, - * other -ve value on hash failure, - * 0 otherwise. + * @param [in] priv Array holding private key or private+public keys + * @param [in] privSz Number of bytes of data in private key array. + * @param [in] pub Array holding public key (or NULL). + * @param [in] pubSz Number of bytes of data in public key array (or 0). + * @param [in] key Dilithium private/public key. + * @return 0 on success. + * @return BAD_FUNC_ARG when a required parameter is NULL an invalid + * combination of keys/lengths is supplied. */ -int wc_dilithium_check_key(dilithium_key* key) +int wc_dilithium_import_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, dilithium_key* key) { - if (key == NULL) { - return BAD_FUNC_ARG; - } - int ret = 0; - /* The public key is also decoded and stored within the private key buffer - * behind the private key. Hence, we can compare both stored public keys. */ - if (key->level == 2) { - ret = XMEMCMP(key->p, key->k + DILITHIUM_LEVEL2_KEY_SIZE, - DILITHIUM_LEVEL2_PUB_KEY_SIZE); + /* Validate parameters. */ + if ((priv == NULL) || (key == NULL)) { + ret = BAD_FUNC_ARG; } - else if (key->level == 3) { - ret = XMEMCMP(key->p, key->k + DILITHIUM_LEVEL3_KEY_SIZE, - DILITHIUM_LEVEL3_PUB_KEY_SIZE); + if ((pub == NULL) && (pubSz != 0)) { + ret = BAD_FUNC_ARG; } - else if (key->level == 5) { - ret = XMEMCMP(key->p, key->k + DILITHIUM_LEVEL5_KEY_SIZE, - DILITHIUM_LEVEL5_PUB_KEY_SIZE); + if ((ret == 0) && (key->level != 2) && (key->level != 3) && + (key->level != 5)) { + ret = BAD_FUNC_ARG; } - if (ret != 0) { - ret = PUBLIC_KEY_E; + if ((ret == 0) && (pub != NULL)) { + /* Import public key. */ + ret = wc_dilithium_import_public(pub, pubSz, key); + } + if (ret == 0) { + ret = dilithium_set_priv_key(priv, privSz, key); } return ret; - } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ -/* Returns the size of a dilithium private key. +/* Export the dilithium private key. * - * key [in] Dilithium private/public key. - * returns BAD_FUNC_ARG when key is NULL, - * DILITHIUM_LEVEL2_KEY_SIZE otherwise. + * @param [in] key Dilithium private key. + * @param [out] out Array to hold private key. + * @param [in, out] outLen On in, the number of bytes in array. + * On out, the number bytes put into array. + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BUFFER_E when outLen is less than DILITHIUM_LEVEL2_KEY_SIZE. */ -int wc_dilithium_size(dilithium_key* key) +int wc_dilithium_export_private(dilithium_key* key, byte* out, + word32* outLen) { - if (key == NULL) { - return BAD_FUNC_ARG; - } + int ret = 0; + word32 inLen; - if (key->level == 2) { - return DILITHIUM_LEVEL2_KEY_SIZE; - } - else if (key->level == 3) { - return DILITHIUM_LEVEL3_KEY_SIZE; - } - else if (key->level == 5) { - return DILITHIUM_LEVEL5_KEY_SIZE; + /* Validate parameters. */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; } - return BAD_FUNC_ARG; -} - -/* Returns the size of a dilithium private plus public key. - * - * key [in] Dilithium private/public key. - * returns BAD_FUNC_ARG when key is NULL, - * DILITHIUM_LEVEL2_PRV_KEY_SIZE otherwise. - */ -int wc_dilithium_priv_size(dilithium_key* key) -{ - if (key == NULL) { - return BAD_FUNC_ARG; + /* Check private key available. */ + if ((ret == 0) && (!key->prvKeySet)) { + ret = BAD_FUNC_ARG; } - if (key->level == 2) { - return DILITHIUM_LEVEL2_PRV_KEY_SIZE; + if (ret == 0) { + inLen = *outLen; + /* check and set up out length */ + if (key->level == 2) { + *outLen = DILITHIUM_LEVEL2_KEY_SIZE; + } + else if (key->level == 3) { + *outLen = DILITHIUM_LEVEL3_KEY_SIZE; + } + else if (key->level == 5) { + *outLen = DILITHIUM_LEVEL5_KEY_SIZE; + } + else { + /* Level not set. */ + ret = BAD_FUNC_ARG; + } } - else if (key->level == 3) { - return DILITHIUM_LEVEL3_PRV_KEY_SIZE; + + /* Check array length. */ + if ((ret == 0) && (inLen < *outLen)) { + ret = BUFFER_E; } - else if (key->level == 5) { - return DILITHIUM_LEVEL5_PRV_KEY_SIZE; + + if (ret == 0) { + /* Copy private key out key. */ + XMEMCPY(out, key->k, *outLen); } - return BAD_FUNC_ARG; + return ret; } -/* Returns the size of a dilithium public key. +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY +/* Export the dilithium private and public key. * - * key [in] Dilithium private/public key. - * returns BAD_FUNC_ARG when key is NULL, - * DILITHIUM_LEVEL2_PUB_KEY_SIZE otherwise. + * @param [in] key Dilithium private/public key. + * @param [out] priv Array to hold private key. + * @param [in, out] privSz On in, the number of bytes in private key array. + * On out, the number bytes put into private key. + * @param [out] pub Array to hold public key. + * @param [in, out] pubSz On in, the number of bytes in public key array. + * On out, the number bytes put into public key. + * @return 0 on success. + * @return BAD_FUNC_ARG when a key, priv, privSz, pub or pubSz is NULL. + * @return BUFFER_E when privSz or pubSz is less than required size. */ -int wc_dilithium_pub_size(dilithium_key* key) +int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) { - if (key == NULL) { - return BAD_FUNC_ARG; - } + int ret; - if (key->level == 2) { - return DILITHIUM_LEVEL2_PUB_KEY_SIZE; - } - else if (key->level == 3) { - return DILITHIUM_LEVEL3_PUB_KEY_SIZE; - } - else if (key->level == 5) { - return DILITHIUM_LEVEL5_PUB_KEY_SIZE; + /* Export private key only. */ + ret = wc_dilithium_export_private(key, priv, privSz); + if (ret == 0) { + /* Export public key. */ + ret = wc_dilithium_export_public(key, pub, pubSz); } - return BAD_FUNC_ARG; + return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ -/* Returns the size of a dilithium signature. - * - * key [in] Dilithium private/public key. - * returns BAD_FUNC_ARG when key is NULL, - * DILITHIUM_LEVEL2_SIG_SIZE otherwise. - */ -int wc_dilithium_sig_size(dilithium_key* key) -{ - if (key == NULL) { - return BAD_FUNC_ARG; - } +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ - if (key->level == 2) { - return DILITHIUM_LEVEL2_SIG_SIZE; - } - else if (key->level == 3) { - return DILITHIUM_LEVEL3_SIG_SIZE; - } - else if (key->level == 5) { - return DILITHIUM_LEVEL5_SIG_SIZE; - } +#ifndef WOLFSSL_DILITHIUM_NO_ASN1 - return BAD_FUNC_ARG; -} +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) +/* Decode the DER encoded Dilithium key. + * + * @param [in] input Array holding DER encoded data. + * @param [in, out] inOutIdx On in, index into array of start of DER encoding. + * On out, index into array after DER encoding. + * @param [in, out] key Dilithium key to store key. + * @param [in] inSz Total size of data in array. + * @return 0 on success. + * @return BAD_FUNC_ARG when input, inOutIdx or key is NULL or inSz is 0. + * @return BAD_FUNC_ARG when level not set. + * @return Other negative on parse error. + */ int wc_Dilithium_PrivateKeyDecode(const byte* input, word32* inOutIdx, - dilithium_key* key, word32 inSz) + dilithium_key* key, word32 inSz) { int ret = 0; - byte privKey[DILITHIUM_MAX_PRV_KEY_SIZE]; - byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; - word32 privKeyLen = (word32)sizeof(privKey); - word32 pubKeyLen = (word32)sizeof(pubKey); + const byte* privKey = NULL; + const byte* pubKey = NULL; + word32 privKeyLen = 0; + word32 pubKeyLen = 0; int keytype = 0; - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { - return BAD_FUNC_ARG; + /* Validate parameters. */ + if ((input == NULL) || (inOutIdx == NULL) || (key == NULL) || (inSz == 0)) { + ret = BAD_FUNC_ARG; } - if (key->level == 2) { - keytype = DILITHIUM_LEVEL2k; - } - else if (key->level == 3) { - keytype = DILITHIUM_LEVEL3k; + if (ret == 0) { + /* Get OID sum for level. */ + if (key->level == 2) { + keytype = DILITHIUM_LEVEL2k; + } + else if (key->level == 3) { + keytype = DILITHIUM_LEVEL3k; + } + else if (key->level == 5) { + keytype = DILITHIUM_LEVEL5k; + } + else { + /* Level not set. */ + ret = BAD_FUNC_ARG; + } } - else if (key->level == 5) { - keytype = DILITHIUM_LEVEL5k; + + if (ret == 0) { + /* Decode the asymmetric key and get out private and public key data. */ + ret = DecodeAsymKey_Assign(input, inOutIdx, inSz, &privKey, &privKeyLen, + &pubKey, &pubKeyLen, keytype); } - else { - return BAD_FUNC_ARG; + if ((ret == 0) && (pubKey == NULL) && (pubKeyLen == 0)) { + /* Check if the public key is included in the private key. */ + if ((key->level == 2) && + (privKeyLen == DILITHIUM_LEVEL2_PRV_KEY_SIZE)) { + pubKey = privKey + DILITHIUM_LEVEL2_KEY_SIZE; + pubKeyLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + privKeyLen -= DILITHIUM_LEVEL2_PUB_KEY_SIZE; + } + else if ((key->level == 3) && + (privKeyLen == DILITHIUM_LEVEL3_PRV_KEY_SIZE)) { + pubKey = privKey + DILITHIUM_LEVEL3_KEY_SIZE; + pubKeyLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + privKeyLen -= DILITHIUM_LEVEL3_PUB_KEY_SIZE; + } + else if ((key->level == 5) && + (privKeyLen == DILITHIUM_LEVEL5_PRV_KEY_SIZE)) { + pubKey = privKey + DILITHIUM_LEVEL5_KEY_SIZE; + pubKeyLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + privKeyLen -= DILITHIUM_LEVEL5_PUB_KEY_SIZE; + } } - ret = DecodeAsymKey(input, inOutIdx, inSz, privKey, &privKeyLen, - pubKey, &pubKeyLen, keytype); if (ret == 0) { - if (pubKeyLen == 0) { - ret = wc_dilithium_import_private_only(input, inSz, key); + /* Check whether public key data was found. */ +#if defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) + if (pubKeyLen == 0) +#endif + { + /* No public key data, only import private key data. */ + ret = wc_dilithium_import_private(privKey, privKeyLen, key); } +#if defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) else { - ret = wc_dilithium_import_private_key(privKey, privKeyLen, - pubKey, pubKeyLen, key); + /* Import private and public key data. */ + ret = wc_dilithium_import_key(privKey, privKeyLen, pubKey, + pubKeyLen, key); } +#endif } + + (void)pubKey; + (void)pubKeyLen; + return ret; } +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ + +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY + +/* Decode the DER encoded Dilithium public key. + * + * @param [in] input Array holding DER encoded data. + * @param [in, out] inOutIdx On in, index into array of start of DER encoding. + * On out, index into array after DER encoding. + * @param [in, out] key Dilithium key to store key. + * @param [in] inSz Total size of data in array. + * @return 0 on success. + * @return BAD_FUNC_ARG when input, inOutIdx or key is NULL or inSz is 0. + * @return BAD_FUNC_ARG when level not set. + * @return Other negative on parse error. + */ int wc_Dilithium_PublicKeyDecode(const byte* input, word32* inOutIdx, - dilithium_key* key, word32 inSz) + dilithium_key* key, word32 inSz) { int ret = 0; - byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; - word32 pubKeyLen = (word32)sizeof(pubKey); + const byte* pubKey; + word32 pubKeyLen = 0; int keytype = 0; - if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) { - return BAD_FUNC_ARG; - } - - ret = wc_dilithium_import_public(input, inSz, key); - if (ret == 0) { - return 0; - } - - if (key->level == 2) { - keytype = DILITHIUM_LEVEL2k; - } - else if (key->level == 3) { - keytype = DILITHIUM_LEVEL3k; - } - else if (key->level == 5) { - keytype = DILITHIUM_LEVEL5k; - } - else { - return BAD_FUNC_ARG; + /* Validate parameters. */ + if ((input == NULL) || (inOutIdx == NULL) || (key == NULL) || (inSz == 0)) { + ret = BAD_FUNC_ARG; } - ret = DecodeAsymKeyPublic(input, inOutIdx, inSz, pubKey, &pubKeyLen, - keytype); if (ret == 0) { - ret = wc_dilithium_import_public(pubKey, pubKeyLen, key); + /* Try to import the key directly. */ + ret = wc_dilithium_import_public(input, inSz, key); + if (ret != 0) { + /* Start again. */ + ret = 0; + + /* Get OID sum for level. */ + if (key->level == 2) { + keytype = DILITHIUM_LEVEL2k; + } + else if (key->level == 3) { + keytype = DILITHIUM_LEVEL3k; + } + else if (key->level == 5) { + keytype = DILITHIUM_LEVEL5k; + } + else { + /* Level not set. */ + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + /* Decode the asymmetric key and get out public key data. */ + ret = DecodeAsymKeyPublic_Assign(input, inOutIdx, inSz, &pubKey, + &pubKeyLen, keytype); + } + if (ret == 0) { + /* Import public key data. */ + ret = wc_dilithium_import_public(pubKey, pubKeyLen, key); + } + } } return ret; } #ifdef WC_ENABLE_ASYM_KEY_EXPORT -/* Encode the public part of an Dilithium key in DER. +/* Encode the public part of a Dilithium key in DER. * * Pass NULL for output to get the size of the encoding. * - * @param [in] key Dilithium key object. - * @param [out] output Buffer to put encoded data in. - * @param [in] outLen Size of buffer in bytes. - * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. + * @param [in] key Dilithium key object. + * @param [out] output Buffer to put encoded data in. + * @param [in] len Size of buffer in bytes. + * @param [in] withAlg Whether to use SubjectPublicKeyInfo format. * @return Size of encoded data in bytes on success. * @return BAD_FUNC_ARG when key is NULL. * @return MEMORY_E when dynamic memory allocation failed. */ -int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 inLen, - int withAlg) +int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, word32 len, + int withAlg) { - int ret; - byte pubKey[DILITHIUM_MAX_PUB_KEY_SIZE]; - word32 pubKeyLen = (word32)sizeof(pubKey); - int keytype = 0; - - if (key == NULL || output == NULL) { - return BAD_FUNC_ARG; - } + int ret = 0; + int keytype = 0; + int pubKeyLen = 0; - if (key->level == 2) { - keytype = DILITHIUM_LEVEL2k; - } - else if (key->level == 3) { - keytype = DILITHIUM_LEVEL3k; + /* Validate parameters. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; } - else if (key->level == 5) { - keytype = DILITHIUM_LEVEL5k; + /* Check we have a public key to encode. */ + if ((ret == 0) && (!key->pubKeySet)) { + ret = BAD_FUNC_ARG; } - else { - return BAD_FUNC_ARG; + + if (ret == 0) { + /* Get OID and length for level. */ + if (key->level == 2) { + keytype = DILITHIUM_LEVEL2k; + pubKeyLen = DILITHIUM_LEVEL2_PUB_KEY_SIZE; + } + else if (key->level == 3) { + keytype = DILITHIUM_LEVEL3k; + pubKeyLen = DILITHIUM_LEVEL3_PUB_KEY_SIZE; + } + else if (key->level == 5) { + keytype = DILITHIUM_LEVEL5k; + pubKeyLen = DILITHIUM_LEVEL5_PUB_KEY_SIZE; + } + else { + /* Level not set. */ + ret = BAD_FUNC_ARG; + } } - ret = wc_dilithium_export_public(key, pubKey, &pubKeyLen); if (ret == 0) { - ret = SetAsymKeyDerPublic(pubKey, pubKeyLen, output, inLen, keytype, - withAlg); + ret = SetAsymKeyDerPublic(key->p, pubKeyLen, output, len, keytype, + withAlg); } return ret; } -#endif +#endif /* WC_ENABLE_ASYM_KEY_EXPORT */ + +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ -int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, word32 inLen) +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY + +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY +/* Encode the private and public data of a Dilithium key in DER. + * + * Pass NULL for output to get the size of the encoding. + * + * @param [in] key Dilithium key object. + * @param [out] output Buffer to put encoded data in. + * @param [in] len Size of buffer in bytes. + * @return Size of encoded data in bytes on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation failed. + */ +int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, word32 len) { - if (key == NULL) { - return BAD_FUNC_ARG; - } + int ret = BAD_FUNC_ARG; - if (key->level == 2) { - return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, key->p, - DILITHIUM_LEVEL2_KEY_SIZE, output, inLen, - DILITHIUM_LEVEL2k); - } - else if (key->level == 3) { - return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, key->p, - DILITHIUM_LEVEL3_KEY_SIZE, output, inLen, - DILITHIUM_LEVEL3k); - } - else if (key->level == 5) { - return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, key->p, - DILITHIUM_LEVEL5_KEY_SIZE, output, inLen, - DILITHIUM_LEVEL5k); + /* Validate parameters and check public and private key set. */ + if ((key != NULL) && key->prvKeySet && key->pubKeySet) { + /* Create DER for level. */ + if (key->level == 2) { + ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, key->p, + DILITHIUM_LEVEL2_PUB_KEY_SIZE, output, len, DILITHIUM_LEVEL2k); + } + else if (key->level == 3) { + ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, key->p, + DILITHIUM_LEVEL3_PUB_KEY_SIZE, output, len, DILITHIUM_LEVEL3k); + } + else if (key->level == 5) { + ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, key->p, + DILITHIUM_LEVEL5_PUB_KEY_SIZE, output, len, DILITHIUM_LEVEL5k); + } } - return BAD_FUNC_ARG; + return ret; } +#endif /* WOLFSSL_DILITHIUM_PUBLIC_KEY */ -int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, word32 inLen) +/* Encode the private data of a Dilithium key in DER. + * + * Pass NULL for output to get the size of the encoding. + * + * @param [in] key Dilithium key object. + * @param [out] output Buffer to put encoded data in. + * @param [in] len Size of buffer in bytes. + * @return Size of encoded data in bytes on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return MEMORY_E when dynamic memory allocation failed. + */ +int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, word32 len) { - if (key == NULL) { - return BAD_FUNC_ARG; - } + int ret = BAD_FUNC_ARG; - if (key->level == 2) { - return SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, NULL, 0, output, - inLen, DILITHIUM_LEVEL2k); - } - else if (key->level == 3) { - return SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, NULL, 0, output, - inLen, DILITHIUM_LEVEL3k); - } - else if (key->level == 5) { - return SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, NULL, 0, output, - inLen, DILITHIUM_LEVEL5k); + /* Validate parameters and check private key set. */ + if ((key != NULL) && key->prvKeySet) { + /* Create DER for level. */ + if (key->level == 2) { + ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL2_KEY_SIZE, NULL, 0, + output, len, DILITHIUM_LEVEL2k); + } + else if (key->level == 3) { + ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL3_KEY_SIZE, NULL, 0, + output, len, DILITHIUM_LEVEL3k); + } + else if (key->level == 5) { + ret = SetAsymKeyDer(key->k, DILITHIUM_LEVEL5_KEY_SIZE, NULL, 0, + output, len, DILITHIUM_LEVEL5k); + } } - return BAD_FUNC_ARG; + return ret; } -#endif /* HAVE_PQC && HAVE_DILITHIUM */ + +#endif /* WOLFSSL_DILITHIUM_PRIVATE_KEY */ + +#endif /* WOLFSSL_DILITHIUM_NO_ASN1 */ + +#endif /* HAVE_DILITHIUM */ diff --git a/src/wolfcrypt/src/dsa.c b/src/wolfcrypt/src/dsa.c index 08f70db..c1606b3 100644 --- a/src/wolfcrypt/src/dsa.c +++ b/src/wolfcrypt/src/dsa.c @@ -930,33 +930,39 @@ int wc_DsaSign_ex(const byte* digest, word32 digestSz, byte* out, DsaKey* key, #ifdef WOLFSSL_SMALL_STACK if (k) { - if ((ret != MP_INIT_E) && (ret != MEMORY_E)) + if ((ret != WC_NO_ERR_TRACE(MP_INIT_E)) && + (ret != WC_NO_ERR_TRACE(MEMORY_E))) mp_forcezero(k); XFREE(k, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (kInv) { - if ((ret != MP_INIT_E) && (ret != MEMORY_E)) + if ((ret != WC_NO_ERR_TRACE(MP_INIT_E)) && + (ret != WC_NO_ERR_TRACE(MEMORY_E))) mp_forcezero(kInv); XFREE(kInv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (r) { - if ((ret != MP_INIT_E) && (ret != MEMORY_E)) + if ((ret != WC_NO_ERR_TRACE(MP_INIT_E)) && + (ret != WC_NO_ERR_TRACE(MEMORY_E))) mp_clear(r); XFREE(r, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (s) { - if ((ret != MP_INIT_E) && (ret != MEMORY_E)) + if ((ret != WC_NO_ERR_TRACE(MP_INIT_E)) && + (ret != WC_NO_ERR_TRACE(MEMORY_E))) mp_clear(s); XFREE(s, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (H) { - if ((ret != MP_INIT_E) && (ret != MEMORY_E)) + if ((ret != WC_NO_ERR_TRACE(MP_INIT_E)) && + (ret != WC_NO_ERR_TRACE(MEMORY_E))) mp_clear(H); XFREE(H, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } #ifndef WOLFSSL_MP_INVMOD_CONSTANT_TIME if (b) { - if ((ret != MP_INIT_E) && (ret != MEMORY_E)) + if ((ret != WC_NO_ERR_TRACE(MP_INIT_E)) && + (ret != WC_NO_ERR_TRACE(MEMORY_E))) mp_forcezero(b); XFREE(b, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } @@ -966,7 +972,7 @@ int wc_DsaSign_ex(const byte* digest, word32 digestSz, byte* out, DsaKey* key, XFREE(buffer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } #else /* !WOLFSSL_SMALL_STACK */ - if (ret != MP_INIT_E) { + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) { ForceZero(buffer, halfSz); mp_forcezero(kInv); mp_forcezero(k); @@ -1106,37 +1112,37 @@ int wc_DsaVerify_ex(const byte* digest, word32 digestSz, const byte* sig, #ifdef WOLFSSL_SMALL_STACK if (s) { - if (ret != MP_INIT_E) + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(s); XFREE(s, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (r) { - if (ret != MP_INIT_E) + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(r); XFREE(r, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (u1) { - if (ret != MP_INIT_E) + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(u1); XFREE(u1, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (u2) { - if (ret != MP_INIT_E) + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(u2); XFREE(u2, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (w) { - if (ret != MP_INIT_E) + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(w); XFREE(w, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } if (v) { - if (ret != MP_INIT_E) + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(v); XFREE(v, key->heap, DYNAMIC_TYPE_TMP_BUFFER); } #else - if (ret != MP_INIT_E) { + if (ret != WC_NO_ERR_TRACE(MP_INIT_E)) { mp_clear(s); mp_clear(r); mp_clear(u1); diff --git a/src/wolfcrypt/src/ecc.c b/src/wolfcrypt/src/ecc.c index 78101ed..ee1e7b7 100644 --- a/src/wolfcrypt/src/ecc.c +++ b/src/wolfcrypt/src/ecc.c @@ -98,6 +98,12 @@ Possible ECC enable options: * Use this when CPU state can be closely observed by * attacker. * default: off + * WOLFSSL_ECC_BLIND_K + * Blind the private key k by using a random mask. + * The private key is never stored unprotected but an + * unmasked copy is computed and stored each time it is + * needed. + * default: off */ /* @@ -180,6 +186,15 @@ ECC Curve Sizes: #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_ecc_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000005 }; + int wolfCrypt_FIPS_ECC_sanity(void) + { + return 0; + } +#endif + #if defined(FREESCALE_LTC_ECC) #include #endif @@ -288,6 +303,53 @@ ECC Curve Sizes: #endif +#ifdef WOLFSSL_ECC_BLIND_K +mp_int* ecc_get_k(ecc_key* key) +{ + mp_xor_ct(key->k, key->kb, key->dp->size, key->ku); + return key->ku; +} +void ecc_blind_k(ecc_key* key, mp_int* b) +{ + mp_xor_ct(key->k, b, key->dp->size, key->k); + mp_xor_ct(key->kb, b, key->dp->size, key->kb); +} +int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng) +{ + int ret = 0; + WC_RNG local_rng; + +#ifdef ECC_TIMING_RESISTANT + if (rng == NULL) { + rng = key->rng; + } +#endif + if (rng == NULL) { + ret = wc_InitRng(&local_rng); + if (ret == 0) { + rng = &local_rng; + } + } + if (ret == 0) { + ret = mp_rand(key->kb, (key->dp->size + sizeof(mp_digit) - 1) / + sizeof(mp_digit), rng); + if (ret == 0) { + mp_xor_ct(key->k, key->kb, key->dp->size, key->k); + } + } + + if (rng == &local_rng) { + wc_FreeRng(&local_rng); + } + return ret; +} + +mp_int* wc_ecc_key_get_priv(ecc_key* key) +{ + return ecc_get_k(key); +} +#endif + /* forward declarations */ static int wc_ecc_new_point_ex(ecc_point** point, void* heap); static void wc_ecc_del_point_ex(ecc_point* p, void* heap); @@ -1486,7 +1548,11 @@ static int xil_mpi_import(mp_int *mpi, #ifdef ECC_CACHE_CURVE /* cache (mp_int) of the curve parameters */ + #ifdef WOLFSSL_NO_MALLOC + static ecc_curve_spec ecc_curve_spec_cache[ECC_SET_COUNT]; + #else static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT]; + #endif #ifndef SINGLE_THREADED static wolfSSL_Mutex ecc_curve_cache_mutex WOLFSSL_MUTEX_INITIALIZER_CLAUSE(ecc_curve_cache_mutex); #endif @@ -1666,6 +1732,9 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, } #endif +#ifdef WOLFSSL_NO_MALLOC + curve = &ecc_curve_spec_cache[x]; +#else /* make sure cache has been allocated */ if (ecc_curve_spec_cache[x] == NULL #ifdef WOLFSSL_CUSTOM_CURVES @@ -1692,6 +1761,8 @@ static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, else { curve = ecc_curve_spec_cache[x]; } +#endif /* WOLFSSL_NO_MALLOC */ + /* return new or cached curve */ *pCurve = curve; #else @@ -1771,11 +1842,16 @@ void wc_ecc_curve_cache_free(void) /* free all ECC curve caches */ for (x = 0; x < (int)ECC_SET_COUNT; x++) { + #ifdef WOLFSSL_NO_MALLOC + wc_ecc_curve_cache_free_spec(&ecc_curve_spec_cache[x]); + XMEMSET(&ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec_cache[x])); + #else if (ecc_curve_spec_cache[x]) { wc_ecc_curve_cache_free_spec(ecc_curve_spec_cache[x]); XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC); ecc_curve_spec_cache[x] = NULL; } + #endif /* WOLFSSL_NO_MALLOC */ } #if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) && \ @@ -2617,6 +2693,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, */ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) { + int err = MP_OKAY; #if !defined(WOLFSSL_SP_MATH) DECL_MP_INT_SIZE_DYN(t1, mp_bitsused(modulus), MAX_ECC_BITS_USE); DECL_MP_INT_SIZE_DYN(t2, mp_bitsused(modulus), MAX_ECC_BITS_USE); @@ -2626,7 +2703,6 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) DECL_MP_INT_SIZE_DYN(rz, mp_bitsused(modulus), MAX_ECC_BITS_USE); #endif mp_int *x, *y, *z; - int err; (void)ct; @@ -2844,7 +2920,7 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct) err = ECC_BAD_ARG_E; #endif - WOLFSSL_LEAVE("ecc_map_ex (SP Math)"); + WOLFSSL_LEAVE("ecc_map_ex (SP Math)", err); return err; #endif /* WOLFSSL_SP_MATH */ } @@ -3982,6 +4058,12 @@ int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point* G, ecc_point* R, mp_int* a, int wc_ecc_mulmod(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map) { + if ((k != NULL) && (R != NULL) && (mp_iszero(k))) { + mp_zero(R->x); + mp_zero(R->y); + mp_set(R->z, 1); + return MP_OKAY; + } return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } @@ -4279,8 +4361,11 @@ static int wc_ecc_cmp_param(const char* curveParam, if (param == NULL || curveParam == NULL) return BAD_FUNC_ARG; - if (encType == WC_TYPE_HEX_STR) - return XSTRNCMP(curveParam, (char*) param, paramSz); + if (encType == WC_TYPE_HEX_STR) { + if ((word32)XSTRLEN(curveParam) != paramSz) + return -1; + return (XSTRNCMP(curveParam, (char*) param, paramSz) == 0) ? 0 : -1; + } #ifdef WOLFSSL_SMALL_STACK a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); @@ -4596,7 +4681,7 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, #endif { err = wc_CryptoCb_Ecdh(private_key, public_key, out, outlen); - if (err != CRYPTOCB_UNAVAILABLE) + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return err; /* fall-through when unavailable */ } @@ -4667,7 +4752,7 @@ int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, byte* out, word32* outlen) { int err = MP_OKAY; - mp_int* k = private_key->k; + mp_int* k = ecc_get_k(private_key); #ifdef HAVE_ECC_CDH #ifdef WOLFSSL_SMALL_STACK mp_int *k_lcl = NULL; @@ -4697,7 +4782,7 @@ int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, goto errout; } /* multiply cofactor times private key "k" */ - err = mp_mul_d(private_key->k, cofactor, k); + err = mp_mul_d(ecc_get_k(private_key), cofactor, k); if (err != MP_OKAY) goto errout; } @@ -4938,7 +5023,8 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, word32 keySz = private_key->dp->size; /* sync public key x/y */ - err = wc_mp_to_bigint_sz(private_key->k, &private_key->k->raw, keySz); + err = wc_mp_to_bigint_sz(ecc_get_k(private_key), + &ecc_get_k(private_key)->raw, keySz); if (err == MP_OKAY) err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz); if (err == MP_OKAY) @@ -4952,7 +5038,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, NitroxEccGetSize(private_key)*2); if (err == MP_OKAY) err = NitroxEcdh(private_key, - &private_key->k->raw, &point->x->raw, &point->y->raw, + &ecc_get_k(private_key)->raw, &point->x->raw, &point->y->raw, private_key->e->raw.buf, &private_key->e->raw.len, &curve->prime->raw); #else @@ -4960,7 +5046,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); if (err == MP_OKAY) err = IntelQaEcdh(&private_key->asyncDev, - &private_key->k->raw, &point->x->raw, &point->y->raw, + &ecc_get_k(private_key)->raw, &point->x->raw, &point->y->raw, out, outlen, &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, private_key->dp->cofactor); @@ -4983,7 +5069,7 @@ static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen); } - if (err == WC_PENDING_E) { + if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) { private_key->state++; } @@ -5076,7 +5162,7 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, RESTORE_VECTOR_REGISTERS(); /* if async pending then return and skip done cleanup below */ - if (err == WC_PENDING_E) { + if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) { return err; } @@ -5098,11 +5184,33 @@ int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, err = wc_ecc_init_ex(&public_key, private_key->heap, INVALID_DEVID); if (err == MP_OKAY) { + #if FIPS_VERSION3_GE(6,0,0) + /* Since we are allowing a pass-through of ecc_make_key_ex_fips when + * both keysize == 0 and curve_id == 0 ensure we select an appropriate + * keysize here when relying on default selection */ + if (private_key->dp->size < WC_ECC_FIPS_GEN_MIN) { + if (private_key->dp->size == 0 && + (private_key->dp->id == ECC_SECP256R1 || + private_key->dp->id == ECC_SECP224R1 || + private_key->dp->id == ECC_SECP384R1 || + private_key->dp->id == ECC_SECP521R1)) { + WOLFSSL_MSG("ECC dp->size zero but dp->id sufficient for FIPS"); + err = 0; + } else { + WOLFSSL_MSG("ECC curve too small for FIPS mode"); + err = ECC_CURVE_OID_E; + } + } + if (err == 0) { /* FIPS specific check */ + #endif err = wc_ecc_set_curve(&public_key, private_key->dp->size, private_key->dp->id); if (err == MP_OKAY) { err = mp_copy(point->x, public_key.pubkey.x); } + #if FIPS_VERSION3_GE(6,0,0) + } /* end FIPS specific check */ + #endif if (err == MP_OKAY) { err = mp_copy(point->y, public_key.pubkey.y); } @@ -5323,9 +5431,9 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, key->type = ECC_PRIVATEKEY_ONLY; } - if ((err == MP_OKAY) && (mp_iszero(key->k) || mp_isneg(key->k) || - (mp_cmp(key->k, curve->order) != MP_LT))) - { + if ((err == MP_OKAY) && (mp_iszero(ecc_get_k(key)) || + mp_isneg(ecc_get_k(key)) || + (mp_cmp(ecc_get_k(key), curve->order) != MP_LT))) { err = ECC_PRIV_KEY_E; } @@ -5347,10 +5455,10 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, if (err == MP_OKAY && key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { word32 keySz = key->dp->size; /* sync private key to raw */ - err = wc_mp_to_bigint_sz(key->k, &key->k->raw, keySz); + err = wc_mp_to_bigint_sz(ecc_get_k(key), &ecc_get_k(key)->raw, keySz); if (err == MP_OKAY) { err = IntelQaEccPointMul(&key->asyncDev, - &key->k->raw, pub->x, pub->y, pub->z, + &ecc_get_k(key)->raw, pub->x, pub->y, pub->z, &curve->Gx->raw, &curve->Gy->raw, &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, key->dp->cofactor); @@ -5366,25 +5474,25 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, else #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - err = sp_ecc_mulmod_base_256(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_256(ecc_get_k(key), pub, 1, key->heap); } else #endif /* WOLFSSL_SP_NO_256 */ #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) { - err = sp_ecc_mulmod_base_sm2_256(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_sm2_256(ecc_get_k(key), pub, 1, key->heap); } else #endif #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - err = sp_ecc_mulmod_base_384(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_384(ecc_get_k(key), pub, 1, key->heap); } else #endif #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { - err = sp_ecc_mulmod_base_521(key->k, pub, 1, key->heap); + err = sp_ecc_mulmod_base_521(ecc_get_k(key), pub, 1, key->heap); } else #endif @@ -5416,8 +5524,8 @@ static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curve, /* make the public key */ if (err == MP_OKAY) { /* Map in a separate call as this should be constant time */ - err = wc_ecc_mulmod_ex2(key->k, base, pub, curve->Af, curve->prime, - curve->order, rng, 0, key->heap); + err = wc_ecc_mulmod_ex2(ecc_get_k(key), base, pub, curve->Af, + curve->prime, curve->order, rng, 0, key->heap); if (err == MP_MEM) { err = MEMORY_E; } @@ -5539,11 +5647,30 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, /* make sure required variables are reset */ wc_ecc_reset(key); + #if FIPS_VERSION3_GE(6,0,0) + /* Since we are allowing a pass-through of ecc_make_key_ex_fips when + * both keysize == 0 and curve_id == 0 ensure we select an appropriate + * keysize here when relying on default selection */ + if (keysize < WC_ECC_FIPS_GEN_MIN) { + if (keysize == 0 && (curve_id == ECC_SECP256R1 || + curve_id == ECC_SECP224R1 || curve_id == ECC_SECP384R1 || + curve_id == ECC_SECP521R1)) { + WOLFSSL_MSG("ECC keysize zero but curve_id sufficient for FIPS"); + err = 0; + } else { + WOLFSSL_MSG("ECC curve too small for FIPS mode"); + err = ECC_CURVE_OID_E; + } + } + if (err == 0) { /* FIPS specific check */ + #endif err = wc_ecc_set_curve(key, keysize, curve_id); if (err != 0) { return err; } - + #if FIPS_VERSION3_GE(6,0,0) + } /* end FIPS specific check */ + #endif key->flags = (byte)flags; #ifdef WOLF_CRYPTO_CB @@ -5552,7 +5679,7 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, #endif { err = wc_CryptoCb_MakeEccKey(rng, keysize, key, curve_id); - if (err != CRYPTOCB_UNAVAILABLE) + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return err; /* fall-through when unavailable */ } @@ -5653,6 +5780,11 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, if (err == SA_SILIB_RET_OK) { err = mp_read_unsigned_bin(key->k, ucompressed_key, raw_size); +#ifdef WOLFSSL_ECC_BLIND_K + if (err == MP_OKAY) { + err = ecc_blind_k_rng(key, rng); + } +#endif } #elif defined(WOLFSSL_SILABS_SE_ACCEL) @@ -5704,7 +5836,12 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, err = xil_mpi_import(key->pubkey.y, key->keyRaw + key->dp->size, key->dp->size, key->heap); if (err == 0) - err = xil_mpi_import(key->k, key->privKey, key->dp->size, key->heap); + err = xil_mpi_import(key->k, key->privKey, key->dp->size, + key->heap); +#ifdef WOLFSSL_ECC_BLIND_K + if (err == 0) + err = ecc_blind_k_rng(key, rng); +#endif if (err == 0) err = mp_set(key->pubkey.z, 1); if (err) { @@ -5886,6 +6023,11 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, err = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw); #endif +#ifdef WOLFSSL_ECC_BLIND_K + if (err == MP_OKAY) + err = ecc_blind_k_rng(key, rng); +#endif + #endif /* HAVE_ECC_MAKE_PUB */ return err; @@ -6041,20 +6183,11 @@ WOLFSSL_ABI int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) { int ret = 0; -#if defined(HAVE_PKCS11) - int isPkcs11 = 0; -#endif if (key == NULL) { return BAD_FUNC_ARG; } -#if defined(HAVE_PKCS11) - if (key->isPkcs11) { - isPkcs11 = 1; - } -#endif - #ifdef ECC_DUMP_OID wc_ecc_dump_oids(); #endif @@ -6082,13 +6215,27 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) alt_fp_init(key->pubkey.z); key->k = (mp_int*)key->ka; alt_fp_init(key->k); +#ifdef WOLFSSL_ECC_BLIND_K + key->kb = (mp_int*)key->kba; + key->ku = (mp_int*)key->kia; + alt_fp_init(key->kb); + alt_fp_init(key->ku); +#endif #else ret = mp_init_multi(key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL); +#ifndef WOLFSSL_ECC_BLIND_K + NULL, NULL +#else + key->kb, key->ku +#endif + ); if (ret != MP_OKAY) { return MEMORY_E; } #endif /* ALT_ECC_SIZE */ +#ifdef WOLFSSL_ECC_BLIND_K + mp_forcezero(key->kb); +#endif #endif /* WOLFSSL_ATECC508A */ #if (defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ @@ -6108,16 +6255,17 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) #endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - #if defined(HAVE_PKCS11) - if (!isPkcs11) + #ifdef WOLF_CRYPTO_CB + /* prefer crypto callback */ + if (key->devId != INVALID_DEVID) #endif - { - /* handle as async */ - ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, - key->heap, devId); - } -#elif defined(HAVE_PKCS11) - (void)isPkcs11; + { + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, + key->heap, devId); + } + if (ret != 0) + return ret; #endif #if defined(WOLFSSL_DSP) @@ -6131,6 +6279,10 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) #ifdef WOLFSSL_CHECK_MEM_ZERO mp_memzero_add("ECC k", key->k); +#ifdef WOLFSSL_ECC_BLIND_K + mp_memzero_add("ECC kb", key->kb); + mp_memzero_add("ECC ku", key->ku); +#endif #endif #if defined(WOLFSSL_XILINX_CRYPT_VERSAL) @@ -6169,12 +6321,6 @@ int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, ret = BAD_FUNC_ARG; if (ret == 0 && (len < 0 || len > ECC_MAX_ID_LEN)) ret = BUFFER_E; - -#if defined(HAVE_PKCS11) - XMEMSET(key, 0, sizeof(ecc_key)); - key->isPkcs11 = 1; -#endif - if (ret == 0) ret = wc_ecc_init_ex(key, heap, devId); if (ret == 0 && id != NULL && len != 0) { @@ -6204,12 +6350,6 @@ int wc_ecc_init_label(ecc_key* key, const char* label, void* heap, int devId) if (labelLen == 0 || labelLen > ECC_MAX_LABEL_LEN) ret = BUFFER_E; } - -#if defined(HAVE_PKCS11) - XMEMSET(key, 0, sizeof(ecc_key)); - key->isPkcs11 = 1; -#endif - if (ret == 0) ret = wc_ecc_init_ex(key, heap, devId); if (ret == 0) { @@ -6551,7 +6691,7 @@ static int wc_ecc_sign_hash_async(const byte* in, word32 inlen, byte* out, } /* if async pending then return and skip done cleanup below */ - if (err == WC_PENDING_E) { + if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) { key->state++; return err; } @@ -6593,7 +6733,7 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, #endif { err = wc_CryptoCb_EccSign(in, inlen, out, outlen, rng, key); - if (err != CRYPTOCB_UNAVAILABLE) + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return err; /* fall-through when unavailable */ } @@ -6703,7 +6843,7 @@ static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key) /* currently limiting to SHA256 for auto create */ if (mp_init(key->sign_k) != MP_OKAY || wc_ecc_gen_deterministic_k(in, inlen, - WC_HASH_TYPE_SHA256, key->k, key->sign_k, + WC_HASH_TYPE_SHA256, ecc_get_k(key), key->sign_k, curve->order, key->heap) != 0) { mp_free(key->sign_k); XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC); @@ -6722,8 +6862,8 @@ static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key) #else key->sign_k_set = 0; /* currently limiting to SHA256 for auto create */ - if (wc_ecc_gen_deterministic_k(in, inlen, WC_HASH_TYPE_SHA256, key->k, - key->sign_k, curve->order, key->heap) != 0) { + if (wc_ecc_gen_deterministic_k(in, inlen, WC_HASH_TYPE_SHA256, + ecc_get_k(key), key->sign_k, curve->order, key->heap) != 0) { err = ECC_PRIV_KEY_E; } else { @@ -6783,7 +6923,7 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order); } - while (err == MP_ZERO_E); + while (err == WC_NO_ERR_TRACE(MP_ZERO_E)); loop_check = 0; } #ifdef WOLFSSL_CHECK_MEM_ZERO @@ -6861,15 +7001,18 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, if (err != MP_OKAY) break; if (mp_iszero(r) == MP_NO) { - mp_int* ep = pubkey->k; - mp_int* kp = pubkey->k; - mp_int* x = key->k; + mp_int* kp = ecc_get_k(pubkey); + mp_int* ep = kp; + mp_int* x = ecc_get_k(key); + + /* Blind after getting. */ + ecc_blind_k(key, b); /* find s = (e + xr)/k = b.(e/k.b + x.r/k.b) */ /* k' = k.b */ - err = mp_mulmod(pubkey->k, b, curve->order, kp); + err = mp_mulmod(kp, b, curve->order, kp); if (err != MP_OKAY) break; /* k' = 1/k.b @@ -6948,12 +7091,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, #endif if (key->nb_ctx) { return sp_ecc_sign_256_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ err = sp_ecc_sign_256_nb(&nb_ctx.sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif @@ -6962,8 +7105,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_256(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_256(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -6974,8 +7117,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, if (ecc_sets[key->idx].id == ECC_SM2P256V1) { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_sm2_256(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_sm2_256(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -6988,12 +7131,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, #endif if (key->nb_ctx) { return sp_ecc_sign_384_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ err = sp_ecc_sign_384_nb(&nb_ctx.sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif @@ -7002,8 +7145,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_384(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_384(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -7018,12 +7161,12 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, #endif if (key->nb_ctx) { return sp_ecc_sign_521_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } #ifdef WC_ECC_NONBLOCK_ONLY do { /* perform blocking call to non-blocking function */ err = sp_ecc_sign_521_nb(&nb_ctx.sp_ctx, in, inlen, rng, - key->k, r, s, sign_k, key->heap); + ecc_get_k(key), r, s, sign_k, key->heap); } while (err == FP_WOULDBLOCK); return err; #endif @@ -7032,8 +7175,8 @@ static int ecc_sign_hash_sp(const byte* in, word32 inlen, WC_RNG* rng, { int ret; SAVE_VECTOR_REGISTERS(return _svr_ret;); - ret = sp_ecc_sign_521(in, inlen, rng, key->k, r, s, sign_k, - key->heap); + ret = sp_ecc_sign_521(in, inlen, rng, ecc_get_k(key), r, s, + sign_k, key->heap); RESTORE_VECTOR_REGISTERS(); return ret; } @@ -7124,7 +7267,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ - defined(WOLFSSL_ASYNC_CRYPT_SW) + defined(WOLFSSL_ASYNC_CRYPT_SW) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_ECC_SIGN)) { WC_ASYNC_SW* sw = &key->asyncDev.sw; @@ -7141,7 +7284,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #if defined(WOLFSSL_HAVE_SP_ECC) err = ecc_sign_hash_sp(in, inlen, rng, key, r, s); - if (err != WC_KEY_SIZE_E) { + if (err != WC_NO_ERR_TRACE(WC_KEY_SIZE_E)) { return err; } #else @@ -7256,7 +7399,8 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err == MP_OKAY) err = wc_mp_to_bigint_sz(e, &e->raw, keySz); if (err == MP_OKAY) - err = wc_mp_to_bigint_sz(key->k, &key->k->raw, keySz); + err = wc_mp_to_bigint_sz(ecc_get_k(key), &ecc_get_k(key)->raw, + keySz); if (err == MP_OKAY) err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order); if (err == MP_OKAY) @@ -7264,14 +7408,15 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, #ifdef HAVE_CAVIUM_V if (err == MP_OKAY) - err = NitroxEcdsaSign(key, &e->raw, &key->k->raw, &k->raw, - &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw); + err = NitroxEcdsaSign(key, &e->raw, &ecc_get_k(key)->raw, + &k->raw, &r->raw, &s->raw, &curve->prime->raw, + &curve->order->raw); #else 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); + err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, + &ecc_get_k(key)->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); #endif #ifndef HAVE_CAVIUM_V @@ -7773,6 +7918,16 @@ int wc_ecc_free(ecc_key* key) if (key->k) #endif mp_forcezero(key->k); +#ifdef WOLFSSL_ECC_BLIND_K +#ifdef ALT_ECC_SIZE + if (key->kb) +#endif + mp_forcezero(key->kb); +#ifdef ALT_ECC_SIZE + if (key->ku) +#endif + mp_forcezero(key->ku); +#endif #ifdef WOLFSSL_CUSTOM_CURVES if (key->deallocSet && key->dp != NULL) @@ -8317,7 +8472,7 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, #endif { err = wc_CryptoCb_EccVerify(sig, siglen, hash, hashlen, res, key); - if (err != CRYPTOCB_UNAVAILABLE) + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return err; /* fall-through when unavailable */ } @@ -8425,7 +8580,7 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, #ifdef WOLFSSL_ASYNC_CRYPT /* if async pending then return and skip done cleanup below */ - if (err == WC_PENDING_E) { + if (err == WC_NO_ERR_TRACE(WC_PENDING_E)) { if (!isPrivateKeyOnly) /* do not advance state if doing make pub key */ key->state++; return err; @@ -9067,7 +9222,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, } err = ecc_verify_hash_sp(r, s, hash, hashlen, res, key); - if (err != NOT_COMPILED_IN) { + if (err != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { if (curveLoaded) { wc_ecc_curve_free(curve); FREE_CURVE_SPECS(); @@ -9845,7 +10000,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_256(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_256(ecc_get_k(key), res, 1, key->heap); } } else @@ -9853,7 +10008,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_sm2_256(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_sm2_256(ecc_get_k(key), res, 1, key->heap); } } else @@ -9861,7 +10016,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_384(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_384(ecc_get_k(key), res, 1, key->heap); } } else @@ -9869,7 +10024,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { if (err == MP_OKAY) { - err = sp_ecc_mulmod_base_521(key->k, res, 1, key->heap); + err = sp_ecc_mulmod_base_521(ecc_get_k(key), res, 1, key->heap); } } else @@ -9922,12 +10077,12 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) #else #ifdef ECC_TIMING_RESISTANT if (err == MP_OKAY) - err = wc_ecc_mulmod_ex2(key->k, base, res, a, prime, curve->order, - key->rng, 1, key->heap); + err = wc_ecc_mulmod_ex2(ecc_get_k(key), base, res, a, prime, + curve->order, key->rng, 1, key->heap); #else if (err == MP_OKAY) - err = wc_ecc_mulmod_ex2(key->k, base, res, a, prime, curve->order, - NULL, 1, key->heap); + err = wc_ecc_mulmod_ex2(ecc_get_k(key), base, res, a, prime, + curve->order, NULL, 1, key->heap); #endif #endif /* WOLFSSL_KCAPI_ECC */ } @@ -10198,31 +10353,31 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv) #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { return sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SP_SM2) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SM2P256V1) { return sp_ecc_check_key_sm2_256(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { return sp_ecc_check_key_384(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { return sp_ecc_check_key_521(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #if defined(WOLFSSL_SP_1024) && defined(WOLFCRYPT_HAVE_SAKKE) if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SAKKE_1) { return sp_ecc_check_key_1024(key->pubkey.x, key->pubkey.y, - key->type == ECC_PRIVATEKEY ? key->k : NULL, key->heap); + key->type == ECC_PRIVATEKEY ? ecc_get_k(key) : NULL, key->heap); } #endif #endif @@ -10333,8 +10488,8 @@ static int _ecc_validate_public_key(ecc_key* key, int partial, int priv) /* SP 800-56Ar3, section 5.6.2.1.2 */ /* private keys must be in the range [1, n-1] */ if ((err == MP_OKAY) && (key->type == ECC_PRIVATEKEY) && - (mp_iszero(key->k) || mp_isneg(key->k) || - (mp_cmp(key->k, curve->order) != MP_LT)) + (mp_iszero(ecc_get_k(key)) || mp_isneg(ecc_get_k(key)) || + (mp_cmp(ecc_get_k(key), curve->order) != MP_LT)) #ifdef WOLFSSL_KCAPI_ECC && key->handle == NULL #endif @@ -10419,12 +10574,26 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, alt_fp_init(key->pubkey.z); key->k = (mp_int*)key->ka; alt_fp_init(key->k); + #ifdef WOLFSSL_ECC_BLIND_K + key->kb = (mp_int*)key->kba; + key->ku = (mp_int*)key->kua; + alt_fp_init(key->kb); + alt_fp_init(key->ku); + #endif + #else + err = mp_init_multi(key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + #ifndef WOLFSSL_ECC_BLIND_K + NULL, NULL #else - err = mp_init_multi(key->k, - key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL); + key->kb, key->ku + #endif + ); #endif if (err != MP_OKAY) return MEMORY_E; +#ifdef WOLFSSL_ECC_BLIND_K + mp_forcezero(key->kb); +#endif SAVE_VECTOR_REGISTERS(return _svr_ret;); @@ -10468,6 +10637,8 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, /* determine key size */ keysize = (int)(inLen>>1); + /* NOTE: FIPS v6.0.0 or greater, no restriction on imported keys, only + * on created keys or signatures */ err = wc_ecc_set_curve(key, keysize, curve_id); key->type = ECC_PUBLICKEY; } @@ -10731,7 +10902,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, return BUFFER_E; } - err = wc_export_int(key->k, d, dLen, keySz + WC_CAAM_MAC_SZ, + err = wc_export_int(ecc_get_k(key), d, dLen, keySz + WC_CAAM_MAC_SZ, encType); *dLen = keySz + WC_CAAM_MAC_SZ; } @@ -10753,7 +10924,7 @@ int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, else #endif { - err = wc_export_int(key->k, d, dLen, keySz, encType); + err = wc_export_int(ecc_get_k(key), d, dLen, keySz, encType); if (err != MP_OKAY) return err; } @@ -10862,6 +11033,8 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, wc_ecc_reset(key); /* set key size */ + /* NOTE: FIPS v6.0.0 or greater, no restriction on imported keys, only + * on created keys or signatures */ ret = wc_ecc_set_curve(key, (int)privSz, curve_id); key->type = ECC_PRIVATEKEY_ONLY; } @@ -10886,6 +11059,11 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, } ret = mp_read_unsigned_bin(key->k, priv, privSz); + #ifdef WOLFSSL_ECC_BLIND_K + if (ret == MP_OKAY) { + err = ecc_blind_k_rng(key, NULL); + } + #endif } #elif defined(WOLFSSL_QNX_CAAM) || defined(WOLFSSL_IMXRT1170_CAAM) if ((wc_ecc_size(key) + WC_CAAM_MAC_SZ) == (int)privSz) { @@ -10917,11 +11095,21 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, #else key->blackKey = CAAM_BLACK_KEY_CCM; ret = mp_read_unsigned_bin(key->k, priv, privSz); + #ifdef WOLFSSL_ECC_BLIND_K + if (ret == MP_OKAY) { + err = ecc_blind_k_rng(key, NULL); + } + #endif #endif } else { key->blackKey = 0; ret = mp_read_unsigned_bin(key->k, priv, privSz); + #ifdef WOLFSSL_ECC_BLIND_K + if (ret == MP_OKAY) { + err = ecc_blind_k_rng(key, NULL); + } + #endif /* If using AES-ECB encrypted black keys check here if key is valid, * if not valid than assume is an encrypted key. A public key is needed @@ -10950,8 +11138,8 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, ret = mp_read_unsigned_bin(key->k, priv, privSz); #ifdef HAVE_WOLF_BIGINT - if (ret == 0 && - wc_bigint_from_unsigned_bin(&key->k->raw, priv, privSz) != 0) { + if (ret == 0 && wc_bigint_from_unsigned_bin(&key->k->raw, priv, + privSz) != 0) { mp_clear(key->k); ret = ASN_GETINT_E; } @@ -10993,6 +11181,11 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, #endif } #endif /* WOLFSSL_VALIDATE_ECC_IMPORT */ +#ifdef WOLFSSL_ECC_BLIND_K + if (ret == 0) { + ret = ecc_blind_k_rng(key, NULL); + } +#endif #endif /* WOLFSSL_CRYPTOCELL */ @@ -11168,6 +11361,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, wc_ecc_reset(key); /* set curve type and index */ + /* NOTE: FIPS v6.0.0 or greater, no restriction on imported keys, only + * on created keys or signatures */ err = wc_ecc_set_curve(key, 0, curve_id); if (err != 0) { return err; @@ -11183,12 +11378,26 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, alt_fp_init(key->pubkey.z); key->k = (mp_int*)key->ka; alt_fp_init(key->k); +#ifdef WOLFSSL_ECC_BLIND_K + key->kb = (mp_int*)key->kba; + key->ku = (mp_int*)key->kua; + alt_fp_init(key->kb); + alt_fp_init(key->ku); +#endif #else err = mp_init_multi(key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL); +#ifndef WOLFSSL_ECC_BLIND_K + NULL, NULL +#else + key->kb, key->ku +#endif + ); #endif if (err != MP_OKAY) return MEMORY_E; +#ifdef WOLFSSL_ECC_BLIND_K + mp_forcezero(key->kb); +#endif /* read Qx */ if (err == MP_OKAY) { @@ -11335,6 +11544,11 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, err = wc_export_int(key->k, &keyRaw[0], &keySz, keySz, WC_TYPE_UNSIGNED_BIN); } + #ifdef WOLFSSL_ECC_BLIND_K + if (err == 0) { + err = ecc_blind_k_rng(key, NULL); + } + #endif if (err == MP_OKAY) { /* Create private key from external key buffer*/ @@ -11366,12 +11580,17 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, (word32)key->dp->size); } } + #ifdef WOLFSSL_ECC_BLIND_K + if (err == 0) { + err = ecc_blind_k_rng(key, NULL); + } + #endif #if defined(WOLFSSL_XILINX_CRYPT_VERSAL) if (err == MP_OKAY) { const word32 key_size = key->dp->size; word32 buf_size = key_size; - err = wc_export_int(key->k, key->privKey, - &buf_size, key_size, WC_TYPE_UNSIGNED_BIN); + err = wc_export_int(key, key->privKey, &buf_size, key_size, + WC_TYPE_UNSIGNED_BIN); mp_reverse(key->privKey, key_size); } #endif @@ -11389,7 +11608,7 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, #ifdef WOLFSSL_VALIDATE_ECC_IMPORT if (err == MP_OKAY) { err = wc_ecc_check_key(key); - if (err == IS_POINT_E && (mp_iszero(key->pubkey.x) || + if (err == WC_NO_ERR_TRACE(IS_POINT_E) && (mp_iszero(key->pubkey.x) || mp_iszero(key->pubkey.y))) { err = BAD_FUNC_ARG; } @@ -13611,17 +13830,17 @@ int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) * * @param [in, out] ctx ECIES context object. * @param [in] salt Salt to use with KDF. - * @param [in] len Length of salt in bytes. + * @param [in] sz Length of salt in bytes. * @return 0 on success. * @return BAD_FUNC_ARG when ctx is NULL or salt is NULL and len is not 0. */ -int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 len) +int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 sz) { - if (ctx == NULL || (salt == NULL && len != 0)) + if (ctx == NULL || (salt == NULL && sz != 0)) return BAD_FUNC_ARG; ctx->kdfSalt = salt; - ctx->kdfSaltSz = len; + ctx->kdfSaltSz = sz; if (ctx->protocol == REQ_RESP_CLIENT) { ctx->cliSt = ecCLI_SALT_SET; @@ -13633,9 +13852,37 @@ int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 len) return 0; } +/* Set your own salt. By default we generate a random salt for ourselves. + * This allows overriding that after init or reset. + * + * @param [in, out] ctx ECIES context object. + * @param [in] salt Salt to use for ourselves + * @param [in] sz Length of salt in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when ctx is NULL or salt is NULL and len is not 0. + */ +int wc_ecc_ctx_set_own_salt(ecEncCtx* ctx, const byte* salt, word32 sz) +{ + byte* saltBuffer; + + if (ctx == NULL || ctx->protocol == 0 || salt == NULL) + return BAD_FUNC_ARG; + + if (sz > EXCHANGE_SALT_SZ) + sz = EXCHANGE_SALT_SZ; + saltBuffer = (ctx->protocol == REQ_RESP_CLIENT) ? + ctx->clientSalt : + ctx->serverSalt; + XMEMSET(saltBuffer, 0, EXCHANGE_SALT_SZ); + XMEMCPY(saltBuffer, salt, sz); + + return 0; +} + + static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags) { - byte* saltBuffer = NULL; + byte* saltBuffer; if (ctx == NULL || flags == 0) return BAD_FUNC_ARG; @@ -13645,7 +13892,6 @@ static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags) return wc_RNG_GenerateBlock(ctx->rng, saltBuffer, EXCHANGE_SALT_SZ); } - static void ecc_ctx_init(ecEncCtx* ctx, int flags, WC_RNG* rng) { if (ctx) { @@ -13938,7 +14184,7 @@ int wc_ecc_encrypt_ex(ecc_key* privKey, ecc_key* pubKey, const byte* msg, &sharedSz); #endif } - while (ret == WC_PENDING_E); + while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); if (ret == 0) { #ifdef WOLFSSL_ECIES_ISO18033 @@ -14357,7 +14603,7 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret + pubKeySz, &sharedSz); #endif - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); } if (ret == 0) { #ifdef WOLFSSL_ECIES_ISO18033 @@ -14990,57 +15236,57 @@ static int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) #ifdef WOLFSSL_SMALL_STACK if (t1) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(t1); XFREE(t1, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (C) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(C); XFREE(C, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (Q) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(Q); XFREE(Q, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (S) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(S); XFREE(S, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (Z) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(Z); XFREE(Z, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (M) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(M); XFREE(M, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (T) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(T); XFREE(T, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (R) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(R); XFREE(R, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (N) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(N); XFREE(N, NULL, DYNAMIC_TYPE_ECC_BUFFER); } if (two) { - if (res != MP_INIT_E) + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(two); XFREE(two, NULL, DYNAMIC_TYPE_ECC_BUFFER); } #else - if (res != MP_INIT_E) { + if (res != WC_NO_ERR_TRACE(MP_INIT_E)) { mp_clear(t1); mp_clear(C); mp_clear(Q); diff --git a/src/wolfcrypt/src/eccsi.c b/src/wolfcrypt/src/eccsi.c index 0b12991..69d999b 100644 --- a/src/wolfcrypt/src/eccsi.c +++ b/src/wolfcrypt/src/eccsi.c @@ -1447,7 +1447,7 @@ static int eccsi_mulmod_point_add(EccsiKey* key, const mp_int* n, ecc_point* point, ecc_point* a, ecc_point* res, mp_digit mp, int map) { #if defined(WOLFSSL_HAVE_SP_ECC) && !defined(WOLFSSL_SP_NO_256) - int err = NOT_COMPILED_IN; + int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN); if ((key->ecc.idx != ECC_CUSTOM_IDX) && (ecc_sets[key->ecc.idx].id == ECC_SECP256R1)) { diff --git a/src/wolfcrypt/src/ed25519.c b/src/wolfcrypt/src/ed25519.c index f59b672..381b911 100644 --- a/src/wolfcrypt/src/ed25519.c +++ b/src/wolfcrypt/src/ed25519.c @@ -36,6 +36,15 @@ #include #ifdef HAVE_ED25519 +#if FIPS_VERSION3_GE(6,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$f") + #pragma const_seg(".fipsB$f") + #endif +#endif #include #include @@ -48,6 +57,15 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_ed25519_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000006 }; + int wolfCrypt_FIPS_ED25519_sanity(void) + { + return 0; + } +#endif + #ifdef FREESCALE_LTC_ECC #include #endif @@ -190,6 +208,56 @@ static int ed25519_hash(ed25519_key* key, const byte* in, word32 inLen, } #ifdef HAVE_ED25519_MAKE_KEY +#if FIPS_VERSION3_GE(6,0,0) +/* Performs a Pairwise Consistency Test on an Ed25519 key pair. + * + * @param [in] key Ed25519 key to test. + * @param [in] rng Random number generator to use to create random digest. + * @return 0 on success. + * @return ECC_PCT_E when signing or verification fail. + * @return Other -ve when random number generation fails. + */ +static int ed25519_pairwise_consistency_test(ed25519_key* key, WC_RNG* rng) +{ + int err = 0; + byte digest[WC_SHA512_DIGEST_SIZE]; + word32 digestLen = WC_SHA512_DIGEST_SIZE; + byte sig[ED25519_SIG_SIZE]; + word32 sigLen = ED25519_SIG_SIZE; + int res = 0; + + /* Generate a random digest to sign. */ + err = wc_RNG_GenerateBlock(rng, digest, digestLen); + if (err == 0) { + /* Sign digest without context. */ + err = wc_ed25519_sign_msg_ex(digest, digestLen, sig, &sigLen, key, + (byte)Ed25519, NULL, 0); + if (err != 0) { + /* Any sign failure means test failed. */ + err = ECC_PCT_E; + } + } + if (err == 0) { + /* Verify digest without context. */ + err = wc_ed25519_verify_msg_ex(sig, sigLen, digest, digestLen, &res, + key, (byte)Ed25519, NULL, 0); + if (err != 0) { + /* Any verification operation failure means test failed. */ + err = ECC_PCT_E; + } + /* Check whether the signature verified. */ + else if (res == 0) { + /* Test failed. */ + err = ECC_PCT_E; + } + } + + ForceZero(sig, sigLen); + + return err; +} +#endif + int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey, word32 pubKeySz) { @@ -252,7 +320,7 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) #ifdef WOLF_CRYPTO_CB if (key->devId != INVALID_DEVID) { ret = wc_CryptoCb_Ed25519Gen(rng, keySz, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -273,6 +341,13 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) /* put public key after private key, on the same buffer */ XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); +#if FIPS_VERSION3_GE(6,0,0) + ret = wc_ed25519_check_key(key); + if (ret == 0) { + ret = ed25519_pairwise_consistency_test(key, rng); + } +#endif + return ret; } #endif /* HAVE_ED25519_MAKE_KEY */ @@ -325,7 +400,7 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out, if (key->devId != INVALID_DEVID) { ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type, context, contextLen); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -623,15 +698,14 @@ static int ed25519_verify_msg_update_with_sha(const byte* msgSegment, return ed25519_hash_update(key, sha, msgSegment, msgSegmentLen); } -/* Low part of order in big endian. */ -static const byte ed25519_low_order[] = { - 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7, 0x9c, 0xd6, - 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed +/* ed25519 order in little endian. */ +static const byte ed25519_order[] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; -#define ED25519_SIG_LOW_ORDER_IDX \ - ((int)(ED25519_SIG_SIZE/2 + sizeof(ed25519_low_order) - 1)) - /* sig is array of bytes containing the signature sigLen is the length of sig byte array @@ -650,6 +724,7 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen, ge_p2 R; #endif int ret; + int i; /* sanity check on arguments */ if (sig == NULL || res == NULL || key == NULL) @@ -665,33 +740,19 @@ static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen, * 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed * = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed */ - if (sig[ED25519_SIG_SIZE-1] > 0x10) - return BAD_FUNC_ARG; - if (sig[ED25519_SIG_SIZE-1] == 0x10) { - int i = ED25519_SIG_SIZE-1; - int j; - - /* Check high zeros. */ - for (--i; i > ED25519_SIG_LOW_ORDER_IDX; i--) { - if (sig[i] > 0x00) - break; - } - /* Did we see all zeros up to lower order index? */ - if (i == ED25519_SIG_LOW_ORDER_IDX) { - /* Check lower part. */ - for (j = 0; j < (int)sizeof(ed25519_low_order); j++, i--) { - /* Check smaller. */ - if (sig[i] < ed25519_low_order[j]) - break; - /* Check bigger. */ - if (sig[i] > ed25519_low_order[j]) - return BAD_FUNC_ARG; - } - /* Check equal - all bytes match. */ - if (i == ED25519_SIG_SIZE/2 - 1) - return BAD_FUNC_ARG; - } + + /* Check S is not larger than or equal to order. */ + for (i = (int)sizeof(ed25519_order) - 1; i >= 0; i--) { + /* Bigger than order. */ + if (sig[ED25519_SIG_SIZE/2 + i] > ed25519_order[i]) + return BAD_FUNC_ARG; + /* Less than order. */ + if (sig[ED25519_SIG_SIZE/2 + i] < ed25519_order[i]) + break; } + /* Check equal - all bytes match. */ + if (i == -1) + return BAD_FUNC_ARG; /* uncompress A (public key), test if valid, and negate it */ #ifndef FREESCALE_LTC_ECC @@ -797,7 +858,7 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, if (key->devId != INVALID_DEVID) { ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key, type, context, contextLen); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1059,7 +1120,7 @@ int wc_ed25519_import_public_ex(const byte* in, word32 inLen, ed25519_key* key, if (ret == 0) { key->pubKeySet = 1; - if (key->privKeySet && (!trusted)) { + if (!trusted) { ret = wc_ed25519_check_key(key); } } @@ -1260,23 +1321,84 @@ int wc_ed25519_export_key(ed25519_key* key, #endif /* HAVE_ED25519_KEY_EXPORT */ -/* check the private and public keys match */ +/* Check the public key is valid. + * + * When private key available, check the calculated public key matches. + * When no private key, check Y is in range and an X is able to be calculated. + * + * @param [in] key Ed25519 private/public key. + * @return 0 otherwise. + * @return BAD_FUNC_ARG when key is NULL. + * @return PUBLIC_KEY_E when the public key is not set, doesn't match or is + * invalid. + * @return other -ve value on hash failure. + */ int wc_ed25519_check_key(ed25519_key* key) { int ret = 0; -#ifdef HAVE_ED25519_MAKE_KEY - ALIGN16 unsigned char pubKey[ED25519_PUB_KEY_SIZE]; - if (!key->pubKeySet) + /* Validate parameter. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Check we have a public key to check. */ + if ((ret == 0) && (!key->pubKeySet)) { ret = PUBLIC_KEY_E; - if (ret == 0) + } + +#ifdef HAVE_ED25519_MAKE_KEY + /* If we have a private key just make the public key and compare. */ + if ((ret == 0) && (key->privKeySet)) { + ALIGN16 unsigned char pubKey[ED25519_PUB_KEY_SIZE]; + ret = wc_ed25519_make_public(key, pubKey, sizeof(pubKey)); - if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0) - ret = PUBLIC_KEY_E; + if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0) + ret = PUBLIC_KEY_E; + } #else - (void)key; + (void)key; #endif /* HAVE_ED25519_MAKE_KEY */ + /* No private key (or ability to make a public key), check Y is valid. */ + if ((ret == 0) +#ifdef HAVE_ED25519_MAKE_KEY + && (!key->privKeySet) +#endif + ) { + /* Verify that Q is not identity element 0. + * 0 has no representation for Ed25519. */ + + /* Verify that xQ and yQ are integers in the interval [0, p - 1]. + * Only have yQ so check that ordinate. p = 2^255 - 19 */ + if ((key->p[ED25519_PUB_KEY_SIZE - 1] & 0x7f) == 0x7f) { + int i; + + ret = PUBLIC_KEY_E; + /* Check up to last byte. */ + for (i = ED25519_PUB_KEY_SIZE - 2; i > 0; i--) { + if (key->p[i] != 0xff) { + ret = 0; + break; + } + } + /* Bits are all one up to last byte - check less than -19. */ + if ((ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) && (key->p[0] < 0xed)) { + ret = 0; + } + } + + if (ret == 0) { + /* Verify that Q is on the curve. + * Uncompressing the public key will validate yQ. */ + ge_p3 A; + + if (ge_frombytes_negate_vartime(&A, key->p) != 0) { + ret = PUBLIC_KEY_E; + } + } + } + return ret; } diff --git a/src/wolfcrypt/src/ed448.c b/src/wolfcrypt/src/ed448.c index e93c212..e9e865c 100644 --- a/src/wolfcrypt/src/ed448.c +++ b/src/wolfcrypt/src/ed448.c @@ -38,6 +38,15 @@ #include #ifdef HAVE_ED448 +#if FIPS_VERSION3_GE(6,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$f") + #pragma const_seg(".fipsB$f") + #endif +#endif #include #include @@ -56,6 +65,14 @@ static const byte ed448Ctx[ED448CTX_SIZE+1] = "SigEd448"; #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_ed448_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000007 }; + int wolfCrypt_FIPS_ED448_sanity(void) + { + return 0; + } +#endif static int ed448_hash_init(ed448_key* key, wc_Shake *sha) { @@ -170,6 +187,56 @@ static int ed448_hash(ed448_key* key, const byte* in, word32 inLen, return ret; } +#if FIPS_VERSION3_GE(6,0,0) +/* Performs a Pairwise Consistency Test on an Ed448 key pair. + * + * @param [in] key Ed448 key to test. + * @param [in] rng Random number generator to use to create random digest. + * @return 0 on success. + * @return ECC_PCT_E when signing or verification fail. + * @return Other -ve when random number generation fails. + */ +static int ed448_pairwise_consistency_test(ed448_key* key, WC_RNG* rng) +{ + int err = 0; + byte digest[WC_SHA256_DIGEST_SIZE]; + word32 digestLen = WC_SHA256_DIGEST_SIZE; + byte sig[ED448_SIG_SIZE]; + word32 sigLen = ED448_SIG_SIZE; + int res = 0; + + /* Generate a random digest to sign. */ + err = wc_RNG_GenerateBlock(rng, digest, digestLen); + if (err == 0) { + /* Sign digest without context. */ + err = wc_ed448_sign_msg_ex(digest, digestLen, sig, &sigLen, key, Ed448, + NULL, 0); + if (err != 0) { + /* Any sign failure means test failed. */ + err = ECC_PCT_E; + } + } + if (err == 0) { + /* Verify digest without context. */ + err = wc_ed448_verify_msg_ex(sig, sigLen, digest, digestLen, &res, key, + Ed448, NULL, 0); + if (err != 0) { + /* Any verification operation failure means test failed. */ + err = ECC_PCT_E; + } + /* Check whether the signature verified. */ + else if (res == 0) { + /* Test failed. */ + err = ECC_PCT_E; + } + } + + ForceZero(sig, sigLen); + + return err; +} +#endif + /* Derive the public key for the private key. * * key [in] Ed448 key object. @@ -255,6 +322,13 @@ int wc_ed448_make_key(WC_RNG* rng, int keySz, ed448_key* key) if (ret == 0) { /* put public key after private key, on the same buffer */ XMEMMOVE(key->k + ED448_KEY_SIZE, key->p, ED448_PUB_KEY_SIZE); + + #if FIPS_VERSION3_GE(6,0,0) + ret = wc_ed448_check_key(key); + if (ret == 0) { + ret = ed448_pairwise_consistency_test(key, rng); + } + #endif } return ret; @@ -949,7 +1023,7 @@ int wc_ed448_import_public_ex(const byte* in, word32 inLen, ed448_key* key, ret = BAD_FUNC_ARG; } - if (inLen != ED448_PUB_KEY_SIZE) { + if ((inLen != ED448_PUB_KEY_SIZE) && (inLen != ED448_PUB_KEY_SIZE + 1)) { ret = BAD_FUNC_ARG; } @@ -978,7 +1052,7 @@ int wc_ed448_import_public_ex(const byte* in, word32 inLen, ed448_key* key, if (ret == 0) { key->pubKeySet = 1; - if (key->privKeySet && (!trusted)) { + if (!trusted) { /* Check untrusted public key data matches private key. */ ret = wc_ed448_check_key(key); } @@ -1226,31 +1300,91 @@ int wc_ed448_export_key(ed448_key* key, byte* priv, word32 *privSz, #endif /* HAVE_ED448_KEY_EXPORT */ -/* Check the public key of the ed448 key matches the private key. +/* Check the public key is valid. * - * key [in] Ed448 private/public key. - * returns BAD_FUNC_ARG when key is NULL, - * PUBLIC_KEY_E when the public key is not set or doesn't match, - * other -ve value on hash failure, - * 0 otherwise. + * When private key available, check the calculated public key matches. + * When no private key, check Y is in range and an X is able to be calculated. + * + * @param [in] key Ed448 private/public key. + * @return 0 otherwise. + * @return BAD_FUNC_ARG when key is NULL. + * @return PUBLIC_KEY_E when the public key is not set, doesn't match or is + * invalid. + * @return other -ve value on hash failure. */ int wc_ed448_check_key(ed448_key* key) { int ret = 0; unsigned char pubKey[ED448_PUB_KEY_SIZE]; + /* Validate parameter. */ if (key == NULL) { ret = BAD_FUNC_ARG; } + /* Check we have a public key to check. */ if (ret == 0 && !key->pubKeySet) { ret = PUBLIC_KEY_E; } - if (ret == 0) { + + /* If we have a private key just make the public key and compare. */ + if ((ret == 0) && key->privKeySet) { ret = wc_ed448_make_public(key, pubKey, sizeof(pubKey)); + if ((ret == 0) && (XMEMCMP(pubKey, key->p, ED448_PUB_KEY_SIZE) != 0)) { + ret = PUBLIC_KEY_E; + } } - if ((ret == 0) && (XMEMCMP(pubKey, key->p, ED448_PUB_KEY_SIZE) != 0)) { - ret = PUBLIC_KEY_E; + /* No private key, check Y is valid. */ + else if ((ret == 0) && (!key->privKeySet)) { + /* Verify that Q is not identity element 0. + * 0 has no representation for Ed448. */ + + /* Verify that xQ and yQ are integers in the interval [0, p - 1]. + * Only have yQ so check that ordinate. + * p = 2^448-2^224-1 = 0xff..fe..ff + */ + { + int i; + ret = PUBLIC_KEY_E; + + /* Check top part before 0xFE. */ + for (i = ED448_PUB_KEY_SIZE - 1; i > ED448_PUB_KEY_SIZE/2; i--) { + if (key->p[i] < 0xff) { + ret = 0; + break; + } + } + if (ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) { + /* Check against 0xFE. */ + if (key->p[ED448_PUB_KEY_SIZE/2] < 0xfe) { + ret = 0; + } + else if (key->p[ED448_PUB_KEY_SIZE/2] == 0xfe) { + /* Check bottom part before last byte. */ + for (i = ED448_PUB_KEY_SIZE/2 - 1; i > 0; i--) { + if (key->p[i] != 0xff) { + ret = 0; + break; + } + } + /* Check last byte. */ + if ((ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) && + (key->p[0] < 0xff)) { + ret = 0; + } + } + } + } + + if (ret == 0) { + /* Verify that Q is on the curve. + * Uncompressing the public key will validate yQ. */ + ge448_p2 A; + + if (ge448_from_bytes_negate_vartime(&A, key->p) != 0) { + ret = PUBLIC_KEY_E; + } + } } return ret; diff --git a/src/wolfcrypt/src/error.c b/src/wolfcrypt/src/error.c index eebd4db..2e25b60 100644 --- a/src/wolfcrypt/src/error.c +++ b/src/wolfcrypt/src/error.c @@ -34,6 +34,11 @@ #endif #ifndef NO_ERROR_STRINGS + +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES_H +#include +#endif + WOLFSSL_ABI const char* wc_GetErrorString(int error) { @@ -604,12 +609,37 @@ const char* wc_GetErrorString(int error) case KEY_EXHAUSTED_E: return "Key no longer usable for operation"; + case FIPS_INVALID_VER_E: + return "Invalid FIPS version defined, check length"; + + case FIPS_DATA_SZ_E: + return "FIPS Module Data too large adjust MAX_FIPS_DATA_SZ"; + + case FIPS_CODE_SZ_E: + return "FIPS Module Code too large adjust MAX_FIPS_CODE_SZ"; + + case KDF_SRTP_KAT_FIPS_E: + return "wolfCrypt FIPS SRTP-KDF Known Answer Test Failure"; + + case ED25519_KAT_FIPS_E: + return "wolfCrypt FIPS Ed25519 Known Answer Test Failure"; + + case ED448_KAT_FIPS_E: + return "wolfCrypt FIPS Ed448 Known Answer Test Failure"; + + case PBKDF2_KAT_FIPS_E: + return "wolfCrypt FIPS PBKDF2 Known Answer Test Failure"; + default: return "unknown error number"; } } +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES +#include +#endif + void wc_ErrorString(int error, char* buffer) { XSTRNCPY(buffer, wc_GetErrorString(error), WOLFSSL_MAX_ERROR_SZ); diff --git a/src/wolfcrypt/src/evp.c b/src/wolfcrypt/src/evp.c index a365ff6..42949fc 100644 --- a/src/wolfcrypt/src/evp.c +++ b/src/wolfcrypt/src/evp.c @@ -711,8 +711,19 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { - byte* tmp = (byte*)XREALLOC(ctx->authIn, + byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authInSz + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authIn, (size_t)ctx->authInSz); + XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authIn = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authIn, (size_t)(ctx->authInSz + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { ctx->authIn = tmp; XMEMCPY(ctx->authIn + ctx->authInSz, in, (size_t)inl); @@ -745,9 +756,19 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, /* Buffer input for one-shot API */ if (inl > 0) { byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authBufferLen + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authBuffer, (size_t)ctx->authBufferLen); + XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authBuffer = NULL; + } + #else tmp = (byte*)XREALLOC(ctx->authBuffer, (size_t)(ctx->authBufferLen + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { XMEMCPY(tmp + ctx->authBufferLen, in, (size_t)inl); ctx->authBufferLen += inl; @@ -817,8 +838,19 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, static int wolfSSL_EVP_CipherUpdate_CCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { - byte* tmp = (byte*)XREALLOC(ctx->authIn, + byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authInSz + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authIn, (size_t)ctx->authInSz); + XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authIn = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authIn, (size_t)(ctx->authInSz + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { ctx->authIn = tmp; XMEMCPY(ctx->authIn + ctx->authInSz, in, (size_t)inl); @@ -843,9 +875,19 @@ static int wolfSSL_EVP_CipherUpdate_CCM(WOLFSSL_EVP_CIPHER_CTX *ctx, /* Buffer input for one-shot API */ if (inl > 0) { byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authBufferLen + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authBuffer, (size_t)ctx->authBufferLen); + XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authBuffer = NULL; + } + #else tmp = (byte*)XREALLOC(ctx->authBuffer, (size_t)(ctx->authBufferLen + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { XMEMCPY(tmp + ctx->authBufferLen, in, (size_t)inl); ctx->authBufferLen += inl; @@ -875,8 +917,19 @@ static int wolfSSL_EVP_CipherUpdate_AriaGCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { - byte* tmp = (byte*)XREALLOC(ctx->authIn, + byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)ctx->authInSz + inl, NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authIn, (size_t)ctx->authInSz); + XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authIn = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authIn, (size_t)ctx->authInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { ctx->authIn = tmp; XMEMCPY(ctx->authIn + ctx->authInSz, in, (size_t)inl); @@ -905,9 +958,18 @@ static int wolfSSL_EVP_CipherUpdate_AriaGCM(WOLFSSL_EVP_CIPHER_CTX *ctx, if (ctx->enc == 0) { /* Append extra space for the tag */ size = WC_ARIA_GCM_GET_CIPHERTEXT_SIZE(size); } - tmp = (byte*)XREALLOC(ctx->authBuffer, - (size_t)size, NULL, - DYNAMIC_TYPE_OPENSSL); + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)size, NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authBuffer, (size_t)ctx->authBufferLen); + XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authBuffer = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authBuffer, (size_t)size, NULL, + DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { XMEMCPY(tmp + ctx->authBufferLen, in, (size_t)inl); ctx->authBufferLen += inl; @@ -2693,9 +2755,19 @@ int wolfSSL_EVP_PKEY_CTX_add1_hkdf_info(WOLFSSL_EVP_PKEY_CTX* ctx, if (ret == WOLFSSL_SUCCESS && info != NULL && infoSz > 0) { unsigned char* p; /* If there's already info in the buffer, append. */ + #ifdef WOLFSSL_NO_REALLOC + p = (byte*)XMALLOC((size_t)(ctx->pkey->hkdfInfoSz + (word32)infoSz), NULL, + DYNAMIC_TYPE_INFO); + if (p != NULL) { + XMEMCPY(p, ctx->pkey->hkdfInfo, (size_t)ctx->pkey->hkdfInfoSz); + XFREE(ctx->pkey->hkdfInfo, NULL, DYNAMIC_TYPE_INFO); + ctx->pkey->hkdfInfo = NULL; + } + #else p = (byte*)XREALLOC(ctx->pkey->hkdfInfo, (size_t)(ctx->pkey->hkdfInfoSz + (word32)infoSz), NULL, DYNAMIC_TYPE_INFO); + #endif if (p == NULL) { WOLFSSL_MSG("Failed to reallocate larger HKDF info buffer."); ret = WOLFSSL_FAILURE; @@ -3211,6 +3283,8 @@ int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey) if (pkey == NULL) return 0; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_bits"); if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0; + if (bytes < 0) + return 0; return bytes*8; } @@ -4275,23 +4349,39 @@ static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx, int ret; if (ctx->isHMAC) { - Hmac hmacCopy; - - if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS) +#ifdef WOLFSSL_SMALL_STACK + Hmac *hmacCopy = (Hmac *)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_OPENSSL); + if (hmacCopy == NULL) return WOLFSSL_FAILURE; - ret = wc_HmacFinal(&hmacCopy, md) == 0; - wc_HmacFree(&hmacCopy); +#else + Hmac hmacCopy[1]; +#endif + ret = wolfSSL_HmacCopy(hmacCopy, &ctx->hash.hmac); + if (ret == WOLFSSL_SUCCESS) + ret = wc_HmacFinal(hmacCopy, md) == 0; + wc_HmacFree(hmacCopy); +#ifdef WOLFSSL_SMALL_STACK + XFREE(hmacCopy, NULL, DYNAMIC_TYPE_OPENSSL); +#endif return ret; } else { - WOLFSSL_EVP_MD_CTX ctxCopy; - wolfSSL_EVP_MD_CTX_init(&ctxCopy); - - if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS) +#ifdef WOLFSSL_SMALL_STACK + WOLFSSL_EVP_MD_CTX *ctxCopy = (WOLFSSL_EVP_MD_CTX *)XMALLOC(sizeof(WOLFSSL_EVP_MD_CTX), NULL, DYNAMIC_TYPE_OPENSSL); + if (ctxCopy == NULL) return WOLFSSL_FAILURE; +#else + WOLFSSL_EVP_MD_CTX ctxCopy[1]; +#endif + wolfSSL_EVP_MD_CTX_init(ctxCopy); - ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen); - wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy); + ret = wolfSSL_EVP_MD_CTX_copy_ex(ctxCopy, ctx); + if (ret == WOLFSSL_SUCCESS) + ret = wolfSSL_EVP_DigestFinal(ctxCopy, md, mdlen); + wolfSSL_EVP_MD_CTX_cleanup(ctxCopy); +#ifdef WOLFSSL_SMALL_STACK + XFREE(ctxCopy, NULL, DYNAMIC_TYPE_OPENSSL); +#endif return ret; } } @@ -5468,7 +5558,7 @@ void wolfSSL_EVP_init(void) #endif /* HAVE_AES_CBC */ #ifdef WOLFSSL_AES_CFB -#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0)) #ifdef WOLFSSL_AES_128 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void) { @@ -8465,7 +8555,7 @@ void wolfSSL_EVP_init(void) } if (ret < 0) { - if (ret == AES_GCM_AUTH_E) { + if (ret == WC_NO_ERR_TRACE(AES_GCM_AUTH_E)) { WOLFSSL_MSG("wolfSSL_EVP_Cipher failure: bad AES-GCM tag."); } WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); @@ -8543,7 +8633,7 @@ static int PopulateRSAEvpPkeyDer(WOLFSSL_EVP_PKEY *pkey) if (key->pkcs8HeaderSz) { ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, NULL, (word32)derSz, RSAk, NULL, 0); - if (ret == LENGTH_ONLY_E) + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) ret = 0; } #endif @@ -8917,7 +9007,7 @@ int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) ret = wc_DhParamsToDer(dhkey,NULL,&derSz); } - if (derSz == 0 || ret != LENGTH_ONLY_E) { + if (derSz == 0 || ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Failed to get size of DH Key"); return WOLFSSL_FAILURE; } @@ -9060,7 +9150,7 @@ static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) #ifdef HAVE_PKCS8 if (key->pkcs8HeaderSz) { /* when key has pkcs8 header the pkey should too */ - if (wc_EccKeyToPKCS8(ecc, NULL, (word32*)&derSz) == LENGTH_ONLY_E) { + if (wc_EccKeyToPKCS8(ecc, NULL, (word32*)&derSz) == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { derBuf = (byte*)XMALLOC((size_t)derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); if (derBuf) { @@ -9112,8 +9202,17 @@ static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) } else if (ecc->type == ECC_PUBLICKEY) { if ((derSz = wc_EccPublicKeyDerSize(ecc, 1)) > 0) { - derBuf = (byte*)XREALLOC(pkey->pkey.ptr, (size_t)derSz, NULL, + #ifdef WOLFSSL_NO_REALLOC + derBuf = (byte*)XMALLOC((size_t)derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); + if (derBuf != NULL) { + XMEMCPY(derBuf, pkey->pkey.ptr, (size_t)pkey->pkey_sz); + XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_OPENSSL); + pkey->pkey.ptr = NULL; + } + #else + derBuf = (byte*)XREALLOC(pkey->pkey.ptr, (size_t)derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); + #endif if (derBuf != NULL) { pkey->pkey.ptr = (char*)derBuf; if ((derSz = wc_EccPublicKeyToDer(ecc, derBuf, (word32)derSz, @@ -9205,7 +9304,7 @@ const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) int wolfSSL_EVP_MD_pkey_type(const WOLFSSL_EVP_MD* type) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); WOLFSSL_ENTER("wolfSSL_EVP_MD_pkey_type"); @@ -9229,6 +9328,9 @@ int wolfSSL_EVP_MD_pkey_type(const WOLFSSL_EVP_MD* type) ret = NID_sha512WithRSAEncryption; } } + else { + ret = BAD_FUNC_ARG; + } WOLFSSL_LEAVE("wolfSSL_EVP_MD_pkey_type", ret); @@ -12432,7 +12534,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, (word32)(BASE64_DECODE_BLOCK_SIZE - ctx->remaining), (word32)inl); for ( i = 0; cpySz > 0 && inLen > 0; i++) { - if (Base64_SkipNewline(in, &inLen, &j) == ASN_INPUT_E) { + if (Base64_SkipNewline(in, &inLen, &j) == WC_NO_ERR_TRACE(ASN_INPUT_E)) { return -1; /* detected an illegal char in input */ } c = in[j++]; @@ -12472,7 +12574,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, */ while (inLen > 3) { if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12486,7 +12588,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12497,7 +12599,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, e[1] = in[j++]; inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12508,7 +12610,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, e[2] = in[j++]; inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12615,8 +12717,10 @@ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, inLen = (word32)ctx->remaining; if ((res = Base64_SkipNewline(ctx->data, &inLen, &j)) != 0) { *outl = 0; - if (res == BUFFER_E) /* means no valid data to decode in buffer */ + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { + /* means no valid data to decode in buffer */ return 1; /* returns as success with no output */ + } else return -1; } diff --git a/src/wolfcrypt/src/ext_kyber.c b/src/wolfcrypt/src/ext_kyber.c index 0e694c0..77ab430 100644 --- a/src/wolfcrypt/src/ext_kyber.c +++ b/src/wolfcrypt/src/ext_kyber.c @@ -329,7 +329,7 @@ int wc_KyberKey_MakeKey(KyberKey* key, WC_RNG* rng) { ret = wc_CryptoCb_MakePqcKemKey(rng, WC_PQC_KEM_TYPE_KYBER, key->type, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; @@ -440,7 +440,7 @@ int wc_KyberKey_Encapsulate(KyberKey* key, unsigned char* ct, unsigned char* ss, ) { ret = wc_CryptoCb_PqcEncapsulate(ct, ctlen, ss, KYBER_SS_SZ, rng, WC_PQC_KEM_TYPE_KYBER, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; @@ -549,7 +549,7 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, ) { ret = wc_CryptoCb_PqcDecapsulate(ct, ctlen, ss, KYBER_SS_SZ, WC_PQC_KEM_TYPE_KYBER, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; @@ -608,7 +608,8 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, * @return NOT_COMPILED_IN when key type is not supported. * @return BUFFER_E when len is not the correct size. */ -int wc_KyberKey_DecodePrivateKey(KyberKey* key, unsigned char* in, word32 len) +int wc_KyberKey_DecodePrivateKey(KyberKey* key, const unsigned char* in, + word32 len) { int ret = 0; word32 privLen = 0; @@ -647,7 +648,8 @@ int wc_KyberKey_DecodePrivateKey(KyberKey* key, unsigned char* in, word32 len) * @return NOT_COMPILED_IN when key type is not supported. * @return BUFFER_E when len is not the correct size. */ -int wc_KyberKey_DecodePublicKey(KyberKey* key, unsigned char* in, word32 len) +int wc_KyberKey_DecodePublicKey(KyberKey* key, const unsigned char* in, + word32 len) { int ret = 0; word32 pubLen = 0; diff --git a/src/wolfcrypt/src/ext_lms.c b/src/wolfcrypt/src/ext_lms.c index a515507..7a59576 100644 --- a/src/wolfcrypt/src/ext_lms.c +++ b/src/wolfcrypt/src/ext_lms.c @@ -160,38 +160,77 @@ const char * wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm) { switch (lmsParm) { case WC_LMS_PARM_NONE: - return "LMS_NONE"; - + return "LMS/HSS NONE"; + case WC_LMS_PARM_L1_H5_W1: + return "LMS/HSS L1_H5_W1"; + case WC_LMS_PARM_L1_H5_W2: + return "LMS/HSS L1_H5_W2"; + case WC_LMS_PARM_L1_H5_W4: + return "LMS/HSS L1_H5_W4"; + case WC_LMS_PARM_L1_H5_W8: + return "LMS/HSS L1_H5_W8"; + case WC_LMS_PARM_L1_H10_W2: + return "LMS/HSS L1_H10_W2"; + case WC_LMS_PARM_L1_H10_W4: + return "LMS/HSS L1_H10_W4"; + case WC_LMS_PARM_L1_H10_W8: + return "LMS/HSS L1_H10_W8"; case WC_LMS_PARM_L1_H15_W2: return "LMS/HSS L1_H15_W2"; - case WC_LMS_PARM_L1_H15_W4: return "LMS/HSS L1_H15_W4"; - + case WC_LMS_PARM_L1_H15_W8: + return "LMS/HSS L1_H15_W8"; + case WC_LMS_PARM_L1_H20_W2: + return "LMS/HSS L1_H20_W2"; + case WC_LMS_PARM_L1_H20_W4: + return "LMS/HSS L1_H20_W4"; + case WC_LMS_PARM_L1_H20_W8: + return "LMS/HSS L1_H20_W8"; + case WC_LMS_PARM_L2_H5_W2: + return "LMS/HSS L2_H5_W2"; + case WC_LMS_PARM_L2_H5_W4: + return "LMS/HSS L2_H5_W4"; + case WC_LMS_PARM_L2_H5_W8: + return "LMS/HSS L2_H5_W8"; case WC_LMS_PARM_L2_H10_W2: return "LMS/HSS L2_H10_W2"; - case WC_LMS_PARM_L2_H10_W4: return "LMS/HSS L2_H10_W4"; - case WC_LMS_PARM_L2_H10_W8: return "LMS/HSS L2_H10_W8"; - + case WC_LMS_PARM_L2_H15_W2: + return "LMS/HSS L2_H15_W2"; + case WC_LMS_PARM_L2_H15_W4: + return "LMS/HSS L2_H15_W4"; + case WC_LMS_PARM_L2_H15_W8: + return "LMS/HSS L2_H15_W8"; + case WC_LMS_PARM_L2_H20_W2: + return "LMS/HSS L2_H20_W2"; + case WC_LMS_PARM_L2_H20_W4: + return "LMS/HSS L2_H20_W4"; + case WC_LMS_PARM_L2_H20_W8: + return "LMS/HSS L2_H20_W8"; case WC_LMS_PARM_L3_H5_W2: return "LMS/HSS L3_H5_W2"; - case WC_LMS_PARM_L3_H5_W4: return "LMS/HSS L3_H5_W4"; - case WC_LMS_PARM_L3_H5_W8: return "LMS/HSS L3_H5_W8"; - case WC_LMS_PARM_L3_H10_W4: return "LMS/HSS L3_H10_W4"; - + case WC_LMS_PARM_L3_H10_W8: + return "LMS/HSS L3_H10_W8"; + case WC_LMS_PARM_L4_H5_W2: + return "LMS/HSS L4_H5_W2"; + case WC_LMS_PARM_L4_H5_W4: + return "LMS/HSS L4_H5_W4"; case WC_LMS_PARM_L4_H5_W8: return "LMS/HSS L4_H5_W8"; - + case WC_LMS_PARM_L4_H10_W4: + return "LMS/HSS L4_H10_W4"; + case WC_LMS_PARM_L4_H10_W8: + return "LMS/HSS L4_H10_W8"; default: WOLFSSL_MSG("error: invalid LMS parameter"); break; @@ -279,36 +318,76 @@ int wc_LmsKey_SetLmsParm(LmsKey * key, enum wc_LmsParm lmsParm) /* If NONE is passed, default to the lowest predefined set. */ switch (lmsParm) { case WC_LMS_PARM_NONE: + case WC_LMS_PARM_L1_H5_W1: + return wc_LmsKey_SetParameters(key, 1, 5, 1); + case WC_LMS_PARM_L1_H5_W2: + return wc_LmsKey_SetParameters(key, 1, 5, 2); + case WC_LMS_PARM_L1_H5_W4: + return wc_LmsKey_SetParameters(key, 1, 5, 4); + case WC_LMS_PARM_L1_H5_W8: + return wc_LmsKey_SetParameters(key, 1, 5, 8); + case WC_LMS_PARM_L1_H10_W2: + return wc_LmsKey_SetParameters(key, 1, 10, 2); + case WC_LMS_PARM_L1_H10_W4: + return wc_LmsKey_SetParameters(key, 1, 10, 4); + case WC_LMS_PARM_L1_H10_W8: + return wc_LmsKey_SetParameters(key, 1, 10, 8); case WC_LMS_PARM_L1_H15_W2: return wc_LmsKey_SetParameters(key, 1, 15, 2); - case WC_LMS_PARM_L1_H15_W4: return wc_LmsKey_SetParameters(key, 1, 15, 4); - + case WC_LMS_PARM_L1_H15_W8: + return wc_LmsKey_SetParameters(key, 1, 15, 8); + case WC_LMS_PARM_L1_H20_W2: + return wc_LmsKey_SetParameters(key, 1, 20, 2); + case WC_LMS_PARM_L1_H20_W4: + return wc_LmsKey_SetParameters(key, 1, 20, 4); + case WC_LMS_PARM_L1_H20_W8: + return wc_LmsKey_SetParameters(key, 1, 20, 8); + case WC_LMS_PARM_L2_H5_W2: + return wc_LmsKey_SetParameters(key, 2, 5, 2); + case WC_LMS_PARM_L2_H5_W4: + return wc_LmsKey_SetParameters(key, 2, 5, 4); + case WC_LMS_PARM_L2_H5_W8: + return wc_LmsKey_SetParameters(key, 2, 5, 8); case WC_LMS_PARM_L2_H10_W2: return wc_LmsKey_SetParameters(key, 2, 10, 2); - case WC_LMS_PARM_L2_H10_W4: return wc_LmsKey_SetParameters(key, 2, 10, 4); - case WC_LMS_PARM_L2_H10_W8: return wc_LmsKey_SetParameters(key, 2, 10, 8); - + case WC_LMS_PARM_L2_H15_W2: + return wc_LmsKey_SetParameters(key, 2, 15, 2); + case WC_LMS_PARM_L2_H15_W4: + return wc_LmsKey_SetParameters(key, 2, 15, 4); + case WC_LMS_PARM_L2_H15_W8: + return wc_LmsKey_SetParameters(key, 2, 15, 8); + case WC_LMS_PARM_L2_H20_W2: + return wc_LmsKey_SetParameters(key, 2, 20, 2); + case WC_LMS_PARM_L2_H20_W4: + return wc_LmsKey_SetParameters(key, 2, 20, 4); + case WC_LMS_PARM_L2_H20_W8: + return wc_LmsKey_SetParameters(key, 2, 20, 8); case WC_LMS_PARM_L3_H5_W2: return wc_LmsKey_SetParameters(key, 3, 5, 2); - case WC_LMS_PARM_L3_H5_W4: return wc_LmsKey_SetParameters(key, 3, 5, 4); - case WC_LMS_PARM_L3_H5_W8: return wc_LmsKey_SetParameters(key, 3, 5, 8); - case WC_LMS_PARM_L3_H10_W4: return wc_LmsKey_SetParameters(key, 3, 10, 4); - + case WC_LMS_PARM_L3_H10_W8: + return wc_LmsKey_SetParameters(key, 3, 10, 8); + case WC_LMS_PARM_L4_H5_W2: + return wc_LmsKey_SetParameters(key, 4, 5, 2); + case WC_LMS_PARM_L4_H5_W4: + return wc_LmsKey_SetParameters(key, 4, 5, 4); case WC_LMS_PARM_L4_H5_W8: return wc_LmsKey_SetParameters(key, 4, 5, 8); - + case WC_LMS_PARM_L4_H10_W4: + return wc_LmsKey_SetParameters(key, 4, 10, 4); + case WC_LMS_PARM_L4_H10_W8: + return wc_LmsKey_SetParameters(key, 4, 10, 8); default: WOLFSSL_MSG("error: invalid LMS parameter set"); break; @@ -507,7 +586,7 @@ void wc_LmsKey_Free(LmsKey* key) * * Returns 0 on success. * */ -int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb) +int wc_LmsKey_SetWriteCb(LmsKey * key, wc_lms_write_private_key_cb write_cb) { if (key == NULL || write_cb == NULL) { return BAD_FUNC_ARG; @@ -531,7 +610,7 @@ int wc_LmsKey_SetWriteCb(LmsKey * key, write_private_key_cb write_cb) * * Returns 0 on success. * */ -int wc_LmsKey_SetReadCb(LmsKey * key, read_private_key_cb read_cb) +int wc_LmsKey_SetReadCb(LmsKey * key, wc_lms_read_private_key_cb read_cb) { if (key == NULL || read_cb == NULL) { return BAD_FUNC_ARG; diff --git a/src/wolfcrypt/src/ext_xmss.c b/src/wolfcrypt/src/ext_xmss.c index 84498d9..9ce012e 100644 --- a/src/wolfcrypt/src/ext_xmss.c +++ b/src/wolfcrypt/src/ext_xmss.c @@ -307,7 +307,7 @@ void wc_XmssKey_Free(XmssKey* key) * returns BAD_FUNC_ARG when a parameter is NULL. * returns -1 on failure. * */ -int wc_XmssKey_SetWriteCb(XmssKey * key, write_private_key_cb write_cb) +int wc_XmssKey_SetWriteCb(XmssKey * key, wc_xmss_write_private_key_cb write_cb) { if (key == NULL || write_cb == NULL) { return BAD_FUNC_ARG; @@ -336,7 +336,7 @@ int wc_XmssKey_SetWriteCb(XmssKey * key, write_private_key_cb write_cb) * returns BAD_FUNC_ARG when a parameter is NULL. * returns -1 on failure. * */ -int wc_XmssKey_SetReadCb(XmssKey * key, read_private_key_cb read_cb) +int wc_XmssKey_SetReadCb(XmssKey * key, wc_xmss_read_private_key_cb read_cb) { if (key == NULL || read_cb == NULL) { return BAD_FUNC_ARG; diff --git a/src/wolfcrypt/src/falcon.c b/src/wolfcrypt/src/falcon.c index 2645db6..04309db 100644 --- a/src/wolfcrypt/src/falcon.c +++ b/src/wolfcrypt/src/falcon.c @@ -75,7 +75,7 @@ int wc_falcon_sign_msg(const byte* in, word32 inLen, { ret = wc_CryptoCb_PqcSign(in, inLen, out, outLen, rng, WC_PQC_SIG_TYPE_FALCON, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; @@ -173,7 +173,7 @@ int wc_falcon_verify_msg(const byte* sig, word32 sigLen, const byte* msg, { ret = wc_CryptoCb_PqcVerify(sig, sigLen, msg, msgLen, res, WC_PQC_SIG_TYPE_FALCON, key); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; @@ -282,7 +282,7 @@ int wc_falcon_init_id(falcon_key* key, const unsigned char* id, int len, key->idLen = len; } - /* Set the maxiumum level here */ + /* Set the maximum level here */ wc_falcon_set_level(key, 5); return ret; @@ -309,7 +309,7 @@ int wc_falcon_init_label(falcon_key* key, const char* label, void* heap, key->labelLen = labelLen; } - /* Set the maxiumum level here */ + /* Set the maximum level here */ wc_falcon_set_level(key, 5); return ret; @@ -469,7 +469,8 @@ static int parse_private_key(const byte* priv, word32 privSz, /* At this point, it is still a PKCS8 private key. */ if ((ret = ToTraditionalInline(priv, &idx, privSz)) < 0) { - return ret; + /* ignore error, did not have PKCS8 header */ + (void)ret; } /* Now it is a octet_string(concat(priv,pub)) */ @@ -846,11 +847,11 @@ int wc_Falcon_PrivateKeyDecode(const byte* input, word32* inOutIdx, pubKey, &pubKeyLen, keytype); if (ret == 0) { if (pubKeyLen == 0) { - ret = wc_falcon_import_private_only(input, inSz, key); + ret = wc_falcon_import_private_key(input, inSz, NULL, 0, key); } else { - ret = wc_falcon_import_private_key(privKey, privKeyLen, - pubKey, pubKeyLen, key); + ret = wc_falcon_import_private_key(input, inSz, pubKey, + pubKeyLen, key); } } return ret; @@ -912,7 +913,7 @@ int wc_Falcon_PublicKeyToDer(falcon_key* key, byte* output, word32 inLen, word32 pubKeyLen = (word32)sizeof(pubKey); int keytype = 0; - if (key == NULL || output == NULL) { + if (key == NULL) { return BAD_FUNC_ARG; } diff --git a/src/wolfcrypt/src/fe_448.c b/src/wolfcrypt/src/fe_448.c index 73853b7..36c6096 100644 --- a/src/wolfcrypt/src/fe_448.c +++ b/src/wolfcrypt/src/fe_448.c @@ -1437,56 +1437,56 @@ void fe448_to_bytes(unsigned char* b, const sword32* a) b[ 0] = (byte)(in0 >> 0); b[ 1] = (byte)(in0 >> 8); b[ 2] = (byte)(in0 >> 16); - b[ 3] = (byte)(in0 >> 24) + ((in1 >> 0) << 4); + b[ 3] = (byte)((in0 >> 24) + ((in1 >> 0) << 4)); b[ 4] = (byte)(in1 >> 4); b[ 5] = (byte)(in1 >> 12); b[ 6] = (byte)(in1 >> 20); b[ 7] = (byte)(in2 >> 0); b[ 8] = (byte)(in2 >> 8); b[ 9] = (byte)(in2 >> 16); - b[10] = (byte)(in2 >> 24) + ((in3 >> 0) << 4); + b[10] = (byte)((in2 >> 24) + ((in3 >> 0) << 4)); b[11] = (byte)(in3 >> 4); b[12] = (byte)(in3 >> 12); b[13] = (byte)(in3 >> 20); b[14] = (byte)(in4 >> 0); b[15] = (byte)(in4 >> 8); b[16] = (byte)(in4 >> 16); - b[17] = (byte)(in4 >> 24) + ((in5 >> 0) << 4); + b[17] = (byte)((in4 >> 24) + ((in5 >> 0) << 4)); b[18] = (byte)(in5 >> 4); b[19] = (byte)(in5 >> 12); b[20] = (byte)(in5 >> 20); b[21] = (byte)(in6 >> 0); b[22] = (byte)(in6 >> 8); b[23] = (byte)(in6 >> 16); - b[24] = (byte)(in6 >> 24) + ((in7 >> 0) << 4); + b[24] = (byte)((in6 >> 24) + ((in7 >> 0) << 4)); b[25] = (byte)(in7 >> 4); b[26] = (byte)(in7 >> 12); b[27] = (byte)(in7 >> 20); b[28] = (byte)(in8 >> 0); b[29] = (byte)(in8 >> 8); b[30] = (byte)(in8 >> 16); - b[31] = (byte)(in8 >> 24) + ((in9 >> 0) << 4); + b[31] = (byte)((in8 >> 24) + ((in9 >> 0) << 4)); b[32] = (byte)(in9 >> 4); b[33] = (byte)(in9 >> 12); b[34] = (byte)(in9 >> 20); b[35] = (byte)(in10 >> 0); b[36] = (byte)(in10 >> 8); b[37] = (byte)(in10 >> 16); - b[38] = (byte)(in10 >> 24) + ((in11 >> 0) << 4); + b[38] = (byte)((in10 >> 24) + ((in11 >> 0) << 4)); b[39] = (byte)(in11 >> 4); b[40] = (byte)(in11 >> 12); b[41] = (byte)(in11 >> 20); b[42] = (byte)(in12 >> 0); b[43] = (byte)(in12 >> 8); b[44] = (byte)(in12 >> 16); - b[45] = (byte)(in12 >> 24) + ((in13 >> 0) << 4); + b[45] = (byte)((in12 >> 24) + ((in13 >> 0) << 4)); b[46] = (byte)(in13 >> 4); b[47] = (byte)(in13 >> 12); b[48] = (byte)(in13 >> 20); b[49] = (byte)(in14 >> 0); b[50] = (byte)(in14 >> 8); b[51] = (byte)(in14 >> 16); - b[52] = (byte)(in14 >> 24) + ((in15 >> 0) << 4); + b[52] = (byte)((in14 >> 24) + ((in15 >> 0) << 4)); b[53] = (byte)(in15 >> 4); b[54] = (byte)(in15 >> 12); b[55] = (byte)(in15 >> 20); @@ -1834,6 +1834,7 @@ static WC_INLINE void fe448_mul_8(sword32* r, const sword32* a, const sword32* b sword64 t13 = (sword64)a[ 6] * b[ 7]; sword64 t113 = (sword64)a[ 7] * b[ 6]; sword64 t14 = (sword64)a[ 7] * b[ 7]; + sword64 o, t15; t1 += t101; t2 += t102; t2 += t202; t3 += t103; t3 += t203; t3 += t303; @@ -1850,8 +1851,8 @@ static WC_INLINE void fe448_mul_8(sword32* r, const sword32* a, const sword32* b t11 += t111; t11 += t211; t11 += t311; t12 += t112; t12 += t212; t13 += t113; - sword64 o = t14 >> 28; - sword64 t15 = o; + o = t14 >> 28; + t15 = o; t14 -= o << 28; o = (t0 >> 28); t1 += o; t = o << 28; t0 -= t; o = (t1 >> 28); t2 += o; t = o << 28; t1 -= t; diff --git a/src/wolfcrypt/src/fe_operations.c b/src/wolfcrypt/src/fe_operations.c index 18e2b05..704b455 100644 --- a/src/wolfcrypt/src/fe_operations.c +++ b/src/wolfcrypt/src/fe_operations.c @@ -45,7 +45,7 @@ #elif defined(WOLFSSL_ARMASM) /* Assembly code in fe_armv[78]_x25519.* */ #elif defined(CURVED25519_128BIT) -#include "fe_x25519_128.i" +#include "fe_x25519_128.h" #else #if defined(HAVE_CURVE25519) || \ @@ -58,24 +58,24 @@ t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on context. */ -word64 load_3(const unsigned char *in) +sword64 load_3(const unsigned char *in) { word64 result; result = (word64) in[0]; result |= ((word64) in[1]) << 8; result |= ((word64) in[2]) << 16; - return result; + return (sword64)result; } -word64 load_4(const unsigned char *in) +sword64 load_4(const unsigned char *in) { word64 result; result = (word64) in[0]; result |= ((word64) in[1]) << 8; result |= ((word64) in[2]) << 16; result |= ((word64) in[3]) << 24; - return result; + return (sword64)result; } #endif @@ -170,8 +170,8 @@ int curve25519(byte* q, const byte* n, const byte* p) #endif b &= 1; swap ^= b; - fe_cswap(x2,x3,swap); - fe_cswap(z2,z3,swap); + fe_cswap(x2,x3,(int)swap); + fe_cswap(z2,z3,(int)swap); swap = b; /* montgomery */ @@ -194,8 +194,8 @@ int curve25519(byte* q, const byte* n, const byte* p) fe_mul(z3,x1,z2); fe_mul(z2,tmp1,tmp0); } - fe_cswap(x2,x3,swap); - fe_cswap(z2,z3,swap); + fe_cswap(x2,x3,(int)swap); + fe_cswap(z2,z3,(int)swap); fe_invert(z2,z2); fe_mul(x2,x2,z2); diff --git a/src/wolfcrypt/src/ge_448.c b/src/wolfcrypt/src/ge_448.c index 5ce8ea7..d2033af 100644 --- a/src/wolfcrypt/src/ge_448.c +++ b/src/wolfcrypt/src/ge_448.c @@ -5453,56 +5453,56 @@ void sc448_reduce(byte* b) b[ 0] = (byte)(d[0 ] >> 0); b[ 1] = (byte)(d[0 ] >> 8); b[ 2] = (byte)(d[0 ] >> 16); - b[ 3] = (byte)(d[0 ] >> 24) + ((d[1 ] >> 0) << 4); + b[ 3] = (byte)((d[0 ] >> 24) + ((d[1 ] >> 0) << 4)); b[ 4] = (byte)(d[1 ] >> 4); b[ 5] = (byte)(d[1 ] >> 12); b[ 6] = (byte)(d[1 ] >> 20); b[ 7] = (byte)(d[2 ] >> 0); b[ 8] = (byte)(d[2 ] >> 8); b[ 9] = (byte)(d[2 ] >> 16); - b[10] = (byte)(d[2 ] >> 24) + ((d[3 ] >> 0) << 4); + b[10] = (byte)((d[2 ] >> 24) + ((d[3 ] >> 0) << 4)); b[11] = (byte)(d[3 ] >> 4); b[12] = (byte)(d[3 ] >> 12); b[13] = (byte)(d[3 ] >> 20); b[14] = (byte)(d[4 ] >> 0); b[15] = (byte)(d[4 ] >> 8); b[16] = (byte)(d[4 ] >> 16); - b[17] = (byte)(d[4 ] >> 24) + ((d[5 ] >> 0) << 4); + b[17] = (byte)((d[4 ] >> 24) + ((d[5 ] >> 0) << 4)); b[18] = (byte)(d[5 ] >> 4); b[19] = (byte)(d[5 ] >> 12); b[20] = (byte)(d[5 ] >> 20); b[21] = (byte)(d[6 ] >> 0); b[22] = (byte)(d[6 ] >> 8); b[23] = (byte)(d[6 ] >> 16); - b[24] = (byte)(d[6 ] >> 24) + ((d[7 ] >> 0) << 4); + b[24] = (byte)((d[6 ] >> 24) + ((d[7 ] >> 0) << 4)); b[25] = (byte)(d[7 ] >> 4); b[26] = (byte)(d[7 ] >> 12); b[27] = (byte)(d[7 ] >> 20); b[28] = (byte)(d[8 ] >> 0); b[29] = (byte)(d[8 ] >> 8); b[30] = (byte)(d[8 ] >> 16); - b[31] = (byte)(d[8 ] >> 24) + ((d[9 ] >> 0) << 4); + b[31] = (byte)((d[8 ] >> 24) + ((d[9 ] >> 0) << 4)); b[32] = (byte)(d[9 ] >> 4); b[33] = (byte)(d[9 ] >> 12); b[34] = (byte)(d[9 ] >> 20); b[35] = (byte)(d[10] >> 0); b[36] = (byte)(d[10] >> 8); b[37] = (byte)(d[10] >> 16); - b[38] = (byte)(d[10] >> 24) + ((d[11] >> 0) << 4); + b[38] = (byte)((d[10] >> 24) + ((d[11] >> 0) << 4)); b[39] = (byte)(d[11] >> 4); b[40] = (byte)(d[11] >> 12); b[41] = (byte)(d[11] >> 20); b[42] = (byte)(d[12] >> 0); b[43] = (byte)(d[12] >> 8); b[44] = (byte)(d[12] >> 16); - b[45] = (byte)(d[12] >> 24) + ((d[13] >> 0) << 4); + b[45] = (byte)((d[12] >> 24) + ((d[13] >> 0) << 4)); b[46] = (byte)(d[13] >> 4); b[47] = (byte)(d[13] >> 12); b[48] = (byte)(d[13] >> 20); b[49] = (byte)(d[14] >> 0); b[50] = (byte)(d[14] >> 8); b[51] = (byte)(d[14] >> 16); - b[52] = (byte)(d[14] >> 24) + ((d[15] >> 0) << 4); + b[52] = (byte)((d[14] >> 24) + ((d[15] >> 0) << 4)); b[53] = (byte)(d[15] >> 4); b[54] = (byte)(d[15] >> 12); b[55] = (byte)(d[15] >> 20); @@ -6206,56 +6206,56 @@ void sc448_muladd(byte* r, const byte* a, const byte* b, const byte* d) r[ 0] = (byte)(rd[0 ] >> 0); r[ 1] = (byte)(rd[0 ] >> 8); r[ 2] = (byte)(rd[0 ] >> 16); - r[ 3] = (byte)(rd[0 ] >> 24) + ((rd[1 ] >> 0) << 4); + r[ 3] = (byte)((rd[0 ] >> 24) + ((rd[1 ] >> 0) << 4)); r[ 4] = (byte)(rd[1 ] >> 4); r[ 5] = (byte)(rd[1 ] >> 12); r[ 6] = (byte)(rd[1 ] >> 20); r[ 7] = (byte)(rd[2 ] >> 0); r[ 8] = (byte)(rd[2 ] >> 8); r[ 9] = (byte)(rd[2 ] >> 16); - r[10] = (byte)(rd[2 ] >> 24) + ((rd[3 ] >> 0) << 4); + r[10] = (byte)((rd[2 ] >> 24) + ((rd[3 ] >> 0) << 4)); r[11] = (byte)(rd[3 ] >> 4); r[12] = (byte)(rd[3 ] >> 12); r[13] = (byte)(rd[3 ] >> 20); r[14] = (byte)(rd[4 ] >> 0); r[15] = (byte)(rd[4 ] >> 8); r[16] = (byte)(rd[4 ] >> 16); - r[17] = (byte)(rd[4 ] >> 24) + ((rd[5 ] >> 0) << 4); + r[17] = (byte)((rd[4 ] >> 24) + ((rd[5 ] >> 0) << 4)); r[18] = (byte)(rd[5 ] >> 4); r[19] = (byte)(rd[5 ] >> 12); r[20] = (byte)(rd[5 ] >> 20); r[21] = (byte)(rd[6 ] >> 0); r[22] = (byte)(rd[6 ] >> 8); r[23] = (byte)(rd[6 ] >> 16); - r[24] = (byte)(rd[6 ] >> 24) + ((rd[7 ] >> 0) << 4); + r[24] = (byte)((rd[6 ] >> 24) + ((rd[7 ] >> 0) << 4)); r[25] = (byte)(rd[7 ] >> 4); r[26] = (byte)(rd[7 ] >> 12); r[27] = (byte)(rd[7 ] >> 20); r[28] = (byte)(rd[8 ] >> 0); r[29] = (byte)(rd[8 ] >> 8); r[30] = (byte)(rd[8 ] >> 16); - r[31] = (byte)(rd[8 ] >> 24) + ((rd[9 ] >> 0) << 4); + r[31] = (byte)((rd[8 ] >> 24) + ((rd[9 ] >> 0) << 4)); r[32] = (byte)(rd[9 ] >> 4); r[33] = (byte)(rd[9 ] >> 12); r[34] = (byte)(rd[9 ] >> 20); r[35] = (byte)(rd[10] >> 0); r[36] = (byte)(rd[10] >> 8); r[37] = (byte)(rd[10] >> 16); - r[38] = (byte)(rd[10] >> 24) + ((rd[11] >> 0) << 4); + r[38] = (byte)((rd[10] >> 24) + ((rd[11] >> 0) << 4)); r[39] = (byte)(rd[11] >> 4); r[40] = (byte)(rd[11] >> 12); r[41] = (byte)(rd[11] >> 20); r[42] = (byte)(rd[12] >> 0); r[43] = (byte)(rd[12] >> 8); r[44] = (byte)(rd[12] >> 16); - r[45] = (byte)(rd[12] >> 24) + ((rd[13] >> 0) << 4); + r[45] = (byte)((rd[12] >> 24) + ((rd[13] >> 0) << 4)); r[46] = (byte)(rd[13] >> 4); r[47] = (byte)(rd[13] >> 12); r[48] = (byte)(rd[13] >> 20); r[49] = (byte)(rd[14] >> 0); r[50] = (byte)(rd[14] >> 8); r[51] = (byte)(rd[14] >> 16); - r[52] = (byte)(rd[14] >> 24) + ((rd[15] >> 0) << 4); + r[52] = (byte)((rd[14] >> 24) + ((rd[15] >> 0) << 4)); r[53] = (byte)(rd[15] >> 4); r[54] = (byte)(rd[15] >> 12); r[55] = (byte)(rd[15] >> 20); diff --git a/src/wolfcrypt/src/hash.c b/src/wolfcrypt/src/hash.c index 9c7682f..bc69c3b 100644 --- a/src/wolfcrypt/src/hash.c +++ b/src/wolfcrypt/src/hash.c @@ -145,7 +145,7 @@ enum wc_HashType wc_HashTypeConvert(int hashType) int wc_HashGetOID(enum wc_HashType hash_type) { - int oid = HASH_TYPE_E; /* Default to hash type error */ + int oid = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ switch(hash_type) { case WC_HASH_TYPE_MD2: @@ -317,7 +317,7 @@ enum wc_HashType wc_OidGetHash(int oid) /* Get Hash digest size */ int wc_HashGetDigestSize(enum wc_HashType hash_type) { - int dig_size = HASH_TYPE_E; /* Default to hash type error */ + int dig_size = WC_NO_ERR_TRACE(HASH_TYPE_E); switch(hash_type) { case WC_HASH_TYPE_MD2: @@ -436,7 +436,7 @@ int wc_HashGetDigestSize(enum wc_HashType hash_type) /* Get Hash block size */ int wc_HashGetBlockSize(enum wc_HashType hash_type) { - int block_size = HASH_TYPE_E; /* Default to hash type error */ + int block_size = WC_NO_ERR_TRACE(HASH_TYPE_E); switch (hash_type) { case WC_HASH_TYPE_MD2: @@ -555,7 +555,7 @@ int wc_HashGetBlockSize(enum wc_HashType hash_type) int wc_Hash_ex(enum wc_HashType hash_type, const byte* data, word32 data_len, byte* hash, word32 hash_len, void* heap, int devId) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ int dig_size; /* Validate hash buffer size */ @@ -689,7 +689,7 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, int wc_HashInit_ex(wc_HashAlg* hash, enum wc_HashType type, void* heap, int devId) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ if (hash == NULL) return BAD_FUNC_ARG; @@ -801,7 +801,7 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, word32 dataSz) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ if (hash == NULL || (data == NULL && dataSz > 0)) return BAD_FUNC_ARG; @@ -904,7 +904,7 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ if (hash == NULL || out == NULL) return BAD_FUNC_ARG; @@ -1007,7 +1007,7 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ if (hash == NULL) return BAD_FUNC_ARG; @@ -1124,7 +1124,7 @@ int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) #ifdef WOLFSSL_HASH_FLAGS int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, word32 flags) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ if (hash == NULL) return BAD_FUNC_ARG; @@ -1203,7 +1203,7 @@ int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, word32 flags) } int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags) { - int ret = HASH_TYPE_E; /* Default to hash type error */ + int ret = WC_NO_ERR_TRACE(HASH_TYPE_E); /* Default to hash type error */ if (hash == NULL) return BAD_FUNC_ARG; diff --git a/src/wolfcrypt/src/hmac.c b/src/wolfcrypt/src/hmac.c index 9a80cb1..fb71bf3 100644 --- a/src/wolfcrypt/src/hmac.c +++ b/src/wolfcrypt/src/hmac.c @@ -30,15 +30,13 @@ #ifndef NO_HMAC -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) - +#if FIPS_VERSION3_GE(2,0,0) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$b") - #pragma const_seg(".fipsB$b") + #pragma code_seg(".fipsA$g") + #pragma const_seg(".fipsB$g") #endif #endif @@ -64,6 +62,14 @@ #define wc_HmacFinal wc_HmacFinal_Software #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_hmac_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000008 }; + int wolfCrypt_FIPS_HMAC_sanity(void) + { + return 0; + } +#endif int wc_HmacSizeByType(int type) { @@ -237,7 +243,8 @@ int _InitHmac(Hmac* hmac, int type, void* heap) } -int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) +int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length, + int allowFlag) { #ifndef WOLFSSL_MAXQ108X byte* ip; @@ -259,7 +266,7 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) return BAD_FUNC_ARG; } -#ifndef HAVE_FIPS +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0) /* if set key has already been run then make sure and free existing */ /* This is for async and PIC32MZ situations, and just normally OK, provided the user calls wc_HmacInit() first. That function is not @@ -277,12 +284,40 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) if (ret != 0) return ret; -#ifdef HAVE_FIPS - if (length < HMAC_FIPS_MIN_KEY) { - WOLFSSL_ERROR_VERBOSE(HMAC_MIN_KEYLEN_E); - return HMAC_MIN_KEYLEN_E; + /* Regarding the password length: + * SP800-107r1 ss 5.3.2 states: "An HMAC key shall have a security strength + * that meets or exceeds the security strength required to protect the data + * over which the HMAC is computed" then refers to SP800-133 for HMAC keys + * generation. + * + * SP800-133r2 ss 6.2.3 states: "When a key is generated from a password, + * the entropy provided (and thus, the maximum security strength that can be + * supported by the generated key) shall be considered to be zero unless the + * password is generated using an approved RBG" + * + * wolfSSL Notes: The statement from SP800-133r2 applies to + * all password lengths. Any human generated password is considered to have + * 0 security strength regardless of length, there is no minimum length that + * is OK or will provide any amount of security strength other than 0. If + * a security strength is required users shall generate random passwords + * using a FIPS approved RBG of sufficient length that any HMAC key + * generated from that password can claim to inherit the needed security + * strength from that input. + */ + + /* In light of the above, Loosen past restriction that limited passwords to + * no less than 14-bytes to allow for shorter Passwords. + * User needs to pass true (non-zero) to override historical behavior that + * prevented use of any password less than 14-bytes. ALL non-RBG generated + * passwords shall inherit a security strength of zero + * (no security strength) + */ + if (!allowFlag) { + if (length < HMAC_FIPS_MIN_KEY) { + WOLFSSL_ERROR_VERBOSE(HMAC_MIN_KEYLEN_E); + return HMAC_MIN_KEYLEN_E; + } } -#endif #ifdef WOLF_CRYPTO_CB hmac->keyRaw = key; /* use buffer directly */ @@ -564,6 +599,16 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) #endif /* WOLFSSL_MAXQ108X */ } +int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) +{ + int allowFlag; + #if defined(HAVE_FIPS) + allowFlag = 0; /* default false for FIPS cases */ + #else + allowFlag = 1; /* default true for all non-FIPS cases */ + #endif + return wc_HmacSetKey_ex(hmac, type, key, length, allowFlag); +} static int HmacKeyInnerHash(Hmac* hmac) { @@ -666,7 +711,7 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) #ifdef WOLF_CRYPTO_CB if (hmac->devId != INVALID_DEVID) { ret = wc_CryptoCb_Hmac(hmac, hmac->macType, msg, length, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; /* reset error code */ @@ -775,7 +820,7 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) #ifdef WOLF_CRYPTO_CB if (hmac->devId != INVALID_DEVID) { ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, hash); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1230,7 +1275,12 @@ int wolfSSL_GetHmacMaxSize(void) ret = wc_HmacInit(myHmac, heap, devId); if (ret == 0) { + #if FIPS_VERSION3_GE(6,0,0) + ret = wc_HmacSetKey_ex(myHmac, type, localSalt, saltSz, + FIPS_ALLOW_SHORT); + #else ret = wc_HmacSetKey(myHmac, type, localSalt, saltSz); + #endif if (ret == 0) ret = wc_HmacUpdate(myHmac, inKey, inKeySz); if (ret == 0) @@ -1311,7 +1361,12 @@ int wolfSSL_GetHmacMaxSize(void) word32 tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; + #if FIPS_VERSION3_GE(6,0,0) + ret = wc_HmacSetKey_ex(myHmac, type, inKey, inKeySz, + FIPS_ALLOW_SHORT); + #else ret = wc_HmacSetKey(myHmac, type, inKey, inKeySz); + #endif if (ret != 0) break; ret = wc_HmacUpdate(myHmac, tmp, tmpSz); diff --git a/src/wolfcrypt/src/kdf.c b/src/wolfcrypt/src/kdf.c index 55b7ab0..9edf3a5 100644 --- a/src/wolfcrypt/src/kdf.c +++ b/src/wolfcrypt/src/kdf.c @@ -30,15 +30,13 @@ #ifndef NO_KDF -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 5) - +#if FIPS_VERSION3_GE(5,0,0) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$m") - #pragma const_seg(".fipsB$m") + #pragma code_seg(".fipsA$h") + #pragma const_seg(".fipsB$h") #endif #endif @@ -56,6 +54,14 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_kdf_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000009 }; + int wolfCrypt_FIPS_KDF_sanity(void) + { + return 0; + } +#endif #if defined(WOLFSSL_HAVE_PRF) && !defined(NO_HMAC) @@ -300,6 +306,16 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, { int ret = 0; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" secret"); + WOLFSSL_BUFFER(secret, secLen); + WOLFSSL_MSG(" label"); + WOLFSSL_BUFFER(label, labLen); + WOLFSSL_MSG(" seed"); + WOLFSSL_BUFFER(seed, seedLen); +#endif + + if (useAtLeastSha256) { #ifdef WOLFSSL_SMALL_STACK byte* labelSeed; @@ -344,6 +360,12 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, #endif } +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" digest"); + WOLFSSL_BUFFER(digest, digLen); + WOLFSSL_MSG_EX("hash_type %d", hash_type); +#endif + return ret; } #endif /* WOLFSSL_HAVE_PRF && !NO_HMAC */ @@ -542,14 +564,14 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, const byte* info, word32 infoLen, int digest, void* heap) { int ret = 0; - int idx = 0; - int len; + word32 idx = 0; + size_t len; byte *data; (void)heap; /* okmLen (2) + protocol|label len (1) + info len(1) + protocollen + * labellen + infolen */ - len = 4 + protocolLen + labelLen + infoLen; + len = 4U + protocolLen + labelLen + infoLen; data = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER); if (data == NULL) @@ -637,7 +659,7 @@ typedef union { static int _HashInit(byte hashId, _hash* hash) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (hashId) { #ifndef NO_SHA @@ -662,6 +684,9 @@ int _HashInit(byte hashId, _hash* hash) ret = wc_InitSha512(&hash->sha512); break; #endif /* WOLFSSL_SHA512 */ + default: + ret = BAD_FUNC_ARG; + break; } return ret; @@ -671,7 +696,7 @@ static int _HashUpdate(byte hashId, _hash* hash, const byte* data, word32 dataSz) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (hashId) { #ifndef NO_SHA @@ -696,6 +721,9 @@ int _HashUpdate(byte hashId, _hash* hash, ret = wc_Sha512Update(&hash->sha512, data, dataSz); break; #endif /* WOLFSSL_SHA512 */ + default: + ret = BAD_FUNC_ARG; + break; } return ret; @@ -704,7 +732,7 @@ int _HashUpdate(byte hashId, _hash* hash, static int _HashFinal(byte hashId, _hash* hash, byte* digest) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); switch (hashId) { #ifndef NO_SHA @@ -729,6 +757,9 @@ int _HashFinal(byte hashId, _hash* hash, byte* digest) ret = wc_Sha512Final(&hash->sha512, digest); break; #endif /* WOLFSSL_SHA512 */ + default: + ret = BAD_FUNC_ARG; + break; } return ret; @@ -936,7 +967,7 @@ static void wc_srtp_kdf_first_block(const byte* salt, word32 saltSz, int kdrIdx, * @param [in] aes AES object to encrypt with. * @return 0 on success. */ -static int wc_srtp_kdf_derive_key(byte* block, byte indexSz, byte label, +static int wc_srtp_kdf_derive_key(byte* block, int indexSz, byte label, byte* key, word32 keySz, Aes* aes) { int i; @@ -1093,9 +1124,9 @@ int wc_SRTP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, * @return MEMORY_E on dynamic memory allocation failure. * @return 0 on success. */ -int wc_SRTCP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, +int wc_SRTCP_KDF_ex(const byte* key, word32 keySz, const byte* salt, word32 saltSz, int kdrIdx, const byte* index, byte* key1, word32 key1Sz, byte* key2, - word32 key2Sz, byte* key3, word32 key3Sz) + word32 key2Sz, byte* key3, word32 key3Sz, int idxLenIndicator) { int ret = 0; byte block[AES_BLOCK_SIZE]; @@ -1105,6 +1136,15 @@ int wc_SRTCP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, Aes aes[1]; #endif int aes_inited = 0; + int idxLen; + + if (idxLenIndicator == WC_SRTCP_32BIT_IDX) { + idxLen = WC_SRTCP_INDEX_LEN; + } else if (idxLenIndicator == WC_SRTCP_48BIT_IDX) { + idxLen = WC_SRTP_INDEX_LEN; + } else { + return BAD_FUNC_ARG; /* bad or invalid idxLenIndicator */ + } /* Validate parameters. */ if ((key == NULL) || (keySz > AES_256_KEY_SIZE) || (salt == NULL) || @@ -1136,23 +1176,22 @@ int wc_SRTCP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, /* Calculate first block that can be used in each derivation. */ if (ret == 0) { - wc_srtp_kdf_first_block(salt, saltSz, kdrIdx, index, WC_SRTCP_INDEX_LEN, - block); + wc_srtp_kdf_first_block(salt, saltSz, kdrIdx, index, idxLen, block); } /* Calculate first key if required. */ if ((ret == 0) && (key1 != NULL)) { - ret = wc_srtp_kdf_derive_key(block, WC_SRTCP_INDEX_LEN, + ret = wc_srtp_kdf_derive_key(block, idxLen, WC_SRTCP_LABEL_ENCRYPTION, key1, key1Sz, aes); } /* Calculate second key if required. */ if ((ret == 0) && (key2 != NULL)) { - ret = wc_srtp_kdf_derive_key(block, WC_SRTCP_INDEX_LEN, + ret = wc_srtp_kdf_derive_key(block, idxLen, WC_SRTCP_LABEL_MSG_AUTH, key2, key2Sz, aes); } /* Calculate third key if required. */ if ((ret == 0) && (key3 != NULL)) { - ret = wc_srtp_kdf_derive_key(block, WC_SRTCP_INDEX_LEN, + ret = wc_srtp_kdf_derive_key(block, idxLen, WC_SRTCP_LABEL_SALT, key3, key3Sz, aes); } @@ -1164,6 +1203,15 @@ int wc_SRTCP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, return ret; } +int wc_SRTCP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, + int kdrIdx, const byte* index, byte* key1, word32 key1Sz, byte* key2, + word32 key2Sz, byte* key3, word32 key3Sz) +{ + /* The default 32-bit IDX expected by many implementations */ + return wc_SRTCP_KDF_ex(key, keySz, salt, saltSz, kdrIdx, index, + key1, key1Sz, key2, key2Sz, key3, key3Sz, + WC_SRTCP_32BIT_IDX); +} /* Derive key with label using SRTP KDF algorithm. * * SP 800-135 (RFC 3711). @@ -1350,4 +1398,104 @@ int wc_SRTP_KDF_kdr_to_idx(word32 kdr) } #endif /* WC_SRTP_KDF */ +#ifdef WC_KDF_NIST_SP_800_56C +static int wc_KDA_KDF_iteration(const byte* z, word32 zSz, word32 counter, + const byte* fixedInfo, word32 fixedInfoSz, enum wc_HashType hashType, + byte* output) +{ + byte counterBuf[4]; + wc_HashAlg hash; + int ret; + + ret = wc_HashInit(&hash, hashType); + if (ret != 0) + return ret; + c32toa(counter, counterBuf); + ret = wc_HashUpdate(&hash, hashType, counterBuf, 4); + if (ret == 0) { + ret = wc_HashUpdate(&hash, hashType, z, zSz); + } + if (ret == 0 && fixedInfoSz > 0) { + ret = wc_HashUpdate(&hash, hashType, fixedInfo, fixedInfoSz); + } + if (ret == 0) { + ret = wc_HashFinal(&hash, hashType, output); + } + wc_HashFree(&hash, hashType); + return ret; +} + +/** + * \brief Performs the single-step key derivation function (KDF) as specified in + * SP800-56C option 1. + * + * \param [in] z The input keying material. + * \param [in] zSz The size of the input keying material. + * \param [in] fixedInfo The fixed information to be included in the KDF. + * \param [in] fixedInfoSz The size of the fixed information. + * \param [in] derivedSecretSz The desired size of the derived secret. + * \param [in] hashType The hash algorithm to be used in the KDF. + * \param [out] output The buffer to store the derived secret. + * \param [in] outputSz The size of the output buffer. + * + * \return 0 if the KDF operation is successful. + * \return BAD_FUNC_ARG if the input parameters are invalid. + * \return negative error code if the KDF operation fails. + */ +int wc_KDA_KDF_onestep(const byte* z, word32 zSz, const byte* fixedInfo, + word32 fixedInfoSz, word32 derivedSecretSz, enum wc_HashType hashType, + byte* output, word32 outputSz) +{ + byte hashTempBuf[WC_MAX_DIGEST_SIZE]; + word32 counter, outIdx; + int hashOutSz; + int ret; + + if (output == NULL || outputSz < derivedSecretSz) + return BAD_FUNC_ARG; + if (z == NULL || zSz == 0 || (fixedInfoSz > 0 && fixedInfo == NULL)) + return BAD_FUNC_ARG; + if (derivedSecretSz == 0) + return BAD_FUNC_ARG; + + hashOutSz = wc_HashGetDigestSize(hashType); + if (hashOutSz == WC_NO_ERR_TRACE(HASH_TYPE_E)) + return BAD_FUNC_ARG; + + /* According to SP800_56C, table 1, the max input size (max_H_inputBits) + * depends on the HASH algo. The smaller value in the table is (2**64-1)/8. + * This is larger than the possible length using word32 integers. */ + + counter = 1; + outIdx = 0; + ret = 0; + + /* According to SP800_56C the number of iterations shall not be greater than + * 2**32-1. This is not possible using word32 integers.*/ + while (outIdx + hashOutSz <= derivedSecretSz) { + ret = wc_KDA_KDF_iteration(z, zSz, counter, fixedInfo, fixedInfoSz, + hashType, output + outIdx); + if (ret != 0) + break; + counter++; + outIdx += hashOutSz; + } + + if (ret == 0 && outIdx < derivedSecretSz) { + ret = wc_KDA_KDF_iteration(z, zSz, counter, fixedInfo, fixedInfoSz, + hashType, hashTempBuf); + if (ret == 0) { + XMEMCPY(output + outIdx, hashTempBuf, derivedSecretSz - outIdx); + } + ForceZero(hashTempBuf, hashOutSz); + } + + if (ret != 0) { + ForceZero(output, derivedSecretSz); + } + + return ret; +} +#endif /* WC_KDF_NIST_SP_800_56C */ + #endif /* NO_KDF */ diff --git a/src/wolfcrypt/src/logging.c b/src/wolfcrypt/src/logging.c index 43c44a1..de87dbf 100644 --- a/src/wolfcrypt/src/logging.c +++ b/src/wolfcrypt/src/logging.c @@ -126,7 +126,10 @@ THREAD_LS_T void *StackSizeCheck_stackOffsetPointer = 0; /* Set these to default values initially. */ static wolfSSL_Logging_cb log_function = NULL; -static int loggingEnabled = 0; +#ifndef WOLFSSL_LOGGINGENABLED_DEFAULT +#define WOLFSSL_LOGGINGENABLED_DEFAULT 0 +#endif +static int loggingEnabled = WOLFSSL_LOGGINGENABLED_DEFAULT; THREAD_LS_T const char* log_prefix = NULL; #if defined(WOLFSSL_APACHE_MYNEWT) @@ -276,8 +279,11 @@ void WOLFSSL_TIME(int count) #include #endif -static void wolfssl_log(const int logLevel, const char *const logMessage) +static void wolfssl_log(const int logLevel, const char* const file_name, + int line_number, const char* const logMessage) { + (void)file_name; + (void)line_number; if (log_function) log_function(logLevel, logMessage); else { @@ -286,46 +292,103 @@ static void wolfssl_log(const int logLevel, const char *const logMessage) #elif defined(ARDUINO) wolfSSL_Arduino_Serial_Print(logMessage); #elif defined(WOLFSSL_LOG_PRINTF) - printf("%s\n", logMessage); + if (file_name != NULL) + printf("[%s L %d] %s\n", file_name, line_number, logMessage); + else + printf("%s\n", logMessage); #elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) - dc_log_printf("%s\n", logMessage); + if (file_name != NULL) + dc_log_printf("[%s L %d] %s\n", file_name, line_number, logMessage); + else + dc_log_printf("%s\n", logMessage); #elif defined(WOLFSSL_DEOS) - printf("%s\r\n", logMessage); + if (file_name != NULL) + printf("[%s L %d] %s\r\n", file_name, line_number, logMessage); + else + printf("%s\r\n", logMessage); #elif defined(MICRIUM) - BSP_Ser_Printf("%s\r\n", logMessage); + if (file_name != NULL) + BSP_Ser_Printf("[%s L %d] %s\r\n", + file_name, line_number, logMessage); + else + BSP_Ser_Printf("%s\r\n", logMessage); #elif defined(WOLFSSL_MDK_ARM) fflush(stdout) ; - printf("%s\n", logMessage); + if (file_name != NULL) + printf("[%s L %d] %s\n", file_name, line_number, logMessage); + else + printf("%s\n", logMessage); fflush(stdout) ; #elif defined(WOLFSSL_UTASKER) fnDebugMsg((char*)logMessage); fnDebugMsg("\r\n"); #elif defined(MQX_USE_IO_OLD) - fprintf(_mqxio_stderr, "%s\n", logMessage); + if (file_name != NULL) + fprintf(_mqxio_stderr, "[%s L %d] %s\n", + file_name, line_number, logMessage); + else + fprintf(_mqxio_stderr, "%s\n", logMessage); #elif defined(WOLFSSL_APACHE_MYNEWT) - LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "%s\n", logMessage); + if (file_name != NULL) + LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "[%s L %d] %s\n", + file_name, line_number, logMessage); + else + LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "%s\n", logMessage); #elif defined(WOLFSSL_ESPIDF) - ESP_LOGI("wolfssl", "%s", logMessage); + if (file_name != NULL) + ESP_LOGI("wolfssl", "[%s L %d] %s", + file_name, line_number, logMessage); + else + ESP_LOGI("wolfssl", "%s", logMessage); #elif defined(WOLFSSL_ZEPHYR) - printk("%s\n", logMessage); + if (file_name != NULL) + printk("[%s L %d] %s\n", file_name, line_number, logMessage); + else + printk("%s\n", logMessage); #elif defined(WOLFSSL_TELIT_M2MB) - M2M_LOG_INFO("%s\n", logMessage); + if (file_name != NULL) + M2M_LOG_INFO("[%s L %d] %s\n", file_name, line_number, logMessage); + else + M2M_LOG_INFO("%s\n", logMessage); #elif defined(WOLFSSL_ANDROID_DEBUG) - __android_log_print(ANDROID_LOG_VERBOSE, "[wolfSSL]", "%s", logMessage); + if (file_name != NULL) + __android_log_print(ANDROID_LOG_VERBOSE, "[wolfSSL]", "[%s L %d] %s", + file_name, line_number, logMessage); + else + __android_log_print(ANDROID_LOG_VERBOSE, "[wolfSSL]", "%s", + logMessage); #elif defined(WOLFSSL_XILINX) - xil_printf("%s\r\n", logMessage); + if (file_name != NULL) + xil_printf("[%s L %d] %s\r\n", file_name, line_number, logMessage); + else + xil_printf("%s\r\n", logMessage); #elif defined(WOLFSSL_LINUXKM) - printk("%s\n", logMessage); + if (file_name != NULL) + printk("[%s L %d] %s\n", file_name, line_number, logMessage); + else + printk("%s\n", logMessage); #elif defined(WOLFSSL_RENESAS_RA6M4) - myprintf("%s\n", logMessage); + if (file_name != NULL) + myprintf("[%s L %d] %s\n", file_name, line_number, logMessage); + else + myprintf("%s\n", logMessage); #elif defined(STACK_SIZE_CHECKPOINT_MSG) && \ defined(HAVE_STACK_SIZE_VERBOSE) && defined(HAVE_STACK_SIZE_VERBOSE_LOG) STACK_SIZE_CHECKPOINT_MSG(logMessage); #else - if (log_prefix != NULL) - fprintf(stderr, "[%s]: %s\n", log_prefix, logMessage); - else - fprintf(stderr, "%s\n", logMessage); + if (log_prefix != NULL) { + if (file_name != NULL) + fprintf(stderr, "[%s]: [%s L %d] %s\n", + log_prefix, file_name, line_number, logMessage); + else + fprintf(stderr, "[%s]: %s\n", log_prefix, logMessage); + } else { + if (file_name != NULL) + fprintf(stderr, "[%s L %d] %s\n", + file_name, line_number, logMessage); + else + fprintf(stderr, "%s\n", logMessage); + } #endif } } @@ -337,6 +400,7 @@ static void wolfssl_log(const int logLevel, const char *const logMessage) #ifndef WOLFSSL_MSG_EX_BUF_SZ #define WOLFSSL_MSG_EX_BUF_SZ 100 #endif +#undef WOLFSSL_MSG_EX /* undo WOLFSSL_DEBUG_CODEPOINTS wrapper */ #ifdef __clang__ /* tell clang argument 1 is format */ __attribute__((__format__ (__printf__, 1, 0))) @@ -351,16 +415,42 @@ void WOLFSSL_MSG_EX(const char* fmt, ...) written = XVSNPRINTF(msg, sizeof(msg), fmt, args); va_end(args); if (written > 0) - wolfssl_log(INFO_LOG , msg); + wolfssl_log(INFO_LOG, NULL, 0, msg); + } +} + +#ifdef WOLFSSL_DEBUG_CODEPOINTS +void WOLFSSL_MSG_EX2(const char *file, int line, const char* fmt, ...) +{ + if (loggingEnabled) { + char msg[WOLFSSL_MSG_EX_BUF_SZ]; + int written; + va_list args; + va_start(args, fmt); + written = XVSNPRINTF(msg, sizeof(msg), fmt, args); + va_end(args); + if (written > 0) + wolfssl_log(INFO_LOG, file, line, msg); } } #endif +#endif + +#undef WOLFSSL_MSG /* undo WOLFSSL_DEBUG_CODEPOINTS wrapper */ void WOLFSSL_MSG(const char* msg) { if (loggingEnabled) - wolfssl_log(INFO_LOG , msg); + wolfssl_log(INFO_LOG, NULL, 0, msg); +} + +#ifdef WOLFSSL_DEBUG_CODEPOINTS +void WOLFSSL_MSG2(const char *file, int line, const char* msg) +{ + if (loggingEnabled) + wolfssl_log(INFO_LOG, file, line, msg); } +#endif #ifndef LINE_LEN #define LINE_LEN 16 @@ -375,7 +465,7 @@ void WOLFSSL_BUFFER(const byte* buffer, word32 length) } if (!buffer) { - wolfssl_log(INFO_LOG, "\tNULL"); + wolfssl_log(INFO_LOG, NULL, 0, "\tNULL"); return; } @@ -405,32 +495,66 @@ void WOLFSSL_BUFFER(const byte* buffer, word32 length) } } - wolfssl_log(INFO_LOG, line); + wolfssl_log(INFO_LOG, NULL, 0, line); buffer += LINE_LEN; buflen -= LINE_LEN; } } - +#undef WOLFSSL_ENTER /* undo WOLFSSL_DEBUG_CODEPOINTS wrapper */ void WOLFSSL_ENTER(const char* msg) { if (loggingEnabled) { char buffer[WOLFSSL_MAX_ERROR_SZ]; XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg); - wolfssl_log(ENTER_LOG , buffer); + wolfssl_log(ENTER_LOG, NULL, 0, buffer); } } +#ifdef WOLFSSL_DEBUG_CODEPOINTS +void WOLFSSL_ENTER2(const char *file, int line, const char* msg) +{ + if (loggingEnabled) { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg); + wolfssl_log(ENTER_LOG, file, line, buffer); + } +} +#endif +#undef WOLFSSL_LEAVE /* undo WOLFSSL_DEBUG_CODEPOINTS wrapper */ void WOLFSSL_LEAVE(const char* msg, int ret) { if (loggingEnabled) { char buffer[WOLFSSL_MAX_ERROR_SZ]; XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", msg, ret); - wolfssl_log(LEAVE_LOG , buffer); + wolfssl_log(LEAVE_LOG, NULL, 0, buffer); + } +} + +#ifdef WOLFSSL_DEBUG_CODEPOINTS +void WOLFSSL_LEAVE2(const char *file, int line, const char* msg, int ret) +{ + if (loggingEnabled) { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", + msg, ret); + wolfssl_log(LEAVE_LOG, file, line, buffer); } } +#endif + +#ifdef WOLFSSL_DEBUG_CODEPOINTS + /* restore the wrappers */ + #define WOLFSSL_MSG(msg) WOLFSSL_MSG2(__FILE__, __LINE__, msg) + #define WOLFSSL_ENTER(msg) WOLFSSL_ENTER2(__FILE__, __LINE__, msg) + #define WOLFSSL_LEAVE(msg, ret) WOLFSSL_LEAVE2(__FILE__, __LINE__, msg, ret) + #ifdef XVSNPRINTF + #define WOLFSSL_MSG_EX(fmt, args...) \ + WOLFSSL_MSG_EX2(__FILE__, __LINE__, fmt, ## args) + #endif +#endif WOLFSSL_API int WOLFSSL_IS_DEBUG_ON(void) { @@ -714,7 +838,7 @@ unsigned long wc_PeekErrorNodeLineData(const char **file, int *line, while (1) { int ret = wc_PeekErrorNode(0, file, NULL, line); - if (ret == BAD_STATE_E) { + if (ret == WC_NO_ERR_TRACE(BAD_STATE_E)) { WOLFSSL_MSG("Issue peeking at error node in queue"); return 0; } @@ -744,7 +868,7 @@ unsigned long wc_GetErrorNodeErr(void) ret = wc_PullErrorNode(NULL, NULL, NULL); if (ret < 0) { - if (ret == BAD_STATE_E) { + if (ret == WC_NO_ERR_TRACE(BAD_STATE_E)) { ret = 0; /* no errors in queue */ } else { @@ -1230,7 +1354,9 @@ unsigned long wc_PeekErrorNodeLineData(const char **file, int *line, idx = getErrorNodeCurrentIdx(); while (1) { int ret = peekErrorNode(idx, file, NULL, line); - if (ret == BAD_MUTEX_E || ret == BAD_FUNC_ARG || ret == BAD_STATE_E) { + if (ret == WC_NO_ERR_TRACE(BAD_MUTEX_E) || + ret == WC_NO_ERR_TRACE(BAD_FUNC_ARG) || + ret == WC_NO_ERR_TRACE(BAD_STATE_E)) { ERRQ_UNLOCK(); WOLFSSL_MSG("Issue peeking at error node in queue"); return 0; @@ -1263,7 +1389,7 @@ unsigned long wc_GetErrorNodeErr(void) ret = pullErrorNode(NULL, NULL, NULL); if (ret < 0) { - if (ret == BAD_STATE_E) { + if (ret == WC_NO_ERR_TRACE(BAD_STATE_E)) { ret = 0; /* no errors in queue */ } else { @@ -1483,7 +1609,7 @@ void WOLFSSL_ERROR(int error) #endif { #ifdef WOLFSSL_ASYNC_CRYPT - if (error != WC_PENDING_E) + if (error != WC_NO_ERR_TRACE(WC_PENDING_E)) #endif { char buffer[WOLFSSL_MAX_ERROR_SZ]; @@ -1501,7 +1627,8 @@ void WOLFSSL_ERROR(int error) #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) /* If running in compatibility mode do not add want read and want right to error queue */ - if (error != WANT_READ && error != WANT_WRITE) { + if (error != WC_NO_ERR_TRACE(WANT_READ) && + error != WC_NO_ERR_TRACE(WANT_WRITE)) { #endif if (error < 0) error = error - (2 * error); /* get absolute value */ @@ -1531,7 +1658,7 @@ void WOLFSSL_ERROR(int error) #ifdef DEBUG_WOLFSSL if (loggingEnabled) - wolfssl_log(ERROR_LOG , buffer); + wolfssl_log(ERROR_LOG, NULL, 0, buffer); #endif } } @@ -1540,7 +1667,7 @@ void WOLFSSL_ERROR_MSG(const char* msg) { #ifdef DEBUG_WOLFSSL if (loggingEnabled) - wolfssl_log(ERROR_LOG , msg); + wolfssl_log(ERROR_LOG, NULL, 0, msg); #else (void)msg; #endif diff --git a/src/wolfcrypt/src/memory.c b/src/wolfcrypt/src/memory.c index 4b068ce..d9958a9 100644 --- a/src/wolfcrypt/src/memory.c +++ b/src/wolfcrypt/src/memory.c @@ -38,6 +38,16 @@ Possible memory options: * NO_WOLFSSL_MEMORY: Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY. * WOLFSSL_STATIC_MEMORY: Turns on the use of static memory buffers and functions. This allows for using static memory instead of dynamic. + * WOLFSSL_STATIC_MEMORY_LEAN: Requires WOLFSSL_STATIC_MEMORY be defined. + * Uses smaller type sizes for structs + * requiring that memory pool sizes be less + * then 65k and limits features available like + * IO buffers to reduce footprint size. + * WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK: + * Enables option to register a debugging + * callback function, useful for + * WOLFSSL_STATIC_MEMORY builds where XMALLOC + * and XFREE are not user defined. * WOLFSSL_STATIC_ALIGN: Define defaults to 16 to indicate static memory alignment. * HAVE_IO_POOL: Enables use of static thread safe memory pool for input/output buffers. * XMALLOC_OVERRIDE: Allows override of the XMALLOC, XFREE and XREALLOC macros. @@ -514,20 +524,39 @@ void* wolfSSL_Realloc(void *ptr, size_t size) struct wc_Memory { byte* buffer; struct wc_Memory* next; +#ifdef WOLFSSL_STATIC_MEMORY_LEAN + /* lean static memory is assumed to be under 65k */ + word16 sz; +#else word32 sz; +#endif +#ifdef WOLFSSL_DEBUG_MEMORY + word16 szUsed; +#endif }; +#ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK +static DebugMemoryCb DebugCb = NULL; + +/* Used to set a debug memory callback. Helpful in cases where + * printf is not available. */ +void wolfSSL_SetDebugMemoryCb(DebugMemoryCb cb) +{ + DebugCb = cb; +} +#endif + /* returns amount of memory used on success. On error returns negative value wc_Memory** list is the list that new buckets are prepended to */ -static int create_memory_buckets(byte* buffer, word32 bufSz, - word32 buckSz, word32 buckNum, wc_Memory** list) { - word32 i; +static int wc_create_memory_buckets(byte* buffer, word32 bufSz, + word32 buckSz, byte buckNum, wc_Memory** list) { byte* pt = buffer; int ret = 0; - word32 memSz = (word32)sizeof(wc_Memory); - word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + byte memSz = (byte)sizeof(wc_Memory); + word16 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + word16 i; /* if not enough space available for bucket size then do not try */ if (buckSz + memSz + padSz > bufSz) { @@ -542,6 +571,12 @@ static int create_memory_buckets(byte* buffer, word32 bufSz, mem->buffer = (byte*)pt + padSz + memSz; mem->next = NULL; + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + DebugCb(buckSz, buckSz, WOLFSSL_DEBUG_MEMORY_INIT, 0); + } + #endif + /* add the newly created struct to front of list */ if (*list == NULL) { *list = mem; @@ -562,41 +597,126 @@ static int create_memory_buckets(byte* buffer, word32 bufSz, return ret; } -int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) +static int wc_partition_static_memory(byte* buffer, word32 sz, int flag, + WOLFSSL_HEAP* heap) { - word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; - word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + word32 ava = sz; + byte* pt = buffer; + int ret = 0; + byte memSz = (word32)sizeof(wc_Memory); + byte padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); - if (heap == NULL) { - return BAD_FUNC_ARG; + WOLFSSL_ENTER("wc_partition_static_memory"); + + /* align pt */ + while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + *pt = 0x00; + pt++; + ava--; } +#ifdef WOLFSSL_DEBUG_MEMORY + fprintf(stderr, "Allocated %d bytes for static memory @ %p\n", ava, pt); +#endif + + /* divide into chunks of memory and add them to available list */ + while (ava >= (word32)(heap->sizeList[0] + padSz + memSz)) { + #ifndef WOLFSSL_STATIC_MEMORY_LEAN + /* creating only IO buffers from memory passed in, max TLS is 16k */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + if ((ret = wc_create_memory_buckets(pt, ava, + WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { + WOLFSSL_LEAVE("wc_partition_static_memory", ret); + return ret; + } + + /* check if no more room left for creating IO buffers */ + if (ret == 0) { + break; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + else + #endif + { + int i; + /* start at largest and move to smaller buckets */ + for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + if ((word32)(heap->sizeList[i] + padSz + memSz) <= ava) { + if ((ret = wc_create_memory_buckets(pt, ava, + heap->sizeList[i], heap->distList[i], + &(heap->ava[i]))) < 0) { + WOLFSSL_LEAVE("wc_partition_static_memory", ret); + return ret; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + } + } + } + + (void)flag; + return 1; +} + +static int wc_init_memory_heap(WOLFSSL_HEAP* heap, unsigned int listSz, + const unsigned int* sizeList, const unsigned int* distList) +{ + unsigned int i; + XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); - XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); - XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); + /* avoid XMEMCPY for LEAN static memory build */ + for (i = 0; i < listSz; i++) { + heap->sizeList[i] = sizeList[i]; + } + + for (i = 0; i < listSz; i++) { + heap->distList[i] = distList[i]; + } +#ifndef SINGLE_THREADED if (wc_InitMutex(&(heap->memory_mutex)) != 0) { WOLFSSL_MSG("Error creating heap memory mutex"); return BAD_MUTEX_E; } +#endif return 0; } -int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, - unsigned char* buf, unsigned int sz, int flag, int maxSz) +int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, + unsigned int listSz, const unsigned int* sizeList, + const unsigned int* distList, unsigned char* buf, + unsigned int sz, int flag, int maxSz) { + WOLFSSL_HEAP* heap = NULL; + WOLFSSL_HEAP_HINT* hint = NULL; + word16 idx = 0; int ret; - WOLFSSL_HEAP* heap; - WOLFSSL_HEAP_HINT* hint; - word32 idx = 0; - if (pHint == NULL || buf == NULL) { + WOLFSSL_ENTER("wc_LoadStaticMemory_ex"); + + if (pHint == NULL || buf == NULL || sizeList == NULL || distList == NULL) { return BAD_FUNC_ARG; } + /* Cap the listSz to the actual number of items allocated in the list. */ + if (listSz > WOLFMEM_MAX_BUCKETS) { + WOLFSSL_MSG("Truncating the list of memory buckets"); + listSz = WOLFMEM_MAX_BUCKETS; + } + if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) { + WOLFSSL_MSG("Not enough memory for partition tracking"); return BUFFER_E; /* not enough memory for structures */ } @@ -607,7 +727,7 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, hint = (WOLFSSL_HEAP_HINT*)(buf + idx); idx += sizeof(WOLFSSL_HEAP_HINT); - ret = wolfSSL_init_memory_heap(heap); + ret = wc_init_memory_heap(heap, listSz, sizeList, distList); if (ret != 0) { return ret; } @@ -627,12 +747,13 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, heap = hint->memory; } - ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap); + ret = wc_partition_static_memory(buf + idx, sz - idx, flag, heap); if (ret != 1) { WOLFSSL_MSG("Error partitioning memory"); - return -1; + return MEMORY_E; } +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* determine what max applies too */ if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) { heap->maxIO = maxSz; @@ -640,85 +761,44 @@ int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, else { /* general memory used in handshakes */ heap->maxHa = maxSz; } - heap->flag |= flag; +#endif *pHint = hint; (void)maxSz; - return 0; } -int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag, - WOLFSSL_HEAP* heap) +int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, + unsigned char* buf, unsigned int sz, int flag, int maxSz) { - word32 ava = sz; - byte* pt = buffer; - int ret = 0; - word32 memSz = (word32)sizeof(wc_Memory); - word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); - - WOLFSSL_ENTER("wolfSSL_load_static_memory"); - - if (buffer == NULL) { - return BAD_FUNC_ARG; - } - - /* align pt */ - while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { - *pt = 0x00; - pt++; - ava--; - } - -#ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Allocated %d bytes for static memory @ %p\n", ava, pt); +#ifdef WOLFSSL_LEAN_STATIC_PSK + word16 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + byte distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; +#else + word32 sizeList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 distList[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; #endif + int ret = 0; - /* divide into chunks of memory and add them to available list */ - while (ava >= (heap->sizeList[0] + padSz + memSz)) { - /* creating only IO buffers from memory passed in, max TLS is 16k */ - if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { - if ((ret = create_memory_buckets(pt, ava, - WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { - WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); - return ret; - } + WOLFSSL_ENTER("wc_LoadStaticMemory"); + ret = wc_LoadStaticMemory_ex(pHint, + WOLFMEM_DEF_BUCKETS, sizeList, distList, + buf, sz, flag, maxSz); + WOLFSSL_LEAVE("wc_LoadStaticMemory", ret); + return ret; +} - /* check if no more room left for creating IO buffers */ - if (ret == 0) { - break; - } - /* advance pointer in buffer for next buckets and keep track - of how much memory is left available */ - pt += ret; - ava -= ret; - } - else { - int i; - /* start at largest and move to smaller buckets */ - for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { - if ((heap->sizeList[i] + padSz + memSz) <= ava) { - if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i], - heap->distList[i], &(heap->ava[i]))) < 0) { - WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); - return ret; - } - - /* advance pointer in buffer for next buckets and keep track - of how much memory is left available */ - pt += ret; - ava -= ret; - } - } - } +void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap) +{ + WOLFSSL_ENTER("wc_UnloadStaticMemory"); + if (heap != NULL && heap->memory != NULL) { + wc_FreeMutex(&heap->memory->memory_mutex); } - - return 1; } - +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* returns the size of management memory needed for each bucket. * This is memory that is used to keep track of and align memory buckets. */ int wolfSSL_MemoryPaddingSz(void) @@ -731,28 +811,34 @@ int wolfSSL_MemoryPaddingSz(void) /* Used to calculate memory size for optimum use with buckets. returns the suggested size rounded down to the nearest bucket. */ -int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) +int wolfSSL_StaticBufferSz_ex(unsigned int listSz, + const unsigned int *sizeList, const unsigned int *distList, + byte* buffer, word32 sz, int flag) { - word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS}; - word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST}; - word32 ava = sz; byte* pt = buffer; word32 memSz = (word32)sizeof(wc_Memory); word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); - WOLFSSL_ENTER("wolfSSL_static_size"); + WOLFSSL_ENTER("wolfSSL_StaticBufferSz_ex"); - if (buffer == NULL) { + if (buffer == NULL || sizeList == NULL || distList == NULL) { return BAD_FUNC_ARG; } + /* Cap the listSz to the actual number of items allocated in the list. */ + if (listSz > WOLFMEM_MAX_BUCKETS) { + WOLFSSL_MSG("Truncating the list of memory buckets"); + listSz = WOLFMEM_MAX_BUCKETS; + } + /* align pt */ while ((wc_ptr_t)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { pt++; ava--; } +#ifndef WOLFSSL_STATIC_MEMORY_LEAN /* creating only IO buffers from memory passed in, max TLS is 16k */ if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { @@ -761,29 +847,44 @@ int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); } - else { + else +#endif + { int i, k; - if (ava < (bucketSz[0] + padSz + memSz)) { + if (ava < (sizeList[0] + padSz + memSz)) { return 0; /* not enough room for even one bucket */ } - while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { + while ((ava >= (sizeList[0] + padSz + memSz)) && (ava > 0)) { /* start at largest and move to smaller buckets */ - for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + for (i = (listSz - 1); i >= 0; i--) { for (k = distList[i]; k > 0; k--) { - if ((bucketSz[i] + padSz + memSz) <= ava) { - ava -= bucketSz[i] + padSz + memSz; + if ((sizeList[i] + padSz + memSz) <= ava) { + ava -= sizeList[i] + padSz + memSz; } } } } } + WOLFSSL_LEAVE("wolfSSL_StaticBufferSz_ex", sz - ava); return sz - ava; /* round down */ } +/* Calls wolfSSL_StaticBufferSz_ex with the static memory pool config + * used by wolfSSL by default. */ +int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) +{ + word32 bucketSz[WOLFMEM_DEF_BUCKETS] = {WOLFMEM_BUCKETS}; + word32 distList[WOLFMEM_DEF_BUCKETS] = {WOLFMEM_DIST}; + + return wolfSSL_StaticBufferSz_ex(WOLFMEM_DEF_BUCKETS, bucketSz, distList, + buffer, sz, flag); +} + + int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) { WOLFSSL_MSG("Freeing fixed IO buffer"); @@ -855,6 +956,32 @@ int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats) return 1; } +#endif /* !WOLFSSL_STATIC_MEMORY_LEAN */ + + +/* global heap hint to fall back on when no heap hint is passed to + * XMALLOC/XFREE + * NOT thread safe, should be set once before any expected XMALLOC XFREE calls + */ +static void* globalHeapHint = NULL; + + +/* Used to set a new global heap hint. Returns a pointer to the current global + * heap hint before being set. */ +void* wolfSSL_SetGlobalHeapHint(void* heap) +{ + void *oldHint = globalHeapHint; + + globalHeapHint = heap; + return oldHint; +} + + +/* returns a pointer to the current global heap hint */ +void* wolfSSL_GetGlobalHeapHint(void) +{ + return globalHeapHint; +} #ifdef WOLFSSL_DEBUG_MEMORY @@ -875,7 +1002,7 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) #endif /* if no heap hint then use dynamic memory*/ - if (heap == NULL) { + if (heap == NULL && globalHeapHint == NULL) { #ifdef WOLFSSL_HEAP_TEST /* allow using malloc for creating ctx and method */ if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || @@ -910,13 +1037,24 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } else { WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; - WOLFSSL_HEAP* mem = hint->memory; + WOLFSSL_HEAP* mem; + + if (hint == NULL) { + hint = (WOLFSSL_HEAP_HINT*)globalHeapHint; + #ifdef WOLFSSL_DEBUG_MEMORY + fprintf(stderr, "(Using global heap hint %p) ", hint); + #endif + } + mem = hint->memory; + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return NULL; } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* case of using fixed IO buffers */ if (mem->flag & WOLFMEM_IO_POOL_FIXED && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -928,7 +1066,10 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) pt = hint->inBuf; } } - else { + else + #endif + { + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* check if using IO pool flag */ if (mem->flag & WOLFMEM_IO_POOL && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -938,6 +1079,7 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) mem->io = pt->next; } } + #endif /* general static memory */ if (pt == NULL) { @@ -950,7 +1092,7 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } #ifdef WOLFSSL_DEBUG_STATIC_MEMORY else { - fprintf(stderr, "Size: %ld, Empty: %d\n", size, + fprintf(stderr, "Size: %lu, Empty: %d\n", (unsigned long) size, mem->sizeList[i]); } #endif @@ -960,14 +1102,21 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } if (pt != NULL) { - mem->inUse += pt->sz; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN mem->alloc += 1; + #endif res = pt->buffer; #ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + pt->szUsed = size; + fprintf(stderr, "Alloc: %p -> %lu at %s:%d\n", pt->buffer, size, func, line); #endif - + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + DebugCb(size, pt->sz, WOLFSSL_DEBUG_MEMORY_ALLOC, type); + } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* keep track of connection statistics if flag is set */ if (mem->flag & WOLFMEM_TRACK_STATS) { WOLFSSL_MEM_CONN_STATS* stats = hint->stats; @@ -983,15 +1132,24 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) stats->totalAlloc++; } } + #endif } else { WOLFSSL_MSG("ERROR ran out of static memory"); + res = NULL; #ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Looking for %lu bytes at %s:%d\n", size, func, line); + fprintf(stderr, "Looking for %lu bytes at %s:%d\n", (unsigned long) size, func, + line); + #endif + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + DebugCb(size, 0, WOLFSSL_DEBUG_MEMORY_FAIL, type); + } #endif } - + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } #ifdef WOLFSSL_MALLOC_CHECK @@ -1030,7 +1188,7 @@ void wolfSSL_Free(void *ptr, void* heap, int type) } #endif - if (heap == NULL) { + if (heap == NULL && globalHeapHint == NULL) { #ifdef WOLFSSL_HEAP_TEST /* allow using malloc for creating ctx and method */ if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || @@ -1055,16 +1213,31 @@ void wolfSSL_Free(void *ptr, void* heap, int type) } else { WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; - WOLFSSL_HEAP* mem = hint->memory; + WOLFSSL_HEAP* mem; word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); + if (hint == NULL) { + hint = (WOLFSSL_HEAP_HINT*)globalHeapHint; + #ifdef WOLFSSL_DEBUG_MEMORY + fprintf(stderr, "(Using global heap hint %p) ", hint); + #endif + } + mem = hint->memory; + if (mem == NULL) { + WOLFSSL_MSG("Bad hint pointer to memory"); + return; + } + /* get memory struct and add it to available list */ pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz); + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return; } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* case of using fixed IO buffers */ if (mem->flag & WOLFMEM_IO_POOL_FIXED && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1078,22 +1251,38 @@ void wolfSSL_Free(void *ptr, void* heap, int type) pt->next = mem->io; mem->io = pt; } - else { /* general memory free */ + else + #endif + { /* general memory free */ for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { if (pt->sz == mem->sizeList[i]) { pt->next = mem->ava[i]; mem->ava[i] = pt; + + #ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + if (DebugCb) { + #ifdef WOLFSSL_DEBUG_MEMORY + DebugCb(pt->szUsed, pt->sz, WOLFSSL_DEBUG_MEMORY_FREE, type); + #else + DebugCb(pt->sz, pt->sz, WOLFSSL_DEBUG_MEMORY_FREE, type); + #endif + } + #endif break; } } } + #ifndef WOLFSSL_STATIC_MEMORY_LEAN mem->inUse -= pt->sz; mem->frAlc += 1; + #endif #ifdef WOLFSSL_DEBUG_MEMORY - fprintf(stderr, "Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + fprintf (stderr, "Free: %p -> %u at %s:%d\n", pt->buffer, + pt->szUsed, func, line); #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* keep track of connection statistics if flag is set */ if (mem->flag & WOLFMEM_TRACK_STATS) { WOLFSSL_MEM_CONN_STATS* stats = hint->stats; @@ -1112,7 +1301,10 @@ void wolfSSL_Free(void *ptr, void* heap, int type) stats->totalFr++; } } + #endif + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } } @@ -1121,6 +1313,7 @@ void wolfSSL_Free(void *ptr, void* heap, int type) (void)type; } +#ifndef WOLFSSL_NO_REALLOC #ifdef WOLFSSL_DEBUG_MEMORY void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line) #else @@ -1138,7 +1331,7 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) } #endif - if (heap == NULL) { + if (heap == NULL && globalHeapHint == NULL) { #ifdef WOLFSSL_HEAP_TEST WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC"); #endif @@ -1150,9 +1343,17 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) } else { WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; - WOLFSSL_HEAP* mem = hint->memory; + WOLFSSL_HEAP* mem; word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); + if (hint == NULL) { + hint = (WOLFSSL_HEAP_HINT*)globalHeapHint; + #ifdef WOLFSSL_DEBUG_MEMORY + fprintf(stderr, "(Using global heap hint %p) ", hint); + #endif + } + mem = hint->memory; + if (ptr == NULL) { #ifdef WOLFSSL_DEBUG_MEMORY return wolfSSL_Malloc(size, heap, type, func, line); @@ -1160,12 +1361,14 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) return wolfSSL_Malloc(size, heap, type); #endif } - + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return NULL; } + #endif + #ifndef WOLFSSL_STATIC_MEMORY_LEAN /* case of using fixed IO buffers or IO pool */ if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED)) && (type == DYNAMIC_TYPE_OUT_BUFFER || @@ -1178,7 +1381,9 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) } res = pt->buffer; } - else { + else + #endif + { /* general memory */ for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { if ((word32)size <= mem->sizeList[i]) { @@ -1191,30 +1396,40 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) } if (pt != NULL && res == NULL) { + word32 prvSz; + res = pt->buffer; /* copy over original information and free ptr */ - word32 prvSz = ((wc_Memory*)((byte*)ptr - padSz - + prvSz = ((wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory)))->sz; prvSz = (prvSz > pt->sz)? pt->sz: prvSz; XMEMCPY(pt->buffer, ptr, prvSz); + #ifndef WOLFSSL_STATIC_MEMORY_LEAN mem->inUse += pt->sz; mem->alloc += 1; + #endif /* free memory that was previously being used */ + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif wolfSSL_Free(ptr, heap, type #ifdef WOLFSSL_DEBUG_MEMORY , func, line #endif ); + #ifndef SINGLE_THREADED if (wc_LockMutex(&(mem->memory_mutex)) != 0) { WOLFSSL_MSG("Bad memory_mutex lock"); return NULL; } + #endif } } + #ifndef SINGLE_THREADED wc_UnLockMutex(&(mem->memory_mutex)); + #endif } #ifdef WOLFSSL_MALLOC_CHECK @@ -1231,7 +1446,7 @@ void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) return res; } #endif /* WOLFSSL_STATIC_MEMORY */ - +#endif /* WOLFSSL_NO_REALLOC */ #endif /* USE_WOLFSSL_MEMORY */ diff --git a/src/wolfcrypt/src/misc.c b/src/wolfcrypt/src/misc.c index af5f09a..10f733b 100644 --- a/src/wolfcrypt/src/misc.c +++ b/src/wolfcrypt/src/misc.c @@ -1001,6 +1001,25 @@ WC_MISC_STATIC WC_INLINE word32 HashObject(const byte* o, word32 len, #endif /* WOLFCRYPT_ONLY && !NO_HASH_WRAPPER && * (!NO_SESSION_CACHE || HAVE_SESSION_TICKET) */ +WC_MISC_STATIC WC_INLINE char* CopyString(const char* src, int srcLen, + void* heap, int type) { + char* dst = NULL; + + if (src == NULL) + return NULL; + + if (srcLen <= 0) + srcLen = (int)XSTRLEN(src); + + dst = (char*)XMALLOC((size_t)srcLen + 1, heap, type); + if (dst != NULL) { + XMEMCPY(dst, src, (size_t)srcLen); + dst[srcLen] = '\0'; + } + + return dst; +} + #endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */ #endif /* WOLF_CRYPT_MISC_C */ diff --git a/src/wolfcrypt/src/pkcs12.c b/src/wolfcrypt/src/pkcs12.c index 123b2e9..ef111a6 100644 --- a/src/wolfcrypt/src/pkcs12.c +++ b/src/wolfcrypt/src/pkcs12.c @@ -130,15 +130,22 @@ typedef struct WC_PKCS12_ATTRIBUTE { WC_PKCS12* wc_PKCS12_new(void) +{ + return wc_PKCS12_new_ex(NULL); +} + + +WC_PKCS12* wc_PKCS12_new_ex(void* heap) { WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12), - NULL, DYNAMIC_TYPE_PKCS); + heap, DYNAMIC_TYPE_PKCS); if (pkcs12 == NULL) { WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct"); return NULL; } XMEMSET(pkcs12, 0, sizeof(WC_PKCS12)); + pkcs12->heap = heap; return pkcs12; } @@ -202,7 +209,7 @@ void wc_PKCS12_free(WC_PKCS12* pkcs12) } #endif - XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS); + XFREE(pkcs12, heap, DYNAMIC_TYPE_PKCS); } @@ -290,7 +297,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, #ifdef ASN_BER_TO_DER if (pkcs12->indefinite) { if (wc_BerToDer(input, safe->dataSz, NULL, - &pkcs12->safeDersz) != LENGTH_ONLY_E) { + &pkcs12->safeDersz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Not BER sequence"); return ASN_PARSE_E; } @@ -704,7 +711,7 @@ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) #ifdef ASN_BER_TO_DER if (size == 0) { if (wc_BerToDer(der, totalSz, NULL, - (word32*)&size) != LENGTH_ONLY_E) { + (word32*)&size) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Not BER sequence"); return ASN_PARSE_E; } @@ -1119,8 +1126,8 @@ static WARN_UNUSED_RESULT int freeDecCertList(WC_DerCertList** list, while (current != NULL) { InitDecodedCert(DeCert, current->buffer, current->bufferSz, heap); - if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { - if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert) == 1) { + if (ParseCertRelative(DeCert, CERT_TYPE, NO_VERIFY, NULL, NULL) == 0) { + if (wc_CheckPrivateKeyCert(*pkey, *pkeySz, DeCert, 0) == 1) { WOLFSSL_MSG("Key Pair found"); *cert = current->buffer; *certSz = current->bufferSz; @@ -1819,7 +1826,7 @@ static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, ret = UnTraditionalEnc(key, keySz, pkcs8Key, &sz, pass, passSz, vPKCS, vAlgo, NULL, 0, itt, rng, heap); } - if (ret == LENGTH_ONLY_E) { + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { *outSz = sz + MAX_LENGTH_SZ + 1; return LENGTH_ONLY_E; } @@ -1876,7 +1883,7 @@ static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng, /* get max size for shrouded key */ ret = wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz, algo, pass, passSz, iter); - if (ret != LENGTH_ONLY_E && ret < 0) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E) && ret < 0) { return ret; } @@ -2085,7 +2092,7 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, encSz = contentSz; if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz, pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return ret; } } @@ -2275,7 +2282,7 @@ static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey, /* get max size for key bag */ ret = wc_PKCS12_create_key_bag(pkcs12, rng, NULL, &keyBufSz, key, keySz, algo, iter, pass, (int)passSz); - if (ret != LENGTH_ONLY_E && ret < 0) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E) && ret < 0) { WOLFSSL_MSG("Error getting key bag size"); return NULL; } @@ -2312,7 +2319,7 @@ static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey, #endif ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, keyCiSz, NULL, keyBufSz, algo, pass, (int)passSz, iter, WC_PKCS12_DATA); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); WOLFSSL_MSG("Error getting key encrypt content size"); return NULL; @@ -2397,7 +2404,7 @@ static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert, /* get max size of buffer needed */ ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return NULL; } @@ -2409,7 +2416,7 @@ static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert, while (current != NULL) { ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, current->buffer, current->bufferSz); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return NULL; } certBufSz += curBufSz; @@ -2461,7 +2468,7 @@ static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert, /* get buffer size needed for content info */ ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, certCiSz, NULL, certBufSz, algo, pass, (int)passSz, iter, type); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); WOLFSSL_LEAVE("wc_PKCS12_create()", ret); return NULL; @@ -2517,7 +2524,7 @@ static int PKCS12_create_safe(WC_PKCS12* pkcs12, byte* certCi, word32 certCiSz, /* add Content Info structs to safe, key first then cert */ ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, &safeDataSz, NULL, innerDataSz, 0, NULL, 0, 0, WC_PKCS12_DATA); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return ret; } @@ -2604,20 +2611,12 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, return NULL; } - if ((pkcs12 = wc_PKCS12_new()) == NULL) { + if ((pkcs12 = wc_PKCS12_new_ex(heap)) == NULL) { wc_FreeRng(&rng); WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); return NULL; } - if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - WOLFSSL_LEAVE("wc_PKCS12_create", ret); - (void)ret; - return NULL; - } - if (iter <= 0) { iter = WC_PKCS12_ITT_DEFAULT; } diff --git a/src/wolfcrypt/src/pkcs7.c b/src/wolfcrypt/src/pkcs7.c index 997fd4f..acf7ef8 100644 --- a/src/wolfcrypt/src/pkcs7.c +++ b/src/wolfcrypt/src/pkcs7.c @@ -284,12 +284,12 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, if (rdSz >= inSz) { /* no more input to read, reset input index and request more data */ pkcs7->stream->idx = 0; - return WC_PKCS7_WANT_READ_E; + return WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E); } /* try to store input data into stream buffer */ if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { - int len = min(inSz - rdSz, expected - pkcs7->stream->length); + int len = (int)min(inSz - rdSz, expected - pkcs7->stream->length); /* sanity check that the input buffer is not internal buffer */ if (in == pkcs7->stream->buffer) { @@ -324,7 +324,7 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, /* if not enough data was read in then request more */ if (pkcs7->stream->length < expected) { pkcs7->stream->idx = 0; - return WC_PKCS7_WANT_READ_E; + return WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E); } /* adjust pointer to read from stored buffer */ @@ -357,11 +357,11 @@ static int wc_PKCS7_SetMaxStream(PKCS7* pkcs7, byte* in, word32 defSz) byte* pt; if (pkcs7->stream->length > 0) { - length = pkcs7->stream->length; + length = (int)pkcs7->stream->length; pt = pkcs7->stream->buffer; } else { - length = defSz; + length = (int)defSz; pt = in; } maxIdx = (word32)length; @@ -379,8 +379,8 @@ static int wc_PKCS7_SetMaxStream(PKCS7* pkcs7, byte* in, word32 defSz) #ifdef ASN_BER_TO_DER if (length == 0 && ret == 0) { idx = 0; - if ((ret = wc_BerToDer(pt, maxIdx, NULL, - (word32*)&length)) != LENGTH_ONLY_E) { + if ((ret = wc_BerToDer(pt, maxIdx, NULL, (word32*)&length)) + != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return ret; } } @@ -504,7 +504,7 @@ static void wc_PKCS7_ChangeState(PKCS7* pkcs7, int newState) pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state), newState, wc_PKCS7_GetStateName(newState)); #endif - pkcs7->state = newState; + pkcs7->state = (word32)newState; } #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ @@ -630,7 +630,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) return BAD_FUNC_ARG; } - idSz = SetLength(typeSz, ID_Length); + idSz = (int)SetLength(typeSz, ID_Length); output[idx++] = ASN_OBJECT_ID; XMEMCPY(output + idx, ID_Length, idSz); idx += idSz; @@ -1041,9 +1041,11 @@ static int wc_PKCS7_CheckPublicKeyDer(PKCS7* pkcs7, int keyOID, /* Try to decode public key and check with wc_ecc_check_key() */ ret = wc_EccPublicKeyDecode(key, &scratch, ecc, keySz); + #if defined(WOLFSSL_VALIDATE_ECC_IMPORT) if (ret == 0) { ret = wc_ecc_check_key(ecc); } + #endif wc_ecc_free(ecc); break; @@ -1167,9 +1169,9 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) pkcs7->publicKeyOID = dCert->keyOID; XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE); pkcs7->issuer = dCert->issuerRaw; - pkcs7->issuerSz = dCert->issuerRawLen; + pkcs7->issuerSz = (word32)dCert->issuerRawLen; XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz); - pkcs7->issuerSnSz = dCert->serialSz; + pkcs7->issuerSnSz = (word32)dCert->serialSz; XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE); /* default to IssuerAndSerialNumber for SignerIdentifier */ @@ -1306,7 +1308,7 @@ static int wc_PKCS7_SignerInfoSetSID(PKCS7* pkcs7, byte* in, int inSz) return MEMORY_E; } XMEMCPY(pkcs7->signerInfo->sid, in, inSz); - pkcs7->signerInfo->sidSz = inSz; + pkcs7->signerInfo->sidSz = (word32)inSz; return 0; } @@ -1554,7 +1556,7 @@ static int EncodeAttributes(EncodedAttrib* ea, int eaSz, PKCS7Attrib* attribs, int attribsSz) { int i; - int maxSz = min(eaSz, attribsSz); + int maxSz = (int)min((word32)eaSz, attribsSz); int allAttribsSz = 0; for (i = 0; i < maxSz; i++) @@ -1564,14 +1566,14 @@ static int EncodeAttributes(EncodedAttrib* ea, int eaSz, ea[i].value = attribs[i].value; ea[i].valueSz = attribs[i].valueSz; attribSz += ea[i].valueSz; - ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet); + ea[i].valueSetSz = SetSet((word32)attribSz, ea[i].valueSet); attribSz += ea[i].valueSetSz; ea[i].oid = attribs[i].oid; ea[i].oidSz = attribs[i].oidSz; attribSz += ea[i].oidSz; - ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq); + ea[i].valueSeqSz = SetSequence((word32)attribSz, ea[i].valueSeq); attribSz += ea[i].valueSeqSz; - ea[i].totalSz = attribSz; + ea[i].totalSz = (word32)attribSz; allAttribsSz += attribSz; } @@ -1614,7 +1616,7 @@ static void FreeAttribArray(PKCS7* pkcs7, FlatAttrib** arr, int rows) XFREE(arr[i], pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); } } - ForceZero(arr, rows); + ForceZero(arr, (word32)rows); XFREE(arr, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); } (void)pkcs7; @@ -1637,12 +1639,12 @@ static int SortAttribArray(FlatAttrib** arr, int rows) for (i = 0; i < rows; i++) { a = arr[i]; minSz = a->dataSz; - minIdx = i; + minIdx = (word32)i; for (j = i+1; j < rows; j++) { b = arr[j]; if (b->dataSz < minSz) { minSz = b->dataSz; - minIdx = j; + minIdx = (word32)j; } } if (minSz < a->dataSz) { @@ -1695,7 +1697,7 @@ static int FlattenEncodedAttribs(PKCS7* pkcs7, FlatAttrib** derArr, int rows, fa = derArr[i]; fa->data = output; - fa->dataSz = sz; + fa->dataSz = (word32)sz; } return 0; @@ -1715,12 +1717,12 @@ static int FlattenAttributes(PKCS7* pkcs7, byte* output, EncodedAttrib* ea, } /* create array of FlatAttrib struct pointers to hold DER attribs */ - derArr = (FlatAttrib**) XMALLOC(eaSz * sizeof(FlatAttrib*), pkcs7->heap, + derArr = (FlatAttrib**) XMALLOC((unsigned long)eaSz * sizeof(FlatAttrib*), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (derArr == NULL) { return MEMORY_E; } - XMEMSET(derArr, 0, eaSz * sizeof(FlatAttrib*)); + XMEMSET(derArr, 0, (unsigned long)eaSz * sizeof(FlatAttrib*)); for (i = 0; i < eaSz; i++) { derArr[i] = NewAttrib(pkcs7->heap); @@ -1785,7 +1787,8 @@ static int wc_PKCS7_ImportRSA(PKCS7* pkcs7, RsaKey* privKey) #endif } #ifdef WOLF_CRYPTO_CB - else if (ret == ASN_PARSE_E && pkcs7->devId != INVALID_DEVID) { + else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) && + pkcs7->devId != INVALID_DEVID) { /* if using crypto callbacks, try public key decode */ idx = 0; ret = wc_RsaPublicKeyDecode(pkcs7->privateKey, &idx, privKey, @@ -1837,7 +1840,7 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) privKey, pkcs7->rng); } #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif } @@ -1874,7 +1877,8 @@ static int wc_PKCS7_ImportECC(PKCS7* pkcs7, ecc_key* privKey) } } #ifdef WOLF_CRYPTO_CB - else if (ret == ASN_PARSE_E && pkcs7->devId != INVALID_DEVID) { + else if (ret == WC_NO_ERR_TRACE(ASN_PARSE_E) && + pkcs7->devId != INVALID_DEVID) { /* if using crypto callbacks, try public key decode */ idx = 0; ret = wc_EccPublicKeyDecode(pkcs7->privateKey, &idx, privKey, @@ -1927,7 +1931,7 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) &outSz, pkcs7->rng, privKey); } #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif if (ret == 0) ret = (int)outSz; @@ -2068,7 +2072,7 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, cannedAttribs[idx].oid = signingTimeOid; cannedAttribs[idx].oidSz = signingTimeOidSz; cannedAttribs[idx].value = signingTime; - cannedAttribs[idx].valueSz = timeSz; + cannedAttribs[idx].valueSz = (word32)timeSz; idx++; } #endif @@ -2078,13 +2082,13 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, cannedAttribs[idx].oid = messageDigestOid; cannedAttribs[idx].oidSz = messageDigestOidSz; cannedAttribs[idx].value = esd->contentDigest; - cannedAttribs[idx].valueSz = hashSz + 2; /* ASN.1 heading */ + cannedAttribs[idx].valueSz = (word32)hashSz + 2; /* ASN.1 heading */ idx++; } esd->signedAttribsCount += cannedAttribsCount; esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[atrIdx], - idx, cannedAttribs, cannedAttribsCount); + (int)idx, cannedAttribs, cannedAttribsCount); atrIdx += idx; } else { esd->signedAttribsCount = 0; @@ -2330,7 +2334,7 @@ static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); digIdx += hashSz; - *digestInfoSz = digIdx; + *digestInfoSz = (word32)digIdx; return 0; } @@ -2426,7 +2430,7 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, /* CMS with ECDSA does not sign DigestInfo structure * like PKCS#7 with RSA does */ ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, - hashSz, esd); + (word32)hashSz, esd); break; #endif @@ -2468,7 +2472,7 @@ static int wc_PKCS7_EncodeContentStreamHelper(PKCS7* pkcs7, int cipherType, Aes* aes, byte* encContentOut, byte* contentData, int contentDataSz, byte* out, word32* outIdx, ESD* esd) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); byte encContentOutOct[MAX_OCTET_STR_SZ]; word32 encContentOutOctSz = 0; @@ -2477,39 +2481,40 @@ static int wc_PKCS7_EncodeContentStreamHelper(PKCS7* pkcs7, int cipherType, XMEMCPY(encContentOut, contentData, contentDataSz); if (esd && esd->contentDigestSet != 1) { ret = wc_HashUpdate(&esd->hash, esd->hashType, - contentData, contentDataSz); + contentData, (word32)contentDataSz); } break; #ifndef NO_AES case WC_CIPHER_AES_CBC: ret = wc_AesCbcEncrypt(aes, encContentOut, - contentData, contentDataSz); + contentData, (word32)contentDataSz); break; #endif #ifdef WOLFSSL_AESGCM_STREAM case WC_CIPHER_AES_GCM: ret = wc_AesGcmEncryptUpdate(aes, encContentOut, - contentData, contentDataSz, NULL, 0); + contentData, (word32)contentDataSz, NULL, 0); break; #endif } #ifdef WOLFSSL_ASYNC_CRYPT /* async encrypt not available here, so block till done */ - if (ret == WC_PENDING_E && cipherType != WC_CIPHER_NONE) { + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E) && + cipherType != WC_CIPHER_NONE) { ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); } #endif if (ret == 0) { - encContentOutOctSz = SetOctetString(contentDataSz, encContentOutOct); + encContentOutOctSz = SetOctetString((word32)contentDataSz, encContentOutOct); wc_PKCS7_WriteOut(pkcs7, (out)? out + *outIdx: NULL, encContentOutOct, encContentOutOctSz); *outIdx += encContentOutOctSz; wc_PKCS7_WriteOut(pkcs7, (out)? out + *outIdx : NULL, - encContentOut, contentDataSz); + encContentOut, (word32)contentDataSz); *outIdx += contentDataSz; } @@ -2517,7 +2522,7 @@ static int wc_PKCS7_EncodeContentStreamHelper(PKCS7* pkcs7, int cipherType, } -/* Used for encoding the content, potentially one octet chunck at a time if +/* Used for encoding the content, potentially one octet chunk at a time if * in streaming mode with IO callbacks set. * Can handle the cipher types: * - WC_CIPHER_NONE, used for encoding signed bundle where no encryption is @@ -2551,7 +2556,7 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, if (cipherType != WC_CIPHER_NONE) { padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, - wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID)); + (word32)wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID)); } if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { @@ -2633,7 +2638,7 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, /* copy over any remaining data */ XMEMCPY(contentData, buf + sz, contentDataRead); - idx = contentDataRead; + idx = (word32)contentDataRead; } else { /* was not on an octet boundary, copy full @@ -2661,7 +2666,7 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, /* encrypt and flush out remainder of content data */ ret = wc_PKCS7_EncodeContentStreamHelper(pkcs7, cipherType, aes, - encContentOut, contentData, idx, out, &outIdx, esd); + encContentOut, contentData, (int)idx, out, &outIdx, esd); if (ret == 0) { if (cipherType == WC_CIPHER_NONE && esd && esd->contentDigestSet != 1) { @@ -2688,7 +2693,7 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, ret = wc_HashInit(&esd->hash, esd->hashType); if (ret == 0) ret = wc_HashUpdate(&esd->hash, esd->hashType, in, - inSz); + (word32)inSz); if (ret == 0) ret = wc_HashFinal(&esd->hash, esd->hashType, esd->contentDigest + 2); @@ -2698,13 +2703,13 @@ static int wc_PKCS7_EncodeContentStream(PKCS7* pkcs7, ESD* esd, void* aes, #ifndef NO_AES case WC_CIPHER_AES_CBC: - ret = wc_AesCbcEncrypt(aes, out, in, inSz); + ret = wc_AesCbcEncrypt(aes, out, in, (word32)inSz); break; #endif #ifdef WOLFSSL_AESGCM_STREAM case WC_CIPHER_AES_GCM: - ret = wc_AesGcmEncryptUpdate(aes, out, in, inSz, NULL, 0); + ret = wc_AesGcmEncryptUpdate(aes, out, in, (word32)inSz, NULL, 0); break; #endif } @@ -2829,7 +2834,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, idx = ret; goto out; } - pkcs7->contentTypeSz = ret; + pkcs7->contentTypeSz = (word32)ret; } /* set signedData outer content type */ @@ -2838,7 +2843,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, idx = ret; goto out; } - signedDataOidSz = ret; + signedDataOidSz = (word32)ret; if (pkcs7->sidType != DEGENERATE_SID) { esd->hashType = wc_OidGetHash(pkcs7->hashOID); @@ -2884,7 +2889,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, /* SignerIdentifier */ if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { /* IssuerAndSerialNumber */ - esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, + esd->issuerSnSz = (word32)SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, esd->issuerSn, MAX_SN_SZ, MAX_SN_SZ); signerInfoSz += esd->issuerSnSz; esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); @@ -2894,22 +2899,22 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, if (pkcs7->version == 3) { /* RFC 4108 version MUST be 3 for firmware package signer */ - esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); + esd->signerVersionSz = (word32)SetMyVersion(3, esd->signerVersion, 0); } else { /* version MUST be 1 otherwise*/ - esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); + esd->signerVersionSz = (word32)SetMyVersion(1, esd->signerVersion, 0); } } else if (pkcs7->sidType == CMS_SKID) { /* SubjectKeyIdentifier */ - esd->issuerSKIDSz = SetOctetString(keyIdSize, esd->issuerSKID); + esd->issuerSKIDSz = SetOctetString((word32)keyIdSize, esd->issuerSKID); esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + keyIdSize, esd->issuerSKIDSeq, 0); signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + keyIdSize); /* version MUST be 3 */ - esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); + esd->signerVersionSz = (word32)SetMyVersion(3, esd->signerVersion, 0); } else if (pkcs7->sidType == DEGENERATE_SID) { /* no signer info added */ } else { @@ -2966,7 +2971,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, } if (pkcs7->publicKeyOID != ECDSAk && hashBuf == NULL) { - ret = esd->encContentDigestSz = wc_PKCS7_GetSignSize(pkcs7); + ret = wc_PKCS7_GetSignSize(pkcs7); + esd->encContentDigestSz = (word32)ret; } else { ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, @@ -3011,10 +3017,10 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, if (pkcs7->version == 3) { /* RFC 4108 version MUST be 3 for firmware package signer */ - esd->versionSz = SetMyVersion(3, esd->version, 0); + esd->versionSz = (word32)SetMyVersion(3, esd->version, 0); } else { - esd->versionSz = SetMyVersion(1, esd->version, 0); + esd->versionSz = (word32)SetMyVersion(1, esd->version, 0); } totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + @@ -3096,7 +3102,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, } #endif *outputSz = totalSz; - idx = totalSz; + idx = (int)totalSz; goto out; } idx = BUFFER_E; @@ -3149,7 +3155,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, /* support returning header and footer without content */ if (output2 && output2Sz) { - *outputSz = idx; + *outputSz = (word32)idx; idx = 0; } else { @@ -3243,7 +3249,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, esd->issuerSKID, esd->issuerSKIDSz); idx += esd->issuerSKIDSz; wc_PKCS7_WriteOut(pkcs7, (output2)? (output2 + idx) : NULL, - pkcs7->issuerSubjKeyId, keyIdSize); + pkcs7->issuerSubjKeyId, (word32)keyIdSize); idx += keyIdSize; } else if (pkcs7->sidType == DEGENERATE_SID) { /* no signer infos in degenerate case */ @@ -3341,11 +3347,11 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, #endif if (output2Sz) { - *output2Sz = idx; + *output2Sz = (word32)idx; idx = 0; /* success */ } else { - *outputSz = idx; + *outputSz = (word32)idx; } out: @@ -3517,7 +3523,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) wc_HashFree(&hash, hashType); } if (ret == 0) { - ret = PKCS7_EncodeSigned(pkcs7, hashBuf, hashSz, + ret = PKCS7_EncodeSigned(pkcs7, hashBuf, (word32)hashSz, output, &outputSz, NULL, NULL); } } @@ -3669,7 +3675,7 @@ int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); if (ret != 0) { - ForceZero(encrypted, encryptedSz); + ForceZero(encrypted, (word32)encryptedSz); XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } @@ -3677,7 +3683,7 @@ int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, /* 2: build up SignedData, encapsulating EncryptedData */ pkcs7->rng = &rng; pkcs7->content = encrypted; - pkcs7->contentSz = encryptedSz; + pkcs7->contentSz = (word32)encryptedSz; pkcs7->contentOID = ENCRYPTED_DATA; pkcs7->hashOID = hashOID; pkcs7->encryptOID = signOID; @@ -3691,7 +3697,7 @@ int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, WOLFSSL_MSG("Error encoding CMS SignedData content type"); } - ForceZero(encrypted, encryptedSz); + ForceZero(encrypted, (word32)encryptedSz); XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); pkcs7->rng = NULL; wc_FreeRng(&rng); @@ -4041,11 +4047,11 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, + ret = wc_RsaSSL_Verify(sig, (word32)sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); } #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif FreeDecodedCert(dCert); wc_FreeRsaKey(key); @@ -4169,10 +4175,10 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { - ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + ret = wc_ecc_verify_hash(sig, (word32)sigSz, hash, hashSz, &res, key); } #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif FreeDecodedCert(dCert); @@ -4248,7 +4254,7 @@ static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, ret = wc_HashGetDigestSize(hashType); if (ret < 0) return ret; - hashSz = ret; + hashSz = (word32)ret; if (signedAttribSz > 0) { if (signedAttrib == NULL) @@ -4329,7 +4335,7 @@ static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, digIdx += hashSz; XMEMCPY(pkcs7Digest, digestInfo, digIdx); - *pkcs7DigestSz = digIdx; + *pkcs7DigestSz = (word32)digIdx; /* set plain digest pointer */ *plainDigest = pkcs7Digest + digIdx - hashSz; @@ -4421,7 +4427,7 @@ static int wc_PKCS7_VerifyContentMessageDigest(PKCS7* pkcs7, XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); content = pkcs7->content; - contentLen = pkcs7->contentSz; + contentLen = (int)pkcs7->contentSz; if (pkcs7->contentIsPkcs7Type == 1) { /* Content follows PKCS#7 RFC, which defines type as ANY. CMS @@ -4434,7 +4440,7 @@ static int wc_PKCS7_VerifyContentMessageDigest(PKCS7* pkcs7, } if (GetLength_ex(content, &contentIdx, &contentLen, - contentLen, 1) < 0) { + (word32)contentLen, 1) < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -4442,7 +4448,7 @@ static int wc_PKCS7_VerifyContentMessageDigest(PKCS7* pkcs7, } } - ret = wc_Hash(hashType, content + contentIdx, contentLen, digest, + ret = wc_Hash(hashType, content + contentIdx, (word32)contentLen, digest, MAX_PKCS7_DIGEST_SZ); if (ret < 0) { WOLFSSL_MSG("Error hashing PKCS7 content for verification"); @@ -4623,11 +4629,11 @@ static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, #ifndef NO_RSA case RSAk: - ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, + ret = wc_PKCS7_RsaVerify(pkcs7, sig, (int)sigSz, pkcs7Digest, pkcs7DigestSz); if (ret < 0) { WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); - ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, + ret = wc_PKCS7_RsaVerify(pkcs7, sig, (int)sigSz, plainDigest, plainDigestSz); } break; @@ -4635,7 +4641,7 @@ static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, #ifdef HAVE_ECC case ECDSAk: - ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, + ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, (int)sigSz, plainDigest, plainDigestSz); break; #endif @@ -4681,7 +4687,7 @@ static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) /* if sigOID is already RSAk */ case RSAk: - pkcs7->publicKeyOID = sigOID; + pkcs7->publicKeyOID = (word32)sigOID; break; #endif @@ -4693,7 +4699,7 @@ static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) /* if sigOID is already DSAk */ case DSAk: - pkcs7->publicKeyOID = sigOID; + pkcs7->publicKeyOID = (word32)sigOID; break; #endif @@ -4713,7 +4719,7 @@ static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) /* if sigOID is already ECDSAk */ case ECDSAk: - pkcs7->publicKeyOID = sigOID; + pkcs7->publicKeyOID = (word32)sigOID; break; #endif @@ -4757,7 +4763,7 @@ static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) int oidIdx; PKCS7DecodedAttrib* attrib; - if (GetSequence(in, &idx, &length, inSz) < 0) + if (GetSequence(in, &idx, &length, (word32)inSz) < 0) return ASN_PARSE_E; attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib), @@ -4767,8 +4773,8 @@ static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) } XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib)); - oidIdx = idx; - if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz) + oidIdx = (int)idx; + if (GetObjectId(in, &idx, &oid, oidIgnoreType, (word32)inSz) < 0) { XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; @@ -4783,7 +4789,7 @@ static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz); /* Get Set that contains the printable string value */ - if (GetSet(in, &idx, &length, inSz) < 0) { + if (GetSet(in, &idx, &length, (word32)inSz) < 0) { XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ASN_PARSE_E; @@ -4992,7 +4998,7 @@ static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, /* store public key type based on digestEncryptionAlgorithm */ if (ret == 0) { - ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); + ret = wc_PKCS7_SetPublicKeyOID(pkcs7, (int)sigOID); if (ret < 0) { WOLFSSL_MSG("Failed to set public key OID from signature"); } @@ -5087,8 +5093,8 @@ static int wc_PKCS7_HandleOctetStrings(PKCS7* pkcs7, byte* in, word32 inSz, } /* set up for next octet string */ - pkcs7->stream->currContSz = length; - pkcs7->stream->currContRmnSz = length; + pkcs7->stream->currContSz = (word32)length; + pkcs7->stream->currContRmnSz = (word32)length; pkcs7->stream->expected = min(pkcs7->stream->currContRmnSz, MAX_PKCS7_STREAM_BUFFER); @@ -5100,7 +5106,7 @@ static int wc_PKCS7_HandleOctetStrings(PKCS7* pkcs7, byte* in, word32 inSz, /* check if expected data is available in stream */ ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, &msg, idx); - if (ret == WC_PKCS7_WANT_READ_E) { + if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { break; /* ask user more input */ } @@ -5114,7 +5120,7 @@ static int wc_PKCS7_HandleOctetStrings(PKCS7* pkcs7, byte* in, word32 inSz, * in-definite length encoding. * number of indef is stored in pkcs7->stream->cntIdfCnt. */ - pkcs7->stream->expected = (ASN_TAG_SZ + TRAILING_ZERO) * + pkcs7->stream->expected = (word32)(ASN_TAG_SZ + TRAILING_ZERO) * pkcs7->stream->cntIdfCnt; /* dec idx by one since already consumed to get ASN_EOC */ @@ -5127,7 +5133,7 @@ static int wc_PKCS7_HandleOctetStrings(PKCS7* pkcs7, byte* in, word32 inSz, /* check if expected data is available in stream */ ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, &msg, idx); - if (ret == WC_PKCS7_WANT_READ_E) { + if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { break; /* ask user more input */ } @@ -5164,7 +5170,7 @@ static int wc_PKCS7_HandleOctetStrings(PKCS7* pkcs7, byte* in, word32 inSz, ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, &msg, idx); - if (ret == WC_PKCS7_WANT_READ_E) { + if (ret == WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { break; } @@ -5371,7 +5377,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 len = 0; ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); - if (ret != LENGTH_ONLY_E) + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) return ret; pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -5475,7 +5481,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, < 0) ret = ASN_PARSE_E; - pkcs7->hashOID = hashOID; + pkcs7->hashOID = (int)hashOID; /* get hash type */ hashType = wc_OidGetHash(pkcs7->hashOID); @@ -5708,8 +5714,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #ifndef NO_PKCS7_STREAM pkcs7->stream->multi = multiPart; pkcs7->stream->currContIdx = localIdx; - pkcs7->stream->currContSz = length; - pkcs7->stream->currContRmnSz = length; + pkcs7->stream->currContSz = (word32)length; + pkcs7->stream->currContRmnSz = (word32)length; #endif /* reset length to outer OCTET_STRING for bundle * size check below */ @@ -5736,8 +5742,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (ret == 0) { pkcs7->stream->multi = multiPart; pkcs7->stream->currContIdx = localIdx; - pkcs7->stream->currContSz = length; - pkcs7->stream->currContRmnSz = length; + pkcs7->stream->currContSz = (word32)length; + pkcs7->stream->currContRmnSz = (word32)length; } #endif } @@ -5821,7 +5827,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { break; } - wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, (int)localIdx, length); #endif /* !NO_PKCS7_STREAM */ @@ -6081,7 +6087,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); if (length > 0) { - pkcs7->stream->expected = length; + pkcs7->stream->expected = (word32)length; } else { pkcs7->stream->expected = MAX_SEQ_SZ; @@ -6119,7 +6125,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* restore content */ content = pkcs7->stream->content; - contentSz = pkcs7->stream->contentSz; + contentSz = (int)pkcs7->stream->contentSz; /* restore detached flag */ detached = pkcs7->stream->detached; @@ -6139,7 +6145,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); pkiMsg2 = pkcs7->stream->tmpCert; - pkiMsg2Sz = length; + pkiMsg2Sz = (word32)length; idx = 0; } #else @@ -6209,7 +6215,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->isDynamic = isDynamic; /* This will reset PKCS7 structure and then set the * certificate */ - ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + ret = wc_PKCS7_InitWithCert(pkcs7, cert, (word32)certSz); /* Restore pkcs7->contentDynamic from above, will be * freed by application with wc_PKCS7_Free() */ @@ -6238,7 +6244,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, int i; pkcs7->cert[0] = cert; - pkcs7->certSz[0] = certSz; + pkcs7->certSz[0] = (word32)certSz; certIdx = idx + certSz; for (i = 1; i < MAX_PKCS7_CERTS && @@ -6411,7 +6417,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { if (length > 0) { - pkcs7->stream->expected = length; + pkcs7->stream->expected = (word32)length; } else { pkcs7->stream->expected = 0; @@ -6426,10 +6432,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, * zero's should exist at the end of the bundle. */ if (pkcs7->stream->indefLen == 1) { - pkcs7->stream->expected = length + 3 * ASN_INDEF_END_SZ; + pkcs7->stream->expected = (word32)length + 3 * ASN_INDEF_END_SZ; } else { - pkcs7->stream->expected = length; + pkcs7->stream->expected = (word32)length; } wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE7); @@ -6460,7 +6466,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* restore content */ content = pkcs7->stream->content; - contentSz = pkcs7->stream->contentSz; + contentSz = (int)pkcs7->stream->contentSz; #endif ret = wc_PKCS7_ParseSignerInfo(pkcs7, pkiMsg2, pkiMsg2Sz, &idx, @@ -6489,18 +6495,18 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } pkcs7->content = content; - pkcs7->contentSz = contentSz; + pkcs7->contentSz = (word32)contentSz; if (ret == 0) { - ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, - signedAttrib, signedAttribSz, + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, (word32)sigSz, + signedAttrib, (word32)signedAttribSz, hashBuf, hashSz); } } #ifndef NO_PKCS7_STREAM /* make sure that terminating zero's follow */ - if ((ret == PKCS7_SIGNEEDS_CHECK || ret >= 0) && + if ((ret == WC_NO_ERR_TRACE(PKCS7_SIGNEEDS_CHECK) || ret >= 0) && pkcs7->stream->indefLen == 1) { int i; for (i = 0; i < 3 * ASN_INDEF_END_SZ; i++) { @@ -6528,7 +6534,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, ret = BAD_FUNC_ARG; } - if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { #ifndef NO_PKCS7_STREAM wc_PKCS7_ResetStream(pkcs7); #endif @@ -7037,7 +7043,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) return BAD_FUNC_ARG; /* kekOctet */ - kekOctetSz = SetOctetString(sizeof(word32), kekOctet); + kekOctetSz = (int)SetOctetString(sizeof(word32), kekOctet); sharedInfoSz += (kekOctetSz + sizeof(word32)); /* suppPubInfo */ @@ -7048,7 +7054,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) /* optional ukm/entityInfo */ if (kari->ukmSz > 0) { - entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); + entityUInfoOctetSz = (int)SetOctetString(kari->ukmSz, entityUInfoOctet); sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + @@ -7058,11 +7064,11 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) } /* keyInfo */ - keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0); + keyInfoSz = (int)SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0); sharedInfoSz += keyInfoSz; /* sharedInfo */ - sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq); + sharedInfoSeqSz = (int)SetSequence((word32)sharedInfoSz, sharedInfoSeq); sharedInfoSz += sharedInfoSeqSz; kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap, @@ -7070,7 +7076,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) if (kari->sharedInfo == NULL) return MEMORY_E; - kari->sharedInfoSz = sharedInfoSz; + kari->sharedInfoSz = (word32)sharedInfoSz; XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz); idx += sharedInfoSeqSz; @@ -7132,7 +7138,7 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, WC_RNG* rng, return ret; /* generate shared secret */ - secretSz = kari->senderKey->dp->size; + secretSz = (word32)kari->senderKey->dp->size; secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7); if (secret == NULL) return MEMORY_E; @@ -7321,7 +7327,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, } /* generate random content encryption key, if needed */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz); if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -7420,11 +7426,11 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* Start of RecipientEncryptedKeys */ /* EncryptedKey */ - encryptedKeyOctetSz = SetOctetString(encryptedKeySz, encryptedKeyOctet); + encryptedKeyOctetSz = (int)SetOctetString(encryptedKeySz, encryptedKeyOctet); totalSz += (encryptedKeyOctetSz + encryptedKeySz); /* SubjectKeyIdentifier */ - subjKeyIdOctetSz = SetOctetString(keyIdSize, subjKeyIdOctet); + subjKeyIdOctetSz = (int)SetOctetString((word32)keyIdSize, subjKeyIdOctet); totalSz += (subjKeyIdOctetSz + keyIdSize); /* RecipientKeyIdentifier IMPLICIT [0] */ @@ -7433,17 +7439,17 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, totalSz += recipKeyIdSeqSz; /* RecipientEncryptedKey */ - recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq); + recipEncKeySeqSz = (int)SetSequence((word32)totalSz, recipEncKeySeq); totalSz += recipEncKeySeqSz; /* RecipientEncryptedKeys */ - recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq); + recipEncKeysSeqSz = (int)SetSequence((word32)totalSz, recipEncKeysSeq); totalSz += recipEncKeysSeqSz; /* Start of optional UserKeyingMaterial */ if (kari->ukmSz > 0) { - ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr); + ukmOctetSz = (int)SetOctetString(kari->ukmSz, ukmOctetStr); totalSz += (ukmOctetSz + kari->ukmSz); ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz, @@ -7454,11 +7460,11 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* Start of KeyEncryptionAlgorithmIdentifier */ /* KeyWrapAlgorithm */ - keyWrapAlgSz = SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0); + keyWrapAlgSz = (int)SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0); totalSz += keyWrapAlgSz; /* KeyEncryptionAlgorithmIdentifier */ - keyEncryptAlgoIdSz = SetAlgoID(keyAgreeOID, keyEncryptAlgoId, + keyEncryptAlgoIdSz = (int)SetAlgoID(keyAgreeOID, keyEncryptAlgoId, oidCmsKeyAgreeType, keyWrapAlgSz); totalSz += keyEncryptAlgoIdSz; @@ -7467,25 +7473,25 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* recipient ECPoint, public key */ XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */ origPubKeyStr[0] = ASN_BIT_STRING; - origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1, + origPubKeyStrSz = (int)SetLength(kari->senderKeyExportSz + 1, origPubKeyStr + 1) + 2; totalSz += (origPubKeyStrSz + kari->senderKeyExportSz); /* Originator AlgorithmIdentifier, params set to NULL for interop compatibility */ - origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2); + origAlgIdSz = (int)SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2); origAlgId[origAlgIdSz++] = ASN_TAG_NULL; origAlgId[origAlgIdSz++] = 0; totalSz += origAlgIdSz; /* outer OriginatorPublicKey IMPLICIT [1] */ - origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1, + origPubKeySeqSz = (int)SetImplicit(ASN_SEQUENCE, 1, origAlgIdSz + origPubKeyStrSz + kari->senderKeyExportSz, origPubKeySeq, 0); totalSz += origPubKeySeqSz; /* outer OriginatorIdentifierOrKey IMPLICIT [0] */ - origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0, + origIdOrKeySeqSz = (int)SetImplicit(ASN_SEQUENCE, 0, origPubKeySeqSz + origAlgIdSz + origPubKeyStrSz + kari->senderKeyExportSz, origIdOrKeySeq, 0); @@ -7497,7 +7503,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, recip->recipVersion = 3; /* outer IMPLICIT [1] kari */ - kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq, 0); + kariSeqSz = (int)SetImplicit(ASN_SEQUENCE, 1, (word32)totalSz, kariSeq, 0); totalSz += kariSeqSz; if (totalSz > MAX_RECIP_SZ) { @@ -7583,7 +7589,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, (void)options; - return idx; + return (int)idx; } #endif /* HAVE_ECC */ @@ -7704,7 +7710,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, } /* generate random content encryption key, if needed */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz); if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -7757,7 +7763,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, return -1; } issuerSz = decoded->issuerRawLen; - issuerSeqSz = SetSequence(issuerSz, issuerSeq); + issuerSeqSz = (int)SetSequence((word32)issuerSz, issuerSeq); if (decoded->serialSz == 0) { WOLFSSL_MSG("DecodedCert missing serial number"); @@ -7793,7 +7799,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, verSz = SetMyVersion(2, ver, 0); recip->recipVersion = 2; - issuerSKIDSz = SetLength(keyIdSize, issuerSKID); + issuerSKIDSz = SetLength((word32)keyIdSize, issuerSKID); } else { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK @@ -7906,7 +7912,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, encryptedKeySz, pubKey, &rng); } #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif wc_FreeRsaKey(pubKey); wc_FreeRng(&rng); @@ -7927,13 +7933,13 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } - encryptedKeySz = ret; + encryptedKeySz = (word32)ret; - encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + encKeyOctetStrSz = (int)SetOctetString(encryptedKeySz, encKeyOctetStr); /* RecipientInfo */ if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { - recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + + recipSeqSz = (int)SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz, recipSeq); @@ -8024,7 +8030,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, lastRecip->next = recip; } - return idx; + return (int)idx; } #endif /* !NO_RSA */ @@ -8137,7 +8143,7 @@ static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif ret = wc_AesInit(aes, heap, devId); if (ret == 0) { - ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION); + ret = wc_AesSetKey(aes, key, (word32)keySz, iv, AES_ENCRYPTION); if (ret == 0) { ret = wc_PKCS7_EncodeContentStream(pkcs7, NULL, aes, in, inSz, out, WC_CIPHER_AES_CBC); @@ -8171,7 +8177,7 @@ static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif ret = wc_AesInit(aes, heap, devId); if (ret == 0) { - ret = wc_AesGcmSetKey(aes, key, keySz); + ret = wc_AesGcmSetKey(aes, key, (word32)keySz); if (ret == 0) { #ifndef WOLFSSL_AESGCM_STREAM if (pkcs7->encodeStream) { @@ -8188,7 +8194,7 @@ static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif } #else - ret = wc_AesGcmEncryptInit(aes, key, keySz, iv, ivSz); + ret = wc_AesGcmEncryptInit(aes, key, (word32)keySz, iv, ivSz); if (ret == 0) { ret = wc_AesGcmEncryptUpdate(aes, NULL, NULL, 0, aad, aadSz); @@ -8238,9 +8244,9 @@ static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif ret = wc_AesInit(aes, heap, devId); if (ret == 0) { - ret = wc_AesCcmSetKey(aes, key, keySz); + ret = wc_AesCcmSetKey(aes, key, (word32)keySz); if (ret == 0) { - ret = wc_AesCcmEncrypt(aes, out, in, inSz, iv, ivSz, + ret = wc_AesCcmEncrypt(aes, out, in, (word32)inSz, iv, ivSz, authTag, authTagSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async encrypt not available here, so block till done */ @@ -8268,7 +8274,7 @@ static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION); if (ret == 0) - ret = wc_Des_CbcEncrypt(&des, out, in, inSz); + ret = wc_Des_CbcEncrypt(&des, out, in, (word32)inSz); break; @@ -8285,7 +8291,7 @@ static int wc_PKCS7_EncryptContent(PKCS7* pkcs7, int encryptOID, byte* key, if (ret == 0) { ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION); if (ret == 0) { - ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz); + ret = wc_Des3_CbcEncrypt(&des3, out, in, (word32)inSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async encrypt not available here, so block till done */ ret = wc_AsyncWait(ret, &des3.asyncDev, WC_ASYNC_FLAG_NONE); @@ -8372,9 +8378,9 @@ static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif ret = wc_AesInit(aes, heap, devId); if (ret == 0) { - ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION); + ret = wc_AesSetKey(aes, key, (word32)keySz, iv, AES_DECRYPTION); if (ret == 0) { - ret = wc_AesCbcDecrypt(aes, out, in, inSz); + ret = wc_AesCbcDecrypt(aes, out, in, (word32)inSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async decrypt not available here, so block till done */ ret = wc_AsyncWait(ret, &aes->asyncDev, WC_ASYNC_FLAG_NONE); @@ -8409,9 +8415,9 @@ static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif ret = wc_AesInit(aes, heap, devId); if (ret == 0) { - ret = wc_AesGcmSetKey(aes, key, keySz); + ret = wc_AesGcmSetKey(aes, key, (word32)keySz); if (ret == 0) { - ret = wc_AesGcmDecrypt(aes, out, in, inSz, iv, ivSz, + ret = wc_AesGcmDecrypt(aes, out, in, (word32)inSz, iv, ivSz, authTag, authTagSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async decrypt not available here, so block till done */ @@ -8448,9 +8454,9 @@ static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, #endif ret = wc_AesInit(aes, heap, devId); if (ret == 0) { - ret = wc_AesCcmSetKey(aes, key, keySz); + ret = wc_AesCcmSetKey(aes, key, (word32)keySz); if (ret == 0) { - ret = wc_AesCcmDecrypt(aes, out, in, inSz, iv, ivSz, + ret = wc_AesCcmDecrypt(aes, out, in, (word32)inSz, iv, ivSz, authTag, authTagSz, aad, aadSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async decrypt not available here, so block till done */ @@ -8473,7 +8479,7 @@ static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION); if (ret == 0) - ret = wc_Des_CbcDecrypt(&des, out, in, inSz); + ret = wc_Des_CbcDecrypt(&des, out, in, (word32)inSz); break; case DES3b: @@ -8484,7 +8490,7 @@ static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, if (ret == 0) { ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION); if (ret == 0) { - ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz); + ret = wc_Des3_CbcDecrypt(&des3, out, in, (word32)inSz); #ifdef WOLFSSL_ASYNC_CRYPT /* async decrypt not available here, so block till done */ ret = wc_AsyncWait(ret, &des3.asyncDev, WC_ASYNC_FLAG_NONE); @@ -8628,6 +8634,8 @@ int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, return BAD_FUNC_ARG; padSz = wc_PKCS7_GetPadSize(inSz, blockSz); + if (padSz < 0) + return padSz; if (outSz < (inSz + padSz)) return BAD_FUNC_ARG; @@ -8682,7 +8690,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, } /* generate random content encryption key, if needed */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz); if (ret < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; @@ -8697,7 +8705,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, return ret; } - oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen); + oriTypeLenSz = (int)SetLength(oriTypeSz, oriTypeLen); recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz + oriValueSz, recipSeq, 0); @@ -8734,7 +8742,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, (void)options; - return idx; + return (int)idx; } #if !defined(NO_PWDBASED) && !defined(NO_SHA) @@ -8754,8 +8762,8 @@ static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, case PBKDF2_OID: - ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations, - outSz, prfOID); + ret = wc_PBKDF2(out, passwd, (int)pLen, salt, saltSz, iterations, + (int)outSz, prfOID); if (ret != 0) { return ret; } @@ -8806,7 +8814,7 @@ static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, /* if user set out to NULL, give back required length */ if (out == NULL) { - *outSz = outLen; + *outSz = (word32)outLen; return LENGTH_ONLY_E; } @@ -8829,21 +8837,21 @@ static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, if (ret == 0) { /* encrypt, normal */ - ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, - (byte*)iv, ivSz, NULL, 0, NULL, 0, out, + ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, (int)kekSz, + (byte*)iv, (int)ivSz, NULL, 0, NULL, 0, out, outLen, out); } if (ret == 0) { /* encrypt again, using last ciphertext block as IV */ lastBlock = out + (((outLen / blockSz) - 1) * blockSz); - ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, kekSz, + ret = wc_PKCS7_EncryptContent(pkcs7, algID, (byte*)kek, (int)kekSz, lastBlock, blockSz, NULL, 0, NULL, 0, out, outLen, out); } if (ret == 0) { - *outSz = outLen; + *outSz = (word32)outLen; } else { outLen = ret; } @@ -8899,21 +8907,21 @@ static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, tmpIv = lastBlock - blockSz; /* decrypt last block */ - ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, tmpIv, + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, (int)kekSz, tmpIv, blockSz, NULL, 0, NULL, 0, lastBlock, blockSz, outTmp + inSz - blockSz, pkcs7->devId, pkcs7->heap); if (ret == 0) { /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ lastBlock = outTmp + inSz - blockSz; - ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, (int)kekSz, lastBlock, blockSz, NULL, 0, NULL, 0, (byte*)in, inSz - blockSz, outTmp, pkcs7->devId, pkcs7->heap); } if (ret == 0) { /* decrypt using original kek and iv */ - ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, (int)kekSz, (byte*)iv, ivSz, NULL, 0, NULL, 0, outTmp, inSz, outTmp, pkcs7->devId, pkcs7->heap); } @@ -9035,12 +9043,12 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, return kekBlockSz; /* generate random CEK */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, cekKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)cekKeySz); if (ret < 0) return ret; /* generate random IV */ - ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, kekBlockSz); + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, (word32)kekBlockSz); if (ret != 0) return ret; @@ -9072,7 +9080,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, /* generate KEK: expand password into KEK */ ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, kdfOID, hashOID, iterations, kek, - kekKeySz); + (word32)kekKeySz); if (ret < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -9081,23 +9089,23 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, } /* generate encrypted key: encrypt CEK with KEK */ - ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, kekKeySz, pkcs7->cek, + ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, (word32)kekKeySz, pkcs7->cek, pkcs7->cekSz, encryptedKey, &encryptedKeySz, - tmpIv, kekBlockSz, encryptOID); + tmpIv, (word32)kekBlockSz, encryptOID); if (ret < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } - encryptedKeySz = ret; + encryptedKeySz = (word32)ret; /* put together encrypted key OCTET STRING */ encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); totalSz += (encKeyOctetStrSz + encryptedKeySz); /* put together IV OCTET STRING */ - ivOctetStringSz = SetOctetString(kekBlockSz, ivOctetString); + ivOctetStringSz = SetOctetString((word32)kekBlockSz, ivOctetString); totalSz += (ivOctetStringSz + kekBlockSz); /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + @@ -9114,7 +9122,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } - keyEncAlgoIdSz = ret; + keyEncAlgoIdSz = (word32)ret; totalSz += keyEncAlgoIdSz; /* KeyEncryptionAlgorithm SEQ */ @@ -9128,7 +9136,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, totalSz += (kdfSaltOctetStrSz + saltSz); /* set KDF iteration count */ - kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0); + kdfIterationsSz = (word32)SetMyVersion((word32)iterations, kdfIterations, 0); totalSz += kdfIterationsSz; /* set KDF params SEQ */ @@ -9144,7 +9152,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } - kdfAlgoIdSz = ret; + kdfAlgoIdSz = (word32)ret; totalSz += kdfAlgoIdSz; /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */ @@ -9154,7 +9162,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, totalSz += kdfAlgoIdSeqSz; /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ - verSz = SetMyVersion(0, ver, 0); + verSz = (word32)SetMyVersion(0, ver, 0); totalSz += verSz; recip->recipVersion = 0; @@ -9202,7 +9210,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); idx += encryptedKeySz; - ForceZero(kek, kekBlockSz); + ForceZero(kek, (word32)kekBlockSz); ForceZero(encryptedKey, encryptedKeySz); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -9224,7 +9232,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, (void)options; - return idx; + return (int)idx; } /* Import password and KDF settings into a PKCS7 structure. Used for setting @@ -9315,7 +9323,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, } /* generate random content encryption key, if needed */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz); if (ret < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; @@ -9340,7 +9348,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, #endif encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz, - encryptedKey, encryptedKeySz, keyWrapOID, + encryptedKey, (word32)encryptedKeySz, keyWrapOID, direction); if (encryptedKeySz < 0) { #ifdef WOLFSSL_SMALL_STACK @@ -9358,7 +9366,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, return WC_KEY_SIZE_E; } - encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + encKeyOctetStrSz = SetOctetString((word32)encryptedKeySz, encKeyOctetStr); totalSz += (encKeyOctetStrSz + encryptedKeySz); /* KeyEncryptionAlgorithmIdentifier */ @@ -9397,7 +9405,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, totalSz += kekIdSeqSz; /* version */ - verSz = SetMyVersion(4, ver, 0); + verSz = (word32)SetMyVersion(4, ver, 0); totalSz += verSz; recip->recipVersion = 4; @@ -9464,7 +9472,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, (void)options; - return idx; + return (int)idx; } @@ -9583,7 +9591,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* generate random content encryption key */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz); if (ret != 0) { return ret; } @@ -9626,7 +9634,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("You must add at least one CMS recipient"); return PKCS7_RECIP_E; } - recipSetSz = SetSet(recipSz, recipSet); + recipSetSz = (int)SetSet((word32)recipSz, recipSet); /* version, defined in Section 6.1 of RFC 5652 */ kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA); @@ -9636,7 +9644,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) return PKCS7_RECIP_E; } - verSz = SetMyVersion(kariVersion, ver, 0); + verSz = SetMyVersion((word32)kariVersion, ver, 0); ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); if (ret != 0) { @@ -9645,7 +9653,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* generate IV for block cipher */ - ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, blockSz); + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, (word32)blockSz); wc_FreeRng(&rng); if (ret != 0) { wc_PKCS7_FreeEncodedRecipientSet(pkcs7); @@ -9663,7 +9671,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentTypeSz = ret; /* allocate encrypted content buffer and PKCS#7 padding */ - padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, (word32)blockSz); if (padSz < 0) { wc_PKCS7_FreeEncodedRecipientSet(pkcs7); return padSz; @@ -9682,7 +9690,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, - encryptedOutSz, blockSz); + (word32)encryptedOutSz, blockSz); if (ret < 0) { XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); wc_PKCS7_FreeEncodedRecipientSet(pkcs7); @@ -9705,11 +9713,11 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* put together IV OCTET STRING */ - ivOctetStringSz = SetOctetString(blockSz, ivOctetString); + ivOctetStringSz = (int)SetOctetString((word32)blockSz, ivOctetString); /* build up our ContentEncryptionAlgorithmIdentifier sequence, * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ - contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + contentEncAlgoSz = (int)SetAlgoID(pkcs7->encryptOID, contentEncAlgo, oidBlkType, ivOctetStringSz + blockSz); if (contentEncAlgoSz == 0) { @@ -9719,9 +9727,9 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) return BAD_FUNC_ARG; } - encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctetSz = (int)SetImplicit(ASN_OCTET_STRING, 0, (word32)encryptedOutSz, encContentOctet, pkcs7->encodeStream); - encContentSeqSz = SetSequenceEx(contentTypeSz + contentEncAlgoSz + + encContentSeqSz = (int)SetSequenceEx(contentTypeSz + contentEncAlgoSz + ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz, encContentSeq, pkcs7->encodeStream); @@ -9743,10 +9751,10 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) totalSz += ASN_INDEF_END_SZ; /* account for asn1 syntax around octet strings */ - StreamOctetString(NULL, encryptedOutSz, NULL, &streamSz, &tmpIdx); + StreamOctetString(NULL, (word32)encryptedOutSz, NULL, &streamSz, &tmpIdx); totalSz += (streamSz - encryptedOutSz); - /* resize encrytped content buffer */ + /* resize encrypted content buffer */ if (encryptedContent != NULL) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); encryptedContent = (byte*)XMALLOC(streamSz, pkcs7->heap, @@ -9759,7 +9767,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } } #endif - envDataSeqSz = SetSequenceEx(totalSz, envDataSeq, pkcs7->encodeStream); + envDataSeqSz = (int)SetSequenceEx((word32)totalSz, envDataSeq, pkcs7->encodeStream); totalSz += envDataSeqSz; #ifdef ASN_BER_TO_DER if (pkcs7->encodeStream) { @@ -9768,7 +9776,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif /* outer content */ - outerContentSz = SetExplicit(0, totalSz, outerContent, pkcs7->encodeStream); + outerContentSz = (int)SetExplicit(0, (word32)totalSz, outerContent, pkcs7->encodeStream); #ifdef ASN_BER_TO_DER if (pkcs7->encodeStream) { totalSz += ASN_INDEF_END_SZ; @@ -9779,7 +9787,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { /* ContentInfo */ - contentInfoSeqSz = SetSequenceEx(totalSz, contentInfoSeq, + contentInfoSeqSz = (int)SetSequenceEx((word32)totalSz, contentInfoSeq, pkcs7->encodeStream); totalSz += contentInfoSeqSz; #ifdef ASN_BER_TO_DER @@ -9804,24 +9812,24 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* begin writing out PKCS7 bundle */ if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - contentInfoSeq, contentInfoSeqSz); + contentInfoSeq, (word32)contentInfoSeqSz); idx += contentInfoSeqSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - outerContentType, outerContentTypeSz); + outerContentType, (word32)outerContentTypeSz); idx += outerContentTypeSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - outerContent, outerContentSz); + outerContent, (word32)outerContentSz); idx += outerContentSz; } wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - envDataSeq, envDataSeqSz); + envDataSeq, (word32)envDataSeqSz); idx += envDataSeqSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - ver, verSz); + ver, (word32)verSz); idx += verSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - recipSet, recipSetSz); + recipSet, (word32)recipSetSz); idx += recipSetSz; /* copy in recipients from list */ tmpRecip = pkcs7->recipList; @@ -9834,22 +9842,22 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) wc_PKCS7_FreeEncodedRecipientSet(pkcs7); wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - encContentSeq, encContentSeqSz); + encContentSeq, (word32)encContentSeqSz); idx += encContentSeqSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - contentType, contentTypeSz); + contentType, (word32)contentTypeSz); idx += contentTypeSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - contentEncAlgo, contentEncAlgoSz); + contentEncAlgo, (word32)contentEncAlgoSz); idx += contentEncAlgoSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - ivOctetString, ivOctetStringSz); + ivOctetString, (word32)ivOctetStringSz); idx += ivOctetStringSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - tmpIv, blockSz); + tmpIv, (word32)blockSz); idx += blockSz; wc_PKCS7_WriteOut(pkcs7, (output)? (output + idx) : NULL, - encContentOctet, encContentOctetSz); + encContentOctet, (word32)encContentOctetSz); idx += encContentOctetSz; /* encrypt content */ @@ -10035,7 +10043,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkcs7->stream->expected = sz + MAX_ALGO_SZ + ASN_TAG_SZ + + pkcs7->stream->expected = (word32)sz + MAX_ALGO_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ; if (pkcs7->stream->length > 0 && pkcs7->stream->length < pkcs7->stream->expected) { @@ -10050,7 +10058,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - if (GetNameHash_ex(pkiMsg, idx, issuerHash, pkiMsgSz, + if (GetNameHash_ex(pkiMsg, idx, issuerHash, (int)pkiMsgSz, pkcs7->publicKeyOID) < 0) return ASN_PARSE_E; @@ -10156,8 +10164,8 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { break; } - wc_PKCS7_StreamStoreVar(pkcs7, encryptedKeySz, sidType, version); - pkcs7->stream->expected = encryptedKeySz; + wc_PKCS7_StreamStoreVar(pkcs7, (word32)encryptedKeySz, sidType, version); + pkcs7->stream->expected = (word32)encryptedKeySz; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3); FALL_THROUGH; @@ -10168,7 +10176,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->expected, &pkiMsg, idx)) != 0) { return ret; } - encryptedKeySz = pkcs7->stream->expected; + encryptedKeySz = (int)pkcs7->stream->expected; #endif /* Always allocate to ensure aligned use with RSA */ @@ -10239,12 +10247,12 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, if (encOID != RSAESOAEPk) { #endif keySz = wc_RsaPrivateDecryptInline(encryptedKey, - encryptedKeySz, &outKey, + (word32)encryptedKeySz, &outKey, privKey); #ifndef WC_NO_RSA_OAEP } else { - word32 outLen = wc_RsaEncryptSize(privKey); + word32 outLen = (word32)wc_RsaEncryptSize(privKey); outKey = (byte*)XMALLOC(outLen, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (!outKey) { @@ -10261,14 +10269,14 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, } keySz = wc_RsaPrivateDecrypt_ex(encryptedKey, - encryptedKeySz, outKey, outLen, privKey, + (word32)encryptedKeySz, outKey, outLen, privKey, WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA, WC_MGF1SHA1, NULL, 0); } #endif } #ifdef WOLFSSL_ASYNC_CRYPT - } while (keySz == WC_PENDING_E); + } while (keySz == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif #ifdef WC_RSA_BLINDING wc_FreeRng(&rng); @@ -10279,7 +10287,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, wc_FreeRsaKey(privKey); if (keySz <= 0 || outKey == NULL) { - ForceZero(encryptedKey, encryptedKeySz); + ForceZero(encryptedKey, (word32)encryptedKeySz); XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT); #ifdef WOLFSSL_SMALL_STACK XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -10293,9 +10301,9 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, #endif return keySz; } else { - *decryptedKeySz = keySz; + *decryptedKeySz = (word32)keySz; XMEMCPY(decryptedKey, outKey, keySz); - ForceZero(encryptedKey, encryptedKeySz); + ForceZero(encryptedKey, (word32)encryptedKeySz); } XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_WOLF_BIGINT); @@ -10470,7 +10478,7 @@ static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, } (*idx) += length; - kari->ukmSz = length; + kari->ukmSz = (word32)length; return 0; } @@ -10603,7 +10611,7 @@ static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari, if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - if (GetNameHash_ex(pkiMsg, idx, rid, pkiMsgSz, + if (GetNameHash_ex(pkiMsg, idx, rid, (int)pkiMsgSz, kari->decoded->signatureOID) < 0) { return ASN_PARSE_E; } @@ -10994,14 +11002,14 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return ASN_PARSE_E; } - blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); + blockSz = wc_PKCS7_GetOIDBlockSize((int)pwriEncAlgoId); if (blockSz < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return blockSz; } /* get content-encryption key size, based on algorithm */ - kekKeySz = wc_PKCS7_GetOIDKeySize(pwriEncAlgoId); + kekKeySz = wc_PKCS7_GetOIDKeySize((int)pwriEncAlgoId); if (kekKeySz < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return kekKeySz; @@ -11049,7 +11057,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, } /* allocate temporary space for decrypted key */ - cekSz = length; + cekSz = (word32)length; cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (cek == NULL) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -11065,8 +11073,8 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, } ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, - salt, saltSz, kdfAlgoId, hashOID, - iterations, kek, kekKeySz); + salt, (word32)saltSz, kdfAlgoId, hashOID, + iterations, kek, (word32)kekKeySz); if (ret < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -11075,17 +11083,17 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, } /* decrypt CEK with KEK */ - ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, kekKeySz, - pkiMsg + (*idx), length, cek, - cekSz, tmpIv, blockSz, - pwriEncAlgoId); + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, (word32)kekKeySz, + pkiMsg + (*idx), (word32)length, cek, + cekSz, tmpIv, (word32)blockSz, + (int)pwriEncAlgoId); if (ret < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } - cekSz = ret; + cekSz = (word32)ret; if (*decryptedKeySz < cekSz) { WOLFSSL_MSG("Decrypted key buffer too small for CEK"); @@ -11158,7 +11166,7 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - kekIdSz = length; + kekIdSz = (word32)length; if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -11171,14 +11179,14 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, /* save keyIdentifier and length */ keyId = pkiMsg + *idx; - keyIdSz = length; + keyIdSz = (word32)length; *idx += keyIdSz; /* may have OPTIONAL GeneralizedTime */ localIdx = *idx; if ((*idx < kekIdSz) && GetASNTag(pkiMsg, &localIdx, &tag, pkiMsgSz) == 0 && tag == ASN_GENERALIZED_TIME) { - if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, + if (wc_GetDateInfo(pkiMsg + *idx, (int)pkiMsgSz, &datePtr, &dateFormat, &dateLen) != 0) { return ASN_PARSE_E; } @@ -11227,15 +11235,15 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, /* decrypt CEK with KEK */ if (pkcs7->wrapCEKCb) { - keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, length, keyId, + keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, (word32)length, keyId, keyIdSz, NULL, 0, decryptedKey, - *decryptedKeySz, keyWrapOID, + *decryptedKeySz, (int)keyWrapOID, (int)PKCS7_KEKRI, direction); } else { - keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, + keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, (word32)length, pkcs7->privateKey, pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, - keyWrapOID, direction); + (int)keyWrapOID, direction); } if (keySz <= 0) return keySz; @@ -11378,7 +11386,7 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, /* if user has not explicitly set keyAgreeOID, set from one in bundle */ if (pkcs7->keyAgreeOID == 0) - pkcs7->keyAgreeOID = keyAgreeOID; + pkcs7->keyAgreeOID = (int)keyAgreeOID; /* set direction based on key wrap algorithm */ switch (keyWrapOID) { @@ -11430,7 +11438,7 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_x963(kari->senderKey, NULL, &tmpKeySz); PRIVATE_KEY_LOCK(); - if (ret != LENGTH_ONLY_E) { + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { return ret; } @@ -11456,10 +11464,10 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, } tmpKeySz = (word32)ret; - keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, encryptedKeySz, - rid, keyIdSize, tmpKeyDer, tmpKeySz, + keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, (word32)encryptedKeySz, + rid, (word32)keyIdSize, tmpKeyDer, tmpKeySz, decryptedKey, *decryptedKeySz, - keyWrapOID, (int)PKCS7_KARI, direction); + (int)keyWrapOID, (int)PKCS7_KARI, direction); XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (keySz > 0) { @@ -11472,7 +11480,7 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, } else { /* create KEK */ - ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, keyWrapOID, + ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, (int)keyWrapOID, pkcs7->keyAgreeOID); if (ret != 0) { wc_PKCS7_KariFree(kari); @@ -11483,9 +11491,9 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, } /* decrypt CEK with KEK */ - keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, + keySz = wc_PKCS7_KeyWrap(encryptedKey, (word32)encryptedKeySz, kari->kek, kari->kekSz, decryptedKey, *decryptedKeySz, - keyWrapOID, direction); + (int)keyWrapOID, direction); } if (keySz <= 0) { wc_PKCS7_KariFree(kari); @@ -11857,7 +11865,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, len = 0; ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); - if (ret != LENGTH_ONLY_E) + if (ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) return ret; pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (pkcs7->der == NULL) @@ -11960,7 +11968,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, break; } - pkcs7->stream->varOne = version; + pkcs7->stream->varOne = (word32)version; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END); FALL_THROUGH; @@ -11972,7 +11980,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz; - version = pkcs7->stream->varOne; + version = (int)pkcs7->stream->varOne; #endif if (type == ENVELOPED_DATA) { @@ -12220,7 +12228,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } if (ret == 0) { - pkcs7->contentOID = contentType; + pkcs7->contentOID = (int)contentType; } if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, @@ -12228,12 +12236,12 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, ret = ASN_PARSE_E; } - blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + blockKeySz = wc_PKCS7_GetOIDKeySize((int)encOID); if (ret == 0 && blockKeySz < 0) { ret = blockKeySz; } - expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID); if (ret == 0 && expBlockSz < 0) { ret = expBlockSz; } @@ -12264,8 +12272,8 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, break; } wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length); - pkcs7->stream->contentSz = blockKeySz; - pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ + + pkcs7->stream->contentSz = (word32)blockKeySz; + pkcs7->stream->expected = (word32)length + MAX_LENGTH_SZ + MAX_LENGTH_SZ + ASN_TAG_SZ + ASN_TAG_SZ; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4); @@ -12320,7 +12328,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; } - pkcs7->stream->expected = encryptedContentTotalSz; + pkcs7->stream->expected = (word32)encryptedContentTotalSz; wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0); wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, explicitOctet); #endif @@ -12337,12 +12345,12 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &explicitOctet); tmpIv = pkcs7->stream->tmpIv; - encryptedContentTotalSz = pkcs7->stream->expected; + encryptedContentTotalSz = (int)pkcs7->stream->expected; /* restore decrypted key */ decryptedKey = pkcs7->stream->aad; decryptedKeySz = pkcs7->stream->aadSz; - blockKeySz = pkcs7->stream->contentSz; + blockKeySz = (int)pkcs7->stream->contentSz; #else ret = 0; #endif @@ -12369,7 +12377,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, if (ret == 0) { ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx], - encryptedContentSz); + (word32)encryptedContentSz); } if (ret != 0) { @@ -12387,7 +12395,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } else { /* cache encrypted content, no OCTET STRING */ ret = PKCS7_CacheEncryptedContent(pkcs7, &pkiMsg[idx], - encryptedContentTotalSz); + (word32)encryptedContentTotalSz); if (ret != 0) { break; } @@ -12396,10 +12404,10 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, /* use cached content */ encryptedContent = pkcs7->cachedEncryptedContent; - encryptedContentSz = pkcs7->cachedEncryptedContentSz; + encryptedContentSz = (int)pkcs7->cachedEncryptedContentSz; /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, + ret = wc_PKCS7_DecryptContent(pkcs7, (int)encOID, decryptedKey, blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, encryptedContent, encryptedContentSz, encryptedContent, pkcs7->devId, pkcs7->heap); @@ -12442,7 +12450,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } #ifndef NO_PKCS7_STREAM - if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { + if (ret < 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { wc_PKCS7_ResetStream(pkcs7); wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); if (pkcs7->cachedEncryptedContent != NULL) { @@ -12594,7 +12602,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, verSz = SetMyVersion(0, ver, 0); /* generate random content encryption key */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, (word32)blockKeySz); if (ret != 0) { return ret; } @@ -12637,7 +12645,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, WOLFSSL_MSG("You must add at least one CMS recipient"); return PKCS7_RECIP_E; } - recipSetSz = SetSet(recipSz, recipSet); + recipSetSz = (int)SetSet((word32)recipSz, recipSet); /* generate random nonce and IV for encryption */ switch (pkcs7->encryptOID) { @@ -12709,7 +12717,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, sizeof(contentTypeValue)); if (ret > 0) { contentTypeAttrib.value = contentTypeValue; - contentTypeAttrib.valueSz = ret; + contentTypeAttrib.valueSz = (word32)ret; /* otherwise, try to set from custom content type */ } else { @@ -12747,7 +12755,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, } ret = FlattenAttributes(pkcs7, flatAuthAttribs, authAttribs, - authAttribsCount); + (int)authAttribsCount); if (ret != 0) { wc_PKCS7_FreeEncodedRecipientSet(pkcs7); XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -12799,7 +12807,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, } FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs, - unauthAttribsCount); + (int)unauthAttribsCount); unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz, unauthAttribSet, 0); } @@ -12807,7 +12815,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, /* AES-GCM/CCM does NOT require padding for plaintext content or * AAD inputs RFC 5084 section 3.1 and 3.2, but we must alloc * full blocks to ensure crypto only gets full blocks */ - encryptedOutSz = pkcs7->contentSz; + encryptedOutSz = (int)pkcs7->contentSz; encryptedAllocSz = (encryptedOutSz % blockSz) ? encryptedOutSz + blockSz - (encryptedOutSz % blockSz) : @@ -12885,10 +12893,10 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, contentTypeSz = ret; /* put together nonce OCTET STRING */ - nonceOctetStringSz = SetOctetString(nonceSz, nonceOctetString); + nonceOctetStringSz = (int)SetOctetString(nonceSz, nonceOctetString); /* put together aes-ICVlen INTEGER */ - macIntSz = SetMyVersion(sizeof(authTag), macInt, 0); + macIntSz = (word32)SetMyVersion(sizeof(authTag), macInt, 0); /* add nonce and icv len into parameters string RFC5084 */ algoParamSeqSz = SetSequence(nonceOctetStringSz + nonceSz + macIntSz, @@ -12897,7 +12905,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, /* build up our ContentEncryptionAlgorithmIdentifier sequence, * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING * and tag size */ - contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + contentEncAlgoSz = (int)SetAlgoID(pkcs7->encryptOID, contentEncAlgo, oidBlkType, nonceOctetStringSz + nonceSz + macIntSz + algoParamSeqSz); @@ -12911,14 +12919,14 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, return BAD_FUNC_ARG; } - encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctetSz = (int)SetImplicit(ASN_OCTET_STRING, 0, (word32)encryptedOutSz, encContentOctet, 0); - encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + encContentSeqSz = (int)SetSequence(contentTypeSz + contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz + algoParamSeqSz + encContentOctetSz + encryptedOutSz, encContentSeq); - macOctetStringSz = SetOctetString(sizeof(authTag), macOctetString); + macOctetStringSz = (int)SetOctetString(sizeof(authTag), macOctetString); /* keep track of sizes for outer wrapper layering */ totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + @@ -12928,16 +12936,16 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, sizeof(authTag) + unauthAttribsSz + unauthAttribsSetSz; /* EnvelopedData */ - envDataSeqSz = SetSequence(totalSz, envDataSeq); + envDataSeqSz = (int)SetSequence((word32)totalSz, envDataSeq); totalSz += envDataSeqSz; /* outer content */ - outerContentSz = SetExplicit(0, totalSz, outerContent, 0); + outerContentSz = (int)SetExplicit(0, (word32)totalSz, outerContent, 0); totalSz += outerContentTypeSz; totalSz += outerContentSz; /* ContentInfo */ - contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + contentInfoSeqSz = (int)SetSequence((word32)totalSz, contentInfoSeq); totalSz += contentInfoSeqSz; if (totalSz > (int)outputSz) { @@ -13183,7 +13191,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } if (ret == 0) { - pkcs7->contentOID = contentType; + pkcs7->contentOID = (int)contentType; } if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, @@ -13192,14 +13200,14 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } if (ret == 0) { - blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + blockKeySz = wc_PKCS7_GetOIDKeySize((int)encOID); if (blockKeySz < 0) { ret = blockKeySz; } } if (ret == 0) { - expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID); if (expBlockSz < 0) { ret = expBlockSz; } @@ -13315,7 +13323,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, /* store nonce for later */ if (nonceSz > 0) { - pkcs7->stream->nonceSz = nonceSz; + pkcs7->stream->nonceSz = (word32)nonceSz; pkcs7->stream->nonce = (byte*)XMALLOC(nonceSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (pkcs7->stream->nonce == NULL) { @@ -13327,7 +13335,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } } - pkcs7->stream->expected = encryptedContentSz; + pkcs7->stream->expected = (word32)encryptedContentSz; wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, encryptedContentSz); #endif @@ -13344,7 +13352,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz; - encryptedContentSz = pkcs7->stream->expected; + encryptedContentSz = (int)pkcs7->stream->expected; #else pkiMsgSz = inSz; #endif @@ -13356,7 +13364,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (encOID == 0) expBlockSz = 1; else { - expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID); if (expBlockSz < 0) { ret = expBlockSz; break; @@ -13397,7 +13405,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) <= 0) ret = ASN_PARSE_E; #ifndef NO_PKCS7_STREAM - pkcs7->stream->expected = length; + pkcs7->stream->expected = (word32)length; #endif encodedAttribSz = length + (idx - encodedAttribIdx); @@ -13442,7 +13450,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - length = pkcs7->stream->expected; + length = (int)pkcs7->stream->expected; encodedAttribs = pkcs7->stream->aad; #endif @@ -13530,7 +13538,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, /* store tag for later */ if (authTagSz > 0) { - pkcs7->stream->tagSz = authTagSz; + pkcs7->stream->tagSz = (word32)authTagSz; pkcs7->stream->tag = (byte*)XMALLOC(authTagSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (pkcs7->stream->tag == NULL) { @@ -13555,7 +13563,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, /* restore all variables needed */ if (pkcs7->stream->nonceSz > 0) { - nonceSz = pkcs7->stream->nonceSz; + nonceSz = (int)pkcs7->stream->nonceSz; if (nonceSz > GCM_NONCE_MID_SZ) { WOLFSSL_MSG("PKCS7 saved nonce is too large"); ret = BUFFER_E; @@ -13567,7 +13575,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } if (pkcs7->stream->tagSz > 0) { - authTagSz = pkcs7->stream->tagSz; + authTagSz = (int)pkcs7->stream->tagSz; if (authTagSz > AES_BLOCK_SIZE) { WOLFSSL_MSG("PKCS7 saved tag is too large"); ret = BUFFER_E; @@ -13592,9 +13600,9 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, #endif /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, + ret = wc_PKCS7_DecryptContent(pkcs7, (int)encOID, decryptedKey, blockKeySz, nonce, nonceSz, encodedAttribs, encodedAttribSz, - authTag, authTagSz, encryptedContent, encryptedContentSz, + authTag, (word32)authTagSz, encryptedContent, encryptedContentSz, encryptedContent, pkcs7->devId, pkcs7->heap); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -13610,7 +13618,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, XMEMCPY(output, encryptedContent, encryptedContentSz); /* free memory, zero out keys */ - ForceZero(encryptedContent, encryptedContentSz); + ForceZero(encryptedContent, (word32)encryptedContentSz); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); #ifdef WOLFSSL_SMALL_STACK @@ -13632,7 +13640,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } #ifdef WOLFSSL_SMALL_STACK - if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { if (decryptedKey != NULL) { ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); } @@ -13640,7 +13648,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } #endif #ifndef NO_PKCS7_STREAM - if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + if (ret != 0 && ret != WC_NO_ERR_TRACE(WC_PKCS7_WANT_READ_E)) { wc_PKCS7_ResetStream(pkcs7); } #endif @@ -13739,7 +13747,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (blockSz < 0) return blockSz; - padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, (word32)blockSz); if (padSz < 0) return padSz; @@ -13751,7 +13759,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) return MEMORY_E; ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, - encryptedOutSz, blockSz); + (word32)encryptedOutSz, blockSz); if (ret < 0) { XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; @@ -13765,11 +13773,11 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* put together IV OCTET STRING */ - ivOctetStringSz = SetOctetString(blockSz, ivOctetString); + ivOctetStringSz = (int)SetOctetString((word32)blockSz, ivOctetString); /* build up ContentEncryptionAlgorithmIdentifier sequence, adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ - contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + contentEncAlgoSz = (int)SetAlgoID(pkcs7->encryptOID, contentEncAlgo, oidBlkType, ivOctetStringSz + blockSz); if (contentEncAlgoSz == 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -13779,7 +13787,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* encrypt content */ WOLFSSL_MSG("Encrypting the content"); - ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, blockSz); + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, (word32)blockSz); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -13795,10 +13803,10 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) return ret; } - encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, - encryptedOutSz, encContentOctet, 0); + encContentOctetSz = (int)SetImplicit(ASN_OCTET_STRING, 0, + (word32)encryptedOutSz, encContentOctet, 0); - encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + encContentSeqSz = (int)SetSequence(contentTypeSz + contentEncAlgoSz + ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz, encContentSeq); @@ -13834,7 +13842,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) return MEMORY_E; } - ret = FlattenAttributes(pkcs7, flatAttribs, attribs, attribsCount); + ret = FlattenAttributes(pkcs7, flatAttribs, attribs, (int)attribsCount); if (ret != 0) { XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -13855,16 +13863,16 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) attribsSz + attribsSetSz; /* EncryptedData */ - encDataSeqSz = SetSequence(totalSz, encDataSeq); + encDataSeqSz = (int)SetSequence((word32)totalSz, encDataSeq); totalSz += encDataSeqSz; if (pkcs7->version != 3) { /* outer content */ - outerContentSz = SetExplicit(0, totalSz, outerContent, 0); + outerContentSz = (int)SetExplicit(0, (word32)totalSz, outerContent, 0); totalSz += outerContentTypeSz; totalSz += outerContentSz; /* ContentInfo */ - contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + contentInfoSeqSz = (int)SetSequence((word32)totalSz, contentInfoSeq); totalSz += contentInfoSeqSz; } else { contentInfoSeqSz = 0; @@ -14101,27 +14109,27 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, ret = ASN_PARSE_E; if (ret == 0) { - pkcs7->contentOID = contentType; + pkcs7->contentOID = (int)contentType; } if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz)) < 0) ret = ASN_PARSE_E; - if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0) + if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize((int)encOID)) < 0) ret = expBlockSz; if (ret != 0) break; #ifndef NO_PKCS7_STREAM /* store expBlockSz for later */ - pkcs7->stream->varOne = expBlockSz; - pkcs7->stream->varTwo = encOID; + pkcs7->stream->varOne = (word32)expBlockSz; + pkcs7->stream->varTwo = (int)encOID; if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; } /* store version for later */ - pkcs7->stream->vers = version; + pkcs7->stream->vers = (word32)version; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4); FALL_THROUGH; @@ -14137,7 +14145,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz; /* restore saved variables */ - expBlockSz = pkcs7->stream->varOne; + expBlockSz = (int)pkcs7->stream->varOne; #endif if (ret == 0 && GetASNTag(pkiMsg, &idx, &tag, pkiMsgSz) < 0) ret = ASN_PARSE_E; @@ -14155,7 +14163,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, if (ret != 0) break; #ifndef NO_PKCS7_STREAM /* next chunk of data expected should have the IV */ - pkcs7->stream->expected = length; + pkcs7->stream->expected = (word32)length; if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; @@ -14176,7 +14184,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, /* use IV buffer from stream structure */ tmpIv = pkcs7->stream->tmpIv; - length = pkcs7->stream->expected; + length = (int)pkcs7->stream->expected; #endif XMEMCPY(tmpIv, &pkiMsg[idx], length); idx += length; @@ -14221,10 +14229,10 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length: inSz; /* restore saved variables */ - expBlockSz = pkcs7->stream->varOne; - encOID = pkcs7->stream->varTwo; + expBlockSz = (int)pkcs7->stream->varOne; + encOID = (word32)pkcs7->stream->varTwo; encryptedContentSz = pkcs7->stream->varThree; - version = pkcs7->stream->vers; + version = (int)pkcs7->stream->vers; tmpIv = pkcs7->stream->tmpIv; #endif if (ret == 0 && (encryptedContent = (byte*)XMALLOC( @@ -14238,7 +14246,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, idx += encryptedContentSz; /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(pkcs7, encOID, + ret = wc_PKCS7_DecryptContent(pkcs7, (int)encOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, encryptedContent, encryptedContentSz, encryptedContent, @@ -14275,7 +14283,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, pkiMsgSz, &idx); if (ret != 0) { - ForceZero(encryptedContent, encryptedContentSz); + ForceZero(encryptedContent, (word32)encryptedContentSz); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); ret = ASN_PARSE_E; } @@ -14283,7 +14291,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } if (ret == 0) { - ForceZero(encryptedContent, encryptedContentSz); + ForceZero(encryptedContent, (word32)encryptedContentSz); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); /* go back and check the version now that attribs have been processed */ diff --git a/src/wolfcrypt/src/poly1305.c b/src/wolfcrypt/src/poly1305.c index f56b3fd..cde7547 100644 --- a/src/wolfcrypt/src/poly1305.c +++ b/src/wolfcrypt/src/poly1305.c @@ -55,7 +55,7 @@ and Daniel J. Bernstein #pragma warning(disable: 4127) #endif -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP #include #include @@ -70,6 +70,10 @@ and Daniel J. Bernstein #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) #undef NO_AVX2_SUPPORT #endif + #if defined(_MSC_VER) && (_MSC_VER <= 1900) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif #define HAVE_INTEL_AVX1 #ifndef NO_AVX2_SUPPORT @@ -77,13 +81,12 @@ and Daniel J. Bernstein #endif #endif -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP static word32 intel_flags = 0; static word32 cpu_flags_set = 0; #endif -#if (defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP)) || \ - defined(POLY130564) +#if defined(USE_INTEL_POLY1305_SPEEDUP) || defined(POLY130564) #if defined(_MSC_VER) #define POLY1305_NOINLINE __declspec(noinline) #elif defined(__GNUC__) @@ -123,7 +126,7 @@ static word32 cpu_flags_set = 0; #endif #endif -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP #ifdef __cplusplus extern "C" { #endif @@ -266,7 +269,7 @@ with a given ctx pointer to a Poly1305 structure. static int poly1305_blocks(Poly1305* ctx, const unsigned char *m, size_t bytes) { -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP /* AVX2 is handled in wc_Poly1305Update. */ SAVE_VECTOR_REGISTERS(return _svr_ret;); poly1305_blocks_avx(ctx, m, bytes); @@ -400,7 +403,7 @@ number of bytes is less than the block size. */ static int poly1305_block(Poly1305* ctx, const unsigned char *m) { -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP /* No call to poly1305_block when AVX2, AVX2 does 4 blocks at a time. */ SAVE_VECTOR_REGISTERS(return _svr_ret;); poly1305_block_avx(ctx, m); @@ -415,8 +418,7 @@ static int poly1305_block(Poly1305* ctx, const unsigned char *m) #if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) { -#if defined(POLY130564) && \ - !(defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP)) +#if defined(POLY130564) && !defined(USE_INTEL_POLY1305_SPEEDUP) word64 t0,t1; #endif @@ -437,7 +439,7 @@ int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) if (keySz != 32 || ctx == NULL) return BAD_FUNC_ARG; -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP if (!cpu_flags_set) { intel_flags = cpuid_get_flags(); cpu_flags_set = 1; @@ -504,7 +506,7 @@ int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) int wc_Poly1305Final(Poly1305* ctx, byte* mac) { -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP #elif defined(POLY130564) word64 h0,h1,h2,c; @@ -523,7 +525,7 @@ int wc_Poly1305Final(Poly1305* ctx, byte* mac) if (ctx == NULL || mac == NULL) return BAD_FUNC_ARG; -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP SAVE_VECTOR_REGISTERS(return _svr_ret;); #ifdef HAVE_INTEL_AVX2 if (IS_INTEL_AVX2(intel_flags)) @@ -709,7 +711,7 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) printf("\n"); #endif -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP #ifdef HAVE_INTEL_AVX2 if (IS_INTEL_AVX2(intel_flags)) { SAVE_VECTOR_REGISTERS(return _svr_ret;); diff --git a/src/wolfcrypt/src/port/Espressif/esp32_aes.c b/src/wolfcrypt/src/port/Espressif/esp32_aes.c index 84211ee..e8c917c 100644 --- a/src/wolfcrypt/src/port/Espressif/esp32_aes.c +++ b/src/wolfcrypt/src/port/Espressif/esp32_aes.c @@ -1,6 +1,6 @@ /* esp32_aes.c * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -48,6 +48,9 @@ static const char* TAG = "wolf_hw_aes"; /* mutex */ static wolfSSL_Mutex aes_mutex; +/* Maximum time to wait for AES HW in FreeRTOS ticks */ +#define WOLFSSL_AES_MUTEX_WAIT 5000 + /* keep track as to whether esp aes is initialized */ static int espaes_CryptHwMutexInit = 0; @@ -86,7 +89,13 @@ static int esp_aes_hw_InUse(void) * of esp_CryptHwMutexLock(&aes_mutex ...) in code */ /* TODO - do we really want to wait? * probably not */ - ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY); + ret = esp_CryptHwMutexLock(&aes_mutex, WOLFSSL_AES_MUTEX_WAIT); + if (ret == ESP_OK) { + ESP_LOGV(TAG, "esp_CryptHwMutexLock aes success"); + } + else { + ESP_LOGW(TAG, "esp_CryptHwMutexLock aes timeout! %d", ret); + } } else { ESP_LOGE(TAG, "aes engine lock failed."); @@ -597,9 +606,9 @@ int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) offset += AES_BLOCK_SIZE; } /* while (blocks--) */ + esp_aes_hw_Leave(); } /* if Set Mode was successful (ret == ESP_OK) */ - esp_aes_hw_Leave(); ESP_LOGV(TAG, "leave wc_esp32AesCbcDecrypt"); return ret; } /* wc_esp32AesCbcDecrypt */ diff --git a/src/wolfcrypt/src/port/Espressif/esp32_mp.c b/src/wolfcrypt/src/port/Espressif/esp32_mp.c index 1afda2b..5c37592 100644 --- a/src/wolfcrypt/src/port/Espressif/esp32_mp.c +++ b/src/wolfcrypt/src/port/Espressif/esp32_mp.c @@ -1,6 +1,6 @@ /* esp32_mp.c * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -23,15 +23,15 @@ * See ESP32 Technical Reference Manual - RSA Accelerator Chapter * * esp_mp_exptmod() Large Number Modular Exponentiation Z = X^Y mod M - * esp_mp_mulmod() Large Number Modular Multiplication Z = X × Y mod M - * esp_mp_mul() Large Number Multiplication Z = X × Y + * esp_mp_mulmod() Large Number Modular Multiplication Z = X * Y mod M + * esp_mp_mul() Large Number Multiplication Z = X * Y * * The ESP32 RSA Accelerator supports operand lengths of: - * N ∈ {512, 1024, 1536, 2048, 2560, 3072, 3584, 4096} bits. The bit length + * N in {512, 1024, 1536, 2048, 2560, 3072, 3584, 4096} bits. The bit length * of arguments Z, X, Y , M, and r can be any one from the N set, but all * numbers in a calculation must be of the same length. * - * The bit length of M′ is always 32. + * The bit length of M' is always 32. * * Also, beware: "we have uint32_t == unsigned long for both Xtensa and RISC-V" * see https://github.com/espressif/esp-idf/issues/9511#issuecomment-1207342464 @@ -413,7 +413,7 @@ static int esp_mp_hw_lock(void) { /* Note these names are different from those in the documentation! * - * Documenation lists the same names as the ESP32-C3: + * Documentation lists the same names as the ESP32-C3: * * DPORT_REG_SET_BIT((volatile void *)(SYSTEM_PERIP_CLK_EN1_REG), * SYSTEM_CRYPTO_RSA_CLK_EN ); @@ -1285,8 +1285,8 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) Zs = Xs + Ys; /* RSA Accelerator only supports Large Number Multiplication - * with operand length N = 32 × x, - * where x ∈ {1, 2, 3, . . . , 64} */ + * with operand length N = 32 * x, + * where x in {1, 2, 3, . . . , 64} */ if (Xs > 64 || Ys > 64) { return MP_HW_FALLBACK; /* TODO add count metric on size fallback */ } @@ -1334,7 +1334,7 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) /* Y (left-extend) * Accelerator supports large-number multiplication with only - * four operand lengths of N ∈ {512, 1024, 1536, 2048} */ + * four operand lengths of N in {512, 1024, 1536, 2048} */ left_pad_offset = maxWords_sz << 2; if (left_pad_offset <= 512 >> 3) { left_pad_offset = 512 >> 3; /* 64 bytes (16 words) */ @@ -1583,10 +1583,10 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) * 0 => no interrupt; 1 => interrupt on completion. */ DPORT_REG_WRITE(RSA_INT_ENA_REG, 0); /* 2. Write number of words required for result. */ - /* see 21.3.3 Write (/N16 − 1) to the RSA_MODE_REG register */ + /* see 21.3.3 Write (/N16 - 1) to the RSA_MODE_REG register */ DPORT_REG_WRITE(RSA_MODE_REG, (hwWords_sz * 2 - 1)); - /* 3. Write Xi and Yi for ∈ {0, 1, . . . , n − 1} to memory blocks + /* 3. Write Xi and Yi for {0, 1, . . . , n - 1} to memory blocks * RSA_X_MEM and RSA_Z_MEM * Maximum is 64 words (64*8*4 = 2048 bits) */ esp_mpint_to_memblock(RSA_X_MEM, @@ -1796,7 +1796,7 @@ int esp_mp_mul(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* Z) * * See 24.3.3 of the ESP32 Technical Reference Manual * - * Z = X × Y mod M */ + * Z = X * Y mod M */ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) { struct esp_mp_helper mph[1]; /* we'll save some values in this mp helper */ @@ -1839,8 +1839,12 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) /* do we have an even moduli? */ if ((M->dp[0] & 1) == 0) { #ifndef NO_ESP_MP_MUL_EVEN_ALT_CALC - /* Z = X × Y mod M in mixed HW & SW*/ + /* Z = X * Y mod M in mixed HW & SW */ + #if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL) + ret = mp_mul(X, Y, tmpZ); /* SW X * Y */ + #else ret = esp_mp_mul(X, Y, tmpZ); /* HW X * Y */ + #endif if (ret == MP_OKAY) { /* z = tmpZ mod M, 0 <= Z < M */ ret = mp_mod(tmpZ, M, Z); /* SW mod M */ @@ -1940,7 +1944,6 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) /* lock HW for use, enable peripheral clock */ if (ret == MP_OKAY) { - mulmod_lock_called = TRUE; /* Don't try to unlock unless we locked */ #ifdef WOLFSSL_HW_METRICS { /* Only track max values when using HW */ @@ -1954,6 +1957,12 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) #endif ret = esp_mp_hw_lock(); + if (ret == ESP_OK) { + mulmod_lock_called = TRUE; /* Don't try to unlock unless locked */ + } + else { + ret = WC_HW_WAIT_E; + } } #if defined(CONFIG_IDF_TARGET_ESP32) @@ -1973,13 +1982,13 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) * or until the RSA_INTR interrupt is generated. * (Or until the INTER interrupt is generated.) * 6. Write 1 to RSA_INTERRUPT_REG to clear the interrupt. - * 7. Write Yi (i ∈ [0, n) ∩ N) to RSA_X_MEM + * 7. Write Yi (i in [0, n) intersect N) to RSA_X_MEM * Users need to write to the memory block only according to the length * of the number. Data beyond this length is ignored. * 8. Write 1 to RSA_MULT_START_REG * 9. Wait for the second operation to be completed. * Poll INTERRUPT_REG until it reads 1. - * 10. Read the Zi (i ∈ [0, n) ∩ N) from RSA_Z_MEM + * 10. Read the Zi (i in [0, n) intersect N) from RSA_Z_MEM * 11. Write 1 to RSA_INTERUPT_REG to clear the interrupt. * * post: Release the HW engine @@ -2441,14 +2450,14 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) esp_mp_mulmod_usage_ct); ESP_LOGI(TAG, "esp_mp_mulmod_error_ct = %lu failures", esp_mp_mulmod_error_ct); - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); esp_show_mp("HW Z", Z); /* this is the HW result */ esp_show_mp("SW Z2", Z2); /* this is the SW result */ ESP_LOGI(TAG, "esp_mp_mulmod_usage_ct = %lu tries", esp_mp_mulmod_usage_ct); ESP_LOGI(TAG, "esp_mp_mulmod_error_ct = %lu failures", esp_mp_mulmod_error_ct); - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); #ifndef NO_RECOVER_SOFTWARE_CALC @@ -2500,15 +2509,15 @@ int esp_mp_mulmod(MATH_INT_T* X, MATH_INT_T* Y, MATH_INT_T* M, MATH_INT_T* Z) * ESP32S3, Section 20.3.1, https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf * * The operation is based on Montgomery multiplication. Aside from the - * arguments X, Y , and M, two additional ones are needed —r and M′ + * arguments X, Y , and M, two additional ones are needed -r and M' .* These arguments are calculated in advance by software. .* -.* The RSA Accelerator supports operand lengths of N ∈ {512, 1024, 1536, 2048, -.* 2560, 3072, 3584, 4096} bits on the ESP32 and N ∈ [32, 4096] bits +.* The RSA Accelerator supports operand lengths of N in {512, 1024, 1536, 2048, +.* 2560, 3072, 3584, 4096} bits on the ESP32 and N in [32, 4096] bits * on the ESP32s3. .* The bit length of arguments Z, X, Y , M, and r can be any one from * the N set, but all numbers in a calculation must be of the same length. -.* The bit length of M′ is always 32. +.* The bit length of M' is always 32. .* * Z = (X ^ Y) mod M : Espressif generic notation * Y = (G ^ X) mod P : wolfSSL DH reference notation */ @@ -2991,7 +3000,7 @@ int esp_hw_show_mp_metrics(void) "NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL"); #else /* Metrics: esp_mp_mul() */ - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); /* mul follows */ + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); /* mul follows */ ESP_LOGI(TAG, "esp_mp_mul HW acceleration enabled."); ESP_LOGI(TAG, "Number of calls to esp_mp_mul: %lu", esp_mp_mul_usage_ct); @@ -3010,7 +3019,7 @@ int esp_hw_show_mp_metrics(void) "NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD"); #else /* Metrics: esp_mp_mulmod() */ - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); /* mulmod follows */ + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); /* mulmod follows */ ESP_LOGI(TAG, "esp_mp_mulmod HW acceleration enabled."); /* Metrics: esp_mp_mulmod() */ @@ -3052,7 +3061,7 @@ int esp_hw_show_mp_metrics(void) "NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD"); #else /* Metrics: sp_mp_exptmod() */ - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); /* exptmod follows */ + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); /* exptmod follows */ ESP_LOGI(TAG, "Number of calls to esp_mp_exptmod: %lu", esp_mp_exptmod_usage_ct); diff --git a/src/wolfcrypt/src/port/Espressif/esp32_sha.c b/src/wolfcrypt/src/port/Espressif/esp32_sha.c index 332c532..bef77b0 100644 --- a/src/wolfcrypt/src/port/Espressif/esp32_sha.c +++ b/src/wolfcrypt/src/port/Espressif/esp32_sha.c @@ -1,6 +1,6 @@ /* esp32_sha.c * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -43,9 +43,6 @@ #if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WC_SHA384) || \ defined(WC_SHA512) -#include "wolfssl/wolfcrypt/logging.h" - - /* this entire file content is excluded if not using HW hash acceleration */ #if defined(WOLFSSL_ESP32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) @@ -58,9 +55,16 @@ #include #include +#elif defined(CONFIG_IDF_TARGET_ESP32) || \ + defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + #include #else #include /* ESP32-WROOM */ #endif + +/* wolfSSL */ +#include #include #include #include @@ -75,13 +79,18 @@ #include #endif +/* A value for an initialized, but not-yet-known SHA: */ +#define WC_UNKNOWN_SHA (-1) + +#define WC_ESP_MAX_IDLE_WAIT 10000 + static const char* TAG = "wolf_hw_sha"; #if defined(CONFIG_IDF_TARGET_ESP32C2) || \ defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) - /* keep track of the currently active SHA hash object for interleaving */ + /* Keep track of the currently active SHA hash object for interleaving. */ const static word32 ** _active_digest_address = 0; #endif @@ -90,7 +99,7 @@ static const char* TAG = "wolf_hw_sha"; #endif #if defined(DEBUG_WOLFSSL) - /* Only when debugging, we'll keep tracking of block numbers. */ + /* Only when debugging, we'll keep tracking of SHA block numbers. */ static int this_block_num = 0; #endif @@ -102,9 +111,12 @@ static const char* TAG = "wolf_hw_sha"; #endif #ifdef WOLFSSL_DEBUG_MUTEX - #ifndef WOLFSSL_TEST_STRAY + #ifdef WOLFSSL_TEST_STRAY + #define WOLFSSL_TEST_STRAY_INJECT (esp_sha_call_count() == 10) + #else /* unless turned on, we won't be testing for strays */ #define WOLFSSL_TEST_STRAY 0 + #define WOLFSSL_TEST_STRAY_INJECT 0 #endif #endif @@ -122,13 +134,32 @@ static const char* TAG = "wolf_hw_sha"; static unsigned long esp_byte_reversal_needed_ct = 0; #endif + static uintptr_t mutex_ctx_owner = NULLPTR; + static portMUX_TYPE sha_crit_sect = portMUX_INITIALIZER_UNLOCKED; + #if defined(ESP_MONITOR_HW_TASK_LOCK) - static void * mutex_ctx_owner = 0; - static TaskHandle_t mutex_ctx_task = 0; + #ifdef SINGLE_THREADED + uintptr_t esp_sha_mutex_ctx_owner(void) + { + return mutex_ctx_owner; + } + #else + static TaskHandle_t mutex_ctx_task = NULL; + uintptr_t esp_sha_mutex_ctx_owner(void) + { + uintptr_t ret = 0; + taskENTER_CRITICAL(&sha_crit_sect); + { + ret = mutex_ctx_owner; + } + taskEXIT_CRITICAL(&sha_crit_sect); + return ret; + }; + #endif + #ifdef WOLFSSL_DEBUG_MUTEX - static portMUX_TYPE sha_crit_sect = portMUX_INITIALIZER_UNLOCKED; WC_ESP32SHA* stray_ctx; - /* each ctx keeps track of the intializer for HW. when debugging + /* each ctx keeps track of the initializer for HW. when debugging * we'll have a global variable to indicate which has the lock. */ static int _sha_lock_count = 0; static int _sha_call_count = 0; @@ -143,40 +174,50 @@ static const char* TAG = "wolf_hw_sha"; return _sha_lock_count; } - void* esp_sha_mutex_ctx_owner(void) - { - void* ret = 0; - taskENTER_CRITICAL(&sha_crit_sect); - { - ret = mutex_ctx_owner; - } - taskEXIT_CRITICAL(&sha_crit_sect); - return ret; - }; - #else - int esp_sha_mutex_ctx_owner(void) - { - return (int)sha_mutex; - } #endif #endif +/* esp_set_hw - set hardware lock, but only if there's no other known + * current mutex owner. */ +int esp_set_hw(WC_ESP32SHA* ctx) +{ + int ret = ESP_FAIL; + if ((uintptr_t)ctx == mutex_ctx_owner || mutex_ctx_owner == NULLPTR) { + ESP_LOGV(TAG, "Initializing current mutext owner!"); + if (esp_sha_hw_islocked(ctx)) { + ESP_LOGV(TAG, "esp_set_hw already locked: 0x%x", (intptr_t)ctx); + } + ctx->mode = ESP32_SHA_HW; + mutex_ctx_owner = (uintptr_t)ctx; + ret = ESP_OK; + } + else { + ESP_LOGV(TAG, "esp_sha_init_ctx HW for non-owner 0x%x", (intptr_t)ctx); + } + return ret; +} + /* ** The wolfCrypt functions for LITTLE_ENDIAN_ORDER typically ** reverse the byte order. Except when the hardware doesn't expect it. ** +** For SoC devices with no HW (Hardware Acceleration) support: +** ctx->sha_type will be SHA_INVALID +** ctx->mode will be ESP32_SHA_SW +** ** Returns 0 (FALSE) or 1 (TRUE); see wolfSSL types.h */ int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx) { - int ret = TRUE; /* assume we'll need reversal, look for exceptions */ + int ret = 1; /* Assume we'll need reversal, look for exceptions. */ + CTX_STACK_CHECK(ctx); #if defined(CONFIG_IDF_TARGET_ESP32C2) || \ defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) if (ctx == NULL) { ESP_LOGE(TAG, " ctx is null"); - /* return true for bad params */ + /* Return true for bad params */ } else { #ifdef WOLFSSL_HW_METRICS @@ -186,12 +227,12 @@ int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx) #endif if (ctx->mode == ESP32_SHA_HW) { ESP_LOGV(TAG, " No reversal, ESP32_SHA_HW"); - ret = FALSE; + ret = 0; } else { - ret = TRUE; + ret = 1; ESP_LOGV(TAG, " Need byte reversal, %d", ctx->mode); - /* return true for SW; only HW C3 skips reversal at this time. */ + /* Return true for SW; only HW C3 skips reversal at this time. */ #ifdef WOLFSSL_HW_METRICS { esp_byte_reversal_needed_ct++; @@ -204,8 +245,10 @@ int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx) } } #else - /* other platforms always return true */ + /* Other platforms always return true. */ #endif + CTX_STACK_CHECK(ctx); + return ret; } @@ -218,20 +261,42 @@ int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx) ** Active HW states, such as from during a copy operation, are demoted to SW. ** For hash_type not available in HW, set SW mode. ** -** See esp_sha_init_ctx(ctx) +** For ctx, mode will be +** ESP32_SHA_INIT - For initialized, hardware-ready +** ESP32_SHA_SW - Software only +** +** See esp_sha_init_ctx(ctx) for common initialization of ctx. */ int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) { - int ret = 0; + int ret = ESP_OK; + +#ifdef DEBUG_WOLFSSL_SHA_MUTEX + ESP_LOGV(TAG, "\n\nesp_sha_init for ctx %p\n\n", ctx); +#endif + + if (ctx == NULL) { + return ESP_FAIL; + } + +#if defined(WOLFSSL_STACK_CHECK) + ctx->first_word = 0; + ctx->last_word = 0; +#endif + CTX_STACK_CHECK(ctx); + + ret = esp_sha_init_ctx(ctx); -#if defined(CONFIG_IDF_TARGET_ESP32) || \ - defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) +#if defined(CONFIG_IDF_TARGET_ESP32) || \ + defined(CONFIG_IDF_TARGET_ESP32S2) || \ + defined(CONFIG_IDF_TARGET_ESP32S3) + + /* ESP32 Xtensa Architecture SoC. Each has different features: */ switch (hash_type) { /* check each wolfSSL hash type WC_[n] */ #ifndef NO_SHA case WC_HASH_TYPE_SHA: ctx->sha_type = SHA1; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; #endif @@ -239,7 +304,6 @@ int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ defined(CONFIG_IDF_TARGET_ESP32S3) ctx->sha_type = SHA2_224; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); #else /* Don't call init, always SW as there's no HW. */ ctx->mode = ESP32_SHA_SW; @@ -248,32 +312,27 @@ int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) case WC_HASH_TYPE_SHA256: ctx->sha_type = SHA2_256; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; #if defined(CONFIG_IDF_TARGET_ESP32S2) || \ defined(CONFIG_IDF_TARGET_ESP32S3) case WC_HASH_TYPE_SHA384: ctx->mode = ESP32_SHA_SW; - ctx->sha_type = SHA2_384; /* Espressif type, but we won't use HW */ break; #else case WC_HASH_TYPE_SHA384: ctx->sha_type = SHA2_384; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; #endif case WC_HASH_TYPE_SHA512: ctx->sha_type = SHA2_512; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; #ifndef WOLFSSL_NOSHA512_224 case WC_HASH_TYPE_SHA512_224: /* Don't call init, always SW as there's no HW. */ ctx->mode = ESP32_SHA_SW; - ctx->sha_type = SHA2_512; /* Espressif type, but we won't use HW */ break; #endif @@ -281,245 +340,84 @@ int esp_sha_init(WC_ESP32SHA* ctx, enum wc_HashType hash_type) case WC_HASH_TYPE_SHA512_256: /* Don't call init, always SW as there's no HW. */ ctx->mode = ESP32_SHA_SW; - ctx->sha_type = SHA2_512; /* Espressif type, but we won't use HW */ break; #endif default: - ret = esp_sha_init_ctx(ctx); - ESP_LOGW(TAG, "Unexpected hash_type in esp_sha_init"); - break; + ctx->mode = ESP32_SHA_SW; + ESP_LOGW(TAG, "Unexpected hash_type in esp_sha_init"); + break; } #elif defined(CONFIG_IDF_TARGET_ESP32C2) || \ defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) + + /* ESP32 RISC-V Architecture SoC. Each has different features: */ + switch (hash_type) { /* check each wolfSSL hash type WC_[n] */ - #ifndef NO_SHA + #ifndef NO_SHA case WC_HASH_TYPE_SHA: ctx->sha_type = SHA1; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; - #endif + #endif case WC_HASH_TYPE_SHA224: ctx->sha_type = SHA2_224; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; case WC_HASH_TYPE_SHA256: ctx->sha_type = SHA2_256; /* assign Espressif SHA HW type */ - ret = esp_sha_init_ctx(ctx); break; default: /* We fall through to SW when there's no enabled HW, above. */ ctx->mode = ESP32_SHA_SW; - ret = 0; - /* If there's no HW, the ctx reference should cause build error. - ** The type should be gated away when there's no HW at all! */ - ctx->isfirstblock = true; - ctx->sha_type = hash_type; ESP_LOGW(TAG, "Unsupported hash_type = %d in esp_sha_init, " "falling back to SW", hash_type); break; } #else - /* other chipsets will be implemented here */ + /* Other chipsets will be implemented here, fallback to SW for now: */ ESP_LOGW(TAG, "SW Fallback; CONFIG_IDF_TARGET = %s", CONFIG_IDF_TARGET); ctx->mode = ESP32_SHA_SW; -#endif /* CONFIG_IDF_TARGET_ESP32 || - * CONFIG_IDF_TARGET_ESP32S2 || - * CONFIG_IDF_TARGET_ESP32S3 */ +#endif /* CONFIG_IDF_TARGET_[nnn] */ + CTX_STACK_CHECK(ctx); return ret; } -/* we'll call a separate init as there's only 1 HW acceleration */ +/* we'll call a common init for non-chip-specific settings */ int esp_sha_init_ctx(WC_ESP32SHA* ctx) { - if (ctx->initializer == NULL) { - ESP_LOGV(TAG, "regular init of blank WC_ESP32SHA ctx"); + CTX_STACK_CHECK(ctx); - /* we'll keep track of who initialized this */ - ctx->initializer = ctx; /* save our address in the initializer */ - #ifdef ESP_MONITOR_HW_TASK_LOCK - { - /* Keep track of which freeRTOS task actually locks HW */ - ctx->task_owner = xTaskGetCurrentTaskHandle(); - } - #endif - ctx->mode = ESP32_SHA_INIT; - } - else { - /* things may be more interesting when previously initialized */ - if (ctx->initializer == ctx) { - /* We're likely re-using an existing object previously initialized. - ** There's of course a non-zero probability that garbage data is - ** the same pointer value, but that's highly unlikely; We'd need - ** to discard, then re-init to same memory location for a matching - ** initializer. */ - ESP_LOGV(TAG, "re-using existing WC_ESP32SHA ctx"); - - /* we should never have an unexpected mode in a known ctx */ - switch (ctx->mode) { - case ESP32_SHA_FREED: - ESP_LOGW(TAG, "Warning: ESP32_SHA_FREED status"); + ctx->mode = ESP32_SHA_INIT; - #ifdef ESP_MONITOR_HW_TASK_LOCK - if (ctx->task_owner == xTaskGetCurrentTaskHandle()) { - esp_sha_hw_unlock(ctx); - } - else { - ESP_LOGW(TAG, "Warning: unable to unlock ctx mutex "); - } - #else - esp_sha_hw_unlock(ctx); - #endif - ctx->mode = ESP32_SHA_INIT; - /* fall through to init */ - - case ESP32_SHA_INIT: - case ESP32_SHA_SW: - /* nothing interesting here */ - break; - - case ESP32_SHA_HW: - /* This will be dealt with below: likely demote to SW */ - break; - - case ESP32_SHA_HW_COPY: - /* This is an interesting mode, caller gave HW mode hint */ - ESP_LOGI(TAG, "ALERT: ESP32_SHA_HW_COPY?"); - break; - - default: - /* This should almost never occur. We'd need to have an - ** uninitialized ctx that just happens to include the - ** breadcrumb initializer with the same address. */ - ESP_LOGW(TAG, "ALERT: unexpected WC_ESP32SHA ctx mode: " - "%d. ", ctx->mode); - ctx->mode = ESP32_SHA_INIT; - break; - } - /* We don't need to do anything here, - ** this section for diagnostics only. - ** May need to unlock HW, below. */ - } /* ctx->initializer == ctx */ - else { - /* We may end up here with either dirty memory - ** or copied SHA ctx. - ** - ** Any copy function should have already set mode = ESP32_SHA_INIT. - ** - ** In either case, initialize: */ - ctx->initializer = ctx; /* set a new address */ - #ifdef ESP_MONITOR_HW_TASK_LOCK - { - /* not HW mode, so we are not interested in task owner */ - ctx->task_owner = 0; - } - #endif - - /* Always set to ESP32_SHA_INIT, but give debug info as to why: */ - switch (ctx->mode) { - case ESP32_SHA_FREED: - ESP_LOGE(TAG, "ERROR: unexpected ESP32_SHA_FREED"); - ctx->mode = ESP32_SHA_INIT; - break; - - case ESP32_SHA_INIT: - /* if we are already in init mode, nothing to do. */ - break; - - case ESP32_SHA_SW: - /* this should rarely, if ever occur */ - ESP_LOGW(TAG, "ALERT: unexpected SW WC_ESP32SHA ctx mode. " - "Copied? Revert to ESP32_SHA_INIT."); - ctx->mode = ESP32_SHA_INIT; - break; - - case ESP32_SHA_HW: - /* this should rarely, if ever occur. */ - ESP_LOGW(TAG, "ALERT: unexpected HW WC_ESP32SHA ctx mode. " - "Copied?"); - ctx->mode = ESP32_SHA_INIT; - break; - - case ESP32_SHA_HW_COPY: - /* This is an interesting but acceptable situation: - ** an anticipated active HW copy that will demote to SW. */ - ESP_LOGV(TAG, "HW WC_ESP32SHA ctx mode = " - "ESP32_SHA_HW_COPY."); - break; - - default: - /* this will frequently occur during new init */ - ESP_LOGV(TAG, "ALERT: unexpected WC_ESP32SHA ctx mode. " - "Uninitialized?"); - ctx->mode = ESP32_SHA_INIT; - break; - } /* switch */ - } /* ctx->initializer != ctx */ - } /* ctx->initializer != NULL */ - - /* - ** After possibly changing the mode (above) handle current mode: - */ - switch (ctx->mode) { - case ESP32_SHA_INIT: - /* Likely a fresh, new SHA, as desired. */ - ESP_LOGV(TAG, "Normal ESP32_SHA_INIT"); - break; + /* This is a generic init; we don't yet know SHA type. */ + ctx->sha_type = WC_UNKNOWN_SHA; - case ESP32_SHA_HW: - /* We're already in hardware mode, so release. */ - /* Interesting, but normal. */ - ESP_LOGV(TAG, ">> HW unlock."); + /* Reminder: always start isfirstblock = 1 (true) when using HW engine. */ + /* We're always on the first block at init time. (not zero-based!) */ + ctx->isfirstblock = 1; + ctx->lockDepth = 0; /* new objects will always start with lock depth = 0 */ - /* During init is the ONLY TIME we call unlock. - ** If there's a problem, likely some undesired operation - ** outside of wolfSSL. - */ - /* TODO debug check if HW actually locked; */ +#if defined(MUTEX_DURING_INIT) + if ((uintptr_t)ctx == mutex_ctx_owner || mutex_ctx_owner == NULLPTR) { + ESP_LOGV(TAG, "Initializing current mutext owner!"); + if (esp_sha_hw_islocked(ctx)) { esp_sha_hw_unlock(ctx); - ctx->mode = ESP32_SHA_INIT; - break; - - case ESP32_SHA_HW_COPY: - /* When we init during a known active HW copy, revert to SW. */ - ESP_LOGV(TAG, "Planned revert to SW during copy."); - ctx->mode = ESP32_SHA_SW; - break; - - case ESP32_SHA_SW: - /* This is an interesting situation: likely a call when - ** another SHA in progress, but copied. */ - ESP_LOGV(TAG, ">> SW Set to init."); - ctx->mode = ESP32_SHA_INIT; - break; - - case ESP32_SHA_FAIL_NEED_UNROLL: - /* Oh, how did we get here? likely uninitialized SHA memory. - ** User code logic may need attention. */ - ESP_LOGW(TAG, "ALERT: \nESP32_SHA_FAIL_NEED_UNROLL\n"); - ctx->mode = ESP32_SHA_INIT; - break; - - default: - /* Most likely corrupted memory. */ - ESP_LOGW(TAG, "ALERT: \nunexpected mode value: " - "%d \n", ctx->mode); - ctx->mode = ESP32_SHA_INIT; - break; - } /* switch (ctx->mode) */ - - /* reminder: always start isfirstblock = 1 (true) when using HW engine */ - /* we're always on the first block at init time (not zero-based!) */ - ctx->isfirstblock = true; - ctx->lockDepth = 0; /* new objects will always start with lock depth = 0 */ + } + mutex_ctx_owner = (uintptr_t)ctx; + } + else { + ESP_LOGI(TAG, "MUTEX_DURING_INIT esp_sha_init_ctx for non-owner: " + "0x%x", (intptr_t)ctx); + } +#endif + CTX_STACK_CHECK(ctx); return ESP_OK; /* Always return success. * We assume all issues handled, above. */ } /* esp_sha_init_ctx */ @@ -542,17 +440,14 @@ int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) /* Get a copy of the HW digest, but don't process it. */ ret = esp_sha_digest_process(dst, 0); if (ret == 0) { - /* Note we arrived here only because - * the src is already in HW mode. - * provide init hint to SW revert: */ - dst->ctx.mode = ESP32_SHA_HW_COPY; - /* initializer will be set during init */ ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA); if (ret != 0) { ESP_LOGE(TAG, "Error during esp_sha_ctx_copy " "in esp_sha_init."); } + /* As src is HW, the copy will be SW. TODO: Future interleave. */ + dst->ctx.mode = ESP32_SHA_SW; } else { ESP_LOGE(TAG, "Error during esp_sha_ctx_copy " @@ -577,7 +472,7 @@ int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) else { /* However NOT reverting to SW is not right. ** This should never happen. */ - ESP_LOGW(TAG, "SHA Copy NOT set to SW"); + ESP_LOGW(TAG, "SHA Copy NOT set to SW from %d", dst->ctx.mode); } } /* (src->ctx.mode == ESP32_SHA_HW */ else { /* src not in HW mode, ok to copy. */ @@ -585,8 +480,8 @@ int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) ** reminder XMEMCOPY, above: dst->ctx = src->ctx; ** No special HW init needed in SW mode. ** but we need to set our initializer breadcrumb: */ - dst->ctx.initializer = &(dst->ctx); /* assign new breadcrumb to dst */ - #ifdef ESP_MONITOR_HW_TASK_LOCK + dst->ctx.initializer = (uintptr_t)&(dst->ctx); + #if defined(ESP_MONITOR_HW_TASK_LOCK) && !defined(SINGLE_THREADED) { /* not HW mode for copy, so we are not interested in task owner */ dst->ctx.task_owner = 0; @@ -600,18 +495,18 @@ int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst) } /* esp_sha_ctx_copy */ #endif - /* -** internal sha224 ctx copy (no ESP HW) +** Internal sha224 ctx copy (no ESP HW) */ #ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 int esp_sha224_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) { - /* There's no 224 hardware on ESP32 */ - dst->ctx.initializer = &dst->ctx; /* assign the initializer to dst */ - #ifdef ESP_MONITOR_HW_TASK_LOCK + /* There's no 224 hardware on ESP32. + * Initializer for dst is this ctx address for use as a breadcrumb. */ + dst->ctx.initializer = (uintptr_t)&dst->ctx; + #if defined(ESP_MONITOR_HW_TASK_LOCK) && !defined(SINGLE_THREADED) { - /* not HW mode for copy, so we are not interested in task owner */ + /* not HW mode for copy, so we are not interested in task owner: */ dst->ctx.task_owner = 0; } #endif @@ -635,14 +530,16 @@ int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) ESP_LOGI(TAG, "esp_sha256_ctx_copy esp_sha512_digest_process"); } #endif - ret = esp_sha256_digest_process(dst, 0); /* TODO Use FALSE*/ - - if (ret == 0) { - /* provide init hint to possibly SW revert */ - dst->ctx.mode = ESP32_SHA_HW_COPY; + ret = esp_sha256_digest_process(dst, FALSE); + if (ret == ESP_OK) { /* initializer breadcrumb will be set during init */ - ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA256 ); + ret = esp_sha_init(&(dst->ctx), WC_HASH_TYPE_SHA256); + /* As src is HW, the copy will be SW. TODO: Future interleave. */ + dst->ctx.mode = ESP32_SHA_SW; + } + else { + ESP_LOGE(TAG, "Unexpected error during sha256 ctx copy: %d", ret); } if (dst->ctx.mode == ESP32_SHA_SW) { @@ -660,17 +557,19 @@ int esp_sha256_ctx_copy(struct wc_Sha256* src, struct wc_Sha256* dst) ESP_LOGV(TAG, "Confirmed wc_Sha256 Copy set to SW"); } else { - ESP_LOGW(TAG, "wc_Sha256 Copy NOT set to SW"); + ESP_LOGW(TAG, "wc_Sha256 Copy (mode = %d) set to SW", + dst->ctx.mode); + dst->ctx.mode = ESP32_SHA_SW; } } /* (src->ctx.mode == ESP32_SHA_HW) */ else { - ret = 0; + ret = ESP_OK; /* ** reminder this happened in XMEMCOPY: dst->ctx = src->ctx; ** No special HW init needed in SW mode. - ** but we need to set our initializer: */ - dst->ctx.initializer = &dst->ctx; /* assign the initializer to dst */ - #ifdef ESP_MONITOR_HW_TASK_LOCK + ** but we need to set our initializer (helpful in multi-task RTOS) */ + dst->ctx.initializer = (uintptr_t)&(dst->ctx); + #if defined(ESP_MONITOR_HW_TASK_LOCK) && !defined(SINGLE_THREADED) { /* not HW mode, so we are not interested in task owner */ dst->ctx.task_owner = 0; @@ -705,7 +604,7 @@ int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) #else if (src->ctx.mode == ESP32_SHA_HW) { /* Get a copy of the HW digest, but don't process it. */ - ESP_LOGI(TAG, "esp_sha384_ctx_copy esp_sha512_digest_process"); + ESP_LOGV(TAG, "esp_sha384_ctx_copy esp_sha512_digest_process"); ret = esp_sha512_digest_process(dst, 0); if (ret == 0) { /* provide init hint to SW revert */ @@ -734,11 +633,11 @@ int esp_sha384_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) else { ret = 0; /* - ** reminder this happened in XMEMCOPY, above: dst->ctx = src->ctx; + ** Reminder this happened in XMEMCOPY, above: dst->ctx = src->ctx; ** No special HW init needed in SW mode. - ** but we need to set our initializer: */ - dst->ctx.initializer = &dst->ctx; /* assign the initializer to dst */ - #ifdef ESP_MONITOR_HW_TASK_LOCK + ** But we need to set our initializer in dst as a breadcrumb: */ + dst->ctx.initializer = (uintptr_t)&(dst->ctx); + #if defined(ESP_MONITOR_HW_TASK_LOCK) && !defined(SINGLE_THREADED) { /* not HW mode for copy, so we are not interested in task owner */ dst->ctx.task_owner = 0; @@ -766,16 +665,17 @@ int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) - /* there's no SHA512 HW on the RISC-V SoC so there's nothing to do. */ + /* There's no SHA512 HW on these RISC-V SoC so there's nothing to do. + * (perhaps a future one will?) */ #elif defined(CONFIG_IDF_TARGET_ESP32) || \ defined(CONFIG_IDF_TARGET_ESP32S2) || \ defined(CONFIG_IDF_TARGET_ESP32S3) if (src->ctx.mode == ESP32_SHA_HW) { /* Get a copy of the HW digest, but don't process it. */ - ESP_LOGI(TAG, "esp_sha512_ctx_copy esp_sha512_digest_process"); - ret = esp_sha512_digest_process(dst, 0); + ESP_LOGV(TAG, "esp_sha512_ctx_copy esp_sha512_digest_process"); + ret = esp_sha512_digest_process(dst, FALSE); - if (ret == 0) { + if (ret == ESP_OK) { /* provide init hint to SW revert */ dst->ctx.mode = ESP32_SHA_HW_COPY; @@ -789,27 +689,27 @@ int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) ESP_LOGV(TAG, "Confirmed wc_Sha512 Copy set to SW"); } else { - ESP_LOGW(TAG, "wc_Sha512 Copy NOT set to SW"); + ESP_LOGW(TAG, "wc_Sha512 Copy set to SW"); + dst->ctx.mode = ESP32_SHA_SW; } } /* src->ctx.mode == ESP32_SHA_HW */ else { - ret = 0; + ret = ESP_OK; /* reminder this happened in XMEMCOPY, above: dst->ctx = src->ctx; ** No special HW init needed when not in active HW mode. ** but we need to set our initializer breadcrumb: */ - /* TODO: instead of what is NOT supported, gate on what IS known to be supported */ #if !defined(CONFIG_IDF_TARGET_ESP32C2) && \ !defined(CONFIG_IDF_TARGET_ESP32C3) && \ !defined(CONFIG_IDF_TARGET_ESP32C6) - dst->ctx.initializer = &dst->ctx; /*breadcrumb is this ctx address */ + dst->ctx.initializer = (uintptr_t)&(dst->ctx); #endif - #ifdef ESP_MONITOR_HW_TASK_LOCK + #if defined(ESP_MONITOR_HW_TASK_LOCK) && !defined(SINGLE_THREADED) { /* not HW mode for copy, so we are not interested in task owner */ dst->ctx.task_owner = 0; } - #endif - } + #endif + } /* else src->ctx.mode != ESP32_SHA_HW */ #endif return ret; @@ -821,14 +721,14 @@ int esp_sha512_ctx_copy(struct wc_Sha512* src, struct wc_Sha512* dst) ** ** See FIPS PUB 180-4, Instruction Section 1. ** -** See ESP32 shah.h for values: +** See ESP32 sha.h for values: ** ** enum SHA_TYPE { ** SHA1 = 0, ** SHA2_256, ** SHA2_384, ** SHA2_512, -** SHA_INVALID = -1, +** SHA_TYPE_MAX = -1, ** }; ** ** given the SHA_TYPE (see Espressif sha.h) return WC digest size. @@ -917,14 +817,14 @@ static word32 wc_esp_sha_digest_size(WC_ESP_SHA_TYPE type) static int wc_esp_wait_until_idle(void) { int ret = 0; /* assume success */ - int loop_ct = 10000; + int loop_ct = WC_ESP_MAX_IDLE_WAIT; #if defined(CONFIG_IDF_TARGET_ESP32C2) || \ defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) /* ESP32-C3 and ESP32-C6 RISC-V */ - while ((sha_ll_busy() == true) && (loop_ct > 0)) { + while ((sha_ll_busy() == 1) && (loop_ct > 0)) { loop_ct--; /* do nothing while waiting. */ } @@ -942,7 +842,7 @@ static int wc_esp_wait_until_idle(void) #endif if (loop_ct <= 0) { - ESP_LOGI(TAG, "too long to exit wc_esp_wait_until_idle"); + ESP_LOGW(TAG, "Too long to exit wc_esp_wait_until_idle"); } return ret; } /* wc_esp_wait_until_idle */ @@ -970,6 +870,7 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) #if defined(CONFIG_IDF_TARGET_ESP32) word32 this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */ #endif + CTX_STACK_CHECK(ctx); if (ctx == NULL) { ESP_LOGE(TAG, "esp_unroll_sha_module_enable called with null ctx."); @@ -1006,7 +907,7 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) periph_module_disable(PERIPH_SHA_MODULE); asm volatile("memw"); actual_unroll_count++; - ESP_LOGI(TAG, "unroll not yet successful. try #%d", + ESP_LOGW(TAG, "unroll not yet successful. try #%d", actual_unroll_count); /* we'll only try this some unreasonable number of times @@ -1025,7 +926,11 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) ** This should never happen unless someone else called ** periph_module_disable() or threading not working properly. **/ - ESP_LOGW(TAG, "warning lockDepth mismatch."); + ESP_LOGW(TAG, "warning lockDepth mismatch: %d", ctx->lockDepth); + if (actual_unroll_count == 0 && ctx->lockDepth > 2) { + ESP_LOGW(TAG, "Large lockDepth discrepancy often indicates " + "stack overflow or memory corruption"); + } } ctx->lockDepth = 0; ctx->mode = ESP32_SHA_INIT; @@ -1039,16 +944,36 @@ int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx) ESP_LOGI(TAG, "Setting ctx->mode = ESP32_SHA_SW"); ctx->mode = ESP32_SHA_SW; } + CTX_STACK_CHECK(ctx); return ret; } /* esp_unroll_sha_module_enable */ -int esp_sha_set_stray(WC_ESP32SHA* ctx) +/* Set and return a stray ctx value stray_ctx. Useful for multi-task debugging. + * Returns zero if not debugging. */ +uintptr_t esp_sha_set_stray(WC_ESP32SHA* ctx) { - int ret = 0; + uintptr_t ret = 0; + CTX_STACK_CHECK(ctx); + #ifdef WOLFSSL_DEBUG_MUTEX stray_ctx = ctx; - ret= (int)stray_ctx; + ret = (uintptr_t)stray_ctx; #endif + CTX_STACK_CHECK(ctx); + return ret; +} + +/* Return 1 if the SHA HW is in use, 0 otherwise. */ +int esp_sha_hw_in_use() +{ + int ret; +#ifdef SINGLE_THREADED + ret = InUse; +#else + ret = (mutex_ctx_owner != NULLPTR); + ESP_LOGV(TAG, "mutex_ctx_owner is 0x%x", mutex_ctx_owner); +#endif + ESP_LOGV(TAG, "esp_sha_hw_in_use is %d", ret); return ret; } @@ -1058,18 +983,21 @@ int esp_sha_set_stray(WC_ESP32SHA* ctx) ** When WOLFSSL_DEBUG_MUTEX is defined, additional ** debugging capabilities are available. */ -int esp_sha_hw_islocked(WC_ESP32SHA* ctx) +uintptr_t esp_sha_hw_islocked(WC_ESP32SHA* ctx) { - int ret = 0; + TaskHandle_t mutexHolder; + uintptr_t ret = 0; + CTX_STACK_CHECK(ctx); + #ifdef WOLFSSL_DEBUG_MUTEX taskENTER_CRITICAL(&sha_crit_sect); { - ret = (int)mutex_ctx_owner; + ret = (uintptr_t)mutex_ctx_owner; if (ctx == 0) { /* we are not checking if a given ctx has the lock */ } else { - if (ret == (int)ctx->initializer) { + if (ret == (uintptr_t)ctx->initializer) { /* confirmed this object is the owner */ } else { @@ -1085,7 +1013,30 @@ int esp_sha_hw_islocked(WC_ESP32SHA* ctx) } #else { - ret = (int)sha_mutex; + if (sha_mutex == NULL) { + mutexHolder = NULL; + } + else { + mutexHolder = xSemaphoreGetMutexHolder(sha_mutex); + } + + if (mutexHolder == NULL) { + /* Mutex is not in use */ + ESP_LOGV(TAG, "multi-threaded esp_mp_hw_islocked = false"); + ret = 0; + } + else { + ESP_LOGV(TAG, "multi-threaded esp_mp_hw_islocked = true"); + ret = mutex_ctx_owner; + } + + /* Verbose debug diagnostics */ + if (NULLPTR == mutex_ctx_owner) { + ESP_LOGV(TAG, "not esp_sha_hw_islocked, mutex_ctx_owner is Null"); + } + else { + ESP_LOGV(TAG, "esp_sha_hw_islocked for 0x%x", mutex_ctx_owner); + } } #endif return ret; @@ -1101,57 +1052,92 @@ int esp_sha_hw_islocked(WC_ESP32SHA* ctx) (int)esp_sha_mutex_ctx_owner()); } #endif + CTX_STACK_CHECK(ctx); return ret; } /* * The HW is typically unlocked when the SHA hash wc_Sha[nn]Final() is called. - * However, in the case of TS connections, the in progress hash may at times be + * However, in the case of TLS connections the in-progress hash may at times be * abandoned. Thus this function should be called at free time. See internal.c + * + * Returns the owner of the current lock, typically used for debugging. + * Returns zero if there was no unfinished lock found to clean up. */ -int esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx) +uintptr_t esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx) { - int ret = 0; + uintptr_t ret = 0; + CTX_STACK_CHECK(ctx); + ret = esp_sha_hw_islocked(ctx); /* get the owner of the current lock */ if (ret == 0) { - /* no lock */ + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGV(TAG, "No unfinished lock to clean up for ctx %p.", ctx); + #endif } else { - if (ret == (int)ctx) { + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + ESP_LOGI(TAG, "Unfinished lock clean up: %p.", ctx); + #endif + if (ret == (uintptr_t)ctx) { /* found a match for this object */ - if (ret == (int)(ctx->initializer)) { + if (ret == ctx->initializer) { /* confirmed match*/ + ESP_LOGW(TAG, "New mutex_ctx_owner = NULL"); + #ifdef ESP_MONITOR_HW_TASK_LOCK + { + mutex_ctx_owner = NULLPTR; + } + #endif } else { - /* the only mismatch expected may be in a mullti-thread RTOS */ - ESP_LOGE(TAG, "ERROR: esp_sha_release_unfinished_lock for %x" - " but found %x", ret, (int)(ctx->initializer)); + /* the only mismatch expected may be in a multi-thread RTOS */ + ESP_LOGE(TAG, "ERROR: Release unfinished lock for %x but " + "found %x", ret, ctx->initializer); } #ifdef WOLFSSL_DEBUG_MUTEX ESP_LOGE(TAG, "\n>>>> esp_sha_release_unfinished_lock %x\n", ret); #endif - /* unlock only if this ctx is the intializer of the lock */ + + /* unlock only if this ctx is the initializer of the lock */ #ifdef SINGLE_THREADED { ret = esp_sha_hw_unlock(ctx); } #else - { - if (ctx->task_owner == xTaskGetCurrentTaskHandle()) { - ret = esp_sha_hw_unlock(ctx); - } - else { - /* We cannot free a SHA onbject locks from a different task. - * So give the ctx a hint for the other task to clean it up. */ - ctx->mode = ESP32_SHA_FREED; + #if defined(ESP_MONITOR_HW_TASK_LOCK) + { + if (ctx->task_owner == xTaskGetCurrentTaskHandle()) { + ESP_LOGV(TAG, "esp_sha_hw_unlock!"); + } + else { + /* We cannot free a SHA object lock from a different task. + * So give the ctx a hint for other task to clean it up. */ + ctx->mode = ESP32_SHA_FREED; + ESP_LOGV(TAG, "ESP32_SHA_FREED"); + } } - } - #endif + #else + /* Here we assume only 1 task, so no ESP32_SHA_FREED hint. */ + ret = esp_sha_hw_unlock(ctx); + #endif /* ESP_MONITOR_HW_TASK_LOCK */ + #endif /* SINGLE_THREADED or not */ + + } /* ret == ctx */ + } /* else not locked */ + CTX_STACK_CHECK(ctx); + if (ctx->mode != ESP32_SHA_INIT) { +#if defined(WOLFSSL_ESP32_HW_LOCK_DEBUG) + ESP_LOGW(TAG, "esp_sha_release_unfinished_lock mode = %d", ctx->mode); +#endif + if (ctx->mode == ESP32_SHA_HW) { + ESP_LOGW(TAG, "esp_sha_release_unfinished_lock HW!"); } } return ret; -} +} /* esp_sha_release_unfinished_lock */ + /* ** lock HW engine. ** this should be called before using engine. @@ -1159,9 +1145,11 @@ int esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx) int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) { int ret = 0; + CTX_STACK_CHECK(ctx); #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG - ESP_LOGI(TAG, "enter esp_sha_hw_lock for %x", (int)ctx->initializer); + ESP_LOGI(TAG, "enter esp_sha_hw_lock for %x", + (uintptr_t)ctx->initializer); #endif #ifdef WOLFSSL_DEBUG_MUTEX @@ -1180,22 +1168,28 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) /* Init mutex * - * Note that even single thread mode may calculate hashes - * concurrently, so we still need to keep track of the - * engine being busy or not. - **/ + * Note that even single thread mode may calculate separate hashes + * concurrently, so we still need to keep track of the engine being + * busy or not. + */ #if defined(SINGLE_THREADED) if (ctx->mode == ESP32_SHA_INIT) { - if (!InUse) { - ctx->mode = ESP32_SHA_HW; - InUse = 1; + if (InUse) { + /* Revert to SW when HW is busy */ + ctx->mode = ESP32_SHA_SW; } else { - ctx->mode = ESP32_SHA_SW; + /* Set single-threaded hardware mode. */ + ctx->mode = ESP32_SHA_HW; + InUse = 1; + #ifdef WOLFSSL_DEBUG_MUTEX + ESP_LOGW(TAG, "\n\nHW in use\n\n"); + #endif } + ret = ESP_OK; } else { - /* this should not happens */ + /* this should not happen */ ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock."); return ESP_FAIL; } @@ -1223,21 +1217,36 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) /* created, but not yet locked */ ret = esp_CryptHwMutexInit(&sha_mutex); if (ret == 0) { - #ifdef WOLFSSL_DEBUG_MUTEX - ESP_LOGI(TAG, "esp_CryptHwMutexInit sha_mutex init success."); - mutex_ctx_owner = 0; - #endif - } + ESP_LOGV(TAG, "esp_CryptHwMutexInit sha_mutex init success."); + mutex_ctx_owner = NULLPTR; /* No one has the mutex yet.*/ + #ifdef WOLFSSL_DEBUG_MUTEX + { + /* Take mutex for lock/unlock test drive to ensure it works: */ + ret = esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0); + if (ret == ESP_OK) { + ret = esp_CryptHwMutexUnLock(&sha_mutex); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_CryptHwMutexInit fail init lock."); + } + } + else { + ESP_LOGE(TAG, "esp_CryptHwMutexInit fail init unlock."); + } + } + #endif + } /* ret == 0 for esp_CryptHwMutexInit */ else { ESP_LOGE(TAG, "esp_CryptHwMutexInit sha_mutex failed."); - sha_mutex = 0; + #ifdef WOLFSSL_DEBUG_MUTEX + { + ESP_LOGV(TAG, "Current mutext owner = %x", + (int)esp_sha_mutex_ctx_owner()); + } + #endif - ESP_LOGI(TAG, "Revert to ctx->mode = ESP32_SHA_SW."); + sha_mutex = NULL; - #ifdef WOLFSSL_DEBUG_MUTEX - ESP_LOGI(TAG, "Current mutext owner = %x", - (int)esp_sha_mutex_ctx_owner()); - #endif + ESP_LOGV(TAG, "Revert to ctx->mode = ESP32_SHA_SW."); ctx->mode = ESP32_SHA_SW; return ESP_OK; /* success, just not using HW */ @@ -1245,32 +1254,42 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) } #ifdef ESP_MONITOR_HW_TASK_LOCK + /* Nothing happening here other than messages based on mutex states */ if (mutex_ctx_task == 0 || mutex_ctx_owner == 0) { /* no known stray mutex task owner */ } else { if (mutex_ctx_task == xTaskGetCurrentTaskHandle()) { - ESP_LOGI(TAG, "Found mutex_ctx_task"); + ESP_LOGV(TAG, "Found mutex_ctx_task"); if (((WC_ESP32SHA*)mutex_ctx_owner)->mode == ESP32_SHA_FREED) { ESP_LOGW(TAG, "ESP32_SHA_FREED unlocking mutex_ctx_task = %x" " for mutex_ctx_owner = %x", - (int)mutex_ctx_task, (int)mutex_ctx_owner ); - esp_CryptHwMutexUnLock(&sha_mutex); - ((WC_ESP32SHA*)mutex_ctx_owner)->mode = ESP32_SHA_INIT; - mutex_ctx_task = 0; - mutex_ctx_owner = 0; + (int)mutex_ctx_task, + (int)mutex_ctx_owner); } else { if (ctx->mode == ESP32_SHA_FREED) { - ESP_LOGW(TAG, "ESP32_SHA_FREED unlocking ctx = %x" - " for ctx.initializer = %x", - (int)ctx, (int)ctx->initializer ); - esp_CryptHwMutexUnLock(&sha_mutex); - ctx->mode = ESP32_SHA_INIT; - mutex_ctx_task = 0; - mutex_ctx_owner = 0; + ESP_LOGW(TAG, "ESP32_SHA_FREED unlocking (disabled) " + "ctx = %x for ctx.initializer = %x", + (uintptr_t)ctx, + (uintptr_t)ctx->initializer); } - } + else { + /* Not very interesting during init. */ + if (ctx->mode == ESP32_SHA_INIT) { + ESP_LOGV(TAG, "mutex_ctx_owner = 0x%x", + mutex_ctx_owner); + ESP_LOGV(TAG, "This ctx = 0x%x is ESP32_SHA_INIT", + (uintptr_t)ctx); + } + else { + ESP_LOGW(TAG, "Not Freed!"); + } + } /* ctx ESP32_SHA_FREED check */ + } /* mutex owner ESP32_SHA_FREED check */ + } /* mutex_ctx_task is current task */ + else { + ESP_LOGW(TAG, "Warning: sha mutex unlock from unexpected task"); } } #endif /* ESP_MONITOR_HW_TASK_LOCK */ @@ -1279,8 +1298,12 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) if (ctx->mode == ESP32_SHA_INIT) { /* try to lock the HW engine */ #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG - ESP_LOGI(TAG, "ESP32_SHA_INIT for %x\n", (int)ctx->initializer); + ESP_LOGI(TAG, "ESP32_SHA_INIT for %x\n", (uintptr_t)ctx->initializer); #endif + ESP_LOGV(TAG, "Init; release unfinished ESP32_SHA_INIT lock " + "for ctx 0x%x", (uintptr_t)ctx); + esp_sha_release_unfinished_lock(ctx); + /* lock hardware; there should be exactly one instance * of esp_CryptHwMutexLock(&sha_mutex ...) in code. * @@ -1290,16 +1313,20 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) * TODO: allow for SHA interleave on chips that support it. */ - if (esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) { + if ((mutex_ctx_owner == NULLPTR) && + esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == ESP_OK) { /* we've successfully locked */ + mutex_ctx_owner = (uintptr_t)ctx; + ESP_LOGV(TAG, "Assigned mutex_ctx_owner to 0x%x", mutex_ctx_owner); #ifdef ESP_MONITOR_HW_TASK_LOCK mutex_ctx_task = xTaskGetCurrentTaskHandle(); #endif #ifdef WOLFSSL_DEBUG_MUTEX - if (esp_sha_call_count() == 8 && WOLFSSL_TEST_STRAY) { - /* Once we've locked 10 times here, - * we'll force a fallback to SW until other thread unlocks. */ + if (WOLFSSL_TEST_STRAY_INJECT) { + ESP_LOGW(TAG, "Introducing SHA stray for testing"); + /* Once we've locked [n] times here, + * we'll force a fallback to SW until other thread unlocks. */ taskENTER_CRITICAL(&sha_crit_sect); { (void)stray_ctx; @@ -1307,8 +1334,8 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) /* no peek task */ } else { - stray_ctx->initializer = stray_ctx; - mutex_ctx_owner = (void*)stray_ctx->initializer; + stray_ctx->initializer = (intptr_t)stray_ctx; + mutex_ctx_owner = (intptr_t)stray_ctx->initializer; } } taskEXIT_CRITICAL(&sha_crit_sect); @@ -1318,8 +1345,8 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) "set the stay test?"); } else { - ESP_LOGI(TAG, "%x", (int)stray_ctx->initializer); - ESP_LOGI(TAG, "%x", (int)&stray_ctx); + ESP_LOGI(TAG, "%x", (uintptr_t)stray_ctx->initializer); + ESP_LOGI(TAG, "%x", (uintptr_t)&stray_ctx); ESP_LOGW(TAG, "\n\nLocking with stray\n\n" "WOLFSSL_DEBUG_MUTEX call count 8, " @@ -1335,17 +1362,22 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) /* check to see if we had a prior fail and need to unroll enables */ #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG ESP_LOGW(TAG, "Locking for ctx %x, current mutex_ctx_owner = %x", - (int)&ctx, (int)esp_sha_mutex_ctx_owner()); + (uintptr_t)&ctx, esp_sha_mutex_ctx_owner()); + ESP_LOGI(TAG, "ctx->lockDepth = %d", ctx->lockDepth); #endif - ret = esp_unroll_sha_module_enable(ctx); + if (ctx->mode == ESP32_SHA_INIT) { + /* Set non-single-threaded hardware mode */ + esp_set_hw(ctx); + } + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG ESP_LOGI(TAG, "Hardware Mode Active, lock depth = %d, for %x", - ctx->lockDepth, (int)ctx->initializer); + ctx->lockDepth, (uintptr_t)ctx->initializer); #endif #ifdef WOLFSSL_DEBUG_MUTEX taskENTER_CRITICAL(&sha_crit_sect); { - mutex_ctx_owner = (void*)ctx->initializer; + mutex_ctx_owner = (uintptr_t)ctx->initializer; /* let's keep track of how many times we lock this */ _sha_lock_count++; } @@ -1357,23 +1389,42 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) ** as the mutex should be gate keeping */ ESP_LOGW(TAG, "WARNING: Hardware Mode " "interesting lock depth = %d, for this %x", - ctx->lockDepth, (int)ctx->initializer); + ctx->lockDepth, (uintptr_t)ctx->initializer); } } else { - /* We should have otherwise anticipated this; how did we get here? - ** This code should rarely, ideally never be reached. */ - #ifdef WOLFSSL_DEBUG_MUTEX - ESP_LOGI(TAG, "\nHardware in use by %x; " - "Mode REVERT to ESP32_SHA_SW for %x\n", - (int)esp_sha_mutex_ctx_owner(), - (int)ctx->initializer); - ESP_LOGI(TAG, "Software Mode, lock depth = %d, for this %x", - ctx->lockDepth, (int)ctx->initializer); - ESP_LOGI(TAG, "Current mutext owner = %x", - (int)esp_sha_mutex_ctx_owner()); - #endif - ctx->mode = ESP32_SHA_SW; + /* When the lock is already in use: is it for this ctx? */ + if ((uintptr_t)ctx == esp_sha_mutex_ctx_owner()) { + ESP_LOGV(TAG, "I'm the owner! 0x%x", (uintptr_t)ctx); + ctx->mode = ESP32_SHA_SW; + } + else { + #ifdef WOLFSSL_DEBUG_MUTEX + ESP_LOGW(TAG, "\nHardware in use by %x; " + "Mode REVERT to ESP32_SHA_SW for %x\n", + esp_sha_mutex_ctx_owner(), + (uintptr_t)ctx->initializer); + ESP_LOGI(TAG, "Software Mode, lock depth = %d, for this %x", + ctx->lockDepth, (uintptr_t)ctx->initializer); + ESP_LOGI(TAG, "Current mutext owner = %x", + esp_sha_mutex_ctx_owner()); + #endif + ESP_LOGV(TAG, "I'm not owner! 0x%x; owner = 0x%x", + (uintptr_t)ctx, mutex_ctx_owner); + if (mutex_ctx_owner) { + #ifdef WOLFSSL_DEBUG_MUTEX + ESP_LOGW(TAG, "revert to SW since mutex_ctx_owner = %x" + " but we are currently ctx = %x", + mutex_ctx_owner, (intptr_t)ctx); + #endif + } + else { + /* No ctx mutex owner, so hardware must be free. */ + } + ESP_LOGV(TAG, "Set update ctx->mode = SW (from %d) for 0x%x", + ctx->mode, (uintptr_t)ctx ); + ctx->mode = ESP32_SHA_SW; + } return ESP_OK; /* success, but revert to SW */ } } /* (ctx->mode == ESP32_SHA_INIT) */ @@ -1384,33 +1435,44 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) } #endif /* not defined(SINGLE_THREADED) */ -#if defined(CONFIG_IDF_TARGET_ESP32C2) || \ - defined(CONFIG_IDF_TARGET_ESP8684) || \ - defined(CONFIG_IDF_TARGET_ESP32C3) || \ - defined(CONFIG_IDF_TARGET_ESP32C6) - { - ESP_LOGV(TAG, "ets_sha_enable for RISC-V"); - ets_sha_enable(); - ctx->mode = ESP32_SHA_HW; - } -#else - if (ret == 0) { + ESP_LOGV(TAG, "ctx->mode = %d", ctx->mode); + if ((ret == ESP_OK) && (ctx->mode == ESP32_SHA_HW)) { ctx->lockDepth++; /* depth for THIS ctx (there could be others!) */ #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG { - printf("1) Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", - __LINE__, ctx->lockDepth, (unsigned)ctx); + ESP_LOGI(TAG, "1) Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", + __LINE__, ctx->lockDepth, (unsigned)ctx); } #endif - periph_module_enable(PERIPH_SHA_MODULE); - ctx->mode = ESP32_SHA_HW; + #if defined(CONFIG_IDF_TARGET_ESP32C2) || \ + defined(CONFIG_IDF_TARGET_ESP8684) || \ + defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + { + ESP_LOGV(TAG, "ets_sha_enable for RISC-V"); + ets_sha_enable(); + } + #else + ESP_LOGV(TAG, "ets_sha_enable for Xtensa"); + periph_module_enable(PERIPH_SHA_MODULE); + #endif } else { - ESP_LOGW(TAG, ">>>> Other problem; Mode REVERT to ESP32_SHA_SW"); + /* Set to SW */ + #ifdef WOLFSSL_ESP32_CRYPT_DEBUG + if (ret == ESP_OK) { + ESP_LOGW(TAG, "Normal SHA Software fallback mode."); + } + else { + ESP_LOGW(TAG, "Warning: Unexpected Mode REVERT to ESP32_SHA_SW" + ", err = %d", ret); + } + #endif ctx->mode = ESP32_SHA_SW; } -#endif + ESP_LOGV(TAG, "leave esp_sha_hw_lock"); + CTX_STACK_CHECK(ctx); return ret; } /* esp_sha_try_hw_lock */ @@ -1422,61 +1484,80 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx) int esp_sha_hw_unlock(WC_ESP32SHA* ctx) { int ret = ESP_OK; /* assume success (zero) */ + CTX_STACK_CHECK(ctx); #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG ESP_LOGV(TAG, "enter esp_sha_hw_unlock"); #endif -#if defined(CONFIG_IDF_TARGET_ESP32C2) || \ - defined(CONFIG_IDF_TARGET_ESP8684) || \ - defined(CONFIG_IDF_TARGET_ESP32C3) || \ - defined(CONFIG_IDF_TARGET_ESP32C6) - ets_sha_disable(); /* disable also resets active, ongoing hash */ - ESP_LOGV(TAG, "ets_sha_disable in esp_sha_hw_unlock()"); -#else - /* Disable AES hardware */ - periph_module_disable(PERIPH_SHA_MODULE); -#endif /* we'll keep track of our lock depth. * in case of unexpected results, all the periph_module_disable() calls * and periph_module_disable() need to be unwound. * * see ref_counts[periph] in file: periph_ctrl.c */ #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG - printf("2) esp_sha_hw_unlock Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", - __LINE__, ctx->lockDepth, (unsigned)ctx); + ESP_LOGI(TAG, "2) esp_sha_hw_unlock Lock depth @ %d = %d " + "for WC_ESP32SHA ctx @ %p\n", + __LINE__, ctx->lockDepth, ctx); #endif + + if (ctx->lockDepth > 0) { + #if defined(CONFIG_IDF_TARGET_ESP32C2) || \ + defined(CONFIG_IDF_TARGET_ESP8684) || \ + defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) + ets_sha_disable(); /* disable also resets active, ongoing hash */ + ESP_LOGV(TAG, "ets_sha_disable in esp_sha_hw_unlock()"); + #else + periph_module_disable(PERIPH_SHA_MODULE); + #endif ctx->lockDepth--; } else { + ESP_LOGW(TAG, "lockDepth <= 0; Disable SHA module skipped for %x", + (uintptr_t)ctx->initializer); ctx->lockDepth = 0; } #if defined(ESP_MONITOR_HW_TASK_LOCK) && defined(WOLFSSL_ESP32_HW_LOCK_DEBUG) - printf("3) esp_sha_hw_unlock Lock depth @ %d = %d for WC_ESP32SHA @ %0x\n", - __LINE__, ctx->lockDepth, (unsigned)ctx); + ESP_LOGI(TAG, "3) esp_sha_hw_unlock Lock depth @ %d = %d " + "for WC_ESP32SHA @ %0x\n", + __LINE__, ctx->lockDepth, (uintptr_t)ctx); #endif - if (0 == ctx->lockDepth) - { + + if (0 != ctx->lockDepth) { + /* If the lockdepth is not zero, unlock success unknown. */ + ESP_LOGE(TAG, "ERROR Non-zero lockDepth. Stray code lock?"); + ret = ESP_FAIL; + } + else { #if defined(SINGLE_THREADED) + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG + { + ESP_LOGW(TAG, "HW released, not in use."); + } + #endif InUse = 0; #else - /* unlock HW engine for next use */ + /* Hardware was unlocked above, now update semaphores. */ #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG { - ESP_LOGW(TAG, "Unlocking for %x, from ctx %x, & = %x, " - "mutex_ctx_owner = %x", - (int)esp_sha_mutex_ctx_owner(), - (int)ctx, - (int)&ctx, - (int)esp_sha_mutex_ctx_owner()); - ESP_LOGW(TAG, "&sha_mutex = %x", (int)&sha_mutex); + ESP_LOGW(TAG, "Unlocking for mutex_ctx_owner %x, from ctx 0x%x", + esp_sha_mutex_ctx_owner(), (uintptr_t)ctx); + ESP_LOGV(TAG, "&sha_mutex = %x", (intptr_t)&sha_mutex); } #endif /* WOLFSSL_ESP32_HW_LOCK_DEBUG */ + + /* There should be exactly 1 instance of SHA unlock, and it's here: */ esp_CryptHwMutexUnLock(&sha_mutex); + /* We don't set owner to zero here. The HW is not in use, + * but there may be a WIP hash calc (e.g. sha update). + * NO: mutex_ctx_owner = NULLPTR; */ + #ifdef ESP_MONITOR_HW_TASK_LOCK mutex_ctx_task = 0; #endif + #endif #ifdef WOLFSSL_DEBUG_MUTEX @@ -1487,14 +1568,12 @@ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) taskEXIT_CRITICAL(&sha_crit_sect); #endif } - else - { - ESP_LOGE(TAG, "ERROR unlock lockDepth not zero"); - ret = ESP_FAIL; - } + #ifdef WOLFSSL_ESP32_HW_LOCK_DEBUG - ESP_LOGI(TAG, "leave esp_sha_hw_unlock, %x", (int)ctx->initializer); + ESP_LOGI(TAG, "leave esp_sha_hw_unlock, %x", + (uintptr_t)ctx->initializer); #endif + CTX_STACK_CHECK(ctx); return ret; } /* esp_sha_hw_unlock */ @@ -1513,7 +1592,7 @@ int esp_sha_hw_unlock(WC_ESP32SHA* ctx) /* Everything else uses esp_sha_start_process() */ static int esp_sha_start_process(WC_ESP32SHA* sha) { - int ret = 0; + int ret = ESP_OK; #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) uint8_t HardwareAlgorithm; #endif @@ -1521,6 +1600,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) if (sha == NULL) { return BAD_FUNC_ARG; } + CTX_STACK_CHECK(sha); ESP_LOGV(TAG, " enter esp_sha_start_process"); @@ -1531,7 +1611,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) ESP_LOGV(TAG, "SHA1 SHA_START_REG"); if (sha->isfirstblock) { sha_ll_start_block(SHA2_256); - sha->isfirstblock = false; + sha->isfirstblock = 0; ESP_LOGV(TAG, " set sha->isfirstblock = 0"); @@ -1584,7 +1664,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) if (sha->isfirstblock) { REG_WRITE(SHA_START_REG, 1); - sha->isfirstblock = false; + sha->isfirstblock = 0; ESP_LOGV(TAG, " set sha->isfirstblock = 0"); @@ -1635,7 +1715,7 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) break; } - sha->isfirstblock = false; + sha->isfirstblock = 0; ESP_LOGV(TAG, " set sha->isfirstblock = 0"); #if defined(DEBUG_WOLFSSL) @@ -1687,9 +1767,10 @@ static int esp_sha_start_process(WC_ESP32SHA* sha) ESP_LOGV(TAG, " continue block #%d", this_block_num); #endif - ESP_LOGV(TAG, " leave esp_sha_start_process"); + ESP_LOGV(TAG, " leave esp_sha_start_process"); + CTX_STACK_CHECK(sha); - return ret; + return ret; } #endif /* esp_sha_start_process !CONFIG_IDF_TARGET_ESP32C3/C6 */ @@ -1705,12 +1786,22 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) word32* MessageSource; word32* AcceleratorMessage; + #define MAX_SHA_VALUE SHA_TYPE_MAX #elif CONFIG_IDF_TARGET_ESP32 int i; + /* Only values 0 .. 3 are valid for ESP32; SHA_INVALID = -1 */ + #define MAX_SHA_VALUE 4 #else - /* not used */ + /* Newer SoC devices have a different value: SHA_TYPE_MAX */ + #define MAX_SHA_VALUE SHA_TYPE_MAX #endif ESP_LOGV(TAG, " enter esp_process_block"); + + if ((ctx->sha_type < 0) || (ctx->sha_type > MAX_SHA_VALUE)) { + ESP_LOGE(TAG, "Unexpected sha_type: %d", ctx->sha_type); + } + CTX_STACK_CHECK(ctx); + if (word32_to_save > 0x31) { word32_to_save = 0x31; ESP_LOGE(TAG, " ERROR esp_process_block length exceeds 0x31 words."); @@ -1722,10 +1813,10 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ #if defined(CONFIG_IDF_TARGET_ESP32) /* load [len] words of message data into HW */ for (i = 0; i < word32_to_save; i++) { - /* by using DPORT_REG_WRITE, we avoid the need + /* By using DPORT_REG_WRITE, we avoid the need * to call __builtin_bswap32 to address endianness. * - * a useful watch array cast to watch at runtime: + * A useful watch array cast to watch at runtime: * ((word32[32]) (*(volatile word32 *)(SHA_TEXT_BASE))) * * Write value to DPORT register (does not require protecting) @@ -1733,7 +1824,7 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ DPORT_REG_WRITE(SHA_TEXT_BASE + (i*sizeof(word32)), *(data + i)); /* memw confirmed auto inserted by compiler here */ } - /* notify HW to start process + /* Notify HW to start process * see ctx->sha_type * reg data does not change until we are ready to read */ ret = esp_sha_start_process(ctx); @@ -1759,7 +1850,7 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ * ((word32[16]) (*(volatile uint32_t *)(SHA_TEXT_BASE))) */ if (&data != _active_digest_address) { - ESP_LOGV(TAG, "TODO Moving alternate ctx->for_digest"); + ESP_LOGV(TAG, "Moving alternate ctx->for_digest"); /* move last known digest into HW reg during interleave */ /* sha_ll_write_digest(ctx->sha_type, ctx->for_digest, WC_SHA256_BLOCK_SIZE); */ @@ -1838,6 +1929,7 @@ static int wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */ } #endif + CTX_STACK_CHECK(ctx); ESP_LOGV(TAG, " leave esp_process_block"); return ret; } /* wc_esp_process_block */ @@ -1857,6 +1949,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) #endif ESP_LOGV(TAG, "enter esp_digest_state"); + CTX_STACK_CHECK(ctx); if (ctx == NULL) { return BAD_FUNC_ARG; @@ -1871,7 +1964,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) defined(CONFIG_IDF_TARGET_ESP32S2) || \ defined(CONFIG_IDF_TARGET_ESP32S3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) - if (ctx->sha_type == SHA_TYPE_MAX) { + if (ctx->sha_type >= SHA_TYPE_MAX) { #else ESP_LOGE(TAG, "unexpected target for wc_esp_digest_state"); { @@ -1889,7 +1982,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) - if (ctx->isfirstblock == true) { + if (ctx->isfirstblock == 1) { /* no hardware use yet. Nothing to do yet */ return ESP_OK; } @@ -1937,7 +2030,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) wc_esp_sha_digest_size(ctx->sha_type) / sizeof(word32) ); #else - /* not CONFIG_IDF_TARGET_ESP32S3 */ + /* Not CONFIG_IDF_TARGET_ESP32S3 */ /* wait until idle */ wc_esp_wait_until_idle(); @@ -1946,9 +2039,11 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ defined(CONFIG_IDF_TARGET_ESP32C6) + #elif defined(CONFIG_IDF_TARGET_ESP32S2) - /* nothing here for S2 */ + #else + switch (ctx->sha_type) { case SHA1: DPORT_REG_WRITE(SHA_1_LOAD_REG, 1); @@ -1975,7 +2070,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) return ESP_FAIL; } - if (ctx->isfirstblock == true) { + if (ctx->isfirstblock == 1) { /* no hardware use yet. Nothing to do yet */ return ESP_OK; } @@ -1999,7 +2094,9 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) * example: * DPORT_SEQUENCE_REG_READ(address + i * 4); */ - + #ifdef WOLFSSL_ESP32_CRYPT_DEBUG + ESP_LOGW(TAG, "SHA HW read..."); + #endif esp_dport_access_read_buffer( #if ESP_IDF_VERSION_MAJOR >= 4 (uint32_t*)(hash), /* the result will be found in hash upon exit */ @@ -2024,6 +2121,7 @@ int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash) } #endif /* SHA512 or SHA384*/ #endif /* not CONFIG_IDF_TARGET_ESP32S3, C3, else... */ + CTX_STACK_CHECK(ctx); ESP_LOGV(TAG, "leave esp_digest_state"); return ESP_OK; @@ -2061,13 +2159,19 @@ int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess) ret = wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); + if (blockprocess) { + ESP_LOGV(TAG, "esp_sha_digest_process NEW UNLOCK"); + esp_sha_hw_unlock(&sha->ctx); /* also unlocks mutex */ + ESP_LOGV(TAG, "sha blockprocess mutex_ctx_owner = NULLPTR"); + mutex_ctx_owner = NULLPTR; + } + ESP_LOGV(TAG, "leave esp_sha_digest_process"); return ret; } /* esp_sha_digest_process */ #endif /* NO_SHA */ - #if !defined(NO_SHA256) && !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) /* ** sha256 process @@ -2078,8 +2182,6 @@ int esp_sha256_process(struct wc_Sha256* sha, const byte* data) { int ret = 0; - ESP_LOGV(TAG, " enter esp_sha256_process"); - switch ((&sha->ctx)->sha_type) { case SHA2_256: #if defined(DEBUG_WOLFSSL_VERBOSE) @@ -2131,6 +2233,13 @@ int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess) } wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); + + if (blockprocess) { + ESP_LOGV(TAG, "esp_sha256_digest_process blockprocess UNLOCK"); + esp_sha_hw_unlock(&sha->ctx); /* also unlocks mutex */ + ESP_LOGV(TAG, "blockprocess mutex_ctx_owner = NULLPTR"); + mutex_ctx_owner = NULLPTR; + } #else ESP_LOGE(TAG, "Call esp_sha256_digest_process with " "NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 "); @@ -2198,7 +2307,7 @@ int esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal) */ int esp_sha512_process(struct wc_Sha512* sha) { - int ret = 0; /* assume success */ + int ret = ESP_OK; /* assume success */ word32 *data = (word32*)sha->buffer; ESP_LOGV(TAG, "enter esp_sha512_process"); @@ -2230,6 +2339,7 @@ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc) ret = esp_sha512_block(sha, data, 1); } + if (sha->ctx.mode == ESP32_SHA_HW) { ret = wc_esp_digest_state(&sha->ctx, (byte*)sha->digest); } @@ -2237,6 +2347,12 @@ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc) ESP_LOGW(TAG, "Call esp_sha512_digest_process in non-HW mode?"); } + if (blockproc) { + ESP_LOGV(TAG, "esp_sha512_digest_process NEW UNLOCK"); + esp_sha_hw_unlock(&sha->ctx); /* also unlocks mutex */ + ESP_LOGV(TAG, "mutex_ctx_owner = NULLPTR"); + mutex_ctx_owner = NULLPTR; + } ESP_LOGV(TAG, "leave esp_sha512_digest_process"); #endif return ret; @@ -2289,6 +2405,24 @@ int esp_hw_show_sha_metrics(void) return ret; } + #endif /* WOLFSSL_ESP32_CRYPT and WOLFSSL_HW_METRICS */ -#endif /* WOLFSSL_ESPIDF (exclude entire contents for non-Espressif projects */ +#if defined(WOLFSSL_STACK_CHECK) +int esp_sha_stack_check(WC_ESP32SHA* sha) { + int ret = ESP_OK; + + if (sha == NULL) { + ESP_LOGW(TAG, "esp_sha_stack_check; sha is NULL"); + } + else { + if (sha->first_word != 0 || sha->last_word != 0) { + ESP_LOGE(TAG, "esp_sha_stack_check warning"); + ret = ESP_FAIL; + } + } + return ret; +} +#endif /* WOLFSSL_STACK_CHECK */ + +#endif /* WOLFSSL_ESPIDF (exclude entire contents for non-Espressif projects. */ diff --git a/src/wolfcrypt/src/port/Espressif/esp32_util.c b/src/wolfcrypt/src/port/Espressif/esp32_util.c index 829afa4..793554a 100644 --- a/src/wolfcrypt/src/port/Espressif/esp32_util.c +++ b/src/wolfcrypt/src/port/Espressif/esp32_util.c @@ -1,6 +1,6 @@ /* esp32_util.c * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -36,6 +36,7 @@ #include #if ESP_IDF_VERSION_MAJOR > 4 #include + #include #endif /* wolfSSL */ #include /* needed to print MATH_INT_T value */ @@ -76,7 +77,7 @@ static int esp_ShowMacroStatus_need_header = 0; #include #include -/* big nums can be very long, perhaps unitialized, so limit displayed words */ +/* big nums can be very long, perhaps uninitialized, so limit displayed words */ #define MAX_WORDS_ESP_SHOW_MP 32 /* @@ -118,7 +119,7 @@ int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t block_time) { * call the ESP-IDF mutex UNlock; xSemaphoreGive * */ -int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { +esp_err_t esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { if (mutex == NULL) { WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex"); return BAD_MUTEX_E; @@ -151,6 +152,13 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) { #if defined(WOLFSSL_ESPIDF) static int ShowExtendedSystemInfo_platform_espressif(void) { +#ifdef WOLFSSL_ESP_NO_WATCHDOG + ESP_LOGI(TAG, "Found WOLFSSL_ESP_NO_WATCHDOG"); +#else + ESP_LOGW(TAG, "Watchdog active; " + "missing WOLFSSL_ESP_NO_WATCHDOG definition."); +#endif + #if defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) WOLFSSL_VERSION_PRINTF("CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ: %u MHz", CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ); @@ -219,8 +227,10 @@ static int ShowExtendedSystemInfo_platform_espressif(void) /* not supported at this time */ #endif - /* check to see if we are using hardware encryption */ -#if defined(NO_ESP32_CRYPT) +/* check to see if we are using hardware encryption */ +#if defined(CONFIG_IDF_TARGET_ESP8266) + WOLFSSL_VERSION_PRINTF("No HW acceleration on ESP8266."); +#elif defined(NO_ESP32_CRYPT) WOLFSSL_VERSION_PRINTF("NO_ESP32_CRYPT defined! " "HW acceleration DISABLED."); #else @@ -246,7 +256,7 @@ static int ShowExtendedSystemInfo_platform_espressif(void) #error "ESP32_CRYPT not yet supported on this IDF TARGET" #endif - /* Even though enabled, some specifics may be disabled */ + /* Even though enabled, some specifics may be disabled */ #if defined(NO_WOLFSSL_ESP32_CRYPT_HASH) WOLFSSL_VERSION_PRINTF("NO_WOLFSSL_ESP32_CRYPT_HASH is defined!" "(disabled HW SHA)."); @@ -385,11 +395,11 @@ int esp_current_boot_count(void) /* See macro helpers above; not_defined is macro name when *not* defined */ static int show_macro(char* s, char* not_defined) { - char hd1[] = "Macro Name Defined Not Defined"; - char hd2[] = "------------------------- --------- -------------"; - char msg[] = "......................... "; - /* 012345678901234567890123456789012345678901234567890 */ - /* 1 2 3 4 5 */ + const char hd1[] = "Macro Name Defined Not Defined"; + char hd2[] = "------------------------- --------- -------------"; + char msg[] = "......................... "; + /* 012345678901234567890123456789012345678901234567890 */ + /* 1 2 3 4 5 */ size_t i = 0; #define MAX_STATUS_NAME_LENGTH 25 #define ESP_SMS_ENA_POS 30 @@ -424,7 +434,7 @@ static int show_macro(char* s, char* not_defined) } /* Show some interesting settings */ -int ShowExtendedSystemInfo_config(void) +esp_err_t ShowExtendedSystemInfo_config(void) { esp_ShowMacroStatus_need_header = 1; @@ -454,6 +464,7 @@ int ShowExtendedSystemInfo_config(void) /* Optimizations */ show_macro("RSA_LOW_MEM", STR_IFNDEF(RSA_LOW_MEM)); + show_macro("SMALL_SESSION_CACHE", STR_IFNDEF(SMALL_SESSION_CACHE)); /* Security Hardening */ show_macro("WC_NO_HARDEN", STR_IFNDEF(WC_NO_HARDEN)); @@ -473,6 +484,8 @@ int ShowExtendedSystemInfo_config(void) show_macro("WOLFSSL_AES_NO_UNROLL", STR_IFNDEF(WOLFSSL_AES_NO_UNROLL)); show_macro("TFM_TIMING_RESISTANT", STR_IFNDEF(TFM_TIMING_RESISTANT)); show_macro("ECC_TIMING_RESISTANT", STR_IFNDEF(ECC_TIMING_RESISTANT)); + + /* WC_RSA_BLINDING takes up additional space: */ show_macro("WC_RSA_BLINDING", STR_IFNDEF(WC_RSA_BLINDING)); show_macro("NO_WRITEV", STR_IFNDEF(NO_WRITEV)); @@ -482,7 +495,7 @@ int ShowExtendedSystemInfo_config(void) show_macro("WOLFSSL_NO_CURRDIR", STR_IFNDEF(WOLFSSL_NO_CURRDIR)); show_macro("WOLFSSL_LWIP", STR_IFNDEF(WOLFSSL_LWIP)); - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); #if defined(CONFIG_COMPILER_OPTIMIZATION_DEFAULT) ESP_LOGI(TAG, "Compiler Optimization: Default"); #elif defined(CONFIG_COMPILER_OPTIMIZATION_SIZE) @@ -494,7 +507,7 @@ int ShowExtendedSystemInfo_config(void) #else ESP_LOGI(TAG, "Compiler Optimization: Unknown"); #endif - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); return ESP_OK; } @@ -629,7 +642,7 @@ int ShowExtendedSystemInfo(void) #ifdef INCLUDE_uxTaskGetStackHighWaterMark ESP_LOGI(TAG, "Stack HWM: %d", uxTaskGetStackHighWaterMark(NULL)); #endif - ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); ShowExtendedSystemInfo_config(); ShowExtendedSystemInfo_git(); @@ -643,29 +656,111 @@ int ShowExtendedSystemInfo(void) return ESP_OK; } -int esp_ShowExtendedSystemInfo(void) +esp_err_t esp_ShowExtendedSystemInfo(void) { /* Someday the ShowExtendedSystemInfo may be global. * See https://github.com/wolfSSL/wolfssl/pull/6149 */ return ShowExtendedSystemInfo(); } +/* + * Disable the watchdog timer (use with caution) + */ + +esp_err_t esp_DisableWatchdog(void) +{ + esp_err_t ret = ESP_OK; +#if defined(CONFIG_IDF_TARGET_ESP8266) + /* magic bit twiddle to disable WDT on ESP8266 */ + *((volatile uint32_t*) 0x60000900) &= ~(1); +#elif CONFIG_IDF_TARGET_ESP32S3 + ESP_LOGW(TAG, "esp_DisableWatchdog TODO S3"); +#else + #if ESP_IDF_VERSION_MAJOR >= 5 + { + #if defined(CONFIG_IDF_TARGET_ESP32) + rtc_wdt_protect_off(); + rtc_wdt_disable(); + #elif defined(CONFIG_IDF_TARGET_ESP32C2) || \ + defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) || \ + defined(CONFIG_IDF_TARGET_ESP32H2) + ESP_LOGW(TAG, "No known rtc_wdt_protect_off for this platform."); + #else + rtc_wdt_protect_off(); + rtc_wdt_disable(); + #endif + } + #else + ESP_LOGW(TAG, "esp_DisableWatchdog not implemented on ESP_OIDF v%d", + ESP_IDF_VERSION_MAJOR); + #endif +#endif + +#ifdef DEBUG_WOLFSSL + ESP_LOGI(TAG, "Watchdog disabled."); +#endif + + return ret; +} + +/* + * Enable the watchdog timer. + */ + +esp_err_t esp_EnabledWatchdog(void) +{ + esp_err_t ret = ESP_OK; +#if defined(CONFIG_IDF_TARGET_ESP8266) + /* magic bit twiddle to enable WDT on ESP8266 */ + *((volatile uint32_t*) 0x60000900) |= 1; +#elif CONFIG_IDF_TARGET_ESP32S3 + ESP_LOGW(TAG, "esp_EnableWatchdog TODO S3"); +#else + #if ESP_IDF_VERSION_MAJOR >= 5 + { + #if defined(CONFIG_IDF_TARGET_ESP32) + rtc_wdt_protect_on(); + rtc_wdt_enable(); + #elif defined(CONFIG_IDF_TARGET_ESP32C2) || \ + defined(CONFIG_IDF_TARGET_ESP32C3) || \ + defined(CONFIG_IDF_TARGET_ESP32C6) || \ + defined(CONFIG_IDF_TARGET_ESP32H2) + ESP_LOGW(TAG, "No known rtc_wdt_protect_off for this platform."); + #else + rtc_wdt_protect_on(); + rtc_wdt_enable(); + #endif + } + #else + ESP_LOGW(TAG, "esp_DisableWatchdog not implemented on ESP_OIDF v%d", + ESP_IDF_VERSION_MAJOR); + #endif +#endif + +#ifdef DEBUG_WOLFSSL + ESP_LOGI(TAG, "Watchdog enabled."); +#endif + + return ret; +} + /* Print a MATH_INT_T attribute list. * * Note with the right string parameters, the result can be pasted as * initialization code. */ -int esp_show_mp_attributes(char* c, MATH_INT_T* X) +esp_err_t esp_show_mp_attributes(char* c, MATH_INT_T* X) { static const char* MP_TAG = "MATH_INT_T"; - int ret = ESP_OK; + esp_err_t ret = ESP_OK; if (X == NULL) { ret = ESP_FAIL; ESP_LOGV(MP_TAG, "esp_show_mp_attributes called with X == NULL"); } else { - ESP_LOGI(MP_TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(MP_TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); ESP_LOGI(MP_TAG, "%s.used = %d;", c, X->used); #if defined(WOLFSSL_SP_INT_NEGATIVE) || defined(USE_FAST_MATH) ESP_LOGI(MP_TAG, "%s.sign = %d;", c, X->sign); @@ -679,10 +774,10 @@ int esp_show_mp_attributes(char* c, MATH_INT_T* X) * Note with the right string parameters, the result can be pasted as * initialization code. */ -int esp_show_mp(char* c, MATH_INT_T* X) +esp_err_t esp_show_mp(char* c, MATH_INT_T* X) { static const char* MP_TAG = "MATH_INT_T"; - int ret = MP_OKAY; + esp_err_t ret = ESP_OK; int words_to_show = 0; if (X == NULL) { @@ -717,16 +812,16 @@ int esp_show_mp(char* c, MATH_INT_T* X) i /* the index, again, for comment */ ); } - ESP_LOGI(MP_TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); + ESP_LOGI(MP_TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE); } return ret; } /* Perform a full mp_cmp and binary compare. * (typically only used during debugging) */ -int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B) +esp_err_t esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B) { - int ret = MP_OKAY; + esp_err_t ret = ESP_OK; int e = memcmp(A, B, sizeof(mp_int)); if (mp_cmp(A, B) == MP_EQ) { if (e == 0) { @@ -769,6 +864,7 @@ int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B) } if (ret == MP_OKAY) { + ret = ESP_OK; ESP_LOGV(TAG, "esp_mp_cmp equal for %s and %s!", name_A, name_B); } @@ -779,7 +875,7 @@ int esp_mp_cmp(char* name_A, MATH_INT_T* A, char* name_B, MATH_INT_T* B) return ret; } -int esp_hw_show_metrics(void) +esp_err_t esp_hw_show_metrics(void) { #if defined(WOLFSSL_HW_METRICS) #if defined(WOLFSSL_ESP32_CRYPT) diff --git a/src/wolfcrypt/src/port/Espressif/esp_sdk_mem_lib.c b/src/wolfcrypt/src/port/Espressif/esp_sdk_mem_lib.c new file mode 100644 index 0000000..8c5cd37 --- /dev/null +++ b/src/wolfcrypt/src/port/Espressif/esp_sdk_mem_lib.c @@ -0,0 +1,280 @@ +/* esp_sdk_mem_lib.c + * + * Copyright (C) 2006-2024 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 + +/* wolfSSL */ +/* Always include wolfcrypt/settings.h before any other wolfSSL file. */ +/* Reminder: settings.h pulls in user_settings.h; don't include it here. */ +#ifdef WOLFSSL_USER_SETTINGS + #include +#endif + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ + +#if defined(WOLFSSL_USER_SETTINGS) + #include +#else + /* Define WOLFSSL_USER_SETTINGS project wide for settings.h to include */ + /* wolfSSL user settings in ./components/wolfssl/include/user_settings.h */ + #error "Missing WOLFSSL_USER_SETTINGS in CMakeLists or Makefile:\ + CFLAGS +=-DWOLFSSL_USER_SETTINGS" +#endif + +#ifndef SINGLE_THREADED + #ifdef PLATFORMIO + #include + #else + #include "semphr.h" + #endif +#endif + +/* Espressif */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include +#include + +/* wolfSSL */ +#include + +static const char* TAG = "mem lib"; +static intptr_t _starting_stack_pointer = 0; +static int _stack_used = 0; + + +/* see + * C:\SysGCC\esp8266\rtos-sdk\v3.4\components\esp8266\ld\esp8266.project.ld.in + */ +extern wc_ptr_t _data_start[]; +extern wc_ptr_t _data_end[]; +extern wc_ptr_t _rodata_start[]; +extern wc_ptr_t _rodata_end[]; +extern wc_ptr_t _bss_start[]; +extern wc_ptr_t _bss_end[]; +extern wc_ptr_t _rtc_data_start[]; +extern wc_ptr_t _rtc_data_end[]; +extern wc_ptr_t _rtc_bss_start[]; +extern wc_ptr_t _rtc_bss_end[]; +extern wc_ptr_t _iram_start[]; +extern wc_ptr_t _iram_end[]; +#if defined(CONFIG_IDF_TARGET_ESP8266) +extern wc_ptr_t _init_start[]; +extern wc_ptr_t _init_end[]; +#endif +extern wc_ptr_t _iram_text_start[]; +extern wc_ptr_t _iram_text_end[]; +extern wc_ptr_t _iram_bss_start[]; +extern wc_ptr_t _iram_bss_end[]; +extern wc_ptr_t _noinit_start[]; +extern wc_ptr_t _noinit_end[]; +extern wc_ptr_t _text_start[]; +extern wc_ptr_t _text_end[]; +extern wc_ptr_t _heap_start[]; +extern wc_ptr_t _heap_end[]; +extern wc_ptr_t _rtc_data_start[]; +extern wc_ptr_t _rtc_data_end[]; +extern void* _thread_local_start; +extern void* _thread_local_end; + +/* See https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map */ +#define MEM_MAP_IO_START ((void*)(0x3FF00000)) +#define MEM_MAP_IO_END ((void*)(0x3FF0FFFF)) +#define USER_DATA_START ((void*)(0x3FFE8000)) +#define USER_DATA_END ((void*)(0x3FFE8000 + 0x14000)) +#define ETS_SYS_START ((void*)(0x3FFFC000)) +#define ETS_SYS_END ((void*)(0x3FFFC000 + 0x4000)) +#define IRAM1_START ((void*)(0x40100000)) +#define IRAM1_END ((void*)(0x40100000 + 0x8000)) +#define IRAMF1_START ((void*)(0x40108000)) +#define IRAMF1_END ((void*)(0x40108000 + 0x4000)) +#define IRAMF2_START ((void*)(0x4010C000)) +#define IRAMF2_END ((void*)(0x4010C000 + 0x4000)) + +enum sdk_memory_segment +{ + /* Ensure this list exactly matches order in sdk_memory_segment_text */ + mem_map_io = 0, + thread_local, + data, + user_data_ram, + bss, + noinit, + ets_system, + iram1, + iramf1, + iramf2, + iram, + iram_text, + iram_bss, + init, + text, + rodata, + rtc_data, + SDK_MEMORY_SEGMENT_COUNT +}; + +static void* sdk_memory_segment_start[SDK_MEMORY_SEGMENT_COUNT + 1] = {}; +static void* sdk_memory_segment_end[SDK_MEMORY_SEGMENT_COUNT + 1] = {}; +static const char* sdk_memory_segment_text[SDK_MEMORY_SEGMENT_COUNT + 1] = { + "C memory map io ", + "* thread_local ", + "C data ", + "* user data ram ", + "* bss ", + "* noinit ", + "C ets system ", + "C iram1 ", + "C iramf1 ", + "C iramf2 ", + "* iram ", + "* iram_text ", + "* iram_bss ", + "* init ", + "* text ", + "* rodata ", + "* rtc data ", + "last item", +}; + +/* Given a given memory segment [m]: assign text names, starting and ending + * addresses. See also sdk_var_whereis() that requires this initialization. */ +int sdk_log_meminfo(enum sdk_memory_segment m, void* start, void* end) +{ + const char* str; + int len = 0; + str = sdk_memory_segment_text[m]; + sdk_memory_segment_start[m] = start; + sdk_memory_segment_end[m] = end; + /* For ESP8266 See ./build/[Debug|Release]/esp8266/esp8266.project.ld */ + /* For ESP32 See ./build/VisualGDB/Debug/esp-idf/esp_system/ld/ */ + if (m == SDK_MEMORY_SEGMENT_COUNT) { + ESP_LOGI(TAG, " Linker Memory Map"); + ESP_LOGI(TAG, "-----------------------------------------------------"); + ESP_LOGI(TAG, " Start End Length"); + } + else { + len = (uint32_t)end - (uint32_t)start; + ESP_LOGI(TAG, "%s: %p ~ %p : 0x%05x (%d)", str, start, end, len, len ); + } + return ESP_OK; +} + +/* Show all known linker memory segment names, starting & ending addresses. */ +int sdk_init_meminfo(void) { + void* sample_heap_var; + int sample_stack_var = 0; + + sdk_log_meminfo(SDK_MEMORY_SEGMENT_COUNT, NULL, NULL); /* print header */ + sdk_log_meminfo(mem_map_io, MEM_MAP_IO_START, MEM_MAP_IO_END); + sdk_log_meminfo(thread_local, _thread_local_start, _thread_local_end); + sdk_log_meminfo(data, _data_start, _data_end); + sdk_log_meminfo(user_data_ram, USER_DATA_START, USER_DATA_END); + sdk_log_meminfo(bss, _bss_start, _bss_end); + sdk_log_meminfo(noinit, _noinit_start, _noinit_end); + sdk_log_meminfo(ets_system, ETS_SYS_START, ETS_SYS_END); + sdk_log_meminfo(rodata, _rodata_start, _rodata_end); + sdk_log_meminfo(iram1, IRAM1_START, IRAM1_END); + sdk_log_meminfo(iramf1, IRAMF1_START, IRAMF1_END); + sdk_log_meminfo(iramf2, IRAMF2_START, IRAMF2_END); + sdk_log_meminfo(iram, _iram_start, _iram_end); + sdk_log_meminfo(iram_text, _iram_text_start, _iram_text_end); + sdk_log_meminfo(iram_bss, _iram_bss_start, _iram_bss_end); +#if defined(CONFIG_IDF_TARGET_ESP8266) + sdk_log_meminfo(init, _init_start, _init_end); +#endif + sdk_log_meminfo(text, _text_start, _text_end); + sdk_log_meminfo(rtc_data, _rtc_data_start, _rtc_data_end); + ESP_LOGI(TAG, "-----------------------------------------------------"); + sample_heap_var = malloc(1); + if (sample_heap_var == NULL) { + ESP_LOGE(TAG, "Unable to allocate heap memory in sdk_var_whereis()."); + } + else { + sdk_var_whereis("sample_stack_var", (void*)&sample_stack_var); + sdk_var_whereis("sample_heap_var", sample_heap_var); + free(sample_heap_var); + } + return ESP_OK; +} + +/* Returns ESP_OK if found in known memory map, ESP_FAIL otherwise */ +esp_err_t sdk_var_whereis(const char* v_name, void* v) { + esp_err_t ret = ESP_FAIL; + + for (enum sdk_memory_segment m = 0 ;m < SDK_MEMORY_SEGMENT_COUNT; m++) { + if (v >= sdk_memory_segment_start[m] && + v <= sdk_memory_segment_end[m]) { + ret = ESP_OK; + ESP_LOGI(TAG, "Variable [%s] found at %p in %s", v_name, v, + sdk_memory_segment_text[m]); + if (m == user_data_ram) { + + } + } + } + + if (ret == ESP_FAIL) { + ESP_LOGW(TAG, "%s not found in known memory map: %p", v_name, v); + } + return ret; +} + +intptr_t esp_sdk_stack_pointer(void) +{ + intptr_t sp = 0; +#if defined(CONFIG_IDF_TARGET_ARCH_RISCV) + if (CONFIG_IDF_TARGET_ARCH_RISCV == 1) { + __asm volatile("mv %0, sp" : "=r" (sp)); + } +#elif defined(CONFIG_IDF_TARGET_ARCH_XTENSA) + if (CONFIG_IDF_TARGET_ARCH_XTENSA == 1) { + __asm volatile("mov %0, sp" : "=r"(sp)); + } +#endif + if (_starting_stack_pointer == 0) { + _starting_stack_pointer = sp; + } + _stack_used = _starting_stack_pointer - sp; + return sp; +} + +esp_err_t esp_sdk_mem_lib_init(void) +{ + int ret = ESP_OK; + sdk_init_meminfo(); + ESP_LOGI(TAG, "esp_sdk_mem_lib_init Ver %d", ESP_SDK_MEM_LIB_VERSION); + return ret; +} + +void* wc_debug_pvPortMalloc(size_t size, + const char* file, int line, const char* fname) { + void* ret = NULL; + ret = pvPortMalloc(size); + if (ret == NULL) { + ESP_LOGE("malloc", "%s:%d (%s)", file, line, fname); + ESP_LOGE("malloc", "Failed Allocating memory of size: %d bytes", size); + } + return ret; +} + +#endif diff --git a/src/wolfcrypt/src/port/Espressif/esp_sdk_time_lib.c b/src/wolfcrypt/src/port/Espressif/esp_sdk_time_lib.c new file mode 100644 index 0000000..1ef8de4 --- /dev/null +++ b/src/wolfcrypt/src/port/Espressif/esp_sdk_time_lib.c @@ -0,0 +1,442 @@ +/* esp_sdk_time_lib.c + * + * Copyright (C) 2006-2024 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 + +/* Reminder: user_settings.h is needed and included from settings.h + * Be sure to define WOLFSSL_USER_SETTINGS, typically in CMakeLists.txt */ +#include + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ +#if defined(USE_WOLFSSL_ESP_SDK_TIME) +/* Espressif */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include +#include + +/* wolfSSL */ +#include + +#define ESP_SDK_TIME_LIB_VERSION 1 + +static const char* TAG = "time lib"; + +esp_err_t esp_sdk_time_lib_init(void) +{ + int ret = ESP_OK; + ESP_LOGI(TAG, "esp_sdk_time_lib_init Ver %d", ESP_SDK_TIME_LIB_VERSION); + return ret; +} + +#if defined(CONFIG_IDF_TARGET_ESP8266) + #include + +#elif defined(ESP_IDF_VERSION_MAJOR) && defined(ESP_IDF_VERSION_MINOR) + #if (ESP_IDF_VERSION_MAJOR == 5) && (ESP_IDF_VERSION_MINOR == 1) + #define HAS_ESP_NETIF_SNTP 1 + #include + #include + #elif (ESP_IDF_VERSION_MAJOR == 5) && (ESP_IDF_VERSION_MINOR > 1) + #define HAS_ESP_NETIF_SNTP 1 + #include + #include + #else + #include + #include + #endif + +#else + /* TODO Consider non ESP-IDF environments */ +#endif + +/* ESP-IDF uses a 64-bit signed integer to represent time_t + * starting from release v5.0 + * See: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html#year-2036-and-2038-overflow-issues + */ + +/* see https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html */ +#ifndef TIME_ZONE + /* + * PST represents Pacific Standard Time. + * +8 specifies the offset from UTC (Coordinated Universal Time), + * indicating that Pacific Time is UTC-8 during standard time. + * PDT represents Pacific Daylight Time. + * M3.2.0 indicates that Daylight Saving Time (DST) starts on the + * second (2) Sunday (0) of March (3). + * M11.1.0 indicates that DST ends on the first (1) Sunday (0) + * of November (11) + */ + #define TIME_ZONE "PST+8PDT,M3.2.0,M11.1.0" +#endif /* not defined: TIME_ZONE, so we are setting our own */ + +#define NTP_RETRY_COUNT 10 + +/* NELEMS(x) number of elements + * To determine the number of elements in the array, we can divide the total + * size of the array by the size of the array element. + * See https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c + **/ +#define NELEMS(x) ( (int)(sizeof(x) / sizeof((x)[0])) ) + +/* See also CONFIG_LWIP_SNTP_MAX_SERVERS in sdkconfig */ +#define NTP_SERVER_LIST ( (char*[]) { \ + "pool.ntp.org", \ + "time.nist.gov", \ + "utcnist.colorado.edu" \ + } \ + ) +/* #define NTP_SERVER_COUNT using NELEMS: + * + * (int)(sizeof(NTP_SERVER_LIST) / sizeof(NTP_SERVER_LIST[0])) + */ +#define NTP_SERVER_COUNT NELEMS(NTP_SERVER_LIST) + +#ifndef CONFIG_LWIP_SNTP_MAX_SERVERS + /* We should find max value in sdkconfig, if not set it to our count:*/ + #define CONFIG_LWIP_SNTP_MAX_SERVERS NTP_SERVER_COUNT +#endif + +/* our NTP server list is global info */ +extern char* ntpServerList[NTP_SERVER_COUNT]; + +char* ntpServerList[NTP_SERVER_COUNT] = NTP_SERVER_LIST; + +/* Show the current date and time */ +int esp_show_current_datetime(void) +{ + time_t now; + char strftime_buf[64]; + struct tm timeinfo; + + time(&now); + setenv("TZ", TIME_ZONE, 1); + tzset(); + + localtime_r(&now, &timeinfo); + strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); + ESP_LOGI(TAG, "The current date/time is: %s", strftime_buf); + return ESP_OK; +} + +/* the worst-case scenario is a hard-coded date/time */ +int set_fixed_default_time(void) +{ + /* ideally, we'd like to set time from network, + * but let's set a default time, just in case */ + struct tm timeinfo = { + .tm_year = 2024 - 1900, + .tm_mon = 1, + .tm_mday = 05, + .tm_hour = 13, + .tm_min = 01, + .tm_sec = 05 + }; + struct timeval now; + time_t interim_time; + int ret = -1; + + /* set interim static time */ + interim_time = mktime(&timeinfo); + + ESP_LOGI(TAG, "Adjusting time from fixed value"); + now = (struct timeval){ .tv_sec = interim_time }; +#if defined(CONFIG_IDF_TARGET_ESP8266) + (void)now; +#else + ret = settimeofday(&now, NULL); +#endif + ESP_LOGI(TAG, "settimeofday result = %d", ret); + return ret; +} + +/* probably_valid_time_string(s) + * + * some sanity checks on time string before calling sscanf() + * + * returns 0 == ESP_OK == Success if str is likely a valid time. + * -1 == ESP_FAIL otherwise + */ +int probably_valid_time_string(const char* str) +{ + int ret = ESP_OK; + size_t length = 0; + size_t spaces = 0; + size_t colons = 0; + + while (str[length] != '\0') { + if (str[length] == ' ') { + spaces++; + } + if (str[length] == ':') { + colons++; + } + length++; + } + + if ((length > 32) || (spaces < 4) || (spaces > 5) || (colons > 2)) { + ret = ESP_FAIL; + ESP_LOGE(TAG, "ERROR, failed time sanity check: %s", str); + } + return ret; +} + +#if defined(CONFIG_IDF_TARGET_ESP8266) +/* TODO implement time functions for ESP8266 */ +int set_time_from_string(const char* time_buffer) +{ + ESP_LOGE(TAG, "set_time_from_string not implemented for ESP8266"); + return ESP_FAIL; +} + +int set_time(void) +{ + ESP_LOGE(TAG, "set_time not implemented for ESP8266"); + return ESP_FAIL; +} + +int set_time_wait_for_ntp(void) +{ + ESP_LOGE(TAG, "set_time_wait_for_ntp not implemented for ESP8266"); + return ESP_FAIL; +} + +#else +/* ESP32 Time Helpers */ + +/* set_time_from_string(s) + * + * returns 0 = success if able to set the time from the provided string + * error for any other value, typically -1 */ +int set_time_from_string(const char* time_buffer) +{ + /* expecting github default formatting: 'Thu Aug 31 12:41:45 2023 -0700' */ + char offset[28]; /* large arrays, just in case there's still bad data */ + char day_str[28]; + char month_str[28]; + const char *format = "%3s %3s %d %d:%d:%d %d %s"; + struct tm this_timeinfo; + struct timeval now; + time_t interim_time; + int day, year, hour, minute, second; + int quote_offset = 0; + int ret = 0; + + /* perform some basic sanity checks */ + ret = probably_valid_time_string(time_buffer); + if (ret == ESP_OK) { + /* we are expecting the string to be encapsulated in single quotes */ + if (*time_buffer == 0x27) { + quote_offset = 1; + } + + ret = sscanf(time_buffer + quote_offset, + format, + day_str, month_str, + &day, &hour, &minute, &second, &year, &offset); + + if (ret == 8) { + /* we found a match for all components */ + + const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + + for (int i = 0; i < 12; i++) { + if (strcmp(month_str, months[i]) == 0) { + this_timeinfo.tm_mon = i; + break; + } + } + + this_timeinfo.tm_mday = day; + this_timeinfo.tm_hour = hour; + this_timeinfo.tm_min = minute; + this_timeinfo.tm_sec = second; + this_timeinfo.tm_year = year - 1900; /* Years since 1900 */ + + interim_time = mktime(&this_timeinfo); + now = (struct timeval){ .tv_sec = interim_time }; + ret = settimeofday(&now, NULL); + ESP_LOGI(TAG, "Time updated to %s", time_buffer); + } + else { + ESP_LOGE(TAG, "Failed to convert \"%s\" to a tm date.", + time_buffer); + ESP_LOGI(TAG, "Trying fixed date that was hard-coded...."); + set_fixed_default_time(); + ret = ESP_FAIL; + } + } + + return ret; +} + +/* set time; returns 0 if succecssfully configured with NTP */ +int set_time(void) +{ +#ifndef NTP_SERVER_COUNT + ESP_LOGW(TAG, "Warning: no sntp server names defined. " + "Setting to empty list"); + #define NTP_SERVER_COUNT 0 + #warning "NTP not properly configured" +#endif /* not defined: NTP_SERVER_COUNT */ + +#ifdef HAS_ESP_NETIF_SNTP + #if CONFIG_LWIP_SNTP_MAX_SERVERS > 1 + esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE( + NTP_SERVER_COUNT, + ESP_SNTP_SERVER_LIST(ntpServerList[0]) + ); + #else + esp_sntp_config_t config = + ESP_NETIF_SNTP_DEFAULT_CONFIG(ntpServerList[0]); + #endif /* CONFIG_LWIP_SNTP_MAX_SERVERS > 1 */ +#endif /* HAS_ESP_NETIF_SNTP */ + + int ret = 0; + int i = 0; /* counter for time servers */ + + ESP_LOGI(TAG, "Setting the time. Startup time:"); + esp_show_current_datetime(); + +#ifdef LIBWOLFSSL_VERSION_GIT_HASH_DATE + /* initially set a default approximate time from recent git commit */ + ESP_LOGI(TAG, "Found git hash date, attempting to set system date: %s", + LIBWOLFSSL_VERSION_GIT_HASH_DATE); + set_time_from_string(LIBWOLFSSL_VERSION_GIT_HASH_DATE"\0"); + esp_show_current_datetime(); + + ret = -4; +#else + /* otherwise set a fixed time that was hard coded */ + set_fixed_default_time(); + esp_show_current_datetime(); + ret = -3; +#endif + +#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH + config.smooth_sync = true; +#endif + + if (NTP_SERVER_COUNT) { + /* next, let's setup NTP time servers + * + * see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html#sntp-time-synchronization + * + * WARNING: do not set operating mode while SNTP client is running! + */ + /* TODO Consider esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); */ + sntp_setoperatingmode(SNTP_OPMODE_POLL); + if (NTP_SERVER_COUNT > CONFIG_LWIP_SNTP_MAX_SERVERS) { + ESP_LOGW(TAG, "WARNING: %d NTP Servers defined, but " + "CONFIG_LWIP_SNTP_MAX_SERVERS = %d", + NTP_SERVER_COUNT,CONFIG_LWIP_SNTP_MAX_SERVERS); + } + ESP_LOGI(TAG, "sntp_setservername:"); + for (i = 0; i < CONFIG_LWIP_SNTP_MAX_SERVERS; i++) { + const char* thisServer = ntpServerList[i]; + if (strncmp(thisServer, "\x00", 1) == 0) { + /* just in case we run out of NTP servers */ + break; + } + ESP_LOGI(TAG, "%s", thisServer); + sntp_setservername(i, thisServer); + ret = ESP_OK; + } + #ifdef HAS_ESP_NETIF_SNTP + ret = esp_netif_sntp_init(&config); + #else + ESP_LOGW(TAG,"Warning: Consider upgrading ESP-IDF to take advantage " + "of updated SNTP libraries"); + #endif + if (ret == ESP_OK) { + ESP_LOGV(TAG, "Successfully called esp_netif_sntp_init"); + } + else { + ESP_LOGE(TAG, "ERROR: esp_netif_sntp_init return = %d", ret); + } + + sntp_init(); + switch (ret) { + case ESP_ERR_INVALID_STATE: + break; + default: + break; + } + ESP_LOGI(TAG, "sntp_init done."); + } + else { + ESP_LOGW(TAG, "No sntp time servers found."); + ret = -1; + } + + esp_show_current_datetime(); + ESP_LOGI(TAG, "time helper existing with result = %d", ret); + return ret; +} + +/* wait for NTP to actually set the time */ +int set_time_wait_for_ntp(void) +{ + int ret = 0; +#ifdef HAS_ESP_NETIF_SNTP + int ntp_retry = 0; + const int ntp_retry_count = NTP_RETRY_COUNT; + + ret = esp_netif_sntp_start(); + + ret = esp_netif_sntp_sync_wait(500 / portTICK_PERIOD_MS); +#else + ESP_LOGE(TAG, "HAS_ESP_NETIF_SNTP not defined"); +#endif /* HAS_ESP_NETIF_SNTP */ + esp_show_current_datetime(); + +#ifdef HAS_ESP_NETIF_SNTP + while (ret == ESP_ERR_TIMEOUT && (ntp_retry++ < ntp_retry_count)) { + ret = esp_netif_sntp_sync_wait(1000 / portTICK_PERIOD_MS); + ESP_LOGI(TAG, "Waiting for NTP to sync time... (%d/%d)", + ntp_retry, + ntp_retry_count); + esp_show_current_datetime(); + } +#endif /* HAS_ESP_NETIF_SNTP */ + +#ifdef TIME_ZONE + setenv("TZ", TIME_ZONE, 1); + tzset(); +#endif + + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Successfully set time via NTP servers."); + } + else { + ESP_LOGW(TAG, "Warning: Failed to set time with NTP: " + "result = 0x%0x: %s", + ret, esp_err_to_name(ret)); + } + return ret; +} +#endif /* ESP32 or ESP8266 time helpers */ + +#endif /* USE_WOLFSSL_ESP_SDK_TIME */ +#endif /* WOLFSSL_ESPIDF*/ diff --git a/src/wolfcrypt/src/port/Espressif/esp_sdk_wifi_lib.c b/src/wolfcrypt/src/port/Espressif/esp_sdk_wifi_lib.c new file mode 100644 index 0000000..06c9f81 --- /dev/null +++ b/src/wolfcrypt/src/port/Espressif/esp_sdk_wifi_lib.c @@ -0,0 +1,468 @@ +/* esp_sdk_wifi_lib.c + * + * Copyright (C) 2006-2024 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 + +/* Reminder: user_settings.h is needed and included from settings.h + * Be sure to define WOLFSSL_USER_SETTINGS, typically in CMakeLists.txt */ +#include + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ +#if defined(USE_WOLFSSL_ESP_SDK_WIFI) + +/* Espressif */ +#include "sdkconfig.h" /* programmatically generated from sdkconfig */ +#include +#include +#include + + +/* wolfSSL */ +#include +#include + +#define ESP_SDK_WIFI_LIB_VERSION 1 + +static const char* TAG = "wifi lib"; + +esp_err_t esp_sdk_wifi_lib_init(void) +{ + int ret = ESP_OK; + ESP_LOGI(TAG, "esp_sdk_wifi_lib_init Ver %d", ESP_SDK_WIFI_LIB_VERSION); + return ret; +} + + +/* When there's too little heap, WiFi quietly refuses to connect */ +#define WIFI_LOW_HEAP_WARNING 21132 + +#if defined(CONFIG_IDF_TARGET_ESP8266) +#elif ESP_IDF_VERSION_MAJOR >= 5 && defined(FOUND_PROTOCOL_EXAMPLES_DIR) + /* example path set in cmake file */ +#elif ESP_IDF_VERSION_MAJOR >= 4 + #include "protocol_examples_common.h" +#else + const static int CONNECTED_BIT = BIT0; + static EventGroupHandle_t wifi_event_group; +#endif + +#if defined(CONFIG_IDF_TARGET_ESP8266) + +#elif defined(ESP_IDF_VERSION_MAJOR) && defined(ESP_IDF_VERSION_MINOR) + #if ESP_IDF_VERSION_MAJOR >= 4 + /* likely using examples, see wifi_connect.h */ + #else + /* TODO - still supporting pre V4 ? */ + const static int CONNECTED_BIT = BIT0; + static EventGroupHandle_t wifi_event_group; + #endif + #if (ESP_IDF_VERSION_MAJOR == 5) + #define HAS_WPA3_FEATURES + #else + #undef HAS_WPA3_FEATURES + #endif +#else + /* TODO Consider pre IDF v5? */ +#endif + +#if defined(CONFIG_IDF_TARGET_ESP8266) +#ifndef CONFIG_ESP_MAX_STA_CONN + #define CONFIG_ESP_MAX_STA_CONN 4 +#endif +#define EXAMPLE_MAX_STA_CONN CONFIG_ESP_MAX_STA_CONN + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 +#ifndef CONFIG_ESP_MAXIMUM_RETRY + #define CONFIG_ESP_MAXIMUM_RETRY 5 +#endif +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t s_wifi_event_group; +static int s_retry_num = 0; + +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#if 0 +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG,"connect to the AP fail"); + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->ip_info.ip)); + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} +#else +static void event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base == WIFI_EVENT) { + if (event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + ESP_LOGV(TAG, "Connect event!!"); + } + else { + if (event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, ">> Retry to connect to the AP"); + } + else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG, ">> Connect to the AP fail"); + } /* WIFI_EVENT_STA_DISCONNECTED */ + else if(event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; + ESP_LOGI(TAG, "got ip:%s", ip4addr_ntoa(&event->ip_info.ip)); + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } /* IP_EVENT_STA_GOT_IP */ + } /* not WIFI_EVENT_STA_START */ + } /* event_base == WIFI_EVENT */ +} /* event_handler */ + +#endif +esp_err_t esp_sdk_wifi_init_sta(void) +{ + word32 this_heap; + + s_wifi_event_group = xEventGroupCreate(); + + tcpip_adapter_init(); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, + &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, + &event_handler, NULL)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS + }, + }; + + /* Setting a password implies station will connect to all security modes + * including WEP/WPA. However these modes are deprecated and not advisable + * to be used. In case your Access point doesn't support WPA2, these mode + * can be enabled by commenting below line */ + if (strlen((char *)wifi_config.sta.password)) { + wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; + } + + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config) ); + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished. Connecting..."); + this_heap = esp_get_free_heap_size(); + ESP_LOGI(TAG, "this heap = %d", this_heap); + if (this_heap < WIFI_LOW_HEAP_WARNING) { + ESP_LOGW(TAG, "Warning: WiFi low heap: %d", WIFI_LOW_HEAP_WARNING); + } + /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) + * or connection failed for the maximum number of re-tries (WIFI_FAIL_BIT). + * The bits are set by event_handler() + * (see above) */ + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + ESP_LOGI(TAG, "xEventGroupWaitBits finished."); +#if 0 + /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually + * happened. */ + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "connected to ap SSID:%s", + EXAMPLE_ESP_WIFI_SSID); + } else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } +#else + /* xEventGroupWaitBits() returns the bits before the call returned, + * hence we can test which event actually happened. */ + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "Connected to AP SSID: %s", + EXAMPLE_ESP_WIFI_SSID); + } + else { + if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to SSID: %s, password:%s", + EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS); + } + else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } + } + +#endif + ESP_ERROR_CHECK(esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, + &event_handler)); + ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + &event_handler)); + vEventGroupDelete(s_wifi_event_group); + return ESP_OK; +} + +#elif ESP_IDF_VERSION_MAJOR < 4 +/* event handler for wifi events */ +static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) + { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + #if ESP_IDF_VERSION_MAJOR >= 4 + ESP_LOGI(TAG, "got ip:" IPSTR "\n", + IP2STR(&event->event_info.got_ip.ip_info.ip)); + #else + ESP_LOGI(TAG, "got ip:%s", + ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + #endif + /* see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos_idf.html */ + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} +#else + +#ifdef CONFIG_ESP_MAXIMUM_RETRY + #define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY +#else + #define CONFIG_ESP_MAXIMUM_RETRY 5 +#endif + +#if CONFIG_ESP_WIFI_AUTH_OPEN +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN +#elif CONFIG_ESP_WIFI_AUTH_WEP +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP +#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK +#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK +#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK +#endif + +#ifndef ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD + #define CONFIG_ESP_WIFI_AUTH_WPA2_PSK 1 + #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD CONFIG_ESP_WIFI_AUTH_WPA2_PSK +#endif + +/* FreeRTOS event group to signal when we are connected*/ +static EventGroupHandle_t s_wifi_event_group; + +/* The event group allows multiple bits for each event, + * but we only care about two events: + * - we are connected to the AP with an IP + * - we failed to connect after the maximum amount of retries */ +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + + +static int s_retry_num = 0; +ip_event_got_ip_t* event; + + +static void event_handler(void* arg, + esp_event_base_t event_base, + int32_t event_id, + void* event_data) +{ + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + } + else if (event_base == WIFI_EVENT && + event_id == WIFI_EVENT_STA_DISCONNECTED) { + if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + esp_wifi_connect(); + s_retry_num++; + ESP_LOGI(TAG, "retry to connect to the AP"); + } + else { + xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); + } + ESP_LOGI(TAG, "connect to the AP fail"); + } + else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + event = (ip_event_got_ip_t*) event_data; + /* wifi_show_ip(); */ + s_retry_num = 0; + xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + } +} + +esp_err_t wc_wifi_init_sta(void) +{ + esp_err_t ret = ESP_OK; + + s_wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + esp_event_handler_instance_t instance_any_id; + esp_event_handler_instance_t instance_got_ip; + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, + ESP_EVENT_ANY_ID, + &event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler, + NULL, + &instance_got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = EXAMPLE_ESP_WIFI_SSID, + .password = EXAMPLE_ESP_WIFI_PASS, + /* Authmode threshold resets to WPA2 as default if password matches + * WPA2 standards (password len => 8). If you want to connect the + * device to deprecated WEP/WPA networks, Please set the threshold + * value WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK and set the password with + * length and format matching to WIFI_AUTH_WEP/WIFI_AUTH_WPA_PSK + * standards. */ + .threshold.authmode = ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD, + #ifdef HAS_WPA3_FEATURES + .sae_pwe_h2e = WPA3_SAE_PWE_BOTH, + #endif + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); + +#ifdef CONFIG_EXAMPLE_WIFI_SSID + if (XSTRCMP(CONFIG_EXAMPLE_WIFI_SSID, "myssid") == 0) { + ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID is \"myssid\"."); + ESP_LOGW(TAG, " Do you have a WiFi AP called \"myssid\", "); + ESP_LOGW(TAG, " or did you forget the ESP-IDF configuration?"); + } +#else + ESP_LOGW(TAG, "WARNING: CONFIG_EXAMPLE_WIFI_SSID not defined."); +#endif + + ESP_ERROR_CHECK(esp_wifi_start() ); + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) + * or connection failed for the maximum number of re-tries (WIFI_FAIL_BIT). + * The bits are set by event_handler() (see above) */ + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + /* xEventGroupWaitBits() returns the bits before the call returned, + * hence we can test which event actually happened. */ +#if defined(SHOW_SSID_AND_PASSWORD) + ESP_LOGW(TAG, "Undefine SHOW_SSID_AND_PASSWORD to not show SSID/password"); + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "connected to ap SSID:%s password:%s", + EXAMPLE_ESP_WIFI_SSID, + EXAMPLE_ESP_WIFI_PASS); + } + else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to SSID:%s, password:%s", + EXAMPLE_ESP_WIFI_SSID, + EXAMPLE_ESP_WIFI_PASS); + } + else { + ESP_LOGE(TAG, "UNEXPECTED EVENT"); + } +#else + if (bits & WIFI_CONNECTED_BIT) { + ESP_LOGI(TAG, "Connected to AP"); + } + else if (bits & WIFI_FAIL_BIT) { + ESP_LOGI(TAG, "Failed to connect to AP"); + ret = -1; + } + else { + ESP_LOGE(TAG, "AP UNEXPECTED EVENT"); + ret = -2; + } +#endif + return ret; +} + +esp_err_t wc_wifi_show_ip(void) +{ + /* TODO Causes panic: ESP_LOGI(TAG, "got ip:" IPSTR, + * IP2STR(&event->ip_info.ip)); */ + return ESP_OK; +} + +#endif + + +#endif /* USE_WOLFSSL_ESP_SDK_WIFI */ +#endif /* WOLFSSL_ESPIDF */ diff --git a/src/wolfcrypt/src/port/atmel/atmel.c b/src/wolfcrypt/src/port/atmel/atmel.c index 9a404d8..b3c6b79 100644 --- a/src/wolfcrypt/src/port/atmel/atmel.c +++ b/src/wolfcrypt/src/port/atmel/atmel.c @@ -136,7 +136,7 @@ int atmel_get_random_number(uint32_t count, uint8_t* rand_out) int atmel_get_random_block(unsigned char* output, unsigned int sz) { - return atmel_get_random_number((uint32_t)sz, (uint8_t*)output); + return atmel_get_random_number((uint32_t)sz, (uint8_t*)output); } #if defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME) @@ -148,12 +148,12 @@ long atmel_get_curr_time_and_date(long* tm) { long rt = 0; - /* Get current time */ + /* Get current time */ struct rtc_calendar_time rtcTime; const int monthDay[] = {0,31,59,90,120,151,181,212,243,273,304,334}; int month, year, yearLeap; - rtc_calendar_get_time(_rtc_instance[0], &rtcTime); + rtc_calendar_get_time(_rtc_instance[0], &rtcTime); /* Convert rtc_calendar_time to seconds since UTC */ month = rtcTime.month % 12; @@ -359,7 +359,7 @@ int atmel_get_enc_key_default(byte* enckey, word16 keysize) static int atmel_init_enc_key(void) { int ret; - uint8_t read_key[ATECC_KEY_SIZE]; + uint8_t read_key[ATECC_KEY_SIZE]; uint8_t writeBlock = 0; uint8_t writeOffset = 0; int slotId; @@ -388,7 +388,7 @@ static int atmel_init_enc_key(void) ForceZero(read_key, sizeof(read_key)); ret = atmel_ecc_translate_err(ret); - return ret; + return ret; } #endif @@ -497,7 +497,7 @@ int atmel_init(void) extern ATCAIfaceCfg atecc608_0_init_data; #endif #endif - + if (!mAtcaInitDone) { ATCA_STATUS status; int i; @@ -940,7 +940,7 @@ int atcatls_verify_signature_cb(WOLFSSL* ssl, const byte* sig, return ret; } -static int atcatls_set_certificates(WOLFSSL_CTX *ctx) +static int atcatls_set_certificates(WOLFSSL_CTX *ctx) { #ifndef ATCATLS_SIGNER_CERT_MAX_SIZE #define ATCATLS_SIGNER_CERT_MAX_SIZE 0x250 @@ -966,7 +966,7 @@ static int atcatls_set_certificates(WOLFSSL_CTX *ctx) uint8_t signerPubKeyBuffer[ATCATLS_PUBKEY_BUFF_MAX_SIZE]; #endif -#ifdef WOLFSSL_ATECC_TNGTLS +#ifdef WOLFSSL_ATECC_TNGTLS ret = tng_atcacert_max_signer_cert_size(&signerCertSize); if (ret != ATCACERT_E_SUCCESS) { #ifdef WOLFSSL_ATECC_DEBUG diff --git a/src/wolfcrypt/src/pwdbased.c b/src/wolfcrypt/src/pwdbased.c index 8be0c64..1aef716 100644 --- a/src/wolfcrypt/src/pwdbased.c +++ b/src/wolfcrypt/src/pwdbased.c @@ -28,6 +28,16 @@ #ifndef NO_PWDBASED +#if FIPS_VERSION3_GE(6,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$h") + #pragma const_seg(".fipsB$h") + #endif +#endif + #include #include #include @@ -41,6 +51,17 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + #ifdef DEBUG_WOLFSSL + #include + #endif + const unsigned int wolfCrypt_FIPS_pbkdf_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000010 }; + int wolfCrypt_FIPS_PBKDF_sanity(void) + { + return 0; + } +#endif #ifdef HAVE_PBKDF1 @@ -165,6 +186,7 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, int sLen, int iterations, int kLen, int hashType) { + return wc_PBKDF1_ex(output, kLen, NULL, 0, passwd, pLen, salt, sLen, iterations, hashType, NULL); } @@ -191,6 +213,24 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt, return BAD_FUNC_ARG; } +#if FIPS_VERSION3_GE(6,0,0) + /* Per SP800-132 section 5 "The kLen value shall be at least 112 bits in + * length", ensure the returned bits for the derived master key are at a + * minimum 14-bytes or 112-bits after stretching and strengthening + * (iterations) */ + if (kLen < HMAC_FIPS_MIN_KEY/8) + return BAD_LENGTH_E; +#endif + +#if FIPS_VERSION3_GE(6,0,0) && defined(DEBUG_WOLFSSL) + /* SP800-132 section 5.2 recommends an iteration count of 1000 but this is + * not strictly enforceable and is listed in Appendix B Table 1 as a + * non-testable requirement. wolfCrypt will log it when appropriate but + * take no action */ + if (iterations < 1000) { + WOLFSSL_MSG("WARNING: Iteration < 1,000, see SP800-132 section 5.2"); + } +#endif if (iterations <= 0) iterations = 1; @@ -214,7 +254,17 @@ int wc_PBKDF2_ex(byte* output, const byte* passwd, int pLen, const byte* salt, if (ret == 0) { word32 i = 1; /* use int hashType here, since HMAC FIPS uses the old unique value */ + #if FIPS_VERSION3_GE(6,0,0) + { + /* Allow passwords that are less than 14-bytes for compatibility + * / interoperability, only since module v6.0.0 */ + int allowShortPasswd = 1; + ret = wc_HmacSetKey_ex(hmac, hashType, passwd, (word32)pLen, + allowShortPasswd); + } + #else ret = wc_HmacSetKey(hmac, hashType, passwd, (word32)pLen); + #endif while (ret == 0 && kLen) { int currentLen; diff --git a/src/wolfcrypt/src/random.c b/src/wolfcrypt/src/random.c index d44f2e2..89c7411 100644 --- a/src/wolfcrypt/src/random.c +++ b/src/wolfcrypt/src/random.c @@ -50,8 +50,8 @@ This library contains implementation for the random number generator. #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$c") - #pragma const_seg(".fipsB$c") + #pragma code_seg(".fipsA$i") + #pragma const_seg(".fipsB$i") #endif #endif @@ -128,6 +128,8 @@ This library contains implementation for the random number generator. #elif defined(WOLFSSL_TELIT_M2MB) #elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_TRNG) #elif defined(WOLFSSL_IMXRT1170_CAAM) +#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL) + #include "cyhal_trng.h" /* Infineon/Cypress HAL RNG implementation */ #elif defined(WOLFSSL_GETRANDOM) #include #include @@ -151,6 +153,15 @@ This library contains implementation for the random number generator. #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_drbg_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000011 }; + int wolfCrypt_FIPS_DRBG_sanity(void) + { + return 0; + } +#endif + #if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) || \ defined(HAVE_AMD_RDSEED) static word32 intel_flags = 0; @@ -611,6 +622,9 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) } if (drbg->reseedCtr == RESEED_INTERVAL) { +#if FIPS_VERSION3_GE(6,0,0) + printf("Reseed triggered\n"); +#endif return DRBG_NEED_RESEED; } else { @@ -1456,7 +1470,7 @@ int wc_Entropy_Get(int bits, unsigned char* entropy, word32 len) Entropy_StopThread(); #endif - if (ret != BAD_MUTEX_E) { + if (ret != WC_NO_ERR_TRACE(BAD_MUTEX_E)) { /* Unlock mutex now we are done. */ wc_UnLockMutex(&entropy_mutex); } @@ -1472,7 +1486,7 @@ int wc_Entropy_Get(int bits, unsigned char* entropy, word32 len) * @return ENTROPY_RT_E or ENTROPY_APT_E on failure. * @return BAD_MUTEX_E when unable to lock mutex. */ -int wc_Entropy_OnDemandTest() +int wc_Entropy_OnDemandTest(void) { int ret = 0; @@ -1488,7 +1502,7 @@ int wc_Entropy_OnDemandTest() ret = Entropy_HealthTest_Startup(); } - if (ret != BAD_MUTEX_E) { + if (ret != WC_NO_ERR_TRACE(BAD_MUTEX_E)) { /* Unlock mutex now we are done. */ wc_UnLockMutex(&entropy_mutex); } @@ -1500,7 +1514,7 @@ int wc_Entropy_OnDemandTest() * @return 0 on success. * @return Negative on failure. */ -int Entropy_Init() +int Entropy_Init(void) { int ret = 0; @@ -1537,7 +1551,7 @@ int Entropy_Init() /* Finalize the data associated with the MemUse Entropy source. */ -void Entropy_Final() +void Entropy_Final(void) { /* Only finalize when initialized. */ if (entropy_memuse_initialized) { @@ -1854,7 +1868,7 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) #endif { ret = wc_CryptoCb_RandomBlock(rng, output, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -2662,7 +2676,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #endif { ret = wc_CryptoCb_RandomSeed(os, output, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -3462,7 +3476,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) } /* driver could be waiting for entropy */ - if (ret != RAN_BLOCK_E && ret != 0) { + if (ret != WC_NO_ERR_TRACE(RAN_BLOCK_E) && ret != 0) { return ret; } #ifndef WOLFSSL_IMXRT1170_CAAM @@ -3717,25 +3731,33 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #elif defined(WOLFSSL_ZEPHYR) - #include + #include #if KERNEL_VERSION_NUMBER >= 0x30500 #include #else - #include + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #else + #include + #endif #endif #ifndef _POSIX_C_SOURCE - #include + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #else + #include + #endif #else #include #endif - int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) - { - sys_rand_get(output, sz); - return 0; - } + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + sys_rand_get(output, sz); + return 0; + } #elif defined(WOLFSSL_TELIT_M2MB) @@ -3832,6 +3854,40 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return ret; } +#elif defined(CY_USING_HAL) && defined(COMPONENT_WOLFSSL) + + /* Infineon/Cypress HAL RNG implementation */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + cyhal_trng_t obj; + cy_rslt_t result; + uint32_t val; + word32 i = 0; + + (void)os; + + result = cyhal_trng_init(&obj); + if (result == CY_RSLT_SUCCESS) { + while (i < sz) { + /* If not aligned or there is odd/remainder add single byte */ + if( (i + sizeof(word32)) > sz || + ((wc_ptr_t)&output[i] % sizeof(word32)) != 0 + ) { + val = cyhal_trng_generate(&obj); + output[i++] = (byte)val; + } + else { + /* Use native 32 instruction */ + val = cyhal_trng_generate(&obj); + *((uint32_t*)&output[i]) = val; + i += sizeof(word32); + } + } + cyhal_trng_free(&obj); + } + return 0; + } + #elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \ defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) || \ defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) || \ @@ -3853,14 +3909,14 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { - int ret = WC_HW_E; + int ret = WC_NO_ERR_TRACE(WC_HW_E); #ifndef WOLF_CRYPTO_CB_FIND if (os->devId != INVALID_DEVID) #endif { ret = wc_CryptoCb_RandomSeed(os, output, sz); - if (ret == CRYPTOCB_UNAVAILABLE) { + if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { ret = WC_HW_E; } } @@ -3898,7 +3954,7 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) #endif { ret = wc_CryptoCb_RandomSeed(os, output, sz); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; /* reset error code */ diff --git a/src/wolfcrypt/src/rsa.c b/src/wolfcrypt/src/rsa.c index 4299fd2..587e47c 100644 --- a/src/wolfcrypt/src/rsa.c +++ b/src/wolfcrypt/src/rsa.c @@ -35,15 +35,13 @@ RSA keys can be used to encrypt, decrypt, sign and verify data. #ifndef NO_RSA -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) - +#if FIPS_VERSION3_GE(2,0,0) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$e") - #pragma const_seg(".fipsB$e") + #pragma code_seg(".fipsA$j") + #pragma const_seg(".fipsB$j") #endif #endif @@ -108,6 +106,14 @@ RSA Key Size Configuration: #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_rsa_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000012 }; + int wolfCrypt_FIPS_RSA_sanity(void) + { + return 0; + } +#endif enum { RSA_STATE_NONE = 0, @@ -121,22 +127,25 @@ enum { RSA_STATE_DECRYPT_RES }; - static void wc_RsaCleanup(RsaKey* key) { -#if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_NO_MALLOC) - if (key && key->data) { +#if !defined(WOLFSSL_NO_MALLOC) && (defined(WOLFSSL_ASYNC_CRYPT) || \ + (!defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE))) + if (key != NULL) { + #ifndef WOLFSSL_RSA_PUBLIC_ONLY + /* if private operation zero temp buffer */ + if ((key->data != NULL && key->dataLen > 0) && + (key->type == RSA_PRIVATE_DECRYPT || + key->type == RSA_PRIVATE_ENCRYPT)) { + ForceZero(key->data, key->dataLen); + } + #endif /* make sure any allocated memory is free'd */ if (key->dataIsAlloc) { - #ifndef WOLFSSL_RSA_PUBLIC_ONLY - if (key->type == RSA_PRIVATE_DECRYPT || - key->type == RSA_PRIVATE_ENCRYPT) { - ForceZero(key->data, key->dataLen); - } - #endif XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); key->dataIsAlloc = 0; } + key->data = NULL; key->dataLen = 0; } @@ -148,29 +157,21 @@ static void wc_RsaCleanup(RsaKey* key) int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) { int ret = 0; -#if defined(HAVE_PKCS11) - int isPkcs11 = 0; -#endif if (key == NULL) { return BAD_FUNC_ARG; } -#if defined(HAVE_PKCS11) - if (key->isPkcs11) { - isPkcs11 = 1; - } -#endif - XMEMSET(key, 0, sizeof(RsaKey)); key->type = RSA_TYPE_UNKNOWN; key->state = RSA_STATE_NONE; key->heap = heap; -#if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_NO_MALLOC) +#if !defined(WOLFSSL_NO_MALLOC) && (defined(WOLFSSL_ASYNC_CRYPT) || \ + (!defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE))) key->dataIsAlloc = 0; - key->data = NULL; #endif + key->data = NULL; key->dataLen = 0; #ifdef WC_RSA_BLINDING key->rng = NULL; @@ -188,19 +189,18 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) #endif #ifdef WC_ASYNC_ENABLE_RSA - #if defined(HAVE_PKCS11) - if (!isPkcs11) + #ifdef WOLF_CRYPTO_CB + /* prefer crypto callback */ + if (key->devId != INVALID_DEVID) #endif - { - /* handle as async */ - ret = wolfAsync_DevCtxInit(&key->asyncDev, - WOLFSSL_ASYNC_MARKER_RSA, key->heap, devId); - if (ret != 0) - return ret; - } + { + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, + WOLFSSL_ASYNC_MARKER_RSA, key->heap, devId); + if (ret != 0) + return ret; + } #endif /* WC_ASYNC_ENABLE_RSA */ -#elif defined(HAVE_PKCS11) - (void)isPkcs11; #endif /* WOLFSSL_ASYNC_CRYPT */ #ifndef WOLFSSL_RSA_PUBLIC_ONLY @@ -273,14 +273,6 @@ int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, void* heap, ret = BAD_FUNC_ARG; if (ret == 0 && (len < 0 || len > RSA_MAX_ID_LEN)) ret = BUFFER_E; - -#if defined(HAVE_PKCS11) - if (ret == 0) { - XMEMSET(key, 0, sizeof(RsaKey)); - key->isPkcs11 = 1; - } -#endif - if (ret == 0) ret = wc_InitRsaKey_ex(key, heap, devId); if (ret == 0 && id != NULL && len != 0) { @@ -310,14 +302,6 @@ int wc_InitRsaKey_Label(RsaKey* key, const char* label, void* heap, int devId) if (labelLen == 0 || labelLen > RSA_MAX_LABEL_LEN) ret = BUFFER_E; } - -#if defined(HAVE_PKCS11) - if (ret == 0) { - XMEMSET(key, 0, sizeof(RsaKey)); - key->isPkcs11 = 1; - } -#endif - if (ret == 0) ret = wc_InitRsaKey_ex(key, heap, devId); if (ret == 0) { @@ -648,13 +632,13 @@ static int _ifc_pairwise_consistency_test(RsaKey* key, WC_RNG* rng) #ifdef WOLFSSL_ASYNC_CRYPT /* Do blocking async calls here, caller does not support WC_PENDING_E */ do { - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); if (ret >= 0) #endif ret = wc_RsaSSL_Sign((const byte*)msg, msgLen, sig, sigLen, key, rng); #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif if (ret > 0) { @@ -662,13 +646,13 @@ static int _ifc_pairwise_consistency_test(RsaKey* key, WC_RNG* rng) #ifdef WOLFSSL_ASYNC_CRYPT /* Do blocking async calls here, caller does not support WC_PENDING_E */ do { - if (ret == WC_PENDING_E) + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) ret = wc_AsyncWait(ret, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); if (ret >= 0) #endif ret = wc_RsaSSL_VerifyInline(sig, sigLen, &plain, key); #ifdef WOLFSSL_ASYNC_CRYPT - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif } @@ -689,13 +673,17 @@ static int _ifc_pairwise_consistency_test(RsaKey* key, WC_RNG* rng) int wc_CheckRsaKey(RsaKey* key) { - DECL_MP_INT_SIZE_DYN(tmp, mp_bitsused(&key->n), RSA_MAX_SIZE); #ifdef WOLFSSL_SMALL_STACK WC_RNG *rng = NULL; #else WC_RNG rng[1]; #endif int ret = 0; + DECL_MP_INT_SIZE_DYN(tmp, (key)? mp_bitsused(&key->n) : 0, RSA_MAX_SIZE); + + if (key == NULL) { + return BAD_FUNC_ARG; + } #ifdef WOLFSSL_CAAM /* can not perform these checks on an encrypted key */ @@ -727,11 +715,6 @@ int wc_CheckRsaKey(RsaKey* key) ret = MP_INIT_E; } - if (ret == 0) { - if (key == NULL) - ret = BAD_FUNC_ARG; - } - if (ret == 0) ret = _ifc_pairwise_consistency_test(key, rng); @@ -1805,7 +1788,7 @@ static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, byte **output, byte padValue) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); word16 i; if (output == NULL || pkcsBlockLen < 2 || pkcsBlockLen > 0xFFFF) { @@ -2794,7 +2777,7 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, #ifdef WOLFSSL_HAVE_SP_RSA ret = RsaFunction_SP(in, inLen, out, outLen, type, key, rng); - if (ret != WC_KEY_SIZE_E) + if (ret != WC_NO_ERR_TRACE(WC_KEY_SIZE_E)) return ret; #endif /* WOLFSSL_HAVE_SP_RSA */ @@ -2948,7 +2931,7 @@ int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, key->dataLen = *outSz; ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng); - if (ret >= 0 || ret == WC_PENDING_E) { + if (ret >= 0 || ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { key->state = (type == RSA_PRIVATE_ENCRYPT || type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES: RSA_STATE_DECRYPT_RES; @@ -3146,12 +3129,12 @@ static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, { ret = wc_CryptoCb_Rsa(in, inLen, out, outLen, type, key, rng); #ifndef WOLF_CRYPTO_CB_ONLY_RSA - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable and try using software */ #endif #ifdef WOLF_CRYPTO_CB_ONLY_RSA - if (ret == CRYPTOCB_UNAVAILABLE) { + if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { return NO_VALID_DEVID; } return ret; @@ -3203,7 +3186,7 @@ static int wc_RsaFunction_ex(const byte* in, word32 inLen, byte* out, && ret != FP_WOULDBLOCK #endif ) { - if (ret == MP_EXPTMOD_E) { + if (ret == WC_NO_ERR_TRACE(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"); } @@ -3339,8 +3322,8 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, if (key->devId != INVALID_DEVID) { /* SCE supports 1024 and 2048 bits */ ret = wc_CryptoCb_Rsa(in, inLen, out, - outLen, rsa_type, key, rng); - if (ret != CRYPTOCB_UNAVAILABLE) + &outLen, rsa_type, key, rng); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; /* reset error code and try using software */ @@ -3365,7 +3348,7 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, ret = wc_RsaFunction(out, (word32)sz, out, &key->dataLen, rsa_type, key, rng); - if (ret >= 0 || ret == WC_PENDING_E) { + if (ret >= 0 || ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { key->state = RSA_STATE_ENCRYPT_RES; } if (ret < 0) { @@ -3425,7 +3408,7 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, byte* label, word32 labelSz, int saltLen, WC_RNG* rng) { - int ret = RSA_WRONG_TYPE_E; + int ret = WC_NO_ERR_TRACE(RSA_WRONG_TYPE_E); byte* pad = NULL; if (in == NULL || inLen == 0 || out == NULL || key == NULL) { @@ -3496,8 +3479,8 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, #ifdef WOLF_CRYPTO_CB if (key->devId != INVALID_DEVID) { ret = wc_CryptoCb_Rsa(in, inLen, out, - outLen, rsa_type, key, rng); - if (ret != CRYPTOCB_UNAVAILABLE) + &outLen, rsa_type, key, rng); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ ret = 0; /* reset error code and try using software */ @@ -3525,6 +3508,7 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, break; } XMEMCPY(key->data, in, inLen); + key->dataLen = inLen; } else { key->dataIsAlloc = 0; @@ -3546,7 +3530,7 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, rng, pad_type != WC_RSA_OAEP_PAD); #endif - if (ret >= 0 || ret == WC_PENDING_E) { + if (ret >= 0 || ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { key->state = RSA_STATE_DECRYPT_UNPAD; } if (ret < 0) { @@ -3558,13 +3542,13 @@ static int RsaPrivateDecryptEx(const byte* in, word32 inLen, byte* out, case RSA_STATE_DECRYPT_UNPAD: #if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) && \ !defined(WOLFSSL_NO_MALLOC) - ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type, - hash, mgf, label, labelSz, saltLen, - mp_count_bits(&key->n), key->heap); + ret = wc_RsaUnPad_ex(key->data, + key->dataLen, &pad, pad_value, pad_type, hash, mgf, + label, labelSz, saltLen, mp_count_bits(&key->n), key->heap); #else - ret = wc_RsaUnPad_ex(out, key->dataLen, &pad, pad_value, pad_type, hash, - mgf, label, labelSz, saltLen, - mp_count_bits(&key->n), key->heap); + ret = wc_RsaUnPad_ex(out, + key->dataLen, &pad, pad_value, pad_type, hash, mgf, label, + labelSz, saltLen, mp_count_bits(&key->n), key->heap); #endif if (rsa_type == RSA_PUBLIC_DECRYPT && ret > (int)outLen) { ret = RSA_BUFFER_E; @@ -4033,7 +4017,10 @@ int wc_RsaPSS_CheckPadding_ex2(const byte* in, word32 inSz, byte* sig, /* Sig = Salt | Exp Hash */ if (ret == 0) { - if (sigSz != inSz + (word32)saltLen) { + word32 totalSz; + if ((WC_SAFE_SUM_WORD32(inSz, (word32)saltLen, totalSz) == 0) || + (sigSz != totalSz)) + { ret = PSS_SALTLEN_E; } } @@ -4259,7 +4246,7 @@ int wc_RsaEncryptSize(const RsaKey* key) #ifdef WOLF_CRYPTO_CB if (ret == 0 && key->devId != INVALID_DEVID) { - if (wc_CryptoCb_RsaGetSize(key, &ret) == CRYPTOCB_UNAVAILABLE) { + if (wc_CryptoCb_RsaGetSize(key, &ret) == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { ret = 2048/8; /* hardware handles, use 2048-bit as default */ } } @@ -4326,7 +4313,7 @@ int wc_RsaExportKey(RsaKey* key, byte* d, word32* dSz, byte* p, word32* pSz, byte* q, word32* qSz) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) ret = 0; @@ -4531,7 +4518,8 @@ static int _CheckProbablePrime(mp_int* p, mp_int* q, mp_int* e, int nlen, if (q != NULL) { int valid = 0; - /* 5.4 - check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */ + /* 5.4 (186-4) 5.5 (186-5) - + * check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */ ret = wc_CompareDiffPQ(p, q, nlen, &valid); if ((ret != MP_OKAY) || (!valid)) goto notOkay; prime = q; @@ -4539,14 +4527,15 @@ static int _CheckProbablePrime(mp_int* p, mp_int* q, mp_int* e, int nlen, else prime = p; - /* 4.4,5.5 - Check that prime >= (2^(1/2))(2^((nlen/2)-1)) + /* 4.4,5.5 (186-4) 4.4,5.4 (186-5) - + * Check that prime >= (2^(1/2))(2^((nlen/2)-1)) * This is a comparison against lowerBound */ ret = mp_read_unsigned_bin(tmp1, lower_bound, (word32)nlen/16); if (ret != MP_OKAY) goto notOkay; ret = mp_cmp(prime, tmp1); if (ret == MP_LT) goto exit; - /* 4.5,5.6 - Check that GCD(p-1, e) == 1 */ + /* 4.5,5.6 (186-4 & 186-5) - Check that GCD(p-1, e) == 1 */ ret = mp_sub_d(prime, 1, tmp1); /* tmp1 = prime-1 */ if (ret != MP_OKAY) goto notOkay; #ifdef WOLFSSL_CHECK_MEM_ZERO @@ -4721,7 +4710,12 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) #endif /* WOLFSSL_SMALL_STACK */ int i, failCount, isPrime = 0; word32 primeSz; +#ifndef WOLFSSL_NO_MALLOC byte* buf = NULL; +#else + /* RSA_MAX_SIZE is the size of n in bits. */ + byte buf[RSA_MAX_SIZE/16]; +#endif #endif /* !WOLFSSL_CRYPTOCELL && !WOLFSSL_SE050 */ int err; @@ -4780,12 +4774,12 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { err = wc_CryptoCb_MakeRsaKey(key, size, e, rng); #ifndef WOLF_CRYPTO_CB_ONLY_RSA - if (err != CRYPTOCB_UNAVAILABLE) + if (err != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) goto out; /* fall-through when unavailable */ #endif #ifdef WOLF_CRYPTO_CB_ONLY_RSA - if (err == CRYPTOCB_UNAVAILABLE) + if (err == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) err = NO_VALID_DEVID; goto out; } @@ -4827,12 +4821,14 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) primeSz = (word32)size / 16; /* size is the size of n in bits. primeSz is in bytes. */ +#ifndef WOLFSSL_NO_MALLOC /* allocate buffer to work with */ if (err == MP_OKAY) { buf = (byte*)XMALLOC(primeSz, key->heap, DYNAMIC_TYPE_RSA); if (buf == NULL) err = MEMORY_E; } +#endif SAVE_VECTOR_REGISTERS(err = _svr_ret;); @@ -4935,10 +4931,14 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (err == MP_OKAY && !isPrime) err = PRIME_GEN_E; +#ifndef WOLFSSL_NO_MALLOC if (buf) { ForceZero(buf, primeSz); XFREE(buf, key->heap, DYNAMIC_TYPE_RSA); } +#else + ForceZero(buf, primeSz); +#endif if (err == MP_OKAY && mp_cmp(p, q) < 0) { err = mp_copy(p, tmp1); @@ -5156,4 +5156,115 @@ int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz) #endif /* WC_RSA_NONBLOCK_TIME */ #endif /* WC_RSA_NONBLOCK */ +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) +/* + * Calculate y = d mod(x-1) + */ +static int CalcDX(mp_int* y, mp_int* x, mp_int* d) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + mp_int m[1]; +#else + mp_int* m = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_WOLF_BIGINT); + if (m == NULL) + return MEMORY_E; +#endif + + err = mp_init(m); + if (err == MP_OKAY) { + err = mp_sub_d(x, 1, m); + if (err == MP_OKAY) + err = mp_mod(d, m, y); + mp_forcezero(m); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(m, NULL, DYNAMIC_TYPE_WOLF_BIGINT); +#endif + + return err; +} +#endif + +int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, const byte* d, word32 dSz, + const byte* u, word32 uSz, const byte* p, word32 pSz, + const byte* q, word32 qSz, const byte* dP, word32 dPSz, + const byte* dQ, word32 dQSz, RsaKey* key) +{ + int err = MP_OKAY; + + if (n == NULL || nSz == 0 || e == NULL || eSz == 0 + || d == NULL || dSz == 0 || p == NULL || pSz == 0 + || q == NULL || qSz == 0 || key == NULL) { + err = BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if (err == MP_OKAY) { + if ((u == NULL || uSz == 0) + || (dP != NULL && dPSz == 0) + || (dQ != NULL && dQSz == 0)) { + err = BAD_FUNC_ARG; + } + } +#else + (void)u; + (void)uSz; + (void)dP; + (void)dPSz; + (void)dQ; + (void)dQSz; +#endif + + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->n, n, nSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->e, e, eSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->d, d, dSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->p, p, pSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->q, q, qSz); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->u, u, uSz); + if (err == MP_OKAY) { + if (dP != NULL) + err = mp_read_unsigned_bin(&key->dP, dP, dPSz); + else + err = CalcDX(&key->dP, &key->p, &key->d); + } + if (err == MP_OKAY) { + if (dQ != NULL) + err = mp_read_unsigned_bin(&key->dQ, dQ, dQSz); + else + err = CalcDX(&key->dQ, &key->q, &key->d); + } +#endif + + if (err == MP_OKAY) { + key->type = RSA_PRIVATE; + } + else { + mp_clear(&key->n); + mp_clear(&key->e); + mp_clear(&key->d); + mp_clear(&key->p); + mp_clear(&key->q); +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_clear(&key->u); + mp_clear(&key->dP); + mp_clear(&key->dQ); +#endif + } + + return err; +} +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + #endif /* NO_RSA */ diff --git a/src/wolfcrypt/src/sakke.c b/src/wolfcrypt/src/sakke.c index eb0f932..c87963a 100644 --- a/src/wolfcrypt/src/sakke.c +++ b/src/wolfcrypt/src/sakke.c @@ -327,14 +327,18 @@ static int sakke_load_base_point(SakkeKey* key) static int sakke_mulmod_base(SakkeKey* key, const mp_int* n, ecc_point* res, int map) { - int err = NOT_COMPILED_IN; + int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SP_1024 if ((key->ecc.idx != ECC_CUSTOM_IDX) && (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { err = sp_ecc_mulmod_base_1024(n, res, map, key->heap); } + else #endif + { + err = NOT_COMPILED_IN; + } return err; } @@ -353,14 +357,18 @@ static int sakke_mulmod_base(SakkeKey* key, const mp_int* n, ecc_point* res, static int sakke_mulmod_base_add(SakkeKey* key, const mp_int* n, const ecc_point* a, ecc_point* res, int map) { - int err = NOT_COMPILED_IN; + int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SP_1024 if ((key->ecc.idx != ECC_CUSTOM_IDX) && (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { err = sp_ecc_mulmod_base_add_1024(n, a, 0, res, map, key->heap); } + else #endif + { + err = NOT_COMPILED_IN; + } return err; } @@ -440,7 +448,7 @@ static int sakke_mulmod_base_add(SakkeKey* key, const mp_int* n, ecc_point* a, static int sakke_mulmod_point(SakkeKey* key, const mp_int* n, const ecc_point* p, byte* table, ecc_point* res, int map) { - int err = NOT_COMPILED_IN; + int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SP_1024 if ((key->ecc.idx != ECC_CUSTOM_IDX) && @@ -452,7 +460,11 @@ static int sakke_mulmod_point(SakkeKey* key, const mp_int* n, err = sp_ecc_mulmod_table_1024(n, p, table, res, map, key->heap); } } + else #endif + { + err = NOT_COMPILED_IN; + } return err; } @@ -1351,7 +1363,7 @@ int wc_GenerateSakkeRskTable(const SakkeKey* key, const ecc_point* rsk, static int sakke_pairing(const SakkeKey* key, const ecc_point* p, const ecc_point* q, mp_int* r, const byte* table, word32 len) { - int err = NOT_COMPILED_IN; + int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SP_1024 if ((key->ecc.idx != ECC_CUSTOM_IDX) && @@ -1363,6 +1375,9 @@ static int sakke_pairing(const SakkeKey* key, const ecc_point* p, err = sp_Pairing_precomp_1024(p, q, r, table, len); } } + else { + err = NOT_COMPILED_IN; + } #else (void)key; (void)p; @@ -1370,6 +1385,7 @@ static int sakke_pairing(const SakkeKey* key, const ecc_point* p, (void)r; (void)table; (void)len; + err = NOT_COMPILED_IN; #endif return err; @@ -2523,14 +2539,18 @@ int wc_GetSakkeAuthSize(SakkeKey* key, word16* authSz) static int sakke_modexp(const SakkeKey* key, const mp_int* b, mp_int* e, mp_int* r) { - int err = NOT_COMPILED_IN; + int err = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SP_1024 if ((key->ecc.idx != ECC_CUSTOM_IDX) && (ecc_sets[key->ecc.idx].id == ECC_SAKKE_1)) { err = sp_ModExp_Fp_star_1024(b, e, r); } + else #endif + { + err = NOT_COMPILED_IN; + } return err; } @@ -6551,7 +6571,7 @@ int wc_SetSakkePointITable(SakkeKey* key, byte* table, word32 len) #ifdef WOLFSSL_HAVE_SP_ECC if (err == 0) { err = sp_ecc_gen_table_1024(key->i.i, NULL, &sz, NULL); - if (err == LENGTH_ONLY_E) { + if (err == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { err = 0; } } diff --git a/src/wolfcrypt/src/sha.c b/src/wolfcrypt/src/sha.c index 6999079..1892de4 100644 --- a/src/wolfcrypt/src/sha.c +++ b/src/wolfcrypt/src/sha.c @@ -36,13 +36,13 @@ #if !defined(NO_SHA) -#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$j") - #pragma const_seg(".fipsB$j") + #pragma code_seg(".fipsA$k") + #pragma const_seg(".fipsB$k") #endif #endif @@ -118,6 +118,14 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_sha_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000013 }; + int wolfCrypt_FIPS_SHA_sanity(void) + { + return 0; + } +#endif /* Hardware Acceleration */ #if defined(WOLFSSL_PIC32MZ_HASH) @@ -598,7 +606,7 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) #ifdef WOLF_CRYPTO_CB if (sha->devId != INVALID_DEVID) { ret = wc_CryptoCb_ShaHash(sha, data, len, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; ret = 0; /* reset ret */ /* fall-through when unavailable */ @@ -817,7 +825,7 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash) #ifdef WOLF_CRYPTO_CB if (sha->devId != INVALID_DEVID) { ret = wc_CryptoCb_ShaHash(sha, NULL, 0, hash); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } diff --git a/src/wolfcrypt/src/sha256.c b/src/wolfcrypt/src/sha256.c index 0025e85..f955dff 100644 --- a/src/wolfcrypt/src/sha256.c +++ b/src/wolfcrypt/src/sha256.c @@ -71,8 +71,8 @@ on the specific device platform. #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$d") - #pragma const_seg(".fipsB$d") + #pragma code_seg(".fipsA$l") + #pragma const_seg(".fipsB$l") #endif #endif @@ -141,6 +141,14 @@ on the specific device platform. #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_sha256_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000014 }; + int wolfCrypt_FIPS_SHA256_sanity(void) + { + return 0; + } +#endif #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) #if defined(__GNUC__) && ((__GNUC__ < 4) || \ @@ -168,8 +176,7 @@ on the specific device platform. #define HAVE_INTEL_RORX #endif - -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) +#if defined(LITTLE_ENDIAN_ORDER) #if ( defined(CONFIG_IDF_TARGET_ESP32C2) || \ defined(CONFIG_IDF_TARGET_ESP8684) || \ defined(CONFIG_IDF_TARGET_ESP32C3) || \ @@ -182,20 +189,28 @@ on the specific device platform. * depending on if HW is active or not. */ #define SHA256_REV_BYTES(ctx) \ (esp_sha_need_byte_reversal(ctx)) + #elif defined(FREESCALE_MMCAU_SHA) + #define SHA256_REV_BYTES(ctx) 1 /* reverse needed on final */ #endif #endif #ifndef SHA256_REV_BYTES - #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(LITTLE_ENDIAN_ORDER) #define SHA256_REV_BYTES(ctx) 1 #else #define SHA256_REV_BYTES(ctx) 0 #endif #endif -#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) && \ +#if defined(LITTLE_ENDIAN_ORDER) && \ defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) - #define SHA256_UPDATE_REV_BYTES(ctx) \ - (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA256_UPDATE_REV_BYTES(ctx) (sha256->sha_method == SHA256_C) + #else + #define SHA256_UPDATE_REV_BYTES(ctx) \ + (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif +#elif defined(FREESCALE_MMCAU_SHA) + #define SHA256_UPDATE_REV_BYTES(ctx) 0 /* reverse not needed on update */ #else #define SHA256_UPDATE_REV_BYTES(ctx) SHA256_REV_BYTES(ctx) #endif @@ -217,6 +232,15 @@ on the specific device platform. (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \ !defined(WOLFSSL_RENESAS_RX64_HASH) +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) +#ifdef WC_C_DYNAMIC_FALLBACK + #define SHA256_SETTRANSFORM_ARGS int *sha_method +#else + #define SHA256_SETTRANSFORM_ARGS void +#endif +static void Sha256_SetTransform(SHA256_SETTRANSFORM_ARGS); +#endif static int InitSha256(wc_Sha256* sha256) { @@ -242,6 +266,17 @@ static int InitSha256(wc_Sha256* sha256) sha256->used = 0; #endif +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + /* choose best Transform function under this runtime environment */ +#ifdef WC_C_DYNAMIC_FALLBACK + sha256->sha_method = 0; + Sha256_SetTransform(&sha256->sha_method); +#else + Sha256_SetTransform(); +#endif +#endif + #ifdef WOLF_CRYPTO_CB sha256->devId = wc_CryptoCb_DefaultDevID(); #endif @@ -360,25 +395,205 @@ static int InitSha256(wc_Sha256* sha256) } /* extern "C" */ #endif + static word32 intel_flags = 0; + +#if defined(WC_C_DYNAMIC_FALLBACK) && !defined(WC_NO_INTERNAL_FUNCTION_POINTERS) + #define WC_NO_INTERNAL_FUNCTION_POINTERS +#endif + +#ifdef WC_NO_INTERNAL_FUNCTION_POINTERS + + enum sha_methods { SHA256_UNSET = 0, SHA256_AVX1_SHA, SHA256_AVX2, + SHA256_AVX1_RORX, SHA256_AVX1_NOSHA, SHA256_AVX2_RORX, + SHA256_SSE2, SHA256_C }; + +#ifndef WC_C_DYNAMIC_FALLBACK + static enum sha_methods sha_method = SHA256_UNSET; +#endif + + static void Sha256_SetTransform(SHA256_SETTRANSFORM_ARGS) + { + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA_METHOD (*sha_method) + #else + #define SHA_METHOD sha_method + #endif + if (SHA_METHOD != SHA256_UNSET) + return; + + #ifdef WC_C_DYNAMIC_FALLBACK + if (! CAN_SAVE_VECTOR_REGISTERS()) { + SHA_METHOD = SHA256_C; + return; + } + #endif + + if (intel_flags == 0) + intel_flags = cpuid_get_flags(); + + if (IS_INTEL_SHA(intel_flags)) { + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + SHA_METHOD = SHA256_AVX1_SHA; + } + else + #endif + { + SHA_METHOD = SHA256_SSE2; + } + } + else + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + SHA_METHOD = SHA256_AVX2_RORX; + } + else + #endif + { + SHA_METHOD = SHA256_AVX2; + } + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + SHA_METHOD = SHA256_AVX1_RORX; + } + else + #endif + { + SHA_METHOD = SHA256_AVX1_NOSHA; + } + } + else + #endif + { + SHA_METHOD = SHA256_C; + } + #undef SHA_METHOD + } + + static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) { + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA_METHOD (S->sha_method) + #else + #define SHA_METHOD sha_method + #endif + int ret; + + if (SHA_METHOD == SHA256_C) + return Transform_Sha256(S, D); + SAVE_VECTOR_REGISTERS(return _svr_ret;); + switch (SHA_METHOD) { + case SHA256_AVX2: + ret = Transform_Sha256_AVX2(S, D); + break; + case SHA256_AVX2_RORX: + ret = Transform_Sha256_AVX2_RORX(S, D); + break; + case SHA256_AVX1_SHA: + ret = Transform_Sha256_AVX1_Sha(S, D); + break; + case SHA256_AVX1_NOSHA: + ret = Transform_Sha256_AVX1(S, D); + break; + case SHA256_AVX1_RORX: + ret = Transform_Sha256_AVX1_RORX(S, D); + break; + case SHA256_SSE2: + ret = Transform_Sha256_SSE2_Sha(S, D); + break; + case SHA256_C: + case SHA256_UNSET: + default: + ret = Transform_Sha256(S, D); + break; + } + RESTORE_VECTOR_REGISTERS(); + return ret; + #undef SHA_METHOD + } +#define XTRANSFORM(...) inline_XTRANSFORM(__VA_ARGS__) + + static WC_INLINE int inline_XTRANSFORM_LEN(wc_Sha256* S, const byte* D, word32 L) { + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA_METHOD (S->sha_method) + #else + #define SHA_METHOD sha_method + #endif + int ret; + SAVE_VECTOR_REGISTERS(return _svr_ret;); + switch (SHA_METHOD) { + case SHA256_AVX2: + ret = Transform_Sha256_AVX2_Len(S, D, L); + break; + case SHA256_AVX2_RORX: + ret = Transform_Sha256_AVX2_RORX_Len(S, D, L); + break; + case SHA256_AVX1_SHA: + ret = Transform_Sha256_AVX1_Sha_Len(S, D, L); + break; + case SHA256_AVX1_NOSHA: + ret = Transform_Sha256_AVX1_Len(S, D, L); + break; + case SHA256_AVX1_RORX: + ret = Transform_Sha256_AVX1_RORX_Len(S, D, L); + break; + case SHA256_SSE2: + ret = Transform_Sha256_SSE2_Sha_Len(S, D, L); + break; + case SHA256_C: + case SHA256_UNSET: + default: + ret = 0; + break; + } + RESTORE_VECTOR_REGISTERS(); + return ret; + #undef SHA_METHOD + } +#define XTRANSFORM_LEN(...) inline_XTRANSFORM_LEN(__VA_ARGS__) + +#else /* !WC_NO_INTERNAL_FUNCTION_POINTERS */ + static int (*Transform_Sha256_p)(wc_Sha256* sha256, const byte* data); /* = _Transform_Sha256 */ static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, const byte* data, word32 len); /* = NULL */ static int transform_check = 0; - static word32 intel_flags; static int Transform_Sha256_is_vectorized = 0; static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) { int ret; + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha256_is_vectorized) + SAVE_VECTOR_REGISTERS(return _svr_ret;); + #endif ret = (*Transform_Sha256_p)(S, D); + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha256_is_vectorized) + RESTORE_VECTOR_REGISTERS(); + #endif return ret; } #define XTRANSFORM(...) inline_XTRANSFORM(__VA_ARGS__) static WC_INLINE int inline_XTRANSFORM_LEN(wc_Sha256* S, const byte* D, word32 L) { int ret; + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha256_is_vectorized) + SAVE_VECTOR_REGISTERS(return _svr_ret;); + #endif ret = (*Transform_Sha256_Len_p)(S, D, L); + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha256_is_vectorized) + RESTORE_VECTOR_REGISTERS(); + #endif return ret; } #define XTRANSFORM_LEN(...) inline_XTRANSFORM_LEN(__VA_ARGS__) @@ -452,6 +667,8 @@ static int InitSha256(wc_Sha256* sha256) transform_check = 1; } +#endif /* !WC_NO_INTERNAL_FUNCTION_POINTERS */ + #if !defined(WOLFSSL_KCAPI_HASH) int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) { @@ -472,9 +689,6 @@ static int InitSha256(wc_Sha256* sha256) if (ret != 0) return ret; - /* choose best Transform function under this runtime environment */ - Sha256_SetTransform(); - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) ret = wolfAsync_DevCtxInit(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); @@ -617,7 +831,14 @@ static int InitSha256(wc_Sha256* sha256) { int ret = 0; - if (sha256 == NULL || (data == NULL && len > 0)) { + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { return BAD_FUNC_ARG; } @@ -668,6 +889,17 @@ static int InitSha256(wc_Sha256* sha256) int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) { + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { + return BAD_FUNC_ARG; + } + return se050_hash_update(&sha256->se050Ctx, data, len); } @@ -1151,7 +1383,15 @@ static int InitSha256(wc_Sha256* sha256) #ifdef XTRANSFORM_LEN #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha256->sha_method != SHA256_C) + #elif defined(WC_NO_INTERNAL_FUNCTION_POINTERS) + if (sha_method != SHA256_C) + #else if (Transform_Sha256_Len_p != NULL) + #endif + #endif { if (len >= WC_SHA256_BLOCK_SIZE) { @@ -1259,7 +1499,7 @@ static int InitSha256(wc_Sha256* sha256) #endif { int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1387,8 +1627,12 @@ static int InitSha256(wc_Sha256* sha256) /* Kinetis requires only these bytes reversed */ #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha256->sha_method != SHA256_C) + #else if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags)) #endif + #endif { ByteReverseWords( &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], @@ -1456,7 +1700,7 @@ static int InitSha256(wc_Sha256* sha256) #endif { ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1732,11 +1976,19 @@ static int InitSha256(wc_Sha256* sha256) sha224->loLen = 0; sha224->hiLen = 0; + #ifdef WC_C_DYNAMIC_FALLBACK + sha224->sha_method = 0; + #endif + #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) /* choose best Transform function under this runtime environment */ + #ifdef WC_C_DYNAMIC_FALLBACK + Sha256_SetTransform(&sha224->sha_method); + #else Sha256_SetTransform(); #endif + #endif #ifdef WOLFSSL_HASH_FLAGS sha224->flags = 0; #endif diff --git a/src/wolfcrypt/src/sha3.c b/src/wolfcrypt/src/sha3.c index 096566d..99f739b 100644 --- a/src/wolfcrypt/src/sha3.c +++ b/src/wolfcrypt/src/sha3.c @@ -29,13 +29,13 @@ #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_XILINX_CRYPT) && \ !defined(WOLFSSL_AFALG_XILINX_SHA3) -#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$l") - #pragma const_seg(".fipsB$l") + #pragma code_seg(".fipsA$n") + #pragma const_seg(".fipsB$n") #endif #endif @@ -43,6 +43,9 @@ #include #include +#ifdef WOLF_CRYPTO_CB + #include +#endif #ifdef NO_INLINE #include #else @@ -50,17 +53,33 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_sha3_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000016 }; + int wolfCrypt_FIPS_SHA3_sanity(void) + { + return 0; + } +#endif -#if !defined(WOLFSSL_ARMASM) || !defined(WOLFSSL_ARMASM_CRYPTO_SHA3) +#if !defined(WOLFSSL_ARMASM) || (!defined(__arm__) && \ + !defined(WOLFSSL_ARMASM_CRYPTO_SHA3)) #ifdef USE_INTEL_SPEEDUP #include word32 cpuid_flags; int cpuid_flags_set = 0; +#ifdef WC_C_DYNAMIC_FALLBACK + #define SHA3_BLOCK (sha3->sha3_block) + #define SHA3_BLOCK_N (sha3->sha3_block_n) +#else void (*sha3_block)(word64 *s) = NULL; void (*sha3_block_n)(word64 *s, const byte* data, word32 n, word64 c) = NULL; + #define SHA3_BLOCK sha3_block + #define SHA3_BLOCK_N sha3_block_n +#endif #endif #ifdef WOLFSSL_SHA3_SMALL @@ -614,15 +633,26 @@ static int InitSha3(wc_Sha3* sha3) if (!cpuid_flags_set) { cpuid_flags = cpuid_get_flags(); cpuid_flags_set = 1; +#ifdef WC_C_DYNAMIC_FALLBACK + } + { + if (! CAN_SAVE_VECTOR_REGISTERS()) { + SHA3_BLOCK = BlockSha3; + SHA3_BLOCK_N = NULL; + } + else +#endif if (IS_INTEL_BMI1(cpuid_flags) && IS_INTEL_BMI2(cpuid_flags)) { - sha3_block = sha3_block_bmi2; - sha3_block_n = sha3_block_n_bmi2; + SHA3_BLOCK = sha3_block_bmi2; + SHA3_BLOCK_N = sha3_block_n_bmi2; } else if (IS_INTEL_AVX2(cpuid_flags)) { - sha3_block = sha3_block_avx2; + SHA3_BLOCK = sha3_block_avx2; + SHA3_BLOCK_N = NULL; } else { - sha3_block = BlockSha3; + SHA3_BLOCK = BlockSha3; + SHA3_BLOCK_N = NULL; } } #endif @@ -643,6 +673,10 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) word32 i; word32 blocks; +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#endif if (sha3->i > 0) { byte *t; byte l = (byte)(p * 8 - sha3->i); @@ -663,7 +697,7 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); } #ifdef USE_INTEL_SPEEDUP - (*sha3_block)(sha3->s); + (*SHA3_BLOCK)(sha3->s); #else BlockSha3(sha3->s); #endif @@ -672,8 +706,8 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) } blocks = len / (p * 8); #ifdef USE_INTEL_SPEEDUP - if ((sha3_block_n != NULL) && (blocks > 0)) { - (*sha3_block_n)(sha3->s, data, blocks, p * 8); + if ((SHA3_BLOCK_N != NULL) && (blocks > 0)) { + (*SHA3_BLOCK_N)(sha3->s, data, blocks, p * 8); len -= blocks * (p * 8); data += blocks * (p * 8); blocks = 0; @@ -684,13 +718,17 @@ static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) sha3->s[i] ^= Load64Unaligned(data + 8 * i); } #ifdef USE_INTEL_SPEEDUP - (*sha3_block)(sha3->s); + (*SHA3_BLOCK)(sha3->s); #else BlockSha3(sha3->s); #endif len -= p * 8; data += p * 8; } +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + RESTORE_VECTOR_REGISTERS(); +#endif XMEMCPY(sha3->t, data, len); sha3->i += (byte)len; @@ -724,9 +762,15 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l) for (i = 0; i < p; i++) { sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); } + +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#endif + for (j = 0; l - j >= rate; j += rate) { #ifdef USE_INTEL_SPEEDUP - (*sha3_block)(sha3->s); + (*SHA3_BLOCK)(sha3->s); #else BlockSha3(sha3->s); #endif @@ -738,7 +782,7 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l) } if (j != l) { #ifdef USE_INTEL_SPEEDUP - (*sha3_block)(sha3->s); + (*SHA3_BLOCK)(sha3->s); #else BlockSha3(sha3->s); #endif @@ -747,6 +791,11 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l) #endif XMEMCPY(hash + j, sha3->s, l - j); } +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + RESTORE_VECTOR_REGISTERS(); +#endif + return 0; } @@ -772,10 +821,12 @@ static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId) #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) ret = wolfAsync_DevCtxInit(&sha3->asyncDev, WOLFSSL_ASYNC_MARKER_SHA3, sha3->heap, devId); -#else - (void)devId; +#elif defined(WOLF_CRYPTO_CB) + sha3->devId = devId; #endif /* WOLFSSL_ASYNC_CRYPT */ + (void)devId; + return ret; } @@ -800,13 +851,32 @@ static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) return 0; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (sha3->devId != INVALID_DEVID) + #endif + { + int hash_type = WC_HASH_TYPE_NONE; + switch (p) { + case WC_SHA3_224_COUNT: hash_type = WC_HASH_TYPE_SHA3_224; break; + case WC_SHA3_256_COUNT: hash_type = WC_HASH_TYPE_SHA3_256; break; + case WC_SHA3_384_COUNT: hash_type = WC_HASH_TYPE_SHA3_384; break; + case WC_SHA3_512_COUNT: hash_type = WC_HASH_TYPE_SHA3_512; break; + default: return BAD_FUNC_ARG; + } + ret = wc_CryptoCb_Sha3Hash(sha3, hash_type, data, len, NULL); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + } +#endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { #if defined(HAVE_INTEL_QA) && defined(QAT_V2) /* QAT only supports SHA3_256 */ if (p == WC_SHA3_256_COUNT) { ret = IntelQaSymSha3(&sha3->asyncDev, NULL, data, len); - if (ret != NOT_COMPILED_IN) + if (ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) return ret; /* fall-through when unavailable */ } @@ -835,6 +905,25 @@ static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len) return BAD_FUNC_ARG; } +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_FIND + if (sha3->devId != INVALID_DEVID) + #endif + { + int hash_type = WC_HASH_TYPE_NONE; + switch (p) { + case WC_SHA3_224_COUNT: hash_type = WC_HASH_TYPE_SHA3_224; break; + case WC_SHA3_256_COUNT: hash_type = WC_HASH_TYPE_SHA3_256; break; + case WC_SHA3_384_COUNT: hash_type = WC_HASH_TYPE_SHA3_384; break; + case WC_SHA3_512_COUNT: hash_type = WC_HASH_TYPE_SHA3_512; break; + default: return BAD_FUNC_ARG; + } + ret = wc_CryptoCb_Sha3Hash(sha3, hash_type, NULL, 0, hash); + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) + return ret; + /* fall-through when unavailable */ + } +#endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { #if defined(HAVE_INTEL_QA) && defined(QAT_V2) @@ -842,7 +931,7 @@ static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len) /* QAT SHA-3 only supported on v2 (8970 or later cards) */ if (len == WC_SHA3_256_DIGEST_SIZE) { ret = IntelQaSymSha3(&sha3->asyncDev, hash, NULL, len); - if (ret != NOT_COMPILED_IN) + if (ret != WC_NO_ERR_TRACE(NOT_COMPILED_IN)) return ret; /* fall-through when unavailable */ } @@ -1311,6 +1400,13 @@ int wc_Shake128_Absorb(wc_Shake* shake, const byte* data, word32 len) return ret; } +#ifdef WC_C_DYNAMIC_FALLBACK + #undef SHA3_BLOCK + #undef SHA3_BLOCK_N + #define SHA3_BLOCK (shake->sha3_block) + #define SHA3_BLOCK_N (shake->sha3_block_n) +#endif + /* Squeeze the state to produce pseudo-random output. * * shake wc_Shake object holding state. @@ -1320,9 +1416,13 @@ int wc_Shake128_Absorb(wc_Shake* shake, const byte* data, word32 len) */ int wc_Shake128_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt) { +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#endif for (; (blockCnt > 0); blockCnt--) { #ifdef USE_INTEL_SPEEDUP - (*sha3_block)(shake->s); + (*SHA3_BLOCK)(shake->s); #else BlockSha3(shake->s); #endif @@ -1333,6 +1433,10 @@ int wc_Shake128_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt) #endif out += WC_SHA3_128_COUNT * 8; } +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + RESTORE_VECTOR_REGISTERS(); +#endif return 0; } @@ -1450,9 +1554,13 @@ int wc_Shake256_Absorb(wc_Shake* shake, const byte* data, word32 len) */ int wc_Shake256_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt) { +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + SAVE_VECTOR_REGISTERS(return _svr_ret;); +#endif for (; (blockCnt > 0); blockCnt--) { #ifdef USE_INTEL_SPEEDUP - (*sha3_block)(shake->s); + (*SHA3_BLOCK)(shake->s); #else BlockSha3(shake->s); #endif @@ -1463,6 +1571,10 @@ int wc_Shake256_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt) #endif out += WC_SHA3_256_COUNT * 8; } +#if defined(WOLFSSL_LINUXKM) && defined(USE_INTEL_SPEEDUP) + if (SHA3_BLOCK == sha3_block_avx2) + RESTORE_VECTOR_REGISTERS(); +#endif return 0; } diff --git a/src/wolfcrypt/src/sha512.c b/src/wolfcrypt/src/sha512.c index 91bf1e5..88c38f0 100644 --- a/src/wolfcrypt/src/sha512.c +++ b/src/wolfcrypt/src/sha512.c @@ -50,8 +50,8 @@ #define FIPS_NO_WRAPPERS #ifdef USE_WINDOWS_API - #pragma code_seg(".fipsA$k") - #pragma const_seg(".fipsB$k") + #pragma code_seg(".fipsA$m") + #pragma const_seg(".fipsB$m") #endif #endif @@ -82,11 +82,20 @@ #include #endif +#if FIPS_VERSION3_GE(6,0,0) + const unsigned int wolfCrypt_FIPS_sha512_ro_sanity[2] = + { 0x1a2b3c4d, 0x00000015 }; + int wolfCrypt_FIPS_SHA512_sanity(void) + { + return 0; + } +#endif + + #if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH) #include #endif - #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) #if defined(__GNUC__) && ((__GNUC__ < 4) || \ (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) @@ -157,6 +166,17 @@ } int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) { + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { + return BAD_FUNC_ARG; + } + return se050_hash_update(&sha512->se050Ctx, data, len); } int wc_Sha512Final(wc_Sha512* sha512, byte* hash) @@ -196,6 +216,16 @@ #ifdef WOLFSSL_SHA512 +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) +#ifdef WC_C_DYNAMIC_FALLBACK + #define SHA512_SETTRANSFORM_ARGS int *sha_method +#else + #define SHA512_SETTRANSFORM_ARGS void +#endif +static void Sha512_SetTransform(SHA512_SETTRANSFORM_ARGS); +#endif + static int InitSha512(wc_Sha512* sha512) { if (sha512 == NULL) @@ -214,6 +244,16 @@ static int InitSha512(wc_Sha512* sha512) sha512->loLen = 0; sha512->hiLen = 0; +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) +#ifdef WC_C_DYNAMIC_FALLBACK + sha512->sha_method = 0; + Sha512_SetTransform(&sha512->sha_method); +#else + Sha512_SetTransform(); +#endif +#endif + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) @@ -255,6 +295,16 @@ static int InitSha512_224(wc_Sha512* sha512) sha512->loLen = 0; sha512->hiLen = 0; +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) +#ifdef WC_C_DYNAMIC_FALLBACK + sha512->sha_method = 0; + Sha512_SetTransform(&sha512->sha_method); +#else + Sha512_SetTransform(); +#endif +#endif + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* HW needs to be carefully initialized, taking into account soft copy. @@ -298,6 +348,16 @@ static int InitSha512_256(wc_Sha512* sha512) sha512->loLen = 0; sha512->hiLen = 0; +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) +#ifdef WC_C_DYNAMIC_FALLBACK + sha512->sha_method = 0; + Sha512_SetTransform(&sha512->sha_method); +#else + Sha512_SetTransform(); +#endif +#endif + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) /* HW needs to be carefully initialized, taking into account soft copy. @@ -415,21 +475,174 @@ static int InitSha512_256(wc_Sha512* sha512) } /* extern "C" */ #endif + static word32 intel_flags = 0; + +#if defined(WC_C_DYNAMIC_FALLBACK) && !defined(WC_NO_INTERNAL_FUNCTION_POINTERS) + #define WC_NO_INTERNAL_FUNCTION_POINTERS +#endif + static int _Transform_Sha512(wc_Sha512 *sha512); + +#ifdef WC_NO_INTERNAL_FUNCTION_POINTERS + + enum sha_methods { SHA512_UNSET = 0, SHA512_AVX1, SHA512_AVX2, + SHA512_AVX1_RORX, SHA512_AVX2_RORX, SHA512_C }; + +#ifndef WC_C_DYNAMIC_FALLBACK + static enum sha_methods sha_method = SHA512_UNSET; +#endif + + static void Sha512_SetTransform(SHA512_SETTRANSFORM_ARGS) + { + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA_METHOD (*sha_method) + #else + #define SHA_METHOD sha_method + #endif + if (SHA_METHOD != SHA512_UNSET) + return; + + #ifdef WC_C_DYNAMIC_FALLBACK + if (! CAN_SAVE_VECTOR_REGISTERS()) { + SHA_METHOD = SHA512_C; + return; + } + #endif + + if (intel_flags == 0) + intel_flags = cpuid_get_flags(); + + #if defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX2(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + SHA_METHOD = SHA512_AVX2_RORX; + } + else + #endif + { + SHA_METHOD = SHA512_AVX2; + } + } + else + #endif + #if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + SHA_METHOD = SHA512_AVX1_RORX; + } + else + #endif + { + SHA_METHOD = SHA512_AVX1; + } + } + else + #endif + { + SHA_METHOD = SHA512_C; + } + #undef SHA_METHOD + } + + static WC_INLINE int Transform_Sha512(wc_Sha512 *sha512) { + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA_METHOD (sha512->sha_method) + #else + #define SHA_METHOD sha_method + #endif + int ret; + if (SHA_METHOD == SHA512_C) + return _Transform_Sha512(sha512); + SAVE_VECTOR_REGISTERS(return _svr_ret;); + switch (SHA_METHOD) { + case SHA512_AVX2: + ret = Transform_Sha512_AVX2(sha512); + break; + case SHA512_AVX2_RORX: + ret = Transform_Sha512_AVX2_RORX(sha512); + break; + case SHA512_AVX1: + ret = Transform_Sha512_AVX1(sha512); + break; + case SHA512_AVX1_RORX: + ret = Transform_Sha512_AVX1_RORX(sha512); + break; + case SHA512_C: + case SHA512_UNSET: + default: + ret = _Transform_Sha512(sha512); + break; + } + RESTORE_VECTOR_REGISTERS(); + return ret; + #undef SHA_METHOD + } + + static WC_INLINE int Transform_Sha512_Len(wc_Sha512 *sha512, word32 len) { + #ifdef WC_C_DYNAMIC_FALLBACK + #define SHA_METHOD (sha512->sha_method) + #else + #define SHA_METHOD sha_method + #endif + int ret; + SAVE_VECTOR_REGISTERS(return _svr_ret;); + switch (SHA_METHOD) { + case SHA512_AVX2: + ret = Transform_Sha512_AVX2_Len(sha512, len); + break; + case SHA512_AVX2_RORX: + ret = Transform_Sha512_AVX2_RORX_Len(sha512, len); + break; + case SHA512_AVX1: + ret = Transform_Sha512_AVX1_Len(sha512, len); + break; + case SHA512_AVX1_RORX: + ret = Transform_Sha512_AVX1_RORX_Len(sha512, len); + break; + case SHA512_C: + case SHA512_UNSET: + default: + ret = 0; + break; + } + RESTORE_VECTOR_REGISTERS(); + return ret; + #undef SHA_METHOD + } + +#else /* !WC_NO_INTERNAL_FUNCTION_POINTERS */ + static int (*Transform_Sha512_p)(wc_Sha512* sha512) = _Transform_Sha512; static int (*Transform_Sha512_Len_p)(wc_Sha512* sha512, word32 len) = NULL; static int transform_check = 0; - static word32 intel_flags; static int Transform_Sha512_is_vectorized = 0; static WC_INLINE int Transform_Sha512(wc_Sha512 *sha512) { int ret; + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha512_is_vectorized) + SAVE_VECTOR_REGISTERS(return _svr_ret;); + #endif ret = (*Transform_Sha512_p)(sha512); + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha512_is_vectorized) + RESTORE_VECTOR_REGISTERS(); + #endif return ret; } static WC_INLINE int Transform_Sha512_Len(wc_Sha512 *sha512, word32 len) { int ret; + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha512_is_vectorized) + SAVE_VECTOR_REGISTERS(return _svr_ret;); + #endif ret = (*Transform_Sha512_Len_p)(sha512, len); + #ifdef WOLFSSL_LINUXKM + if (Transform_Sha512_is_vectorized) + RESTORE_VECTOR_REGISTERS(); + #endif return ret; } @@ -485,6 +698,8 @@ static int InitSha512_256(wc_Sha512* sha512) transform_check = 1; } +#endif /* !WC_NO_INTERNAL_FUNCTION_POINTERS */ + #else #define Transform_Sha512(sha512) _Transform_Sha512(sha512) @@ -495,7 +710,7 @@ static int InitSha512_256(wc_Sha512* sha512) static int InitSha512_Family(wc_Sha512* sha512, void* heap, int devId, int (*initfp)(wc_Sha512*)) { - int ret = 0; + int ret = 0; if (sha512 == NULL) { return BAD_FUNC_ARG; @@ -516,10 +731,6 @@ static int InitSha512_Family(wc_Sha512* sha512, void* heap, int devId, if (ret != 0) return ret; -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ - (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) - Sha512_SetTransform(); -#endif #ifdef WOLFSSL_HASH_KEEP sha512->msg = NULL; sha512->len = 0; @@ -759,7 +970,11 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le #if defined(LITTLE_ENDIAN_ORDER) #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha512->sha_method == SHA512_C) + #else if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif #endif { #if !defined(WOLFSSL_ESP32_CRYPT) || \ @@ -775,15 +990,17 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) ret = Transform_Sha512(sha512); #else - if(sha512->ctx.mode == ESP32_SHA_INIT) { + if (sha512->ctx.mode == ESP32_SHA_INIT) { esp_sha_try_hw_lock(&sha512->ctx); } - ret = esp_sha512_process(sha512); - if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + if (sha512->ctx.mode == ESP32_SHA_SW) { ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_BLOCK_SIZE); ret = Transform_Sha512(sha512); } + else { + ret = esp_sha512_process(sha512); + } #endif if (ret == 0) sha512->buffLen = 0; @@ -794,7 +1011,16 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) - if (Transform_Sha512_Len_p != NULL) { + + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha512->sha_method != SHA512_C) + #elif defined(WC_NO_INTERNAL_FUNCTION_POINTERS) + if (sha_method != SHA512_C) + #else + if (Transform_Sha512_Len_p != NULL) + #endif + + { word32 blocksLen = len & ~((word32)WC_SHA512_BLOCK_SIZE-1); if (blocksLen > 0) { @@ -819,7 +1045,11 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha512->sha_method == SHA512_C) + #else if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif { ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_BLOCK_SIZE); @@ -879,7 +1109,14 @@ static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 le int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) { - if (sha512 == NULL || (data == NULL && len > 0)) { + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { return BAD_FUNC_ARG; } @@ -889,7 +1126,7 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) #endif { int ret = wc_CryptoCb_Sha512Hash(sha512, data, len, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -949,7 +1186,11 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512) #if defined(LITTLE_ENDIAN_ORDER) #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha512->sha_method == SHA512_C) + #else if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif #endif { @@ -995,7 +1236,11 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512) #if defined(LITTLE_ENDIAN_ORDER) #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha512->sha_method == SHA512_C) + #else if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif #endif #if !defined(WOLFSSL_ESP32_CRYPT) || \ defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ @@ -1014,7 +1259,11 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512) #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha512->sha_method != SHA512_C) + #else if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags)) + #endif ByteReverseWords64(&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]), &(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]), WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE); @@ -1109,7 +1358,7 @@ static int Sha512_Family_Final(wc_Sha512* sha512, byte* hash, size_t digestSz, { byte localHash[WC_SHA512_DIGEST_SIZE]; ret = wc_CryptoCb_Sha512Hash(sha512, NULL, 0, localHash); - if (ret != CRYPTOCB_UNAVAILABLE) { + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { XMEMCPY(hash, localHash, digestSz); return ret; } @@ -1217,15 +1466,14 @@ int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data) return MEMORY_E; #endif -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ - (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) - Sha512_SetTransform(); -#endif - #if defined(LITTLE_ENDIAN_ORDER) #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) + #ifdef WC_C_DYNAMIC_FALLBACK + if (sha->sha_method == SHA512_C) + #else if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif #endif { ByteReverseWords64((word64*)data, (word64*)data, @@ -1269,6 +1517,17 @@ int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data) } int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) { + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { + return BAD_FUNC_ARG; + } + return se050_hash_update(&sha384->se050Ctx, data, len); } @@ -1318,6 +1577,16 @@ static int InitSha384(wc_Sha384* sha384) sha384->loLen = 0; sha384->hiLen = 0; +#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ + (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) +#ifdef WC_C_DYNAMIC_FALLBACK + sha384->sha_method = 0; + Sha512_SetTransform(&sha384->sha_method); +#else + Sha512_SetTransform(); +#endif +#endif + #if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384) /* HW needs to be carefully initialized, taking into account soft copy. @@ -1344,7 +1613,15 @@ static int InitSha384(wc_Sha384* sha384) int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) { - if (sha384 == NULL || (data == NULL && len > 0)) { + + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + if (data == NULL) { return BAD_FUNC_ARG; } @@ -1354,7 +1631,7 @@ int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) #endif { int ret = wc_CryptoCb_Sha384Hash(sha384, data, len, NULL); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1406,7 +1683,7 @@ int wc_Sha384Final(wc_Sha384* sha384, byte* hash) #endif { ret = wc_CryptoCb_Sha384Hash(sha384, NULL, 0, hash); - if (ret != CRYPTOCB_UNAVAILABLE) + if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ } @@ -1460,11 +1737,6 @@ int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) return ret; } -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ - (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) - Sha512_SetTransform(); -#endif - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384, sha384->heap, devId); @@ -1614,7 +1886,8 @@ int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); #endif -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) #if defined(CONFIG_IDF_TARGET_ESP32) if (ret == 0) { ret = esp_sha512_ctx_copy(src, dst); @@ -1899,7 +2172,8 @@ int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); #endif -#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) +#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384) #if defined(CONFIG_IDF_TARGET_ESP32) esp_sha384_ctx_copy(src, dst); #elif defined(CONFIG_IDF_TARGET_ESP32C2) || \ diff --git a/src/wolfcrypt/src/signature.c b/src/wolfcrypt/src/signature.c index efcbd88..33cec70 100644 --- a/src/wolfcrypt/src/signature.c +++ b/src/wolfcrypt/src/signature.c @@ -169,7 +169,7 @@ int wc_SignatureVerifyHash( 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); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); if (ret != 0 || is_valid_sig != 1) { ret = SIG_VERIFY_E; } @@ -226,7 +226,7 @@ int wc_SignatureVerifyHash( #endif if (ret >= 0) ret = wc_RsaSSL_VerifyInline(plain_data, sig_len, &plain_ptr, (RsaKey*)key); - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); if (ret >= 0 && plain_ptr) { if ((word32)ret == hash_len && XMEMCMP(plain_ptr, hash_data, hash_len) == 0) { @@ -395,7 +395,7 @@ int wc_SignatureGenerateHash_ex( if (ret >= 0) ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #else ret = SIG_TYPE_E; #endif @@ -426,7 +426,7 @@ int wc_SignatureGenerateHash_ex( if (ret >= 0) ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); - } while (ret == WC_PENDING_E); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #endif /* WOLFSSL_CRYPTOCELL */ if (ret >= 0) { *sig_len = (word32)ret; diff --git a/src/wolfcrypt/src/sp_cortexm.c b/src/wolfcrypt/src/sp_cortexm.c index 07a3112..8ef1a13 100644 --- a/src/wolfcrypt/src/sp_cortexm.c +++ b/src/wolfcrypt/src/sp_cortexm.c @@ -2211,7 +2211,7 @@ static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x100\n\t" "\n" - "L_sp_2048_add_64_word:\n\t" + "L_sp_2048_add_64_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -2224,9 +2224,9 @@ static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, const sp_digit* b "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_2048_add_64_word\n\t" + "BNE L_sp_2048_add_64_word%=\n\t" #else - "BNE.N L_sp_2048_add_64_word\n\t" + "BNE.N L_sp_2048_add_64_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -2258,7 +2258,7 @@ static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x100\n\t" "\n" - "L_sp_2048_sub_in_pkace_64_word:\n\t" + "L_sp_2048_sub_in_pkace_64_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -2270,9 +2270,9 @@ static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_2048_sub_in_pkace_64_word\n\t" + "BNE L_sp_2048_sub_in_pkace_64_word%=\n\t" #else - "BNE.N L_sp_2048_sub_in_pkace_64_word\n\t" + "BNE.N L_sp_2048_sub_in_pkace_64_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -2312,13 +2312,13 @@ static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_2048_mul_64_outer:\n\t" + "L_sp_2048_mul_64_outer%=:\n\t" "SUBS r3, r5, #0xfc\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_2048_mul_64_inner:\n\t" + "L_sp_2048_mul_64_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -2335,14 +2335,14 @@ static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_mul_64_inner_done\n\t" + "BGT L_sp_2048_mul_64_inner_done%=\n\t" #else - "BGT.N L_sp_2048_mul_64_inner_done\n\t" + "BGT.N L_sp_2048_mul_64_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mul_64_inner\n\t" + "BLT L_sp_2048_mul_64_inner%=\n\t" #else - "BLT.N L_sp_2048_mul_64_inner\n\t" + "BLT.N L_sp_2048_mul_64_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -2351,7 +2351,7 @@ static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_2048_mul_64_inner_done:\n\t" + "L_sp_2048_mul_64_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -2359,9 +2359,9 @@ static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x1f4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_2048_mul_64_outer\n\t" + "BLE L_sp_2048_mul_64_outer%=\n\t" #else - "BLE.N L_sp_2048_mul_64_outer\n\t" + "BLE.N L_sp_2048_mul_64_outer%=\n\t" #endif "LDR lr, [%[a], #252]\n\t" "LDR r11, [%[b], #252]\n\t" @@ -2370,14 +2370,14 @@ static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_2048_mul_64_store:\n\t" + "L_sp_2048_mul_64_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_mul_64_store\n\t" + "BGT L_sp_2048_mul_64_store%=\n\t" #else - "BGT.N L_sp_2048_mul_64_store\n\t" + "BGT.N L_sp_2048_mul_64_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -2410,13 +2410,13 @@ static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_2048_sqr_64_outer:\n\t" + "L_sp_2048_sqr_64_outer%=:\n\t" "SUBS r3, r5, #0xfc\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_2048_sqr_64_inner:\n\t" + "L_sp_2048_sqr_64_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -2430,14 +2430,14 @@ static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_sqr_64_inner_done\n\t" + "BGT L_sp_2048_sqr_64_inner_done%=\n\t" #else - "BGT.N L_sp_2048_sqr_64_inner_done\n\t" + "BGT.N L_sp_2048_sqr_64_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_sqr_64_inner\n\t" + "BLT L_sp_2048_sqr_64_inner%=\n\t" #else - "BLT.N L_sp_2048_sqr_64_inner\n\t" + "BLT.N L_sp_2048_sqr_64_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -2445,7 +2445,7 @@ static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_2048_sqr_64_inner_done:\n\t" + "L_sp_2048_sqr_64_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -2453,9 +2453,9 @@ static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x1f4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_2048_sqr_64_outer\n\t" + "BLE L_sp_2048_sqr_64_outer%=\n\t" #else - "BLE.N L_sp_2048_sqr_64_outer\n\t" + "BLE.N L_sp_2048_sqr_64_outer%=\n\t" #endif "LDR lr, [%[a], #252]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -2463,14 +2463,14 @@ static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_2048_sqr_64_store:\n\t" + "L_sp_2048_sqr_64_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_sqr_64_store\n\t" + "BGT L_sp_2048_sqr_64_store%=\n\t" #else - "BGT.N L_sp_2048_sqr_64_store\n\t" + "BGT.N L_sp_2048_sqr_64_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -2520,7 +2520,7 @@ static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x80\n\t" "\n" - "L_sp_2048_add_32_word:\n\t" + "L_sp_2048_add_32_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -2533,9 +2533,9 @@ static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_2048_add_32_word\n\t" + "BNE L_sp_2048_add_32_word%=\n\t" #else - "BNE.N L_sp_2048_add_32_word\n\t" + "BNE.N L_sp_2048_add_32_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -2567,7 +2567,7 @@ static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x80\n\t" "\n" - "L_sp_2048_sub_in_pkace_32_word:\n\t" + "L_sp_2048_sub_in_pkace_32_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -2579,9 +2579,9 @@ static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_2048_sub_in_pkace_32_word\n\t" + "BNE L_sp_2048_sub_in_pkace_32_word%=\n\t" #else - "BNE.N L_sp_2048_sub_in_pkace_32_word\n\t" + "BNE.N L_sp_2048_sub_in_pkace_32_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -2621,13 +2621,13 @@ static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_2048_mul_32_outer:\n\t" + "L_sp_2048_mul_32_outer%=:\n\t" "SUBS r3, r5, #0x7c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_2048_mul_32_inner:\n\t" + "L_sp_2048_mul_32_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -2644,14 +2644,14 @@ static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_mul_32_inner_done\n\t" + "BGT L_sp_2048_mul_32_inner_done%=\n\t" #else - "BGT.N L_sp_2048_mul_32_inner_done\n\t" + "BGT.N L_sp_2048_mul_32_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mul_32_inner\n\t" + "BLT L_sp_2048_mul_32_inner%=\n\t" #else - "BLT.N L_sp_2048_mul_32_inner\n\t" + "BLT.N L_sp_2048_mul_32_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -2660,7 +2660,7 @@ static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_2048_mul_32_inner_done:\n\t" + "L_sp_2048_mul_32_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -2668,9 +2668,9 @@ static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0xf4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_2048_mul_32_outer\n\t" + "BLE L_sp_2048_mul_32_outer%=\n\t" #else - "BLE.N L_sp_2048_mul_32_outer\n\t" + "BLE.N L_sp_2048_mul_32_outer%=\n\t" #endif "LDR lr, [%[a], #124]\n\t" "LDR r11, [%[b], #124]\n\t" @@ -2679,14 +2679,14 @@ static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_2048_mul_32_store:\n\t" + "L_sp_2048_mul_32_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_mul_32_store\n\t" + "BGT L_sp_2048_mul_32_store%=\n\t" #else - "BGT.N L_sp_2048_mul_32_store\n\t" + "BGT.N L_sp_2048_mul_32_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -2719,13 +2719,13 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_2048_sqr_32_outer:\n\t" + "L_sp_2048_sqr_32_outer%=:\n\t" "SUBS r3, r5, #0x7c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_2048_sqr_32_inner:\n\t" + "L_sp_2048_sqr_32_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -2739,14 +2739,14 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_sqr_32_inner_done\n\t" + "BGT L_sp_2048_sqr_32_inner_done%=\n\t" #else - "BGT.N L_sp_2048_sqr_32_inner_done\n\t" + "BGT.N L_sp_2048_sqr_32_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_sqr_32_inner\n\t" + "BLT L_sp_2048_sqr_32_inner%=\n\t" #else - "BLT.N L_sp_2048_sqr_32_inner\n\t" + "BLT.N L_sp_2048_sqr_32_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -2754,7 +2754,7 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_2048_sqr_32_inner_done:\n\t" + "L_sp_2048_sqr_32_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -2762,9 +2762,9 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0xf4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_2048_sqr_32_outer\n\t" + "BLE L_sp_2048_sqr_32_outer%=\n\t" #else - "BLE.N L_sp_2048_sqr_32_outer\n\t" + "BLE.N L_sp_2048_sqr_32_outer%=\n\t" #endif "LDR lr, [%[a], #124]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -2772,14 +2772,14 @@ static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_2048_sqr_32_store:\n\t" + "L_sp_2048_sqr_32_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_2048_sqr_32_store\n\t" + "BGT L_sp_2048_sqr_32_store%=\n\t" #else - "BGT.N L_sp_2048_sqr_32_store\n\t" + "BGT.N L_sp_2048_sqr_32_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -2838,7 +2838,7 @@ static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_2048_mul_d_64_word:\n\t" + "L_sp_2048_mul_d_64_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -2852,9 +2852,9 @@ static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mul_d_64_word\n\t" + "BLT L_sp_2048_mul_d_64_word%=\n\t" #else - "BLT.N L_sp_2048_mul_d_64_word\n\t" + "BLT.N L_sp_2048_mul_d_64_word%=\n\t" #endif "STR r3, [%[r], #256]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -3252,7 +3252,7 @@ static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_dig "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_2048_cond_sub_32_words:\n\t" + "L_sp_2048_cond_sub_32_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -3263,9 +3263,9 @@ static sp_digit sp_2048_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_dig "ADD r5, r5, #0x4\n\t" "CMP r5, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_cond_sub_32_words\n\t" + "BLT L_sp_2048_cond_sub_32_words%=\n\t" #else - "BLT.N L_sp_2048_cond_sub_32_words\n\t" + "BLT.N L_sp_2048_cond_sub_32_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -3448,7 +3448,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_2048_mont_reduce_32_word:\n\t" + "L_sp_2048_mont_reduce_32_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -3711,9 +3711,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x80\n\t" #ifdef __GNUC__ - "BLT L_sp_2048_mont_reduce_32_word\n\t" + "BLT L_sp_2048_mont_reduce_32_word%=\n\t" #else - "BLT.W L_sp_2048_mont_reduce_32_word\n\t" + "BLT.W L_sp_2048_mont_reduce_32_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -3752,7 +3752,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_32_word:\n\t" + "L_sp_2048_mont_reduce_32_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -3760,7 +3760,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_32_mul:\n\t" + "L_sp_2048_mont_reduce_32_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -3803,9 +3803,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_32_mul\n\t" + "BLT L_sp_2048_mont_reduce_32_mul%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_32_mul\n\t" + "BLT.N L_sp_2048_mont_reduce_32_mul%=\n\t" #endif "LDR r10, [%[a], #128]\n\t" "ADDS r4, r4, r3\n\t" @@ -3819,9 +3819,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_32_word\n\t" + "BLT L_sp_2048_mont_reduce_32_word%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_32_word\n\t" + "BLT.N L_sp_2048_mont_reduce_32_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -3863,7 +3863,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_2048_mont_reduce_32_word:\n\t" + "L_sp_2048_mont_reduce_32_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -4031,9 +4031,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x80\n\t" #ifdef __GNUC__ - "BLT L_sp_2048_mont_reduce_32_word\n\t" + "BLT L_sp_2048_mont_reduce_32_word%=\n\t" #else - "BLT.W L_sp_2048_mont_reduce_32_word\n\t" + "BLT.W L_sp_2048_mont_reduce_32_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -4075,7 +4075,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_32_word:\n\t" + "L_sp_2048_mont_reduce_32_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -4083,7 +4083,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_32_mul:\n\t" + "L_sp_2048_mont_reduce_32_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -4114,9 +4114,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_32_mul\n\t" + "BLT L_sp_2048_mont_reduce_32_mul%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_32_mul\n\t" + "BLT.N L_sp_2048_mont_reduce_32_mul%=\n\t" #endif "LDR r10, [%[a], #128]\n\t" "ADDS r4, r4, r3\n\t" @@ -4130,9 +4130,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_32_word\n\t" + "BLT L_sp_2048_mont_reduce_32_word%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_32_word\n\t" + "BLT.N L_sp_2048_mont_reduce_32_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -4203,7 +4203,7 @@ static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_2048_mul_d_32_word:\n\t" + "L_sp_2048_mul_d_32_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -4217,9 +4217,9 @@ static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mul_d_32_word\n\t" + "BLT L_sp_2048_mul_d_32_word%=\n\t" #else - "BLT.N L_sp_2048_mul_d_32_word\n\t" + "BLT.N L_sp_2048_mul_d_32_word%=\n\t" #endif "STR r3, [%[r], #128]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -4517,7 +4517,7 @@ SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_2048_word_32_bit:\n\t" + "L_div_2048_word_32_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -4527,7 +4527,7 @@ SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_2048_word_32_bit\n\t" + "bpl L_div_2048_word_32_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -4579,7 +4579,7 @@ static sp_int32 sp_2048_cmp_32(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x7c\n\t" "\n" - "L_sp_2048_cmp_32_words:\n\t" + "L_sp_2048_cmp_32_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -4592,7 +4592,7 @@ static sp_int32 sp_2048_cmp_32(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_2048_cmp_32_words\n\t" + "bcs L_sp_2048_cmp_32_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #124]\n\t" @@ -5380,7 +5380,7 @@ static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_dig "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_2048_cond_sub_64_words:\n\t" + "L_sp_2048_cond_sub_64_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -5391,9 +5391,9 @@ static sp_digit sp_2048_cond_sub_64(sp_digit* r, const sp_digit* a, const sp_dig "ADD r5, r5, #0x4\n\t" "CMP r5, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_cond_sub_64_words\n\t" + "BLT L_sp_2048_cond_sub_64_words%=\n\t" #else - "BLT.N L_sp_2048_cond_sub_64_words\n\t" + "BLT.N L_sp_2048_cond_sub_64_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -5688,7 +5688,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_2048_mont_reduce_64_word:\n\t" + "L_sp_2048_mont_reduce_64_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -6207,9 +6207,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x100\n\t" #ifdef __GNUC__ - "BLT L_sp_2048_mont_reduce_64_word\n\t" + "BLT L_sp_2048_mont_reduce_64_word%=\n\t" #else - "BLT.W L_sp_2048_mont_reduce_64_word\n\t" + "BLT.W L_sp_2048_mont_reduce_64_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -6248,7 +6248,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_64_word:\n\t" + "L_sp_2048_mont_reduce_64_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -6256,7 +6256,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_64_mul:\n\t" + "L_sp_2048_mont_reduce_64_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -6299,9 +6299,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_64_mul\n\t" + "BLT L_sp_2048_mont_reduce_64_mul%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_64_mul\n\t" + "BLT.N L_sp_2048_mont_reduce_64_mul%=\n\t" #endif "LDR r10, [%[a], #256]\n\t" "ADDS r4, r4, r3\n\t" @@ -6315,9 +6315,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_64_word\n\t" + "BLT L_sp_2048_mont_reduce_64_word%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_64_word\n\t" + "BLT.N L_sp_2048_mont_reduce_64_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -6359,7 +6359,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_2048_mont_reduce_64_word:\n\t" + "L_sp_2048_mont_reduce_64_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -6687,9 +6687,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x100\n\t" #ifdef __GNUC__ - "BLT L_sp_2048_mont_reduce_64_word\n\t" + "BLT L_sp_2048_mont_reduce_64_word%=\n\t" #else - "BLT.W L_sp_2048_mont_reduce_64_word\n\t" + "BLT.W L_sp_2048_mont_reduce_64_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -6731,7 +6731,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_64_word:\n\t" + "L_sp_2048_mont_reduce_64_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -6739,7 +6739,7 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_2048_mont_reduce_64_mul:\n\t" + "L_sp_2048_mont_reduce_64_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -6770,9 +6770,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_64_mul\n\t" + "BLT L_sp_2048_mont_reduce_64_mul%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_64_mul\n\t" + "BLT.N L_sp_2048_mont_reduce_64_mul%=\n\t" #endif "LDR r10, [%[a], #256]\n\t" "ADDS r4, r4, r3\n\t" @@ -6786,9 +6786,9 @@ SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_mont_reduce_64_word\n\t" + "BLT L_sp_2048_mont_reduce_64_word%=\n\t" #else - "BLT.N L_sp_2048_mont_reduce_64_word\n\t" + "BLT.N L_sp_2048_mont_reduce_64_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -6854,7 +6854,7 @@ static sp_digit sp_2048_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r11, #0x0\n\t" "ADD r12, %[a], #0x100\n\t" "\n" - "L_sp_2048_sub_64_word:\n\t" + "L_sp_2048_sub_64_word%=:\n\t" "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3, r4, r5, r6}\n\t" "LDM %[b]!, {r7, r8, r9, r10}\n\t" @@ -6866,9 +6866,9 @@ static sp_digit sp_2048_sub_64(sp_digit* r, const sp_digit* a, const sp_digit* b "SBC r11, r3, r3\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_2048_sub_64_word\n\t" + "BNE L_sp_2048_sub_64_word%=\n\t" #else - "BNE.N L_sp_2048_sub_64_word\n\t" + "BNE.N L_sp_2048_sub_64_word%=\n\t" #endif "MOV %[r], r11\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -7121,7 +7121,7 @@ SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_2048_word_64_bit:\n\t" + "L_div_2048_word_64_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -7131,7 +7131,7 @@ SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_2048_word_64_bit\n\t" + "bpl L_div_2048_word_64_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -7286,7 +7286,7 @@ static sp_int32 sp_2048_cmp_64(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0xfc\n\t" "\n" - "L_sp_2048_cmp_64_words:\n\t" + "L_sp_2048_cmp_64_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -7299,7 +7299,7 @@ static sp_int32 sp_2048_cmp_64(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_2048_cmp_64_words\n\t" + "bcs L_sp_2048_cmp_64_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #252]\n\t" @@ -8562,7 +8562,7 @@ static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig "MOV r8, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_2048_cond_add_32_words:\n\t" + "L_sp_2048_cond_add_32_words%=:\n\t" "ADDS r5, r5, #0xffffffff\n\t" "LDR r6, [%[a], r4]\n\t" "LDR r7, [%[b], r4]\n\t" @@ -8573,9 +8573,9 @@ static sp_digit sp_2048_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig "ADD r4, r4, #0x4\n\t" "CMP r4, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_2048_cond_add_32_words\n\t" + "BLT L_sp_2048_cond_add_32_words%=\n\t" #else - "BLT.N L_sp_2048_cond_add_32_words\n\t" + "BLT.N L_sp_2048_cond_add_32_words%=\n\t" #endif "MOV %[r], r5\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -12948,7 +12948,7 @@ static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x180\n\t" "\n" - "L_sp_3072_add_96_word:\n\t" + "L_sp_3072_add_96_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -12961,9 +12961,9 @@ static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, const sp_digit* b "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_3072_add_96_word\n\t" + "BNE L_sp_3072_add_96_word%=\n\t" #else - "BNE.N L_sp_3072_add_96_word\n\t" + "BNE.N L_sp_3072_add_96_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -12995,7 +12995,7 @@ static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x180\n\t" "\n" - "L_sp_3072_sub_in_pkace_96_word:\n\t" + "L_sp_3072_sub_in_pkace_96_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -13007,9 +13007,9 @@ static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_3072_sub_in_pkace_96_word\n\t" + "BNE L_sp_3072_sub_in_pkace_96_word%=\n\t" #else - "BNE.N L_sp_3072_sub_in_pkace_96_word\n\t" + "BNE.N L_sp_3072_sub_in_pkace_96_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -13049,13 +13049,13 @@ static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_3072_mul_96_outer:\n\t" + "L_sp_3072_mul_96_outer%=:\n\t" "SUBS r3, r5, #0x17c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_3072_mul_96_inner:\n\t" + "L_sp_3072_mul_96_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -13072,14 +13072,14 @@ static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_mul_96_inner_done\n\t" + "BGT L_sp_3072_mul_96_inner_done%=\n\t" #else - "BGT.N L_sp_3072_mul_96_inner_done\n\t" + "BGT.N L_sp_3072_mul_96_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mul_96_inner\n\t" + "BLT L_sp_3072_mul_96_inner%=\n\t" #else - "BLT.N L_sp_3072_mul_96_inner\n\t" + "BLT.N L_sp_3072_mul_96_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -13088,7 +13088,7 @@ static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_3072_mul_96_inner_done:\n\t" + "L_sp_3072_mul_96_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -13096,9 +13096,9 @@ static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x2f4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_3072_mul_96_outer\n\t" + "BLE L_sp_3072_mul_96_outer%=\n\t" #else - "BLE.N L_sp_3072_mul_96_outer\n\t" + "BLE.N L_sp_3072_mul_96_outer%=\n\t" #endif "LDR lr, [%[a], #380]\n\t" "LDR r11, [%[b], #380]\n\t" @@ -13107,14 +13107,14 @@ static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_3072_mul_96_store:\n\t" + "L_sp_3072_mul_96_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_mul_96_store\n\t" + "BGT L_sp_3072_mul_96_store%=\n\t" #else - "BGT.N L_sp_3072_mul_96_store\n\t" + "BGT.N L_sp_3072_mul_96_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -13147,13 +13147,13 @@ static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_3072_sqr_96_outer:\n\t" + "L_sp_3072_sqr_96_outer%=:\n\t" "SUBS r3, r5, #0x17c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_3072_sqr_96_inner:\n\t" + "L_sp_3072_sqr_96_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -13167,14 +13167,14 @@ static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_sqr_96_inner_done\n\t" + "BGT L_sp_3072_sqr_96_inner_done%=\n\t" #else - "BGT.N L_sp_3072_sqr_96_inner_done\n\t" + "BGT.N L_sp_3072_sqr_96_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_sqr_96_inner\n\t" + "BLT L_sp_3072_sqr_96_inner%=\n\t" #else - "BLT.N L_sp_3072_sqr_96_inner\n\t" + "BLT.N L_sp_3072_sqr_96_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -13182,7 +13182,7 @@ static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_3072_sqr_96_inner_done:\n\t" + "L_sp_3072_sqr_96_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -13190,9 +13190,9 @@ static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x2f4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_3072_sqr_96_outer\n\t" + "BLE L_sp_3072_sqr_96_outer%=\n\t" #else - "BLE.N L_sp_3072_sqr_96_outer\n\t" + "BLE.N L_sp_3072_sqr_96_outer%=\n\t" #endif "LDR lr, [%[a], #380]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -13200,14 +13200,14 @@ static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_3072_sqr_96_store:\n\t" + "L_sp_3072_sqr_96_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_sqr_96_store\n\t" + "BGT L_sp_3072_sqr_96_store%=\n\t" #else - "BGT.N L_sp_3072_sqr_96_store\n\t" + "BGT.N L_sp_3072_sqr_96_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -13257,7 +13257,7 @@ static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r3, #0x0\n\t" "ADD r12, %[a], #0xc0\n\t" "\n" - "L_sp_3072_add_48_word:\n\t" + "L_sp_3072_add_48_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -13270,9 +13270,9 @@ static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_3072_add_48_word\n\t" + "BNE L_sp_3072_add_48_word%=\n\t" #else - "BNE.N L_sp_3072_add_48_word\n\t" + "BNE.N L_sp_3072_add_48_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -13304,7 +13304,7 @@ static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0xc0\n\t" "\n" - "L_sp_3072_sub_in_pkace_48_word:\n\t" + "L_sp_3072_sub_in_pkace_48_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -13316,9 +13316,9 @@ static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_3072_sub_in_pkace_48_word\n\t" + "BNE L_sp_3072_sub_in_pkace_48_word%=\n\t" #else - "BNE.N L_sp_3072_sub_in_pkace_48_word\n\t" + "BNE.N L_sp_3072_sub_in_pkace_48_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -13358,13 +13358,13 @@ static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_3072_mul_48_outer:\n\t" + "L_sp_3072_mul_48_outer%=:\n\t" "SUBS r3, r5, #0xbc\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_3072_mul_48_inner:\n\t" + "L_sp_3072_mul_48_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -13381,14 +13381,14 @@ static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_mul_48_inner_done\n\t" + "BGT L_sp_3072_mul_48_inner_done%=\n\t" #else - "BGT.N L_sp_3072_mul_48_inner_done\n\t" + "BGT.N L_sp_3072_mul_48_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mul_48_inner\n\t" + "BLT L_sp_3072_mul_48_inner%=\n\t" #else - "BLT.N L_sp_3072_mul_48_inner\n\t" + "BLT.N L_sp_3072_mul_48_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -13397,7 +13397,7 @@ static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_3072_mul_48_inner_done:\n\t" + "L_sp_3072_mul_48_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -13405,9 +13405,9 @@ static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x174\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_3072_mul_48_outer\n\t" + "BLE L_sp_3072_mul_48_outer%=\n\t" #else - "BLE.N L_sp_3072_mul_48_outer\n\t" + "BLE.N L_sp_3072_mul_48_outer%=\n\t" #endif "LDR lr, [%[a], #188]\n\t" "LDR r11, [%[b], #188]\n\t" @@ -13416,14 +13416,14 @@ static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_3072_mul_48_store:\n\t" + "L_sp_3072_mul_48_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_mul_48_store\n\t" + "BGT L_sp_3072_mul_48_store%=\n\t" #else - "BGT.N L_sp_3072_mul_48_store\n\t" + "BGT.N L_sp_3072_mul_48_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -13456,13 +13456,13 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_3072_sqr_48_outer:\n\t" + "L_sp_3072_sqr_48_outer%=:\n\t" "SUBS r3, r5, #0xbc\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_3072_sqr_48_inner:\n\t" + "L_sp_3072_sqr_48_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -13476,14 +13476,14 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_sqr_48_inner_done\n\t" + "BGT L_sp_3072_sqr_48_inner_done%=\n\t" #else - "BGT.N L_sp_3072_sqr_48_inner_done\n\t" + "BGT.N L_sp_3072_sqr_48_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_sqr_48_inner\n\t" + "BLT L_sp_3072_sqr_48_inner%=\n\t" #else - "BLT.N L_sp_3072_sqr_48_inner\n\t" + "BLT.N L_sp_3072_sqr_48_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -13491,7 +13491,7 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_3072_sqr_48_inner_done:\n\t" + "L_sp_3072_sqr_48_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -13499,9 +13499,9 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x174\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_3072_sqr_48_outer\n\t" + "BLE L_sp_3072_sqr_48_outer%=\n\t" #else - "BLE.N L_sp_3072_sqr_48_outer\n\t" + "BLE.N L_sp_3072_sqr_48_outer%=\n\t" #endif "LDR lr, [%[a], #188]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -13509,14 +13509,14 @@ static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_3072_sqr_48_store:\n\t" + "L_sp_3072_sqr_48_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_3072_sqr_48_store\n\t" + "BGT L_sp_3072_sqr_48_store%=\n\t" #else - "BGT.N L_sp_3072_sqr_48_store\n\t" + "BGT.N L_sp_3072_sqr_48_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -13575,7 +13575,7 @@ static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_3072_mul_d_96_word:\n\t" + "L_sp_3072_mul_d_96_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -13589,9 +13589,9 @@ static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x180\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mul_d_96_word\n\t" + "BLT L_sp_3072_mul_d_96_word%=\n\t" #else - "BLT.N L_sp_3072_mul_d_96_word\n\t" + "BLT.N L_sp_3072_mul_d_96_word%=\n\t" #endif "STR r3, [%[r], #384]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -14149,7 +14149,7 @@ static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_dig "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_3072_cond_sub_48_words:\n\t" + "L_sp_3072_cond_sub_48_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -14160,9 +14160,9 @@ static sp_digit sp_3072_cond_sub_48(sp_digit* r, const sp_digit* a, const sp_dig "ADD r5, r5, #0x4\n\t" "CMP r5, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_cond_sub_48_words\n\t" + "BLT L_sp_3072_cond_sub_48_words%=\n\t" #else - "BLT.N L_sp_3072_cond_sub_48_words\n\t" + "BLT.N L_sp_3072_cond_sub_48_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -14401,7 +14401,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_3072_mont_reduce_48_word:\n\t" + "L_sp_3072_mont_reduce_48_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -14792,9 +14792,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0xc0\n\t" #ifdef __GNUC__ - "BLT L_sp_3072_mont_reduce_48_word\n\t" + "BLT L_sp_3072_mont_reduce_48_word%=\n\t" #else - "BLT.W L_sp_3072_mont_reduce_48_word\n\t" + "BLT.W L_sp_3072_mont_reduce_48_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -14833,7 +14833,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_48_word:\n\t" + "L_sp_3072_mont_reduce_48_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -14841,7 +14841,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_48_mul:\n\t" + "L_sp_3072_mont_reduce_48_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -14884,9 +14884,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_48_mul\n\t" + "BLT L_sp_3072_mont_reduce_48_mul%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_48_mul\n\t" + "BLT.N L_sp_3072_mont_reduce_48_mul%=\n\t" #endif "LDR r10, [%[a], #192]\n\t" "ADDS r4, r4, r3\n\t" @@ -14900,9 +14900,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_48_word\n\t" + "BLT L_sp_3072_mont_reduce_48_word%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_48_word\n\t" + "BLT.N L_sp_3072_mont_reduce_48_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -14944,7 +14944,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_3072_mont_reduce_48_word:\n\t" + "L_sp_3072_mont_reduce_48_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -15192,9 +15192,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0xc0\n\t" #ifdef __GNUC__ - "BLT L_sp_3072_mont_reduce_48_word\n\t" + "BLT L_sp_3072_mont_reduce_48_word%=\n\t" #else - "BLT.W L_sp_3072_mont_reduce_48_word\n\t" + "BLT.W L_sp_3072_mont_reduce_48_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -15236,7 +15236,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_48_word:\n\t" + "L_sp_3072_mont_reduce_48_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -15244,7 +15244,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_48_mul:\n\t" + "L_sp_3072_mont_reduce_48_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -15275,9 +15275,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_48_mul\n\t" + "BLT L_sp_3072_mont_reduce_48_mul%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_48_mul\n\t" + "BLT.N L_sp_3072_mont_reduce_48_mul%=\n\t" #endif "LDR r10, [%[a], #192]\n\t" "ADDS r4, r4, r3\n\t" @@ -15291,9 +15291,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_48_word\n\t" + "BLT L_sp_3072_mont_reduce_48_word%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_48_word\n\t" + "BLT.N L_sp_3072_mont_reduce_48_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -15364,7 +15364,7 @@ static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_3072_mul_d_48_word:\n\t" + "L_sp_3072_mul_d_48_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -15378,9 +15378,9 @@ static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mul_d_48_word\n\t" + "BLT L_sp_3072_mul_d_48_word%=\n\t" #else - "BLT.N L_sp_3072_mul_d_48_word\n\t" + "BLT.N L_sp_3072_mul_d_48_word%=\n\t" #endif "STR r3, [%[r], #192]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -15758,7 +15758,7 @@ SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_3072_word_48_bit:\n\t" + "L_div_3072_word_48_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -15768,7 +15768,7 @@ SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_3072_word_48_bit\n\t" + "bpl L_div_3072_word_48_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -15820,7 +15820,7 @@ static sp_int32 sp_3072_cmp_48(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0xbc\n\t" "\n" - "L_sp_3072_cmp_48_words:\n\t" + "L_sp_3072_cmp_48_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -15833,7 +15833,7 @@ static sp_int32 sp_3072_cmp_48(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_3072_cmp_48_words\n\t" + "bcs L_sp_3072_cmp_48_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #188]\n\t" @@ -16797,7 +16797,7 @@ static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a, const sp_dig "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_3072_cond_sub_96_words:\n\t" + "L_sp_3072_cond_sub_96_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -16808,9 +16808,9 @@ static sp_digit sp_3072_cond_sub_96(sp_digit* r, const sp_digit* a, const sp_dig "ADD r5, r5, #0x4\n\t" "CMP r5, #0x180\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_cond_sub_96_words\n\t" + "BLT L_sp_3072_cond_sub_96_words%=\n\t" #else - "BLT.N L_sp_3072_cond_sub_96_words\n\t" + "BLT.N L_sp_3072_cond_sub_96_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -17217,7 +17217,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_3072_mont_reduce_96_word:\n\t" + "L_sp_3072_mont_reduce_96_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -17992,9 +17992,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x180\n\t" #ifdef __GNUC__ - "BLT L_sp_3072_mont_reduce_96_word\n\t" + "BLT L_sp_3072_mont_reduce_96_word%=\n\t" #else - "BLT.W L_sp_3072_mont_reduce_96_word\n\t" + "BLT.W L_sp_3072_mont_reduce_96_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -18033,7 +18033,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_96_word:\n\t" + "L_sp_3072_mont_reduce_96_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -18041,7 +18041,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_96_mul:\n\t" + "L_sp_3072_mont_reduce_96_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -18084,9 +18084,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0x180\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_96_mul\n\t" + "BLT L_sp_3072_mont_reduce_96_mul%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_96_mul\n\t" + "BLT.N L_sp_3072_mont_reduce_96_mul%=\n\t" #endif "LDR r10, [%[a], #384]\n\t" "ADDS r4, r4, r3\n\t" @@ -18100,9 +18100,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x180\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_96_word\n\t" + "BLT L_sp_3072_mont_reduce_96_word%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_96_word\n\t" + "BLT.N L_sp_3072_mont_reduce_96_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -18144,7 +18144,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_3072_mont_reduce_96_word:\n\t" + "L_sp_3072_mont_reduce_96_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -18632,9 +18632,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x180\n\t" #ifdef __GNUC__ - "BLT L_sp_3072_mont_reduce_96_word\n\t" + "BLT L_sp_3072_mont_reduce_96_word%=\n\t" #else - "BLT.W L_sp_3072_mont_reduce_96_word\n\t" + "BLT.W L_sp_3072_mont_reduce_96_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -18676,7 +18676,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_96_word:\n\t" + "L_sp_3072_mont_reduce_96_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -18684,7 +18684,7 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_3072_mont_reduce_96_mul:\n\t" + "L_sp_3072_mont_reduce_96_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -18715,9 +18715,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "ADD r12, r12, #0x4\n\t" "CMP r12, #0x180\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_96_mul\n\t" + "BLT L_sp_3072_mont_reduce_96_mul%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_96_mul\n\t" + "BLT.N L_sp_3072_mont_reduce_96_mul%=\n\t" #endif "LDR r10, [%[a], #384]\n\t" "ADDS r4, r4, r3\n\t" @@ -18731,9 +18731,9 @@ SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x180\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_mont_reduce_96_word\n\t" + "BLT L_sp_3072_mont_reduce_96_word%=\n\t" #else - "BLT.N L_sp_3072_mont_reduce_96_word\n\t" + "BLT.N L_sp_3072_mont_reduce_96_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -18799,7 +18799,7 @@ static sp_digit sp_3072_sub_96(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r11, #0x0\n\t" "ADD r12, %[a], #0x180\n\t" "\n" - "L_sp_3072_sub_96_word:\n\t" + "L_sp_3072_sub_96_word%=:\n\t" "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3, r4, r5, r6}\n\t" "LDM %[b]!, {r7, r8, r9, r10}\n\t" @@ -18811,9 +18811,9 @@ static sp_digit sp_3072_sub_96(sp_digit* r, const sp_digit* a, const sp_digit* b "SBC r11, r3, r3\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_3072_sub_96_word\n\t" + "BNE L_sp_3072_sub_96_word%=\n\t" #else - "BNE.N L_sp_3072_sub_96_word\n\t" + "BNE.N L_sp_3072_sub_96_word%=\n\t" #endif "MOV %[r], r11\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -19122,7 +19122,7 @@ SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_3072_word_96_bit:\n\t" + "L_div_3072_word_96_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -19132,7 +19132,7 @@ SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_3072_word_96_bit\n\t" + "bpl L_div_3072_word_96_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -19287,7 +19287,7 @@ static sp_int32 sp_3072_cmp_96(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x17c\n\t" "\n" - "L_sp_3072_cmp_96_words:\n\t" + "L_sp_3072_cmp_96_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -19300,7 +19300,7 @@ static sp_int32 sp_3072_cmp_96(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_3072_cmp_96_words\n\t" + "bcs L_sp_3072_cmp_96_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #380]\n\t" @@ -20915,7 +20915,7 @@ static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_dig "MOV r8, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_3072_cond_add_48_words:\n\t" + "L_sp_3072_cond_add_48_words%=:\n\t" "ADDS r5, r5, #0xffffffff\n\t" "LDR r6, [%[a], r4]\n\t" "LDR r7, [%[b], r4]\n\t" @@ -20926,9 +20926,9 @@ static sp_digit sp_3072_cond_add_48(sp_digit* r, const sp_digit* a, const sp_dig "ADD r4, r4, #0x4\n\t" "CMP r4, #0xc0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_3072_cond_add_48_words\n\t" + "BLT L_sp_3072_cond_add_48_words%=\n\t" #else - "BLT.N L_sp_3072_cond_add_48_words\n\t" + "BLT.N L_sp_3072_cond_add_48_words%=\n\t" #endif "MOV %[r], r5\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -23059,7 +23059,7 @@ static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, const sp_digit* "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x200\n\t" "\n" - "L_sp_4096_add_128_word:\n\t" + "L_sp_4096_add_128_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -23072,9 +23072,9 @@ static sp_digit sp_4096_add_128(sp_digit* r, const sp_digit* a, const sp_digit* "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_4096_add_128_word\n\t" + "BNE L_sp_4096_add_128_word%=\n\t" #else - "BNE.N L_sp_4096_add_128_word\n\t" + "BNE.N L_sp_4096_add_128_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -23106,7 +23106,7 @@ static sp_digit sp_4096_sub_in_place_128(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x200\n\t" "\n" - "L_sp_4096_sub_in_pkace_128_word:\n\t" + "L_sp_4096_sub_in_pkace_128_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -23118,9 +23118,9 @@ static sp_digit sp_4096_sub_in_place_128(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_4096_sub_in_pkace_128_word\n\t" + "BNE L_sp_4096_sub_in_pkace_128_word%=\n\t" #else - "BNE.N L_sp_4096_sub_in_pkace_128_word\n\t" + "BNE.N L_sp_4096_sub_in_pkace_128_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -23160,13 +23160,13 @@ static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_4096_mul_128_outer:\n\t" + "L_sp_4096_mul_128_outer%=:\n\t" "SUBS r3, r5, #0x1fc\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_4096_mul_128_inner:\n\t" + "L_sp_4096_mul_128_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -23183,14 +23183,14 @@ static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_4096_mul_128_inner_done\n\t" + "BGT L_sp_4096_mul_128_inner_done%=\n\t" #else - "BGT.N L_sp_4096_mul_128_inner_done\n\t" + "BGT.N L_sp_4096_mul_128_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_mul_128_inner\n\t" + "BLT L_sp_4096_mul_128_inner%=\n\t" #else - "BLT.N L_sp_4096_mul_128_inner\n\t" + "BLT.N L_sp_4096_mul_128_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -23199,7 +23199,7 @@ static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_4096_mul_128_inner_done:\n\t" + "L_sp_4096_mul_128_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -23207,9 +23207,9 @@ static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x3f4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_4096_mul_128_outer\n\t" + "BLE L_sp_4096_mul_128_outer%=\n\t" #else - "BLE.N L_sp_4096_mul_128_outer\n\t" + "BLE.N L_sp_4096_mul_128_outer%=\n\t" #endif "LDR lr, [%[a], #508]\n\t" "LDR r11, [%[b], #508]\n\t" @@ -23218,14 +23218,14 @@ static void sp_4096_mul_128(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_4096_mul_128_store:\n\t" + "L_sp_4096_mul_128_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_4096_mul_128_store\n\t" + "BGT L_sp_4096_mul_128_store%=\n\t" #else - "BGT.N L_sp_4096_mul_128_store\n\t" + "BGT.N L_sp_4096_mul_128_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -23258,13 +23258,13 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_4096_sqr_128_outer:\n\t" + "L_sp_4096_sqr_128_outer%=:\n\t" "SUBS r3, r5, #0x1fc\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_4096_sqr_128_inner:\n\t" + "L_sp_4096_sqr_128_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -23278,14 +23278,14 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_4096_sqr_128_inner_done\n\t" + "BGT L_sp_4096_sqr_128_inner_done%=\n\t" #else - "BGT.N L_sp_4096_sqr_128_inner_done\n\t" + "BGT.N L_sp_4096_sqr_128_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_sqr_128_inner\n\t" + "BLT L_sp_4096_sqr_128_inner%=\n\t" #else - "BLT.N L_sp_4096_sqr_128_inner\n\t" + "BLT.N L_sp_4096_sqr_128_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -23293,7 +23293,7 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_4096_sqr_128_inner_done:\n\t" + "L_sp_4096_sqr_128_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -23301,9 +23301,9 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x3f4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_4096_sqr_128_outer\n\t" + "BLE L_sp_4096_sqr_128_outer%=\n\t" #else - "BLE.N L_sp_4096_sqr_128_outer\n\t" + "BLE.N L_sp_4096_sqr_128_outer%=\n\t" #endif "LDR lr, [%[a], #508]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -23311,14 +23311,14 @@ static void sp_4096_sqr_128(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_4096_sqr_128_store:\n\t" + "L_sp_4096_sqr_128_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_4096_sqr_128_store\n\t" + "BGT L_sp_4096_sqr_128_store%=\n\t" #else - "BGT.N L_sp_4096_sqr_128_store\n\t" + "BGT.N L_sp_4096_sqr_128_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -23375,7 +23375,7 @@ static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_4096_mul_d_128_word:\n\t" + "L_sp_4096_mul_d_128_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -23389,9 +23389,9 @@ static void sp_4096_mul_d_128(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x200\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_mul_d_128_word\n\t" + "BLT L_sp_4096_mul_d_128_word%=\n\t" #else - "BLT.N L_sp_4096_mul_d_128_word\n\t" + "BLT.N L_sp_4096_mul_d_128_word%=\n\t" #endif "STR r3, [%[r], #512]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -24110,7 +24110,7 @@ static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a, const sp_di "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_4096_cond_sub_128_words:\n\t" + "L_sp_4096_cond_sub_128_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -24121,9 +24121,9 @@ static sp_digit sp_4096_cond_sub_128(sp_digit* r, const sp_digit* a, const sp_di "ADD r5, r5, #0x4\n\t" "CMP r5, #0x200\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_cond_sub_128_words\n\t" + "BLT L_sp_4096_cond_sub_128_words%=\n\t" #else - "BLT.N L_sp_4096_cond_sub_128_words\n\t" + "BLT.N L_sp_4096_cond_sub_128_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -24642,7 +24642,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_4096_mont_reduce_128_word:\n\t" + "L_sp_4096_mont_reduce_128_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -25673,9 +25673,9 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x200\n\t" #ifdef __GNUC__ - "BLT L_sp_4096_mont_reduce_128_word\n\t" + "BLT L_sp_4096_mont_reduce_128_word%=\n\t" #else - "BLT.W L_sp_4096_mont_reduce_128_word\n\t" + "BLT.W L_sp_4096_mont_reduce_128_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -25714,7 +25714,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_4096_mont_reduce_128_word:\n\t" + "L_sp_4096_mont_reduce_128_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -25722,7 +25722,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_4096_mont_reduce_128_mul:\n\t" + "L_sp_4096_mont_reduce_128_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -25765,9 +25765,9 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "ADD r12, r12, #0x4\n\t" "CMP r12, #0x200\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_mont_reduce_128_mul\n\t" + "BLT L_sp_4096_mont_reduce_128_mul%=\n\t" #else - "BLT.N L_sp_4096_mont_reduce_128_mul\n\t" + "BLT.N L_sp_4096_mont_reduce_128_mul%=\n\t" #endif "LDR r10, [%[a], #512]\n\t" "ADDS r4, r4, r3\n\t" @@ -25781,9 +25781,9 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x200\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_mont_reduce_128_word\n\t" + "BLT L_sp_4096_mont_reduce_128_word%=\n\t" #else - "BLT.N L_sp_4096_mont_reduce_128_word\n\t" + "BLT.N L_sp_4096_mont_reduce_128_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -25825,7 +25825,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_4096_mont_reduce_128_word:\n\t" + "L_sp_4096_mont_reduce_128_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -26473,9 +26473,9 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x200\n\t" #ifdef __GNUC__ - "BLT L_sp_4096_mont_reduce_128_word\n\t" + "BLT L_sp_4096_mont_reduce_128_word%=\n\t" #else - "BLT.W L_sp_4096_mont_reduce_128_word\n\t" + "BLT.W L_sp_4096_mont_reduce_128_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -26517,7 +26517,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, /* ca = 0 */ "MOV r3, #0x0\n\t" "\n" - "L_sp_4096_mont_reduce_128_word:\n\t" + "L_sp_4096_mont_reduce_128_word%=:\n\t" /* mu = a[i] * mp */ "LDR r10, [%[a]]\n\t" "MUL r8, %[mp], r10\n\t" @@ -26525,7 +26525,7 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "MOV r12, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_4096_mont_reduce_128_mul:\n\t" + "L_sp_4096_mont_reduce_128_mul%=:\n\t" /* a[i+j+0] += m[j+0] * mu */ "LDR r7, [%[m], r12]\n\t" "LDR r10, [%[a], r12]\n\t" @@ -26556,9 +26556,9 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "ADD r12, r12, #0x4\n\t" "CMP r12, #0x200\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_mont_reduce_128_mul\n\t" + "BLT L_sp_4096_mont_reduce_128_mul%=\n\t" #else - "BLT.N L_sp_4096_mont_reduce_128_mul\n\t" + "BLT.N L_sp_4096_mont_reduce_128_mul%=\n\t" #endif "LDR r10, [%[a], #512]\n\t" "ADDS r4, r4, r3\n\t" @@ -26572,9 +26572,9 @@ SP_NOINLINE static void sp_4096_mont_reduce_128(sp_digit* a, const sp_digit* m, "ADD %[a], %[a], #0x4\n\t" "CMP r9, #0x200\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_mont_reduce_128_word\n\t" + "BLT L_sp_4096_mont_reduce_128_word%=\n\t" #else - "BLT.N L_sp_4096_mont_reduce_128_word\n\t" + "BLT.N L_sp_4096_mont_reduce_128_word%=\n\t" #endif /* Loop Done */ "MOV %[mp], r3\n\t" @@ -26640,7 +26640,7 @@ static sp_digit sp_4096_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* "MOV r11, #0x0\n\t" "ADD r12, %[a], #0x200\n\t" "\n" - "L_sp_4096_sub_128_word:\n\t" + "L_sp_4096_sub_128_word%=:\n\t" "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3, r4, r5, r6}\n\t" "LDM %[b]!, {r7, r8, r9, r10}\n\t" @@ -26652,9 +26652,9 @@ static sp_digit sp_4096_sub_128(sp_digit* r, const sp_digit* a, const sp_digit* "SBC r11, r3, r3\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_4096_sub_128_word\n\t" + "BNE L_sp_4096_sub_128_word%=\n\t" #else - "BNE.N L_sp_4096_sub_128_word\n\t" + "BNE.N L_sp_4096_sub_128_word%=\n\t" #endif "MOV %[r], r11\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -27019,7 +27019,7 @@ SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, sp_digit /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_4096_word_128_bit:\n\t" + "L_div_4096_word_128_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -27029,7 +27029,7 @@ SP_NOINLINE static sp_digit div_4096_word_128(sp_digit d1, sp_digit d0, sp_digit "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_4096_word_128_bit\n\t" + "bpl L_div_4096_word_128_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -27184,7 +27184,7 @@ static sp_int32 sp_4096_cmp_128(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x1fc\n\t" "\n" - "L_sp_4096_cmp_128_words:\n\t" + "L_sp_4096_cmp_128_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -27197,7 +27197,7 @@ static sp_int32 sp_4096_cmp_128(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_4096_cmp_128_words\n\t" + "bcs L_sp_4096_cmp_128_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #508]\n\t" @@ -29164,7 +29164,7 @@ static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_dig "MOV r8, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_4096_cond_add_64_words:\n\t" + "L_sp_4096_cond_add_64_words%=:\n\t" "ADDS r5, r5, #0xffffffff\n\t" "LDR r6, [%[a], r4]\n\t" "LDR r7, [%[b], r4]\n\t" @@ -29175,9 +29175,9 @@ static sp_digit sp_4096_cond_add_64(sp_digit* r, const sp_digit* a, const sp_dig "ADD r4, r4, #0x4\n\t" "CMP r4, #0x100\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_4096_cond_add_64_words\n\t" + "BLT L_sp_4096_cond_add_64_words%=\n\t" #else - "BLT.N L_sp_4096_cond_add_64_words\n\t" + "BLT.N L_sp_4096_cond_add_64_words%=\n\t" #endif "MOV %[r], r5\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -30857,13 +30857,13 @@ static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_256_mul_8_outer:\n\t" + "L_sp_256_mul_8_outer%=:\n\t" "SUBS r3, r5, #0x1c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_256_mul_8_inner:\n\t" + "L_sp_256_mul_8_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -30880,14 +30880,14 @@ static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_256_mul_8_inner_done\n\t" + "BGT L_sp_256_mul_8_inner_done%=\n\t" #else - "BGT.N L_sp_256_mul_8_inner_done\n\t" + "BGT.N L_sp_256_mul_8_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_256_mul_8_inner\n\t" + "BLT L_sp_256_mul_8_inner%=\n\t" #else - "BLT.N L_sp_256_mul_8_inner\n\t" + "BLT.N L_sp_256_mul_8_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -30896,7 +30896,7 @@ static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_256_mul_8_inner_done:\n\t" + "L_sp_256_mul_8_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -30904,9 +30904,9 @@ static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x34\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_256_mul_8_outer\n\t" + "BLE L_sp_256_mul_8_outer%=\n\t" #else - "BLE.N L_sp_256_mul_8_outer\n\t" + "BLE.N L_sp_256_mul_8_outer%=\n\t" #endif "LDR lr, [%[a], #28]\n\t" "LDR r11, [%[b], #28]\n\t" @@ -30915,14 +30915,14 @@ static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_256_mul_8_store:\n\t" + "L_sp_256_mul_8_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_256_mul_8_store\n\t" + "BGT L_sp_256_mul_8_store%=\n\t" #else - "BGT.N L_sp_256_mul_8_store\n\t" + "BGT.N L_sp_256_mul_8_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -31455,13 +31455,13 @@ static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_256_sqr_8_outer:\n\t" + "L_sp_256_sqr_8_outer%=:\n\t" "SUBS r3, r5, #0x1c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_256_sqr_8_inner:\n\t" + "L_sp_256_sqr_8_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -31475,14 +31475,14 @@ static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_256_sqr_8_inner_done\n\t" + "BGT L_sp_256_sqr_8_inner_done%=\n\t" #else - "BGT.N L_sp_256_sqr_8_inner_done\n\t" + "BGT.N L_sp_256_sqr_8_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_256_sqr_8_inner\n\t" + "BLT L_sp_256_sqr_8_inner%=\n\t" #else - "BLT.N L_sp_256_sqr_8_inner\n\t" + "BLT.N L_sp_256_sqr_8_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -31490,7 +31490,7 @@ static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_256_sqr_8_inner_done:\n\t" + "L_sp_256_sqr_8_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -31498,9 +31498,9 @@ static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x34\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_256_sqr_8_outer\n\t" + "BLE L_sp_256_sqr_8_outer%=\n\t" #else - "BLE.N L_sp_256_sqr_8_outer\n\t" + "BLE.N L_sp_256_sqr_8_outer%=\n\t" #endif "LDR lr, [%[a], #28]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -31508,14 +31508,14 @@ static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_256_sqr_8_store:\n\t" + "L_sp_256_sqr_8_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_256_sqr_8_store\n\t" + "BGT L_sp_256_sqr_8_store%=\n\t" #else - "BGT.N L_sp_256_sqr_8_store\n\t" + "BGT.N L_sp_256_sqr_8_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -31915,7 +31915,7 @@ static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x20\n\t" "\n" - "L_sp_256_add_8_word:\n\t" + "L_sp_256_add_8_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -31928,9 +31928,9 @@ static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_256_add_8_word\n\t" + "BNE L_sp_256_add_8_word%=\n\t" #else - "BNE.N L_sp_256_add_8_word\n\t" + "BNE.N L_sp_256_add_8_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -33938,7 +33938,7 @@ static sp_int32 sp_256_cmp_8(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x1c\n\t" "\n" - "L_sp_256_cmp_8_words:\n\t" + "L_sp_256_cmp_8_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -33951,7 +33951,7 @@ static sp_int32 sp_256_cmp_8(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_256_cmp_8_words\n\t" + "bcs L_sp_256_cmp_8_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #28]\n\t" @@ -34085,7 +34085,7 @@ static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a, const sp_digit "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_256_cond_sub_8_words:\n\t" + "L_sp_256_cond_sub_8_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -34096,9 +34096,9 @@ static sp_digit sp_256_cond_sub_8(sp_digit* r, const sp_digit* a, const sp_digit "ADD r5, r5, #0x4\n\t" "CMP r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_256_cond_sub_8_words\n\t" + "BLT L_sp_256_cond_sub_8_words%=\n\t" #else - "BLT.N L_sp_256_cond_sub_8_words\n\t" + "BLT.N L_sp_256_cond_sub_8_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -34199,7 +34199,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_ "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_256_mont_reduce_8_word:\n\t" + "L_sp_256_mont_reduce_8_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -34270,9 +34270,9 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_ "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x20\n\t" #ifdef __GNUC__ - "BLT L_sp_256_mont_reduce_8_word\n\t" + "BLT L_sp_256_mont_reduce_8_word%=\n\t" #else - "BLT.W L_sp_256_mont_reduce_8_word\n\t" + "BLT.W L_sp_256_mont_reduce_8_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -34314,7 +34314,7 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_ "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_256_mont_reduce_8_word:\n\t" + "L_sp_256_mont_reduce_8_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -34362,9 +34362,9 @@ SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, const sp_digit* m, sp_ "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x20\n\t" #ifdef __GNUC__ - "BLT L_sp_256_mont_reduce_8_word\n\t" + "BLT L_sp_256_mont_reduce_8_word%=\n\t" #else - "BLT.W L_sp_256_mont_reduce_8_word\n\t" + "BLT.W L_sp_256_mont_reduce_8_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -34573,7 +34573,7 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_256_mont_reduce_order_8_word:\n\t" + "L_sp_256_mont_reduce_order_8_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -34644,9 +34644,9 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x20\n\t" #ifdef __GNUC__ - "BLT L_sp_256_mont_reduce_order_8_word\n\t" + "BLT L_sp_256_mont_reduce_order_8_word%=\n\t" #else - "BLT.W L_sp_256_mont_reduce_order_8_word\n\t" + "BLT.W L_sp_256_mont_reduce_order_8_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -34688,7 +34688,7 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_256_mont_reduce_order_8_word:\n\t" + "L_sp_256_mont_reduce_order_8_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -34736,9 +34736,9 @@ SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, const sp_digit* "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x20\n\t" #ifdef __GNUC__ - "BLT L_sp_256_mont_reduce_order_8_word\n\t" + "BLT L_sp_256_mont_reduce_order_8_word%=\n\t" #else - "BLT.W L_sp_256_mont_reduce_order_8_word\n\t" + "BLT.W L_sp_256_mont_reduce_order_8_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -39075,7 +39075,7 @@ static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x20\n\t" "\n" - "L_sp_256_sub_in_pkace_8_word:\n\t" + "L_sp_256_sub_in_pkace_8_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -39087,9 +39087,9 @@ static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_256_sub_in_pkace_8_word\n\t" + "BNE L_sp_256_sub_in_pkace_8_word%=\n\t" #else - "BNE.N L_sp_256_sub_in_pkace_8_word\n\t" + "BNE.N L_sp_256_sub_in_pkace_8_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -39168,7 +39168,7 @@ static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_256_mul_d_8_word:\n\t" + "L_sp_256_mul_d_8_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -39182,9 +39182,9 @@ static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_256_mul_d_8_word\n\t" + "BLT L_sp_256_mul_d_8_word%=\n\t" #else - "BLT.N L_sp_256_mul_d_8_word\n\t" + "BLT.N L_sp_256_mul_d_8_word%=\n\t" #endif "STR r3, [%[r], #32]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -39362,7 +39362,7 @@ SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit di /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_256_word_8_bit:\n\t" + "L_div_256_word_8_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -39372,7 +39372,7 @@ SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit di "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_256_word_8_bit\n\t" + "bpl L_div_256_word_8_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -40066,7 +40066,7 @@ static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r11, #0x0\n\t" "ADD r12, %[a], #0x20\n\t" "\n" - "L_sp_256_sub_8_word:\n\t" + "L_sp_256_sub_8_word%=:\n\t" "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3, r4, r5, r6}\n\t" "LDM %[b]!, {r7, r8, r9, r10}\n\t" @@ -40078,9 +40078,9 @@ static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, const sp_digit* b) "SBC r11, r3, r3\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_256_sub_8_word\n\t" + "BNE L_sp_256_sub_8_word%=\n\t" #else - "BNE.N L_sp_256_sub_8_word\n\t" + "BNE.N L_sp_256_sub_8_word%=\n\t" #endif "MOV %[r], r11\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -40200,9 +40200,9 @@ static void sp_256_div2_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m) "LDM %[a]!, {r4}\n\t" "ANDS r3, r4, #0x1\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_div2_mod_8_even\n\t" + "BEQ L_sp_256_div2_mod_8_even%=\n\t" #else - "BEQ.N L_sp_256_div2_mod_8_even\n\t" + "BEQ.N L_sp_256_div2_mod_8_even%=\n\t" #endif "LDM %[a]!, {r5, r6, r7}\n\t" "LDM %[m]!, {r8, r9, r10, r11}\n\t" @@ -40219,16 +40219,16 @@ static void sp_256_div2_mod_8(sp_digit* r, const sp_digit* a, const sp_digit* m) "ADCS r7, r7, r11\n\t" "ADC r3, r12, r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_div2_mod_8_div2\n\t" + "B L_sp_256_div2_mod_8_div2%=\n\t" #else - "B.N L_sp_256_div2_mod_8_div2\n\t" + "B.N L_sp_256_div2_mod_8_div2%=\n\t" #endif "\n" - "L_sp_256_div2_mod_8_even:\n\t" + "L_sp_256_div2_mod_8_even%=:\n\t" "LDRD r4, r5, [%[a], #12]\n\t" "LDRD r6, r7, [%[a], #20]\n\t" "\n" - "L_sp_256_div2_mod_8_div2:\n\t" + "L_sp_256_div2_mod_8_div2%=:\n\t" "LSR r8, r4, #1\n\t" "AND r4, r4, #0x1\n\t" "LSR r9, r5, #1\n\t" @@ -40271,128 +40271,128 @@ static int sp_256_num_bits_8(const sp_digit* a) "LDR r1, [%[a], #28]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_7\n\t" + "BEQ L_sp_256_num_bits_8_7%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_7\n\t" + "BEQ.N L_sp_256_num_bits_8_7%=\n\t" #endif "MOV r2, #0x100\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_7:\n\t" + "L_sp_256_num_bits_8_7%=:\n\t" "LDR r1, [%[a], #24]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_6\n\t" + "BEQ L_sp_256_num_bits_8_6%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_6\n\t" + "BEQ.N L_sp_256_num_bits_8_6%=\n\t" #endif "MOV r2, #0xe0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_6:\n\t" + "L_sp_256_num_bits_8_6%=:\n\t" "LDR r1, [%[a], #20]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_5\n\t" + "BEQ L_sp_256_num_bits_8_5%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_5\n\t" + "BEQ.N L_sp_256_num_bits_8_5%=\n\t" #endif "MOV r2, #0xc0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_5:\n\t" + "L_sp_256_num_bits_8_5%=:\n\t" "LDR r1, [%[a], #16]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_4\n\t" + "BEQ L_sp_256_num_bits_8_4%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_4\n\t" + "BEQ.N L_sp_256_num_bits_8_4%=\n\t" #endif "MOV r2, #0xa0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_4:\n\t" + "L_sp_256_num_bits_8_4%=:\n\t" "LDR r1, [%[a], #12]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_3\n\t" + "BEQ L_sp_256_num_bits_8_3%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_3\n\t" + "BEQ.N L_sp_256_num_bits_8_3%=\n\t" #endif "MOV r2, #0x80\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_3:\n\t" + "L_sp_256_num_bits_8_3%=:\n\t" "LDR r1, [%[a], #8]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_2\n\t" + "BEQ L_sp_256_num_bits_8_2%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_2\n\t" + "BEQ.N L_sp_256_num_bits_8_2%=\n\t" #endif "MOV r2, #0x60\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_2:\n\t" + "L_sp_256_num_bits_8_2%=:\n\t" "LDR r1, [%[a], #4]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_256_num_bits_8_1\n\t" + "BEQ L_sp_256_num_bits_8_1%=\n\t" #else - "BEQ.N L_sp_256_num_bits_8_1\n\t" + "BEQ.N L_sp_256_num_bits_8_1%=\n\t" #endif "MOV r2, #0x40\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_256_num_bits_8_9\n\t" + "B L_sp_256_num_bits_8_9%=\n\t" #else - "B.N L_sp_256_num_bits_8_9\n\t" + "B.N L_sp_256_num_bits_8_9%=\n\t" #endif "\n" - "L_sp_256_num_bits_8_1:\n\t" + "L_sp_256_num_bits_8_1%=:\n\t" "LDR r1, [%[a]]\n\t" "MOV r2, #0x20\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" "\n" - "L_sp_256_num_bits_8_9:\n\t" + "L_sp_256_num_bits_8_9%=:\n\t" "MOV %[a], r4\n\t" : [a] "+r" (a) : @@ -41515,13 +41515,13 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_384_mul_12_outer:\n\t" + "L_sp_384_mul_12_outer%=:\n\t" "SUBS r3, r5, #0x2c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_384_mul_12_inner:\n\t" + "L_sp_384_mul_12_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -41538,14 +41538,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_384_mul_12_inner_done\n\t" + "BGT L_sp_384_mul_12_inner_done%=\n\t" #else - "BGT.N L_sp_384_mul_12_inner_done\n\t" + "BGT.N L_sp_384_mul_12_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_384_mul_12_inner\n\t" + "BLT L_sp_384_mul_12_inner%=\n\t" #else - "BLT.N L_sp_384_mul_12_inner\n\t" + "BLT.N L_sp_384_mul_12_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -41554,7 +41554,7 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_384_mul_12_inner_done:\n\t" + "L_sp_384_mul_12_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -41562,9 +41562,9 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x54\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_384_mul_12_outer\n\t" + "BLE L_sp_384_mul_12_outer%=\n\t" #else - "BLE.N L_sp_384_mul_12_outer\n\t" + "BLE.N L_sp_384_mul_12_outer%=\n\t" #endif "LDR lr, [%[a], #44]\n\t" "LDR r11, [%[b], #44]\n\t" @@ -41573,14 +41573,14 @@ static void sp_384_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_384_mul_12_store:\n\t" + "L_sp_384_mul_12_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_384_mul_12_store\n\t" + "BGT L_sp_384_mul_12_store%=\n\t" #else - "BGT.N L_sp_384_mul_12_store\n\t" + "BGT.N L_sp_384_mul_12_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -42643,13 +42643,13 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_384_sqr_12_outer:\n\t" + "L_sp_384_sqr_12_outer%=:\n\t" "SUBS r3, r5, #0x2c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_384_sqr_12_inner:\n\t" + "L_sp_384_sqr_12_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -42663,14 +42663,14 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_384_sqr_12_inner_done\n\t" + "BGT L_sp_384_sqr_12_inner_done%=\n\t" #else - "BGT.N L_sp_384_sqr_12_inner_done\n\t" + "BGT.N L_sp_384_sqr_12_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_384_sqr_12_inner\n\t" + "BLT L_sp_384_sqr_12_inner%=\n\t" #else - "BLT.N L_sp_384_sqr_12_inner\n\t" + "BLT.N L_sp_384_sqr_12_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -42678,7 +42678,7 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_384_sqr_12_inner_done:\n\t" + "L_sp_384_sqr_12_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -42686,9 +42686,9 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x54\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_384_sqr_12_outer\n\t" + "BLE L_sp_384_sqr_12_outer%=\n\t" #else - "BLE.N L_sp_384_sqr_12_outer\n\t" + "BLE.N L_sp_384_sqr_12_outer%=\n\t" #endif "LDR lr, [%[a], #44]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -42696,14 +42696,14 @@ static void sp_384_sqr_12(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_384_sqr_12_store:\n\t" + "L_sp_384_sqr_12_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_384_sqr_12_store\n\t" + "BGT L_sp_384_sqr_12_store%=\n\t" #else - "BGT.N L_sp_384_sqr_12_store\n\t" + "BGT.N L_sp_384_sqr_12_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -43436,7 +43436,7 @@ static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x30\n\t" "\n" - "L_sp_384_add_12_word:\n\t" + "L_sp_384_add_12_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -43449,9 +43449,9 @@ static sp_digit sp_384_add_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_384_add_12_word\n\t" + "BNE L_sp_384_add_12_word%=\n\t" #else - "BNE.N L_sp_384_add_12_word\n\t" + "BNE.N L_sp_384_add_12_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -43836,7 +43836,7 @@ static sp_digit sp_384_cond_sub_12(sp_digit* r, const sp_digit* a, const sp_digi "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_384_cond_sub_12_words:\n\t" + "L_sp_384_cond_sub_12_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -43847,9 +43847,9 @@ static sp_digit sp_384_cond_sub_12(sp_digit* r, const sp_digit* a, const sp_digi "ADD r5, r5, #0x4\n\t" "CMP r5, #0x30\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_384_cond_sub_12_words\n\t" + "BLT L_sp_384_cond_sub_12_words%=\n\t" #else - "BLT.N L_sp_384_cond_sub_12_words\n\t" + "BLT.N L_sp_384_cond_sub_12_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -43963,7 +43963,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_384_mont_reduce_12_word:\n\t" + "L_sp_384_mont_reduce_12_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -44066,9 +44066,9 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x30\n\t" #ifdef __GNUC__ - "BLT L_sp_384_mont_reduce_12_word\n\t" + "BLT L_sp_384_mont_reduce_12_word%=\n\t" #else - "BLT.W L_sp_384_mont_reduce_12_word\n\t" + "BLT.W L_sp_384_mont_reduce_12_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -44110,7 +44110,7 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_384_mont_reduce_12_word:\n\t" + "L_sp_384_mont_reduce_12_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -44178,9 +44178,9 @@ SP_NOINLINE static void sp_384_mont_reduce_12(sp_digit* a, const sp_digit* m, sp "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x30\n\t" #ifdef __GNUC__ - "BLT L_sp_384_mont_reduce_12_word\n\t" + "BLT L_sp_384_mont_reduce_12_word%=\n\t" #else - "BLT.W L_sp_384_mont_reduce_12_word\n\t" + "BLT.W L_sp_384_mont_reduce_12_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -44365,7 +44365,7 @@ static sp_int32 sp_384_cmp_12(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x2c\n\t" "\n" - "L_sp_384_cmp_12_words:\n\t" + "L_sp_384_cmp_12_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -44378,7 +44378,7 @@ static sp_int32 sp_384_cmp_12(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_384_cmp_12_words\n\t" + "bcs L_sp_384_cmp_12_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #44]\n\t" @@ -44668,7 +44668,7 @@ static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r11, #0x0\n\t" "ADD r12, %[a], #0x30\n\t" "\n" - "L_sp_384_sub_12_word:\n\t" + "L_sp_384_sub_12_word%=:\n\t" "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3, r4, r5, r6}\n\t" "LDM %[b]!, {r7, r8, r9, r10}\n\t" @@ -44680,9 +44680,9 @@ static sp_digit sp_384_sub_12(sp_digit* r, const sp_digit* a, const sp_digit* b) "SBC r11, r3, r3\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_384_sub_12_word\n\t" + "BNE L_sp_384_sub_12_word%=\n\t" #else - "BNE.N L_sp_384_sub_12_word\n\t" + "BNE.N L_sp_384_sub_12_word%=\n\t" #endif "MOV %[r], r11\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -44769,7 +44769,7 @@ static sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digi "MOV r8, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_384_cond_add_12_words:\n\t" + "L_sp_384_cond_add_12_words%=:\n\t" "ADDS r5, r5, #0xffffffff\n\t" "LDR r6, [%[a], r4]\n\t" "LDR r7, [%[b], r4]\n\t" @@ -44780,9 +44780,9 @@ static sp_digit sp_384_cond_add_12(sp_digit* r, const sp_digit* a, const sp_digi "ADD r4, r4, #0x4\n\t" "CMP r4, #0x30\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_384_cond_add_12_words\n\t" + "BLT L_sp_384_cond_add_12_words%=\n\t" #else - "BLT.N L_sp_384_cond_add_12_words\n\t" + "BLT.N L_sp_384_cond_add_12_words%=\n\t" #endif "MOV %[r], r5\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -48974,7 +48974,7 @@ static sp_digit sp_384_sub_in_place_12(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x30\n\t" "\n" - "L_sp_384_sub_in_pkace_12_word:\n\t" + "L_sp_384_sub_in_pkace_12_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -48986,9 +48986,9 @@ static sp_digit sp_384_sub_in_place_12(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_384_sub_in_pkace_12_word\n\t" + "BNE L_sp_384_sub_in_pkace_12_word%=\n\t" #else - "BNE.N L_sp_384_sub_in_pkace_12_word\n\t" + "BNE.N L_sp_384_sub_in_pkace_12_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -49074,7 +49074,7 @@ static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_384_mul_d_12_word:\n\t" + "L_sp_384_mul_d_12_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -49088,9 +49088,9 @@ static void sp_384_mul_d_12(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x30\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_384_mul_d_12_word\n\t" + "BLT L_sp_384_mul_d_12_word%=\n\t" #else - "BLT.N L_sp_384_mul_d_12_word\n\t" + "BLT.N L_sp_384_mul_d_12_word%=\n\t" #endif "STR r3, [%[r], #48]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -49288,7 +49288,7 @@ SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, sp_digit d /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_384_word_12_bit:\n\t" + "L_div_384_word_12_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -49298,7 +49298,7 @@ SP_NOINLINE static sp_digit div_384_word_12(sp_digit d1, sp_digit d0, sp_digit d "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_384_word_12_bit\n\t" + "bpl L_div_384_word_12_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -49962,9 +49962,9 @@ static void sp_384_div2_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m "LDM %[a]!, {r4}\n\t" "ANDS r3, r4, #0x1\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_div2_mod_12_even\n\t" + "BEQ L_sp_384_div2_mod_12_even%=\n\t" #else - "BEQ.N L_sp_384_div2_mod_12_even\n\t" + "BEQ.N L_sp_384_div2_mod_12_even%=\n\t" #endif "MOV r12, #0x0\n\t" "LDM %[a]!, {r5, r6, r7}\n\t" @@ -49990,12 +49990,12 @@ static void sp_384_div2_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m "STM %[r]!, {r4, r5, r6, r7}\n\t" "ADC r3, r12, r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_div2_mod_12_div2\n\t" + "B L_sp_384_div2_mod_12_div2%=\n\t" #else - "B.N L_sp_384_div2_mod_12_div2\n\t" + "B.N L_sp_384_div2_mod_12_div2%=\n\t" #endif "\n" - "L_sp_384_div2_mod_12_even:\n\t" + "L_sp_384_div2_mod_12_even%=:\n\t" "LDM %[a]!, {r5, r6, r7}\n\t" "STM %[r]!, {r4, r5, r6, r7}\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" @@ -50003,7 +50003,7 @@ static void sp_384_div2_mod_12(sp_digit* r, const sp_digit* a, const sp_digit* m "LDM %[a]!, {r4, r5, r6, r7}\n\t" "STM %[r]!, {r4, r5, r6, r7}\n\t" "\n" - "L_sp_384_div2_mod_12_div2:\n\t" + "L_sp_384_div2_mod_12_div2%=:\n\t" "SUB %[r], %[r], #0x30\n\t" "LDRD r8, r9, [%[r]]\n\t" "LSR r8, r8, #1\n\t" @@ -50072,196 +50072,196 @@ static int sp_384_num_bits_12(const sp_digit* a) "LDR r1, [%[a], #44]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_11\n\t" + "BEQ L_sp_384_num_bits_12_11%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_11\n\t" + "BEQ.N L_sp_384_num_bits_12_11%=\n\t" #endif "MOV r2, #0x180\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_11:\n\t" + "L_sp_384_num_bits_12_11%=:\n\t" "LDR r1, [%[a], #40]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_10\n\t" + "BEQ L_sp_384_num_bits_12_10%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_10\n\t" + "BEQ.N L_sp_384_num_bits_12_10%=\n\t" #endif "MOV r2, #0x160\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_10:\n\t" + "L_sp_384_num_bits_12_10%=:\n\t" "LDR r1, [%[a], #36]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_9\n\t" + "BEQ L_sp_384_num_bits_12_9%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_9\n\t" + "BEQ.N L_sp_384_num_bits_12_9%=\n\t" #endif "MOV r2, #0x140\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_9:\n\t" + "L_sp_384_num_bits_12_9%=:\n\t" "LDR r1, [%[a], #32]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_8\n\t" + "BEQ L_sp_384_num_bits_12_8%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_8\n\t" + "BEQ.N L_sp_384_num_bits_12_8%=\n\t" #endif "MOV r2, #0x120\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_8:\n\t" + "L_sp_384_num_bits_12_8%=:\n\t" "LDR r1, [%[a], #28]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_7\n\t" + "BEQ L_sp_384_num_bits_12_7%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_7\n\t" + "BEQ.N L_sp_384_num_bits_12_7%=\n\t" #endif "MOV r2, #0x100\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_7:\n\t" + "L_sp_384_num_bits_12_7%=:\n\t" "LDR r1, [%[a], #24]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_6\n\t" + "BEQ L_sp_384_num_bits_12_6%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_6\n\t" + "BEQ.N L_sp_384_num_bits_12_6%=\n\t" #endif "MOV r2, #0xe0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_6:\n\t" + "L_sp_384_num_bits_12_6%=:\n\t" "LDR r1, [%[a], #20]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_5\n\t" + "BEQ L_sp_384_num_bits_12_5%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_5\n\t" + "BEQ.N L_sp_384_num_bits_12_5%=\n\t" #endif "MOV r2, #0xc0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_5:\n\t" + "L_sp_384_num_bits_12_5%=:\n\t" "LDR r1, [%[a], #16]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_4\n\t" + "BEQ L_sp_384_num_bits_12_4%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_4\n\t" + "BEQ.N L_sp_384_num_bits_12_4%=\n\t" #endif "MOV r2, #0xa0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_4:\n\t" + "L_sp_384_num_bits_12_4%=:\n\t" "LDR r1, [%[a], #12]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_3\n\t" + "BEQ L_sp_384_num_bits_12_3%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_3\n\t" + "BEQ.N L_sp_384_num_bits_12_3%=\n\t" #endif "MOV r2, #0x80\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_3:\n\t" + "L_sp_384_num_bits_12_3%=:\n\t" "LDR r1, [%[a], #8]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_2\n\t" + "BEQ L_sp_384_num_bits_12_2%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_2\n\t" + "BEQ.N L_sp_384_num_bits_12_2%=\n\t" #endif "MOV r2, #0x60\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_2:\n\t" + "L_sp_384_num_bits_12_2%=:\n\t" "LDR r1, [%[a], #4]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_384_num_bits_12_1\n\t" + "BEQ L_sp_384_num_bits_12_1%=\n\t" #else - "BEQ.N L_sp_384_num_bits_12_1\n\t" + "BEQ.N L_sp_384_num_bits_12_1%=\n\t" #endif "MOV r2, #0x40\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_384_num_bits_12_13\n\t" + "B L_sp_384_num_bits_12_13%=\n\t" #else - "B.N L_sp_384_num_bits_12_13\n\t" + "B.N L_sp_384_num_bits_12_13%=\n\t" #endif "\n" - "L_sp_384_num_bits_12_1:\n\t" + "L_sp_384_num_bits_12_1%=:\n\t" "LDR r1, [%[a]]\n\t" "MOV r2, #0x20\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" "\n" - "L_sp_384_num_bits_12_13:\n\t" + "L_sp_384_num_bits_12_13%=:\n\t" "MOV %[a], r4\n\t" : [a] "+r" (a) : @@ -51430,13 +51430,13 @@ static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_521_mul_17_outer:\n\t" + "L_sp_521_mul_17_outer%=:\n\t" "SUBS r3, r5, #0x40\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_521_mul_17_inner:\n\t" + "L_sp_521_mul_17_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -51453,14 +51453,14 @@ static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_521_mul_17_inner_done\n\t" + "BGT L_sp_521_mul_17_inner_done%=\n\t" #else - "BGT.N L_sp_521_mul_17_inner_done\n\t" + "BGT.N L_sp_521_mul_17_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_521_mul_17_inner\n\t" + "BLT L_sp_521_mul_17_inner%=\n\t" #else - "BLT.N L_sp_521_mul_17_inner\n\t" + "BLT.N L_sp_521_mul_17_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -51469,7 +51469,7 @@ static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_521_mul_17_inner_done:\n\t" + "L_sp_521_mul_17_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -51477,9 +51477,9 @@ static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x7c\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_521_mul_17_outer\n\t" + "BLE L_sp_521_mul_17_outer%=\n\t" #else - "BLE.N L_sp_521_mul_17_outer\n\t" + "BLE.N L_sp_521_mul_17_outer%=\n\t" #endif "LDR lr, [%[a], #64]\n\t" "LDR r11, [%[b], #64]\n\t" @@ -51491,14 +51491,14 @@ static void sp_521_mul_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "STM %[r]!, {r6, r7}\n\t" "SUB r5, r5, #0x8\n\t" "\n" - "L_sp_521_mul_17_store:\n\t" + "L_sp_521_mul_17_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_521_mul_17_store\n\t" + "BGT L_sp_521_mul_17_store%=\n\t" #else - "BGT.N L_sp_521_mul_17_store\n\t" + "BGT.N L_sp_521_mul_17_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -53575,13 +53575,13 @@ static void sp_521_sqr_17(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_521_sqr_17_outer:\n\t" + "L_sp_521_sqr_17_outer%=:\n\t" "SUBS r3, r5, #0x40\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_521_sqr_17_inner:\n\t" + "L_sp_521_sqr_17_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -53595,14 +53595,14 @@ static void sp_521_sqr_17(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_521_sqr_17_inner_done\n\t" + "BGT L_sp_521_sqr_17_inner_done%=\n\t" #else - "BGT.N L_sp_521_sqr_17_inner_done\n\t" + "BGT.N L_sp_521_sqr_17_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_521_sqr_17_inner\n\t" + "BLT L_sp_521_sqr_17_inner%=\n\t" #else - "BLT.N L_sp_521_sqr_17_inner\n\t" + "BLT.N L_sp_521_sqr_17_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -53610,7 +53610,7 @@ static void sp_521_sqr_17(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_521_sqr_17_inner_done:\n\t" + "L_sp_521_sqr_17_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -53618,9 +53618,9 @@ static void sp_521_sqr_17(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0x7c\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_521_sqr_17_outer\n\t" + "BLE L_sp_521_sqr_17_outer%=\n\t" #else - "BLE.N L_sp_521_sqr_17_outer\n\t" + "BLE.N L_sp_521_sqr_17_outer%=\n\t" #endif "LDR lr, [%[a], #64]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -53631,14 +53631,14 @@ static void sp_521_sqr_17(sp_digit* r, const sp_digit* a) "STM %[r]!, {r6, r7}\n\t" "SUB r5, r5, #0x8\n\t" "\n" - "L_sp_521_sqr_17_store:\n\t" + "L_sp_521_sqr_17_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_521_sqr_17_store\n\t" + "BGT L_sp_521_sqr_17_store%=\n\t" #else - "BGT.N L_sp_521_sqr_17_store\n\t" + "BGT.N L_sp_521_sqr_17_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -54955,7 +54955,7 @@ static sp_digit sp_521_add_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x40\n\t" "\n" - "L_sp_521_add_17_word:\n\t" + "L_sp_521_add_17_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -54968,9 +54968,9 @@ static sp_digit sp_521_add_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_521_add_17_word\n\t" + "BNE L_sp_521_add_17_word%=\n\t" #else - "BNE.N L_sp_521_add_17_word\n\t" + "BNE.N L_sp_521_add_17_word%=\n\t" #endif "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a], {r4}\n\t" @@ -55288,7 +55288,7 @@ static sp_digit sp_521_cond_sub_17(sp_digit* r, const sp_digit* a, const sp_digi "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_521_cond_sub_17_words:\n\t" + "L_sp_521_cond_sub_17_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -55299,9 +55299,9 @@ static sp_digit sp_521_cond_sub_17(sp_digit* r, const sp_digit* a, const sp_digi "ADD r5, r5, #0x4\n\t" "CMP r5, #0x44\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_521_cond_sub_17_words\n\t" + "BLT L_sp_521_cond_sub_17_words%=\n\t" #else - "BLT.N L_sp_521_cond_sub_17_words\n\t" + "BLT.N L_sp_521_cond_sub_17_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -55568,19 +55568,19 @@ SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a, const sp_digit* "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_521_mont_reduce_order_17_word:\n\t" + "L_sp_521_mont_reduce_order_17_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" "CMP r11, #0x40\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_521_mont_reduce_order_17_nomask\n\t" + "BNE L_sp_521_mont_reduce_order_17_nomask%=\n\t" #else - "BNE.N L_sp_521_mont_reduce_order_17_nomask\n\t" + "BNE.N L_sp_521_mont_reduce_order_17_nomask%=\n\t" #endif "MOV r9, #0x1ff\n\t" "AND r10, r10, r9\n\t" "\n" - "L_sp_521_mont_reduce_order_17_nomask:\n\t" + "L_sp_521_mont_reduce_order_17_nomask%=:\n\t" /* a[i+0] += m[0] * mu */ "MOV r7, #0x0\n\t" "UMLAL r4, r7, r10, lr\n\t" @@ -55722,9 +55722,9 @@ SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a, const sp_digit* "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x44\n\t" #ifdef __GNUC__ - "BLT L_sp_521_mont_reduce_order_17_word\n\t" + "BLT L_sp_521_mont_reduce_order_17_word%=\n\t" #else - "BLT.W L_sp_521_mont_reduce_order_17_word\n\t" + "BLT.W L_sp_521_mont_reduce_order_17_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -55836,19 +55836,19 @@ SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a, const sp_digit* "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_521_mont_reduce_order_17_word:\n\t" + "L_sp_521_mont_reduce_order_17_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" "CMP r4, #0x40\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_521_mont_reduce_order_17_nomask\n\t" + "BNE L_sp_521_mont_reduce_order_17_nomask%=\n\t" #else - "BNE.N L_sp_521_mont_reduce_order_17_nomask\n\t" + "BNE.N L_sp_521_mont_reduce_order_17_nomask%=\n\t" #endif "MOV r12, #0x1ff\n\t" "AND lr, lr, r12\n\t" "\n" - "L_sp_521_mont_reduce_order_17_nomask:\n\t" + "L_sp_521_mont_reduce_order_17_nomask%=:\n\t" /* a[i+0] += m[0] * mu */ "LDR r12, [%[m]]\n\t" "MOV r3, #0x0\n\t" @@ -55940,9 +55940,9 @@ SP_NOINLINE static void sp_521_mont_reduce_order_17(sp_digit* a, const sp_digit* "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x44\n\t" #ifdef __GNUC__ - "BLT L_sp_521_mont_reduce_order_17_word\n\t" + "BLT L_sp_521_mont_reduce_order_17_word%=\n\t" #else - "BLT.W L_sp_521_mont_reduce_order_17_word\n\t" + "BLT.W L_sp_521_mont_reduce_order_17_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -56194,7 +56194,7 @@ static sp_int32 sp_521_cmp_17(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x40\n\t" "\n" - "L_sp_521_cmp_17_words:\n\t" + "L_sp_521_cmp_17_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -56207,7 +56207,7 @@ static sp_int32 sp_521_cmp_17(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_521_cmp_17_words\n\t" + "bcs L_sp_521_cmp_17_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #64]\n\t" @@ -61995,7 +61995,7 @@ static sp_digit sp_521_sub_in_place_17(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x40\n\t" "\n" - "L_sp_521_sub_in_pkace_17_word:\n\t" + "L_sp_521_sub_in_pkace_17_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -62007,9 +62007,9 @@ static sp_digit sp_521_sub_in_place_17(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_521_sub_in_pkace_17_word\n\t" + "BNE L_sp_521_sub_in_pkace_17_word%=\n\t" #else - "BNE.N L_sp_521_sub_in_pkace_17_word\n\t" + "BNE.N L_sp_521_sub_in_pkace_17_word%=\n\t" #endif "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2}\n\t" @@ -62111,7 +62111,7 @@ static void sp_521_mul_d_17(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_521_mul_d_17_word:\n\t" + "L_sp_521_mul_d_17_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -62125,9 +62125,9 @@ static void sp_521_mul_d_17(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x44\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_521_mul_d_17_word\n\t" + "BLT L_sp_521_mul_d_17_word%=\n\t" #else - "BLT.N L_sp_521_mul_d_17_word\n\t" + "BLT.N L_sp_521_mul_d_17_word%=\n\t" #endif "STR r3, [%[r], #68]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -62350,7 +62350,7 @@ SP_NOINLINE static sp_digit div_521_word_17(sp_digit d1, sp_digit d0, sp_digit d /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_521_word_17_bit:\n\t" + "L_div_521_word_17_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -62360,7 +62360,7 @@ SP_NOINLINE static sp_digit div_521_word_17(sp_digit d1, sp_digit d0, sp_digit d "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_521_word_17_bit\n\t" + "bpl L_div_521_word_17_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -63055,7 +63055,7 @@ static sp_digit sp_521_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r11, #0x0\n\t" "ADD r12, %[a], #0x40\n\t" "\n" - "L_sp_521_sub_17_word:\n\t" + "L_sp_521_sub_17_word%=:\n\t" "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3, r4, r5, r6}\n\t" "LDM %[b]!, {r7, r8, r9, r10}\n\t" @@ -63067,9 +63067,9 @@ static sp_digit sp_521_sub_17(sp_digit* r, const sp_digit* a, const sp_digit* b) "SBC r11, r3, r3\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_521_sub_17_word\n\t" + "BNE L_sp_521_sub_17_word%=\n\t" #else - "BNE.N L_sp_521_sub_17_word\n\t" + "BNE.N L_sp_521_sub_17_word%=\n\t" #endif "RSBS r11, r11, #0x0\n\t" "LDM %[a]!, {r3}\n\t" @@ -63167,9 +63167,9 @@ static void sp_521_div2_mod_17(sp_digit* r, const sp_digit* a, const sp_digit* m "LDM %[a]!, {r4}\n\t" "ANDS r3, r4, #0x1\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_div2_mod_17_even\n\t" + "BEQ L_sp_521_div2_mod_17_even%=\n\t" #else - "BEQ.N L_sp_521_div2_mod_17_even\n\t" + "BEQ.N L_sp_521_div2_mod_17_even%=\n\t" #endif "MOV r12, #0x0\n\t" "LDM %[a]!, {r5, r6, r7}\n\t" @@ -63206,12 +63206,12 @@ static void sp_521_div2_mod_17(sp_digit* r, const sp_digit* a, const sp_digit* m "STM %[r]!, {r4}\n\t" "ADC r3, r12, r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_div2_mod_17_div2\n\t" + "B L_sp_521_div2_mod_17_div2%=\n\t" #else - "B.N L_sp_521_div2_mod_17_div2\n\t" + "B.N L_sp_521_div2_mod_17_div2%=\n\t" #endif "\n" - "L_sp_521_div2_mod_17_even:\n\t" + "L_sp_521_div2_mod_17_even%=:\n\t" "LDM %[a]!, {r5, r6, r7}\n\t" "STM %[r]!, {r4, r5, r6, r7}\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" @@ -63223,7 +63223,7 @@ static void sp_521_div2_mod_17(sp_digit* r, const sp_digit* a, const sp_digit* m "LDM %[a]!, {r4}\n\t" "STM %[r]!, {r4}\n\t" "\n" - "L_sp_521_div2_mod_17_div2:\n\t" + "L_sp_521_div2_mod_17_div2%=:\n\t" "SUB %[r], %[r], #0x44\n\t" "LDRD r8, r9, [%[r]]\n\t" "LSR r8, r8, #1\n\t" @@ -63312,281 +63312,281 @@ static int sp_521_num_bits_17(const sp_digit* a) "LDR r1, [%[a], #64]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_16\n\t" + "BEQ L_sp_521_num_bits_17_16%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_16\n\t" + "BEQ.N L_sp_521_num_bits_17_16%=\n\t" #endif "MOV r2, #0x220\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_16:\n\t" + "L_sp_521_num_bits_17_16%=:\n\t" "LDR r1, [%[a], #60]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_15\n\t" + "BEQ L_sp_521_num_bits_17_15%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_15\n\t" + "BEQ.N L_sp_521_num_bits_17_15%=\n\t" #endif "MOV r2, #0x200\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_15:\n\t" + "L_sp_521_num_bits_17_15%=:\n\t" "LDR r1, [%[a], #56]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_14\n\t" + "BEQ L_sp_521_num_bits_17_14%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_14\n\t" + "BEQ.N L_sp_521_num_bits_17_14%=\n\t" #endif "MOV r2, #0x1e0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_14:\n\t" + "L_sp_521_num_bits_17_14%=:\n\t" "LDR r1, [%[a], #52]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_13\n\t" + "BEQ L_sp_521_num_bits_17_13%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_13\n\t" + "BEQ.N L_sp_521_num_bits_17_13%=\n\t" #endif "MOV r2, #0x1c0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_13:\n\t" + "L_sp_521_num_bits_17_13%=:\n\t" "LDR r1, [%[a], #48]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_12\n\t" + "BEQ L_sp_521_num_bits_17_12%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_12\n\t" + "BEQ.N L_sp_521_num_bits_17_12%=\n\t" #endif "MOV r2, #0x1a0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_12:\n\t" + "L_sp_521_num_bits_17_12%=:\n\t" "LDR r1, [%[a], #44]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_11\n\t" + "BEQ L_sp_521_num_bits_17_11%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_11\n\t" + "BEQ.N L_sp_521_num_bits_17_11%=\n\t" #endif "MOV r2, #0x180\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_11:\n\t" + "L_sp_521_num_bits_17_11%=:\n\t" "LDR r1, [%[a], #40]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_10\n\t" + "BEQ L_sp_521_num_bits_17_10%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_10\n\t" + "BEQ.N L_sp_521_num_bits_17_10%=\n\t" #endif "MOV r2, #0x160\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_10:\n\t" + "L_sp_521_num_bits_17_10%=:\n\t" "LDR r1, [%[a], #36]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_9\n\t" + "BEQ L_sp_521_num_bits_17_9%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_9\n\t" + "BEQ.N L_sp_521_num_bits_17_9%=\n\t" #endif "MOV r2, #0x140\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_9:\n\t" + "L_sp_521_num_bits_17_9%=:\n\t" "LDR r1, [%[a], #32]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_8\n\t" + "BEQ L_sp_521_num_bits_17_8%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_8\n\t" + "BEQ.N L_sp_521_num_bits_17_8%=\n\t" #endif "MOV r2, #0x120\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_8:\n\t" + "L_sp_521_num_bits_17_8%=:\n\t" "LDR r1, [%[a], #28]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_7\n\t" + "BEQ L_sp_521_num_bits_17_7%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_7\n\t" + "BEQ.N L_sp_521_num_bits_17_7%=\n\t" #endif "MOV r2, #0x100\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_7:\n\t" + "L_sp_521_num_bits_17_7%=:\n\t" "LDR r1, [%[a], #24]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_6\n\t" + "BEQ L_sp_521_num_bits_17_6%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_6\n\t" + "BEQ.N L_sp_521_num_bits_17_6%=\n\t" #endif "MOV r2, #0xe0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_6:\n\t" + "L_sp_521_num_bits_17_6%=:\n\t" "LDR r1, [%[a], #20]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_5\n\t" + "BEQ L_sp_521_num_bits_17_5%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_5\n\t" + "BEQ.N L_sp_521_num_bits_17_5%=\n\t" #endif "MOV r2, #0xc0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_5:\n\t" + "L_sp_521_num_bits_17_5%=:\n\t" "LDR r1, [%[a], #16]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_4\n\t" + "BEQ L_sp_521_num_bits_17_4%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_4\n\t" + "BEQ.N L_sp_521_num_bits_17_4%=\n\t" #endif "MOV r2, #0xa0\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_4:\n\t" + "L_sp_521_num_bits_17_4%=:\n\t" "LDR r1, [%[a], #12]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_3\n\t" + "BEQ L_sp_521_num_bits_17_3%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_3\n\t" + "BEQ.N L_sp_521_num_bits_17_3%=\n\t" #endif "MOV r2, #0x80\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_3:\n\t" + "L_sp_521_num_bits_17_3%=:\n\t" "LDR r1, [%[a], #8]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_2\n\t" + "BEQ L_sp_521_num_bits_17_2%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_2\n\t" + "BEQ.N L_sp_521_num_bits_17_2%=\n\t" #endif "MOV r2, #0x60\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_2:\n\t" + "L_sp_521_num_bits_17_2%=:\n\t" "LDR r1, [%[a], #4]\n\t" "CMP r1, #0x0\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BEQ L_sp_521_num_bits_17_1\n\t" + "BEQ L_sp_521_num_bits_17_1%=\n\t" #else - "BEQ.N L_sp_521_num_bits_17_1\n\t" + "BEQ.N L_sp_521_num_bits_17_1%=\n\t" #endif "MOV r2, #0x40\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "B L_sp_521_num_bits_17_18\n\t" + "B L_sp_521_num_bits_17_18%=\n\t" #else - "B.N L_sp_521_num_bits_17_18\n\t" + "B.N L_sp_521_num_bits_17_18%=\n\t" #endif "\n" - "L_sp_521_num_bits_17_1:\n\t" + "L_sp_521_num_bits_17_1%=:\n\t" "LDR r1, [%[a]]\n\t" "MOV r2, #0x20\n\t" "CLZ r4, r1\n\t" "SUB r4, r2, r4\n\t" "\n" - "L_sp_521_num_bits_17_18:\n\t" + "L_sp_521_num_bits_17_18%=:\n\t" "MOV %[a], r4\n\t" : [a] "+r" (a) : @@ -67981,13 +67981,13 @@ static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_1024_mul_32_outer:\n\t" + "L_sp_1024_mul_32_outer%=:\n\t" "SUBS r3, r5, #0x7c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_1024_mul_32_inner:\n\t" + "L_sp_1024_mul_32_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -68004,14 +68004,14 @@ static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_1024_mul_32_inner_done\n\t" + "BGT L_sp_1024_mul_32_inner_done%=\n\t" #else - "BGT.N L_sp_1024_mul_32_inner_done\n\t" + "BGT.N L_sp_1024_mul_32_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_1024_mul_32_inner\n\t" + "BLT L_sp_1024_mul_32_inner%=\n\t" #else - "BLT.N L_sp_1024_mul_32_inner\n\t" + "BLT.N L_sp_1024_mul_32_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[b], r3]\n\t" @@ -68020,7 +68020,7 @@ static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_1024_mul_32_inner_done:\n\t" + "L_sp_1024_mul_32_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -68028,9 +68028,9 @@ static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "CMP r5, #0xf4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_1024_mul_32_outer\n\t" + "BLE L_sp_1024_mul_32_outer%=\n\t" #else - "BLE.N L_sp_1024_mul_32_outer\n\t" + "BLE.N L_sp_1024_mul_32_outer%=\n\t" #endif "LDR lr, [%[a], #124]\n\t" "LDR r11, [%[b], #124]\n\t" @@ -68039,14 +68039,14 @@ static void sp_1024_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_1024_mul_32_store:\n\t" + "L_sp_1024_mul_32_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_1024_mul_32_store\n\t" + "BGT L_sp_1024_mul_32_store%=\n\t" #else - "BGT.N L_sp_1024_mul_32_store\n\t" + "BGT.N L_sp_1024_mul_32_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) : @@ -68079,13 +68079,13 @@ static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) "MOV r8, #0x0\n\t" "MOV r5, #0x4\n\t" "\n" - "L_sp_1024_sqr_32_outer:\n\t" + "L_sp_1024_sqr_32_outer%=:\n\t" "SUBS r3, r5, #0x7c\n\t" "IT cc\n\t" "MOVCC r3, #0x0\n\t" "SUB r4, r5, r3\n\t" "\n" - "L_sp_1024_sqr_32_inner:\n\t" + "L_sp_1024_sqr_32_inner%=:\n\t" "LDR lr, [%[a], r3]\n\t" "LDR r11, [%[a], r4]\n\t" "UMULL r9, r10, lr, r11\n\t" @@ -68099,14 +68099,14 @@ static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) "SUB r4, r4, #0x4\n\t" "CMP r3, r4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_1024_sqr_32_inner_done\n\t" + "BGT L_sp_1024_sqr_32_inner_done%=\n\t" #else - "BGT.N L_sp_1024_sqr_32_inner_done\n\t" + "BGT.N L_sp_1024_sqr_32_inner_done%=\n\t" #endif #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_1024_sqr_32_inner\n\t" + "BLT L_sp_1024_sqr_32_inner%=\n\t" #else - "BLT.N L_sp_1024_sqr_32_inner\n\t" + "BLT.N L_sp_1024_sqr_32_inner%=\n\t" #endif "LDR lr, [%[a], r3]\n\t" "UMULL r9, r10, lr, lr\n\t" @@ -68114,7 +68114,7 @@ static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) "ADCS r7, r7, r10\n\t" "ADC r8, r8, #0x0\n\t" "\n" - "L_sp_1024_sqr_32_inner_done:\n\t" + "L_sp_1024_sqr_32_inner_done%=:\n\t" "STR r6, [sp, r5]\n\t" "MOV r6, r7\n\t" "MOV r7, r8\n\t" @@ -68122,9 +68122,9 @@ static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "CMP r5, #0xf4\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLE L_sp_1024_sqr_32_outer\n\t" + "BLE L_sp_1024_sqr_32_outer%=\n\t" #else - "BLE.N L_sp_1024_sqr_32_outer\n\t" + "BLE.N L_sp_1024_sqr_32_outer%=\n\t" #endif "LDR lr, [%[a], #124]\n\t" "UMLAL r6, r7, lr, lr\n\t" @@ -68132,14 +68132,14 @@ static void sp_1024_sqr_32(sp_digit* r, const sp_digit* a) "ADD r5, r5, #0x4\n\t" "STR r7, [sp, r5]\n\t" "\n" - "L_sp_1024_sqr_32_store:\n\t" + "L_sp_1024_sqr_32_store%=:\n\t" "LDM sp!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "STM %[r]!, {r3, r4, r6, r7, r8, r9, r10, r11}\n\t" "SUBS r5, r5, #0x20\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BGT L_sp_1024_sqr_32_store\n\t" + "BGT L_sp_1024_sqr_32_store%=\n\t" #else - "BGT.N L_sp_1024_sqr_32_store\n\t" + "BGT.N L_sp_1024_sqr_32_store%=\n\t" #endif : [r] "+r" (r), [a] "+r" (a) : @@ -68254,7 +68254,7 @@ static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b) "MOV r10, #0x0\n\t" "ADD r11, %[a], #0x80\n\t" "\n" - "L_sp_1024_sub_in_pkace_32_word:\n\t" + "L_sp_1024_sub_in_pkace_32_word%=:\n\t" "RSBS r10, r10, #0x0\n\t" "LDM %[a], {r2, r3, r4, r5}\n\t" "LDM %[b]!, {r6, r7, r8, r9}\n\t" @@ -68266,9 +68266,9 @@ static sp_digit sp_1024_sub_in_place_32(sp_digit* a, const sp_digit* b) "SBC r10, r10, r10\n\t" "CMP %[a], r11\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_1024_sub_in_pkace_32_word\n\t" + "BNE L_sp_1024_sub_in_pkace_32_word%=\n\t" #else - "BNE.N L_sp_1024_sub_in_pkace_32_word\n\t" + "BNE.N L_sp_1024_sub_in_pkace_32_word%=\n\t" #endif "MOV %[a], r10\n\t" : [a] "+r" (a), [b] "+r" (b) @@ -68306,7 +68306,7 @@ static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_dig "MOV r4, #0x0\n\t" "MOV r5, #0x0\n\t" "\n" - "L_sp_1024_cond_sub_32_words:\n\t" + "L_sp_1024_cond_sub_32_words%=:\n\t" "SUBS r4, r8, r4\n\t" "LDR r6, [%[a], r5]\n\t" "LDR r7, [%[b], r5]\n\t" @@ -68317,9 +68317,9 @@ static sp_digit sp_1024_cond_sub_32(sp_digit* r, const sp_digit* a, const sp_dig "ADD r5, r5, #0x4\n\t" "CMP r5, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_1024_cond_sub_32_words\n\t" + "BLT L_sp_1024_cond_sub_32_words%=\n\t" #else - "BLT.N L_sp_1024_cond_sub_32_words\n\t" + "BLT.N L_sp_1024_cond_sub_32_words%=\n\t" #endif "MOV %[r], r4\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) @@ -68497,7 +68497,7 @@ static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b "MOV r3, #0x0\n\t" "ADD r12, %[a], #0x80\n\t" "\n" - "L_sp_1024_add_32_word:\n\t" + "L_sp_1024_add_32_word%=:\n\t" "ADDS r3, r3, #0xffffffff\n\t" "LDM %[a]!, {r4, r5, r6, r7}\n\t" "LDM %[b]!, {r8, r9, r10, r11}\n\t" @@ -68510,9 +68510,9 @@ static sp_digit sp_1024_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b "ADC r3, r4, #0x0\n\t" "CMP %[a], r12\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BNE L_sp_1024_add_32_word\n\t" + "BNE L_sp_1024_add_32_word%=\n\t" #else - "BNE.N L_sp_1024_add_32_word\n\t" + "BNE.N L_sp_1024_add_32_word%=\n\t" #endif "MOV %[r], r3\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -68551,7 +68551,7 @@ static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b) "MOV r5, #0x0\n\t" "MOV r9, #0x4\n\t" "\n" - "L_sp_1024_mul_d_32_word:\n\t" + "L_sp_1024_mul_d_32_word%=:\n\t" /* A[i] * B */ "LDR r8, [%[a], r9]\n\t" "UMULL r6, r7, %[b], r8\n\t" @@ -68565,9 +68565,9 @@ static void sp_1024_mul_d_32(sp_digit* r, const sp_digit* a, sp_digit b) "ADD r9, r9, #0x4\n\t" "CMP r9, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_1024_mul_d_32_word\n\t" + "BLT L_sp_1024_mul_d_32_word%=\n\t" #else - "BLT.N L_sp_1024_mul_d_32_word\n\t" + "BLT.N L_sp_1024_mul_d_32_word%=\n\t" #endif "STR r3, [%[r], #128]\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) @@ -68865,7 +68865,7 @@ SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, sp_digit /* Next 30 bits */ "MOV r4, #0x1d\n\t" "\n" - "L_div_1024_word_32_bit:\n\t" + "L_div_1024_word_32_bit%=:\n\t" "LSLS r6, r6, #1\n\t" "ADC r7, r7, r7\n\t" "SUBS r8, r5, r7\n\t" @@ -68875,7 +68875,7 @@ SP_NOINLINE static sp_digit div_1024_word_32(sp_digit d1, sp_digit d0, sp_digit "AND r8, r8, r5\n\t" "SUBS r7, r7, r8\n\t" "SUBS r4, r4, #0x1\n\t" - "bpl L_div_1024_word_32_bit\n\t" + "bpl L_div_1024_word_32_bit%=\n\t" "ADD r3, r3, r3\n\t" "ADD r3, r3, #0x1\n\t" "UMULL r6, r7, r3, %[div]\n\t" @@ -68957,7 +68957,7 @@ static sp_int32 sp_1024_cmp_32(const sp_digit* a, const sp_digit* b) #ifdef WOLFSSL_SP_SMALL "MOV r6, #0x7c\n\t" "\n" - "L_sp_1024_cmp_32_words:\n\t" + "L_sp_1024_cmp_32_words%=:\n\t" "LDR r4, [%[a], r6]\n\t" "LDR r5, [%[b], r6]\n\t" "AND r4, r4, r3\n\t" @@ -68970,7 +68970,7 @@ static sp_int32 sp_1024_cmp_32(const sp_digit* a, const sp_digit* b) "IT ne\n\t" "movne r3, r7\n\t" "SUBS r6, r6, #0x4\n\t" - "bcs L_sp_1024_cmp_32_words\n\t" + "bcs L_sp_1024_cmp_32_words%=\n\t" "EOR r2, r2, r3\n\t" #else "LDR r4, [%[a], #124]\n\t" @@ -69690,7 +69690,7 @@ SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, s "LDR r4, [%[a]]\n\t" "LDR r5, [%[a], #4]\n\t" "\n" - "L_sp_1024_mont_reduce_32_word:\n\t" + "L_sp_1024_mont_reduce_32_word%=:\n\t" /* mu = a[i] * mp */ "MUL r10, %[mp], r4\n\t" /* a[i+0] += m[0] * mu */ @@ -69953,9 +69953,9 @@ SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r11, #0x80\n\t" #ifdef __GNUC__ - "BLT L_sp_1024_mont_reduce_32_word\n\t" + "BLT L_sp_1024_mont_reduce_32_word%=\n\t" #else - "BLT.W L_sp_1024_mont_reduce_32_word\n\t" + "BLT.W L_sp_1024_mont_reduce_32_word%=\n\t" #endif /* Loop Done */ "STR r4, [%[a]]\n\t" @@ -70002,7 +70002,7 @@ SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, s "LDR r9, [%[a], #12]\n\t" "LDR r10, [%[a], #16]\n\t" "\n" - "L_sp_1024_mont_reduce_32_word:\n\t" + "L_sp_1024_mont_reduce_32_word%=:\n\t" /* mu = a[i] * mp */ "MUL lr, %[mp], r6\n\t" /* a[i+0] += m[0] * mu */ @@ -70170,9 +70170,9 @@ SP_NOINLINE static void sp_1024_mont_reduce_32(sp_digit* a, const sp_digit* m, s "ADD %[a], %[a], #0x4\n\t" "CMP r4, #0x80\n\t" #ifdef __GNUC__ - "BLT L_sp_1024_mont_reduce_32_word\n\t" + "BLT L_sp_1024_mont_reduce_32_word%=\n\t" #else - "BLT.W L_sp_1024_mont_reduce_32_word\n\t" + "BLT.W L_sp_1024_mont_reduce_32_word%=\n\t" #endif /* Loop Done */ "STR r6, [%[a]]\n\t" @@ -71187,7 +71187,7 @@ static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig "MOV r8, #0x0\n\t" "MOV r4, #0x0\n\t" "\n" - "L_sp_1024_cond_add_32_words:\n\t" + "L_sp_1024_cond_add_32_words%=:\n\t" "ADDS r5, r5, #0xffffffff\n\t" "LDR r6, [%[a], r4]\n\t" "LDR r7, [%[b], r4]\n\t" @@ -71198,9 +71198,9 @@ static sp_digit sp_1024_cond_add_32(sp_digit* r, const sp_digit* a, const sp_dig "ADD r4, r4, #0x4\n\t" "CMP r4, #0x80\n\t" #if defined(__GNUC__) || defined(__ICCARM__) || defined(__IAR_SYSTEMS_ICC__) - "BLT L_sp_1024_cond_add_32_words\n\t" + "BLT L_sp_1024_cond_add_32_words%=\n\t" #else - "BLT.N L_sp_1024_cond_add_32_words\n\t" + "BLT.N L_sp_1024_cond_add_32_words%=\n\t" #endif "MOV %[r], r5\n\t" : [r] "+r" (r), [a] "+r" (a), [b] "+r" (b), [m] "+r" (m) diff --git a/src/wolfcrypt/src/sp_int.c b/src/wolfcrypt/src/sp_int.c index 83a1306..3a6884a 100644 --- a/src/wolfcrypt/src/sp_int.c +++ b/src/wolfcrypt/src/sp_int.c @@ -8097,6 +8097,27 @@ int sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r) } #endif /* WOLFSSL_SP_MATH_ALL && HAVE_ECC */ +#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) && \ + defined(WOLFSSL_ECC_BLIND_K) +void sp_xor_ct(const sp_int* a, const sp_int* b, int len, sp_int* r) +{ + if ((a != NULL) && (b != NULL) && (r != NULL)) { + unsigned int i; + + r->used = (len * 8 + SP_WORD_SIZE - 1) / SP_WORD_SIZE; + for (i = 0; i < r->used; i++) { + r->dp[i] = a->dp[i] ^ b->dp[i]; + } + i = (len * 8) % SP_WORD_SIZE; + if (i > 0) { + r->dp[r->used - 1] &= ((sp_int_digit)1 << i) - 1; + } + /* Remove leading zeros. */ + sp_clamp_ct(r); + } +} +#endif + /******************** * Shifting functoins ********************/ diff --git a/src/wolfcrypt/src/sphincs.c b/src/wolfcrypt/src/sphincs.c index a0196ce..05ba27f 100644 --- a/src/wolfcrypt/src/sphincs.c +++ b/src/wolfcrypt/src/sphincs.c @@ -431,7 +431,8 @@ static int parse_private_key(const byte* priv, word32 privSz, /* At this point, it is still a PKCS8 private key. */ if ((ret = ToTraditionalInline(priv, &idx, privSz)) < 0) { - return ret; + /* ignore error, did not have PKCS8 header */ + (void)ret; } /* Now it is a octet_string(concat(priv,pub)) */ @@ -952,7 +953,7 @@ int wc_Sphincs_PublicKeyToDer(sphincs_key* key, byte* output, word32 inLen, word32 pubKeyLen = (word32)sizeof(pubKey); int keytype = 0; - if (key == NULL || output == NULL) { + if (key == NULL) { return BAD_FUNC_ARG; } diff --git a/src/wolfcrypt/src/srp.c b/src/wolfcrypt/src/srp.c index e32c353..b914f58 100644 --- a/src/wolfcrypt/src/srp.c +++ b/src/wolfcrypt/src/srp.c @@ -908,27 +908,27 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, if (digest) XFREE(digest, srp->heap, DYNAMIC_TYPE_SRP); if (u) { - if (r != MP_INIT_E) + if (r != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(u); XFREE(u, srp->heap, DYNAMIC_TYPE_SRP); } if (s) { - if (r != MP_INIT_E) + if (r != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(s); XFREE(s, srp->heap, DYNAMIC_TYPE_SRP); } if (temp1) { - if (r != MP_INIT_E) + if (r != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(temp1); XFREE(temp1, srp->heap, DYNAMIC_TYPE_SRP); } if (temp2) { - if (r != MP_INIT_E) + if (r != WC_NO_ERR_TRACE(MP_INIT_E)) mp_clear(temp2); XFREE(temp2, srp->heap, DYNAMIC_TYPE_SRP); } #else - if (r != MP_INIT_E) { + if (r != WC_NO_ERR_TRACE(MP_INIT_E)) { mp_clear(u); mp_clear(s); mp_clear(temp1); diff --git a/src/wolfcrypt/src/wc_encrypt.c b/src/wolfcrypt/src/wc_encrypt.c index 506ac11..3b6d87d 100644 --- a/src/wolfcrypt/src/wc_encrypt.c +++ b/src/wolfcrypt/src/wc_encrypt.c @@ -244,7 +244,7 @@ int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz, const byte* password, int passwordSz, int hashType) { - int ret = NOT_COMPILED_IN; + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SMALL_STACK byte* key = NULL; #else @@ -318,7 +318,7 @@ int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz, int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz, const byte* password, int passwordSz, int hashType) { - int ret = NOT_COMPILED_IN; + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); #ifdef WOLFSSL_SMALL_STACK byte* key = NULL; #else @@ -545,9 +545,15 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz, iterations, (int)derivedLen, typeH, 1); + if (ret < 0) + break; if (id != PBE_SHA1_RC4_128) { - ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, + i = ret; + ret = wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz, iterations, 8, typeH, 2); + if (ret < 0) + break; + ret += i; } break; } @@ -658,15 +664,21 @@ int wc_CryptKey(const char* password, int passwordSz, byte* salt, AES_ENCRYPTION); } else { + #ifdef HAVE_AES_DECRYPT ret = wc_AesSetKey(aes, key, derivedLen, cbcIv, AES_DECRYPTION); + #else + ret = NOT_COMPILED_IN; + #endif } } if (ret == 0) { if (enc) ret = wc_AesCbcEncrypt(aes, input, input, (word32)length); + #ifdef HAVE_AES_DECRYPT else ret = wc_AesCbcDecrypt(aes, input, input, (word32)length); + #endif } if (free_aes) wc_AesFree(aes); diff --git a/src/wolfcrypt/src/wc_kyber.c b/src/wolfcrypt/src/wc_kyber.c index b0b358f..ffa37d8 100644 --- a/src/wolfcrypt/src/wc_kyber.c +++ b/src/wolfcrypt/src/wc_kyber.c @@ -59,6 +59,11 @@ /******************************************************************************/ +/* Declare variable to make compiler not optimize code in kyber_from_msg(). */ +volatile sword16 kyber_opt_blocker = 0; + +/******************************************************************************/ + /** * Initialize the Kyber key. * @@ -203,7 +208,7 @@ int wc_KyberKey_MakeKeyWithRandom(KyberKey* key, const unsigned char* rand, byte* pubSeed = buf; byte* noiseSeed = buf + KYBER_SYM_SZ; sword16* a = NULL; - sword16* e; + sword16* e = NULL; int ret = 0; int kp = 0; @@ -364,12 +369,12 @@ static int kyberkey_encapsulate(KyberKey* key, const byte* msg, byte* coins, unsigned char* ct) { int ret = 0; - sword16* sp; - sword16* ep; - sword16* k; - sword16* epp; - unsigned int kp; - unsigned int compVecSz; + sword16* sp = NULL; + sword16* ep = NULL; + sword16* k = NULL; + sword16* epp = NULL; + unsigned int kp = 0; + unsigned int compVecSz = 0; #ifndef USE_INTEL_SPEEDUP sword16* at = NULL; #else @@ -528,7 +533,9 @@ int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, byte msg[2 * KYBER_SYM_SZ]; byte kr[2 * KYBER_SYM_SZ + 1]; int ret = 0; - unsigned int ctSz; +#ifndef WOLFSSL_ML_KEM + unsigned int ctSz = 0; +#endif /* Validate parameters. */ if ((key == NULL) || (ct == NULL) || (ss == NULL) || (rand == NULL)) { @@ -538,6 +545,7 @@ int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, ret = BUFFER_E; } +#ifndef WOLFSSL_ML_KEM if (ret == 0) { /* Establish parameters based on key type. */ switch (key->type) { @@ -562,6 +570,7 @@ int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, break; } } +#endif /* If public hash (h) is not stored against key, calculate it. */ if ((ret == 0) && ((key->flags & KYBER_FLAG_H_SET) == 0)) { @@ -591,8 +600,12 @@ int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, } if (ret == 0) { +#ifndef WOLFSSL_ML_KEM /* Hash random to anonymize as seed data. */ ret = KYBER_HASH_H(rand, KYBER_SYM_SZ, msg); +#else + XMEMCPY(msg, rand, KYBER_SYM_SZ); +#endif } if (ret == 0) { /* Copy the hash of the public key into msg. */ @@ -607,6 +620,7 @@ int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, ret = kyberkey_encapsulate(key, msg, kr + KYBER_SYM_SZ, ct); } +#ifndef WOLFSSL_ML_KEM if (ret == 0) { /* Hash the cipher text after the seed. */ ret = KYBER_HASH_H(ct, ctSz, kr + KYBER_SYM_SZ); @@ -615,6 +629,11 @@ int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, /* Derive the secret from the seed and hash of cipher text. */ ret = KYBER_KDF(kr, 2 * KYBER_SYM_SZ, ss, KYBER_SS_SZ); } +#else + if (ret == 0) { + XMEMCPY(ss, kr, KYBER_SS_SZ); + } +#endif return ret; } @@ -636,7 +655,7 @@ static KYBER_NOINLINE int kyberkey_decapsulate(KyberKey* key, int ret = 0; sword16* v; sword16* mp; - unsigned int kp; + unsigned int kp = 0; unsigned int compVecSz; #ifndef USE_INTEL_SPEEDUP sword16* bp = NULL; @@ -720,6 +739,39 @@ static KYBER_NOINLINE int kyberkey_decapsulate(KyberKey* key, return ret; } +#ifdef WOLFSSL_ML_KEM +/* Derive the secret from z and cipher text. + * + * @param [in] z Implicit rejection value. + * @param [in] ct Cipher text. + * @param [in] ctSz Length of cipher text in bytes. + * @param [out] ss Shared secret. + * @return 0 on success. + * @return MEMORY_E when dynamic memory allocation failed. + * @return Other negative when a hash error occurred. + */ +static int kyber_derive_secret(const byte* z, const byte* ct, word32 ctSz, + byte* ss) +{ + int ret; + wc_Shake shake; + + ret = wc_InitShake256(&shake, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Shake256_Update(&shake, z, KYBER_SYM_SZ); + if (ret == 0) { + ret = wc_Shake256_Update(&shake, ct, ctSz); + } + if (ret == 0) { + ret = wc_Shake256_Final(&shake, ss, KYBER_SS_SZ); + } + wc_Shake256_Free(&shake); + } + + return ret; +} +#endif + /** * Decapsulate the cipher text to calculate the shared secret. * @@ -741,9 +793,9 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, byte msg[2 * KYBER_SYM_SZ]; byte kr[2 * KYBER_SYM_SZ + 1]; int ret = 0; - unsigned int ctSz; - unsigned int i; - int fail; + unsigned int ctSz = 0; + unsigned int i = 0; + int fail = 0; #ifndef USE_INTEL_SPEEDUP byte* cmp = NULL; #else @@ -813,6 +865,7 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, /* Compare generated cipher text with that passed in. */ fail = kyber_cmp(ct, cmp, ctSz); +#ifndef WOLFSSL_ML_KEM /* Hash the cipher text after the seed. */ ret = KYBER_HASH_H(ct, ctSz, kr + KYBER_SYM_SZ); } @@ -824,6 +877,15 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, /* Derive the secret from the seed and hash of cipher text. */ ret = KYBER_KDF(kr, 2 * KYBER_SYM_SZ, ss, KYBER_SS_SZ); +#else + ret = kyber_derive_secret(key->z, ct, ctSz, msg); + } + if (ret == 0) { + /* Change seed to z on comparison failure. */ + for (i = 0; i < KYBER_SYM_SZ; i++) { + ss[i] = kr[i] ^ ((kr[i] ^ msg[i]) & fail); + } +#endif } #ifndef USE_INTEL_SPEEDUP @@ -849,13 +911,14 @@ int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, * @return NOT_COMPILED_IN when key type is not supported. * @return BUFFER_E when len is not the correct size. */ -int wc_KyberKey_DecodePrivateKey(KyberKey* key, unsigned char* in, word32 len) +int wc_KyberKey_DecodePrivateKey(KyberKey* key, const unsigned char* in, + word32 len) { int ret = 0; word32 privLen = 0; word32 pubLen = 0; unsigned int k = 0; - unsigned char* p = in; + const unsigned char* p = in; /* Validate parameters. */ if ((key == NULL) || (in == NULL)) { @@ -933,12 +996,13 @@ int wc_KyberKey_DecodePrivateKey(KyberKey* key, unsigned char* in, word32 len) * @return NOT_COMPILED_IN when key type is not supported. * @return BUFFER_E when len is not the correct size. */ -int wc_KyberKey_DecodePublicKey(KyberKey* key, unsigned char* in, word32 len) +int wc_KyberKey_DecodePublicKey(KyberKey* key, const unsigned char* in, + word32 len) { int ret = 0; word32 pubLen = 0; unsigned int k = 0; - unsigned char* p = in; + const unsigned char* p = in; if ((key == NULL) || (in == NULL)) { ret = BAD_FUNC_ARG; diff --git a/src/wolfcrypt/src/wc_kyber_poly.c b/src/wolfcrypt/src/wc_kyber_poly.c index fe140f4..aed437c 100644 --- a/src/wolfcrypt/src/wc_kyber_poly.c +++ b/src/wolfcrypt/src/wc_kyber_poly.c @@ -28,12 +28,44 @@ * polynomials. */ +/* Possible Kyber options: + * + * WOLFSSL_WC_KYBER Default: OFF + * Enables this code, wolfSSL implementation, to be built. + * + * WOLFSSL_KYBER512 Default: OFF + * Enables the KYBER512 parameter implementations. + * WOLFSSL_KYBER768 Default: OFF + * Enables the KYBER768 parameter implementations. + * WOLFSSL_KYBER1024 Default: OFF + * Enables the KYBER1024 parameter implementations. + * + * USE_INTEL_SPEEDUP Default: OFF + * Compiles in Intel x64 specific implementations that are faster. + * WOLFSSL_KYBER_NO_LARGE_CODE Default: OFF + * Compiles smaller, fast code size with a speed trade-off. + * WOLFSSL_KYBER_SMALL Default: OFF + * Compiles to small code size with a speed trade-off. + * WOLFSSL_SMALL_STACK Default: OFF + * Use less stack by dynamically allocating local variables. + * + * WOLFSSL_KYBER_NTT_UNROLL Defualt: OFF + * Enable an alternative NTT implementation that may be faster on some + * platforms and is smaller in code size. + * WOLFSSL_KYBER_INVNTT_UNROLL Default: OFF + * Enables an alternative inverse NTT implementation that may be faster on + * some platforms and is smaller in code size. + */ + #include #include #include #ifdef WOLFSSL_WC_KYBER +/* Declared in wc_kyber.c to stop compiler optimizer from simplifying. */ +extern volatile sword16 kyber_opt_blocker; + #ifdef USE_INTEL_SPEEDUP static word32 cpuid_flags = 0; #endif @@ -50,7 +82,7 @@ static word32 cpuid_flags = 0; /* Used in Barrett Reduction: * r = a mod q * => r = a - ((V * a) >> 26) * q), as V based on 2^26 - * V is the mulitplier that gets the quotient after shifting. + * V is the multiplier that gets the quotient after shifting. */ #define KYBER_V (((1U << 26) + (KYBER_Q / 2)) / KYBER_Q) @@ -161,7 +193,7 @@ static void kyber_ntt(sword16* r) for (j = 0; j < KYBER_N; ++j) { r[j] = KYBER_BARRETT_RED(r[j]); } -#else +#elif defined(WOLFSSL_KYBER_NO_LARGE_CODE) unsigned int len; unsigned int k = 1; unsigned int j; @@ -192,6 +224,256 @@ static void kyber_ntt(sword16* r) for (j = 0; j < KYBER_N; ++j) { r[j] = KYBER_BARRETT_RED(r[j]); } +#elif defined(WOLFSSL_KYBER_NTT_UNROLL) + unsigned int k = 1; + unsigned int j; + unsigned int start; + sword16 zeta = zetas[k++]; + + for (j = 0; j < KYBER_N / 2; ++j) { + sword32 p = (sword32)zeta * r[j + KYBER_N / 2]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[j]; + r[j + KYBER_N / 2] = rj - t; + r[j] = rj + t; + } + for (start = 0; start < KYBER_N; start += 2 * 64) { + zeta = zetas[k++]; + for (j = 0; j < 64; ++j) { + sword32 p = (sword32)zeta * r[start + j + 64]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[start + j]; + r[start + j + 64] = rj - t; + r[start + j] = rj + t; + } + } + for (start = 0; start < KYBER_N; start += 2 * 32) { + zeta = zetas[k++]; + for (j = 0; j < 32; ++j) { + sword32 p = (sword32)zeta * r[start + j + 32]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[start + j]; + r[start + j + 32] = rj - t; + r[start + j] = rj + t; + } + } + for (start = 0; start < KYBER_N; start += 2 * 16) { + zeta = zetas[k++]; + for (j = 0; j < 16; ++j) { + sword32 p = (sword32)zeta * r[start + j + 16]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[start + j]; + r[start + j + 16] = rj - t; + r[start + j] = rj + t; + } + } + for (start = 0; start < KYBER_N; start += 2 * 8) { + zeta = zetas[k++]; + for (j = 0; j < 8; ++j) { + sword32 p = (sword32)zeta * r[start + j + 8]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[start + j]; + r[start + j + 8] = rj - t; + r[start + j] = rj + t; + } + } + for (start = 0; start < KYBER_N; start += 2 * 4) { + zeta = zetas[k++]; + for (j = 0; j < 4; ++j) { + sword32 p = (sword32)zeta * r[start + j + 4]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[start + j]; + r[start + j + 4] = rj - t; + r[start + j] = rj + t; + } + } + for (start = 0; start < KYBER_N; start += 2 * 2) { + zeta = zetas[k++]; + for (j = 0; j < 2; ++j) { + sword32 p = (sword32)zeta * r[start + j + 2]; + sword16 t = KYBER_MONT_RED(p); + sword16 rj = r[start + j]; + r[start + j + 2] = rj - t; + r[start + j] = rj + t; + } + } + /* Reduce coefficients with quick algorithm. */ + for (j = 0; j < KYBER_N; ++j) { + r[j] = KYBER_BARRETT_RED(r[j]); + } +#else + unsigned int j; + sword16 t0; + sword16 t1; + sword16 t2; + sword16 t3; + + sword16 zeta128 = zetas[1]; + sword16 zeta64_0 = zetas[2]; + sword16 zeta64_1 = zetas[3]; + for (j = 0; j < KYBER_N / 8; j++) { + sword16 r0 = r[j + 0]; + sword16 r1 = r[j + 32]; + sword16 r2 = r[j + 64]; + sword16 r3 = r[j + 96]; + sword16 r4 = r[j + 128]; + sword16 r5 = r[j + 160]; + sword16 r6 = r[j + 192]; + sword16 r7 = r[j + 224]; + + t0 = KYBER_MONT_RED((sword32)zeta128 * r4); + t1 = KYBER_MONT_RED((sword32)zeta128 * r5); + t2 = KYBER_MONT_RED((sword32)zeta128 * r6); + t3 = KYBER_MONT_RED((sword32)zeta128 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = KYBER_MONT_RED((sword32)zeta64_0 * r2); + t1 = KYBER_MONT_RED((sword32)zeta64_0 * r3); + t2 = KYBER_MONT_RED((sword32)zeta64_1 * r6); + t3 = KYBER_MONT_RED((sword32)zeta64_1 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + r[j + 0] = r0; + r[j + 32] = r1; + r[j + 64] = r2; + r[j + 96] = r3; + r[j + 128] = r4; + r[j + 160] = r5; + r[j + 192] = r6; + r[j + 224] = r7; + } + + for (j = 0; j < KYBER_N; j += 64) { + int i; + sword16 zeta32 = zetas[ 4 + j / 64 + 0]; + sword16 zeta16_0 = zetas[ 8 + j / 32 + 0]; + sword16 zeta16_1 = zetas[ 8 + j / 32 + 1]; + sword16 zeta8_0 = zetas[16 + j / 16 + 0]; + sword16 zeta8_1 = zetas[16 + j / 16 + 1]; + sword16 zeta8_2 = zetas[16 + j / 16 + 2]; + sword16 zeta8_3 = zetas[16 + j / 16 + 3]; + for (i = 0; i < 8; i++) { + sword16 r0 = r[j + i + 0]; + sword16 r1 = r[j + i + 8]; + sword16 r2 = r[j + i + 16]; + sword16 r3 = r[j + i + 24]; + sword16 r4 = r[j + i + 32]; + sword16 r5 = r[j + i + 40]; + sword16 r6 = r[j + i + 48]; + sword16 r7 = r[j + i + 56]; + + t0 = KYBER_MONT_RED((sword32)zeta32 * r4); + t1 = KYBER_MONT_RED((sword32)zeta32 * r5); + t2 = KYBER_MONT_RED((sword32)zeta32 * r6); + t3 = KYBER_MONT_RED((sword32)zeta32 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = KYBER_MONT_RED((sword32)zeta16_0 * r2); + t1 = KYBER_MONT_RED((sword32)zeta16_0 * r3); + t2 = KYBER_MONT_RED((sword32)zeta16_1 * r6); + t3 = KYBER_MONT_RED((sword32)zeta16_1 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + t0 = KYBER_MONT_RED((sword32)zeta8_0 * r1); + t1 = KYBER_MONT_RED((sword32)zeta8_1 * r3); + t2 = KYBER_MONT_RED((sword32)zeta8_2 * r5); + t3 = KYBER_MONT_RED((sword32)zeta8_3 * r7); + r1 = r0 - t0; + r3 = r2 - t1; + r5 = r4 - t2; + r7 = r6 - t3; + r0 += t0; + r2 += t1; + r4 += t2; + r6 += t3; + + r[j + i + 0] = r0; + r[j + i + 8] = r1; + r[j + i + 16] = r2; + r[j + i + 24] = r3; + r[j + i + 32] = r4; + r[j + i + 40] = r5; + r[j + i + 48] = r6; + r[j + i + 56] = r7; + } + } + + for (j = 0; j < KYBER_N; j += 8) { + sword16 zeta4 = zetas[32 + j / 8 + 0]; + sword16 zeta2_0 = zetas[64 + j / 4 + 0]; + sword16 zeta2_1 = zetas[64 + j / 4 + 1]; + sword16 r0 = r[j + 0]; + sword16 r1 = r[j + 1]; + sword16 r2 = r[j + 2]; + sword16 r3 = r[j + 3]; + sword16 r4 = r[j + 4]; + sword16 r5 = r[j + 5]; + sword16 r6 = r[j + 6]; + sword16 r7 = r[j + 7]; + + t0 = KYBER_MONT_RED((sword32)zeta4 * r4); + t1 = KYBER_MONT_RED((sword32)zeta4 * r5); + t2 = KYBER_MONT_RED((sword32)zeta4 * r6); + t3 = KYBER_MONT_RED((sword32)zeta4 * r7); + r4 = r0 - t0; + r5 = r1 - t1; + r6 = r2 - t2; + r7 = r3 - t3; + r0 += t0; + r1 += t1; + r2 += t2; + r3 += t3; + + t0 = KYBER_MONT_RED((sword32)zeta2_0 * r2); + t1 = KYBER_MONT_RED((sword32)zeta2_0 * r3); + t2 = KYBER_MONT_RED((sword32)zeta2_1 * r6); + t3 = KYBER_MONT_RED((sword32)zeta2_1 * r7); + r2 = r0 - t0; + r3 = r1 - t1; + r6 = r4 - t2; + r7 = r5 - t3; + r0 += t0; + r1 += t1; + r4 += t2; + r5 += t3; + + r[j + 0] = KYBER_BARRETT_RED(r0); + r[j + 1] = KYBER_BARRETT_RED(r1); + r[j + 2] = KYBER_BARRETT_RED(r2); + r[j + 3] = KYBER_BARRETT_RED(r3); + r[j + 4] = KYBER_BARRETT_RED(r4); + r[j + 5] = KYBER_BARRETT_RED(r5); + r[j + 6] = KYBER_BARRETT_RED(r6); + r[j + 7] = KYBER_BARRETT_RED(r7); + } #endif } @@ -230,7 +512,49 @@ static void kyber_invntt(sword16* r) sword32 p = (sword32)zeta * r[j]; r[j] = KYBER_MONT_RED(p); } -#else +#elif defined(WOLFSSL_KYBER_NO_LARGE_CODE) + unsigned int len; + unsigned int k; + unsigned int j; + sword16 zeta; + sword16 zeta2; + + k = 0; + for (len = 2; len <= KYBER_N / 4; len <<= 1) { + unsigned int start; + for (start = 0; start < KYBER_N; start = j + len) { + zeta = zetas_inv[k++]; + for (j = start; j < start + len; ++j) { + sword32 p; + sword16 rj = r[j]; + sword16 rjl = r[j + len]; + sword16 t = rj + rjl; + r[j] = KYBER_BARRETT_RED(t); + rjl = rj - rjl; + p = (sword32)zeta * rjl; + r[j + len] = KYBER_MONT_RED(p); + } + } + } + + zeta = zetas_inv[126]; + zeta2 = zetas_inv[127]; + for (j = 0; j < KYBER_N / 2; ++j) { + sword32 p; + sword16 rj = r[j]; + sword16 rjl = r[j + KYBER_N / 2]; + sword16 t = rj + rjl; + rjl = rj - rjl; + p = (sword32)zeta * rjl; + r[j] = t; + r[j + KYBER_N / 2] = KYBER_MONT_RED(p); + + p = (sword32)zeta2 * r[j]; + r[j] = KYBER_MONT_RED(p); + p = (sword32)zeta2 * r[j + KYBER_N / 2]; + r[j + KYBER_N / 2] = KYBER_MONT_RED(p); + } +#elif defined(WOLFSSL_KYBER_INVNTT_UNROLL) unsigned int k; unsigned int j; unsigned int start; @@ -335,6 +659,230 @@ static void kyber_invntt(sword16* r) p = (sword32)zeta2 * r[j + KYBER_N / 2]; r[j + KYBER_N / 2] = KYBER_MONT_RED(p); } +#else + unsigned int j; + sword16 t0; + sword16 t1; + sword16 t2; + sword16 t3; + sword16 zeta64_0; + sword16 zeta64_1; + sword16 zeta128; + sword16 zeta256; + sword32 p; + + for (j = 0; j < KYBER_N; j += 8) { + sword16 zeta2_0 = zetas_inv[ 0 + j / 4 + 0]; + sword16 zeta2_1 = zetas_inv[ 0 + j / 4 + 1]; + sword16 zeta4 = zetas_inv[64 + j / 8 + 0]; + sword16 r0 = r[j + 0]; + sword16 r1 = r[j + 1]; + sword16 r2 = r[j + 2]; + sword16 r3 = r[j + 3]; + sword16 r4 = r[j + 4]; + sword16 r5 = r[j + 5]; + sword16 r6 = r[j + 6]; + sword16 r7 = r[j + 7]; + + p = (sword32)zeta2_0 * (sword16)(r0 - r2); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta2_0 * (sword16)(r1 - r3); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta2_1 * (sword16)(r4 - r6); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta2_1 * (sword16)(r5 - r7); + t3 = KYBER_MONT_RED(p); + r0 += r2; + r1 += r3; + r4 += r6; + r5 += r7; + r2 = t0; + r3 = t1; + r6 = t2; + r7 = t3; + + p = (sword32)zeta4 * (sword16)(r0 - r4); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta4 * (sword16)(r1 - r5); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta4 * (sword16)(r2 - r6); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta4 * (sword16)(r3 - r7); + t3 = KYBER_MONT_RED(p); + r0 += r4; + r1 += r5; + r2 += r6; + r3 += r7; + r4 = t0; + r5 = t1; + r6 = t2; + r7 = t3; + + r[j + 0] = r0; + r[j + 1] = r1; + r[j + 2] = r2; + r[j + 3] = r3; + r[j + 4] = r4; + r[j + 5] = r5; + r[j + 6] = r6; + r[j + 7] = r7; + } + + for (j = 0; j < KYBER_N; j += 64) { + int i; + sword16 zeta8_0 = zetas_inv[ 96 + j / 16 + 0]; + sword16 zeta8_1 = zetas_inv[ 96 + j / 16 + 1]; + sword16 zeta8_2 = zetas_inv[ 96 + j / 16 + 2]; + sword16 zeta8_3 = zetas_inv[ 96 + j / 16 + 3]; + sword16 zeta16_0 = zetas_inv[112 + j / 32 + 0]; + sword16 zeta16_1 = zetas_inv[112 + j / 32 + 1]; + sword16 zeta32 = zetas_inv[120 + j / 64 + 0]; + for (i = 0; i < 8; i++) { + sword16 r0 = r[j + i + 0]; + sword16 r1 = r[j + i + 8]; + sword16 r2 = r[j + i + 16]; + sword16 r3 = r[j + i + 24]; + sword16 r4 = r[j + i + 32]; + sword16 r5 = r[j + i + 40]; + sword16 r6 = r[j + i + 48]; + sword16 r7 = r[j + i + 56]; + + p = (sword32)zeta8_0 * (sword16)(r0 - r1); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta8_1 * (sword16)(r2 - r3); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta8_2 * (sword16)(r4 - r5); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta8_3 * (sword16)(r6 - r7); + t3 = KYBER_MONT_RED(p); + r0 = KYBER_BARRETT_RED(r0 + r1); + r2 = KYBER_BARRETT_RED(r2 + r3); + r4 = KYBER_BARRETT_RED(r4 + r5); + r6 = KYBER_BARRETT_RED(r6 + r7); + r1 = t0; + r3 = t1; + r5 = t2; + r7 = t3; + + p = (sword32)zeta16_0 * (sword16)(r0 - r2); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta16_0 * (sword16)(r1 - r3); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta16_1 * (sword16)(r4 - r6); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta16_1 * (sword16)(r5 - r7); + t3 = KYBER_MONT_RED(p); + r0 += r2; + r1 += r3; + r4 += r6; + r5 += r7; + r2 = t0; + r3 = t1; + r6 = t2; + r7 = t3; + + p = (sword32)zeta32 * (sword16)(r0 - r4); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta32 * (sword16)(r1 - r5); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta32 * (sword16)(r2 - r6); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta32 * (sword16)(r3 - r7); + t3 = KYBER_MONT_RED(p); + r0 += r4; + r1 += r5; + r2 += r6; + r3 += r7; + r4 = t0; + r5 = t1; + r6 = t2; + r7 = t3; + + r[j + i + 0] = r0; + r[j + i + 8] = r1; + r[j + i + 16] = r2; + r[j + i + 24] = r3; + r[j + i + 32] = r4; + r[j + i + 40] = r5; + r[j + i + 48] = r6; + r[j + i + 56] = r7; + } + } + + zeta64_0 = zetas_inv[124]; + zeta64_1 = zetas_inv[125]; + zeta128 = zetas_inv[126]; + zeta256 = zetas_inv[127]; + for (j = 0; j < KYBER_N / 8; j++) { + sword16 r0 = r[j + 0]; + sword16 r1 = r[j + 32]; + sword16 r2 = r[j + 64]; + sword16 r3 = r[j + 96]; + sword16 r4 = r[j + 128]; + sword16 r5 = r[j + 160]; + sword16 r6 = r[j + 192]; + sword16 r7 = r[j + 224]; + + p = (sword32)zeta64_0 * (sword16)(r0 - r2); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta64_0 * (sword16)(r1 - r3); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta64_1 * (sword16)(r4 - r6); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta64_1 * (sword16)(r5 - r7); + t3 = KYBER_MONT_RED(p); + r0 = KYBER_BARRETT_RED(r0 + r2); + r1 = KYBER_BARRETT_RED(r1 + r3); + r4 = KYBER_BARRETT_RED(r4 + r6); + r5 = KYBER_BARRETT_RED(r5 + r7); + r2 = t0; + r3 = t1; + r6 = t2; + r7 = t3; + + p = (sword32)zeta128 * (sword16)(r0 - r4); + t0 = KYBER_MONT_RED(p); + p = (sword32)zeta128 * (sword16)(r1 - r5); + t1 = KYBER_MONT_RED(p); + p = (sword32)zeta128 * (sword16)(r2 - r6); + t2 = KYBER_MONT_RED(p); + p = (sword32)zeta128 * (sword16)(r3 - r7); + t3 = KYBER_MONT_RED(p); + r0 += r4; + r1 += r5; + r2 += r6; + r3 += r7; + r4 = t0; + r5 = t1; + r6 = t2; + r7 = t3; + + p = (sword32)zeta256 * r0; + r0 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r1; + r1 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r2; + r2 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r3; + r3 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r4; + r4 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r5; + r5 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r6; + r6 = KYBER_MONT_RED(p); + p = (sword32)zeta256 * r7; + r7 = KYBER_MONT_RED(p); + + r[j + 0] = r0; + r[j + 32] = r1; + r[j + 64] = r2; + r[j + 96] = r3; + r[j + 128] = r4; + r[j + 160] = r5; + r[j + 192] = r6; + r[j + 224] = r7; + } #endif } @@ -387,13 +935,24 @@ static void kyber_basemul_mont(sword16* r, const sword16* a, const sword16* b) kyber_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]); kyber_basemul(r + i + 2, a + i + 2, b + i + 2, -zeta[0]); } -#else +#elif defined(WOLFSSL_KYBER_NO_LARGE_CODE) for (i = 0; i < KYBER_N; i += 8, zeta += 2) { kyber_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]); kyber_basemul(r + i + 2, a + i + 2, b + i + 2, -zeta[0]); kyber_basemul(r + i + 4, a + i + 4, b + i + 4, zeta[1]); kyber_basemul(r + i + 6, a + i + 6, b + i + 6, -zeta[1]); } +#else + for (i = 0; i < KYBER_N; i += 16, zeta += 4) { + kyber_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]); + kyber_basemul(r + i + 2, a + i + 2, b + i + 2, -zeta[0]); + kyber_basemul(r + i + 4, a + i + 4, b + i + 4, zeta[1]); + kyber_basemul(r + i + 6, a + i + 6, b + i + 6, -zeta[1]); + kyber_basemul(r + i + 8, a + i + 8, b + i + 8, zeta[2]); + kyber_basemul(r + i + 10, a + i + 10, b + i + 10, -zeta[2]); + kyber_basemul(r + i + 12, a + i + 12, b + i + 12, zeta[3]); + kyber_basemul(r + i + 14, a + i + 14, b + i + 14, -zeta[3]); + } #endif } @@ -422,7 +981,7 @@ static void kyber_basemul_mont_add(sword16* r, const sword16* a, r[i + 2] += t2[0]; r[i + 3] += t2[1]; } -#else +#elif defined(WOLFSSL_KYBER_NO_LARGE_CODE) for (i = 0; i < KYBER_N; i += 8, zeta += 2) { sword16 t0[2]; sword16 t2[2]; @@ -443,6 +1002,43 @@ static void kyber_basemul_mont_add(sword16* r, const sword16* a, r[i + 6] += t6[0]; r[i + 7] += t6[1]; } +#else + for (i = 0; i < KYBER_N; i += 16, zeta += 4) { + sword16 t0[2]; + sword16 t2[2]; + sword16 t4[2]; + sword16 t6[2]; + sword16 t8[2]; + sword16 t10[2]; + sword16 t12[2]; + sword16 t14[2]; + + kyber_basemul(t0, a + i + 0, b + i + 0, zeta[0]); + kyber_basemul(t2, a + i + 2, b + i + 2, -zeta[0]); + kyber_basemul(t4, a + i + 4, b + i + 4, zeta[1]); + kyber_basemul(t6, a + i + 6, b + i + 6, -zeta[1]); + kyber_basemul(t8, a + i + 8, b + i + 8, zeta[2]); + kyber_basemul(t10, a + i + 10, b + i + 10, -zeta[2]); + kyber_basemul(t12, a + i + 12, b + i + 12, zeta[3]); + kyber_basemul(t14, a + i + 14, b + i + 14, -zeta[3]); + + r[i + 0] += t0[0]; + r[i + 1] += t0[1]; + r[i + 2] += t2[0]; + r[i + 3] += t2[1]; + r[i + 4] += t4[0]; + r[i + 5] += t4[1]; + r[i + 6] += t6[0]; + r[i + 7] += t6[1]; + r[i + 8] += t8[0]; + r[i + 9] += t8[1]; + r[i + 10] += t10[0]; + r[i + 11] += t10[1]; + r[i + 12] += t12[0]; + r[i + 13] += t12[1]; + r[i + 14] += t14[0]; + r[i + 15] += t14[1]; + } #endif } @@ -1460,6 +2056,8 @@ static void kyber_cbd_eta3(sword16* p, const byte* r) { unsigned int i; +#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_KYBER_NO_LARGE_CODE) || \ + defined(BIG_ENDIAN_ORDER) #ifndef WORD64_AVAILABLE /* Calculate four integer coefficients at a time. */ for (i = 0; i < KYBER_N; i += 4) { @@ -1533,7 +2131,59 @@ static void kyber_cbd_eta3(sword16* p, const byte* r) /* Move over used bytes. */ r += 6; } -#endif +#endif /* WORD64_AVAILABLE */ +#else + /* Calculate eight integer coefficients at a time. */ + for (i = 0; i < KYBER_N; i += 16) { + const word32* r32 = (const word32*)r; + /* Take the next 12 bytes, little endian, as 24 bit values. */ + word32 t0 = r32[0] & 0xffffff; + word32 t1 = ((r32[0] >> 24) | (r32[1] << 8)) & 0xffffff; + word32 t2 = ((r32[1] >> 16) | (r32[2] << 16)) & 0xffffff; + word32 t3 = r32[2] >> 8 ; + word32 d0; + word32 d1; + word32 d2; + word32 d3; + + /* Add second and third bits to first. */ + d0 = (t0 >> 0) & 0x00249249; + d0 += (t0 >> 1) & 0x00249249; + d0 += (t0 >> 2) & 0x00249249; + d1 = (t1 >> 0) & 0x00249249; + d1 += (t1 >> 1) & 0x00249249; + d1 += (t1 >> 2) & 0x00249249; + d2 = (t2 >> 0) & 0x00249249; + d2 += (t2 >> 1) & 0x00249249; + d2 += (t2 >> 2) & 0x00249249; + d3 = (t3 >> 0) & 0x00249249; + d3 += (t3 >> 1) & 0x00249249; + d3 += (t3 >> 2) & 0x00249249; + /* Values 0, 1, 2 or 3 in consecutive 3 bits. + * 0 - 1/8, 1 - 3/8, 2 - 3/8, 3 - 1/8. */ + + p[i + 0] = ETA3_SUB(d0, 0); + p[i + 1] = ETA3_SUB(d0, 1); + p[i + 2] = ETA3_SUB(d0, 2); + p[i + 3] = ETA3_SUB(d0, 3); + p[i + 4] = ETA3_SUB(d1, 0); + p[i + 5] = ETA3_SUB(d1, 1); + p[i + 6] = ETA3_SUB(d1, 2); + p[i + 7] = ETA3_SUB(d1, 3); + p[i + 8] = ETA3_SUB(d2, 0); + p[i + 9] = ETA3_SUB(d2, 1); + p[i + 10] = ETA3_SUB(d2, 2); + p[i + 11] = ETA3_SUB(d2, 3); + p[i + 12] = ETA3_SUB(d3, 0); + p[i + 13] = ETA3_SUB(d3, 1); + p[i + 14] = ETA3_SUB(d3, 2); + p[i + 15] = ETA3_SUB(d3, 3); + /* -3-1/64, -2-6/64, -1-15/64, 0-20/64, 1-15/64, 2-6/64, 3-1/64 */ + + /* Move over used bytes. */ + r += 12; + } +#endif /* WOLFSSL_SMALL_STACK || WOLFSSL_KYBER_NO_LARGE_CODE || BIG_ENDIAN_ORDER */ } #endif @@ -2069,9 +2719,6 @@ static void kyber_vec_compress_10_c(byte* r, sword16* v, unsigned int kp) { unsigned int i; unsigned int j; -#ifdef WOLFSSL_KYBER_SMALL - unsigned int k; -#endif for (i = 0; i < kp; i++) { /* Reduce each coefficient to mod q. */ @@ -2081,9 +2728,12 @@ static void kyber_vec_compress_10_c(byte* r, sword16* v, unsigned int kp) /* Each polynomial. */ for (i = 0; i < kp; i++) { +#if defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_KYBER_NO_LARGE_CODE) || \ + defined(BIG_ENDIAN_ORDER) /* Each 4 polynomial coefficients. */ for (j = 0; j < KYBER_N; j += 4) { #ifdef WOLFSSL_KYBER_SMALL + unsigned int k; sword16 t[4]; /* Compress four polynomial values to 10 bits each. */ for (k = 0; k < 4; k++) { @@ -2114,6 +2764,44 @@ static void kyber_vec_compress_10_c(byte* r, sword16* v, unsigned int kp) /* Move over set bytes. */ r += 5; } +#else + /* Each 16 polynomial coefficients. */ + for (j = 0; j < KYBER_N; j += 16) { + /* Compress four polynomial values to 10 bits each. */ + sword16 t0 = TO_COMP_WORD_10(v, i, j, 0); + sword16 t1 = TO_COMP_WORD_10(v, i, j, 1); + sword16 t2 = TO_COMP_WORD_10(v, i, j, 2); + sword16 t3 = TO_COMP_WORD_10(v, i, j, 3); + sword16 t4 = TO_COMP_WORD_10(v, i, j, 4); + sword16 t5 = TO_COMP_WORD_10(v, i, j, 5); + sword16 t6 = TO_COMP_WORD_10(v, i, j, 6); + sword16 t7 = TO_COMP_WORD_10(v, i, j, 7); + sword16 t8 = TO_COMP_WORD_10(v, i, j, 8); + sword16 t9 = TO_COMP_WORD_10(v, i, j, 9); + sword16 t10 = TO_COMP_WORD_10(v, i, j, 10); + sword16 t11 = TO_COMP_WORD_10(v, i, j, 11); + sword16 t12 = TO_COMP_WORD_10(v, i, j, 12); + sword16 t13 = TO_COMP_WORD_10(v, i, j, 13); + sword16 t14 = TO_COMP_WORD_10(v, i, j, 14); + sword16 t15 = TO_COMP_WORD_10(v, i, j, 15); + + word32* r32 = (word32*)r; + /* Pack sixteen 10-bit values into byte array. */ + r32[0] = t0 | ((word32)t1 << 10) | ((word32)t2 << 20) | + ((word32)t3 << 30); + r32[1] = (t3 >> 2) | ((word32)t4 << 8) | ((word32)t5 << 18) | + ((word32)t6 << 28); + r32[2] = (t6 >> 4) | ((word32)t7 << 6) | ((word32)t8 << 16) | + ((word32)t9 << 26); + r32[3] = (t9 >> 6) | ((word32)t10 << 4) | ((word32)t11 << 14) | + ((word32)t12 << 24); + r32[4] = (t12 >> 8) | ((word32)t13 << 2) | ((word32)t14 << 12) | + ((word32)t15 << 22); + + /* Move over set bytes. */ + r += 20; + } +#endif } } @@ -2773,6 +3461,8 @@ void kyber_decompress_5(sword16* p, const unsigned char* b) /* Convert bit from byte to 0 or (KYBER_Q + 1) / 2. * * Constant time implementation. + * XOR in kyber_opt_blocker to ensure optimizer doesn't know what will be ANDed + * with KYBER_Q_1_HALF and can't optimize to non-constant time code. * * @param [out] p Polynomial to hold converted value. * @param [in] msg Message to get bit from byte from. @@ -2780,7 +3470,8 @@ void kyber_decompress_5(sword16* p, const unsigned char* b) * @param [in] j Index of bit in byte. */ #define FROM_MSG_BIT(p, msg, i, j) \ - p[8 * (i) + (j)] = ((sword16)0 - (sword16)(((msg)[i] >> (j)) & 1)) & KYBER_Q_1_HALF + ((p)[8 * (i) + (j)] = (((sword16)0 - (sword16)(((msg)[i] >> (j)) & 1)) ^ \ + kyber_opt_blocker) & KYBER_Q_1_HALF) /* Convert message to polynomial. * diff --git a/src/wolfcrypt/src/wc_lms.c b/src/wolfcrypt/src/wc_lms.c index cdc732f..0ef0b59 100644 --- a/src/wolfcrypt/src/wc_lms.c +++ b/src/wolfcrypt/src/wc_lms.c @@ -19,8 +19,1127 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif + #include +#include +#include + +#if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_WC_LMS) +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* Calculate u. Appendix B. Works for w of 1, 2, 4, or 8. + * + * @param [in] w Winternitz width. + */ +#define LMS_U(w) \ + (8 * WC_SHA256_DIGEST_SIZE / (w)) +/* Calculate u. Appendix B. Works for w of 1, 2, 4, or 8. + * + * @param [in] w Winternitz width. + * @param [in] wb Winternitz width length in bits. + */ +#define LMS_V(w, wb) \ + (2 + (8 - (wb)) / (w)) +/* Calculate ls. Appendix B. Works for w of 1, 2, 4, or 8. + * + * @param [in] w Winternitz width. + * @param [in] wb Winternitz width length in bits. + */ +#define LMS_LS(w, wb) \ + (16 - LMS_V(w, wb) * (w)) +/* Calculate p. Appendix B. Works for w of 1, 2, 4, or 8. + * + * @param [in] w Winternitz width. + * @param [in] wb Winternitz width length in bits. + */ +#define LMS_P(w, wb) \ + (LMS_U(w) + LMS_V(w, wb)) +/* Calculate signature length. + * + * @param [in] l Number of levels. + * @param [in] h Height of the trees. + * @param [in] p Number of n-byte string elements in signature for a tree. + */ +#define LMS_PARAMS_SIG_LEN(l, h, p) \ + (4 + (l) * (4 + 4 + 4 + WC_SHA256_DIGEST_SIZE * (1 + (p) + (h))) + \ + ((l) - 1) * LMS_PUBKEY_LEN) + +#ifndef WOLFSSL_WC_LMS_SMALL + /* Root levels and leaf cache bits. */ + #define LMS_PARAMS_CACHE(h) \ + (((h) < LMS_ROOT_LEVELS) ? (h) : LMS_ROOT_LEVELS), \ + (((h) < LMS_CACHE_BITS ) ? (h) : LMS_CACHE_BITS ) +#else + /* Root levels and leaf cache bits aren't in structure. */ + #define LMS_PARAMS_CACHE(h) /* null expansion */ +#endif + +/* Define parameters entry for LMS. + * + * @param [in] l Number of levels. + * @param [in] h Height of the trees. + * @param [in] w Winternitz width. + * @param [in] wb Winternitz width length in bits. + * @param [in] t LMS type. + * @param [in] t2 LM-OTS type. + */ +#define LMS_PARAMS(l, h, w, wb, t, t2) \ + { l, h, w, LMS_LS(w, wb), LMS_P(w, wb), t, t2, \ + LMS_PARAMS_SIG_LEN(l, h, LMS_P(w, wb)), LMS_PARAMS_CACHE(h) } + + +/* Initialize the working state for LMS operations. + * + * @param [in, out] state LMS state. + * @param [in] params LMS parameters. + */ +static int wc_lmskey_state_init(LmsState* state, const LmsParams* params) +{ + int ret; -#ifdef WOLFSSL_HAVE_LMS - #error "Contact wolfSSL to get the implementation of this file" + /* Zero out every field. */ + XMEMSET(state, 0, sizeof(LmsState)); + + /* Keep a reference to the parameters for use in operations. */ + state->params = params; + + /* Initialize the two hash algorithms. */ + ret = wc_InitSha256(&state->hash); + if (ret == 0) { + ret = wc_InitSha256(&state->hash_k); + if (ret != 0) { + wc_Sha256Free(&state->hash); + } + } + + return ret; +} + +/* Free the working state for LMS operations. + * + * @param [in] state LMS state. + */ +static void wc_lmskey_state_free(LmsState* state) +{ + wc_Sha256Free(&state->hash_k); + wc_Sha256Free(&state->hash); +} + +/* Supported LMS parameters. */ +static const wc_LmsParamsMap wc_lms_map[] = { +#if LMS_MAX_HEIGHT >= 15 + { WC_LMS_PARM_NONE , "LMS_NONE" , + LMS_PARAMS(1, 15, 2, 1, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L1_H15_W2, "LMS/HSS L1_H15_W2", + LMS_PARAMS(1, 15, 2, 1, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L1_H15_W4, "LMS/HSS L1_H15_W4", + LMS_PARAMS(1, 15, 4, 2, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W4) }, +#endif +#if LMS_MAX_LEVELS >= 2 +#if LMS_MAX_HEIGHT >= 10 + { WC_LMS_PARM_L2_H10_W2, "LMS/HSS L2_H10_W2", + LMS_PARAMS(2, 10, 2, 1, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L2_H10_W4, "LMS/HSS L2_H10_W4", + LMS_PARAMS(2, 10, 4, 2, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L2_H10_W8, "LMS/HSS L2_H10_W8", + LMS_PARAMS(2, 10, 8, 3, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W8) }, +#endif +#endif +#if LMS_MAX_LEVELS >= 3 + { WC_LMS_PARM_L3_H5_W2 , "LMS/HSS L3_H5_W2" , + LMS_PARAMS(3, 5, 2, 1, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L3_H5_W4 , "LMS/HSS L3_H5_W4" , + LMS_PARAMS(3, 5, 4, 2, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L3_H5_W8 , "LMS/HSS L3_H5_W8" , + LMS_PARAMS(3, 5, 8, 3, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W8) }, +#if LMS_MAX_HEIGHT >= 10 + { WC_LMS_PARM_L3_H10_W4, "LMS/HSS L3_H10_W4", + LMS_PARAMS(3, 10, 4, 2, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W4) }, +#endif +#endif +#if LMS_MAX_LEVELS >= 4 + { WC_LMS_PARM_L4_H5_W8 , "LMS/HSS L4_H5_W8" , + LMS_PARAMS(4, 5, 8, 3, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W8) }, +#endif + + /* For when user sets L, H, W explicitly. */ + { WC_LMS_PARM_L1_H5_W1 , "LMS/HSS_L1_H5_W1" , + LMS_PARAMS(1, 5, 1, 1, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W1) }, + { WC_LMS_PARM_L1_H5_W2 , "LMS/HSS_L1_H5_W2" , + LMS_PARAMS(1, 5, 2, 1, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L1_H5_W4 , "LMS/HSS_L1_H5_W4" , + LMS_PARAMS(1, 5, 4, 2, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L1_H5_W8 , "LMS/HSS_L1_H5_W8" , + LMS_PARAMS(1, 5, 8, 3, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W8) }, +#if LMS_MAX_HEIGHT >= 10 + { WC_LMS_PARM_L1_H10_W2 , "LMS/HSS_L1_H10_W2", + LMS_PARAMS(1, 10, 2, 1, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L1_H10_W4 , "LMS/HSS_L1_H10_W4", + LMS_PARAMS(1, 10, 4, 2, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L1_H10_W8 , "LMS/HSS_L1_H10_W8", + LMS_PARAMS(1, 10, 8, 3, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W8) }, +#endif +#if LMS_MAX_HEIGHT >= 15 + { WC_LMS_PARM_L1_H15_W8 , "LMS/HSS L1_H15_W8", + LMS_PARAMS(1, 15, 8, 3, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W8) }, +#endif +#if LMS_MAX_HEIGHT >= 20 + { WC_LMS_PARM_L1_H20_W2 , "LMS/HSS_L1_H20_W2", + LMS_PARAMS(1, 20, 2, 1, LMS_SHA256_M32_H20, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L1_H20_W4 , "LMS/HSS_L1_H20_W4", + LMS_PARAMS(1, 20, 4, 2, LMS_SHA256_M32_H20, LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L1_H20_W8 , "LMS/HSS_L1_H20_W8", + LMS_PARAMS(1, 20, 8, 3, LMS_SHA256_M32_H20, LMOTS_SHA256_N32_W8) }, +#endif +#if LMS_MAX_LEVELS >= 2 + { WC_LMS_PARM_L2_H5_W2 , "LMS/HSS_L2_H5_W2" , + LMS_PARAMS(2, 5, 2, 1, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L2_H5_W4 , "LMS/HSS_L2_H5_W4" , + LMS_PARAMS(2, 5, 4, 2, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L2_H5_W8 , "LMS/HSS_L2_H5_W8" , + LMS_PARAMS(2, 5, 8, 3, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W8) }, +#if LMS_MAX_HEIGHT >= 15 + { WC_LMS_PARM_L2_H15_W2 , "LMS/HSS_L2_H15_W2", + LMS_PARAMS(2, 15, 2, 1, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L2_H15_W4 , "LMS/HSS_L2_H15_W4", + LMS_PARAMS(2, 15, 4, 2, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L2_H15_W8 , "LMS/HSS_L2_H15_W8", + LMS_PARAMS(2, 15, 8, 3, LMS_SHA256_M32_H15, LMOTS_SHA256_N32_W8) }, +#endif +#if LMS_MAX_HEIGHT >= 20 + { WC_LMS_PARM_L2_H20_W2 , "LMS/HSS_L2_H20_W2", + LMS_PARAMS(2, 20, 2, 1, LMS_SHA256_M32_H20, LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L2_H20_W4 , "LMS/HSS_L2_H20_W4", + LMS_PARAMS(2, 20, 4, 2, LMS_SHA256_M32_H20, LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L2_H20_W8 , "LMS/HSS_L2_H20_W8", + LMS_PARAMS(2, 20, 8, 3, LMS_SHA256_M32_H20, LMOTS_SHA256_N32_W8) }, +#endif +#endif +#if LMS_MAX_LEVELS >= 3 +#if LMS_MAX_HEIGHT >= 10 + { WC_LMS_PARM_L3_H10_W8 , "LMS/HSS L3_H10_W8", + LMS_PARAMS(3, 10, 8, 3, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W8) }, #endif +#endif +#if LMS_MAX_LEVELS >= 4 + { WC_LMS_PARM_L4_H5_W2 , "LMS/HSS L4_H5_W2" , + LMS_PARAMS(4, 5, 2, 1, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W2) }, + { WC_LMS_PARM_L4_H5_W4 , "LMS/HSS L4_H5_W4" , + LMS_PARAMS(4, 5, 4, 2, LMS_SHA256_M32_H5 , LMOTS_SHA256_N32_W4) }, +#if LMS_MAX_HEIGHT >= 10 + { WC_LMS_PARM_L4_H10_W4 , "LMS/HSS L4_H10_W4", + LMS_PARAMS(4, 10, 4, 2, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W4) }, + { WC_LMS_PARM_L4_H10_W8 , "LMS/HSS L4_H10_W8", + LMS_PARAMS(4, 10, 8, 3, LMS_SHA256_M32_H10, LMOTS_SHA256_N32_W8) }, +#endif +#endif +}; +/* Number of parameter sets supported. */ +#define WC_LMS_MAP_LEN ((int)(sizeof(wc_lms_map) / sizeof(*wc_lms_map))) + +/* Initialize LMS key. + * + * Call this before setting the params of an LMS key. + * + * @param [out] key LMS key to initialize. + * @param [in] heap Heap hint. + * @param [in] devId Device identifier. + * Use INVALID_DEVID when not using a device. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + */ +int wc_LmsKey_Init(LmsKey* key, void* heap, int devId) +{ + int ret = 0; + + (void)heap; + (void)devId; + + /* Validate parameters. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + /* Zeroize the key data. */ + ForceZero(key, sizeof(LmsKey)); + + #ifndef WOLFSSL_LMS_VERIFY_ONLY + /* Initialize other fields. */ + key->write_private_key = NULL; + key->read_private_key = NULL; + key->context = NULL; + key->heap = heap; + #endif + #ifdef WOLF_CRYPTO_CB + key->devId = devId; + #endif + /* Start in initialized state. */ + key->state = WC_LMS_STATE_INITED; + } + + return ret; +} + +/* Get the string representation of the LMS parameter set. + * + * @param [in] lmsParm LMS parameter set identifier. + * @return String representing LMS parameter set on success. + * @return NULL when parameter set not supported. + */ +const char* wc_LmsKey_ParmToStr(enum wc_LmsParm lmsParm) +{ + const char* str = NULL; + int i; + + /* Search through table for matching numeric identifier. */ + for (i = 0; i < WC_LMS_MAP_LEN; i++) { + if (lmsParm == wc_lms_map[i].id) { + /* Get string corresponding to numeric identifier. */ + str = wc_lms_map[i].str; + break; + } + } + + /* Return the string or NULL. */ + return str; +} + +/* Set the wc_LmsParm of an LMS key. + * + * Use this if you wish to set a key with a predefined parameter set, + * such as WC_LMS_PARM_L2_H10_W8. + * + * Key must be inited before calling this. + * + * @param [in, out] key LMS key to set parameters on. + * @param [in] lmsParm Identifier of parameters. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return BAD_FUNC_ARG when parameters not supported. + */ +int wc_LmsKey_SetLmsParm(LmsKey* key, enum wc_LmsParm lmsParm) +{ + int ret = 0; + + /* Validate parameters. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Check state is valid. */ + if ((ret == 0) && (key->state != WC_LMS_STATE_INITED)) { + WOLFSSL_MSG("error: LmsKey needs init"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + int i; + + ret = BAD_FUNC_ARG; + /* Search through table for matching numeric identifier. */ + for (i = 0; i < WC_LMS_MAP_LEN; i++) { + if (lmsParm == wc_lms_map[i].id) { + /* Set the parameters into the key. */ + key->params = &wc_lms_map[i].params; + ret = 0; + break; + } + } + } + + if (ret == 0) { + /* Move the state to params set. + * Key is ready for MakeKey or Reload. */ + key->state = WC_LMS_STATE_PARMSET; + } + + return ret; +} + +/* Set the parameters of an LMS key. + * + * Use this if you wish to set specific parameters not found in the + * wc_LmsParm predefined sets. See comments in lms.h for allowed + * parameters. + * + * Key must be inited before calling this. + * + * @param [in, out] key LMS key to set parameters on. + * @param [in] levels Number of tree levels. + * @param [in] height Height of each tree. + * @param [in] winternitz Width or Winternitz coefficient. + * @return 0 on success. + * @return BAD_FUNC_ARG when key is NULL. + * @return BAD_FUNC_ARG when parameters not supported. + * */ +int wc_LmsKey_SetParameters(LmsKey* key, int levels, int height, + int winternitz) +{ + int ret = 0; + + /* Validate parameters. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + /* Check state is valid. */ + if ((ret == 0) && (key->state != WC_LMS_STATE_INITED)) { + WOLFSSL_MSG("error: LmsKey needs init"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + int i; + + ret = BAD_FUNC_ARG; + /* Search through table for matching levels, height and width. */ + for (i = 0; i < WC_LMS_MAP_LEN; i++) { + if ((levels == wc_lms_map[i].params.levels) && + (height == wc_lms_map[i].params.height) && + (winternitz == wc_lms_map[i].params.width)) { + /* Set the parameters into the key. */ + key->params = &wc_lms_map[i].params; + ret = 0; + break; + } + } + } + + if (ret == 0) { + /* Move the state to params set. + * Key is ready for MakeKey or Reload. */ + key->state = WC_LMS_STATE_PARMSET; + } + + return ret; +} + +/* Get the parameters of an LMS key. + * + * Key must be inited and parameters set before calling this. + * + * @param [in] key LMS key. + * @param [out] levels Number of levels of trees. + * @param [out] height Height of the trees. + * @param [out] winternitz Winternitz width. + * Returns 0 on success. + * */ +int wc_LmsKey_GetParameters(const LmsKey* key, int* levels, int* height, + int* winternitz) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (levels == NULL) || (height == NULL) || + (winternitz == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* Validate the parameters are available. */ + if ((ret == 0) && (key->params == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Set the levels, height and Winternitz width from parameters. */ + *levels = key->params->levels; + *height = key->params->height; + *winternitz = key->params->width; + } + + return ret; +} + +/* Frees the LMS key from memory. + * + * This does not affect the private key saved to non-volatile storage. + * + * @param [in, out] key LMS key to free. + */ +void wc_LmsKey_Free(LmsKey* key) +{ + if (key != NULL) { + #ifndef WOLFSSL_LMS_VERIFY_ONLY + if (key->priv_data != NULL) { + const LmsParams* params = key->params; + + ForceZero(key->priv_data, LMS_PRIV_DATA_LEN(params->levels, + params->height, params->p, params->rootLevels, + params->cacheBits)); + + XFREE(key->priv_data, key->heap, DYNAMIC_TYPE_LMS); + } + #endif + + ForceZero(key, sizeof(LmsKey)); + + key->state = WC_LMS_STATE_FREED; + } +} + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +/* Set the write private key callback to the LMS key structure. + * + * The callback must be able to write/update the private key to + * non-volatile storage. + * + * @param [in, out] key LMS key. + * @param [in] write_cb Callback function that stores private key. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or write_cb is NULL. + * @return BAD_STATE_E when key state is invalid. + */ +int wc_LmsKey_SetWriteCb(LmsKey* key, wc_lms_write_private_key_cb write_cb) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (write_cb == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Changing the write callback of an already working key is forbidden. */ + if ((ret == 0) && (key->state == WC_LMS_STATE_OK)) { + WOLFSSL_MSG("error: wc_LmsKey_SetWriteCb: key in use"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Set the callback into the key. */ + key->write_private_key = write_cb; + } + + return ret; +} + +/* Set the read private key callback to the LMS key structure. + * + * The callback must be able to read the private key from + * non-volatile storage. + * + * @param [in, out] key LMS key. + * @param [in] read_cb Callback function that loads private key. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or read_cb is NULL. + * @return BAD_STATE_E when key state is invalid. + * */ +int wc_LmsKey_SetReadCb(LmsKey* key, wc_lms_read_private_key_cb read_cb) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (read_cb == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Changing the read callback of an already working key is forbidden. */ + if ((ret == 0) && (key->state == WC_LMS_STATE_OK)) { + WOLFSSL_MSG("error: wc_LmsKey_SetReadCb: key in use"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Set the callback into the key. */ + key->read_private_key = read_cb; + } + + return ret; +} + +/* Sets the context to be used by write and read callbacks. + * + * E.g. this could be a filename if the callbacks write/read to file. + * + * @param [in, out] key LMS key. + * @param [in] context Pointer to data for read/write callbacks. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or context is NULL. + * @return BAD_STATE_E when key state is invalid. + * */ +int wc_LmsKey_SetContext(LmsKey* key, void* context) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (context == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Setting context of an already working key is forbidden. */ + if ((ret == 0) && (key->state == WC_LMS_STATE_OK)) { + WOLFSSL_MSG("error: wc_LmsKey_SetContext: key in use"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Set the callback context into the key. */ + key->context = context; + } + + return ret; +} + +/* Make the LMS private/public key pair. The key must have its parameters + * set before calling this. + * + * Write/read callbacks, and context data, must be set prior. + * Key must have parameters set. + * + * @param [in, out] key LMS key. + * @param [in] rng Random number generator. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or rng is NULL. + * @return BAD_STATE_E when key is in an invalid state. + * @return BAD_FUNC_ARG when write callback or callback context not set. + * @return BAD_STATE_E when no more signatures can be created. + */ +int wc_LmsKey_MakeKey(LmsKey* key, WC_RNG* rng) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (rng == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Check state. */ + if ((ret == 0) && (key->state != WC_LMS_STATE_PARMSET)) { + WOLFSSL_MSG("error: LmsKey not ready for generation"); + ret = BAD_STATE_E; + } + /* Check write callback set. */ + if ((ret == 0) && (key->write_private_key == NULL)) { + WOLFSSL_MSG("error: LmsKey write callback is not set"); + ret = BAD_FUNC_ARG; + } + /* Check callback context set. */ + if ((ret == 0) && (key->context == NULL)) { + WOLFSSL_MSG("error: LmsKey context is not set"); + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (key->priv_data == NULL)) { + const LmsParams* params = key->params; + + /* Allocate memory for the private key data. */ + key->priv_data = XMALLOC(LMS_PRIV_DATA_LEN(params->levels, + params->height, params->p, params->rootLevels, params->cacheBits), + key->heap, DYNAMIC_TYPE_LMS); + /* Check pointer is valid. */ + if (key->priv_data == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + LmsState* state; + #else + LmsState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for working state. */ + state = XMALLOC(sizeof(LmsState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize working state for use. */ + ret = wc_lmskey_state_init(state, key->params); + if (ret == 0) { + /* Make the HSS key. */ + ret = wc_hss_make_key(state, rng, key->priv_raw, &key->priv, + key->priv_data, key->pub); + wc_lmskey_state_free(state); + } + ForceZero(state, sizeof(LmsState)); + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + if (ret == 0) { + /* Write private key to storage. */ + int rv = key->write_private_key(key->priv_raw, HSS_PRIVATE_KEY_LEN, + key->context); + if (rv != WC_LMS_RC_SAVED_TO_NV_MEMORY) { + ret = IO_FAILED_E; + } + } + + /* This should not happen, but check whether signatures can be created. */ + if ((ret == 0) && (wc_LmsKey_SigsLeft(key) == 0)) { + WOLFSSL_MSG("error: generated LMS key signatures exhausted"); + key->state = WC_LMS_STATE_NOSIGS; + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Update state. */ + key->state = WC_LMS_STATE_OK; + } + + return ret; +} + +/* Reload a key that has been prepared with the appropriate params and + * data. Use this if you wish to resume signing with an existing key. + * + * Write/read callbacks, and context data, must be set prior. + * Key must have parameters set. + * + * @param [in, out] key LMS key. + * + * Returns 0 on success. */ +int wc_LmsKey_Reload(LmsKey* key) +{ + int ret = 0; + + /* Validate parameter. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + /* Check state. */ + if ((ret == 0) && (key->state != WC_LMS_STATE_PARMSET)) { + WOLFSSL_MSG("error: LmsKey not ready for reload"); + ret = BAD_STATE_E; + } + /* Check read callback present. */ + if ((ret == 0) && (key->read_private_key == NULL)) { + WOLFSSL_MSG("error: LmsKey read callback is not set"); + ret = BAD_FUNC_ARG; + } + /* Check context for callback set */ + if ((ret == 0) && (key->context == NULL)) { + WOLFSSL_MSG("error: LmsKey context is not set"); + ret = BAD_FUNC_ARG; + } + + if ((ret == 0) && (key->priv_data == NULL)) { + const LmsParams* params = key->params; + + /* Allocate memory for the private key data. */ + key->priv_data = XMALLOC(LMS_PRIV_DATA_LEN(params->levels, + params->height, params->p, params->rootLevels, params->cacheBits), + key->heap, DYNAMIC_TYPE_LMS); + /* Check pointer is valid. */ + if (key->priv_data == NULL) { + ret = MEMORY_E; + } + } + if (ret == 0) { + /* Load private key. */ + int rv = key->read_private_key(key->priv_raw, HSS_PRIVATE_KEY_LEN, + key->context); + if (rv != WC_LMS_RC_READ_TO_MEMORY) { + ret = IO_FAILED_E; + } + } + + /* Double check the key actually has signatures left. */ + if ((ret == 0) && (wc_LmsKey_SigsLeft(key) == 0)) { + WOLFSSL_MSG("error: reloaded LMS key signatures exhausted"); + key->state = WC_LMS_STATE_NOSIGS; + ret = BAD_STATE_E; + } + + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + LmsState* state; + #else + LmsState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for working state. */ + state = XMALLOC(sizeof(LmsState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize working state for use. */ + ret = wc_lmskey_state_init(state, key->params); + if (ret == 0) { + /* Reload the key ready for signing. */ + ret = wc_hss_reload_key(state, key->priv_raw, &key->priv, + key->priv_data, NULL); + } + ForceZero(state, sizeof(LmsState)); + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + + if (ret == 0) { + /* Update state. */ + key->state = WC_LMS_STATE_OK; + } + + return ret; +} + +/* Get the private key length based on parameter set of key. + * + * @param [in] key LMS key. + * @param [out] len Length of private key. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or len is NULL or parameters not set. + */ +int wc_LmsKey_GetPrivLen(const LmsKey* key, word32* len) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (len == NULL) || (key->params == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Return private key length from parameter set. */ + *len = HSS_PRIVATE_KEY_LEN; + } + + return ret; +} + +/* Sign a message. + * + * @param [in, out] key LMS key to sign with. + * @param [out] sig Signature data. Buffer must be big enough to hold + * signature data. + * @param [out] sigSz Length of signature data. + * @param [in] msg Message to sign. + * @param [in] msgSz Length of message in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, sig, sigSz or msg is NULL. + * @return BAD_FUNC_ARG when msgSz is not greater than 0. + */ +int wc_LmsKey_Sign(LmsKey* key, byte* sig, word32* sigSz, const byte* msg, + int msgSz) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (sig == NULL) || (sigSz == NULL) || (msg == NULL)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (msgSz <= 0)) { + ret = BAD_FUNC_ARG; + } + /* Check state. */ + if ((ret == 0) && (key->state == WC_LMS_STATE_NOSIGS)) { + WOLFSSL_MSG("error: LMS signatures exhausted"); + ret = BAD_STATE_E; + } + if ((ret == 0) && (key->state != WC_LMS_STATE_OK)) { + /* The key had an error the last time it was used, and we + * can't guarantee its state. */ + WOLFSSL_MSG("error: can't sign, LMS key not in good state"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + LmsState* state; + #else + LmsState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for working state. */ + state = XMALLOC(sizeof(LmsState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize working state for use. */ + ret = wc_lmskey_state_init(state, key->params); + if (ret == 0) { + /* Sign message. */ + ret = wc_hss_sign(state, key->priv_raw, &key->priv, + key->priv_data, msg, msgSz, sig); + wc_lmskey_state_free(state); + } + ForceZero(state, sizeof(LmsState)); + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + if (ret == 0) { + *sigSz = (word32)key->params->sig_len; + } + if (ret == 0) { + /* Write private key to storage. */ + int rv = key->write_private_key(key->priv_raw, HSS_PRIVATE_KEY_LEN, + key->context); + if (rv != WC_LMS_RC_SAVED_TO_NV_MEMORY) { + ret = IO_FAILED_E; + } + } + + return ret; +} + +/* Returns whether signatures can be created with key. + * + * @param [in] key LMS key. + * + * @return 1 if there are signatures remaining. + * @return 0 if available signatures are exhausted. + */ +int wc_LmsKey_SigsLeft(LmsKey* key) +{ + int ret = 0; + + /* NULL keys have no signatures remaining. */ + if (key != NULL) { + ret = wc_hss_sigsleft(key->params, key->priv_raw); + } + + return ret; +} + +#endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY*/ + +/* Get the public key length based on parameter set of key. + * + * @param [in] key LMS key. + * @param [out] len Length of public key. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or len is NULL or parameters not set. + */ +int wc_LmsKey_GetPubLen(const LmsKey* key, word32* len) +{ + int ret = 0; + + /* Validate parameters */ + if ((key == NULL) || (len == NULL) || (key->params == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + *len = HSS_PUBLIC_KEY_LEN; + } + + return ret; +} + +/* Export a generated public key and parameter set from one LmsKey + * to another. Use this to prepare a signature verification LmsKey + * that is pub only. + * + * Though the public key is all that is used to verify signatures, + * the parameter set is needed to calculate the signature length + * before hand. + * + * @param [out] keyDst LMS key to copy into. + * @param [in] keySrc LMS key to copy. + * @return 0 on success. + * @return BAD_FUNC_ARG when keyDst or keySrc is NULL. + */ +int wc_LmsKey_ExportPub(LmsKey* keyDst, const LmsKey* keySrc) +{ + int ret = 0; + + if ((keyDst == NULL) || (keySrc == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + ForceZero(keyDst, sizeof(LmsKey)); + + keyDst->params = keySrc->params; + XMEMCPY(keyDst->pub, keySrc->pub, sizeof(keySrc->pub)); + + /* Mark this key as verify only, to prevent misuse. */ + keyDst->state = WC_LMS_STATE_VERIFYONLY; + } + + return ret; +} + +/* Exports the raw LMS public key buffer from key to out buffer. + * The out buffer should be large enough to hold the public key, and + * outLen should indicate the size of the buffer. + * + * Call wc_LmsKey_GetPubLen beforehand to determine pubLen. + * + * @param [in] key LMS key. + * @param [out] out Buffer to hold encoded public key. + * @param [in, out] outLen On in, length of out in bytes. + * On out, the length of the public key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key, out or outLen is NULL. + * @return BUFFER_E when outLen is too small to hold encoded public key. + */ +int wc_LmsKey_ExportPubRaw(const LmsKey* key, byte* out, word32* outLen) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Check size of out is sufficient. */ + if ((ret == 0) && (*outLen < HSS_PUBLIC_KEY_LEN)) { + ret = BUFFER_E; + } + + if (ret == 0) { + /* Return encoded public key. */ + XMEMCPY(out, key->pub, HSS_PUBLIC_KEY_LEN); + *outLen = HSS_PUBLIC_KEY_LEN; + } + + return ret; +} + +/* Imports a raw public key buffer from in array to LmsKey key. + * + * The LMS parameters must be set first with wc_LmsKey_SetLmsParm or + * wc_LmsKey_SetParameters, and inLen must match the length returned + * by wc_LmsKey_GetPubLen. + * + * Call wc_LmsKey_GetPubLen beforehand to determine pubLen. + * + * @param [in, out] key LMS key to put public key in. + * @param [in] in Buffer holding encoded public key. + * @param [in] inLen Length of encoded public key in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or in is NULL. + * @return BUFFER_E when inLen does not match public key length by parameters. + */ +int wc_LmsKey_ImportPubRaw(LmsKey* key, const byte* in, word32 inLen) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (in == NULL)) { + ret = BAD_FUNC_ARG; + } + if ((ret == 0) && (inLen != HSS_PUBLIC_KEY_LEN)) { + /* Something inconsistent. Parameters weren't set, or input + * pub key is wrong.*/ + return BUFFER_E; + } + + if (ret == 0) { + XMEMCPY(key->pub, in, inLen); + + key->state = WC_LMS_STATE_VERIFYONLY; + } + + return ret; +} + +/* Given a levels, height, winternitz parameter set, determine + * the signature length. + * + * Call this before wc_LmsKey_Sign so you know the length of + * the required signature buffer. + * + * @param [in] key LMS key. + * @param [out] len Length of a signature in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when key or len is NULL. + */ +int wc_LmsKey_GetSigLen(const LmsKey* key, word32* len) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (len == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + *len = key->params->sig_len; + } + + return ret; +} + +/* Verify the signature of the message with public key. + * + * @param [in] key LMS key. + * @param [in] sig Signature to verify. + * @param [in] sigSz Size of signature in bytes. + * @param [in] msg Message to verify. + * @param [in] msgSz Length of the message in bytes. + * @return 0 on success. + * @return BAD_FUNC_ARG when a key, sig or msg is NULL. + * @return SIG_VERIFY_E when signature did not verify message. + * @return BAD_STATE_E when wrong state for operation. + * @return BUFFER_E when sigSz is invalid for parameters. + */ +int wc_LmsKey_Verify(LmsKey* key, const byte* sig, word32 sigSz, + const byte* msg, int msgSz) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (sig == NULL) || (msg == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Check state. */ + if ((ret == 0) && (key->state != WC_LMS_STATE_OK) && + (key->state != WC_LMS_STATE_VERIFYONLY)) { + /* LMS key not ready for verification. Param str must be + * set first, and Reload() called. */ + WOLFSSL_MSG("error: LMS key not ready for verification"); + ret = BAD_STATE_E; + } + /* Check signature length. */ + if ((ret == 0) && (sigSz != key->params->sig_len)) { + ret = BUFFER_E; + } + + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + LmsState* state; + #else + LmsState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for working state. */ + state = XMALLOC(sizeof(LmsState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize working state for use. */ + ret = wc_lmskey_state_init(state, key->params); + if (ret == 0) { + /* Verify signature of message with public key. */ + ret = wc_hss_verify(state, key->pub, msg, msgSz, sig); + wc_lmskey_state_free(state); + } + ForceZero(state, sizeof(LmsState)); + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + + return ret; +} + +#endif /* WOLFSSL_HAVE_LMS && WOLFSSL_WC_LMS */ diff --git a/src/wolfcrypt/src/wc_lms_impl.c b/src/wolfcrypt/src/wc_lms_impl.c index dbd5ed6..3f48420 100644 --- a/src/wolfcrypt/src/wc_lms_impl.c +++ b/src/wolfcrypt/src/wc_lms_impl.c @@ -19,8 +19,3074 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#include +/* Implementation based on: + * RFC 8554: Leighton-Micali Hash-Based Signatures + * https://datatracker.ietf.org/doc/html/rfc8554 + * Implementation by Sean Parkinson. + */ + +/* Possible LMS options: + * + * WC_LMS_FULL_HASH Default: OFF + * Performs a full hash instead of assuming internals. + * Enable when using hardware SHA-256. + * WOLFSSL_LMS_VERIFY_ONLY Default: OFF + * Only compiles in verification code. + * WOLFSSL_WC_LMS_SMALL Default: OFF + * Implementation is smaller code size with slow signing. + * Enable when memory is limited. + */ + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_WC_LMS) + +/* Length of R in bytes. */ +#define LMS_R_LEN 4 +/* Length of D in bytes. */ +#define LMS_D_LEN 2 +/* Length of checksum in bytes. */ +#define LMS_CKSM_LEN 2 + +/* Predefined values used in hashes to make them unique. */ +/* Fixed value for calculating x. */ +#define LMS_D_FIXED 0xff +/* D value when computing public key. */ +#define LMS_D_PBLC 0x8080 +/* D value when computing message. */ +#define LMS_D_MESG 0x8181 +/* D value when computing leaf node. */ +#define LMS_D_LEAF 0x8282 +/* D value when computing interior node. */ +#define LMS_D_INTR 0x8383 +/* D value when computing C, randomizer value. */ +#define LMS_D_C 0xfffd +/* D value when computing child SEED for private key. */ +#define LMS_D_CHILD_SEED 0xfffe +/* D value when computing child I for private key. */ +#define LMS_D_CHILD_I 0xffff + +/* Length of data to hash when computing seed: + * 16 + 4 + 2 + 32 = 54 */ +#define LMS_SEED_HASH_LEN \ + (LMS_I_LEN + LMS_R_LEN + LMS_D_LEN + LMS_MAX_NODE_LEN) + +/* Length of data to hash when computing a node: + * 16 + 4 + 2 + 32 + 32 = 86 */ +#define LMS_NODE_HASH_LEN \ + (LMS_I_LEN + LMS_R_LEN + LMS_D_LEN + 2 * LMS_MAX_NODE_LEN) + +/* Length of data to hash when computing most results: + * 16 + 4 + 2 + 1 + 32 = 55 */ +#define LMS_HASH_BUFFER_LEN \ + (LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN + LMS_W_LEN + LMS_MAX_NODE_LEN) + +/* Length of data to hash when computing Q: + * 16 + 4 + 2 + 32 = 54 */ +#define LMS_Q_BUFFER_LEN \ + (LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN + LMS_MAX_NODE_LEN) + +/* Length of preliminary data to hash when computing K: + * 16 + 4 + 2 = 22 */ +#define LMS_K_PRE_LEN (LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN) + +/* Length of preliminary data to hash when computing message hash: + * 16 + 4 + 2 = 22 */ +#define LMS_MSG_PRE_LEN (LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN) + + +#ifdef WC_LMS_DEBUG_PRINT_DATA +/* Print data when dubgging implementation. + * + * @param [in] name String to print before data. + * @param [in] data Array of bytes. + * @param [in] len Length of data in array. + */ +static void print_data(const char* name, const byte* data, int len) +{ + int i; + + fprintf(stderr, "%6s: ", name); + for (i = 0; i < len; i++) { + fprintf(stderr, "%02x", data[i]); + } + fprintf(stderr, "\n"); +} +#endif + +/*************************************** + * Index APIs + **************************************/ + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +/* Zero index. + * + * @param [out] a Byte array. Big-endian encoding. + * @param [in] len Length of array in bytes. + */ +static WC_INLINE void wc_lms_idx_zero(unsigned char* a, int len) +{ + XMEMSET(a, 0, len); +} + +/* Increment big-endian value. + * + * @param [in, out] a Byte array. Big-endian encoding. + * @param [in] len Length of array in bytes. + */ +static WC_INLINE void wc_lms_idx_inc(unsigned char* a, int len) +{ + int i; + + /* Starting at least-significant byte up to most. */ + for (i = len - 1; i >= 0; i--) { + /* Add one/carry to byte. */ + if ((++a[i]) != 0) { + /* No more carry. */ + break; + } + } +} +#endif /* !WOLFSSL_LMS_VERIFY_ONLY */ + +/*************************************** + * Hash APIs + **************************************/ + +/* Set hash data and length into SHA-256 digest. + * + * @param [in, out] state SHA-256 digest object. + * @param [in] data Data to add to hash. + * @param [in] len Number of bytes in data. Must be less than a block. + */ +#define LMS_SHA256_SET_DATA(sha256, data, len) \ +do { \ + XMEMCPY((sha256)->buffer, (data), (len)); \ + (sha256)->buffLen = (len); \ + (sha256)->loLen = (len); \ +} while (0) + +/* Add hash data and length into SHA-256 digest. + * + * @param [in, out] state SHA-256 digest object. + * @param [in] data Data to add to hash. + * @param [in] len Number of bytes in data. Must be less than a block. + */ +#define LMS_SHA256_ADD_DATA(sha256, data, len) \ +do { \ + XMEMCPY((byte*)(sha256)->buffer + (sha256)->buffLen, (data), (len)); \ + (sha256)->buffLen += (len); \ + (sha256)->loLen += (len); \ +} while (0) + +/* Set the length of 54 bytes in buffer as per SHA-256 final operation. + * + * @param [in, out] buffer Hash data buffer to add length to. + */ +#define LMS_SHA256_SET_LEN_54(buffer) \ +do { \ + (buffer)[54] = 0x80; \ + (buffer)[55] = 0x00; \ + (buffer)[56] = 0x00; \ + (buffer)[57] = 0x00; \ + (buffer)[58] = 0x00; \ + (buffer)[59] = 0x00; \ + (buffer)[60] = 0x00; \ + (buffer)[61] = 0x00; \ + (buffer)[62] = 0x01; \ + (buffer)[63] = 0xb0; \ +} while (0) + +/* Set the length of 55 bytes in buffer as per SHA-256 final operation. + * + * @param [in, out] buffer Hash data buffer to add length to. + */ +#define LMS_SHA256_SET_LEN_55(buffer) \ +do { \ + (buffer)[55] = 0x80; \ + (buffer)[56] = 0x00; \ + (buffer)[57] = 0x00; \ + (buffer)[58] = 0x00; \ + (buffer)[59] = 0x00; \ + (buffer)[60] = 0x00; \ + (buffer)[61] = 0x00; \ + (buffer)[62] = 0x01; \ + (buffer)[63] = 0xb8; \ +} while (0) + +#ifndef WC_LMS_FULL_HASH +/* Hash one full block of data and compute result. + * + * @param [in] sha256 SHA-256 hash object. + * @param [in] data Data to hash. + * @param [out] hash Hash output. + * @return 0 on success. + */ +static WC_INLINE int wc_lms_hash_block(wc_Sha256* sha256, const byte* data, + byte* hash) +{ + /* Hash the block and reset SHA-256 state. */ + return wc_Sha256HashBlock(sha256, data, hash); +} +#endif /* !WC_LMS_FULL_HASH */ + +/* Hash data and compute result. + * + * @param [in] sha256 SHA-256 hash object. + * @param [in] data Data to hash. + * @param [in] len Length of data to hash. + * @param [out] hash Hash output. + * @return 0 on success. + */ +static WC_INLINE int wc_lms_hash(wc_Sha256* sha256, byte* data, word32 len, + byte* hash) +{ + int ret; + +#ifndef WC_LMS_FULL_HASH + if (len < WC_SHA256_BLOCK_SIZE) { + /* Store data into SHA-256 object's buffer. */ + LMS_SHA256_SET_DATA(sha256, data, len); + ret = wc_Sha256Final(sha256, hash); + } + else if (len < WC_SHA256_BLOCK_SIZE + WC_SHA256_PAD_SIZE) { + ret = wc_Sha256HashBlock(sha256, data, NULL); + if (ret == 0) { + byte* buffer = (byte*)sha256->buffer; + int rem = len - WC_SHA256_BLOCK_SIZE; + + XMEMCPY(buffer, data + WC_SHA256_BLOCK_SIZE, rem); + buffer[rem++] = 0x80; + XMEMSET(buffer + rem, 0, WC_SHA256_BLOCK_SIZE - 2 - rem); + buffer[WC_SHA256_BLOCK_SIZE - 2] = (byte)(len >> 5); + buffer[WC_SHA256_BLOCK_SIZE - 1] = (byte)(len << 3); + ret = wc_Sha256HashBlock(sha256, buffer, hash); + } + } + else { + ret = wc_Sha256Update(sha256, data, len); + if (ret == 0) { + ret = wc_Sha256Final(sha256, hash); + } + } +#else + ret = wc_Sha256Update(sha256, data, len); + if (ret == 0) { + ret = wc_Sha256Final(sha256, hash); + } +#endif /* !WC_LMS_FULL_HASH */ + + return ret; +} + +/* Update hash with first data. + * + * Sets the data directly into SHA-256's buffer if valid. + * + * @param [in] sha256 SHA-256 hash object. + * @param [in] data Data to hash. + * @param [in] len Length of data to hash. + * @return 0 on success. + */ +static WC_INLINE int wc_lms_hash_first(wc_Sha256* sha256, const byte* data, + word32 len) +{ + int ret = 0; + +#ifndef WC_LMS_FULL_HASH + if (len < WC_SHA256_BLOCK_SIZE) { + /* Store data into SHA-256 object's buffer. */ + LMS_SHA256_SET_DATA(sha256, data, len); + } + else +#endif /* !WC_LMS_FULL_HASH */ + { + ret = wc_Sha256Update(sha256, data, len); + } + + return ret; +} + +/* Update hash with further data. + * + * Adds the data directly into SHA-256's buffer if valid. + * + * @param [in] sha256 SHA-256 hash object. + * @param [in] data Data to hash. + * @param [in] len Length of data to hash. + * @return 0 on success. + */ +static WC_INLINE int wc_lms_hash_update(wc_Sha256* sha256, const byte* data, + word32 len) +{ + int ret = 0; + +#ifndef WC_LMS_FULL_HASH + if (sha256->buffLen + len < WC_SHA256_BLOCK_SIZE) { + /* Add data to SHA-256 object's buffer. */ + LMS_SHA256_ADD_DATA(sha256, data, len); + } + else if (sha256->buffLen + len < 2 * WC_SHA256_BLOCK_SIZE) { + byte* buffer = (byte*)sha256->buffer; + + XMEMCPY(buffer + sha256->buffLen, data, + WC_SHA256_BLOCK_SIZE - sha256->buffLen); + ret = wc_Sha256HashBlock(sha256, buffer, NULL); + if (ret == 0) { + int rem = len - (WC_SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(buffer, data + WC_SHA256_BLOCK_SIZE - sha256->buffLen, rem); + sha256->buffLen = rem; + sha256->loLen += len; + } + } + else { + ret = wc_Sha256Update(sha256, data, len); + } +#else + ret = wc_Sha256Update(sha256, data, len); +#endif /* !WC_LMS_FULL_HASH */ + + return ret; +} + +/* Finalize hash. + * + * @param [in] sha256 SHA-256 hash object. + * @param [out] hash Hash output. + * @return 0 on success. + */ +static WC_INLINE int wc_lms_hash_final(wc_Sha256* sha256, byte* hash) +{ +#ifndef WC_LMS_FULL_HASH + int ret = 0; + byte* buffer = (byte*)sha256->buffer; + + buffer[sha256->buffLen++] = 0x80; + if (sha256->buffLen > WC_SHA256_PAD_SIZE) { + XMEMSET(buffer + sha256->buffLen, 0, + WC_SHA256_BLOCK_SIZE - sha256->buffLen); + ret = wc_Sha256HashBlock(sha256, buffer, NULL); + sha256->buffLen = 0; + } + if (ret == 0) { + XMEMSET(buffer + sha256->buffLen, 0, + WC_SHA256_BLOCK_SIZE - 8 - sha256->buffLen); + sha256->hiLen = (sha256->hiLen << 3) + (sha256->loLen >> 29); + sha256->loLen = sha256->loLen << 3; + #ifdef LITTLE_ENDIAN_ORDER + sha256->buffer[14] = ByteReverseWord32(sha256->hiLen); + sha256->buffer[15] = ByteReverseWord32(sha256->loLen); + #else + sha256->buffer[14] = sha256->hiLen; + sha256->buffer[15] = sha256->loLen; + #endif + ret = wc_Sha256HashBlock(sha256, buffer, hash); + sha256->buffLen = 0; + sha256->hiLen = 0; + sha256->loLen = 0; + } + + return ret; +#else + return wc_Sha256Final(sha256, hash); +#endif +} + +/*************************************** + * LM-OTS APIs + **************************************/ + +/* Expand Q to and array of Winternitz width bits values plus checksum. + * + * Supported Winternitz widths: 8, 4, 2, 1. + * + * Algorithm 2: Checksum Calculation + * sum = 0 + * for ( i = 0; i < (n*8/w); i = i + 1 ) { + * sum = sum + (2^w - 1) - coef(S, i, w) + * } + * return (sum << ls) + * Section 3.1.3: Strings of w-Bit Elements + * coef(S, i, w) = (2^w - 1) AND + * ( byte(S, floor(i * w / 8)) >> + * (8 - (w * (i % (8 / w)) + w)) ) + * Combine coefficient expansion with checksum calculation. + * + * @param [in] q Q array of bytes. + * @param [in] n Number of bytes in Q. + * @param [in] w Winternitz width in bits. + * @param [in] ls Left shift of checksum. + * @param [out] qe Expanded Q with checksum. + * @return 0 on success. + * @return BAD_FUNC_ARG when Winternitz width is not supported. + */ +static WC_INLINE int wc_lmots_q_expand(byte* q, word8 n, word8 w, word8 ls, + byte* qe) +{ + int ret = 0; + word16 sum; + unsigned int i; + +#ifndef WOLFSSL_WC_LMS_SMALL + switch (w) { + /* Winternitz width of 8. */ + case 8: + /* No expansion required, just copy. */ + XMEMCPY(qe, q, n); + /* Start sum with all 2^w - 1s and subtract from that. */ + sum = 0xff * n; + /* For each byte of the hash. */ + for (i = 0; i < n; i++) { + /* Subtract coefficient from sum. */ + sum -= q[i]; + } + /* Put coefficients of checksum on the end. */ + qe[n + 0] = (word8)(sum >> 8); + qe[n + 1] = (word8)(sum ); + break; + /* Winternitz width of 4. */ + case 4: + sum = 2 * 0xf * n; + /* For each byte of the hash. */ + for (i = 0; i < n; i++) { + /* Get coefficient. */ + qe[0] = (q[i] >> 4) ; + qe[1] = (q[i] ) & 0xf; + /* Subtract coefficients from sum. */ + sum -= qe[0]; + sum -= qe[1]; + /* Move to next coefficients. */ + qe += 2; + } + /* Put coefficients of checksum on the end. */ + qe[0] = (word8)((sum >> 8) & 0xf); + qe[1] = (word8)((sum >> 4) & 0xf); + qe[2] = (word8)((sum ) & 0xf); + break; + /* Winternitz width of 2. */ + case 2: + sum = 4 * 0x3 * n; + /* For each byte of the hash. */ + for (i = 0; i < n; i++) { + /* Get coefficients. */ + qe[0] = (q[i] >> 4) ; + qe[0] = (q[i] >> 6) ; + qe[1] = (q[i] >> 4) & 0x3; + qe[2] = (q[i] >> 2) & 0x3; + qe[3] = (q[i] ) & 0x3; + /* Subtract coefficients from sum. */ + sum -= qe[0]; + sum -= qe[1]; + sum -= qe[2]; + sum -= qe[3]; + /* Move to next coefficients. */ + qe += 4; + } + /* Put coefficients of checksum on the end. */ + qe[0] = (word8)((sum >> 8) & 0x3); + qe[1] = (word8)((sum >> 6) & 0x3); + qe[2] = (word8)((sum >> 4) & 0x3); + qe[3] = (word8)((sum >> 2) & 0x3); + qe[4] = (word8)((sum ) & 0x3); + break; + /* Winternitz width of 1. */ + case 1: + sum = 8 * 0x01 * n; + /* For each byte of the hash. */ + for (i = 0; i < n; i++) { + /* Get coefficients. */ + qe[0] = (q[i] >> 4) ; + qe[0] = (q[i] >> 7) ; + qe[1] = (q[i] >> 6) & 0x1; + qe[2] = (q[i] >> 5) & 0x1; + qe[3] = (q[i] >> 4) & 0x1; + qe[4] = (q[i] >> 3) & 0x1; + qe[5] = (q[i] >> 2) & 0x1; + qe[6] = (q[i] >> 1) & 0x1; + qe[7] = (q[i] ) & 0x1; + /* Subtract coefficients from sum. */ + sum -= qe[0]; + sum -= qe[1]; + sum -= qe[2]; + sum -= qe[3]; + sum -= qe[4]; + sum -= qe[5]; + sum -= qe[6]; + sum -= qe[7]; + /* Move to next coefficients. */ + qe += 8; + } + /* Put coefficients of checksum on the end. */ + qe[0] = (word8)((sum >> 8) ); + qe[1] = (word8)((sum >> 7) & 0x1); + qe[2] = (word8)((sum >> 6) & 0x1); + qe[3] = (word8)((sum >> 5) & 0x1); + qe[4] = (word8)((sum >> 4) & 0x1); + qe[5] = (word8)((sum >> 3) & 0x1); + qe[6] = (word8)((sum >> 2) & 0x1); + qe[7] = (word8)((sum >> 1) & 0x1); + qe[8] = (word8)((sum ) & 0x1); + break; + default: + ret = BAD_FUNC_ARG; + break; + } + + (void)ls; +#else + int j; + + if ((w != 8) && (w != 4) && (w != 2) && (w != 1)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Start sum with all 2^w - 1s and subtract from that. */ + sum = ((1 << w) - 1) * ((n * 8) / w); + /* For each byte of the hash. */ + for (i = 0; i < n; i++) { + /* Get next byte. */ + byte a = *(q++); + /* For each width bits of byte. */ + for (j = 8 - w; j >= 0; j -= w) { + /* Get coefficient. */ + *qe = a >> (8 - w); + /* Subtract coefficient from sum. */ + sum -= *qe; + /* Move to next coefficient. */ + qe++; + /* Remove width bits. */ + a <<= w; + } + } + /* Shift sum up as required to pack it on the end of hash. */ + sum <<= ls; + /* For each width buts of checksum. */ + for (j = 16 - w; j >= ls; j--) { + /* Get coefficient. */ + *(qe++) = sum >> (16 - w); + /* Remove width bits. */ + sum <<= w; + } + } +#endif /* !WOLFSSL_WC_LMS_SMALL */ + + return ret; +} + +/* Calculate the hash for the message. + * + * Algorithm 3: Generating a One-Time Signature From a Private Key and a + * Message + * ... + * 5. Compute the array y as follows: + * Q = H(I || u32str(q) || u16str(D_MESG) || C || message) + * Algorithm 4b: Computing a Public Key Candidate Kc from a Signature, + * Message, Signature Typecode pubtype, and Identifiers I, q + * ... + * 3. Compute the string Kc as follows: + * Q = H(I || u32str(q) || u16str(D_MESG) || C || message) + * + * @param [in, out] state LMS state. + * @param [in] msg Message to hash. + * @param [in] msgSz Length of message in bytes. + * @param [in] c C or randomizer value. + * @param [out] q Computed Q value. + * @return 0 on success. + */ +static int wc_lmots_msg_hash(LmsState* state, const byte* msg, word32 msgSz, + const byte* c, byte* q) +{ + int ret; + byte* buffer = state->buffer; + byte* ip = buffer + LMS_I_LEN + LMS_Q_LEN; + + /* I || u32str(q) || u16str(D_MESG) */ + c16toa(LMS_D_MESG, ip); + /* H(I || u32str(q) || u16str(D_MESG) || ...) */ + ret = wc_lms_hash_first(&state->hash, buffer, LMS_MSG_PRE_LEN); + if (ret == 0) { + /* H(... || C || ...) */ + ret = wc_lms_hash_update(&state->hash, c, LMS_MAX_NODE_LEN); + } + if (ret == 0) { + /* H(... || message) */ + ret = wc_lms_hash_update(&state->hash, msg, msgSz); + } + if (ret == 0) { + /* Q = H(...) */ + ret = wc_lms_hash_final(&state->hash, q); + } + + return ret; +} + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +/* Compute array y, intermediates of public key calculation, for signature. + * + * Verification will perform the remaining iterations of hashing. + * + * Algorithm 3: Generating a One-Time Signature From a Private Key and a + * Message + * ... + * 5. Compute the array y as follows: + * Q = H(I || u32str(q) || u16str(D_MESG) || C || message) + * for ( i = 0; i < p; i = i + 1 ) { + * a = coef(Q || Cksm(Q), i, w) + * tmp = x[i] + * for ( j = 0; j < a; j = j + 1 ) { + * tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) + * } + * y[i] = tmp + * } + * x[i] can be calculated on the fly using psueodo key generation in Appendix A. + * Appendix A, The elements of the LM-OTS private keys are computed as: + * x_q[i] = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED). + * + * @param [in, out] state LMS state. + * @param [in] seed Seed to hash. + * @param [in] msg Message to sign. + * @param [in] msgSZ Length of message in bytes. + * @param [in] c C or randomizer value to hash. + * @param [out] y Calculated intermediate hashes. + * @return 0 on success. + */ +static int wc_lmots_compute_y_from_seed(LmsState* state, const byte* seed, + const byte* msg, word32 msgSz, const byte* c, byte* y) +{ + const LmsParams* params = state->params; + int ret = 0; + word16 i; + byte q[LMS_MAX_NODE_LEN + LMS_CKSM_LEN]; +#ifdef WOLFSSL_SMALL_STACK + byte* a = state->a; +#else + byte a[LMS_MAX_P]; +#endif /* WOLFSSL_SMALL_STACK */ + byte* buffer = state->buffer; + byte* ip = buffer + LMS_I_LEN + LMS_Q_LEN; + byte* jp = ip + LMS_P_LEN; + byte* tmp = jp + LMS_W_LEN; + + /* Q = H(I || u32str(q) || u16str(D_MESG) || C || message) */ + ret = wc_lmots_msg_hash(state, msg, msgSz, c, q); + if (ret == 0) { + /* Calculate checksum list all coefficients. */ + ret = wc_lmots_q_expand(q, LMS_MAX_NODE_LEN, params->width, params->ls, + a); + } + #ifndef WC_LMS_FULL_HASH + if (ret == 0) { + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_55(buffer); + } + #endif /* !WC_LMS_FULL_HASH */ + + /* Compute y for each coefficient. */ + for (i = 0; (ret == 0) && (i < params->p); i++) { + unsigned int j; + + /* tmp = x[i] + * = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED). */ + c16toa(i, ip); + *jp = LMS_D_FIXED; + XMEMCPY(tmp, seed, LMS_SEED_LEN); + #ifndef WC_LMS_FULL_HASH + ret = wc_lms_hash_block(&state->hash, buffer, tmp); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, tmp); + #endif /* !WC_LMS_FULL_HASH */ + + /* Apply the hash function coefficient number of times. */ + for (j = 0; (ret == 0) && (j < a[i]); j++) { + /* I || u32str(q) || u16str(i) || u8str(j) || tmp */ + *jp = j; + /* tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) */ + #ifndef WC_LMS_FULL_HASH + ret = wc_lms_hash_block(&state->hash, buffer, tmp); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, tmp); + #endif /* !WC_LMS_FULL_HASH */ + } + + if (ret == 0) { + /* y[i] = tmp */ + XMEMCPY(y, tmp, LMS_MAX_NODE_LEN); + y += LMS_MAX_NODE_LEN; + } + } + + return ret; +} +#endif /* !WOLFSSL_LMS_VERIFY_ONLY */ + +/* Compute public key candidate K from signature. + * + * Signing performed the first coefficient number of iterations of hashing. + * + * Algorithm 4b: Computing a Public Key Candidate Kc from a Signature, + * Message, Signature Typecode pubtype, and Identifiers I, q + * ... + * 3. Compute the string Kc as follows: + * Q = H(I || u32str(q) || u16str(D_MESG) || C || message) + * for ( i = 0; i < p; i = i + 1 ) { + * a = coef(Q || Cksm(Q), i, w) + * tmp = y[i] + * for ( j = a; j < 2^w - 1; j = j + 1 ) { + * tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) + * } + * z[i] = tmp + * } + * Kc = H(I || u32str(q) || u16str(D_PBLC) || + * z[0] || z[1] || ... || z[p-1]) + * 4, Return Kc. + * + * @param [in, out] state LMS state. + * @param [in] msg Message to compute Kc for. + * @param [in] msgSz Length of message in bytes. + * @param [in] c C or randomizer value from signature. + * @param [in] sig_y Part of signature containing array y. + * @param [out] kc Kc or public key candidate K. + * @return 0 on success. + */ +static int wc_lmots_compute_kc_from_sig(LmsState* state, const byte* msg, + word32 msgSz, const byte* c, const byte* sig_y, byte* kc) +{ + const LmsParams* params = state->params; + int ret; + word16 i; + byte q[LMS_MAX_NODE_LEN + LMS_CKSM_LEN]; +#ifdef WOLFSSL_SMALL_STACK + byte* a = state->a; +#else + byte a[LMS_MAX_P]; +#endif /* WOLFSSL_SMALL_STACK */ + byte* buffer = state->buffer; + byte* ip = buffer + LMS_I_LEN + LMS_Q_LEN; + byte* jp = ip + LMS_P_LEN; + byte* tmp = jp + LMS_W_LEN; + unsigned int max = ((unsigned int)1 << params->width) - 1; + + /* I || u32str(q) || u16str(D_PBLC). */ + c16toa(LMS_D_PBLC, ip); + /* H(I || u32str(q) || u16str(D_PBLC) || ...). */ + ret = wc_lms_hash_first(&state->hash_k, buffer, LMS_K_PRE_LEN); + if (ret == 0) { + /* Q = H(I || u32str(q) || u16str(D_MESG) || C || message) */ + ret = wc_lmots_msg_hash(state, msg, msgSz, c, q); + } + if (ret == 0) { + /* Calculate checksum list all coefficients. */ + ret = wc_lmots_q_expand(q, LMS_MAX_NODE_LEN, params->width, params->ls, + a); + } + #ifndef WC_LMS_FULL_HASH + if (ret == 0) { + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_55(buffer); + } + #endif /* !WC_LMS_FULL_HASH */ + + /* Compute z for each coefficient. */ + for (i = 0; (ret == 0) && (i < params->p); i++) { + unsigned int j; + + /* I || u32(str) || u16str(i) || ... */ + c16toa(i, ip); + + /* tmp = y[i]. + * I || u32(str) || u16str(i) || ... || tmp */ + XMEMCPY(tmp, sig_y, LMS_MAX_NODE_LEN); + sig_y += LMS_MAX_NODE_LEN; + + /* Finish iterations of hash from coefficient to max. */ + for (j = a[i]; (ret == 0) && (j < max); j++) { + /* I || u32str(q) || u16str(i) || u8str(j) || tmp */ + *jp = (word8)j; + /* tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) */ + #ifndef WC_LMS_FULL_HASH + ret = wc_lms_hash_block(&state->hash, buffer, tmp); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, tmp); + #endif /* !WC_LMS_FULL_HASH */ + } + + if (ret == 0) { + /* H(... || z[i] || ...) (for calculating Kc). */ + ret = wc_lms_hash_update(&state->hash_k, tmp, LMS_MAX_NODE_LEN); + } + } + + if (ret == 0) { + /* Kc = H(...) */ + ret = wc_lms_hash_final(&state->hash_k, kc); + } + + return ret; +} + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +/* Generate LM-OTS public key. + * + * Caller set: state->buffer = I || u32str(q) + * + * Algorithm 1: Generating a One-Time Signature Public Key From a Private Key + * ... + * 4. Compute the string K as follows: + * for ( i = 0; i < p; i = i + 1 ) { + * tmp = x[i] + * for ( j = 0; j < 2^w - 1; j = j + 1 ) { + * tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) + * } + * y[i] = tmp + * } + * K = H(I || u32str(q) || u16str(D_PBLC) || y[0] || ... || y[p-1]) + * ... + * x[i] can be calculated on the fly using psueodo key generation in Appendix A. + * Appendix A, The elements of the LM-OTS private keys are computed as: + * x_q[i] = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED). + * + * @param [in, out] state LMS state. + * @param [in] seed Seed to hash. + * @param [out] k K, the public key hash, or OTS_PUB_HASH + */ +static int wc_lmots_make_public_hash(LmsState* state, const byte* seed, byte* k) +{ + const LmsParams* params = state->params; + int ret; + word16 i; + byte* buffer = state->buffer; + byte* ip = buffer + LMS_I_LEN + LMS_Q_LEN; + byte* jp = ip + LMS_P_LEN; + byte* tmp = jp + LMS_W_LEN; + unsigned int max = ((unsigned int)1 << params->width) - 1; + + /* I || u32str(q) || u16str(D_PBLC). */ + c16toa(LMS_D_PBLC, ip); + /* K = H(I || u32str(q) || u16str(D_PBLC) || ...) */ + ret = wc_lms_hash_first(&state->hash_k, buffer, LMS_K_PRE_LEN); + +#ifndef WC_LMS_FULL_HASH + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_55(buffer); +#endif /* !WC_LMS_FULL_HASH */ + + for (i = 0; (ret == 0) && (i < params->p); i++) { + unsigned int j; + + /* tmp = x[i] + * = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED). */ + c16toa(i, ip); + *jp = LMS_D_FIXED; + XMEMCPY(tmp, seed, LMS_SEED_LEN); + #ifndef WC_LMS_FULL_HASH + ret = wc_lms_hash_block(&state->hash, buffer, tmp); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, tmp); + #endif /* !WC_LMS_FULL_HASH */ + /* Do all iterations to calculate y. */ + for (j = 0; (ret == 0) && (j < max); j++) { + /* I || u32str(q) || u16str(i) || u8str(j) || tmp */ + *jp = (word8)j; + /* tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) */ + #ifndef WC_LMS_FULL_HASH + ret = wc_lms_hash_block(&state->hash, buffer, tmp); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, tmp); + #endif /* !WC_LMS_FULL_HASH */ + } + if (ret == 0) { + /* K = H(... || y[i] || ...) */ + ret = wc_lms_hash_update(&state->hash_k, tmp, LMS_MAX_NODE_LEN); + } + } + if (ret == 0) { + /* K = H(I || u32str(q) || u16str(D_PBLC) || y[0] || ... || y[p-1]) */ + ret = wc_lms_hash_final(&state->hash_k, k); + } + + return ret; +} + +/* Encode the LM-OTS public key. + * + * Encoded into public key and signature if more than one level. + * T[1] is already in place. Putting in: type, ostype and I. + * + * Section 4.3: + * u32str(type) || u32str(otstype) || I || T[1] + * + * @param [in] params LMS parameters. + * @param [in] priv LMS private ley. + * @param [out] pub LMS public key. + */ +static void wc_lmots_public_key_encode(const LmsParams* params, + const byte* priv, byte* pub) +{ + const byte* priv_i = priv + LMS_Q_LEN + LMS_SEED_LEN; + + /* u32str(type) || ... || T(1) */ + c32toa(params->lmsType, pub); + pub += 4; + /* u32str(type) || u32str(otstype) || ... || T(1) */ + c32toa(params->lmOtsType, pub); + pub += 4; + /* u32str(type) || u32str(otstype) || I || T(1) */ + XMEMCPY(pub, priv_i, LMS_I_LEN); +} +#endif /* !WOLFSSL_LMS_VERIFY_ONLY */ + +/* Check the public key matches the parameters. + * + * @param [in] params LMS parameters. + * @param [in] pub Public key. + * @return 0 on success. + * @return PUBLIC_KEY_E when LMS or LM-OTS type doesn't match. + */ +static int wc_lmots_public_key_check(const LmsParams* params, const byte* pub) +{ + int ret = 0; + word32 type; + + /* Get message hash and height type. */ + ato32(pub, &type); + pub += 4; + /* Compare with parameters. */ + if (type != params->lmsType) { + ret = PUBLIC_KEY_E; + } + if (ret == 0) { + /* Get node hash and Winternitz width type. */ + ato32(pub, &type); + /* Compare with parameters. */ + if (type != params->lmOtsType) { + ret = PUBLIC_KEY_E; + } + } + + return ret; +} + +/* Calculate public key candidate K from signature. + * + * Algorithm 4b: Computing a Public Key Candidate Kc from a Signature, + * Message, Signature Typecode pubtype, and Identifiers I, q + * ... + * 2. Parse sigtype, C, and y from the signature as follows: + * a. sigtype = strTou32(first 4 bytes of signature) + * b. If sigtype is not equal to pubtype, return INVALID. + * ... + * d. C = next n bytes of signature + * e. y[0] = next n bytes of signature + * y[1] = next n bytes of signature + * ... + * y[p-1] = next n bytes of signature + * 3. Compute the string Kc as follows: + * ... + * + * @param [in, out] state LMS state. + * @param [in] pub LMS public key. + * @param [in] msg Message/next private key to verify. + * @param [in] msgSz Length of message in bytes. + * @param [in] sig Signature including type, C and y[0..p-1]. + * @param [out] kc Public key candidate Kc. + */ +static int wc_lmots_calc_kc(LmsState* state, const byte* pub, const byte* msg, + word32 msgSz, const byte* sig, byte* kc) +{ + int ret = 0; + + /* Check signature type. */ + if (XMEMCMP(pub, sig, LMS_TYPE_LEN) != 0) { + ret = SIG_TYPE_E; + } + if (ret == 0) { + /* Get C or randomizer value from signature. */ + const byte* c = sig + LMS_TYPE_LEN; + /* Get array y from signature. */ + const byte* y = c + LMS_MAX_NODE_LEN; + + /* Compute the public key candidate Kc from the signature. */ + ret = wc_lmots_compute_kc_from_sig(state, msg, msgSz, c, y, kc); + } + + return ret; +} + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +/* Generate LM-OTS private key. + * + * Algorithm 5: Computing an LMS Private Key + * But use Appendix A to generate x on the fly. + * PRIV = SEED | I + * + * @param [in] rng Random number generator. + * @param [out] priv Private key data. + */ +static int wc_lmots_make_private_key(WC_RNG* rng, byte* priv) +{ + return wc_RNG_GenerateBlock(rng, priv, LMS_SEED_LEN + LMS_I_LEN); +} + +/* Generate LM-OTS signature. + * + * Algorithm 3: Generating a One-Time Signature From a Private Key and a + * Message + * ... + * 4. Set C to a uniformly random n-byte string + * 5. Compute the array y as follows: + * ... + * 6. Return u32str(type) || C || y[0] || ... || y[p-1] + * + * @param [in, out] state LMS state. + * @param [in] seed Private key seed. + * @param [in] msg Message to be signed. + * @param [in] msgSz Length of message in bytes. + * @param [out] sig Signature buffer. + * @return 0 on success. + */ +static int wc_lmots_sign(LmsState* state, const byte* seed, const byte* msg, + word32 msgSz, byte* sig) +{ + int ret; + byte* buffer = state->buffer; + byte* ip = buffer + LMS_I_LEN + LMS_Q_LEN; + byte* jp = ip + LMS_P_LEN; + byte* tmp = jp + LMS_W_LEN; + byte* sig_c = sig; + + /* I || u32str(q) || u16str(0xFFFD) || ... */ + c16toa(LMS_D_C, ip); + /* I || u32str(q) || u16str(0xFFFD) || u8str(0xFF) || ... */ + *jp = LMS_D_FIXED; + /* I || u32str(q) || u16str(0xFFFD) || u8str(0xFF) || SEED */ + XMEMCPY(tmp, seed, LMS_SEED_LEN); + /* C = H(I || u32str(q) || u16str(0xFFFD) || u8str(0xFF) || SEED) + * sig = u32str(type) || C || ... */ +#ifndef WC_LMS_FULL_HASH + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_55(buffer); + ret = wc_lms_hash_block(&state->hash, buffer, sig_c); +#else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, sig_c); +#endif /* !WC_LMS_FULL_HASH */ + + if (ret == 0) { + byte* sig_y = sig_c + LMS_MAX_NODE_LEN; + + /* Compute array y. + * sig = u32str(type) || C || y[0] || ... || y[p-1] */ + ret = wc_lmots_compute_y_from_seed(state, seed, msg, msgSz, sig_c, + sig_y); + } + + return ret; +} +#endif /* WOLFSSL_LMS_VERIFY_ONLY */ + +/*************************************** + * LMS APIs + **************************************/ + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +#ifndef WOLFSSL_WC_LMS_SMALL +/* Load the LMS private state from data. + * + * @param [in] params LMS parameters. + * @param [out] state Private key state. + * @param [in] priv_data Private key data. + */ +static void wc_lms_priv_state_load(const LmsParams* params, LmsPrivState* state, + byte* priv_data) +{ + /* Authentication path data. */ + state->auth_path = priv_data; + priv_data += params->height * LMS_MAX_NODE_LEN; + + /* Stack of nodes. */ + state->stack.stack = priv_data; + priv_data += (params->height + 1) * LMS_MAX_NODE_LEN; + ato32(priv_data, &state->stack.offset); + priv_data += 4; + + /* Cached root nodes. */ + state->root = priv_data; + priv_data += LMS_ROOT_CACHE_LEN(params->rootLevels); + + /* Cached leaf nodes. */ + state->leaf.cache = priv_data; + priv_data += LMS_LEAF_CACHE_LEN(params->cacheBits); + ato32(priv_data, &state->leaf.idx); + priv_data += 4; + ato32(priv_data, &state->leaf.offset); + /* priv_data += 4; */ +} + +/* Store the LMS private state into data. + * + * @param [in] params LMS parameters. + * @param [in] state Private key state. + * @param [in, out] priv_data Private key data. + */ +static void wc_lms_priv_state_store(const LmsParams* params, + LmsPrivState* state, byte* priv_data) +{ + /* Authentication path data. */ + priv_data += params->height * LMS_MAX_NODE_LEN; + + /* Stack of nodes. */ + priv_data += (params->height + 1) * LMS_MAX_NODE_LEN; + c32toa(state->stack.offset, priv_data); + priv_data += 4; + + /* Cached root nodes. */ + priv_data += LMS_ROOT_CACHE_LEN(params->rootLevels); + + /* Cached leaf nodes. */ + priv_data += LMS_LEAF_CACHE_LEN(params->cacheBits); + c32toa(state->leaf.idx, priv_data); + priv_data += 4; + c32toa(state->leaf.offset, priv_data); + /* priv_data += 4; */ +} + +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING +/* Copy LMS private key state. + * + * @param [in] params LMS parameters. + * @param [out] dst LMS private state destination. + * @param [in] src LMS private state source. + */ +static void wc_lms_priv_state_copy(const LmsParams* params, + LmsPrivState* dst, const LmsPrivState* src) +{ + XMEMCPY(dst->auth_path, src->auth_path, LMS_PRIV_STATE_LEN(params->height, + params->rootLevels, params->cacheBits)); + dst->stack.offset = src->stack.offset; + dst->leaf.idx = src->leaf.idx; + dst->leaf.offset = src->leaf.offset; +} +#endif /* !WOLFSSL_LMS_NO_SIGN_SMOOTHING */ +#endif /* !WOLFSSL_WC_LMS_SMALL */ + +/* Calculate the leaf node hash. + * + * Assumes buffer already contains : I + * + * Appendix C. + * ... + * temp = H(I || u32str(r)|| u16str(D_LEAF) || OTS_PUB_HASH[i]) + * ... + * Section 5.3. LMS Public Key + * ... where we denote the public + * key final hash value (namely, the K value computed in Algorithm 1) + * associated with the i-th LM-OTS private key as OTS_PUB_HASH[i], ... + * Algorithm 1: Generating a One-Time Signature Public Key From a + * Private Key + * ... + * K = H(I || u32str(q) || u16str(D_PBLC) || y[0] || ... || y[p-1]) + * ... + * Therefore: + * OTS_PUB_HASH[i] = H(I || u32str(i) || u16str(D_PBLC) || + * y[0] || ... || y[p-1]) + * + * @param [in, out] state LMS state. + * @param [in] seed Private seed to generate x. + * @param [in] i Index of leaf. + * @param [in] r Leaf hash index. + * @param [out] leaf Leaf node hash. + */ +static int wc_lms_leaf_hash(LmsState* state, const byte* seed, word32 i, + word32 r, byte* leaf) +{ + int ret; + byte* buffer = state->buffer; + byte* rp = buffer + LMS_I_LEN; + byte* dp = rp + LMS_R_LEN; + byte* ots_pub_hash = dp + LMS_D_LEN; + + /* I || u32str(i) || ... */ + c32toa(i, rp); + /* OTS_PUB_HASH[i] = H(I || u32str(i) || u16str(D_PBLC) || + * y[0] || ... || y[p-1]) + */ + ret = wc_lmots_make_public_hash(state, seed, ots_pub_hash); + if (ret == 0) { + /* I || u32str(r) || ... || OTS_PUB_HASH[i] */ + c32toa(r, rp); + /* I || u32str(r) || u16str(D_LEAF) || OTS_PUB_HASH[i] */ + c16toa(LMS_D_LEAF, dp); + /* temp = H(I || u32str(r) || u16str(D_LEAF) || OTS_PUB_HASH[i]) */ + #ifndef WC_LMS_FULL_HASH + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_54(buffer); + ret = wc_lms_hash_block(&state->hash, buffer, leaf); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_SEED_HASH_LEN, leaf); + #endif /* !WC_LMS_FULL_HASH */ + } + + return ret; +} + +/* Calculate interior node hash. + * + * Appendix C. n Iterative Algorithm for Computing an LMS Public Key + * Generating an LMS Public Key from an LMS Private Key + * ... + * left_side = pop(data stack); + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) + * ... + * Popping the stack is done in the caller. + * + * @param [in, out] state LMS state. + * @param [in] sp Stack pointer to left nodes. + * @param [in] r Node hash index. + * @param [out] node Interior node hash. + */ +static int wc_lms_interior_hash(LmsState* state, byte* sp, word32 r, + byte* node) +{ + byte* buffer = state->buffer; + byte* rp = buffer + LMS_I_LEN; + byte* left = rp + LMS_R_LEN + LMS_D_LEN; + + /* I || u32str(r) || u16str(D_INTR) || ... || temp */ + c32toa(r, rp); + /* left_side = pop(data stack) + * I || u32str(r) || u16str(D_INTR) || left_side || temp */ + XMEMCPY(left, sp, LMS_MAX_NODE_LEN); + /* temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) */ + return wc_lms_hash(&state->hash, buffer, LMS_NODE_HASH_LEN, node); +} + +#ifdef WOLFSSL_WC_LMS_SMALL +/* Computes hash of the Merkle tree and gets the authentication path for q. + * + * Appendix C: An Iterative Algorithm for Computing an LMS Public Key + * for ( i = 0; i < 2^h; i = i + 1 ) { + * r = i + num_lmots_keys; + * temp = H(I || u32str(r) || u16str(D_LEAF) || OTS_PUB_HASH[i]) + * j = i; + * while (j % 2 == 1) { + * r = (r - 1)/2; + * j = (j-1) / 2; + * left_side = pop(data stack); + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) + * } + * push temp onto the data stack + * } + * public_key = pop(data stack) + * + * @param [in, out] state LMS state. + * @param [in] id Unique tree identifier, I. + * @param [in] seed Private seed to generate x. + * @param [in] max Count of leaf nodes to calculate. Must be greater + * than q. Must be a power of 2. + * @param [in] q Index for authentication path. + * @param [out] auth_path Authentication path for index. + * @param [out] pub LMS public key. + * @param [out] stack_d Where to store stack data. + * @return 0 on success. + */ +static int wc_lms_treehash(LmsState* state, const byte* id, const byte* seed, + word32 q, byte* auth_path, byte* pub) +{ + int ret = 0; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + byte* rp = buffer + LMS_I_LEN; + byte* dp = rp + LMS_R_LEN; + byte* left = dp + LMS_D_LEN; + byte* temp = left + LMS_MAX_NODE_LEN; +#ifdef WOLFSSL_SMALL_STACK + byte* stack = NULL; +#else + byte stack[(LMS_MAX_HEIGHT + 1) * LMS_MAX_NODE_LEN]; +#endif /* WOLFSSL_SMALL_STACK */ + byte* sp; + word32 i; + + /* I || ... */ + XMEMCPY(buffer, id, LMS_I_LEN); + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate stack of left side hashes. */ + stack = XMALLOC((params->height + 1) * LMS_MAX_NODE_LEN, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (stack == NULL) { + ret = MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK */ + sp = stack; + + /* Compute all nodes requested. */ + for (i = 0; (ret == 0) && (i < ((word32)1 << params->height)); i++) { + word32 j = i; + word16 h = 0; + /* r = i + num_lmots_keys */ + word32 r = i + ((word32)1 << (params->height)); + + /* Calculate leaf node hash. */ + ret = wc_lms_leaf_hash(state, seed, i, r, temp); + + /* Store the node if on the authentication path. */ + if ((ret == 0) && (auth_path != NULL) && ((q ^ 0x1) == i)) { + XMEMCPY(auth_path, temp, LMS_MAX_NODE_LEN); + } + + /* I || ... || u16str(D_INTR) || ... || temp */ + c16toa(LMS_D_INTR, dp); + /* Calculate parent node is we have both left and right. */ + while ((ret == 0) && ((j & 0x1) == 1)) { + /* Get parent node index. r and j are odd. */ + r >>= 1; + j >>= 1; + h++; + + /* Calculate interior node hash. + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) + */ + sp -= LMS_MAX_NODE_LEN; + ret = wc_lms_interior_hash(state, sp, r, temp); + + /* Copy out node to authentication path if on path. */ + if ((ret == 0) && (auth_path != NULL) && ((q >> h) ^ 0x1) == j) { + XMEMCPY(auth_path + h * LMS_MAX_NODE_LEN, temp, + LMS_MAX_NODE_LEN); + } + } + /* Push temp onto the data stack. */ + XMEMCPY(sp, temp, LMS_MAX_NODE_LEN); + sp += LMS_MAX_NODE_LEN; + } + + if ((ret == 0) && (pub != NULL)) { + /* Public key, root node, is top of data stack. */ + XMEMCPY(pub, stack, LMS_MAX_NODE_LEN); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(stack, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_SMALL_STACK */ + return ret; +} + +/* Compute the LMS public key - root node of tree. + * + * @param [in, out] state LMS state. + * @param [in] id Unique tree identifier, I. + * @param [in] seed Private seed to generate x. + * @param [out] pub LMS public key. + * @return 0 on success. + */ +static int wc_lms_make_public_key(LmsState* state, const byte* id, + const byte* seed, byte* pub) +{ + return wc_lms_treehash(state, id, seed, 0, NULL, pub); +} + +/* Calculate the authentication path. + * + * @param [in, out] state LMS state. + * @param [in] id Public random: I. + * @param [in] seed Private random: SEED. + * @param [in] q Index of leaf. + * @param [out] sig Signature buffer to place authentication path into. + * @param [out] root Root node of tree. + * @return 0 on success. + */ +static int wc_lms_auth_path(LmsState* state, const byte* id, const byte* seed, + word32 q, byte* sig, byte* root) +{ + return wc_lms_treehash(state, id, seed, q, sig, root); +} +#else +/* Computes hash of the Merkle tree and gets the authentication path for q. + * + * Appendix C: An Iterative Algorithm for Computing an LMS Public Key + * for ( i = 0; i < 2^h; i = i + 1 ) { + * r = i + num_lmots_keys; + * temp = H(I || u32str(r) || u16str(D_LEAF) || OTS_PUB_HASH[i]) + * j = i; + * while (j % 2 == 1) { + * r = (r - 1)/2; + * j = (j-1) / 2; + * left_side = pop(data stack); + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) + * } + * push temp onto the data stack + * } + * public_key = pop(data stack) + * + * @param [in, out] state LMS state. + * @param [in, out] privState LMS state of the private key. + * @param [in] id Unique tree identifier, I. + * @param [in] seed Private seed to generate x. + * @param [in] q Index for authentication path. + * @return 0 on success. + */ +static int wc_lms_treehash_init(LmsState* state, LmsPrivState* privState, + const byte* id, const byte* seed, word32 q) +{ + int ret = 0; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + byte* auth_path = privState->auth_path; + byte* root = privState->root; + HssLeafCache* leaf = &privState->leaf; + byte* rp = buffer + LMS_I_LEN; + byte* dp = rp + LMS_R_LEN; + byte* left = dp + LMS_D_LEN; + byte* temp = left + LMS_MAX_NODE_LEN; +#ifdef WOLFSSL_SMALL_STACK + byte* stack = NULL; +#else + byte stack[(LMS_MAX_HEIGHT + 1) * LMS_MAX_NODE_LEN]; +#endif /* WOLFSSL_SMALL_STACK */ + word32 spi = 0; + word32 i; + word32 max_h = (word32)1 << params->height; + word32 max_cb = (word32)1 << params->cacheBits; + + privState->stack.offset = 0; + /* Reset the cached stack. */ + leaf->offset = 0; + leaf->idx = q; + if ((q + max_cb) > max_h) { + leaf->idx = max_h - max_cb; + } + + /* I || ... */ + XMEMCPY(buffer, id, LMS_I_LEN); + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate stack of left side hashes. */ + stack = XMALLOC((params->height + 1) * LMS_MAX_NODE_LEN, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (stack == NULL) { + ret = MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK */ + + /* Compute all nodes requested. */ + for (i = 0; (ret == 0) && (i < max_h); i++) { + word32 j = i; + word16 h = 0; + /* r = i + num_lmots_keys */ + word32 r = i + max_h; + + /* Calculate leaf node hash. */ + ret = wc_lms_leaf_hash(state, seed, i, r, temp); + + /* Cache leaf node if in range. */ + if ((ret == 0) && (i >= leaf->idx) && (i < leaf->idx + max_cb)) { + XMEMCPY(leaf->cache + i * LMS_MAX_NODE_LEN, temp, LMS_MAX_NODE_LEN); + } + + /* Store the node if on the authentication path. */ + if ((ret == 0) && (auth_path != NULL) && ((q ^ 0x1) == i)) { + XMEMCPY(auth_path, temp, LMS_MAX_NODE_LEN); + } + + /* I || ... || u16str(D_INTR) || ... || temp */ + c16toa(LMS_D_INTR, dp); + /* Calculate parent node is we have both left and right. */ + while ((ret == 0) && ((j & 0x1) == 1)) { + /* Get parent node index. r and j are odd. */ + r >>= 1; + j >>= 1; + h++; + + /* Calculate interior node hash. + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) + */ + spi -= LMS_MAX_NODE_LEN; + ret = wc_lms_interior_hash(state, stack + spi, r, temp); -#ifdef WOLFSSL_HAVE_LMS - #error "Contact wolfSSL to get the implementation of this file" + /* Copy out top root nodes. */ + if ((h > params->height - params->rootLevels) && + ((i >> (h-1)) != ((i + 1) >> (h - 1)))) { + int off = (1 << (params->height - h)) + (i >> h) - 1; + XMEMCPY(root + off * LMS_MAX_NODE_LEN, temp, LMS_MAX_NODE_LEN); + } + + /* Copy out node to authentication path if on path. */ + if ((ret == 0) && (auth_path != NULL) && ((q >> h) ^ 0x1) == j) { + XMEMCPY(auth_path + h * LMS_MAX_NODE_LEN, temp, + LMS_MAX_NODE_LEN); + } + } + /* Push temp onto the data stack. */ + XMEMCPY(stack + spi, temp, LMS_MAX_NODE_LEN); + spi += LMS_MAX_NODE_LEN; + + if (i == q - 1) { + XMEMCPY(privState->stack.stack, stack, spi); + privState->stack.offset = spi; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(stack, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_SMALL_STACK */ + return ret; +} + +/* Computes hash of the Merkle tree and gets the authentication path for q. + * + * Appendix C: An Iterative Algorithm for Computing an LMS Public Key + * for ( i = 0; i < 2^h; i = i + 1 ) { + * r = i + num_lmots_keys; + * temp = H(I || u32str(r) || u16str(D_LEAF) || OTS_PUB_HASH[i]) + * j = i; + * while (j % 2 == 1) { + * r = (r - 1)/2; + * j = (j-1) / 2; + * left_side = pop(data stack); + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || temp) + * } + * push temp onto the data stack + * } + * public_key = pop(data stack) + * + * @param [in, out] state LMS state. + * @param [in, out] privState LMS state of the private key. + * @param [in] id Unique tree identifier, I. + * @param [in] seed Private seed to generate x. + * @param [in] min_idx Minimum leaf index to process. + * @param [in] max_idx Maximum leaf index to process. + * @param [in] q Index for authentication path. + * @param [in] useRoot Whether to use nodes from root cache. + * @return 0 on success. + */ +static int wc_lms_treehash_update(LmsState* state, LmsPrivState* privState, + const byte* id, const byte* seed, word32 min_idx, word32 max_idx, word32 q, + int useRoot) +{ + int ret = 0; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + byte* auth_path = privState->auth_path; + LmsStack* stackCache = &privState->stack; + HssLeafCache* leaf = &privState->leaf; + byte* rp = buffer + LMS_I_LEN; + byte* dp = rp + LMS_R_LEN; + byte* left = dp + LMS_D_LEN; + byte* temp = left + LMS_MAX_NODE_LEN; +#ifdef WOLFSSL_SMALL_STACK + byte* stack = NULL; +#else + byte stack[(LMS_MAX_HEIGHT + 1) * LMS_MAX_NODE_LEN]; +#endif /* WOLFSSL_SMALL_STACK */ + byte* sp; + word32 max_cb = (word32)1 << params->cacheBits; + word32 i; + + /* I || ... */ + XMEMCPY(buffer, id, LMS_I_LEN); + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate stack of left side hashes. */ + stack = XMALLOC((params->height + 1) * LMS_MAX_NODE_LEN, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (stack == NULL) { + ret = MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK */ + + /* Public key, root node, is top of data stack. */ + XMEMCPY(stack, stackCache->stack, params->height * LMS_MAX_NODE_LEN); + sp = stack + stackCache->offset; + + /* Compute all nodes requested. */ + for (i = min_idx; (ret == 0) && (i <= max_idx); i++) { + word32 j = i; + word16 h = 0; + /* r = i + num_lmots_keys */ + word32 r = i + ((word32)1 << (params->height)); + + if ((i >= leaf->idx) && (i < leaf->idx + max_cb)) { + /* Calculate offset of node in cache. */ + word32 off = ((i - (leaf->idx + max_cb) + leaf->offset) % max_cb) * + LMS_MAX_NODE_LEN; + /* Copy cached node into working buffer. */ + XMEMCPY(temp, leaf->cache + off, LMS_MAX_NODE_LEN); + /* I || u32str(i) || ... */ + c32toa(i, rp); + } + else { + /* Calculate leaf node hash. */ + ret = wc_lms_leaf_hash(state, seed, i, r, temp); + + /* Check if this is at the end of the cache and not beyond q plus + * the number of leaf nodes. */ + if ((i == leaf->idx + max_cb) && (i < (q + max_cb))) { + /* Copy working node into cache over old first node. */ + XMEMCPY(leaf->cache + leaf->offset * LMS_MAX_NODE_LEN, temp, + LMS_MAX_NODE_LEN); + /* Increase start index as first node replaced. */ + leaf->idx++; + /* Update offset of first leaf node. */ + leaf->offset = (leaf->offset + 1) & (max_cb - 1); + } + } + + /* Store the node if on the authentication path. */ + if ((ret == 0) && ((q ^ 0x1) == i)) { + XMEMCPY(auth_path, temp, LMS_MAX_NODE_LEN); + } + + /* I || ... || u16str(D_INTR) || ... || temp */ + c16toa(LMS_D_INTR, dp); + /* Calculate parent node if we have both left and right. */ + while ((ret == 0) && ((j & 0x1) == 1)) { + /* Get parent node index. r and j are odd. */ + r >>= 1; + j >>= 1; + h++; + + sp -= LMS_MAX_NODE_LEN; + if (useRoot && (h > params->height - params->rootLevels) && + (h <= params->height)) { + /* Calculate offset of cached root node. */ + word32 off = ((word32)1U << (params->height - h)) + + (i >> h) - 1; + XMEMCPY(temp, privState->root + (off * LMS_MAX_NODE_LEN), + LMS_MAX_NODE_LEN); + } + else { + /* Calculate interior node hash. + * temp = H(I || u32str(r) || u16str(D_INTR) || left_side || + * temp) + */ + ret = wc_lms_interior_hash(state, sp, r, temp); + } + + /* Copy out top root nodes. */ + if ((ret == 0) && (q == 0) && (!useRoot) && + (h > params->height - params->rootLevels) && + ((i >> (h-1)) != ((i + 1) >> (h - 1)))) { + int off = (1 << (params->height - h)) + (i >> h) - 1; + XMEMCPY(privState->root + off * LMS_MAX_NODE_LEN, temp, + LMS_MAX_NODE_LEN); + } + + /* Copy out node to authentication path if on path. */ + if ((ret == 0) && (((q >> h) ^ 0x1) == j)) { + XMEMCPY(auth_path + h * LMS_MAX_NODE_LEN, temp, + LMS_MAX_NODE_LEN); + } + } + if (ret == 0) { + /* Push temp onto the data stack. */ + XMEMCPY(sp, temp, LMS_MAX_NODE_LEN); + sp += LMS_MAX_NODE_LEN; + + /* Save stack after updating first node. */ + if (i == min_idx) { + /* Copy stack back. */ + stackCache->offset = (word32)((size_t)sp - (size_t)stack); + XMEMCPY(stackCache->stack, stack, stackCache->offset); + } + } + } + + if (!useRoot) { + /* Copy stack back. */ + XMEMCPY(stackCache->stack, stack, params->height * LMS_MAX_NODE_LEN); + stackCache->offset = (word32)((size_t)sp - (size_t)stack); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(stack, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif /* WOLFSSL_SMALL_STACK */ + return ret; +} +#endif /* WOLFSSL_WC_LMS_SMALL */ + +/* Sign message using LMS. + * + * Appendix D. Method for Deriving Authentication Path for a Signature. + * Generating an LMS Signature + * ... + * 3. Create the LM-OTS signature for the message: + * ots_signature = lmots_sign(message, LMS_PRIV[q]) + * 4. Compute the array path as follows: + * ... + * 5. S = u32str(q) || ots_signature || u32str(type) || + * path[0] || path[1] || ... || path[h-1] + * ... + * path[] added by caller as it can come from cache. + * + * @param [in, out] state LMS state. + * @param [in] priv LMS private key. + * @param [in] msg Message/public key to sign. + * @param [in] msgSz Length of message in bytes. + * @param [out] sig LMS signature. + * @return 0 on success. + */ +static int wc_lms_sign(LmsState* state, const byte* priv, const byte* msg, + word32 msgSz, byte* sig) +{ + int ret; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + byte* s = sig; + const byte* priv_q = priv; + const byte* priv_seed = priv_q + LMS_Q_LEN; + const byte* priv_i = priv_seed + LMS_SEED_LEN; + + /* Setup for hashing: I || Q */ + XMEMCPY(buffer, priv_i, LMS_I_LEN); + XMEMCPY(buffer + LMS_I_LEN, priv_q, LMS_Q_LEN); + + /* Copy q from private key. + * S = u32str(q) || ... */ + XMEMCPY(s, priv_q, LMS_Q_LEN); + s += LMS_Q_LEN; + + /* ots_signature = sig = u32str(type) || ... */ + c32toa(state->params->lmOtsType, s); + s += LMS_TYPE_LEN; + /* Sign this level. + * S = u32str(q) || ots_signature || ... */ + ret = wc_lmots_sign(state, priv_seed, msg, msgSz, s); + if (ret == 0) { + /* Skip over ots_signature. */ + s += LMS_MAX_NODE_LEN + params->p * LMS_MAX_NODE_LEN; + /* S = u32str(q) || ots_signature || u32str(type) || ... */ + c32toa(params->lmsType, s); + } + + return ret; +} + +#if !defined(WOLFSSL_WC_LMS_SMALL) && !defined(WOLFSSL_LMS_NO_SIG_CACHE) +/* Copy in the cached signature data. + * + * @param [in] params LMS parameters. + * @param [in] y y cache. + * @param [in] priv Private key data. + * @param [out] sig Signature data. + */ +static void wc_lms_sig_copy(const LmsParams* params, const byte* y, + const byte* priv, byte* sig) +{ + /* Put in q. */ + XMEMCPY(sig, priv, LMS_Q_LEN); + sig += LMS_Q_LEN; + /* S = u32str(q) || ... */ + c32toa(params->lmOtsType, sig); + sig += LMS_TYPE_LEN; + /* S = u32str(q) || ots_signature || ... */ + XMEMCPY(sig, y, LMS_MAX_NODE_LEN + params->p * LMS_MAX_NODE_LEN); + sig += LMS_MAX_NODE_LEN + params->p * LMS_MAX_NODE_LEN; + /* S = u32str(q) || ots_signature || u32str(type) || ... */ + c32toa(params->lmsType, sig); +} +#endif /* !WOLFSSL_WC_LMS_SMALL && !WOLFSSL_LMS_NO_SIG_CACHE */ +#endif /* !WOLFSSL_LMS_VERIFY_ONLY */ + +/* Compute the root node of the LMS tree. + * + * Algorithm 6a: Computing an LMS Public Key Candidate from a Signature, + * Message, Identifier, and Algorithm Typecodes + * ... + * 4. Compute the candidate LMS root value Tc as follows: + * node_num = 2^h + q + * tmp = H(I || u32str(node_num) || u16str(D_LEAF) || Kc) + * i = 0 + * while (node_num > 1) { + * if (node_num is odd): + * tmp = H(I||u32str(node_num/2)||u16str(D_INTR)||path[i]||tmp) + * else: + * tmp = H(I||u32str(node_num/2)||u16str(D_INTR)||tmp||path[i]) + * node_num = node_num/2 + * i = i + 1 + * } + * Tc = tmp + * 5. Return Tc. + * + * @param [in, out] state LMS state. + * @param [in] q Index of node. + * @param [in] kc K candidate. + * @param [in] path Authentication path from signature. + * @param [out] tc T candidate. + * @return 0 on success. + */ +static int wc_lms_compute_root(LmsState* state, word32 q, const byte* kc, + const byte* path, byte* tc) +{ + int ret; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + byte* rp = buffer + LMS_I_LEN; + byte* ip = rp + LMS_Q_LEN; + byte* node = ip + LMS_P_LEN; + byte* b[2][2] = { { node, node + LMS_MAX_NODE_LEN }, + { node + LMS_MAX_NODE_LEN, node } }; + /* node_num = 2^h + q */ + word32 r = (1 << params->height) + q; + + /* tmp = H(I || u32str(node_num) || u16str(D_LEAF) || Kc) */ + c32toa(r, rp); + c16toa(LMS_D_LEAF, ip); + XMEMCPY(node, kc, LMS_MAX_NODE_LEN); + /* Put tmp into offset required for first iteration. */ +#ifndef WC_LMS_FULL_HASH + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_54(buffer); + ret = wc_lms_hash_block(&state->hash, buffer, b[r & 1][0]); +#else + ret = wc_lms_hash(&state->hash, buffer, LMS_SEED_HASH_LEN, b[r & 1][0]); +#endif /* !WC_LMS_FULL_HASH */ + + if (ret == 0) { + int i; + + /* I||...||u16str(D_INT)||... */ + c16toa(LMS_D_INTR, ip); + + /* Do all but last height. */ + for (i = 0; (ret == 0) && (i < params->height - 1); i++) { + /* Put path into offset required. */ + XMEMCPY(b[r & 1][1], path, LMS_MAX_NODE_LEN); + path += LMS_MAX_NODE_LEN; + + /* node_num = node_num / 2 */ + r >>= 1; + /* H(...||u32str(node_num/2)||..) */ + c32toa(r, rp); + /* tmp = H(I||u32str(node_num/2)||u16str(D_INTR)||path[i]||tmp) or + * tmp = H(I||u32str(node_num/2)||u16str(D_INTR)||tmp||path[i]) + * Put tmp result into offset required for next iteration. */ + ret = wc_lms_hash(&state->hash, buffer, LMS_NODE_HASH_LEN, + b[r & 1][0]); + } + if (ret == 0) { + /* Last height. */ + /* Put path into offset required. */ + XMEMCPY(b[r & 1][1], path, LMS_MAX_NODE_LEN); + /* node_num = node_num / 2 */ + r >>= 1; + /* H(...||u32str(node_num/2)||..) */ + c32toa(r, rp); + /* tmp = H(I||u32str(node_num/2)||u16str(D_INTR)||path[i]||tmp) or + * tmp = H(I||u32str(node_num/2)||u16str(D_INTR)||tmp||path[i]) + * Put tmp result into Tc.*/ + ret = wc_lms_hash(&state->hash, buffer, LMS_NODE_HASH_LEN, tc); + } + } + + return ret; +} + +/* LMS verify message using public key and signature. + * + * Algorithm 6a: Computing an LMS Public Key Candidate from a Signature, + * Message, Identifier, and Algorithm Typecodes + * ... + * 2. Parse sigtype, q, lmots_signature, and path from the signature + * as follows: + * a. q = strTou32(first 4 bytes of signature) + * ... + * e. lmots_signature = bytes 4 through 7 + n * (p + 1) + * of signature + * ... + * j. Set path as follows: + * path[0] = next m bytes of signature + * path[1] = next m bytes of signature + * ... + * path[h-1] = next m bytes of signature + * 3. Kc = candidate public key computed by applying Algorithm 4b + * to the signature lmots_signature, the message, and the + * identifiers I, q + * 4. Compute the candidate LMS root value Tc as follows: + * ... + * 5. Return Tc + * Algorithm 6: LMS Signature Verification + * ... + * 3. Compute the LMS Public Key Candidate Tc from the signature, + * message, identifier, pubtype, and ots_typecode, using + * Algorithm 6a. + * 4. If Tc is equal to T[1], return VALID; otherwise, return INVALID. + * + * @param [in, out] state LMS state. + * @param [in] pub LMS public key. + * @param [in] msg Message/public key to verify. + * @param [in] msgSz Length of message in bytes. + * @param [in] sig LMS signature. + */ +static int wc_lms_verify(LmsState* state, const byte* pub, const byte* msg, + word32 msgSz, const byte* sig) +{ + int ret; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + const byte* pub_i = pub + LMS_TYPE_LEN + LMS_TYPE_LEN; + const byte* pub_k = pub_i + LMS_I_LEN; + const byte* sig_q = sig; + byte tc[LMS_MAX_NODE_LEN]; + byte* kc = tc; + + /* Algorithm 6. Step 3. */ + /* Check the public key LMS type matches parameters. */ + ret = wc_lmots_public_key_check(params, pub); + if (ret == 0) { + /* Algorithm 6a. Step 2.e. */ + const byte* sig_lmots = sig + LMS_Q_LEN; + + /* Setup buffer with I || Q. */ + XMEMCPY(buffer, pub_i, LMS_I_LEN); + XMEMCPY(buffer + LMS_I_LEN, sig_q, LMS_Q_LEN); + + /* Algorithm 6a. Step 3. */ + ret = wc_lmots_calc_kc(state, pub + LMS_TYPE_LEN, msg, msgSz, + sig_lmots, kc); + } + if (ret == 0) { + /* Algorithm 6a. Step 2.j. */ + const byte* sig_path = sig + LMS_Q_LEN + LMS_TYPE_LEN + + LMS_MAX_NODE_LEN + params->p * LMS_MAX_NODE_LEN + LMS_TYPE_LEN; + word32 q; + + /* Algorithm 6a. Step 2.a. */ + ato32(sig_q, &q); + + /* Algorithm 6a. Steps 4-5. */ + ret = wc_lms_compute_root(state, q, kc, sig_path, tc); + } + /* Algorithm 6. Step 4. */ + if ((ret == 0) && (XMEMCMP(pub_k, tc, LMS_MAX_NODE_LEN) != 0)) { + ret = SIG_VERIFY_E; + } + + return ret; +} + +/*************************************** + * HSS APIs + **************************************/ + +#ifndef WOLFSSL_LMS_VERIFY_ONLY +/* Derive the seed and i for child. + * + * @param [in, out] state LMS state. + * @param [in] id Parent's I. + * @param [in] seed Parent's SEED. + * @param [in] q Parent's q. + * @param [out] seed_i Derived SEED and I. + * @return 0 on success. + */ +static int wc_hss_derive_seed_i(LmsState* state, const byte* id, + const byte* seed, const byte* q, byte* seed_i) +{ + int ret = 0; + byte buffer[WC_SHA256_BLOCK_SIZE]; + byte* idp = buffer; + byte* qp = idp + LMS_I_LEN; + byte* ip = qp + LMS_Q_LEN; + byte* jp = ip + LMS_P_LEN; + byte* tmp = jp + LMS_W_LEN; + + /* parent's I || ... */ + XMEMCPY(idp, id, LMS_I_LEN); + /* parent's I || q || ... */ + XMEMCPY(qp, q, LMS_Q_LEN); + /* parent's I || q || D_CHILD_SEED || ... */ + c16toa(LMS_D_CHILD_SEED, ip); + /* parent's I || q || D_CHILD_SEED || D_FIXED || ... */ + *jp = LMS_D_FIXED; + /* parent's I || q || D_CHILD_SEED || D_FIXED || parent's SEED */ + XMEMCPY(tmp, seed, LMS_SEED_LEN); + /* SEED = H(parent's I || q || D_CHILD_SEED || D_FIXED || parent's SEED) */ +#ifndef WC_LMS_FULL_HASH + /* Put in padding for final block. */ + LMS_SHA256_SET_LEN_55(buffer); + ret = wc_lms_hash_block(&state->hash, buffer, seed_i); +#else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, seed_i); +#endif /* !WC_LMS_FULL_HASH */ + + if (ret == 0) { + seed_i += LMS_SEED_LEN; + /* parent's I || q || D_CHILD_I || D_FIXED || parent's SEED */ + c16toa(LMS_D_CHILD_I, ip); + /* I = H(parent's I || q || D_CHILD_I || D_FIXED || parent's SEED) */ + #ifndef WC_LMS_FULL_HASH + ret = wc_lms_hash_block(&state->hash, buffer, tmp); + #else + ret = wc_lms_hash(&state->hash, buffer, LMS_HASH_BUFFER_LEN, tmp); + #endif /* !WC_LMS_FULL_HASH */ + /* Copy part of hash as new I into private key. */ + XMEMCPY(seed_i, tmp, LMS_I_LEN); + } + + return ret; +} + +/* Get q, index, of leaf at the specified level. */ +#define LMS_Q_AT_LEVEL(q, ls, l, h) \ + (w64GetLow32(w64ShiftRight((q), (((ls) - 1 - (l)) * (h)))) & \ + (((word32)1 << (h)) - 1)) + +/* Expand the seed and I for further levels and set q for each level. + * + * @param [in, out] state LMS state. + * @param [in, out] priv Private key for use in signing. + * @param [in] priv_raw Private key read. + * @param [in] inc Whether this is an incremental expansion. + * @return 0 on success. + */ +static int wc_hss_expand_private_key(LmsState* state, byte* priv, + const byte* priv_raw, int inc) +{ + const LmsParams* params = state->params; + int ret = 0; + w64wrapper q; + w64wrapper qm1; + word32 q32; + byte* priv_q; + byte* priv_seed_i; + int i; + + /* Get the 64-bit q value from the raw private key. */ + ato64(priv_raw, &q); + /* Step over q and parameter set. */ + priv_raw += HSS_Q_LEN + HSS_PRIV_KEY_PARAM_SET_LEN; + + /* Get q of highest level. */ + q32 = LMS_Q_AT_LEVEL(q, params->levels, 0, params->height); + /* Set q of highest tree. */ + c32toa(q32, priv); + + /* Incremental expansion needs q-1. */ + if (inc) { + /* Calculate q-1 for comparison. */ + qm1 = q; + w64Decrement(&qm1); + } + else { + /* Copy out SEED and I into private key. */ + XMEMCPY(priv + LMS_Q_LEN, priv_raw, LMS_SEED_I_LEN); + } + + /* Compute SEED and I for rest of levels. */ + for (i = 1; (ret == 0) && (i < params->levels); i++) { + /* Don't skip calculating SEED and I. */ + int skip = 0; + + /* Incremental means q, SEED and I already present if q unchanged. */ + if (inc) { + /* Calculate previous levels q for previous 64-bit q value. */ + word32 qm1_32 = LMS_Q_AT_LEVEL(qm1, params->levels, i - 1, + params->height); + /* Same q at previous level means no need to re-compute. */ + if (q32 == qm1_32) { + /* Do skip calculating SEED and I. */ + skip = 1; + } + } + + /* Get pointers into private q to write q and seed + I. */ + priv_q = priv; + priv += LMS_Q_LEN; + priv_seed_i = priv; + priv += LMS_SEED_I_LEN; + + /* Get q for level from 64-bit composite. */ + q32 = w64GetLow32(w64ShiftRight(q, (params->levels - 1 - i) * + params->height)) & (((word32)1 << params->height) - 1); + /* Set q of tree. */ + c32toa(q32, priv); + + if (!skip) { + /* Derive SEED and I into private key. */ + ret = wc_hss_derive_seed_i(state, priv_seed_i + LMS_SEED_LEN, + priv_seed_i, priv_q, priv + LMS_Q_LEN); + } + } + + return ret; +} + +#ifndef WOLFSSL_WC_LMS_SMALL +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING +/* Initialize the next subtree. + * + * @param [in] state LMS state. + * @param [in] privState LMS private state. + * @param [in] curr Current private key. + * @param [in] priv Next private key. + * @param [in] q q for this level. + * @return 0 on success. + */ +static int wc_lms_next_subtree_init(LmsState* state, LmsPrivState* privState, + byte* curr, byte* priv, word32 q) +{ + int ret; + const LmsParams* params = state->params; + byte* priv_q; + byte* priv_seed; + byte* priv_i; + word32 pq; + + priv_q = priv; + priv += LMS_Q_LEN; + priv_seed = curr + LMS_Q_LEN; + priv += LMS_SEED_LEN; + priv_i = curr + LMS_Q_LEN + LMS_SEED_LEN; + priv += LMS_I_LEN; + + ato32(curr, &pq); + pq = (pq + 1) & ((1 << params->height) - 1); + c32toa(pq, priv_q); + + privState->stack.offset = 0; + privState->leaf.idx = (word32)-(1 << params->cacheBits); + privState->leaf.offset = 0; + + /* Derive SEED and I for next tree. */ + ret = wc_hss_derive_seed_i(state, priv_i, priv_seed, priv_q, + priv + LMS_Q_LEN); + if (ret == 0) { + /* Update treehash for first leaf. */ + ret = wc_lms_treehash_update(state, privState, + priv + LMS_Q_LEN + LMS_SEED_LEN, priv + LMS_Q_LEN, 0, q, 0, 0); + } + + return ret; +} + +/* Increment count on next subtree. + * + * @param [in] state LMS state. + * @param [in] priv_key HSS private key. + * @param [in] q64 64-bit q for all levels. + * @return 0 on success. + */ +static int wc_hss_next_subtree_inc(LmsState* state, HssPrivKey* priv_key, + w64wrapper q64) +{ + int ret = 0; + const LmsParams* params = state->params; + byte* curr = priv_key->priv; + byte* priv = priv_key->next_priv; + int i; + w64wrapper p64 = q64; + byte tmp_priv[LMS_PRIV_LEN]; + int use_tmp = 0; + int lastQMax = 0; + w64wrapper p64_hi; + w64wrapper q64_hi; + + /* Get previous index. */ + w64Decrement(&p64); + /* Get index of previous and current parent. */ + p64_hi = w64ShiftRight(p64, (params->levels - 1) * params->height); + q64_hi = w64ShiftRight(q64, (params->levels - 1) * params->height); + for (i = 1; (ret == 0) && (i < params->levels); i++) { + word32 qc; + w64wrapper cp64_hi; + w64wrapper cq64_hi; + + /* Get index of previous and current child. */ + cp64_hi = w64ShiftRight(p64, (params->levels - i - 1) * params->height); + cq64_hi = w64ShiftRight(q64, (params->levels - i - 1) * params->height); + /* Get the q for the child. */ + ato32(curr + LMS_PRIV_LEN, &qc); + + /* Compare index of parent node with previous value. */ + if (w64LT(p64_hi, q64_hi)) { + wc_lms_priv_state_copy(params, &priv_key->state[i], + &priv_key->next_state[i-1]); + ret = wc_lms_next_subtree_init(state, &priv_key->next_state[i - 1], + use_tmp ? tmp_priv : curr, priv, 0); + use_tmp = 0; + } + /* Check whether the child is in a new subtree. */ + else if ((qc == ((word32)1 << params->height) - 1) && + w64LT(cp64_hi, cq64_hi)) { + XMEMSET(tmp_priv, 0, LMS_Q_LEN); + /* Check whether the node at the previous level is also in a new + * subtree. */ + if (lastQMax) { + /* Calculate new SEED and I based on new subtree. */ + ret = wc_hss_derive_seed_i(state, + priv + LMS_Q_LEN + LMS_SEED_LEN, priv + LMS_Q_LEN, tmp_priv, + tmp_priv + LMS_Q_LEN); + } + else { + /* Calculate new SEED and I based on parent. */ + ret = wc_hss_derive_seed_i(state, + curr + LMS_Q_LEN + LMS_SEED_LEN, curr + LMS_Q_LEN, priv, + tmp_priv + LMS_Q_LEN); + } + /* Values not stored so note that they are in temporary. */ + use_tmp = 1; + + /* Set the the q. */ + XMEMCPY(tmp_priv, curr + LMS_PRIV_LEN, LMS_Q_LEN); + } + + lastQMax = (qc == ((word32)1 << params->height) - 1); + curr += LMS_PRIV_LEN; + priv += LMS_PRIV_LEN; + p64_hi = cp64_hi; + q64_hi = cq64_hi; + } + + return ret; +} + +/* Initialize the next subtree for each level bar the highest. + * + * @param [in, out] state LMS state. + * @param [out] priv_key Private key data. + * @return 0 on success. + */ +static int wc_hss_next_subtrees_init(LmsState* state, HssPrivKey* priv_key) +{ + int ret = 0; + const LmsParams* params = state->params; + byte* curr = priv_key->priv; + byte* priv = priv_key->next_priv; + int i; + + XMEMCPY(priv, curr, LMS_PRIV_LEN); + wc_lms_idx_inc(priv, LMS_Q_LEN); + + for (i = 1; (ret == 0) && (i < params->levels); i++) { + word32 q; + + ato32(curr + LMS_PRIV_LEN, &q); + ret = wc_lms_next_subtree_init(state, &priv_key->next_state[i - 1], + curr, priv, q); + + curr += LMS_PRIV_LEN; + priv += LMS_PRIV_LEN; + } + + return ret; +} #endif + +/* Update the authentication path and caches. + * + * @param [in, out] state LMS state. + * @param [in, out] priv_key Private key information. + * @param [in] levels Number of level to start at. + * @param [out] pub_root Public root. + * @return 0 on success. + */ +static int wc_hss_init_auth_path(LmsState* state, HssPrivKey* priv_key, + byte* pub_root) +{ + int ret = 0; + int levels = state->params->levels; + byte* priv = priv_key->priv + LMS_PRIV_LEN * (levels - 1); + int l; + + for (l = levels - 1; (ret == 0) && (l >= 0); l--) { + word32 q; + const byte* priv_q = priv; + const byte* priv_seed = priv_q + LMS_Q_LEN; + const byte* priv_i = priv_seed + LMS_SEED_LEN; + + /* Get current q for tree at level. */ + ato32(priv_q, &q); + /* Set cache start to a value that indicates no numbers available. */ + ret = wc_lms_treehash_init(state, &priv_key->state[l], priv_i, + priv_seed, q); + + /* Move onto next level's data. */ + priv -= LMS_PRIV_LEN; + } + + if ((ret == 0) && (pub_root != NULL)) { + XMEMCPY(pub_root, priv_key->state[0].root, LMS_MAX_NODE_LEN); + } + + return ret; +} + +/* Calculate the corresponding authentication path index at that height. + * + * @param [in] i Leaf node index. + * @param [in] h Height to calculate for. + * @return Index on authentication path. + */ +#define LMS_AUTH_PATH_IDX(i, h) \ + (((i) ^ ((word32)1U << (h))) | (((word32)1U << (h)) - 1)) + +/* Update the authentication path. + * + * @param [in, out] state LMS state. + * @param [in, out] priv_key Private key information. + * @param [in] levels Number of level to start at. + * @return 0 on success. + */ +static int wc_hss_update_auth_path(LmsState* state, HssPrivKey* priv_key, + byte* priv_raw, int levels) +{ + const LmsParams* params = state->params; + int ret = 0; + byte* priv = priv_key->priv + LMS_PRIV_LEN * (levels - 1); + int i; +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + w64wrapper q64; +#endif + + (void)priv_raw; +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + ato64(priv_raw, &q64); +#endif + + for (i = levels - 1; (ret == 0) && (i >= 0); i--) { + word32 q; + const byte* priv_q = priv; + const byte* priv_seed = priv_q + LMS_Q_LEN; + const byte* priv_i = priv_seed + LMS_SEED_LEN; + LmsPrivState* privState = &priv_key->state[i]; + + /* Get q for tree at level. */ + ato32(priv_q, &q); + #ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + + if ((levels > 1) && (i == levels - 1) && (q == 0)) { + /* New sub-tree. */ + ret = wc_hss_next_subtree_inc(state, priv_key, q64); + } + if ((ret == 0) && (q != 0)) + #else + if (q == 0) { + /* New sub-tree. */ + ret = wc_lms_treehash_init(state, privState, priv_i, priv_seed, 0); + } + else + #endif + { + word32 maxq = q - 1; + int h; + int maxh = params->height; + + /* Check each index at each height needed for the auth path. */ + for (h = 0; (h < maxh) && (h <= maxh - params->rootLevels); h++) { + /* Calculate the index for current q and q-1. */ + word32 qa = LMS_AUTH_PATH_IDX(q, h); + word32 qm1a = LMS_AUTH_PATH_IDX(q - 1, h); + /* If different then needs to be computed so keep highest. */ + if ((qa != qm1a) && (qa > maxq)) { + maxq = qa; + } + } + for (; h < maxh; h++) { + /* Calculate the index for current q and q-1. */ + word32 qa = LMS_AUTH_PATH_IDX(q, h); + word32 qm1a = LMS_AUTH_PATH_IDX(q - 1, h); + /* If different then copy in cached hash. */ + if ((qa != qm1a) && (qa > maxq)) { + int off = (1 << (params->height - h)) + (qa >> h) - 1; + XMEMCPY(privState->auth_path + h * LMS_MAX_NODE_LEN, + privState->root + off * LMS_MAX_NODE_LEN, + LMS_MAX_NODE_LEN); + } + } + /* Update the treehash and calculate the extra indices for + * authentication path. */ + ret = wc_lms_treehash_update(state, privState, priv_i, priv_seed, + q - 1, maxq, q, 1); + #ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + if ((ret == 0) && (i > 0)) { + w64wrapper tmp64 = w64ShiftRight(q64, + (levels - i) * params->height); + w64Increment(&tmp64); + tmp64 = w64ShiftLeft(tmp64, 64 - (i * params->height)); + if (!w64IsZero(tmp64)) { + priv_seed = priv_key->next_priv + i * LMS_PRIV_LEN + + LMS_Q_LEN; + priv_i = priv_seed + LMS_SEED_LEN; + privState = &priv_key->next_state[i - 1]; + + ret = wc_lms_treehash_update(state, privState, priv_i, + priv_seed, q, q, 0, 0); + } + } + #endif + break; + } + + /* Move onto next level's data. */ + priv -= LMS_PRIV_LEN; + } + + return ret; +} + +#if !defined(WOLFSSL_LMS_NO_SIG_CACHE) && (LMS_MAX_LEVELS > 1) +/* Pre-sign for current q so that it isn't needed in signing. + * + * @param [in, out] state LMS state. + * @param [in, out] priv_key Private key. + */ +static int wc_hss_presign(LmsState* state, HssPrivKey* priv_key) +{ + int ret = 0; + const LmsParams* params = state->params; + byte* buffer = state->buffer; + byte pub[LMS_PUBKEY_LEN]; + byte* root = pub + LMS_PUBKEY_LEN - LMS_MAX_NODE_LEN; + byte* priv = priv_key->priv; + int i; + + for (i = params->levels - 2; i >= 0; i--) { + const byte* p = priv + i * (LMS_Q_LEN + LMS_SEED_LEN + LMS_I_LEN); + const byte* priv_q = p; + const byte* priv_seed = priv_q + LMS_Q_LEN; + const byte* priv_i = priv_seed + LMS_SEED_LEN; + + /* ... || T(1) */ + XMEMCPY(root, priv_key->state[i + 1].root, LMS_MAX_NODE_LEN); + /* u32str(type) || u32str(otstype) || I || T(1) */ + p = priv + (i + 1) * (LMS_Q_LEN + LMS_SEED_LEN + LMS_I_LEN); + wc_lmots_public_key_encode(params, p, pub); + + /* Setup for hashing: I || Q || ... */ + XMEMCPY(buffer, priv_i, LMS_I_LEN); + XMEMCPY(buffer + LMS_I_LEN, priv_q, LMS_Q_LEN); + + /* LM-OTS Sign this level. */ + ret = wc_lmots_sign(state, priv_seed, pub, LMS_PUBKEY_LEN, + priv_key->y + i * LMS_PRIV_Y_TREE_LEN(params->p)); + } + + return ret; +} +#endif /* !WOLFSSL_LMS_NO_SIG_CACHE && LMS_MAX_LEVELS > 1 */ +#endif /* !WOLFSSL_WC_LMS_SMALL */ + +/* Load the private key data into HSS private key structure. + * + * @param [in] params LMS parameters. + * @param [in, out] key HSS private key. + * @param [in] priv_data Private key data. + */ +static void wc_hss_priv_data_load(const LmsParams* params, HssPrivKey* key, + byte* priv_data) +{ +#ifndef WOLFSSL_WC_LMS_SMALL + int l; +#endif + + /* Expanded private keys. */ + key->priv = priv_data; + priv_data += LMS_PRIV_KEY_LEN(params->levels); + +#ifndef WOLFSSL_WC_LMS_SMALL + for (l = 0; l < params->levels; l++) { + /* Caches for subtree. */ + wc_lms_priv_state_load(params, &key->state[l], priv_data); + priv_data += LMS_PRIV_STATE_LEN(params->height, params->rootLevels, + params->cacheBits); + } + +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + /* Next subtree's expanded private keys. */ + key->next_priv = priv_data; + priv_data += LMS_PRIV_KEY_LEN(params->levels); + for (l = 0; l < params->levels - 1; l++) { + /* Next subtree's caches. */ + wc_lms_priv_state_load(params, &key->next_state[l], priv_data); + priv_data += LMS_PRIV_STATE_LEN(params->height, params->rootLevels, + params->cacheBits); + } +#endif /* WOLFSSL_LMS_NO_SIGN_SMOOTHING */ + +#ifndef WOLFSSL_LMS_NO_SIG_CACHE + /* Signature cache. */ + key->y = priv_data; +#endif /* WOLFSSL_LMS_NO_SIG_CACHE */ +#endif /* WOLFSSL_WC_LMS_SMALL */ +} + +#ifndef WOLFSSL_WC_LMS_SMALL +/* Store the private key data from HSS private key structure. + * + * @param [in] params LMS parameters. + * @param [in] key HSS private key. + * @param [in, out] priv_data Private key data. + */ +static void wc_hss_priv_data_store(const LmsParams* params, HssPrivKey* key, + byte* priv_data) +{ + int l; + + (void)key; + + /* Expanded private keys. */ + priv_data += LMS_PRIV_KEY_LEN(params->levels); + + for (l = 0; l < params->levels; l++) { + /* Caches for subtrees. */ + wc_lms_priv_state_store(params, &key->state[l], priv_data); + priv_data += LMS_PRIV_STATE_LEN(params->height, params->rootLevels, + params->cacheBits); + } +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + /* Next subtree's expanded private keys. */ + priv_data += LMS_PRIV_KEY_LEN(params->levels); + for (l = 0; l < params->levels - 1; l++) { + /* Next subtree's caches. */ + wc_lms_priv_state_store(params, &key->next_state[l], priv_data); + priv_data += LMS_PRIV_STATE_LEN(params->height, params->rootLevels, + params->cacheBits); + } +#endif /* WOLFSSL_LMS_NO_SIGN_SMOOTHING */ + +#ifndef WOLFSSL_LMS_NO_SIG_CACHE + /* Signature cache. */ +#endif /* WOLFSSL_LMS_NO_SIG_CACHE */ +} +#endif /* WOLFSSL_WC_LMS_SMALL */ + +/* Expand private key for each level and calculating auth path.. + * + * @param [in, out] state LMS state. + * @param [in] priv_raw Raw private key bytes. + * @param [out] priv_key Private key data. + * @param [out] priv_data Private key data. + * @param [out] pub_root Public key root node. + * @return 0 on success. + */ +int wc_hss_reload_key(LmsState* state, const byte* priv_raw, + HssPrivKey* priv_key, byte* priv_data, byte* pub_root) +{ + int ret; + + (void)pub_root; + + wc_hss_priv_data_load(state->params, priv_key, priv_data); +#ifndef WOLFSSL_WC_LMS_SMALL + priv_key->inited = 0; +#endif + + /* Expand the raw private key into the private key data. */ + ret = wc_hss_expand_private_key(state, priv_key->priv, priv_raw, 0); +#ifndef WOLFSSL_WC_LMS_SMALL + if ((ret == 0) && (!priv_key->inited)) { + /* Initialize the authentication paths and caches for all trees. */ + ret = wc_hss_init_auth_path(state, priv_key, pub_root); + #ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + if (ret == 0) { + ret = wc_hss_next_subtrees_init(state, priv_key); + } + #endif + #if !defined(WOLFSSL_LMS_NO_SIG_CACHE) && (LMS_MAX_LEVELS > 1) + if (ret == 0) { + /* Calculate signatures for trees not at bottom. */ + ret = wc_hss_presign(state, priv_key); + } + #endif /* !WOLFSSL_LMS_NO_SIG_CACHE */ + /* Set initialized flag. */ + priv_key->inited = (ret == 0); + } +#endif /* WOLFSSL_WC_LMS_SMALL */ + + return ret; +} + +/* Make an HSS key pair. + * + * @param [in, out] state LMS state. + * @param [in] rng Random number generator. + * @param [out] priv_raw Private key to write. + * @param [out] priv_key Private key. + * @param [out] priv_data Private key data. + * @param [out] pub Public key. + * @return 0 on success. + */ +int wc_hss_make_key(LmsState* state, WC_RNG* rng, byte* priv_raw, + HssPrivKey* priv_key, byte* priv_data, byte* pub) +{ + const LmsParams* params = state->params; + int ret = 0; + int i; + byte* p = priv_raw; + byte* pub_root = pub + LMS_L_LEN + LMS_TYPE_LEN + LMS_TYPE_LEN + LMS_I_LEN; + + /* The 64-bit q starts at 0 - set into raw private key. */ + wc_lms_idx_zero(p, HSS_Q_LEN); + p += HSS_Q_LEN; + + /* Set the LMS and LM-OTS types for each level. */ + for (i = 0; i < params->levels; i++) { + p[i] = (params->lmsType << 4) + params->lmOtsType; + } + /* Set rest of levels to an invalid value. */ + for (; i < HSS_MAX_LEVELS; i++) { + p[i] = 0xff; + } + p += HSS_PRIV_KEY_PARAM_SET_LEN; + + /* Make the private key. */ + ret = wc_lmots_make_private_key(rng, p); + + if (ret == 0) { + /* Set the levels into the public key data. */ + c32toa(params->levels, pub); + pub += LMS_L_LEN; + + ret = wc_hss_reload_key(state, priv_raw, priv_key, priv_data, pub_root); + } + #ifdef WOLFSSL_WC_LMS_SMALL + if (ret == 0) { + byte* priv_seed = priv_key->priv + LMS_Q_LEN; + byte* priv_i = priv_seed + LMS_SEED_LEN; + + /* Compute the root of the highest tree to get the root for public key. + */ + ret = wc_lms_make_public_key(state, priv_i, priv_seed, pub_root); + } + #endif /* !WOLFSSL_WC_LMS_SMALL */ + if (ret == 0) { + /* Encode the public key with remaining fields from the private key. */ + wc_lmots_public_key_encode(params, priv_key->priv, pub); + } + + return ret; +} + +#ifdef WOLFSSL_WC_LMS_SMALL +/* Sign message using HSS. + * + * Algorithm 8: Generating an HSS signature + * 1. If the message-signing key prv[L-1] is exhausted, regenerate + * that key pair, together with any parent key pairs that might + * be necessary. + * If the root key pair is exhausted, then the HSS key pair is + * exhausted and MUST NOT generate any more signatures. + * d = L + * while (prv[d-1].q == 2^(prv[d-1].h)) { + * d = d - 1 + * if (d == 0) + * return FAILURE + * } + * while (d < L) { + * create lms key pair pub[d], prv[d] + * sig[d-1] = lms_signature( pub[d], prv[d-1] ) + * d = d + 1 + * } + * 2. Sign the message. + * sig[L-1] = lms_signature( msg, prv[L-1] ) + * 3. Create the list of signed public keys. + * i = 0; + * while (i < L-1) { + * signed_pub_key[i] = sig[i] || pub[i+1] + * i = i + 1 + * } + * 4. Return u32str(L-1) || signed_pub_key[0] || ... + * || signed_pub_key[L-2] || sig[L-1] + * + * @param [in, out] state LMS state. + * @param [in, out] priv_raw Raw private key bytes. + * @param [in, out] priv_key Private key data. + * @param [in] msg Message to sign. + * @param [in] msgSz Length of message in bytes. + * @param [out] sig Signature of message. + * @return 0 on success. + */ +int wc_hss_sign(LmsState* state, byte* priv_raw, HssPrivKey* priv_key, + byte* priv_data, const byte* msg, word32 msgSz, byte* sig) +{ + const LmsParams* params = state->params; + int ret = 0; + byte* priv = priv_key->priv; + + (void)priv_data; + + /* Step 1. Part 2: Check for total key exhaustion. */ + if (!wc_hss_sigsleft(params, priv_raw)) { + ret = KEY_EXHAUSTED_E; + } + + if (ret == 0) { + /* Expand the raw private key into the private key data. */ + ret = wc_hss_expand_private_key(state, priv, priv_raw, 0); + } + if (ret == 0) { + int i; + w64wrapper q; + w64wrapper qm1; + + /* Get 64-bit q from raw private key. */ + ato64(priv_raw, &q); + /* Calculate q-1 for comparison. */ + qm1 = q; + w64Decrement(&qm1); + + /* Set number of signed public keys. */ + c32toa(params->levels - 1, sig); + sig += params->sig_len; + + /* Build from bottom up. */ + for (i = params->levels - 1; (ret == 0) && (i >= 0); i--) { + byte* p = priv + i * (LMS_Q_LEN + LMS_SEED_LEN + LMS_I_LEN); + byte* root = NULL; + + /* Move to start of next signature at this level. */ + sig -= LMS_SIG_LEN(params->height, params->p); + if (i != 0) { + /* Put root node into signature at this index. */ + root = sig - LMS_MAX_NODE_LEN; + } + + /* Sign using LMS for this level. */ + ret = wc_lms_sign(state, p, msg, msgSz, sig); + if (ret == 0) { + byte* s = sig + LMS_Q_LEN + LMS_TYPE_LEN + LMS_MAX_NODE_LEN + + params->p * LMS_MAX_NODE_LEN + LMS_TYPE_LEN; + byte* priv_q = p; + byte* priv_seed = priv_q + LMS_Q_LEN; + byte* priv_i = priv_seed + LMS_SEED_LEN; + word32 q32; + + /* Get Q from private key as a number. */ + ato32(priv_q, &q32); + /* Calculate authentication path. */ + ret = wc_lms_auth_path(state, priv_i, priv_seed, q32, s, root); + } + if ((ret == 0) && (i != 0)) { + /* Create public data for this level if there is another. */ + sig -= LMS_PUBKEY_LEN; + msg = sig; + msgSz = LMS_PUBKEY_LEN; + wc_lmots_public_key_encode(params, p, sig); + } + } + } + if (ret == 0) { + /* Increment index of leaf node to sign with in raw data. */ + wc_lms_idx_inc(priv_raw, HSS_Q_LEN); + } + + return ret; +} +#else +/* Build signature for HSS signed message. + * + * Algorithm 8: Generating an HSS signature + * 1. ... + * while (prv[d-1].q == 2^(prv[d-1].h)) { + * d = d - 1 + * if (d == 0) + * return FAILURE + * } + * while (d < L) { + * create lms key pair pub[d], prv[d] + * sig[d-1] = lms_signature( pub[d], prv[d-1] ) + * d = d + 1 + * } + * 2. Sign the message. + * sig[L-1] = lms_signature( msg, prv[L-1] ) + * 3. Create the list of signed public keys. + * i = 0; + * while (i < L-1) { + * signed_pub_key[i] = sig[i] || pub[i+1] + * i = i + 1 + * } + * 4. Return u32str(L-1) || signed_pub_key[0] || ... + * || signed_pub_key[L-2] || sig[L-1] + * + * @param [in, out] state LMS state. + * @param [in, out] priv_raw Raw private key bytes. + * @param [in, out] priv_key Private key data. + * @param [in] msg Message to sign. + * @param [in] msgSz Length of message in bytes. + * @param [out] sig Signature of message. + * @return 0 on success. + */ +static int wc_hss_sign_build_sig(LmsState* state, byte* priv_raw, + HssPrivKey* priv_key, const byte* msg, word32 msgSz, byte* sig) +{ + const LmsParams* params = state->params; + int ret = 0; + int i; + w64wrapper q; + w64wrapper qm1; + byte* priv = priv_key->priv; + + /* Get 64-bit q from raw private key. */ + ato64(priv_raw, &q); + /* Calculate q-1 for comparison. */ + qm1 = q; + w64Decrement(&qm1); + + /* Set number of signed public keys. */ + c32toa(params->levels - 1, sig); + sig += params->sig_len; + + /* Build from bottom up. */ + for (i = params->levels - 1; (ret == 0) && (i >= 0); i--) { + byte* p = priv + i * (LMS_Q_LEN + LMS_SEED_LEN + LMS_I_LEN); + byte* root = NULL; + #ifndef WOLFSSL_LMS_NO_SIG_CACHE + int store_p = 0; + word32 q_32 = LMS_Q_AT_LEVEL(q, params->levels, i, + params->height); + word32 qm1_32 = LMS_Q_AT_LEVEL(qm1, params->levels, i, + params->height); + #endif /* !WOLFSSL_LMS_NO_SIG_CACHE */ + + /* Move to start of next signature at this level. */ + sig -= LMS_SIG_LEN(params->height, params->p); + if (i != 0) { + /* Put root node into signature at this index. */ + root = sig - LMS_MAX_NODE_LEN; + } + + #ifndef WOLFSSL_LMS_NO_SIG_CACHE + /* Check if we have a cached version of C and the p hashes that we + * can reuse. */ + if ((i < params->levels - 1) && (q_32 == qm1_32)) { + wc_lms_sig_copy(params, priv_key->y + + i * LMS_PRIV_Y_TREE_LEN(params->p), p, sig); + } + else + #endif /* !WOLFSSL_LMS_NO_SIG_CACHE */ + { + /* Sign using LMS for this level. */ + ret = wc_lms_sign(state, p, msg, msgSz, sig); + #ifndef WOLFSSL_LMS_NO_SIG_CACHE + store_p = (i < params->levels - 1); + #endif /* !WOLFSSL_LMS_NO_SIG_CACHE */ + } + if (ret == 0) { + byte* s = sig + LMS_Q_LEN + LMS_TYPE_LEN; + + #ifndef WOLFSSL_LMS_NO_SIG_CACHE + /* Check if we computed new C and p hashes. */ + if (store_p) { + /* Cache the C and p hashes. */ + XMEMCPY(priv_key->y + i * LMS_PRIV_Y_TREE_LEN(params->p), s, + LMS_PRIV_Y_TREE_LEN(params->p)); + } + #endif /* !WOLFSSL_LMS_NO_SIG_CACHE */ + s += LMS_MAX_NODE_LEN + params->p * LMS_MAX_NODE_LEN + + LMS_TYPE_LEN; + + /* Copy the authentication path out of the private key. */ + XMEMCPY(s, priv_key->state[i].auth_path, + params->height * LMS_MAX_NODE_LEN); + /* Copy the root node into signature unless at top. */ + if (i != 0) { + XMEMCPY(root, priv_key->state[i].root, LMS_MAX_NODE_LEN); + } + } + if ((ret == 0) && (i != 0)) { + /* Create public data for this level if there is another. */ + sig -= LMS_PUBKEY_LEN; + msg = sig; + msgSz = LMS_PUBKEY_LEN; + wc_lmots_public_key_encode(params, p, sig); + } + } + + return ret; +} + +/* Sign message using HSS. + * + * Algorithm 8: Generating an HSS signature + * 1. If the message-signing key prv[L-1] is exhausted, regenerate + * that key pair, together with any parent key pairs that might + * be necessary. + * If the root key pair is exhausted, then the HSS key pair is + * exhausted and MUST NOT generate any more signatures. + * d = L + * while (prv[d-1].q == 2^(prv[d-1].h)) { + * d = d - 1 + * if (d == 0) + * return FAILURE + * } + * while (d < L) { + * create lms key pair pub[d], prv[d] + * sig[d-1] = lms_signature( pub[d], prv[d-1] ) + * d = d + 1 + * } + * 2. Sign the message. + * sig[L-1] = lms_signature( msg, prv[L-1] ) + * 3. Create the list of signed public keys. + * i = 0; + * while (i < L-1) { + * signed_pub_key[i] = sig[i] || pub[i+1] + * i = i + 1 + * } + * 4. Return u32str(L-1) || signed_pub_key[0] || ... + * || signed_pub_key[L-2] || sig[L-1] + * + * @param [in, out] state LMS state. + * @param [in, out] priv_raw Raw private key bytes. + * @param [in, out] priv_key Private key data. + * @param [in, out] priv_data Private key data. + * @param [in] msg Message to sign. + * @param [in] msgSz Length of message in bytes. + * @param [out] sig Signature of message. + * @return 0 on success. + */ +int wc_hss_sign(LmsState* state, byte* priv_raw, HssPrivKey* priv_key, + byte* priv_data, const byte* msg, word32 msgSz, byte* sig) +{ + const LmsParams* params = state->params; + int ret = 0; + + /* Validate fixed parameters for static code analyzers. */ + if ((params->rootLevels == 0) || (params->rootLevels > params->height)) { + ret = BAD_FUNC_ARG; + } + + /* Step 1. Part 2: Check for total key exhaustion. */ + if ((ret == 0) && (!wc_hss_sigsleft(params, priv_raw))) { + ret = KEY_EXHAUSTED_E; + } + + if ((ret == 0) && (!priv_key->inited)) { + /* Initialize the authentication paths and caches for all trees. */ + ret = wc_hss_init_auth_path(state, priv_key, NULL); + #if !defined(WOLFSSL_LMS_NO_SIG_CACHE) && (LMS_MAX_LEVELS > 1) + if (ret == 0) { + ret = wc_hss_presign(state, priv_key); + } + #endif /* !WOLFSSL_LMS_NO_SIG_CACHE */ + /* Set initialized flag. */ + priv_key->inited = (ret == 0); + } + if (ret == 0) { + ret = wc_hss_sign_build_sig(state, priv_raw, priv_key, msg, msgSz, sig); + } + if (ret == 0) { + /* Increment index of leaf node to sign with in raw data. */ + wc_lms_idx_inc(priv_raw, HSS_Q_LEN); + } + /* Check we will produce another signature. */ + if ((ret == 0) && wc_hss_sigsleft(params, priv_raw)) { + /* Update the expanded private key data. */ + ret = wc_hss_expand_private_key(state, priv_key->priv, priv_raw, 1); + if (ret == 0) { + /* Update authentication path and caches for all trees. */ + ret = wc_hss_update_auth_path(state, priv_key, priv_raw, + params->levels); + } + } + if (ret == 0) { + /* Store the updated private key data. */ + wc_hss_priv_data_store(state->params, priv_key, priv_data); + } + + return ret; +} +#endif + +/* Check whether key is exhausted. + * + * First 8 bytes of raw key is the index. + * Check index is less than count of leaf nodes. + * + * @param [in] params LMS parameters. + * @param [in] priv_raw HSS raw private key. + * @return 1 when signature possible. + * @return 0 when private key exhausted. + */ +int wc_hss_sigsleft(const LmsParams* params, const byte* priv_raw) +{ + w64wrapper q; + w64wrapper cnt; + + /* Get current q - next leaf index to sign with. */ + ato64(priv_raw, &q); + /* 1 << total_height = total leaf nodes. */ + cnt = w64ShiftLeft(w64From32(0, 1), params->levels * params->height); + /* Check q is less than total leaf node count. */ + return w64LT(q, cnt); +} +#endif /* !WOLFSSL_LMS_VERIFY_ONLY */ + +/* Verify message using HSS. + * + * Section 6.3. Signature Verification + * 1. Nspk = strTou32(first four bytes of S) + * 2. if Nspk+1 is not equal to the number of levels L in pub: + * 3. return INVALID + * 4. key = pub + * 5. for (i = 0; i < Nspk; i = i + 1) { + * 6. sig = siglist[i] + * 7. msg = publist[i] + * 8. if (lms_verify(msg, key, sig) != VALID): + * 9. return INVALID + * 10. key = msg + * 11. } + * 12. return lms_verify(message, key, siglist[Nspk]) + * + * @param [in, out] state LMS state. + * @param [in] pub HSS public key. + * @param [in] msg Message to rifyn. + * @param [in] msgSz Length of message in bytes. + * @param [in] sig Signature of message. + * @return 0 on success. + * @return SIG_VERFIY_E on failure. + */ +int wc_hss_verify(LmsState* state, const byte* pub, const byte* msg, + word32 msgSz, const byte* sig) +{ + const LmsParams* params = state->params; + int ret = 0; + word32 nspk; + const byte* key = pub + LMS_L_LEN; + word32 levels; + + /* Get number of levels from public key. */ + ato32(pub, &levels); + /* Line 1: Get number of signed public keys from signature. */ + ato32(sig, &nspk); + /* Line 6 (First iteration): Move to start of next signature. */ + sig += LMS_L_LEN; + + /* Line 2: Verify that pub and signature match in levels. */ + if (nspk + 1 != levels) { + /* Line 3: Return invalid signature. */ + ret = SIG_VERIFY_E; + } + if (ret == 0) { + word32 i; + + /* Line 5: For all but last LMS signature. */ + for (i = 0; (ret == 0) && (i < nspk); i++) { + /* Line 7: Get start of public key in signature. */ + const byte* pubList = sig + LMS_Q_LEN + LMS_TYPE_LEN + + LMS_MAX_NODE_LEN + params->p * LMS_MAX_NODE_LEN + LMS_TYPE_LEN + + params->height * LMS_MAX_NODE_LEN; + /* Line 8: Verify the LMS signature with public key as message. */ + ret = wc_lms_verify(state, key, pubList, LMS_PUBKEY_LEN, sig); + /* Line 10: Next key is from signature. */ + key = pubList; + /* Line 6: Move to start of next signature. */ + sig = pubList + LMS_PUBKEY_LEN; + } + } + if (ret == 0) { + /* Line 12: Verify bottom tree with real message. */ + ret = wc_lms_verify(state, key, msg, msgSz, sig); + } + + return ret; +} + +#endif /* WOLFSSL_HAVE_LMS && WOLFSSL_WC_LMS */ + diff --git a/src/wolfcrypt/src/wc_pkcs11.c b/src/wolfcrypt/src/wc_pkcs11.c index 0d7bd6e..e248d8e 100644 --- a/src/wolfcrypt/src/wc_pkcs11.c +++ b/src/wolfcrypt/src/wc_pkcs11.c @@ -1355,7 +1355,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) int keyType; ret = Pkcs11HmacTypes(hmac->macType, &mechType, &keyType); - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) break; if (ret == 0) @@ -1367,7 +1367,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) (unsigned char*)hmac->id, hmac->idLen, hmac->label, hmac->labelLen, CKA_SIGN); - if (ret == WC_HW_E) { + if (ret == WC_NO_ERR_TRACE(WC_HW_E)) { ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_GENERIC_SECRET, (unsigned char*)hmac->keyRaw, @@ -1414,7 +1414,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) } } #endif - if (ret == 0 || ret == NOT_COMPILED_IN) { + if (ret == 0 || ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { /* Try ECDSA mechanism next. */ ret2 = Pkcs11MechAvail(&session, CKM_ECDSA); if (ret2 == 0) { @@ -1428,7 +1428,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) } } /* OK for this to fail if set for ECDH. */ - if (ret == NOT_COMPILED_IN) + if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) ret = ret2; } if (ret == 0 && clear) @@ -2514,7 +2514,7 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) PRIVATE_KEY_UNLOCK(); ret = wc_ecc_export_x963(info->pk.ecdh.public_key, NULL, &pointLen); PRIVATE_KEY_LOCK(); - if (ret == LENGTH_ONLY_E) { + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { point = (unsigned char*)XMALLOC(pointLen, info->pk.ecdh.public_key->heap, DYNAMIC_TYPE_ECC_BUFFER); @@ -3604,7 +3604,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) ret = Pkcs11CreateSecretKey(&key, session, keyType, (unsigned char*)hmac->keyRaw, hmac->keyLen, NULL, 0, NULL, 0, CKA_SIGN); - if (ret == WC_HW_E) { + if (ret == WC_NO_ERR_TRACE(WC_HW_E)) { ret = Pkcs11CreateSecretKey(&key, session, CKK_GENERIC_SECRET, (unsigned char*)hmac->keyRaw, hmac->keyLen, NULL, 0, NULL, 0, CKA_SIGN); @@ -3614,7 +3614,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) else if (ret == 0 && hmac->labelLen != 0) { ret = Pkcs11FindKeyByLabel(&key, CKO_SECRET_KEY, keyType, session, hmac->label, hmac->labelLen); - if (ret == WC_HW_E) { + if (ret == WC_NO_ERR_TRACE(WC_HW_E)) { ret = Pkcs11FindKeyByLabel(&key, CKO_SECRET_KEY, CKK_GENERIC_SECRET, session, hmac->label, hmac->labelLen); @@ -3623,7 +3623,7 @@ static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) else if (ret == 0) { ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, keyType, session, hmac->id, hmac->idLen); - if (ret == WC_HW_E) { + if (ret == WC_NO_ERR_TRACE(WC_HW_E)) { ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_GENERIC_SECRET, session, hmac->id, hmac->idLen); diff --git a/src/wolfcrypt/src/wc_port.c b/src/wolfcrypt/src/wc_port.c index a21cc2b..32ffb9e 100644 --- a/src/wolfcrypt/src/wc_port.c +++ b/src/wolfcrypt/src/wc_port.c @@ -1303,9 +1303,8 @@ int wolfSSL_CryptHwMutexInit(void) } int wolfSSL_CryptHwMutexLock(void) { - int ret = BAD_MUTEX_E; /* Make sure HW Mutex has been initialized */ - ret = wolfSSL_CryptHwMutexInit(); + int ret = wolfSSL_CryptHwMutexInit(); if (ret == 0) { ret = wc_LockMutex(&wcCryptHwMutex); } @@ -1313,11 +1312,12 @@ int wolfSSL_CryptHwMutexLock(void) } int wolfSSL_CryptHwMutexUnLock(void) { - int ret = BAD_MUTEX_E; if (wcCryptHwMutexInit) { - ret = wc_UnLockMutex(&wcCryptHwMutex); + return wc_UnLockMutex(&wcCryptHwMutex); + } + else { + return BAD_MUTEX_E; } - return ret; } #endif /* WOLFSSL_CRYPT_HW_MUTEX */ @@ -1699,9 +1699,8 @@ int wolfSSL_CryptHwMutexUnLock(void) int maxq_CryptHwMutexTryLock() { - int ret = BAD_MUTEX_E; /* Make sure HW Mutex has been initialized */ - ret = wolfSSL_CryptHwMutexInit(); + int ret = wolfSSL_CryptHwMutexInit(); if (ret == 0) { ret = maxq_LockMutex(&wcCryptHwMutex, 1); } @@ -3431,7 +3430,8 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) #ifndef SINGLE_THREADED /* Environment-specific multi-thread implementation check */ -#if defined(USE_WINDOWS_API) && !defined(WOLFSSL_PTHREADS) +#if defined(USE_WINDOWS_API) && !defined(WOLFSSL_PTHREADS) && \ + !defined(_WIN32_WCE) int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { @@ -3646,7 +3646,7 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) "wolfSSL thread", (entry_functionType)cb, (ULONG)arg, thread->threadStack, - TESTSUITE_THREAD_STACK_SZ, + WOLFSSL_NETOS_STACK_SZ, 2, 2, 1, TX_AUTO_START); if (result != TX_SUCCESS) { @@ -3668,11 +3668,13 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) #elif defined(WOLFSSL_ZEPHYR) + void* wolfsslThreadHeapHint = NULL; + int wolfSSL_NewThread(THREAD_TYPE* thread, THREAD_CB cb, void* arg) { #ifndef WOLFSSL_ZEPHYR_STACK_SZ - #define WOLFSSL_ZEPHYR_STACK_SZ (24*1024) + #define WOLFSSL_ZEPHYR_STACK_SZ (48*1024) #endif if (thread == NULL || cb == NULL) @@ -3686,10 +3688,12 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) * 0); */ thread->threadStack = (void*)XMALLOC( - Z_KERNEL_STACK_SIZE_ADJUST(WOLFSSL_ZEPHYR_STACK_SZ), 0, - DYNAMIC_TYPE_TMP_BUFFER); - if (thread->threadStack == NULL) + Z_KERNEL_STACK_SIZE_ADJUST(WOLFSSL_ZEPHYR_STACK_SZ), + wolfsslThreadHeapHint, DYNAMIC_TYPE_TMP_BUFFER); + if (thread->threadStack == NULL) { + WOLFSSL_MSG("error: XMALLOC failed"); return MEMORY_E; + } /* k_thread_create does not return any error codes */ /* Casting to k_thread_entry_t should be fine since we just ignore the @@ -3716,7 +3720,8 @@ char* mystrnstr(const char* s1, const char* s2, unsigned int n) * if (err != 0) * ret = MEMORY_E; */ - XFREE(thread.threadStack, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(thread.threadStack, wolfsslThreadHeapHint, + DYNAMIC_TYPE_TMP_BUFFER); thread.threadStack = NULL; /* No thread resources to free. Everything is stored in thread.tid */ diff --git a/src/wolfcrypt/src/wc_xmss.c b/src/wolfcrypt/src/wc_xmss.c index 545b531..0e63722 100644 --- a/src/wolfcrypt/src/wc_xmss.c +++ b/src/wolfcrypt/src/wc_xmss.c @@ -19,8 +19,1654 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif + #include +#include +#include #ifdef WOLFSSL_HAVE_XMSS - #error "Contact wolfSSL to get the implementation of this file" +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/*************************** + * DIGEST init and free. + ***************************/ + +/* Initialize the digest algorithm to use. + * + * @param [in, out] state XMSS/MT state including digest and parameters. + * @return 0 on success. + * @return NOT_COMPILED_IN when digest algorithm not supported. + * @return Other negative when digest algorithm initialization failed. + */ +static int wc_xmss_digest_init(XmssState* state) +{ + int ret; + word8 hash = state->params->hash; + +#ifdef WC_XMSS_SHA256 + if (hash == WC_HASH_TYPE_SHA256) { + ret = wc_InitSha256(&state->digest.sha256); + } + else +#endif +#ifdef WC_XMSS_SHA512 + if (hash == WC_HASH_TYPE_SHA512) { + ret = wc_InitSha512(&state->digest.sha512); + } + else +#endif +#ifdef WC_XMSS_SHAKE128 + if (hash == WC_HASH_TYPE_SHAKE128) { + ret = wc_InitShake128(&state->digest.shake, NULL, INVALID_DEVID); + } + else +#endif +#ifdef WC_XMSS_SHAKE256 + if (hash == WC_HASH_TYPE_SHAKE256) { + ret = wc_InitShake256(&state->digest.shake, NULL, INVALID_DEVID); + } + else +#endif + { + ret = NOT_COMPILED_IN; + } + + return ret; +} +/* Free the digest algorithm. + * + * @param [in, out] state XMSS/MT state including digest and parameters. + */ +static void wc_xmss_digest_free(XmssState* state) +{ + word8 hash = state->params->hash; + +#ifdef WC_XMSS_SHA256 + if (hash == WC_HASH_TYPE_SHA256) { + wc_Sha256Free(&state->digest.sha256); + } + else +#endif +#ifdef WC_XMSS_SHA512 + if (hash == WC_HASH_TYPE_SHA512) { + wc_Sha512Free(&state->digest.sha512); + } + else +#endif +#ifdef WC_XMSS_SHAKE128 + if (hash == WC_HASH_TYPE_SHAKE128) { + wc_Shake128_Free(&state->digest.shake); + } + else +#endif +#ifdef WC_XMSS_SHAKE256 + if (hash == WC_HASH_TYPE_SHAKE256) { + wc_Shake256_Free(&state->digest.shake); + } + else +#endif + { + /* Do nothing. */ + } +} + +/* Initialize the XMSS/MT state. + * + * @param [in, out] state XMSS/MT state including digest and parameters. + * @param [in] params Parameters for key. + * @return 0 on success. + * @return NOT_COMPILED_IN when digest algorithm not supported. + * @return Other negative when digest algorithm initialization failed. + */ +static WC_INLINE int wc_xmss_state_init(XmssState* state, + const XmssParams* params) +{ + state->params = params; + state->ret = 0; + return wc_xmss_digest_init(state); +} + +/* Free the XMSS/MT state. + * + * @param [in, out] state XMSS/MT state including digest and parameters. + */ +static WC_INLINE void wc_xmss_state_free(XmssState* state) +{ + wc_xmss_digest_free(state); +} + + +/*************************** + * XMSS PARAMS + ***************************/ + +/* Map of XMSS/MT string name to OID. + */ +typedef struct wc_XmssString { + /* Name of algorithm as a string. */ + const char* str; + /* OID for algorithm. */ + word32 oid; + /* XMSS parameters. */ + XmssParams params; +} wc_XmssString; + +#ifndef WOLFSSL_WC_XMSS_SMALL + +/* Size of BDS State encoded numbers - offset=1, next=3. */ +#define XMSS_BDS_NUMS_SZ 4 +/* Size of treehash encoding - nextIdx=3, completed|used=1. */ +#define XMSS_TREEHASH_SZ 4 + +/* Calculate Secret key length. + * + * See wc_xmss_bds_state_save() and wc_xmss_bds_state_load(). + * + * SK = idx || wots_sk || SK_PRF || root || SEED || BDSs || OTHER + * BDSs = (2 * depth - 1) * BDS + * BDS = stack || height || authPath || keep || nodes || retain || + * offset || next || TREEHASHes + * TREEHASHes = (Subtree height - BDS k param) * TREEHASH + * TREEHASH = nextIdx || completed || used + * + * @param [in] n Number of bytes to hash output. + * @param [in] h Height of full tree. + * @param [in] d Depth of trees (number of subtrees). + * @param [in] s Subtree height. + * @param [in] i Length of index encoding in bytes. + * @param [in] k BDS k parameter. + * @return Secret key length in bytes. + */ +#define XMSS_SK_LEN(n, h, d, s, i, k) \ + (((i) + 4 * (n)) + \ + (2 * (d) - 1) * (((s) + 1) * (n) + \ + (s) + 1 + \ + (s) * (n) + \ + ((s) >> 1) * (n) + \ + ((s) - (k)) * XMSS_TREEHASH_SZ + \ + ((s) - (k)) * (n) + \ + XMSS_RETAIN_LEN(k, n) + \ + XMSS_BDS_NUMS_SZ) + \ + ((d) - 1) * (n) * ((n) * 2 + 3)) + +#else + +/* Calculate Secret key length. + * + * SK = idx || wots_sk || SK_PRF || root || SEED + * + * @param [in] n Number of bytes to hash output. + * @param [in] h Height of full tree. Unused. + * @param [in] d Depth of trees (number of subtrees). Unused. + * @param [in] s Subtree height. Unused. + * @param [in] i Length of index encoding in bytes. + * @param [in] k BDS k parameter. Unused. + * @return Secret key length. + */ +#define XMSS_SK_LEN(n, h, d, s, i, k) \ + ((i) + 4 * (n)) + +#endif + +#ifndef WOLFSSL_XMSS_LARGE_SECRET_KEY +/* Choose the smaller BDS K parameter. */ +#define XMSS_K(k, kl) (k) +#else +/* Choose the larger BDS K parameter. */ +#define XMSS_K(k, kl) (kl) +#endif + +/* Calculate all fixed parameter values and output an array declaration. + * + * @param [in] hash Hash algorithm to use. + * @param [in] n Number of bytes to hash output. + * @param [in] p Number of bytes of padding. + * @param [in] h Height of full tree. + * @param [in] d Depth of trees (number of subtrees). + * @param [in] i Length of index encoding in bytes. + * @param [in] k BDS k parameter. 0 or >= 2 but (h/d - k) is even. + * @param [in] kl BDS k parameter when large signatures. + * @return XMSS/XMSS^MT parameters array declaration. + */ +#define XMSS_PARAMS(hash, n, p, h, d, i, k, kl) \ + { hash, n, p, (n) * 2 + 3, (n) * ((n) * 2 + 3), h, (h) / (d), (d), (i), \ + (i) + (n) + (d) * (((n) * 2 + 3) * (n)) + (h) * (n), \ + XMSS_SK_LEN(n, h, d, ((h) / (d)), i, XMSS_K(k, kl)), (n) * 2, \ + XMSS_K(k, kl) } + /* hash, d, pad_len, wots_len, wots_sig_len, h, sub_h, d, idx_len, + * sig_len, + * sk_len, pk_len, + * bds_k */ + +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 +/* List of known XMSS algorithm strings and their OIDs. */ +static const wc_XmssString wc_xmss_alg[] = { +#ifdef WC_XMSS_SHA256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHA2_10_256", WC_XMSS_OID_SHA2_10_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHA2_16_256", WC_XMSS_OID_SHA2_16_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHA2_20_256", WC_XMSS_OID_SHA2_20_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 256 */ +#endif /* WC_XMSS_SHA256 */ +#ifdef WC_XMSS_SHA512 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHA2_10_512", WC_XMSS_OID_SHA2_10_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHA2_16_512", WC_XMSS_OID_SHA2_16_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHA2_20_512", WC_XMSS_OID_SHA2_20_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 512 */ +#endif /* WC_XMSS_SHA512 */ + +#ifdef WC_XMSS_SHAKE128 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHAKE_10_256", WC_XMSS_OID_SHAKE_10_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHAKE_16_256", WC_XMSS_OID_SHAKE_16_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHAKE_20_256", WC_XMSS_OID_SHAKE_20_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 256 */ +#endif /* WC_XMSS_SHAKE128 */ + +#ifdef WC_XMSS_SHAKE256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHAKE_10_512", WC_XMSS_OID_SHAKE_10_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHAKE_16_512", WC_XMSS_OID_SHAKE_16_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHAKE_20_512", WC_XMSS_OID_SHAKE_20_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 512 */ +#endif /* WC_XMSS_SHAKE256 */ + +#ifdef WC_XMSS_SHA256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHA2_10_192", WC_XMSS_OID_SHA2_10_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHA2_16_192", WC_XMSS_OID_SHA2_16_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHA2_20_192", WC_XMSS_OID_SHA2_20_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 192 */ +#endif /* WC_XMSS_SHA256 */ + +#ifdef WC_XMSS_SHAKE256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHAKE256_10_256", WC_XMSS_OID_SHAKE256_10_256, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHAKE256_16_256", WC_XMSS_OID_SHAKE256_16_256, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHAKE256_20_256", WC_XMSS_OID_SHAKE256_20_256, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 256 */ +#endif /* WC_XMSS_SHAKE256 */ + +#ifdef WC_XMSS_SHAKE256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 10 && WOLFSSL_XMSS_MAX_HEIGHT >= 10 + { "XMSS-SHAKE256_10_192", WC_XMSS_OID_SHAKE256_10_192, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 10, 1, 4, 0, 4), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 16 && WOLFSSL_XMSS_MAX_HEIGHT >= 16 + { "XMSS-SHAKE256_16_192", WC_XMSS_OID_SHAKE256_16_192, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 16, 1, 4, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSS-SHAKE256_20_192", WC_XMSS_OID_SHAKE256_20_192, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 20, 1, 4, 0, 0), }, +#endif +#endif /* HASH_SIZE 192 */ +#endif /* WC_XMSS_SHAKE256 */ +}; +/* Length of array of known XMSS algorithms. */ +#define WC_XMSS_ALG_LEN (sizeof(wc_xmss_alg) / sizeof(*wc_xmss_alg)) +#endif + +/* Convert XMSS algorithm string to an OID - object identifier. + * + * @param [out] oid OID value corresponding to string. + * @param [in] s String to convert. + * @param [out] params XMSS/MT parameters. + * @return 0 on success. + * @return NOT_COMPILED_IN on failure. + */ +static int wc_xmss_str_to_params(const char *s, word32* oid, + const XmssParams** params) +{ + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 + unsigned int i; + + ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); + for (i = 0; i < WC_XMSS_ALG_LEN; i++) { + if (XSTRCMP(s, wc_xmss_alg[i].str) == 0) { + *oid = wc_xmss_alg[i].oid; + *params = &wc_xmss_alg[i].params; + ret = 0; + break; + } + } +#else + (void)s; + (void)oid; + (void)params; + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +#if WOLFSSL_XMSS_MAX_HEIGHT >= 20 +/* List of known XMSS^MT algorithm strings and their OIDs. */ +static const wc_XmssString wc_xmssmt_alg[] = { +#ifdef WC_XMSS_SHA256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHA2_20/2_256", WC_XMSSMT_OID_SHA2_20_2_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHA2_20/4_256", WC_XMSSMT_OID_SHA2_20_4_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHA2_40/2_256", WC_XMSSMT_OID_SHA2_40_2_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHA2_40/4_256", WC_XMSSMT_OID_SHA2_40_4_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHA2_40/8_256", WC_XMSSMT_OID_SHA2_40_8_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHA2_60/3_256", WC_XMSSMT_OID_SHA2_60_3_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHA2_60/6_256", WC_XMSSMT_OID_SHA2_60_6_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHA2_60/12_256", WC_XMSSMT_OID_SHA2_60_12_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 32, 32, 60, 12, 8, 0, 0), }, +#endif +#endif /* HASH_SIZE 256 */ +#endif /* WC_XMSS_SHA256 */ +#ifdef WC_XMSS_SHA512 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHA2_20/2_512", WC_XMSSMT_OID_SHA2_20_2_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHA2_20/4_512", WC_XMSSMT_OID_SHA2_20_4_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHA2_40/2_512", WC_XMSSMT_OID_SHA2_40_2_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHA2_40/4_512", WC_XMSSMT_OID_SHA2_40_4_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHA2_40/8_512", WC_XMSSMT_OID_SHA2_40_8_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHA2_60/3_512", WC_XMSSMT_OID_SHA2_60_3_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHA2_60/6_512", WC_XMSSMT_OID_SHA2_60_6_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHA2_60/12_512", WC_XMSSMT_OID_SHA2_60_12_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHA512, 64, 64, 60, 12, 8, 0, 0), }, +#endif +#endif /* HASH_SIZE 512 */ +#endif /* WC_XMSS_SHA512 */ + +#ifdef WC_XMSS_SHAKE128 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHAKE_20/2_256", WC_XMSSMT_OID_SHAKE_20_2_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHAKE_20/4_256", WC_XMSSMT_OID_SHAKE_20_4_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHAKE_40/2_256", WC_XMSSMT_OID_SHAKE_40_2_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHAKE_40/4_256", WC_XMSSMT_OID_SHAKE_40_4_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHAKE_40/8_256", WC_XMSSMT_OID_SHAKE_40_8_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHAKE_60/3_256", WC_XMSSMT_OID_SHAKE_60_3_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHAKE_60/6_256", WC_XMSSMT_OID_SHAKE_60_6_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHAKE_60/12_256", WC_XMSSMT_OID_SHAKE_60_12_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE128, 32, 32, 60, 12, 8, 0, 0), }, +#endif +#endif /* HASH_SIZE 256 */ +#endif /* WC_XMSS_SHAKE128 */ + +#ifdef WC_XMSS_SHAKE256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 512 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHAKE_20/2_512", WC_XMSSMT_OID_SHAKE_20_2_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHAKE_20/4_512", WC_XMSSMT_OID_SHAKE_20_4_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHAKE_40/2_512", WC_XMSSMT_OID_SHAKE_40_2_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHAKE_40/4_512", WC_XMSSMT_OID_SHAKE_40_4_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHAKE_40/8_512", WC_XMSSMT_OID_SHAKE_40_8_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHAKE_60/3_512", WC_XMSSMT_OID_SHAKE_60_3_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHAKE_60/6_512", WC_XMSSMT_OID_SHAKE_60_6_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHAKE_60/12_512", WC_XMSSMT_OID_SHAKE_60_12_512 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 64, 64, 60, 12, 8, 0, 0), }, +#endif +#endif /* HASH_SIZE 512 */ +#endif /* WC_XMSS_SHAKE256 */ + +#ifdef WC_XMSS_SHA256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHA2_20/2_192", WC_XMSSMT_OID_SHA2_20_2_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHA2_20/4_192", WC_XMSSMT_OID_SHA2_20_4_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHA2_40/2_192", WC_XMSSMT_OID_SHA2_40_2_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHA2_40/4_192", WC_XMSSMT_OID_SHA2_40_4_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHA2_40/8_192", WC_XMSSMT_OID_SHA2_40_8_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHA2_60/3_192", WC_XMSSMT_OID_SHA2_60_3_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHA2_60/6_192", WC_XMSSMT_OID_SHA2_60_6_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHA2_60/12_192", WC_XMSSMT_OID_SHA2_60_12_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHA256, 24, 4, 60, 12, 8, 0, 0), }, +#endif +#endif /* HASH_SIZE 192 */ +#endif /* WC_XMSS_SHA256 */ + +#ifdef WC_XMSS_SHAKE256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 256 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 256 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHAKE256_20/2_256", WC_XMSSMT_OID_SHAKE256_20_2_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHAKE256_20/4_256", WC_XMSSMT_OID_SHAKE256_20_4_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHAKE256_40/2_256", WC_XMSSMT_OID_SHAKE256_40_2_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHAKE256_40/4_256", WC_XMSSMT_OID_SHAKE256_40_4_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHAKE256_40/8_256", WC_XMSSMT_OID_SHAKE256_40_8_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHAKE256_60/3_256", WC_XMSSMT_OID_SHAKE256_60_3_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHAKE256_60/6_256", WC_XMSSMT_OID_SHAKE256_60_6_256 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHAKE256_60/12_256", WC_XMSSMT_OID_SHAKE256_60_12_256, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 32, 32, 60, 12, 8, 0, 0), }, +#endif +#endif /* HASH_SIZE 256 */ +#endif /* WC_XMSS_SHAKE256 */ + +#ifdef WC_XMSS_SHAKE256 +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192 +#if WOLFSSL_XMSS_MIN_HEIGHT <= 20 && WOLFSSL_XMSS_MAX_HEIGHT >= 20 + { "XMSSMT-SHAKE256_20/2_192", WC_XMSSMT_OID_SHAKE256_20_2_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 20, 2, 3, 2, 4), }, + { "XMSSMT-SHAKE256_20/4_192", WC_XMSSMT_OID_SHAKE256_20_4_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 20, 4, 3, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 40 && WOLFSSL_XMSS_MAX_HEIGHT >= 40 + { "XMSSMT-SHAKE256_40/2_192", WC_XMSSMT_OID_SHAKE256_40_2_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 40, 2, 5, 2, 4), }, + { "XMSSMT-SHAKE256_40/4_192", WC_XMSSMT_OID_SHAKE256_40_4_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 40, 4, 5, 2, 4), }, + { "XMSSMT-SHAKE256_40/8_192", WC_XMSSMT_OID_SHAKE256_40_8_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 40, 8, 5, 0, 0), }, +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 60 && WOLFSSL_XMSS_MAX_HEIGHT >= 60 + { "XMSSMT-SHAKE256_60/3_192", WC_XMSSMT_OID_SHAKE256_60_3_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 60, 3, 8, 2, 4), }, + { "XMSSMT-SHAKE256_60/6_192", WC_XMSSMT_OID_SHAKE256_60_6_192 , + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 60, 6, 8, 2, 4), }, + { "XMSSMT-SHAKE256_60/12_192", WC_XMSSMT_OID_SHAKE256_60_12_192, + XMSS_PARAMS(WC_HASH_TYPE_SHAKE256, 24, 4, 60, 12, 8, 0, 0), }, #endif +#endif /* HASH_SIZE 192 */ +#endif /* WC_XMSS_SHAKE256 */ +}; +/* Length of array of known XMSS^MT algorithms. */ +#define WC_XMSSMT_ALG_LEN (sizeof(wc_xmssmt_alg) / sizeof(*wc_xmssmt_alg)) +#endif + +/* Convert XMSS^MT algorithm string to an OID - object identifier. + * + * @param [out] oid OID value corresponding to string. + * @param [in] s String to convert. + * @param [out] params XMSS/MT parameters. + * @return 0 on success. + * @return NOT_COMPILED_IN on failure. + */ +static int wc_xmssmt_str_to_params(const char *s, word32* oid, + const XmssParams** params) +{ + int ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); +#if WOLFSSL_XMSS_MAX_HEIGHT >= 20 + unsigned int i; + + ret = WC_NO_ERR_TRACE(NOT_COMPILED_IN); + for (i = 0; i < WC_XMSSMT_ALG_LEN; i++) { + if (XSTRCMP(s, wc_xmssmt_alg[i].str) == 0) { + *oid = wc_xmssmt_alg[i].oid; + *params = &wc_xmssmt_alg[i].params; + ret = 0; + break; + } + } +#else + (void)s; + (void)oid; + (void)params; + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/*************************** + * OTHER Internal APIs + ***************************/ + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY +/* Allocates the XMSS secret key (sk) array. + * + * The XMSS/XMSS^MT secret key length is a function of the + * parameters, and can't be allocated until the param string + * has been set with SetParamStr. + * + * This is only called by MakeKey() and Reload(). + * + * Note: the XMSS sk array is force zeroed after every use. + * + * @param [in] key The XMSS key. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_FUNC_ARG when private key already allocated. + * @return MEMORY_E when allocating dynamic memory fails. + */ +static int wc_xmsskey_alloc_sk(XmssKey* key) +{ + int ret = 0; + + /* Validate parameter. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + /* Ensure the private key doesn't exist. */ + else if (key->sk != NULL) { + WOLFSSL_MSG("error: XMSS secret key already exists"); + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* The XMSS/XMSS^MT secret key length is a function of the + * parameters. Therefore can't allocate this until param + * string has been set. */ + ret = wc_XmssKey_GetPrivLen(key, &key->sk_len); + } + if (ret == 0) { + /* Allocate a buffer to hold secret key. */ + key->sk = (unsigned char *)XMALLOC(key->sk_len, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (key->sk == NULL) { + WOLFSSL_MSG("error: malloc XMSS key->sk failed"); + ret = MEMORY_E; + } + } + + if (ret == 0) { + /* Zeroize private key buffer. */ + ForceZero(key->sk, key->sk_len); + } + + return ret; +} + +/* Signs the message using the XMSS secret key, and + * updates the secret key on NV storage. + * + * Both operations must succeed to be considered + * successful. + * + * On success: sets key state to WC_XMSS_STATE_OK. + * On failure: sets key state to WC_XMSS_STATE_BAD + * + * If no signatures are left, sets state to WC_XMSS_STATE_NOSIGS. + * + * @return IO_FAILED_E when reading or writing private key failed. + * @return KEY_EXHAUSTED_E when no more keys in private key available. + * @return BAD_COND_E when generated signature length is invalid. + */ +static WC_INLINE int wc_xmsskey_signupdate(XmssKey* key, byte* sig, + const byte* msg, int msgLen) +{ + int ret = 0; + enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE; + + /* Set the key state to bad by default. State is presumed bad unless a + * correct sign and update operation happen together. */ + key->state = WC_XMSS_STATE_BAD; + + /* Read the current secret key from NV storage.*/ + cb_rc = key->read_private_key(key->sk, key->sk_len, key->context); + if (cb_rc != WC_XMSS_RC_READ_TO_MEMORY) { + /* Read from NV storage failed. */ + WOLFSSL_MSG("error: XMSS read_private_key failed"); + ret = IO_FAILED_E; + } + + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + XmssState* state; + #else + XmssState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + state = XMALLOC(sizeof(XmssState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize state for use in signing. */ + ret = wc_xmss_state_init(state, key->params); + if (ret == 0) { + /* Read was good. Now sign and update the secret key in memory. + */ + #ifndef WOLFSSL_WC_XMSS_SMALL + if (key->is_xmssmt) { + ret = wc_xmssmt_sign(state, msg, msgLen, key->sk, sig); + } + else { + ret = wc_xmss_sign(state, msg, msgLen, key->sk, sig); + } + #else + ret = wc_xmssmt_sign(state, msg, msgLen, key->sk, sig); + #endif + if (ret == WC_NO_ERR_TRACE(KEY_EXHAUSTED_E)) { + /* Signature space exhausted. */ + key->state = WC_XMSS_STATE_NOSIGS; + WOLFSSL_MSG("error: no XMSS signatures remaining"); + } + else if (ret != 0) { + /* Something failed or inconsistent in signature. Erase the + * signature just to be safe. */ + ForceZero(sig, key->params->sig_len); + WOLFSSL_MSG("error: XMSS sign failed"); + } + /* Free state after use. */ + wc_xmss_state_free(state); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + + if (ret == 0) { + /* The signature succeeded. key->sk is now updated and must be + * committed to NV storage. */ + cb_rc = key->write_private_key(key->sk, key->sk_len, key->context); + if (cb_rc != WC_XMSS_RC_SAVED_TO_NV_MEMORY) { + /* Write to NV storage failed. Erase the signature from + * memory. */ + ForceZero(sig, key->params->sig_len); + WOLFSSL_MSG("error: XMSS write_private_key failed"); + ret = IO_FAILED_E; + } + } + if (ret == 0) { + /* key->sk was successfully committed to NV storage. Set the + * key state to OK, and set the sigLen. */ + key->state = WC_XMSS_STATE_OK; + } + + /* Force zero the secret key from memory always. */ + ForceZero(key->sk, key->sk_len); + + return ret; +} +#endif /* !WOLFSSL_XMSS_VERIFY_ONLY */ + +/*************************** + * PUBLIC API + ***************************/ + +/* Init an XMSS key. + * + * Call this before setting the parms of an XMSS key. + * + * @param [in] key The XMSS key to init. + * @param [in] heap Unused. + * @param [in] devId Unused. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + */ +int wc_XmssKey_Init(XmssKey* key, void* heap, int devId) +{ + int ret = 0; + + (void) heap; + (void) devId; + + /* Validate parameters. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Zeroize key and set state to initialized. */ + ForceZero(key, sizeof(XmssKey)); + key->state = WC_XMSS_STATE_INITED; + } + + return ret; +} + +/* Set the XMSS key parameter string. + * + * The input string must be one of the supported parm set names in + * the "Name" section from the table in wolfssl/wolfcrypt/xmss.h, + * e.g. "XMSS-SHA2_10_256" or "XMSSMT-SHA2_20/4_256". + * + * @param [in] key The XMSS key to set. + * @param [in] str The XMSS/XMSS^MT parameter string. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_FUNC_ARG when string not recognized. + * @return BAD_STATE_E when wrong state for operation. + * @return NOT_COMPILED_IN when string not supported. + */ +int wc_XmssKey_SetParamStr(XmssKey* key, const char* str) +{ + int ret = 0; + word32 oid = 0; + int is_xmssmt = 0; + + /* Validate parameters. */ + if ((key == NULL) || (str == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* Validate state. */ + if ((ret == 0) && (key->state != WC_XMSS_STATE_INITED)) { + WOLFSSL_MSG("error: XMSS key needs init"); + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Check which type of algorithm the string is for. */ + is_xmssmt = (XMEMCMP(str, "XMSS-", 5) != 0); + + /* Convert XMSS param string to OID. */ + if (is_xmssmt) { + ret = wc_xmssmt_str_to_params(str, &oid, &key->params); + } + else { + ret = wc_xmss_str_to_params(str, &oid, &key->params); + } + if (ret != 0) { + WOLFSSL_MSG("error: xmssmt_str_to_params failed"); + ret = BAD_FUNC_ARG; + } + } + + if (ret == 0) { + /* Set key info. */ + key->oid = oid; + key->is_xmssmt = is_xmssmt; + key->state = WC_XMSS_STATE_PARMSET; + } + + return ret; +} + +/* Force zeros and frees the XMSS key from memory. + * + * This does not touch the private key saved to non-volatile storage. + * + * This is the only function that frees the key->sk array. + * + * @param [in] key XMSS key. + */ +void wc_XmssKey_Free(XmssKey* key) +{ + /* Validate parameter. */ + if (key != NULL) { + #ifndef WOLFSSL_XMSS_VERIFY_ONLY + if (key->sk != NULL) { + /* Zeroize private key. */ + ForceZero(key->sk, key->sk_len); + XFREE(key->sk, NULL, DYNAMIC_TYPE_TMP_BUFFER); + key->sk = NULL; + key->sk_len = 0; + } + #endif /* !WOLFSSL_XMSS_VERIFY_ONLY */ + + /* Ensure all data is zeroized. */ + ForceZero(key, sizeof(XmssKey)); + + /* Set the state to freed. */ + key->state = WC_XMSS_STATE_FREED; + } +} + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY +/* Sets the XMSS write private key callback. + * + * The callback must be able to write/update the private key to + * non-volatile storage. + * + * @param [in] key The XMSS key. + * @param [in] write_cb The write private key callback. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_STATE_E when wrong state for operation. + */ +int wc_XmssKey_SetWriteCb(XmssKey* key, wc_xmss_write_private_key_cb write_cb) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (write_cb == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Changing the write callback of an already working key is forbidden. */ + else if (key->state == WC_XMSS_STATE_OK) { + WOLFSSL_MSG("error: wc_XmssKey_SetWriteCb: key in use"); + ret = BAD_STATE_E; + } + else { + /* Set write callback for storing private key. */ + key->write_private_key = write_cb; + } + + return ret; +} + +/* Sets the XMSS read private key callback. + * + * The callback must be able to read the private key from + * non-volatile storage. + * + * @param [in] key The XMSS key. + * @param [in] read_cb The read private key callback. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_STATE_E when wrong state for operation. + */ +int wc_XmssKey_SetReadCb(XmssKey* key, wc_xmss_read_private_key_cb read_cb) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (read_cb == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Changing the read callback of an already working key is forbidden. */ + else if (key->state == WC_XMSS_STATE_OK) { + WOLFSSL_MSG("error: wc_XmssKey_SetReadCb: key in use"); + ret = BAD_STATE_E; + } + else { + /* Set write callback for getting private key. */ + key->read_private_key = read_cb; + } + + return ret; +} + +/* Sets the XMSS context to be used by write and read callbacks. + * + * E.g. this could be a filename if the callbacks write/read to file. + * + * @param [in] key The XMSS key. + * @param [in] context The context pointer. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_STATE_E when wrong state for operation. + */ +int wc_XmssKey_SetContext(XmssKey* key, void* context) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (context == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Setting context of an already working key is forbidden. */ + else if (key->state == WC_XMSS_STATE_OK) { + WOLFSSL_MSG("error: wc_XmssKey_SetContext: key in use"); + ret = BAD_STATE_E; + } + else { + /* Set read/write callback context for accessing the private key. */ + key->context = context; + } + + return ret; +} + +/* Make the XMSS/XMSS^MT private/public key pair. The key must have its + * parameters set before calling this. + * + * Write/read callbacks, and context data, must be set prior. + * Key must have parameters set. + * + * This function and Reload() are the only functions that allocate + * key->sk array. wc_XmssKey_FreeKey is the only function that + * deallocates key->sk. + * + * @param [in] key The XMSS key to make. + * @param [in] rng Initialized WC_RNG pointer. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_FUNC_ARG when a write private key is not set. + * @return BAD_FUNC_ARG when a read/write private key context is not set. + * @return BAD_FUNC_ARG when private key already allocated. + * @return MEMORY_E when allocating dynamic memory fails. + * @return BAD_STATE_E when wrong state for operation. + * @return IO_FAILED_E when writing private key failed. + * @return Other negative when random number generation failed. + */ +int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG* rng) +{ + int ret = 0; + enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE; +#ifdef WOLFSSL_SMALL_STACK + unsigned char* seed = NULL; +#else + unsigned char seed[3 * WC_XMSS_MAX_N]; +#endif + + /* Validate parameters */ + if ((key == NULL) || (rng == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && (key->state != WC_XMSS_STATE_PARMSET)) { + WOLFSSL_MSG("error: XmssKey not ready for generation"); + ret = BAD_STATE_E; + } + /* Ensure write callback available. */ + if ((ret == 0) && (key->write_private_key == NULL)) { + WOLFSSL_MSG("error: XmssKey write callback is not set"); + ret = BAD_FUNC_ARG; + } + /* Ensure read/write callback context available. */ + if ((ret == 0) && (key->context == NULL)) { + WOLFSSL_MSG("error: XmssKey context is not set"); + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Allocate sk array. */ + ret = wc_xmsskey_alloc_sk(key); + } +#ifdef WOLFSSL_SMALL_STACK + if (ret == 0) { + seed = (unsigned char*)XMALLOC(3 * key->params->n, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (seed == NULL) { + ret = MEMORY_E; + } + } +#endif + + if (ret == 0) { + /* Generate three random seeds. */ + ret = wc_RNG_GenerateBlock(rng, seed, 3 * key->params->n); + } + + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + XmssState* state; + #else + XmssState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + state = XMALLOC(sizeof(XmssState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize state for use in key generation. */ + ret = wc_xmss_state_init(state, key->params); + if (ret == 0) { + /* Finally make the private/public key pair. Immediately write + * it to NV storage and then clear from memory. */ + #ifndef WOLFSSL_WC_XMSS_SMALL + if (key->is_xmssmt) { + ret = wc_xmssmt_keygen(state, seed, key->sk, key->pk); + } + else { + ret = wc_xmss_keygen(state, seed, key->sk, key->pk); + } + #else + ret = wc_xmssmt_keygen(state, seed, key->sk, key->pk); + #endif + if (ret != 0) { + WOLFSSL_MSG("error: XMSS keygen failed"); + key->state = WC_XMSS_STATE_BAD; + } + /* Free state after use. */ + wc_xmss_state_free(state); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + + if (ret == 0) { + /* Write out private key. */ + cb_rc = key->write_private_key(key->sk, key->sk_len, key->context); + /* Zeroize private key data whether it was saved or not. */ + ForceZero(key->sk, key->sk_len); + /* Check writing succeeded. */ + if (cb_rc != WC_XMSS_RC_SAVED_TO_NV_MEMORY) { + WOLFSSL_MSG("error: XMSS write to NV storage failed"); + key->state = WC_XMSS_STATE_BAD; + ret = IO_FAILED_E; + } + } + + if (ret == 0) { + key->state = WC_XMSS_STATE_OK; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + +/* This function allocates the secret key buffer, and does a + * quick sanity check to verify the secret key is readable + * from NV storage, and then force zeros the key from memory. + * + * On success it sets the key state to OK. + * + * Use this function to resume signing with an already existing + * XMSS key pair. + * + * Write/read callbacks, and context data, must be set prior. + * Key must have parameters set. + * + * This function and MakeKey are the only functions that allocate + * key->sk array. wc_XmssKey_FreeKey is the only function that + * deallocates key->sk. + * + * @params [in] key XMSS key to load. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_FUNC_ARG when a read or write function is not set. + * @return BAD_FUNC_ARG when a read/write function context is not set. + * @return BAD_FUNC_ARG when private key already allocated. + * @return MEMORY_E when allocating dynamic memory fails. + * @return BAD_STATE_E when wrong state for operation. + * @return IO_FAILED_E when reading private key failed. + */ +int wc_XmssKey_Reload(XmssKey* key) +{ + int ret = 0; + enum wc_XmssRc cb_rc = WC_XMSS_RC_NONE; + + /* Validate parameter. */ + if (key == NULL) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && (key->state != WC_XMSS_STATE_PARMSET)) { + WOLFSSL_MSG("error: XmssKey not ready for reload"); + ret = BAD_STATE_E; + } + /* Ensure read and write callbacks are available. */ + if ((ret == 0) && ((key->write_private_key == NULL) || + (key->read_private_key == NULL))) { + WOLFSSL_MSG("error: XmssKey write/read callbacks are not set"); + ret = BAD_FUNC_ARG; + } + /* Ensure read and write callback context is available. */ + if ((ret == 0) && (key->context == NULL)) { + WOLFSSL_MSG("error: XmssKey context is not set"); + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Allocate sk array. */ + ret = wc_xmsskey_alloc_sk(key); + } + + if (ret == 0) { + /* Read the current secret key from NV storage. Force clear it + * immediately. This is just to sanity check the secret key + * is readable from permanent storage. */ + cb_rc = key->read_private_key(key->sk, key->sk_len, key->context); + ForceZero(key->sk, key->sk_len); + /* Check reading succeeded. */ + if (cb_rc != WC_XMSS_RC_READ_TO_MEMORY) { + WOLFSSL_MSG("error: XMSS read from NV storage failed"); + key->state = WC_XMSS_STATE_BAD; + ret = IO_FAILED_E; + } + } + if (ret == 0) { + key->state = WC_XMSS_STATE_OK; + } + + return ret; +} + +/* Gets the XMSS/XMSS^MT private key length. + * + * Parameters must be set before calling this, as the key size (sk_len) + * is a function of the parameters. + * + * Note: the XMSS/XMSS^MT private key format is implementation specific, + * and not standardized. Interoperability of XMSS private keys should + * not be expected. + * + * @param [in] key XMSS key. + * @param [out] len Length of the private key in bytes. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_STATE_E when wrong state for operation. + * */ +int wc_XmssKey_GetPrivLen(const XmssKey* key, word32* len) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (len == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && ((key->state != WC_XMSS_STATE_OK) && + (key->state != WC_XMSS_STATE_PARMSET))) { + /* params->sk_len not set yet. */ + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Calculate private key length: OID + private key bytes. */ + *len = XMSS_OID_LEN + (word32)key->params->sk_len; + } + + return ret; +} + +/* Sign the message using the XMSS secret key. + * + * @param [in] key XMSS key to use to sign. + * @param [in] sig Buffer to write signature into. + * @param [in, out] sigLen On in, size of buffer. + * On out, the length of the signature in bytes. + * @param [in] msg Message to sign. + * @param [in] msgLen Length of the message in bytes. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_FUNC_ARG when a write private key is not set. + * @return BAD_FUNC_ARG when a read/write private key context is not set. + * @return BAD_STATE_E when wrong state for operation. + * @return BUFFER_E when sigLen is too small. + * @return IO_FAILED_E when reading or writing private key failed. + * @return KEY_EXHAUSTED_E when no more keys in private key available. + * @return BAD_COND_E when generated signature length is invalid. + */ +int wc_XmssKey_Sign(XmssKey* key, byte* sig, word32* sigLen, const byte* msg, + int msgLen) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (sig == NULL) || (sigLen == NULL) || (msg == NULL) || + (msgLen <= 0)) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && (key->state == WC_XMSS_STATE_NOSIGS)) { + WOLFSSL_MSG("error: XMSS signatures exhausted"); + ret = BAD_STATE_E; + } + if ((ret == 0) && (key->state != WC_XMSS_STATE_OK)) { + /* The key had an error the last time it was used, and we + * can't guarantee its state. */ + WOLFSSL_MSG("error: can't sign, XMSS key not in good state"); + ret = BAD_STATE_E; + } + /* Check signature buffer size. */ + if ((ret == 0) && (*sigLen < key->params->sig_len)) { + /* Signature buffer too small. */ + WOLFSSL_MSG("error: XMSS sig buffer too small"); + ret = BUFFER_E; + } + /* Check read and write callbacks available. */ + if ((ret == 0) && ((key->write_private_key == NULL) || + (key->read_private_key == NULL))) { + WOLFSSL_MSG("error: XmssKey write/read callbacks are not set"); + ret = BAD_FUNC_ARG; + } + /* Check read/write callback context available. */ + if ((ret == 0) && (key->context == NULL)) { + WOLFSSL_MSG("error: XmssKey context is not set"); + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + *sigLen = key->params->sig_len; + /* Finally, sign and update the secret key. */ + ret = wc_xmsskey_signupdate(key, sig, msg, msgLen); + } + + return ret; +} + +/* Check if more signatures are possible with key. + * + * @param [in] key XMSS key to check. + * @return 1 when signatures possible. + * @return 0 when key exhausted. + */ +int wc_XmssKey_SigsLeft(XmssKey* key) +{ + int ret; + + /* Validate parameter. */ + if (key == NULL) { + ret = 0; + } + /* Validate state. */ + else if (key->state == WC_XMSS_STATE_NOSIGS) { + WOLFSSL_MSG("error: XMSS signatures exhausted"); + ret = 0; + } + else if (key->state != WC_XMSS_STATE_OK) { + WOLFSSL_MSG("error: can't sign, XMSS key not in good state"); + ret = 0; + } + /* Read the current secret key from NV storage.*/ + else if (key->read_private_key(key->sk, key->sk_len, key->context) != + WC_XMSS_RC_READ_TO_MEMORY) { + WOLFSSL_MSG("error: XMSS read_private_key failed"); + ret = 0; + } + else { + /* Ask implementation to check index in private key. */ + ret = wc_xmss_sigsleft(key->params, key->sk); + } + + return ret; +} +#endif /* !WOLFSSL_XMSS_VERIFY_ONLY*/ + +/* Get the XMSS/XMSS^MT public key length. + * + * The public key is static in size and does not depend on parameters, + * other than the choice of SHA256 as hashing function. + * + * @param [in] key XMSS key. + * @param [out] len Length of the public key. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return NOT_COMPILED_IN when a hash algorithm not supported. + */ +int wc_XmssKey_GetPubLen(const XmssKey* key, word32* len) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (len == NULL)) { + ret = BAD_FUNC_ARG; + } + else { + *len = XMSS_OID_LEN + key->params->pk_len; + } + + return ret; +} + +/* Export public key and parameters from one XmssKey to another. + * + * Use this to prepare a signature verification XmssKey that is pub only. + * + * @param [out] keyDst Destination key for copy. + * @param [in] keySrc Source key for copy. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a key is NULL. + * @return Other negative when digest algorithm initialization failed. + */ +int wc_XmssKey_ExportPub(XmssKey* keyDst, const XmssKey* keySrc) +{ + int ret = 0; + + /* Validate parameters. */ + if ((keyDst == NULL) || (keySrc == NULL)) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* Zeroize the new key. */ + ForceZero(keyDst, sizeof(XmssKey)); + + /* Copy over the public key. */ + XMEMCPY(keyDst->pk, keySrc->pk, sizeof(keySrc->pk)); + + /* Copy over the key info. */ + keyDst->oid = keySrc->oid; + keyDst->is_xmssmt = keySrc->is_xmssmt; + keyDst->params = keySrc->params; + } + if (ret == 0) { + /* Mark keyDst as verify only, to prevent misuse. */ + keyDst->state = WC_XMSS_STATE_VERIFYONLY; + } + + return 0; +} + +/* Exports the raw XMSS public key buffer from key to out buffer. + * + * The out buffer should be large enough to hold the public key, and + * outLen should indicate the size of the buffer. + * + * @param [in] key XMSS key. + * @param [out] out Array holding public key. + * @param [in, out] outLen On in, size of buffer. + * On out, the length of the public key. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BUFFER_E if array is too small. + */ +int wc_XmssKey_ExportPubRaw(const XmssKey* key, byte* out, word32* outLen) +{ + int ret = 0; + word32 pubLen = 0; + + /* Validate parameters. */ + if ((key == NULL) || (out == NULL) || (outLen == NULL)) { + ret = BAD_FUNC_ARG; + } + + /* Get the public key length. */ + if (ret == 0) { + ret = wc_XmssKey_GetPubLen(key, &pubLen); + } + /* Check the output buffer is large enough. */ + if ((ret == 0) && (*outLen < pubLen)) { + ret = BUFFER_E; + } + + if (ret == 0) { + int i = 0; + /* First copy the oid into buffer. */ + for (; i < XMSS_OID_LEN; i++) { + out[XMSS_OID_LEN - i - 1] = (key->oid >> (8 * i)) & 0xFF; + } + /* Copy the public key data into buffer after oid. */ + XMEMCPY(out + XMSS_OID_LEN, key->pk, pubLen - XMSS_OID_LEN); + /* Return actual public key length. */ + *outLen = pubLen; + } + + return ret; +} + +/* Imports a raw public key buffer from in array to XmssKey key. + * + * The XMSS parameters must be set first with wc_XmssKey_SetParamStr, + * and inLen must match the length returned by wc_XmssKey_GetPubLen. + * + * @param [in, out] key XMSS key. + * @param [in] in Array holding public key. + * @param [in] inLen Length of array in bytes. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BUFFER_E if array is incorrect size. + * @return BAD_STATE_E when wrong state for operation. + * */ +int wc_XmssKey_ImportPubRaw(XmssKey* key, const byte* in, word32 inLen) +{ + int ret = 0; + word32 pubLen = 0; + + /* Validate parameters. */ + if ((key == NULL) || (in == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && (key->state != WC_XMSS_STATE_PARMSET)) { + /* XMSS key not ready for import. Param str must be set first. */ + WOLFSSL_MSG("error: XMSS key not ready for import"); + ret = BAD_STATE_E; + } + + /* Get the public key length. */ + if (ret == 0) { + ret = wc_XmssKey_GetPubLen(key, &pubLen); + } + /* Check the input buffer is the right size. */ + if ((ret == 0) && (inLen != pubLen)) { + /* Something inconsistent. Parameters weren't set, or input + * pub key is wrong.*/ + ret = BUFFER_E; + } + + if (ret == 0) { + /* Copy the public key data into key. */ + XMEMCPY(key->pk, in + XMSS_OID_LEN, pubLen - XMSS_OID_LEN); + + /* Update state to verify-only as we don't have a private key. */ + key->state = WC_XMSS_STATE_VERIFYONLY; + } + + return ret; +} + +/* Gets the XMSS/XMSS^MT signature length. + * + * Parameters must be set before calling this, as the signature size + * is a function of the parameters. + * + * Note: call this before wc_XmssKey_Sign or Verify so you know the + * length of the required signature buffer. + * + * @param [in] key XMSS key to use to sign. + * @param [out] len The length of the signature in bytes. + * + * @return 0 on success. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_STATE_E when wrong state for operation. + * */ +int wc_XmssKey_GetSigLen(const XmssKey* key, word32* len) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (len == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && (key->state != WC_XMSS_STATE_OK) && + (key->state != WC_XMSS_STATE_PARMSET)) { + ret = BAD_STATE_E; + } + + if (ret == 0) { + /* Return the calculated signature length. */ + *len = key->params->sig_len; + } + + return ret; +} + +/* Verify the signature using the XMSS public key. + * + * Requires that XMSS parameters have been set with + * wc_XmssKey_SetParamStr, and that a public key is available + * from importing or MakeKey(). + * + * Call wc_XmssKey_GetSigLen() before this function to determine + * length of the signature buffer. + * + * @param [in] key XMSS key to use to verify. + * @param [in] sig Signature to verify. + * @param [in] sigLen Size of signature in bytes. + * @param [in] m Message to verify. + * @param [in] mLen Length of the message in bytes. + * + * @return 0 on success. + * @return SIG_VERIFY_E when signature did not verify message. + * @return BAD_FUNC_ARG when a parameter is NULL. + * @return BAD_STATE_E when wrong state for operation. + * @return BUFFER_E when sigLen is too small. + */ +int wc_XmssKey_Verify(XmssKey* key, const byte* sig, word32 sigLen, + const byte* m, int mLen) +{ + int ret = 0; + + /* Validate parameters. */ + if ((key == NULL) || (sig == NULL) || (m == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Validate state. */ + if ((ret == 0) && (key->state != WC_XMSS_STATE_OK) && + (key->state != WC_XMSS_STATE_VERIFYONLY)) { + /* XMSS key not ready for verification. Param str must be + * set first, and Reload() called. */ + WOLFSSL_MSG("error: XMSS key not ready for verification"); + ret = BAD_STATE_E; + } + /* Check the signature is the big enough. */ + if ((ret == 0) && (sigLen < key->params->sig_len)) { + /* Signature buffer too small. */ + ret = BUFFER_E; + } + + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + XmssState* state; + #else + XmssState state[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + state = XMALLOC(sizeof(XmssState), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (state == NULL) { + ret = MEMORY_E; + } + if (ret == 0) + #endif + { + /* Initialize state for use in verification. */ + ret = wc_xmss_state_init(state, key->params); + if (ret == 0) { + /* Verify using either XMSS^MT function as it works for both. */ + ret = wc_xmssmt_verify(state, m, mLen, sig, key->pk); + /* Free state after use. */ + wc_xmss_state_free(state); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(state, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + } + + return ret; +} + +#endif /* WOLFSSL_HAVE_XMSS */ diff --git a/src/wolfcrypt/src/wc_xmss_impl.c b/src/wolfcrypt/src/wc_xmss_impl.c index 4a91f99..b45bc59 100644 --- a/src/wolfcrypt/src/wc_xmss_impl.c +++ b/src/wolfcrypt/src/wc_xmss_impl.c @@ -19,8 +19,4321 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/* Based on: + * o RFC 8391 - XMSS: eXtended Merkle Signature Scheme + * o [HDSS] "Hash-based Digital Signature Schemes", Buchmann, Dahmen and Szydlo + * from "Post Quantum Cryptography", Springer 2009. + * o [OPX] "Optimal Parameters for XMSS^MT", Hulsing, Rausch and Buchmann + * + * TODO: "Simple and Memory-efficient Signature Generation of XMSS^MT" + * (https://ece.engr.uvic.ca/~raltawy/SAC2021/9.pdf) + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + #include +#include +#include + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_XMSS) + +/* Indices into Hash Address. */ +#define XMSS_ADDR_LAYER 0 +#define XMSS_ADDR_TREE_HI 1 +#define XMSS_ADDR_TREE 2 +#define XMSS_ADDR_TYPE 3 +#define XMSS_ADDR_OTS 4 +#define XMSS_ADDR_LTREE 4 +#define XMSS_ADDR_TREE_ZERO 4 +#define XMSS_ADDR_CHAIN 5 +#define XMSS_ADDR_TREE_HEIGHT 5 +#define XMSS_ADDR_HASH 6 +#define XMSS_ADDR_TREE_INDEX 6 +#define XMSS_ADDR_KEY_MASK 7 + +/* Types of hash addresses. */ +#define WC_XMSS_ADDR_TYPE_OTS 0 +#define WC_XMSS_ADDR_TYPE_LTREE 1 +#define WC_XMSS_ADDR_TYPE_TREE 2 + +/* Byte to include in hash to create unique sequence. */ +#define XMSS_HASH_PADDING_F 0 +#define XMSS_HASH_PADDING_H 1 +#define XMSS_HASH_PADDING_HASH 2 +#define XMSS_HASH_PADDING_PRF 3 +#define XMSS_HASH_PADDING_PRF_KEYGEN 4 + +/* Fixed parameter values. */ +#define XMSS_WOTS_W 16 +#define XMSS_WOTS_LOG_W 4 +#define XMSS_WOTS_LEN2 3 +#define XMSS_CSUM_SHIFT 4 +#define XMSS_CSUM_LEN 2 + +/* Length of the message to the PRF. */ +#define XMSS_PRF_M_LEN 32 + +/* Length of index encoding when doing XMSS. */ +#define XMSS_IDX_LEN 4 + +/* Size of the N when using SHA-256 and 32 byte padding. */ +#define XMSS_SHA256_32_N WC_SHA256_DIGEST_SIZE +/* Size of the padding when using SHA-256 and 32 byte padding. */ +#define XMSS_SHA256_32_PAD_LEN 32 + +/* Calculate PRF data length for parameters. */ +#define XMSS_HASH_PRF_DATA_LEN(params) \ + ((params)->pad_len + (params)->n + WC_XMSS_ADDR_LEN) +/* PRF data length when using SHA-256 with 32 byte padding. */ +#define XMSS_HASH_PRF_DATA_LEN_SHA256_32 \ + (XMSS_SHA256_32_PAD_LEN + XMSS_SHA256_32_N + WC_XMSS_ADDR_LEN) + +/* Calculate chain hash data length for parameters. */ +#define XMSS_CHAIN_HASH_DATA_LEN(params) \ + ((params)->pad_len + 2 * (params)->n) +/* Chain hash data length when using SHA-256 with 32 byte padding. */ +#define XMSS_CHAIN_HASH_DATA_LEN_SHA256_32 \ + (XMSS_SHA256_32_PAD_LEN + 2 * XMSS_SHA256_32_N) + +/* Calculate rand hash data length for parameters. */ +#define XMSS_RAND_HASH_DATA_LEN(params) \ + ((params)->pad_len + 3 * (params)->n) +/* Rand hash data length when using SHA-256 with 32 byte padding. */ +#define XMSS_RAND_HASH_DATA_LEN_SHA256_32 \ + (XMSS_SHA256_32_PAD_LEN + 3 * XMSS_SHA256_32_N) + +/* Encode pad value into byte array. Front fill with 0s. + * + * RFC 8391: 2.4 + * + * @param [in] n Number to encode. + * @param [out] a Array to hold encoding. + * @param [in] l Length of array. + */ +#define XMSS_PAD_ENC(n, a, l) \ +do { \ + XMEMSET(a, 0, l); \ + (a)[(l) - 1] = (n); \ +} while (0) + + +/******************************************** + * Index 32/64 bits + ********************************************/ + +/* Index of 32 or 64 bits. */ +typedef union wc_Idx { +#if WOLFSSL_XMSS_MAX_HEIGHT > 32 + /* 64-bit representation. */ + w64wrapper u64; +#endif +#if WOLFSSL_XMSS_MIN_HEIGHT <= 32 + /* 32-bit representation. */ + word32 u32; +#endif +} wc_Idx; + +#if WOLFSSL_XMSS_MAX_HEIGHT > 32 +/* Set index to zero. + * + * Index is up to 64-bits. + * + * @param [out] idx 32/64-bit index to zero. + */ +#define WC_IDX_ZERO(idx) w64Zero(&(idx).u64) +#else +/* Set index to zero. + * + * Index is no more than 32-bits. + * + * @param [out] idx 32/64-bit index to zero. + */ +#define WC_IDX_ZERO(idx) idx.u32 = 0 +#endif + +#if WOLFSSL_XMSS_MAX_HEIGHT > 32 +/* Decode 64-bit index. + * + * @param [out] i Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define IDX64_DECODE(i, c, a, ret) \ + if ((c) == 5) { \ + word32 t; \ + ato32((a) + 1, &t); \ + (i) = w64From32((a)[0], t); \ + } \ + else if ((c) == 8) { \ + ato64(a, &(i)); \ + } + +/* Decode 64-bit index. + * + * @param [out] i Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define XMSS_IDX64_DECODE(i, c, a, ret) \ +do { \ + IDX64_DECODE(i, c, a, ret) \ + else { \ + (ret) = NOT_COMPILED_IN; \ + } \ +} while (0) + +/* Check whether index is valid. + * + * @param [in] i Index to check. + * @param [in] c Count of bytes i was encoded in. + * @param [in] h Full tree Height. + */ +#define IDX64_INVALID(i, c, h) \ + ((w64GetHigh32(w64Add32(i, 1, NULL)) >> ((h) - 32)) != 0) + +/* Set 64-bit index as hash address value for tree. + * + * @param [in] i Index to set. + * @param [in] c Count of bytes to encode into. + * @param [in] h Height of tree. + * @param [out] a Hash address to encode into. + * @param [out] l Index of leaf. + */ +#define IDX64_SET_ADDR_TREE(i, c, h, a, l) \ + if ((c) > 4) { \ + (l) = w64GetLow32(i) & (((word32)1 << (h)) - 1);\ + (i) = w64ShiftRight(i, h); \ + (a)[XMSS_ADDR_TREE_HI] = w64GetHigh32(i); \ + (a)[XMSS_ADDR_TREE] = w64GetLow32(i); \ + } +#endif /* WOLFSSL_XMSS_MAX_HEIGHT > 32 */ + +#if WOLFSSL_XMSS_MIN_HEIGHT <= 32 +/* Decode 32-bit index. + * + * @param [out] i Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define IDX32_DECODE(i, c, a, ret) \ + if ((c) == 4) { \ + ato32(a, &(i)); \ + } \ + else if ((c) == 3) { \ + ato24(a, &(i)); \ + } + +/* Decode 32-bit index. + * + * @param [out] i Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define XMSS_IDX32_DECODE(i, c, a, ret) \ +do { \ + IDX32_DECODE(i, c, a, ret) \ + else { \ + (ret) = NOT_COMPILED_IN; \ + } \ +} while (0) + +/* Check whether 32-bit index is valid. + * + * @param [in] i Index to check. + * @param [in] c Count of bytes i was encoded in. + * @param [in] h Full tree Height. + */ +#define IDX32_INVALID(i, c, h) \ + ((((i) + 1) >> (h)) != 0) + +/* Set 32-bit index as hash address value for tree. + * + * @param [in] i Index to set. + * @param [in] c Count of bytes to encode into. + * @param [in] h Height of tree. + * @param [out] a Hash address to encode into. + * @param [out] l Index of leaf. + */ +#define IDX32_SET_ADDR_TREE(i, c, h, a, l) \ + if ((c) <= 4) { \ + (l) = ((i) & ((1 << (h)) - 1)); \ + (i) >>= params->sub_h; \ + (a)[XMSS_ADDR_TREE] = (i); \ + } + +#endif /* WOLFSSL_XMSS_MIN_HEIGHT <= 32 */ + +#if (WOLFSSL_XMSS_MAX_HEIGHT > 32) && (WOLFSSL_XMSS_MIN_HEIGHT <= 32) + +/* Decode 32/64-bit index. + * + * @param [out] idx Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define WC_IDX_DECODE(idx, c, a, ret) \ +do { \ + IDX64_DECODE((idx).u64, c, a, ret) \ + else \ + IDX32_DECODE((idx).u32, c, a, ret) \ + else { \ + (ret) = NOT_COMPILED_IN; \ + } \ +} while (0) + +/* Check whether index is valid. + * + * @param [in] i Index to check. + * @param [in] c Count of bytes i was encoded in. + * @param [in] h Full tree Height. + */ +#define WC_IDX_INVALID(i, c, h) \ + ((((c) > 4) && IDX64_INVALID((i).u64, c, h)) || \ + (((c) <= 4) && IDX32_INVALID((i).u32, c, h))) + +/* Set 32/64-bit index as hash address value for tree. + * + * @param [in] i Index to set. + * @param [in] c Count of bytes to encode into. + * @param [in] h Height of tree. + * @param [out] a Hash address to encode into. + * @param [out] l Index of leaf. + */ +#define WC_IDX_SET_ADDR_TREE(idx, c, h, a, l) \ +do { \ + IDX64_SET_ADDR_TREE((idx).u64, c, h, a, l) \ + else \ + IDX32_SET_ADDR_TREE((idx).u32, c, h, a, l) \ +} while (0) + +#elif WOLFSSL_XMSS_MAX_HEIGHT > 32 + +/* Decode 64-bit index. + * + * @param [out] idx Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define WC_IDX_DECODE(idx, c, a, ret) \ +do { \ + IDX64_DECODE((idx).u64, c, a, ret) \ +} while (0) + +/* Check whether index is valid. + * + * @param [in] i Index to check. + * @param [in] c Count of bytes i was encoded in. + * @param [in] h Full tree Height. + */ +#define WC_IDX_INVALID(i, c, h) \ + IDX64_INVALID((i).u64, c, h) + +/* Set 64-bit index as hash address value for tree. + * + * @param [in] i Index to set. + * @param [in] c Count of bytes to encode into. + * @param [in] h Height of tree. + * @param [out] a Hash address to encode into. + * @param [out] l Index of leaf. + */ +#define WC_IDX_SET_ADDR_TREE(idx, c, h, a, l) \ +do { \ + IDX64_SET_ADDR_TREE((idx).u64, c, h, a, l) \ +} while (0) + +#else + +/* Decode 32-bit index. + * + * @param [out] idx Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + * @param [out] ret Return value. + */ +#define WC_IDX_DECODE(idx, c, a, ret) \ +do { \ + IDX32_DECODE((idx).u32, c, a, ret) \ + else { \ + (ret) = NOT_COMPILED_IN; \ + } \ +} while (0) + +/* Check whether index is valid. + * + * @param [in] i Index to check. + * @param [in] c Count of bytes i was encoded in. + * @param [in] h Full tree Height. + */ +#define WC_IDX_INVALID(i, c, h) \ + IDX32_INVALID((i).u32, c, h) + +/* Set 32-bit index as hash address value for tree. + * + * @param [in] i Index to set. + * @param [in] c Count of bytes to encode into. + * @param [in] h Height of tree. + * @param [out] a Hash address to encode into. + * @param [out] l Index of leaf. + */ +#define WC_IDX_SET_ADDR_TREE(idx, c, h, a, l) \ +do { \ + IDX32_SET_ADDR_TREE(idx.u32, c, h, a, l) \ +} while (0) + +#endif /* (WOLFSSL_XMSS_MAX_HEIGHT > 32) && (WOLFSSL_XMSS_MIN_HEIGHT <= 32) */ + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY +/* Update index by adding one to big-endian encoded value. + * + * @param [in, out] a Array index is encoded in. + * @param [in] l Length of encoded index. + */ +static void wc_idx_update(unsigned char* a, word8 l) +{ + sword8 i; + + for (i = l - 1; i >= 0; i--) { + if ((++a[i]) != 0) { + break; + } + } +} + +/* Copy index from source buffer to destination buffer. + * + * Index is put into the front of the destination buffer with the length of the + * source. + * + * @param [in] s Source buffer. + * @param [in] sl Length of index in source. + * @param [in, out] d Destination buffer. + * @param [in] dl Length of destination buffer. + */ +static void wc_idx_copy(const unsigned char* s, word8 sl, unsigned char* d, + word8 dl) +{ + XMEMCPY(d, s, sl); + XMEMSET(d + sl, 0, dl - sl); +} +#endif + +/******************************************** + * Hash Address. + ********************************************/ + +/* Set the hash address based on subtree. + * + * @param [out] a Hash address. + * @param [in] s Subtree hash address. + * @param [in] t Type of hash address. + */ +#define XMSS_ADDR_SET_SUBTREE(a, s, t) \ +do { \ + (a)[XMSS_ADDR_LAYER] = (s)[XMSS_ADDR_LAYER]; \ + (a)[XMSS_ADDR_TREE_HI] = (s)[XMSS_ADDR_TREE_HI]; \ + (a)[XMSS_ADDR_TREE] = (s)[XMSS_ADDR_TREE]; \ + (a)[XMSS_ADDR_TYPE] = (t); \ + XMEMSET((a) + 4, 0, sizeof(a) - 4 * sizeof(*(a)));\ +} while (0) + +/* Set the OTS hash address based on subtree. + * + * @param [out] a Hash address. + * @param [in] s Subtree hash address. + */ +#define XMSS_ADDR_OTS_SET_SUBTREE(a, s) \ + XMSS_ADDR_SET_SUBTREE(a, s, WC_XMSS_ADDR_TYPE_OTS) +/* Set the L-tree address based on subtree. + * + * @param [out] a Hash address. + * @param [in] s Subtree hash address. + */ +#define XMSS_ADDR_LTREE_SET_SUBTREE(a, s) \ + XMSS_ADDR_SET_SUBTREE(a, s, WC_XMSS_ADDR_TYPE_LTREE) +/* Set the hash tree address based on subtree. + * + * @param [out] a Hash address. + * @param [in] s Subtree hash address. + */ +#define XMSS_ADDR_TREE_SET_SUBTREE(a, s) \ + XMSS_ADDR_SET_SUBTREE(a, s, WC_XMSS_ADDR_TYPE_TREE) + +#ifdef LITTLE_ENDIAN_ORDER + +/* Set a byte value into a word of an encoded address. + * + * @param [in, out] a Encoded hash address. + * @param [in] i Index of word. + * @param [in] b Byte to set. + */ +#define XMSS_ADDR_SET_BYTE(a, i, b) \ + ((word32*)(a))[i] = (word32)(b) << 24 + +#else + +/* Set a byte value into a word of an encoded address. + * + * @param [in, out] a Encoded hash address. + * @param [in] i Index of word. + * @param [in] b Byte to set. + */ +#define XMSS_ADDR_SET_BYTE(a, i, b) \ + ((word32*)(a))[i] = (b) + +#endif /* LITTLE_ENDIAN_ORDER */ + +/* Convert hash address to bytes. + * + * @param [out] bytes Array to encode into. + * @param [in] addr Hash address. + */ +static void wc_xmss_addr_encode(const HashAddress addr, byte* bytes) +{ + c32toa((addr)[0], (bytes) + (0 * 4)); + c32toa((addr)[1], (bytes) + (1 * 4)); + c32toa((addr)[2], (bytes) + (2 * 4)); + c32toa((addr)[3], (bytes) + (3 * 4)); + c32toa((addr)[4], (bytes) + (4 * 4)); + c32toa((addr)[5], (bytes) + (5 * 4)); + c32toa((addr)[6], (bytes) + (6 * 4)); + c32toa((addr)[7], (bytes) + (7 * 4)); +} + +/******************************************** + * HASHING + ********************************************/ + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) && \ + !defined(WC_XMSS_FULL_HASH) + +/* Set hash data and length into SHA-256 digest. + * + * @param [in, out] state XMSS/MT state with SHA-256 digest. + * @param [in] data Data to add to hash. + * @param [in] len Number of bytes in data. + * Must be less than a block. + * @param [in] total_len Number of bytes updated so far. + */ +#define XMSS_SHA256_SET_DATA(state, data, len, total_len) \ +do { \ + XMEMCPY((state)->digest.sha256.buffer, data, len); \ + (state)->digest.sha256.buffLen = (len); \ + (state)->digest.sha256.loLen = (total_len); \ +} while (0) + +/* Save the SHA-256 state to cache. + * + * @param [in, out] state XMSS/MT state with SHA-256 digest and state cache. + */ +#define XMSS_SHA256_STATE_CACHE(state) \ + (state)->dgst_state[0] = (state)->digest.sha256.digest[0]; \ + (state)->dgst_state[1] = (state)->digest.sha256.digest[1]; \ + (state)->dgst_state[2] = (state)->digest.sha256.digest[2]; \ + (state)->dgst_state[3] = (state)->digest.sha256.digest[3]; \ + (state)->dgst_state[4] = (state)->digest.sha256.digest[4]; \ + (state)->dgst_state[5] = (state)->digest.sha256.digest[5]; \ + (state)->dgst_state[6] = (state)->digest.sha256.digest[6]; \ + (state)->dgst_state[7] = (state)->digest.sha256.digest[7]; \ + +/* Restore the SHA-256 state from cache and set length. + * + * @param [in, out] state XMSS/MT state with SHA-256 digest and state cache. + * @param [in] len Number of bytes of data hashed so far. + */ +#define XMSS_SHA256_STATE_RESTORE(state, len) \ +do { \ + (state)->digest.sha256.digest[0] = (state)->dgst_state[0]; \ + (state)->digest.sha256.digest[1] = (state)->dgst_state[1]; \ + (state)->digest.sha256.digest[2] = (state)->dgst_state[2]; \ + (state)->digest.sha256.digest[3] = (state)->dgst_state[3]; \ + (state)->digest.sha256.digest[4] = (state)->dgst_state[4]; \ + (state)->digest.sha256.digest[5] = (state)->dgst_state[5]; \ + (state)->digest.sha256.digest[6] = (state)->dgst_state[6]; \ + (state)->digest.sha256.digest[7] = (state)->dgst_state[7]; \ + (state)->digest.sha256.loLen = (len); \ +} while (0) + +/* Restore the SHA-256 state from cache and set data and length. + * + * @param [in, out] state XMSS/MT state with SHA-256 digest and cache. + * @param [in] data Data to add to hash. + * @param [in] len Number of bytes in data. + * Must be less than a block. + * @param [in] total_len Number of bytes updated so far. + */ +#define XMSS_SHA256_STATE_RESTORE_DATA(state, data, len, total_len) \ +do { \ + (state)->digest.sha256.digest[0] = (state)->dgst_state[0]; \ + (state)->digest.sha256.digest[1] = (state)->dgst_state[1]; \ + (state)->digest.sha256.digest[2] = (state)->dgst_state[2]; \ + (state)->digest.sha256.digest[3] = (state)->dgst_state[3]; \ + (state)->digest.sha256.digest[4] = (state)->dgst_state[4]; \ + (state)->digest.sha256.digest[5] = (state)->dgst_state[5]; \ + (state)->digest.sha256.digest[6] = (state)->dgst_state[6]; \ + (state)->digest.sha256.digest[7] = (state)->dgst_state[7]; \ + XMSS_SHA256_SET_DATA(state, data, len, total_len); \ +} while (0) + +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 && !WC_XMSS_FULL_HASH */ + +/* Hash the data into output buffer. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] in Data to digest. + * @param [in] inlen Length of data to digest in bytes. + * @param [out] out Buffer to put digest into. + */ +static WC_INLINE void wc_xmss_hash(XmssState* state, const byte* in, + word32 inlen, byte* out) +{ + int ret; + const XmssParams* params = state->params; -#ifdef WOLFSSL_HAVE_XMSS - #error "Contact wolfSSL to get the implementation of this file" +#ifdef WC_XMSS_SHA256 + /* Full SHA-256 digest. */ + if ((params->hash == WC_HASH_TYPE_SHA256) && + (params->n == WC_SHA256_DIGEST_SIZE)) { + ret = wc_Sha256Update(&state->digest.sha256, in, inlen); + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, out); + } + } +#if WOLFSSL_WC_XMSS_MIN_HASH_SIZE <= 192 && WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 192 + /* Partial SHA-256 digest. */ + else if (params->hash == WC_HASH_TYPE_SHA256) { + byte buf[WC_SHA256_DIGEST_SIZE]; + ret = wc_Sha256Update(&state->digest.sha256, in, inlen); + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, buf); + } + if (ret == 0) { + XMEMCPY(out, buf, params->n); + } + } #endif + else +#endif /* WC_XMSS_SHA256 */ +#ifdef WC_XMSS_SHA512 + /* Full SHA-512 digest. */ + if (params->hash == WC_HASH_TYPE_SHA512) { + ret = wc_Sha512Update(&state->digest.sha512, in, inlen); + if (ret == 0) { + ret = wc_Sha512Final(&state->digest.sha512, out); + } + } + else +#endif /* WC_XMSS_SHA512 */ +#ifdef WC_XMSS_SHAKE128 + /* Digest with SHAKE-128. */ + if (params->hash == WC_HASH_TYPE_SHAKE128) { + ret = wc_Shake128_Update(&state->digest.shake, in, inlen); + if (ret == 0) { + ret = wc_Shake128_Final(&state->digest.shake, out, params->n); + } + } + else +#endif /* WC_XMSS_SHAKE128 */ +#ifdef WC_XMSS_SHAKE256 + /* Digest with SHAKE-256. */ + if (params->hash == WC_HASH_TYPE_SHAKE256) { + ret = wc_Shake256_Update(&state->digest.shake, in, inlen); + if (ret == 0) { + ret = wc_Shake256_Final(&state->digest.shake, out, params->n); + } + } + else +#endif /* WC_XMSS_SHAKE256 */ + { + /* Unsupported digest function. */ + ret = NOT_COMPILED_IN; + } + + if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +} + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) +#ifndef WC_XMSS_FULL_HASH +/* Chain hashing. + * + * RFC 8391: 3.1.2, Algorithm 2: chain - Chaining Function + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM = PRF(SEED, ADRS); + * tmp = F(KEY, tmp XOR BM); + * return tmp; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] tmp Temporary buffer holding chain data. + * @param [in] addr Hash address as a byte array. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_chain_hash_sha256_32(XmssState* state, const byte* tmp, + byte* addr, byte* hash) +{ + /* Offsets into chain hash data. */ + byte* pad = state->buf; + byte* key = pad + XMSS_SHA256_32_PAD_LEN; + byte* bm = key + XMSS_SHA256_32_N; + int ret; + + /* Calculate n-byte key - KEY. */ + ((word32*)addr)[XMSS_ADDR_KEY_MASK] = 0; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, key); + + if (ret == 0) { + /* Calculate n-byte bit mask - BM. */ + addr[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm); + } + + if (ret == 0) { + /* Function padding set in caller. */ + xorbuf(bm, tmp, XMSS_SHA256_32_N); + ret = wc_Sha256Update(&state->digest.sha256, state->buf, + XMSS_CHAIN_HASH_DATA_LEN_SHA256_32); + } + if (ret == 0) { + /* Calculate the chain hash. */ + ret = wc_Sha256Final(&state->digest.sha256, hash); + } + if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +} +#else +/* Chain hashing. + * + * Padding, seed, addr for PRF set by caller into prf_buf. + * + * RFC 8391: 3.1.2, Algorithm 2: chain - Chaining Function + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM = PRF(SEED, ADRS); + * tmp = F(KEY, tmp XOR BM); + * return tmp; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] tmp Temporary buffer holding chain data. + * @param [out] out Buffer to hold hash. + */ +static void wc_xmss_chain_hash_sha256_32(XmssState* state, const byte* tmp, + byte* hash) +{ + byte* addr = state->prf_buf + XMSS_SHA256_32_PAD_LEN + XMSS_SHA256_32_N; + /* Offsets into chain hash data. */ + byte* pad = state->buf; + byte* key = pad + XMSS_SHA256_32_PAD_LEN; + byte* bm = key + XMSS_SHA256_32_N; + + /* Calculate n-byte key - KEY. */ + ((word32*)addr)[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, key); + /* Calculate the n-byte mask. */ + addr[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, bm); + + /* Function padding set in caller. */ + xorbuf(bm, tmp, XMSS_SHA256_32_N); + /* Calculate the chain hash. */ + wc_xmss_hash(state, state->buf, XMSS_CHAIN_HASH_DATA_LEN_SHA256_32, hash); +} +#endif /* !WC_XMSS_FULL_HASH */ +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + +/* Chain hashing. + * + * Padding, seed, addr for PRF set by caller into prf_buf. + * + * RFC 8391: 3.1.2, Algorithm 2: chain - Chaining Function + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM = PRF(SEED, ADRS); + * tmp = F(KEY, tmp XOR BM); + * return tmp; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] tmp Temporary buffer holding chain data. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_chain_hash(XmssState* state, const byte* tmp, byte* hash) +{ + const XmssParams* params = state->params; + byte* addr = state->prf_buf + params->pad_len + params->n; + /* Offsets into chain hash data. */ + byte* pad = state->buf; + byte* key = pad + params->pad_len; + byte* bm = key + params->n; + + /* Calculate n-byte key - KEY. */ + ((word32*)addr)[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN(params), key); + /* Calculate n-byte bit mask - BM. */ + addr[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN(params), bm); + + /* Function padding set in caller. */ + xorbuf(bm, tmp, params->n); + /* Calculate the chain hash. */ + wc_xmss_hash(state, state->buf, XMSS_CHAIN_HASH_DATA_LEN(params), hash); +} + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) +#ifndef WC_XMSS_FULL_HASH +/* Randomized tree hashing. + * + * RFC 8391: 4.1.4, Algorithm 7: RAND_HASH + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM_0 = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(2); + * BM_1 = PRF(SEED, ADRS); + * return H(KEY, (LEFT XOR BM_0) || (RIGHT XOR BM_1)); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] data Input data. + * @param [in] addr Hash address. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_rand_hash_sha256_32_prehash(XmssState* state, + const byte* data, HashAddress addr, byte* hash) +{ + int ret; + /* Offsets into rand hash data. */ + byte* pad = state->buf; + byte* key = pad + XMSS_SHA256_32_PAD_LEN; + byte* bm0 = key + XMSS_SHA256_32_N; + byte* bm1 = bm0 + XMSS_SHA256_32_N; + byte addr_buf[WC_XMSS_ADDR_LEN]; + + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, key); + + /* Calculate n-byte mask - BM_0. */ + if (ret == 0) { + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm0); + } + + /* Calculate n-byte mask - BM_1. */ + if (ret == 0) { + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm1); + } + + if (ret == 0) { + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, pad, XMSS_SHA256_32_PAD_LEN); + /* XOR into bm0 and bm1. */ + xorbuf(bm0, data, XMSS_SHA256_32_N * 2); + ret = wc_Sha256Update(&state->digest.sha256, state->buf, + XMSS_RAND_HASH_DATA_LEN_SHA256_32); + } + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, hash); + } + if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +} +#endif /* !WC_XMSS_FULL_HASH */ + +/* Randomized tree hashing. + * + * RFC 8391: 4.1.4, Algorithm 7: RAND_HASH + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM_0 = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(2); + * BM_1 = PRF(SEED, ADRS); + * return H(KEY, (LEFT XOR BM_0) || (RIGHT XOR BM_1)); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] data Input data. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_rand_hash_sha256_32(XmssState* state, const byte* data, + const byte* pk_seed, HashAddress addr, byte* hash) +{ + byte* addr_buf = state->prf_buf + XMSS_SHA256_32_PAD_LEN + + XMSS_SHA256_32_N; + /* Offsets into rand hash data. */ + byte* pad = state->buf; + byte* key = pad + XMSS_SHA256_32_PAD_LEN; + byte* bm0 = key + XMSS_SHA256_32_N; + byte* bm1 = bm0 + XMSS_SHA256_32_N; +#ifndef WC_XMSS_FULL_HASH + int ret; + + /* Encode padding byte for PRF. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, state->prf_buf, XMSS_SHA256_32_PAD_LEN); + /* Append public seed for PRF. */ + XMEMCPY(state->prf_buf + XMSS_SHA256_32_PAD_LEN, pk_seed, + XMSS_SHA256_32_N); + + /* Set key mask to initial value and append encoding. */ + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + ret = wc_Sha256Update(&state->digest.sha256, state->prf_buf, + XMSS_SHA256_32_PAD_LEN + XMSS_SHA256_32_N); + if (ret == 0) { + /* Copy state after first 64 bytes. */ + XMSS_SHA256_STATE_CACHE(state); + /* Copy in remaining 32 bytes to buffer. */ + XMSS_SHA256_SET_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, key); + } + + /* Calculate n-byte mask - BM_0. */ + if (ret == 0) { + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm0); + } + + /* Calculate n-byte mask - BM_1. */ + if (ret == 0) { + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm1); + } + + if (ret == 0) { + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, pad, XMSS_SHA256_32_PAD_LEN); + /* XOR into bm0 and bm1. */ + xorbuf(bm0, data, 2 * XMSS_SHA256_32_N); + ret = wc_Sha256Update(&state->digest.sha256, state->buf, + XMSS_RAND_HASH_DATA_LEN_SHA256_32); + } + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, hash); + } + if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +#else + /* Encode padding byte for PRF. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, state->prf_buf, XMSS_SHA256_32_PAD_LEN); + /* Append public seed for PRF. */ + XMEMCPY(state->prf_buf + XMSS_SHA256_32_PAD_LEN, pk_seed, + XMSS_SHA256_32_N); + + /* Set key mask to initial value and append encoding. */ + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, key); + /* Calculate n-byte mask - BM_0. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, bm0); + /* Calculate n-byte mask - BM_1. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, bm1); + + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, state->buf, XMSS_SHA256_32_PAD_LEN); + xorbuf(bm0, data, 2 * XMSS_SHA256_32_N); + wc_xmss_hash(state, state->buf, XMSS_RAND_HASH_DATA_LEN_SHA256_32, hash); +#endif /* WC_XMSS_FULL_HASH */ +} +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + +/* Randomized tree hashing. + * + * RFC 8391: 4.1.4, Algorithm 7: RAND_HASH + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM_0 = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(2); + * BM_1 = PRF(SEED, ADRS); + * return H(KEY, (LEFT XOR BM_0) || (RIGHT XOR BM_1)); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] data Input data. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_rand_hash(XmssState* state, const byte* data, + const byte* pk_seed, HashAddress addr, byte* hash) +{ + const XmssParams* params = state->params; + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + wc_xmss_rand_hash_sha256_32(state, data, pk_seed, addr, hash); + } + else +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + { + byte* addr_buf = state->prf_buf + params->pad_len + params->n; + /* Offsets into rand hash data. */ + byte* pad = state->buf; + byte* key = pad + params->pad_len; + byte* bm0 = key + params->n; + byte* bm1 = bm0 + params->n; + const word32 len = params->pad_len + params->n + WC_XMSS_ADDR_LEN; + + /* Encode padding byte for PRF. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, state->prf_buf, params->pad_len); + /* Append public seed for PRF. */ + XMEMCPY(state->prf_buf + params->pad_len, pk_seed, params->n); + + /* Set key mask to initial value and append encoding. */ + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + wc_xmss_hash(state, state->prf_buf, len, key); + /* Calculate n-byte mask - BM_0. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + wc_xmss_hash(state, state->prf_buf, len, bm0); + /* Calculate n-byte mask - BM_1. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + wc_xmss_hash(state, state->prf_buf, len, bm1); + + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, pad, params->pad_len); + xorbuf(bm0, data, 2 * params->n); + wc_xmss_hash(state, state->buf, params->pad_len + 3 * params->n, + hash); + } +} + +#if !defined(WOLFSSL_WC_XMSS_SMALL) || defined(WOLFSSL_XMSS_VERIFY_ONLY) +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) +/* Randomized tree hashing. + * + * RFC 8391: 4.1.4, Algorithm 7: RAND_HASH + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM_0 = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(2); + * BM_1 = PRF(SEED, ADRS); + * return H(KEY, (LEFT XOR BM_0) || (RIGHT XOR BM_1)); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] left First half of data. + * @param [in] right Second half of data. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_rand_hash_lr_sha256_32(XmssState* state, const byte* left, + const byte* right, const byte* pk_seed, HashAddress addr, byte* hash) +{ + byte* addr_buf = state->prf_buf + XMSS_SHA256_32_PAD_LEN + + XMSS_SHA256_32_N; + /* Offsets into rand hash data. */ + byte* pad = state->buf; + byte* key = pad + XMSS_SHA256_32_PAD_LEN; + byte* bm0 = key + XMSS_SHA256_32_N; + byte* bm1 = bm0 + XMSS_SHA256_32_N; +#ifndef WC_XMSS_FULL_HASH + int ret; + + /* Encode padding byte for PRF. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, state->prf_buf, XMSS_SHA256_32_PAD_LEN); + /* Append public seed for PRF. */ + XMEMCPY(state->prf_buf + XMSS_SHA256_32_PAD_LEN, pk_seed, + XMSS_SHA256_32_N); + + /* Set key mask to initial value and append encoding. */ + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + ret = wc_Sha256Update(&state->digest.sha256, state->prf_buf, + XMSS_SHA256_32_PAD_LEN + XMSS_SHA256_32_N); + if (ret == 0) { + /* Copy state after first 64 bytes. */ + XMSS_SHA256_STATE_CACHE(state); + /* Copy in remaining 32 bytes to buffer. */ + XMSS_SHA256_SET_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, key); + } + + /* Calculate n-byte mask - BM_0. */ + if (ret == 0) { + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm0); + } + + /* Calculate n-byte mask - BM_1. */ + if (ret == 0) { + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + /* Copy back state after first 64 bytes. */ + XMSS_SHA256_STATE_RESTORE_DATA(state, addr_buf, WC_XMSS_ADDR_LEN, + XMSS_HASH_PRF_DATA_LEN_SHA256_32); + /* Calculate hash. */ + ret = wc_Sha256Final(&state->digest.sha256, bm1); + } + + if (ret == 0) { + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, pad, XMSS_SHA256_32_PAD_LEN); + /* XOR into bm0 and bm1. */ + XMEMCPY(state->prf_buf, left, XMSS_SHA256_32_N); + XMEMCPY(state->prf_buf + XMSS_SHA256_32_N, right, XMSS_SHA256_32_N); + xorbuf(bm0, state->prf_buf, 2 * XMSS_SHA256_32_N); + ret = wc_Sha256Update(&state->digest.sha256, state->buf, + XMSS_RAND_HASH_DATA_LEN_SHA256_32); + } + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, hash); + } + if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +#else + /* Encode padding byte for PRF. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, state->prf_buf, XMSS_SHA256_32_PAD_LEN); + /* Append public seed for PRF. */ + XMEMCPY(state->prf_buf + XMSS_SHA256_32_PAD_LEN, pk_seed, XMSS_SHA256_32_N); + + /* Set key mask to initial value and append encoding. */ + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, key); + /* Calculate n-byte mask - BM_0. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, bm0); + /* Calculate n-byte mask - BM_1. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + wc_xmss_hash(state, state->prf_buf, XMSS_HASH_PRF_DATA_LEN_SHA256_32, bm1); + + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, state->buf, XMSS_SHA256_32_PAD_LEN); + XMEMCPY(state->prf_buf, left, XMSS_SHA256_32_N); + XMEMCPY(state->prf_buf + XMSS_SHA256_32_N, right, XMSS_SHA256_32_N); + xorbuf(bm0, state->prf_buf, 2 * XMSS_SHA256_32_N); + wc_xmss_hash(state, state->buf, XMSS_RAND_HASH_DATA_LEN_SHA256_32, hash); +#endif /* WC_XMSS_FULL_HASH */ +} +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ +/* Randomized tree hashing - left and right separate parameters. + * + * RFC 8391: 4.1.4, Algorithm 7: RAND_HASH + * ... + * ADRS.setKeyAndMask(0); + * KEY = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(1); + * BM_0 = PRF(SEED, ADRS); + * ADRS.setKeyAndMask(2); + * BM_1 = PRF(SEED, ADRS); + * return H(KEY, (LEFT XOR BM_0) || (RIGHT XOR BM_1)); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] left First half of data. + * @param [in] right Second half of data. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_rand_hash_lr(XmssState* state, const byte* left, + const byte* right, const byte* pk_seed, HashAddress addr, byte* hash) +{ + const XmssParams* params = state->params; + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + wc_xmss_rand_hash_lr_sha256_32(state, left, right, pk_seed, addr, hash); + } + else +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + { + byte* addr_buf = state->prf_buf + params->pad_len + params->n; + /* Offsets into rand hash data. */ + byte* pad = state->buf; + byte* key = pad + params->pad_len; + byte* bm0 = key + params->n; + byte* bm1 = bm0 + params->n; + const word32 len = params->pad_len + params->n + WC_XMSS_ADDR_LEN; + + /* Encode padding byte for PRF. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, state->prf_buf, params->pad_len); + /* Append public seed for PRF. */ + XMEMCPY(state->prf_buf + params->pad_len, pk_seed, params->n); + + /* Set key mask to initial value and append encoding. */ + addr[XMSS_ADDR_KEY_MASK] = 0; + wc_xmss_addr_encode(addr, addr_buf); + + /* Calculate n-byte key - KEY. */ + wc_xmss_hash(state, state->prf_buf, len, key); + /* Calculate n-byte mask - BM_0. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 1; + wc_xmss_hash(state, state->prf_buf, len, bm0); + /* Calculate n-byte mask - BM_1. */ + addr_buf[XMSS_ADDR_KEY_MASK * 4 + 3] = 2; + wc_xmss_hash(state, state->prf_buf, len, bm1); + + XMSS_PAD_ENC(XMSS_HASH_PADDING_H, pad, params->pad_len); + XMEMCPY(state->prf_buf, left, params->n); + XMEMCPY(state->prf_buf + params->n, right, params->n); + xorbuf(bm0, state->prf_buf, 2 * params->n); + wc_xmss_hash(state, state->buf, params->pad_len + 3 * params->n, + hash); + } +} +#endif /* !WOLFSSL_WC_XMSS_SMALL || WOLFSSL_XMSS_VERIFY_ONLY */ + +/* Compute message hash from the random r, root, index and message. + * + * RFC 8391: 4.1.9, Algorithm 12: XMSS_sign + * ... + * byte[n] M' = H_msg(r || getRoot(SK) || (toByte(idx_sig, n)), M); + * RFC 8391: 5.1 + * H_msg: SHA2-256(toByte(2, 32) || KEY || M) + * H_msg: SHA2-512(toByte(2, 64) || KEY || M) + * H_msg: SHAKE128(toByte(2, 32) || KEY || M, 256) + * H_msg: SHAKE256(toByte(2, 64) || KEY || M, 512) + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] random Random value of n bytes. + * @param [in] root Public root. + * @param [in] idx Buffer holding encoded index. + * @param [in] idx_len Length of encoded index in bytes. + * @param [in] m Message to hash. + * @param [in] mlen Length of message. + * @param [out] hash Buffer to hold hash. + */ +static void wc_xmss_hash_message(XmssState* state, const byte* random, + const byte* root, const byte* idx, word8 idx_len, const byte* m, + word32 mlen, byte* hash) +{ + int ret; + const XmssParams* params = state->params; + word32 padKeyLen = params->pad_len + 3 * params->n; + /* Offsets into message hash data. */ + byte* padKey = state->buf; + byte* pad = padKey; + byte* key = pad + params->pad_len; + byte* root_sk = key + params->n; + byte* idx_sig = root_sk + params->n; + + /* Set prefix data before message. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_HASH, pad, params->pad_len); + XMEMCPY(key, random, params->n); + XMEMCPY(root_sk, root, params->n); + XMEMSET(idx_sig, 0, params->n - idx_len); + XMEMCPY(idx_sig + params->n - idx_len, idx, idx_len); + + /* Hash the padding and key first. */ +#ifdef WC_XMSS_SHA256 + if (params->hash == WC_HASH_TYPE_SHA256) { + ret = wc_Sha256Update(&state->digest.sha256, padKey, padKeyLen); + } + else +#endif /* WC_XMSS_SHA256 */ +#ifdef WC_XMSS_SHA512 + if (params->hash == WC_HASH_TYPE_SHA512) { + ret = wc_Sha512Update(&state->digest.sha512, padKey, padKeyLen); + } + else +#endif /* WC_XMSS_SHA512 */ +#ifdef WC_XMSS_SHAKE128 + if (params->hash == WC_HASH_TYPE_SHAKE128) { + ret = wc_Shake128_Update(&state->digest.shake, padKey, padKeyLen); + } + else +#endif /* WC_XMSS_SHAKE128 */ +#ifdef WC_XMSS_SHAKE256 + if (params->hash == WC_HASH_TYPE_SHAKE256) { + ret = wc_Shake256_Update(&state->digest.shake, padKey, padKeyLen); + } + else +#endif /* WC_XMSS_SHAKE256 */ + { + /* Unsupported digest function. */ + ret = NOT_COMPILED_IN; + } + if (ret == 0) { + /* Generate hash of message - M'. */ + wc_xmss_hash(state, m, mlen, hash); + } + else if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +} + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY + +/* Compute PRF with key and message. + * + * RFC 8391: 5.1 + * PRF: SHA2-256(toByte(3, 32) || KEY || M) + * PRF: SHA2-512(toByte(3, 64) || KEY || M) + * PRF: SHAKE128(toByte(3, 32) || KEY || M, 256) + * PRF: SHAKE256(toByte(3, 64) || KEY || M, 512) + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] key Key used to derive pseudo-random from. + * @param [in] m 32 bytes of data to derive pseudo-random from. + * @param [out] prf Buffer to hold pseudo-random data. + */ +static void wc_xmss_prf(XmssState* state, const byte* key, const byte* m, + byte* prf) +{ + const XmssParams* params = state->params; + byte* pad = state->prf_buf; + byte* key_buf = pad + params->pad_len; + byte* m_buf = key_buf + params->n; + + /* 00[0..pl-1] || 03 || key[0..n-1] || m[0..31] */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, pad, params->pad_len); + XMEMCPY(key_buf, key, params->n); + XMEMCPY(m_buf, m, XMSS_PRF_M_LEN); + + /* Hash the PRF data. */ + wc_xmss_hash(state, state->prf_buf, params->pad_len + params->n + + XMSS_PRF_M_LEN, prf); +} + +#ifdef XMSS_CALL_PRF_KEYGEN +/* Compute PRF for keygen with key and message. + * + * NIST SP 800-208: 5.1, 5.2, 5.3, 5.4 + * PRFkeygen (KEY, M): SHA-256(toByte(4, 32) || KEY || M) + * PRFkeygen (KEY, M): T192(SHA-256(toByte(4, 4) || KEY || M)) + * PRFkeygen (KEY, M): SHAKE256(toByte(4, 32) || KEY || M, 256) + * PRFkeygen (KEY, M): SHAKE256(toByte(4, 4) || KEY || M, 192) + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] key Key of n bytes used to derive pseudo-random from. + * @param [in] m n + 32 bytes of data to derive pseudo-random from. + * @param [out] prf Buffer to hold pseudo-random data. + */ +static void wc_xmss_prf_keygen(XmssState* state, const byte* key, + const byte* m, byte* prf) +{ + const XmssParams* params = state->params; + byte* pad = state->prf_buf; + byte* key_buf = pad + params->pad_len; + byte* m_buf = key_buf + params->n; + + /* 00[0..pl-1] || 04 || key[0..n-1] || m[0..n+31] */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF_KEYGEN, pad, params->pad_len); + XMEMCPY(key_buf, key, params->n); + XMEMCPY(m_buf, m, params->n + XMSS_PRF_M_LEN); + + /* Hash the PRF keygen data. */ + wc_xmss_hash(state, state->prf_buf, params->pad_len + 2 * params->n + + XMSS_PRF_M_LEN, prf); +} +#endif /* XMSS_CALL_PRF_KEYGEN */ + +#endif /* !WOLFSSL_XMSS_VERIFY_ONLY */ + +/******************************************** + * WOTS + ********************************************/ + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) +/* Expand private seed with PRF keygen. + * + * RFC 8391: 4.1.3 + * "the existence of a method getWOTS_SK(SK, i) is assumed" + * NIST SP 800-208: 7.2.1, Algorithm 10' + * ... + * for ( j=0; j < len; j++) { + * ADRS.setChainAddress(j); + * sk[j] = PRFkeygen(S_XMSS, SEED || ADRS); + * } + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sk_seed Buffer holding private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address as a byte array. + * @param [out] gen_seed Buffer to hold seeds. + */ +static void wc_xmss_wots_get_wots_sk_sha256_32(XmssState* state, + const byte* sk_seed, const byte* pk_seed, byte* addr, byte* gen_seed) +{ + const XmssParams* params = state->params; + word32 i; + byte* pad = state->prf_buf; + byte* s_xmss = pad + XMSS_SHA256_32_PAD_LEN; + byte* seed = s_xmss + XMSS_SHA256_32_N; + byte* addr_buf = seed + XMSS_SHA256_32_N; + int ret; + + ((word32*)addr)[XMSS_ADDR_CHAIN] = 0; + ((word32*)addr)[XMSS_ADDR_HASH] = 0; + ((word32*)addr)[XMSS_ADDR_KEY_MASK] = 0; + + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF_KEYGEN, pad, XMSS_SHA256_32_PAD_LEN); + XMEMCPY(s_xmss, sk_seed, XMSS_SHA256_32_N); + XMEMCPY(seed, pk_seed, XMSS_SHA256_32_N); + XMEMCPY(addr_buf, addr, WC_XMSS_ADDR_LEN); + +#ifndef WC_XMSS_FULL_HASH + ret = wc_Sha256Update(&state->digest.sha256, pad, XMSS_SHA256_32_PAD_LEN + + XMSS_SHA256_32_N); + if (ret == 0) { + /* Copy state after first 64 bytes. */ + XMSS_SHA256_STATE_CACHE(state); + ret = wc_Sha256Update(&state->digest.sha256, seed, XMSS_SHA256_32_N + + WC_XMSS_ADDR_LEN); + } + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, gen_seed); + } + for (i = 1; (ret == 0) && (i < params->wots_len); i++) { + gen_seed += XMSS_SHA256_32_N; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + XMSS_SHA256_STATE_RESTORE(state, 64); + ret = wc_Sha256Update(&state->digest.sha256, seed, XMSS_SHA256_32_N + + WC_XMSS_ADDR_LEN); + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, gen_seed); + } + } +#else + ret = wc_Sha256Update(&state->digest.sha256, state->prf_buf, + XMSS_SHA256_32_PAD_LEN + 2 * XMSS_SHA256_32_N + WC_XMSS_ADDR_LEN); + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, gen_seed); + } + for (i = 1; (ret == 0) && i < params->wots_len; i++) { + gen_seed += XMSS_SHA256_32_N; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + ret = wc_Sha256Update(&state->digest.sha256, state->prf_buf, + XMSS_SHA256_32_PAD_LEN + 2 * XMSS_SHA256_32_N + WC_XMSS_ADDR_LEN); + if (ret == 0) { + ret = wc_Sha256Final(&state->digest.sha256, gen_seed); + } + } +#endif /* WC_XMSS_FULL_HASH*/ + + if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +} +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + +/* Expand private seed with PRF keygen. + * + * RFC 8391: 4.1.3 + * "the existence of a method getWOTS_SK(SK, i) is assumed" + * NIST SP 800-208: 7.2.1 + * Algorithm 10' + * ... + * for ( j=0; j < len; j++) { + * ADRS.setChainAddress(j); + * sk[j] = PRFkeygen(S_XMSS, SEED || ADRS); + * } + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sk_seed Buffer holding private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address as a byte array. + * @param [out] gen_seed Buffer to hold seeds. + */ +static void wc_xmss_wots_get_wots_sk(XmssState* state, const byte* sk_seed, + const byte* pk_seed, byte* addr, byte* gen_seed) +{ + const XmssParams* params = state->params; + word32 i; +#ifdef XMSS_CALL_PRF_KEYGEN + byte* seed = state->buf; + byte* addr_buf = seed + params->n; +#else + byte* pad = state->prf_buf; + byte* s_xmss = pad + params->pad_len; + byte* seed = s_xmss + params->n; + byte* addr_buf = seed + params->n; + const word32 len = params->pad_len + params->n * 2 + WC_XMSS_ADDR_LEN; +#endif /* XMSS_CALL_PRF_KEYGEN */ + + /* Ensure hash address fields are 0. */ + ((word32*)addr)[XMSS_ADDR_CHAIN] = 0; + ((word32*)addr)[XMSS_ADDR_HASH] = 0; + ((word32*)addr)[XMSS_ADDR_KEY_MASK] = 0; + +#ifdef XMSS_CALL_PRF_KEYGEN + /* Copy the seed and address into PRF keygen message buffer. */ + XMEMCPY(seed, pk_seed, params->n); + XMEMCPY(addr_buf, addr, WC_XMSS_ADDR_LEN); + + wc_xmss_prf_keygen(state, sk_seed, state->buf, gen_seed); + for (i = 1; i < params->wots_len; i++) { + gen_seed += params->n; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_prf_keygen(state, sk_seed, state->buf, gen_seed); + } +#else + /* Copy the PRF keygen fields into one buffer. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF_KEYGEN, pad, params->pad_len); + XMEMCPY(s_xmss, sk_seed, params->n); + XMEMCPY(seed, pk_seed, params->n); + XMEMCPY(addr_buf, addr, WC_XMSS_ADDR_LEN); + + /* Fill output with hashes of different chain hash addresses. */ + wc_xmss_hash(state, state->prf_buf, len, gen_seed); + for (i = 1; i < params->wots_len; i++) { + gen_seed += params->n; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_hash(state, state->prf_buf, len, gen_seed); + } +#endif /* XMSS_CALL_PRF_KEYGEN */ +} + +#endif /* !WOLFSSL_XMSS_VERIFY_ONLY */ + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) +/* Chain hashing to calculate node hash. + * + * RFC 8391: 3.1.2, Algorithm 2 - recursive. + * This function is an iterative version. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] data Initial data to hash. + * @param [in] start Starting hash value in hash address. + * @param [in] steps Size of step. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address as a byte array. + * @param [out] hash Chained hash. + */ +static void wc_xmss_chain_sha256_32(XmssState* state, const byte* data, + unsigned int start, unsigned int steps, const byte* pk_seed, byte* addr, + byte* hash) +{ + if (steps > 0) { + word32 i; + byte* pad = state->prf_buf; + byte* seed = pad + XMSS_SHA256_32_PAD_LEN; +#ifndef WC_XMSS_FULL_HASH + int ret; + + /* Set data for PRF hash. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, pad, XMSS_SHA256_32_PAD_LEN); + XMEMCPY(seed, pk_seed, XMSS_SHA256_32_N); + + /* Hash first 64 bytes. */ + ret = wc_Sha256Update(&state->digest.sha256, state->prf_buf, + XMSS_SHA256_32_PAD_LEN + XMSS_SHA256_32_N); + if (ret == 0) { + /* Copy state after first 64 bytes. */ + XMSS_SHA256_STATE_CACHE(state); + /* Only do this once for all chain hash calls. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_F, state->buf, + state->params->pad_len); + + /* Set address. */ + XMSS_ADDR_SET_BYTE(addr, XMSS_ADDR_HASH, start); + wc_xmss_chain_hash_sha256_32(state, data, addr, hash); + /* Iterate 'steps' calls to the hash function. */ + for (i = start+1; i < (start+steps) && i < XMSS_WOTS_W; i++) { + addr[XMSS_ADDR_HASH * 4 + 3] = i; + wc_xmss_chain_hash_sha256_32(state, hash, addr, hash); + } + } + else if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } +#else + const XmssParams* params = state->params; + byte* addr_buf = seed + XMSS_SHA256_32_N; + + /* Set data for PRF hash. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, pad, XMSS_SHA256_32_PAD_LEN); + XMEMCPY(seed, pk_seed, params->n); + XMEMCPY(addr_buf, addr, WC_XMSS_ADDR_LEN); + + /* Only do this once for all chain hash calls. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_F, state->buf, params->pad_len); + + /* Set address. */ + XMSS_ADDR_SET_BYTE(addr_buf, XMSS_ADDR_HASH, start); + wc_xmss_chain_hash_sha256_32(state, data, hash); + /* Iterate 'steps' calls to the hash function. */ + for (i = start+1; i < (start+steps) && i < XMSS_WOTS_W; i++) { + addr_buf[XMSS_ADDR_HASH * 4 + 3] = i; + wc_xmss_chain_hash_sha256_32(state, hash, hash); + } +#endif /* !WC_XMSS_FULL_HASH */ + } + else if (hash != data) { + XMEMCPY(hash, data, XMSS_SHA256_32_N); + } +} +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + +/* Chain hashing to calculate node hash. + * + * RFC 8391: 3.1.2, Algorithm 2 - recursive. + * This function is an iterative version. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] data Initial data to hash. + * @param [in] start Starting hash value in hash address. + * @param [in] steps Size of step. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address as a byte array. + * @param [out] hash Chained hash. + */ +static void wc_xmss_chain(XmssState* state, const byte* data, + unsigned int start, unsigned int steps, const byte* pk_seed, byte* addr, + byte* hash) +{ + const XmssParams* params = state->params; + + if (steps > 0) { + word32 i; + byte* pad = state->prf_buf; + byte* seed = pad + params->pad_len; + byte* addr_buf = seed + params->n; + + /* Set data for PRF hash. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, pad, params->pad_len); + XMEMCPY(seed, pk_seed, params->n); + XMEMCPY(addr_buf, addr, 32); + + /* Only do this once for all chain hash calls. */ + XMSS_PAD_ENC(XMSS_HASH_PADDING_F, state->buf, params->pad_len); + + /* Set address. */ + XMSS_ADDR_SET_BYTE(addr_buf, XMSS_ADDR_HASH, start); + wc_xmss_chain_hash(state, data, hash); + /* Iterate 'steps' calls to the hash function. */ + for (i = start+1; i < (start+steps) && i < XMSS_WOTS_W; i++) { + addr_buf[XMSS_ADDR_HASH * 4 + 3] = i; + wc_xmss_chain_hash(state, hash, hash); + } + } + else if (hash != data) { + XMEMCPY(hash, data, params->n); + } +} + +/* Convert base on message and add checksum. + * + * RFC 8391:, 2.6, Algorithm 1: base_w + * int in = 0; + * int out = 0; + * unsigned int total = 0; + * int bits = 0; + * int consumed; + * + * for ( consumed = 0; consumed < out_len; consumed++ ) { + * if ( bits == 0 ) { + * total = X[in]; + * in++; + * bits += 8; + * } + * bits -= lg(w); + * basew[out] = (total >> bits) AND (w - 1); + * out++; + * } + * return basew; + * + * base_w implemented for w == 16 (lg(w) == 4). + * + * RFC 8391: 3.1.5, Algorithm 5: + * ... + * csum = 0; + * + * # Convert message to base w + * msg = base_w(M, w, len_1); + * # Compute checksum + * for ( i = 0; i < len_1; i++ ) { + * csum = csum + w - 1 - msg[i]; + * } + * + * # Convert csum to base w + * csum = csum << ( 8 - ( ( len_2 * lg(w) ) % 8 )); + * len_2_bytes = ceil( ( len_2 * lg(w) ) / 8 ); + * msg = msg || base_w(toByte(csum, len_2_bytes), w, len_2); + * + * len_1 == 8 * n / 4 = n * 2 + * Implemented for len_2 == 3 + * + * @param [in] m Message data. + * @param [in] n Number of bytes in hash. + * @param [out] msg Message in new base. + */ +static void wc_xmss_msg_convert(const byte* m, word8 n, word8* msg) +{ + word8 i; + word16 csum = 0; + + /* Split each full byte of m into two bytes of msg. */ + for (i = 0; i < n; i++) { + msg[0] = m[i] >> 4; + msg[1] = m[i] & 0xf; + csum += XMSS_WOTS_W - 1 - msg[0]; + csum += XMSS_WOTS_W - 1 - msg[1]; + msg += 2; + } + + /* Append checksum to message. (Maximum value: 1920 = 64 * 2 * 15) */ + msg[0] = (csum >> 8) ; + msg[1] = (csum >> 4) & 0x0f; + msg[2] = (csum ) & 0x0f; +} + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY + +/* WOTS+ generate public key with private seed. + * + * RFC 8391: 4.1.6, Algorithm 9: + * ... + * pk = WOTS_genPK (getWOTS_SK(SK, s + i), SEED, ADRS); + * RFC 8391, 3.1.4, Algorithm 4: WOTS_genPK + * ... + * for ( i = 0; i < len; i++ ) { + * ADRS.setChainAddress(i); + * pk[i] = chain(sk[i], 0, w - 1, SEED, ADRS); + * } + * return pk; + * + * WOTS_genPK only used in Algorithm 9 and it is convenient to combine with + * getWOTS_SK due to parameter specific implementations. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sk Random private seed. + * @param [in] seed Random public seed. + * @param [in] addr Hashing address. + * @param [out] pk Public key. + */ +static void wc_xmss_wots_gen_pk(XmssState* state, const byte* sk, + const byte* seed, HashAddress addr, byte* pk) +{ + const XmssParams* params = state->params; + byte* addr_buf = state->encMsg; + word32 i; + + /* Ensure chain address is 0 and encode into a buffer. */ + addr[XMSS_ADDR_CHAIN] = 0; + wc_xmss_addr_encode(addr, addr_buf); + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + /* Expand the private seed - getWOTS_SK */ + wc_xmss_wots_get_wots_sk_sha256_32(state, sk, seed, addr_buf, + pk); + + /* Calculate chain hash. */ + wc_xmss_chain_sha256_32(state, pk, 0, XMSS_WOTS_W - 1, seed, addr_buf, + pk); + for (i = 1; i < params->wots_len; i++) { + pk += params->n; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_chain_sha256_32(state, pk, 0, XMSS_WOTS_W - 1, seed, + addr_buf, pk); + } + } + else +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + { + /* Expand the private seed - getWOTS_SK */ + wc_xmss_wots_get_wots_sk(state, sk, seed, addr_buf, pk); + + /* Calculate chain hash. */ + wc_xmss_chain(state, pk, 0, XMSS_WOTS_W - 1, seed, addr_buf, pk); + for (i = 1; i < params->wots_len; i++) { + pk += params->n; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_chain(state, pk, 0, XMSS_WOTS_W - 1, seed, addr_buf, pk); + } + } +} +/* Generate a signature from a privatge key and message. + * + * RFC 8391: 4.1.9, Algorithm 11: treeSig + * sig_ots = WOTS_sign(getWOTS_SK(SK, idx_sig), + * M', getSEED(SK), ADRS); + * RFC 8391: 3.1.5, Algorithm 5: WOTS_sign + * (Convert message to base w and append checksum in base w) + * ... + * for ( i = 0; i < len; i++ ) { + * ADRS.setChainAddress(i); + * sig[i] = chain(sk[i], 0, msg[i], SEED, ADRS); + * } + * return sig; + * + * WOTS_sign only used in Algorithm 11 and convenient to do getWOTS_SK due to + * hash address reuse and parameter specific implementations. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] m Message hash to sign. + * @param [in] sk Random private seed. + * @param [in] seed Random public seed. + * @param [in] addr Hashing address. + * @param [out] sig Calculated XMSS/MT signature. + */ +static void wc_xmss_wots_sign(XmssState* state, const byte* m, + const byte* sk, const byte* seed, HashAddress addr, byte* sig) +{ + const XmssParams* params = state->params; + byte* addr_buf = state->pk; + word32 i; + + /* Convert message to base w and append checksum in base w. */ + wc_xmss_msg_convert(m, params->n, state->encMsg); + + /* Set initial chain value and encode hash address. */ + addr[XMSS_ADDR_CHAIN] = 0; + wc_xmss_addr_encode(addr, addr_buf); + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + /* Expand the private seed - getWOTS_SK */ + wc_xmss_wots_get_wots_sk_sha256_32(state, sk, seed, addr_buf, sig); + + /* Calculate chain hash. */ + wc_xmss_chain_sha256_32(state, sig, 0, state->encMsg[0], seed, addr_buf, + sig); + for (i = 1; i < params->wots_len; i++) { + sig += params->n; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_chain_sha256_32(state, sig, 0, state->encMsg[i], seed, + addr_buf, sig); + } + } + else +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + { + /* Expand the private seed - getWOTS_SK */ + wc_xmss_wots_get_wots_sk(state, sk, seed, addr_buf, sig); + + /* Calculate chain hash. */ + wc_xmss_chain(state, sig, 0, state->encMsg[0], seed, addr_buf, sig); + for (i = 1; i < params->wots_len; i++) { + sig += params->n; + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_chain(state, sig, 0, state->encMsg[i], seed, addr_buf, sig); + } + } +} + +#endif /* !WOLFSSL_XMSS_VERIFY_ONLY */ + +/* Compute WOTS+ public key value from signature and message. + * + * RFC 8319: 3.1.6 + * Algorithm 6: WOTS_pkFromSig + * (Convert message to base w and append checksum in base w) + * ... + * for ( i = 0; i < len; i++ ) { + * ADRS.setChainAddress(i); + * tmp_pk[i] = chain(sig[i], msg[i], w - 1 - msg[i], SEED, ADRS); + * } + * return tmp_pk; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sig XMSS/MT Signature. + * @param [in] m Message to verify. + * @param [in] seed Random public seed. + * @param [in] addr Hashing address. + * @param [out] pk Public key. + */ +static void wc_xmss_wots_pk_from_sig(XmssState* state, const byte* sig, + const byte* m, const byte* seed, HashAddress addr, byte* pk) +{ + const XmssParams* params = state->params; + byte* addr_buf = state->stack; + word32 i; + + /* Convert message to base w and append checksum in base w. */ + wc_xmss_msg_convert(m, params->n, state->encMsg); + + /* Start with address with chain value of 0. */ + addr[XMSS_ADDR_CHAIN] = 0; + wc_xmss_addr_encode(addr, addr_buf); + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + /* Calculate chain hash. */ + wc_xmss_chain_sha256_32(state, sig, state->encMsg[0], + XMSS_WOTS_W - 1 - state->encMsg[0], seed, addr_buf, pk); + for (i = 1; i < params->wots_len; i++) { + sig += params->n; + pk += params->n; + /* Update chain. */ + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_chain_sha256_32(state, sig, state->encMsg[i], + XMSS_WOTS_W - 1 - state->encMsg[i], seed, addr_buf, pk); + } + } + else +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 */ + { + /* Calculate chain hash. */ + wc_xmss_chain(state, sig, state->encMsg[0], + XMSS_WOTS_W - 1 - state->encMsg[0], seed, addr_buf, pk); + for (i = 1; i < params->wots_len; i++) { + sig += params->n; + pk += params->n; + /* Update chain. */ + addr_buf[XMSS_ADDR_CHAIN * 4 + 3] = i; + wc_xmss_chain(state, sig, state->encMsg[i], + XMSS_WOTS_W - 1 - state->encMsg[i], seed, addr_buf, pk); + } + } +} + +/******************************************** + * L-TREE - unbalanced binary hash tree + ********************************************/ + +/* Compute leaves of L-tree from WOTS+ public key and compress to single value. + * + * RFC 8391: 4.1.5, Algorithm 8: ltree + * unsigned int len' = len; + * ADRS.setTreeHeight(0); + * while ( len' > 1 ) { + * for ( i = 0; i < floor(len' / 2); i++ ) { + * ADRS.setTreeIndex(i); + * pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); + * } + * if ( len' % 2 == 1 ) { + * pk[floor(len' / 2)] = pk[len' - 1]; + * } + * len' = ceil(len' / 2); + * ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); + * } + * return pk[0]; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] pk WOTS+ public key. + * @param [in] seed Random public seed. + * @param [in] addr Hashing address. + * @param [out] pk0 N-byte compressed public key value pk[0]. + */ +static void wc_xmss_ltree(XmssState* state, byte* pk, const byte* seed, + HashAddress addr, byte* pk0) +{ + const XmssParams* params = state->params; + word8 len = params->wots_len; + word32 h = 0; + +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) && \ + !defined(WC_XMSS_FULL_HASH) + /* Precompute hash state after first 64 bytes (common to all hashes). */ + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + byte* prf_buf = state->prf_buf; + int ret; + + XMSS_PAD_ENC(XMSS_HASH_PADDING_PRF, prf_buf, XMSS_SHA256_32_PAD_LEN); + XMEMCPY(prf_buf + XMSS_SHA256_32_PAD_LEN, seed, XMSS_SHA256_32_N); + + ret = wc_Sha256Update(&state->digest.sha256, prf_buf, + XMSS_SHA256_32_PAD_LEN + XMSS_SHA256_32_N); + if (ret == 0) { + /* Copy state after first 64 bytes. */ + XMSS_SHA256_STATE_CACHE(state); + } + else if (state->ret == 0) { + /* Store any digest failures for public APIs to return. */ + state->ret = ret; + } + } +#endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 && !WC_XMSS_FULL_HASH */ + while (len > 1) { + word8 i; + word8 len2 = len >> 1; + + addr[XMSS_ADDR_TREE_HEIGHT] = h++; + + for (i = 0; i < len2; i++) { + addr[XMSS_ADDR_TREE_INDEX] = i; + #if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) && \ + !defined(WC_XMSS_FULL_HASH) + if ((params->pad_len == XMSS_SHA256_32_PAD_LEN) && + (params->n == XMSS_SHA256_32_N) && + (params->hash == WC_HASH_TYPE_SHA256)) { + wc_xmss_rand_hash_sha256_32_prehash(state, + pk + i * 2 * XMSS_SHA256_32_N, addr, + pk + i * XMSS_SHA256_32_N); + } + else + #endif /* !WOLFSSL_WC_XMSS_SMALL && WC_XMSS_SHA256 && + * !WC_XMSS_FULL_HASH */ + { + wc_xmss_rand_hash(state, pk + i * 2 * params->n, + seed, addr, pk + i * params->n); + } + } + if (len & 1) { + XMEMCPY(pk + len2 * params->n, pk + (len - 1) * params->n, + params->n); + } + len = len2 + (len & 1); + } + /* Return compressed public key value pk[0]. */ + XMEMCPY(pk0, pk, params->n); +} + +#ifndef WOLFSSL_XMSS_VERIFY_ONLY + +#ifdef WOLFSSL_WC_XMSS_SMALL + +/******************************************** + * TREE HASH + ********************************************/ + +#ifndef WOLFSSL_SMALL_STACK +/* Compute internal nodes of Merkle tree. + * + * Implementation always starts at index 0. (s = 0) + * + * Build authentication path, if required, rather than duplicating work. + * When node is generated, copy out to authentication path array of nodes. + * + * RFC 8391: 4.1.6, Algorithm 9: treeHash + * if( s % (1 << t) != 0 ) return -1; + * for ( i = 0; i < 2^t; i++ ) { + * SEED = getSEED(SK); + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(s + i); + * pk = WOTS_genPK (getWOTS_SK(SK, s + i), SEED, ADRS); + * ADRS.setType(1); # Type = L-tree address + * ADRS.setLTreeAddress(s + i); + * node = ltree(pk, SEED, ADRS); + * ADRS.setType(2); # Type = hash tree address + * ADRS.setTreeHeight(0); + * ADRS.setTreeIndex(i + s); + * while ( Top node on Stack has same height t' as node ) { + * ADRS.setTreeIndex((ADRS.getTreeIndex() - 1) / 2); + * node = RAND_HASH(Stack.pop(), node, SEED, ADRS); + * ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); + * } + * Stack.push(node); + * } + * return Stack.pop(); + * RFC 8391: 4.1.9, (Example) buildAuth + * for ( j = 0; j < h; j++ ) { + * k = floor(i / (2^j)) XOR 1; + * auth[j] = treeHash(SK, k * 2^j, j, ADRS); + * } + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sk_seed Random private seed. + * @param [in] pk_seed Random public seed. + * @param [in] leafIdx Index of lead node. + * @param [in] subtree_addr Address of subtree. + * @param [out] root Root node of the tree. + * @param [out] auth_path Nodes of the authentication path. + */ +static void wc_xmss_treehash(XmssState* state, const byte* sk_seed, + const byte* pk_seed, word32 leafIdx, const word32* subtree, byte* root, + byte* auth_path) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + byte* node = state->stack; + HashAddress ots; + HashAddress ltree; + HashAddress tree; + word8 height[WC_XMSS_MAX_TREE_HEIGHT + 1]; + word8 offset = 0; + word32 max = (word32)1 << params->sub_h; + word32 i; + + /* Copy hash address into one for each purpose. */ + XMSS_ADDR_OTS_SET_SUBTREE(ots, subtree); + XMSS_ADDR_LTREE_SET_SUBTREE(ltree, subtree); + XMSS_ADDR_TREE_SET_SUBTREE(tree, subtree); + + for (i = 0; i < max; i++) { + word8 h; + + /* Calculate WOTS+ public key. */ + ots[XMSS_ADDR_OTS] = i; + wc_xmss_wots_gen_pk(state, sk_seed, pk_seed, ots, state->pk); + /* Calculate public value. */ + ltree[XMSS_ADDR_LTREE] = i; + wc_xmss_ltree(state, state->pk, pk_seed, ltree, node); + + /* Initial height at this offset is 0. */ + h = height[offset] = 0; + /* Copy node, at height 0, out if on authentication path. */ + if ((auth_path != NULL) && ((leafIdx ^ 0x1) == i)) { + XMEMCPY(auth_path, node, n); + } + + /* Top node on Stack has same height t' as node. */ + while ((offset >= 1) && (h == height[offset - 1])) { + word32 tree_idx = i >> (h + 1); + + node -= n; + /* Calculate hash of node. */ + tree[XMSS_ADDR_TREE_HEIGHT] = h; + tree[XMSS_ADDR_TREE_INDEX] = tree_idx; + wc_xmss_rand_hash(state, node, pk_seed, tree, node); + + /* Update offset and height. */ + offset--; + h = ++height[offset]; + + /* Copy node out if on authentication path. */ + if ((auth_path != NULL) && (((leafIdx >> h) ^ 0x1) == tree_idx)) { + XMEMCPY(auth_path + h * n, node, n); + } + } + offset++; + node += n; + } + + /* Copy the root node. */ + XMEMCPY(root, state->stack, n); +} +#else +/* Compute internal nodes of Merkle tree. + * + * Implementation always starts at index 0. (s = 0) + * + * Build authentication path, if required, rather than duplicating work. + * When node is generated, copy out to authentication path array of nodes. + * + * RFC 8391: 4.1.6, Algorithm 9: treeHash + * if( s % (1 << t) != 0 ) return -1; + * for ( i = 0; i < 2^t; i++ ) { + * SEED = getSEED(SK); + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(s + i); + * pk = WOTS_genPK (getWOTS_SK(SK, s + i), SEED, ADRS); + * ADRS.setType(1); # Type = L-tree address + * ADRS.setLTreeAddress(s + i); + * node = ltree(pk, SEED, ADRS); + * ADRS.setType(2); # Type = hash tree address + * ADRS.setTreeHeight(0); + * ADRS.setTreeIndex(i + s); + * while ( Top node on Stack has same height t' as node ) { + * ADRS.setTreeIndex((ADRS.getTreeIndex() - 1) / 2); + * node = RAND_HASH(Stack.pop(), node, SEED, ADRS); + * ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); + * } + * Stack.push(node); + * } + * return Stack.pop(); + * RFC 8391: 4.1.9, (Example) buildAuth + * for ( j = 0; j < h; j++ ) { + * k = floor(i / (2^j)) XOR 1; + * auth[j] = treeHash(SK, k * 2^j, j, ADRS); + * } + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sk_seed Random private seed. + * @param [in] pk_seed Random public seed. + * @param [in] leafIdx Index of lead node. + * @param [in] subtree_addr Address of subtree. + * @param [out] root Root node of the tree. + * @param [out] auth_path Nodes of the authentication path. + */ +static void wc_xmss_treehash(XmssState* state, const byte* sk_seed, + const byte* pk_seed, word32 leafIdx, const word32* subtree, byte* root, + byte* auth_path) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + byte* node = state->stack; + HashAddress addr; + word8 height[WC_XMSS_MAX_TREE_HEIGHT + 1]; + word8 offset = 0; + word32 max = (word32)1 << params->sub_h; + word32 i; + + XMSS_ADDR_SET_SUBTREE(addr, subtree, 0); + + for (i = 0; i < max; i++) { + word8 h; + + /* Calculate WOTS+ public key. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + addr[XMSS_ADDR_LTREE] = i; + wc_xmss_wots_gen_pk(state, sk_seed, pk_seed, addr, state->pk); + /* Calculate public value. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_LTREE; + wc_xmss_ltree(state, state->pk, pk_seed, addr, node); + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_TREE; + addr[XMSS_ADDR_TREE_ZERO] = 0; + + /* Initial height at this offset is 0. */ + h = height[offset] = 0; + /* Copy node out if on authentication path. */ + if ((auth_path != NULL) && ((leafIdx ^ 0x1) == i)) { + XMEMCPY(auth_path, node, n); + } + + /* Top node on Stack has same height t' as node. */ + while ((offset >= 1) && (h == height[offset - 1])) { + word32 tree_idx = i >> (h + 1); + + node -= n; + /* Calculate hash of node. */ + addr[XMSS_ADDR_TREE_HEIGHT] = h; + addr[XMSS_ADDR_TREE_INDEX] = tree_idx; + wc_xmss_rand_hash(state, node, pk_seed, addr, node); + + /* Update offset and height. */ + offset--; + h = ++height[offset]; + + /* Copy node out if on authentication path. */ + if ((auth_path != NULL) && (((leafIdx >> h) ^ 0x1) == tree_idx)) { + XMEMCPY(auth_path + h * n, node, n); + } + } + offset++; + node += n; + /* Reset hash address ready for use as OTS and LTREE. */ + addr[XMSS_ADDR_TREE_HEIGHT] = 0; + addr[XMSS_ADDR_TREE_INDEX] = 0; + } + + /* Copy the root node. */ + XMEMCPY(root, state->stack, n); +} +#endif /* !WOLFSSL_SMALL_STACK */ + +/******************************************** + * MAKE KEY + ********************************************/ + +/* Derives XMSSMT (and XMSS) key pair from seeds. + * + * RFC 8391: 4.1.7, Algorithm 10: XMSS_keyGen. + * ... + * initialize SK_PRF with a uniformly random n-byte string; + * setSK_PRF(SK, SK_PRF); + * + * # Initialization for common contents + * initialize SEED with a uniformly random n-byte string; + * setSEED(SK, SEED); + * setWOTS_SK(SK, wots_sk)); + * ADRS = toByte(0, 32); + * root = treeHash(SK, 0, h, ADRS); + * + * SK = idx || wots_sk || SK_PRF || root || SEED; + * PK = OID || root || SEED; + * return (SK || PK); + * + * wots_sk, SK_PRF and SEED passed in as seed. + * Store seed for wots_sk instead of generated wots_sk. + * OID not stored in PK this is handled in upper layer. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] seed Random seeds. + * @param [out] sk Secret/Private key. + * @param [out] pk Public key. + * @return 0 on success. + * @return <0 on digest failure. + */ +int wc_xmssmt_keygen(XmssState* state, const unsigned char* seed, + unsigned char* sk, unsigned char* pk) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + const byte* seed_priv = seed; + const byte* seed_pub = seed + 2 * n; + /* Offsets into secret/private key. */ + byte* sk_idx = sk; + byte* sk_seed = sk_idx + params->idx_len; + byte* sk_pub = sk_seed + 2 * n; + /* Offsets into public key. */ + byte* pk_root = pk; + byte* pk_seed = pk_root + n; + + /* Set first index to 0 in private key. */ + XMEMSET(sk_idx, 0, params->idx_len); + /* Set private key seed and private key for PRF in to private key. */ + XMEMCPY(sk_seed, seed_priv, 2 * n); + /* Set public key seed into public key. */ + XMEMCPY(pk_seed, seed_pub, n); + + /* Set all address values to zero. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + /* Set depth into address. */ + state->addr[XMSS_ADDR_LAYER] = params->d - 1; + /* Compute root node into public key. */ + wc_xmss_treehash(state, sk_seed, pk_seed, 0, state->addr, pk_root, NULL); + + /* Append public key (root node and public seed) to private key. */ + XMEMCPY(sk_pub, pk_root, 2 * n); + + /* Return any errors that occurred during hashing. */ + return state->ret; +} + +/******************************************** + * SIGN + ********************************************/ + +/** + * Sign message using XMSS/XMSS^MT. + * + * RFC 8391: 4.1.9, Algorithm 11: treeSig + * auth = buildAuth(SK, idx_sig, ADRS); + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(idx_sig); + * sig_ots = WOTS_sign(getWOTS_SK(SK, idx_sig), + * M', getSEED(SK), ADRS); + * Sig = sig_ots || auth; + * return Sig; + * RFC 8391: 4.2.4, Algorithm 16: XMSSMT_sign + * # Init + * ADRS = toByte(0, 32); + * SEED = getSEED(SK_MT); + * SK_PRF = getSK_PRF(SK_MT); + * idx_sig = getIdx(SK_MT); + * + * # Update SK_MT + * setIdx(SK_MT, idx_sig + 1); + * + * # Message compression + * byte[n] r = PRF(SK_PRF, toByte(idx_sig, 32)); + * byte[n] M' = H_msg(r || getRoot(SK_MT) || (toByte(idx_sig, n)), M); + * + * # Sign + * Sig_MT = idx_sig; + * unsigned int idx_tree + * = (h - h / d) most significant bits of idx_sig; + * unsigned int idx_leaf = (h / d) least significant bits of idx_sig; + * SK = idx_leaf || getXMSS_SK(SK_MT, idx_tree, 0) || SK_PRF + * || toByte(0, n) || SEED; + * ADRS.setLayerAddress(0); + * ADRS.setTreeAddress(idx_tree); + * Sig_tmp = treeSig(M', SK, idx_leaf, ADRS); + * Sig_MT = Sig_MT || r || Sig_tmp; + * for ( j = 1; j < d; j++ ) { + * root = treeHash(SK, 0, h / d, ADRS); + * idx_leaf = (h / d) least significant bits of idx_tree; + * idx_tree = (h - j * (h / d)) most significant bits of idx_tree; + * SK = idx_leaf || getXMSS_SK(SK_MT, idx_tree, j) || SK_PRF + * || toByte(0, n) || SEED; + * ADRS.setLayerAddress(j); + * ADRS.setTreeAddress(idx_tree); + * Sig_tmp = treeSig(root, SK, idx_leaf, ADRS); + * Sig_MT = Sig_MT || Sig_tmp; + * } + * return SK_MT || Sig_MT + * + * buildAuth from treeSig done inside treeHash as this is more efficient. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] m Buffer holding message. + * @param [in] mlen Length of message in buffer. + * @param [in, out] sk Secret/Private key. + * @param [out] sig Signature. + * @return 0 on success. + * @return <0 on digest failure. + */ +int wc_xmssmt_sign(XmssState* state, const unsigned char* m, word32 mlen, + unsigned char* sk, unsigned char* sig) +{ + int ret = 0; + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 hs = params->sub_h; + const word16 hsn = (word16)hs * n; + const byte* sk_seed = sk + params->idx_len; + const byte* pk_seed = sk + params->idx_len + 3 * n; + wc_Idx idx; + byte* sig_r = sig + params->idx_len; + byte root[WC_XMSS_MAX_N]; + unsigned int i; + + WC_IDX_ZERO(idx); + /* Set all address values to zero and set type to OTS. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + state->addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + + /* Copy the index into the signature data: Sig_MT = idx_sig. */ + XMEMCPY(sig, sk, params->idx_len); + + /* Read index from the secret key. */ + WC_IDX_DECODE(idx, params->idx_len, sk, ret); + /* Validate index in secret key. */ + if ((ret == 0) && (WC_IDX_INVALID(idx, params->idx_len, params->h))) { + /* Set index to maximum value to distinguish from valid value. */ + XMEMSET(sk, 0xFF, params->idx_len); + /* Zeroize the secret key. */ + ForceZero(sk + params->idx_len, params->sk_len - params->idx_len); + ret = KEY_EXHAUSTED_E; + } + + /* Update SK_MT */ + if (ret == 0) { + /* Increment the index in the secret key. */ + wc_idx_update(sk, params->idx_len); + } + + /* Message compression */ + if (ret == 0) { + const byte* sk_prf = sk + params->idx_len + n; + + /* byte[n] r = PRF(SK_PRF, toByte(idx_sig, 32)); */ + wc_idx_copy(sig, params->idx_len, state->buf, XMSS_PRF_M_LEN); + wc_xmss_prf(state, sk_prf, state->buf, sig_r); + ret = state->ret; + } + if (ret == 0) { + const byte* pub_root = sk + params->idx_len + 2 * n; + /* byte[n] M' = H_msg(r || getRoot(SK_MT) || (toByte(idx_sig, n)), M); + */ + wc_xmss_hash_message(state, sig_r, pub_root, sig, params->idx_len, m, + mlen, root); + ret = state->ret; + /* Place WOTS+ signatures after index and 'r'. */ + sig += params->idx_len + n; + } + + /* Sign. */ + for (i = 0; (ret == 0) && (i < params->d); i++) { + word32 idx_leaf = 0; + + /* Set layer, tree and OTS leaf index into hash address. */ + state->addr[XMSS_ADDR_LAYER] = i; + WC_IDX_SET_ADDR_TREE(idx, params->idx_len, hs, state->addr, idx_leaf); + /* treeSig || treeHash = sig_ots || auth */ + state->addr[XMSS_ADDR_OTS] = idx_leaf; + /* Create WOTS+ signature for tree into signature (sig_ots). */ + wc_xmss_wots_sign(state, root, sk_seed, pk_seed, state->addr, sig); + ret = state->ret; + if (ret == 0) { + sig += params->wots_sig_len; + /* Add authentication path (auth) and calc new root. */ + wc_xmss_treehash(state, sk_seed, pk_seed, idx_leaf, state->addr, + root, sig); + ret = state->ret; + sig += hsn; + } + } + + return ret; +} + +#else + +/******************************************** + * Fast C implementation + ********************************************/ + +/* Tree hash data - needs to be unpacked from binary. */ +typedef struct TreeHash { + /* Next index to update in tree - max 20 bits. */ + word32 nextIdx; + /* Number of stack entries used by tree - 0... */ + word8 used; + /* Tree is finished. */ + word8 completed; +} TreeHash; + +/* BDS state. */ +typedef struct BdsState { + /* Stack of nodes - subtree height + 1 nodes. */ + byte* stack; + /* Height of stack node - subtree height + 1 of 0... */ + byte* height; + /* Authentication path for next index - subtree height nodes. */ + byte* authPath; + /* Hashes of nodes kept - subtree height / 2 nodes. */ + byte* keep; + /* Tree hash instances - subtree height minus K instances. */ + byte* treeHash; + /* Hashes of nodes for tree hash - one for each tree hash instance. */ + byte* treeHashNode; + /* Hashes of nodes to retain - based on K parameter. */ + byte* retain; + /* Next leaf to calculate - max 20 bits. */ + word32 next; + /* Current offset into stack - 0... */ + word8 offset; +} BdsState; + +/* Index to BDS state accounting for swapping. + * + * @param [in] idx Index of node. + * @param [in] i Depth of tree. + * @param [in] hs Height of subtree. + * @param [in] d Depth/number of trees. + * @return Index of working BDS state. + */ +#define BDS_IDX(idx, i, hs, d) \ + (((((idx) >> ((hs) * ((i) + 1))) & 1) == 0) ? (i) : ((d) + (i))) +/* Index to alternate BDS state accounting for swapping. + * + * @param [in] idx Index of node. + * @param [in] i Depth of tree. + * @param [in] hs Height of subtree. + * @param [in] d Depth/number of trees. + * @return Index of alternate BDS state. + */ +#define BDS_ALT_IDX(idx, i, hs, d) \ + (((((idx) >> ((hs) * ((i) + 1))) & 1) == 0) ? ((d) + (i)) : (i)) + +/******************************************** + * Tree Hash APIs + ********************************************/ + +/* Initialize the tree hash data at specified index for the BDS state. + * + * @param [in, out] bds BDS state. + * @param [in] i Index of tree hash. + */ +static void wc_xmss_bds_state_treehash_init(BdsState* bds, int i) +{ + byte* sk = bds->treeHash + i * 4; + c32to24(0, sk); + sk[3] = 0 | (1 << 7); +} + +/* Set next index into tree hash data at specified index for the BDS state. + * + * @param [in, out] bds BDS state. + * @param [in] i Index of tree hash. + * @param [in] nextIdx Next index for tree hash. + */ +static void wc_xmss_bds_state_treehash_set_next_idx(BdsState* bds, int i, + word32 nextIdx) +{ + byte* sk = bds->treeHash + i * 4; + c32to24(nextIdx, sk); + sk[3] = 0 | (0 << 7); +} + +/* Mark tree hash, at specified index for the BDS state, as complete. + * + * @param [in, out] bds BDS state. + * @param [in] i Index of tree hash. + */ +static void wc_xmss_bds_state_treehash_complete(BdsState* bds, int i) +{ + byte* sk = bds->treeHash + i * 4; + sk[3] |= 1 << 7; +} + +/* Get the tree hash data at specified index for the BDS state. + * + * @param [in] bds BDS state. + * @param [in] i Index of tree hash. + * @param [out] treeHash Tree hash instance to fill out. + */ +static void wc_xmss_bds_state_treehash_get(BdsState* bds, int i, + TreeHash* treeHash) +{ + byte* sk = bds->treeHash + i * 4; + ato24(sk, &treeHash->nextIdx); + treeHash->used = sk[3] & 0x7f; + treeHash->completed = sk[3] >> 7; +} + +/* Set the tree hash data at specified index for the BDS state. + * + * @param [in, out] bds BDS state. + * @param [in] i Index of tree hash. + * @param [in] treeHash Tree hash data. + */ +static void wc_xmss_bds_state_treehash_set(BdsState* bds, int i, + TreeHash* treeHash) +{ + byte* sk = bds->treeHash + i * 4; + c32to24(treeHash->nextIdx, sk); + sk[3] = treeHash->used | (treeHash->completed << 7); +} + +/******************************************** + * BDS State APIs + ********************************************/ + +/* Allocate memory for BDS state. + * + * When using a static BDS state (XMSS) then pass in handle to data for bds. + * + * @param [in] params XMSS/MT parameters. + * @param [in, out] bds Handle to BDS state. May be NULL if not allocated. + * @return 0 on success. + * @return MEMORY_E on dynamic memory allocation failure. + */ +static int wc_xmss_bds_state_alloc(const XmssParams* params, BdsState** bds) +{ + const word8 cnt = 2 * params->d - 1; + int ret = 0; + + if (*bds == NULL) { + /* Allocate memory for BDS states. */ + *bds = (BdsState*)XMALLOC(sizeof(BdsState) * cnt, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (*bds == NULL) { + ret = MEMORY_E; + } + } + + return ret; +} + +/* Dispose of allocated memory associated with BDS state. + * + * @param [in] bds BDS state. + */ +static void wc_xmss_bds_state_free(BdsState* bds) +{ + /* BDS states was allocated - must free. */ + XFREE(bds, NULL, DYNAMIC_TYPE_TMP_BUFFER); +} + +/* Load the BDS state from the secret/private key. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] sk Secret/private key. + * @param [out] bds BDS states. + * @param [out] wots_sigs WOTS signatures when XMSS^MT. + */ +static void wc_xmss_bds_state_load(const XmssState* state, byte* sk, + BdsState* bds, byte** wots_sigs) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 hs = params->sub_h; + const word8 hsk = params->sub_h - params->bds_k; + const word8 k = params->bds_k; + const word32 retainLen = XMSS_RETAIN_LEN(k, n); + int i; + + /* Skip past standard SK = idx || wots_sk || SK_PRF || root || SEED; */ + sk += params->idx_len + 4 * n; + + for (i = 0; i < 2 * (int)params->d - 1; i++) { + /* Set pointers into SK. */ + bds[i].stack = sk; + sk += (hs + 1) * n; + bds[i].height = sk; + sk += hs + 1; + bds[i].authPath = sk; + sk += hs * n; + bds[i].keep = sk; + sk += (hs >> 1) * n; + bds[i].treeHash = sk; + sk += hsk * 4; + bds[i].treeHashNode = sk; + sk += hsk * n; + bds[i].retain = sk; + sk += retainLen; + /* Load values - big-endian encoded. */ + ato24(sk, &bds[i].next); + sk += 3; + bds[i].offset = sk[0]; + sk += 1; + } + + if (wots_sigs != NULL) { + *wots_sigs = sk; + } +} + +/* Store the BDS state into the secret/private key. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] sk Secret/private key. + * @param [in] bds BDS states. + */ +static void wc_xmss_bds_state_store(const XmssState* state, byte* sk, + BdsState* bds) +{ + int i; + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 hs = params->sub_h; + const word8 hsk = params->sub_h - params->bds_k; + const word8 k = params->bds_k; + const word32 skip = (hs + 1) * n + /* BdsState.stack */ + hs + 1 + /* BdsState.height */ + hs * n + /* BdsState.authPath */ + (hs >> 1) * n + /* BdsState.keep */ + hsk * 4 + /* BdsState.treeHash */ + hsk * n + /* BdsState.treeHashNode */ + XMSS_RETAIN_LEN(k, n); /* BdsState.retain */ + + /* Ignore standard SK = idx || wots_sk || SK_PRF || root || SEED; */ + sk += params->idx_len + 4 * n; + + for (i = 0; i < 2 * (int)params->d - 1; i++) { + /* Skip pointers into sk. */ + sk += skip; + /* Save values - big-endian encoded. */ + c32to24(bds[i].next, sk); + sk += 3; + sk[0] = bds[i].offset; + sk += 1; + } +} + +/******************************************** + * BDS + ********************************************/ + +/* Compute node at next index. + * + * RFC 8391: 4.1.6, Algorithm 9: treeHash + * ... + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(s + i); + * pk = WOTS_genPK (getWOTS_SK(SK, s + i), SEED, ADRS); + * ADRS.setType(1); # Type = L-tree address + * ADRS.setLTreeAddress(s + i); + * node = ltree(pk, SEED, ADRS); + * ADRS.setType(2); # Type = hash tree address + * ADRS.setTreeHeight(0); + * ADRS.setTreeIndex(i + s); + * while ( Top node on Stack has same height t' as node ) { + * ADRS.setTreeIndex((ADRS.getTreeIndex() - 1) / 2); + * node = RAND_HASH(Stack.pop(), node, SEED, ADRS); + * ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); + * } + * Stack.push(node); + * ... + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] bds BDS state. + * @param [in] sk_seed Random secret/private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [out] root Root node. + */ +static void wc_xmss_bds_next_idx(XmssState* state, BdsState* bds, + const byte* sk_seed, const byte* pk_seed, HashAddress addr, int i, + word8* height, word8* offset, word8** sp) +{ + const XmssParams* params = state->params; + const word8 hs = params->sub_h; + const word8 hsk = params->sub_h - params->bds_k; + const word8 n = params->n; + word8 o = *offset; + word8* node = *sp; + word8 h; + + /* Calculate WOTS+ public key. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + addr[XMSS_ADDR_OTS] = i; + wc_xmss_wots_gen_pk(state, sk_seed, pk_seed, addr, state->pk); + /* Calculate public value. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_LTREE; + wc_xmss_ltree(state, state->pk, pk_seed, addr, node); + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_TREE; + addr[XMSS_ADDR_TREE_ZERO] = 0; + + /* Initial height at this offset is 0. */ + h = height[o] = 0; + /* HDSS, Section 4.5, 2: TREEHASH[h].push(v[h][3]) + * Copy right node to tree hash nodes if second right node. */ + if ((hsk > 0) && (i == 3)) { + XMEMCPY(bds->treeHashNode, node + n, n); + } + + /* Top node on Stack has same height t' as node. */ + while ((o >= 1) && (h == height[o - 1])) { + /* HDSS, Section 4.5, 1: AUTH[h] = v[h][1], h = 0,...,H-1. + * Cache left node if on authentication path. */ + if ((i >> h) == 1) { + XMEMCPY(bds->authPath + h * n, node, n); + } + /* This is a right node. */ + else if (h < hsk) { + /* HDSS, Section 4.5, 2: TREEHASH[h].push(v[h][3]) + * Copy right node to tree hash if second right node. */ + if ((i >> h) == 3) { + XMEMCPY(bds->treeHashNode + h * n, node, n); + } + } + else { + /* HDSS, Section 4.5, 3: RETAIN[h].push(v[j][2j+3] for + * h = H-K,...,H-2 and j = 2^(H-h-1)-2,...,0. + * Retain high right nodes. + */ + word32 ro = (1 << (hs - 1 - h)) + h - hs + (((i >> h) - 3) >> 1); + XMEMCPY(bds->retain + ro * n, node, n); + } + + node -= n; + /* Calculate hash of node. */ + addr[XMSS_ADDR_TREE_HEIGHT] = h; + addr[XMSS_ADDR_TREE_INDEX] = i >> (h + 1); + wc_xmss_rand_hash(state, node, pk_seed, addr, node); + + /* Update offset and height. */ + o--; + h = ++height[o]; + } + + *offset = o; + *sp = node; +} + +/* Compute initial Merkle tree and store nodes. + * + * HDSS, Section 4.5, The algorithm, Initialization. + * 1. We store the authentication path for the first leaf (s = 0): + * AUTH[h] = v[h][1], h = 0,...,H-1. + * 2. Depending on the parameter K, we store the next right authentication + * node for each height h = 0,...,H-K-1 in the treehash instances: + * TREEHASH[h].push(v[h][3]). + * 3. Finally we store the right authentication nodes clode to the root using + * the stacks RETAIN[h]: + * RETAIN[h].push(v[j][2j+3] for h = H-K,...,H-2 and j = 2^(H-h-1)-2,...,0. + * + * RFC 8391: 4.1.6, Algorithm 9: treeHash + * if( s % (1 << t) != 0 ) return -1; + * for ( i = 0; i < 2^t; i++ ) { + * SEED = getSEED(SK); + * [Compute node at next index] + * } + * return Stack.pop(); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] bds BDS state. + * @param [in] sk_seed Random secret/private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [out] root Root node. + */ +static void wc_xmss_bds_treehash_initial(XmssState* state, BdsState* bds, + const byte* sk_seed, const byte* pk_seed, const HashAddress addr, + byte* root) +{ + const XmssParams* params = state->params; + const word8 hsk = params->sub_h - params->bds_k; + const word8 n = params->n; + word8* node = state->stack; + HashAddress addrCopy; + word8 height[WC_XMSS_MAX_TREE_HEIGHT + 1]; + word8 offset = 0; + word32 maxIdx = (word32)1 << params->sub_h; + word32 i; + + /* First signing index will be 0 - setup BDS state. */ + bds->offset = 0; + bds->next = 0; + /* Reset the hash tree status. */ + for (i = 0; i < hsk; i++) { + wc_xmss_bds_state_treehash_init(bds, i); + } + + /* Copy hash address into local. */ + XMSS_ADDR_OTS_SET_SUBTREE(addrCopy, addr); + + /* Compute each node in tree. */ + for (i = 0; i < maxIdx; i++) { + wc_xmss_bds_next_idx(state, bds, sk_seed, pk_seed, addrCopy, i, height, + &offset, &node); + offset++; + node += n; + /* Rest the hash address for reuse. */ + addrCopy[XMSS_ADDR_TREE_HEIGHT] = 0; + addrCopy[XMSS_ADDR_TREE_INDEX] = 0; + } + + /* Copy the root node. */ + XMEMCPY(root, state->stack, n); +} + +/* Update internal nodes of Merkle tree at next index. + * + * RFC 8391: 4.1.6, Algorithm 9: treeHash + * ... + * SEED = getSEED(SK); + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(s + i); + * pk = WOTS_genPK (getWOTS_SK(SK, s + i), SEED, ADRS); + * ADRS.setType(1); # Type = L-tree address + * ADRS.setLTreeAddress(s + i); + * node = ltree(pk, SEED, ADRS); + * ADRS.setType(2); # Type = hash tree address + * ADRS.setTreeHeight(0); + * ADRS.setTreeIndex(i + s); + * while ( Top node on Stack has same height t' as node ) { + * ADRS.setTreeIndex((ADRS.getTreeIndex() - 1) / 2); + * node = RAND_HASH(Stack.pop(), node, SEED, ADRS); + * ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); + * } + * Stack.push(node); + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] bds BDS state. + * @param [in] height Height of nodes to update. + * @param [in] sk_seed Random secret/private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + */ +static void wc_xmss_bds_treehash_update(XmssState* state, BdsState* bds, + word8 height, const byte* sk_seed, const byte* pk_seed, + const HashAddress addr) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + HashAddress addrLocal; + TreeHash treeHash[1]; + byte* sp = bds->stack + bds->offset * n; + byte* node = state->stack + WC_XMSS_MAX_STACK_LEN - n; + word8 h; + + /* Get the tree hash data. */ + wc_xmss_bds_state_treehash_get(bds, height, treeHash); + /* Copy hash address into local as OTS type. */ + XMSS_ADDR_OTS_SET_SUBTREE(addrLocal, addr); + /* Calculate WOTS+ public key. */ + addrLocal[XMSS_ADDR_OTS] = treeHash->nextIdx; + wc_xmss_wots_gen_pk(state, sk_seed, pk_seed, addrLocal, state->pk); + /* Calculate public value. */ + addrLocal[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_LTREE; + wc_xmss_ltree(state, state->pk, pk_seed, addrLocal, node); + addrLocal[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_TREE; + addrLocal[XMSS_ADDR_TREE_ZERO] = 0; + + /* Initial height is 0. */ + h = 0; + + /* Top node on Stack has same height t' as node. */ + while ((treeHash->used > 0) && (h == bds->height[bds->offset - 1])) { + sp -= n; + /* Copy from stack to before last calculated node. */ + node -= n; + XMEMCPY(node, sp, n); + + /* Calculate hash of node. */ + addrLocal[XMSS_ADDR_TREE_HEIGHT] = h; + addrLocal[XMSS_ADDR_TREE_INDEX] = treeHash->nextIdx >> (h + 1); + wc_xmss_rand_hash(state, node, pk_seed, addrLocal, node); + + /* Update used, offset and height. */ + treeHash->used--; + bds->offset--; + h++; + } + + /* Check whether we reached the height we wanted to update. */ + if (h == height) { + /* Cache node. */ + XMEMCPY(bds->treeHashNode + height * n, node, n); + treeHash->completed = 1; + } + else { + /* Push calculated node onto stack. */ + XMEMCPY(sp, node, n); + treeHash->used++; + /* Update BDS state. */ + bds->height[bds->offset] = h; + bds->offset++; + treeHash->nextIdx++; + } + + /* Set the tree hash data back. */ + wc_xmss_bds_state_treehash_set(bds, height, treeHash); +} + +/* Updates hash trees that need it most. + * + * Algorithm 4.6: Authentication path computation, Step 5. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] bds BDS state. + * @param [in] updates Current number of updates. + * @param [in] sk_seed Random secret/private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @return Number of available updates. + */ +static word8 wc_xmss_bds_treehash_updates(XmssState* state, BdsState* bds, + word8 updates, const byte* sk_seed, const byte* pk_seed, + const HashAddress addr) +{ + const XmssParams* params = state->params; + const word8 hs = params->sub_h; + const word8 hsk = params->sub_h - params->bds_k; + + while (updates > 0) { + word8 minH = hs; + word8 h = hsk; + word8 i; + + /* Step 5.a. k <- min{ h: TREEHASH(h).height() = + min[j=0..H-K-1]{TREEHASH(j.height()} } */ + for (i = 0; i < hsk; i++) { + TreeHash treeHash[1]; + + wc_xmss_bds_state_treehash_get(bds, i, treeHash); + + if (treeHash->completed) { + /* Finished - ignore. */ + } + else if (treeHash->used == 0) { + /* None used, low height. */ + if (i < minH) { + h = i; + minH = i; + } + } + /* Find the height of lowest in cache. */ + else { + word8 j; + word8 lowH = hs; + byte* height = bds->height + bds->offset - treeHash->used; + + for (j = 0; j < treeHash->used; j++) { + lowH = min(height[j], lowH); + } + if (lowH < minH) { + /* New lowest height. */ + h = i; + minH = lowH; + } + } + } + /* If none lower, then stop. */ + if (h == hsk) { + break; + } + + /* Step 5.b. TREEHASH(k).update() */ + /* Update tree to the lowest height. */ + wc_xmss_bds_treehash_update(state, bds, h, sk_seed, pk_seed, addr); + updates--; + } + return updates; +} + +/* Update BDS at next leaf. + * + * Don't do anything if processed all leaves. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] bds BDS state. + * @param [in] sk_seed Random secret/private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + */ +static void wc_xmss_bds_update(XmssState* state, BdsState* bds, + const byte* sk_seed, const byte* pk_seed, const HashAddress addr) +{ + if (bds->next < ((word32)1 << state->params->sub_h)) { + const XmssParams* params = state->params; + byte* sp = bds->stack + bds->offset * params->n; + HashAddress addrCopy; + + XMSS_ADDR_OTS_SET_SUBTREE(addrCopy, addr); + wc_xmss_bds_next_idx(state, bds, sk_seed, pk_seed, addrCopy, bds->next, + bds->height, &bds->offset, &sp); + bds->offset++; + bds->next++; + } +} + +/* Find index of lowest zero bit. + * + * Supports max up to 31. + * + * @param [in] n Number to evaluate. + * @param [in] max Max number of bits. + * @param [out] b Next bit above first zero bit. + * @return Index of lowest bit that is zero. + */ +static word8 wc_xmss_lowest_zero_bit_index(word32 n, word8 max, word8* b) +{ + word8 i; + + /* Check each bit from lowest for a zero bit. */ + for (i = 0; i < max; i++) { + if ((n & 1) == 0) { + break; + } + n >>= 1; + } + + /* Return next bit after 0 bit. */ + *b = (n >> 1) & 1; + return i; +} + +/* Returns auth path for node leafIdx and computes for next leaf node. + * + * HDSS, Algorithm 4.6: Authentication path computation, Steps 1-4. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] bds BDS state. + * @param [in] leafIdx Current leaf index. + * @param [in] sk_seed Random secret/private seed. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + */ +static void wc_xmss_bds_auth_path(XmssState* state, BdsState* bds, + const word32 leafIdx, const byte* sk_seed, const byte* pk_seed, + HashAddress addr) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 hs = params->sub_h; + const word8 hsk = params->sub_h - params->bds_k; + word8 tau; + byte* node = state->encMsg; + word8 parent; + + /* Step 1. Find the height of first left node in authentication path. */ + tau = wc_xmss_lowest_zero_bit_index(leafIdx, hs, &parent); + if (tau == 0) { + /* Step 2. Keep node if parent is a left node. + * if s/(2^tau+1) is even and tau < H-1 then KEEP[tau] <- AUTH[tau] + */ + if (parent == 0) { + XMEMCPY(bds->keep, bds->authPath, n); + } + + /* Step 3. if tau = 0 then AUTH[0] <- LEAFCALC(s) */ + /* Calculate WOTS+ public key. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + addr[XMSS_ADDR_OTS] = leafIdx; + wc_xmss_wots_gen_pk(state, sk_seed, pk_seed, addr, state->pk); + /* Calculate public value. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_LTREE; + wc_xmss_ltree(state, state->pk, pk_seed, addr, bds->authPath); + } + else { + byte* authPath; + byte* nodes; + word8 i; + + authPath = bds->authPath + tau * n; + /* Step 4.a. = AUTH[tau-1] || KEEP[tau-1] + * Only keeping half of nodes, so need to copy out before updating. + */ + XMEMCPY(node, authPath - n, n); + XMEMCPY(node + n, bds->keep + ((tau - 1) >> 1) * n, n); + + /* Step 2. Keep node if parent is a left node. + * if s/(2^tau+1) is even and tau < H-1 then KEEP[tau] <- AUTH[tau] + */ + if ((tau < hs - 1) && (parent == 0)) { + XMEMCPY(bds->keep + (tau >> 1) * n, authPath, n); + } + + /* Step 4.a. AUTH[tau] <- g() */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_TREE; + addr[XMSS_ADDR_TREE_ZERO] = 0; + addr[XMSS_ADDR_TREE_HEIGHT] = tau - 1; + addr[XMSS_ADDR_TREE_INDEX] = leafIdx >> tau; + wc_xmss_rand_hash(state, node, pk_seed, addr, authPath); + + /* Step 4.b. */ + authPath = bds->authPath; + nodes = bds->treeHashNode; + /* for h = 0 to tau - 1 do */ + for (i = 0; i < tau; i++) { + /* if h < H - K then AUTH[h] <- TREEHASH[h].pop()*/ + if (i < hsk) { + XMEMCPY(authPath, nodes, n); + nodes += n; + } + /* if h >= H - K then AUTH[h] <- RETAIN[h].pop()*/ + else { + word32 o = (1 << (hs - 1 - i)) + i - hs + + (((leafIdx >> i) - 1) >> 1); + XMEMCPY(authPath, bds->retain + o * n, n); + } + authPath += n; + } + + /* Step 4.c. Initialize treehash instances for heights: + * 0, ..., min{tau-1, H - K - 1} */ + tau = min(tau, hsk); + for (i = 0; i < tau; i++) { + word32 startIdx = leafIdx + 1 + 3 * (1 << i); + if (startIdx < ((word32)1 << hs)) { + wc_xmss_bds_state_treehash_set_next_idx(bds, i, startIdx); + } + } + } +} + +/******************************************** + * XMSS + ********************************************/ + +/* Derives XMSS key pair from seeds. + * + * RFC 8391: 4.1.7, Algorithm 10: XMSS_keyGen. + * ... + * initialize SK_PRF with a uniformly random n-byte string; + * setSK_PRF(SK, SK_PRF); + * + * # Initialization for common contents + * initialize SEED with a uniformly random n-byte string; + * setSEED(SK, SEED); + * setWOTS_SK(SK, wots_sk)); + * ADRS = toByte(0, 32); + * root = treeHash(SK, 0, h, ADRS); + * + * SK = idx || wots_sk || SK_PRF || root || SEED; + * PK = OID || root || SEED; + * return (SK || PK); + * + * HDSS, Section 4.5, The algorithm, Initialization. + * + * wots_sk, SK_PRF and SEED passed in as seed. + * Store seed for wots_sk instead of generated wots_sk. + * OID not stored in PK this is handled in upper layer. + * BDS state is appended to SK: + * SK = idx || wots_sk || SK_PRF || root || SEED || BDS_STATE; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] seed Secret/Private and public seed. + * @param [out] sk Secret key. + * @param [out] pk Public key. + * @return 0 on success. + * @return MEMORY_E on dynamic memory allocation failure. + * @return <0 on digest failure. + */ +int wc_xmss_keygen(XmssState* state, const unsigned char* seed, + unsigned char* sk, unsigned char* pk) +{ +#if WOLFSSL_XMSS_MIN_HEIGHT <= 32 + int ret = 0; + const XmssParams* params = state->params; + const word8 n = params->n; + /* Offset of root node in public key. */ + byte* pk_root = pk; +#ifdef WOLFSSL_SMALL_STACK + BdsState* bds = NULL; +#else + BdsState bds[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for tree hash instances and put in BDS state. */ + ret = wc_xmss_bds_state_alloc(params, &bds); + if (ret == 0) +#endif + { + /* Offsets into seed. */ + const byte* seed_priv = seed; + const byte* seed_pub = seed + 2 * n; + /* Offsets into secret/private key. */ + word32* sk_idx = (word32*)sk; + byte* sk_seeds = sk + params->idx_len; + /* Offsets into public key. */ + byte* pk_seed = pk + n; + + /* Setup pointers into sk - assumes sk is initialized to zeros. */ + wc_xmss_bds_state_load(state, sk, bds, NULL); + + /* Set first index to 0 in private key. idx_len always 4. */ + *sk_idx = 0; + /* Set private key seed and private key for PRF in to private key. */ + XMEMCPY(sk_seeds, seed_priv, 2 * n); + /* Set public key seed into public key. */ + XMEMCPY(pk_seed, seed_pub, n); + + /* Set all address values to zero. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + /* Hash address layer is 0. */ + /* Compute root node into public key. */ + wc_xmss_bds_treehash_initial(state, bds, sk_seeds, pk_seed, + state->addr, pk_root); + /* Return any errors that occurred during hashing. */ + ret = state->ret; + } + if (ret == 0) { + /* Offset of root node in private key. */ + byte* sk_root = sk + params->idx_len + 2 * n; + + /* Append public key (root node and public seed) to private key. */ + XMEMCPY(sk_root, pk_root, 2 * n); + + /* Store BDS state back into secret/private key. */ + wc_xmss_bds_state_store(state, sk, bds); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of allocated data of BDS states. */ + wc_xmss_bds_state_free(bds); +#endif + return ret; +#else + (void)state; + (void)pk; + (void)sk; + (void)seed; + + return NOT_COMPILED_IN; +#endif /* WOLFSSL_XMSS_MIN_HEIGHT <= 32 */ +} + +/* Sign a message with XMSS. + * + * RFC 8391: 4.1.9, Algorithm 11: treeSig + * ... + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(idx_sig); + * sig_ots = WOTS_sign(getWOTS_SK(SK, idx_sig), + * M', getSEED(SK), ADRS); + * Sig = sig_ots || auth; + * return Sig; + * RFC 8391: 4.1.9, Algorithm 12: XMSS_sign + * idx_sig = getIdx(SK); + * setIdx(SK, idx_sig + 1); + * ADRS = toByte(0, 32); + * byte[n] r = PRF(getSK_PRF(SK), toByte(idx_sig, 32)); + * byte[n] M' = H_msg(r || getRoot(SK) || (toByte(idx_sig, n)), M); + * Sig = idx_sig || r || treeSig(M', SK, idx_sig, ADRS); + * return (SK || Sig); + * + * HDSS, Section 4.5, The algorithm, Update and output phase. + * + * 'auth' was built at key generation or after computing previous signature. + * Build next authentication path after signature created. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] m Buffer holding message. + * @param [in] mlen Length of message in buffer. + * @param [in, out] sk Secret/Private key. + * @param [out] sm Signature and message data. + * @param [in, out] smlen On in, length of signature and message buffer. + * On out, length of signature and message data. + * @return 0 on success. + * @return <0 on digest failure. + */ +int wc_xmss_sign(XmssState* state, const unsigned char* m, word32 mlen, + unsigned char* sk, unsigned char* sig) +{ +#if WOLFSSL_XMSS_MIN_HEIGHT <= 32 + int ret = 0; + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 h = params->h; + const word8 hk = params->h - params->bds_k; + const byte* sk_seed = sk + XMSS_IDX_LEN; + const byte* pk_seed = sk + XMSS_IDX_LEN + 3 * n; + byte node[WC_XMSS_MAX_N]; + word32 idx; + byte* sig_r = sig + XMSS_IDX_LEN; +#ifdef WOLFSSL_SMALL_STACK + BdsState* bds = NULL; +#else + BdsState bds[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for tree hash instances and put in BDS state. */ + ret = wc_xmss_bds_state_alloc(params, &bds); + if (ret == 0) +#endif + { + /* Load the BDS state from secret/private key. */ + wc_xmss_bds_state_load(state, sk, bds, NULL); + + /* Copy the index into the signature data: Sig = idx_sig || ... */ + *((word32*)sig) = *((word32*)sk); + /* Read index from the secret key. */ + ato32(sk, &idx); + + /* Check index is valid. */ + if (IDX32_INVALID(idx, XMSS_IDX_LEN, h)) { + /* Set index to maximum value to distinguish from valid value. */ + XMEMSET(sk, 0xFF, XMSS_IDX_LEN); + /* Zeroize the secret key. */ + ForceZero(sk + XMSS_IDX_LEN, params->sk_len - XMSS_IDX_LEN); + ret = KEY_EXHAUSTED_E; + } + } + + /* Update SK_MT */ + if (ret == 0) { + /* Increment the index in the secret key. */ + c32toa(idx + 1, sk); + } + + /* Message compression */ + if (ret == 0) { + const byte* sk_prf = sk + XMSS_IDX_LEN + n; + + /* byte[n] r = PRF(SK_PRF, toByte(idx_sig, 32)); */ + wc_idx_copy(sig, params->idx_len, state->buf, XMSS_PRF_M_LEN); + wc_xmss_prf(state, sk_prf, state->buf, sig_r); + ret = state->ret; + } + if (ret == 0) { + const byte* pub_root = sk + XMSS_IDX_LEN + 2 * n; + + /* Compute the message hash. */ + wc_xmss_hash_message(state, sig_r, pub_root, sig, XMSS_IDX_LEN, m, mlen, + node); + ret = state->ret; + /* Place new signature data after index and 'r'. */ + sig += XMSS_IDX_LEN + n; + } + + if (ret == 0) { + /* Set all address values to zero and set type to OTS. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + state->addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + /* treeSig || treeHash = sig_ots || auth */ + state->addr[XMSS_ADDR_OTS] = idx; + /* Create WOTS+ signature for tree into signature (sig_ots). */ + wc_xmss_wots_sign(state, node, sk_seed, pk_seed, state->addr, sig); + ret = state->ret; + } + if (ret == 0) { + sig += params->wots_sig_len; + /* Add authentication path (auth) and calc new root. */ + XMEMCPY(sig, bds->authPath, h * n); + ret = state->ret; + } + + if (ret == 0) { + /* Update BDS state - update authentication path for next index. */ + /* Check not last node. */ + if (idx < ((word32)1 << h) - 1) { + /* Calculate next authentication path node. */ + wc_xmss_bds_auth_path(state, bds, idx, sk_seed, pk_seed, + state->addr); + ret = state->ret; + if (ret == 0) { + /* Algorithm 4.6: Step 5. */ + wc_xmss_bds_treehash_updates(state, bds, hk >> 1, sk_seed, + pk_seed, state->addr); + ret = state->ret; + } + } + } + if (ret == 0) { + /* Store BDS state back into secret/private key. */ + wc_xmss_bds_state_store(state, sk, bds); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of allocated data of BDS states. */ + wc_xmss_bds_state_free(bds); +#endif + return ret; +#else + (void)state; + (void)m; + (void)mlen; + (void)sk; + (void)sig; + + return NOT_COMPILED_IN; +#endif /* WOLFSSL_XMSS_MIN_HEIGHT <= 32 */ +} + +/******************************************** + * XMSS^MT + ********************************************/ + +/* Generate a XMSS^MT key pair from seeds. + * + * RFC 8391: 4.2.2, Algorithm 15: XMSS^MT_keyGen. + * ... + * # Example initialization + * idx_MT = 0; + * setIdx(SK_MT, idx_MT); + * initialize SK_PRF with a uniformly random n-byte string; + * setSK_PRF(SK_MT, SK_PRF); + * initialize SEED with a uniformly random n-byte string; + * setSEED(SK_MT, SEED); + * + * # Generate reduced XMSS private keys + * ADRS = toByte(0, 32); + * for ( layer = 0; layer < d; layer++ ) { + * ADRS.setLayerAddress(layer); + * for ( tree = 0; tree < + * (1 << ((d - 1 - layer) * (h / d))); + * tree++ ) { + * ADRS.setTreeAddress(tree); + * for ( i = 0; i < 2^(h / d); i++ ) { + * wots_sk[i] = WOTS_genSK(); + * } + * setXMSS_SK(SK_MT, wots_sk, tree, layer); + * } + * } + * + * SK = getXMSS_SK(SK_MT, 0, d - 1); + * setSEED(SK, SEED); + * root = treeHash(SK, 0, h / d, ADRS); + * setRoot(SK_MT, root); + * + * PK_MT = OID || root || SEED; + * return (SK_MT || PK_MT); + * + * HDSS, Section 4.5, The algorithm, Initialization. + * OPX, Section 2, Key Generation. + * + * wots_sk, SK_PRF and SEED passed in as seed. + * Store seed for wots_sk instead of generated wots_sk. + * OID not stored in PK this is handled in upper layer. + * BDS state is appended to SK: + * SK = idx || wots_sk || SK_PRF || root || SEED || BDS_STATE; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] seed Secret/Private and public seed. + * @param [out] sk Secret key. + * @param [out] pk Public key. + * @return 0 on success. + * @return MEMORY_E on dynamic memory allocation failure. + * @return <0 on digest failure. + */ +int wc_xmssmt_keygen(XmssState* state, const unsigned char* seed, + unsigned char* sk, unsigned char* pk) +{ + int ret = 0; + const XmssParams* params = state->params; + const word8 n = params->n; + unsigned char* sk_seed = sk + params->idx_len; + unsigned char* pk_root = pk; + unsigned char* pk_seed = pk + n; + word8 i; + byte* wots_sigs; + BdsState* bds = NULL; + + /* Allocate memory for BDS states and tree hash instances. */ + ret = wc_xmss_bds_state_alloc(params, &bds); + if (ret == 0) { + /* Offsets into seed. */ + const byte* seed_priv = seed; + const byte* seed_pub = seed + 2 * params->n; + + /* Load the BDS state from secret/private key. */ + wc_xmss_bds_state_load(state, sk, bds, &wots_sigs); + + /* Set first index to 0 in private key. */ + XMEMSET(sk, 0, params->idx_len); + /* Set private key seed and private key for PRF in to private key. */ + XMEMCPY(sk_seed, seed_priv, 2 * n); + /* Set public key seed into public key. */ + XMEMCPY(pk_seed, seed_pub, n); + + /* Set all address values to zero. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + /* Hash address layer is 0 = bottom-most layer. */ + } + + /* Setup state and compute WOTS+ signatures for all but top-most subtree. */ + for (i = 0; (ret == 0) && (i < params->d - 1); i++) { + /* Compute root for subtree. */ + wc_xmss_bds_treehash_initial(state, bds + i, sk_seed, pk_seed, + state->addr, pk_root); + ret = state->ret; + if (ret == 0) { + /* Create signature for subtree for first index. */ + state->addr[XMSS_ADDR_LAYER] = i+1; + wc_xmss_wots_sign(state, pk_root, sk_seed, pk_seed, state->addr, + wots_sigs + i * params->wots_sig_len); + ret = state->ret; + } + } + if (ret == 0) { + /* Compute root for top-most subtree. */ + wc_xmss_bds_treehash_initial(state, bds + i, sk_seed, pk_seed, + state->addr, pk_root); + /* Return any errors that occurred during hashing. */ + ret = state->ret; + } + + if (ret == 0) { + /* Offset of root node in private key. */ + unsigned char* sk_root = sk_seed + 2 * n; + + /* Append public key (root node and public seed) to private key. */ + XMEMCPY(sk_root, pk_root, 2 * n); + + /* Store BDS state back into secret/private key. */ + wc_xmss_bds_state_store(state, sk, bds); + } + + /* Dispose of allocated data of BDS states. */ + wc_xmss_bds_state_free(bds); + return ret; +} + + +#if !defined(WORD64_AVAILABLE) && (WOLFSSL_XMSS_MAX_HEIGHT > 32) + #error "Support not available - use XMSS small code option" +#endif + +#if (WOLFSSL_XMSS_MAX_HEIGHT > 32) + typedef word64 XmssIdx; + #define IDX_MAX_BITS 64 +#else + typedef word32 XmssIdx; + #define IDX_MAX_BITS 32 +#endif + +/* Decode index into word. + * + * @param [out] idx Index from encoding. + * @param [in] c Count of bytes to decode to index. + * @param [in] a Array to decode from. + */ +static void xmss_idx_decode(XmssIdx* idx, word8 c, const unsigned char* a) +{ + word8 i; + XmssIdx n = 0; + + for (i = 0; i < c; i++) { + n <<= 8; + n += a[i]; + } + + *idx = n; +} + +/* Check whether index is valid. + * + * @param [in] i Index to check. + * @param [in] h Full tree Height. + */ +static int xmss_idx_invalid(XmssIdx i, word8 h) +{ + return ((i + 1) >> h) != 0; +} + +/* Get tree and leaf index from index. + * + * @param [in] i Index to split. + * @param [in] h Tree height. + * @param [out] t Tree index. + * @param [out] l Leaf index. + */ +static void xmss_idx_get_tree_leaf(XmssIdx i, word8 h, XmssIdx* t, word32* l) +{ + *l = (word32)i & (((word32)1 << h) - 1); + *t = i >> h; +} + +/* Set the index into address as the tree index. + * + * @param [in] i Tree index. + * @param [in, out] a Hash address. + */ +static void xmss_idx_set_addr_tree(XmssIdx i, HashAddress a) +{ +#if IDX_MAX_BITS == 32 + a[XMSS_ADDR_TREE_HI] = 0; + a[XMSS_ADDR_TREE] = i; +#else + a[XMSS_ADDR_TREE_HI] = (word32)(i >> 32); + a[XMSS_ADDR_TREE] = (word32)(i ); +#endif +} + +/* Sign message with XMSS^MT. + * + * RFC 8391: 4.1.9, Algorithm 11: treeSig + * ... + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(idx_sig); + * sig_ots = WOTS_sign(getWOTS_SK(SK, idx_sig), + * M', getSEED(SK), ADRS); + * Sig = sig_ots || auth; + * return Sig; + * RFC 8391: 4.2.4, Algorithm 16: XMSS^MT_sign. + * ... + * # Init + * ADRS = toByte(0, 32); + * SEED = getSEED(SK_MT); + * SK_PRF = getSK_PRF(SK_MT); + * idx_sig = getIdx(SK_MT); + * + * # Update SK_MT + * setIdx(SK_MT, idx_sig + 1); + * + * # Message compression + * byte[n] r = PRF(SK_PRF, toByte(idx_sig, 32)); + * byte[n] M' = H_msg(r || getRoot(SK_MT) || (toByte(idx_sig, n)), M); + * + * # Sign + * Sig_MT = idx_sig; + * unsigned int idx_tree + * = (h - h / d) most significant bits of idx_sig; + * unsigned int idx_leaf = (h / d) least significant bits of idx_sig; + * SK = idx_leaf || getXMSS_SK(SK_MT, idx_tree, 0) || SK_PRF + * || toByte(0, n) || SEED; + * ADRS.setLayerAddress(0); + * ADRS.setTreeAddress(idx_tree); + * Sig_tmp = treeSig(M', SK, idx_leaf, ADRS); + * Sig_MT = Sig_MT || r || Sig_tmp; + * for ( j = 1; j < d; j++ ) { + * root = treeHash(SK, 0, h / d, ADRS); + * idx_leaf = (h / d) least significant bits of idx_tree; + * idx_tree = (h - j * (h / d)) most significant bits of idx_tree; + * SK = idx_leaf || getXMSS_SK(SK_MT, idx_tree, j) || SK_PRF + * || toByte(0, n) || SEED; + * ADRS.setLayerAddress(j); + * ADRS.setTreeAddress(idx_tree); + * Sig_tmp = treeSig(root, SK, idx_leaf, ADRS); + * Sig_MT = Sig_MT || Sig_tmp; + * } + * return SK_MT || Sig_MT; + * + * 'auth' was built at key generation or after computing previous signature. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] bds BDS state. + * @param [in] idx Index to sign with. + * @param [in] wots_sigs Pre-computed WOTS+ signatures. + * @param [in] m Buffer holding message. + * @param [in] mlen Length of message in buffer. + * @param [in, out] sk Secret/Private key. + * @param [out] sig Signature and message data. + * @return 0 on success. + * @return <0 on digest failure. + */ +static int wc_xmssmt_sign_msg(XmssState* state, BdsState* bds, XmssIdx idx, + byte* wots_sigs, const unsigned char* m, word32 mlen, unsigned char* sk, + unsigned char* sig) +{ + int ret; + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 hs = params->sub_h; + const word8 idx_len = params->idx_len; + const byte* sk_prf = sk + idx_len + n; + byte* sig_mt = sig; + byte* sig_r = sig + idx_len; + byte node[WC_XMSS_MAX_N]; + + /* Message compression */ + /* byte[n] r = PRF(SK_PRF, toByte(idx_sig, 32)); */ + wc_idx_copy(sig_mt, idx_len, state->buf, XMSS_PRF_M_LEN); + wc_xmss_prf(state, sk_prf, state->buf, sig_r); + ret = state->ret; + if (ret == 0) { + const byte* pub_root = sk + idx_len + 2 * n; + /* byte[n] M' = H_msg(r || getRoot(SK_MT) || (toByte(idx_sig, n)), M); + */ + wc_xmss_hash_message(state, sig_r, pub_root, sig, idx_len, m, mlen, + node); + ret = state->ret; + /* Place new signature data after index and 'r'. */ + sig += idx_len + n; + } + + /* Sign */ + if (ret == 0) { + const byte* sk_seed = sk + idx_len; + const byte* pk_seed = sk + idx_len + 3 * n; + XmssIdx idx_tree; + word32 idx_leaf; + + /* Set all address values to zero and set type to OTS. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + state->addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + + /* Fist iteration - calculate signature. */ + /* Set layer, tree and OTS leaf index into hash address. */ + state->addr[XMSS_ADDR_LAYER] = 0; + xmss_idx_get_tree_leaf(idx, hs, &idx_tree, &idx_leaf); + xmss_idx_set_addr_tree(idx_tree, state->addr); + /* treeSig || treeHash = sig_ots || auth */ + state->addr[XMSS_ADDR_OTS] = idx_leaf; + /* Create WOTS+ signature for tree into signature (sig_ots). */ + wc_xmss_wots_sign(state, node, sk_seed, pk_seed, state->addr, sig); + ret = state->ret; + } + if (ret == 0) { + word8 i; + + sig += params->wots_sig_len; + /* Add authentication path. */ + XMEMCPY(sig, bds[BDS_IDX(idx, 0, hs, params->d)].authPath, hs * n); + sig += hs * n; + + /* Remaining iterations from storage. */ + for (i = 1; i < params->d; i++) { + /* Copy out precomputed signature into signature (sig_ots). */ + XMEMCPY(sig, wots_sigs + (i - 1) * params->wots_sig_len, + params->wots_sig_len); + sig += params->wots_sig_len; + /* Add authentication path (auth) and calc new root. */ + XMEMCPY(sig, bds[BDS_IDX(idx, i, hs, params->d)].authPath, hs * n); + sig += hs * n; + } + ret = state->ret; + } + + return ret; +} + +/* Compute BDS state for signing next index. + * + * HDSS, Section 4.5, The algorithm, Update and output phase. + * OPX, Section 2, Signature Generation. Para 2 and 3. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in, out] bds BDS state. + * @param [in] idx Index to sign with. + * @param [in] wots_sigs Pre-computed WOTS+ signatures. + * @param [in] m Buffer holding message. + * @param [in] mlen Length of message in buffer. + * @param [in, out] sk Secret/Private key. + * @param [out] sig Signature and message data. + * @return 0 on success. + * @return <0 on digest failure. + */ +static int wc_xmssmt_sign_next_idx(XmssState* state, BdsState* bds, XmssIdx idx, + byte* wots_sigs, unsigned char* sk) +{ + int ret = 0; + const XmssParams* params = state->params; + const word8 n = params->n; + const word8 h = params->h; + const word8 hs = params->sub_h; + const word8 hsk = params->sub_h - params->bds_k; + const byte* sk_seed = sk + params->idx_len; + const byte* pk_seed = sk + params->idx_len + 3 * n; + XmssIdx idx_tree; + int computeAuthPath = 1; + unsigned int updates; + word8 i; + + /* Update BDS state - update authentication path for next index. */ + /* HDSS, Algorithm 4.6, Step 5: repeat (H - K) / 2 times. */ + updates = hsk >> 1; + + idx_tree = (idx >> hs) + 1; + /* Check whether last tree. */ + if (idx_tree < ((XmssIdx)1 << (h - hs))) { + /* Set hash address to next tree. */ + state->addr[XMSS_ADDR_LAYER] = 0; + xmss_idx_set_addr_tree(idx_tree, state->addr); + /* Update BDS state. */ + wc_xmss_bds_update(state, &bds[BDS_ALT_IDX(idx, 0, hs, params->d)], + sk_seed, pk_seed, state->addr); + ret = state->ret; + } + + for (i = 0; (ret == 0) && (i < params->d); i++) { + word32 idx_leaf; + word8 bds_i = BDS_IDX(idx, i, hs, params->d); + word8 alt_i = BDS_ALT_IDX(idx, i, hs, params->d); + + /* Check not last at height. */ + if (((idx + 1) << (IDX_MAX_BITS - ((i + 1) * hs))) != 0) { + state->addr[XMSS_ADDR_LAYER] = i; + xmss_idx_get_tree_leaf(idx >> (hs * i), hs, &idx_tree, &idx_leaf); + xmss_idx_set_addr_tree(idx_tree, state->addr); + idx_tree++; + + if (computeAuthPath) { + /* Compute authentication path for tree. */ + wc_xmss_bds_auth_path(state, &bds[bds_i], idx_leaf, sk_seed, + pk_seed, state->addr); + ret = state->ret; + computeAuthPath = 0; + } + + if (ret == 0) { + /* HDSS, Algorithm 4.6: Step 5. */ + updates = wc_xmss_bds_treehash_updates(state, &bds[bds_i], + updates, sk_seed, pk_seed, state->addr); + ret = state->ret; + } + + /* Check tree not first, updates to do, tree not last at height and + * next leaf in alt state is not last. */ + if ((ret == 0) && (i > 0) && (updates > 0) && + (idx_tree < ((XmssIdx)1 << (h - (hs * (i + 1))))) && + (bds[alt_i].next < ((XmssIdx)1 << h))) { + xmss_idx_set_addr_tree(idx_tree, state->addr); + /* Update alternative BDS state. */ + wc_xmss_bds_update(state, &bds[alt_i], sk_seed, pk_seed, + state->addr); + ret = state->ret; + updates--; + } + } + /* Last at height. */ + else { + /* Set layer, tree and OTS leaf index into hash address. */ + state->addr[XMSS_ADDR_LAYER] = i + 1; + idx_tree = (idx + 1) >> ((i + 1) * hs); + xmss_idx_get_tree_leaf(idx_tree, hs, &idx_tree, &idx_leaf); + xmss_idx_set_addr_tree(idx_tree, state->addr); + /* Cache WOTS+ signature for new tree. */ + state->addr[XMSS_ADDR_OTS] = idx_leaf; + wc_xmss_wots_sign(state, bds[alt_i].stack, sk_seed, pk_seed, + state->addr, wots_sigs + i * params->wots_sig_len); + ret = state->ret; + + if (ret == 0) { + word8 d; + + /* Reset old BDS state. */ + bds[bds_i].offset = 0; + bds[bds_i].next = 0; + + /* Done an update. */ + updates--; + /* Need to compute authentication path in next tree up. */ + computeAuthPath = 1; + /* Mark the tree hashes as complete in new BDS state. */ + for (d = 0; d < hsk; d++) { + wc_xmss_bds_state_treehash_complete(&bds[alt_i], d); + } + } + } + } + + return ret; +} + +/* Sign a message with XMSS^MT and update BDS state for signing next index. + * + * RFC 8391: 4.2.4, Algorithm 16: XMSS^MT_sign. + * HDSS, Section 4.5, The algorithm, Update and output phase. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] m Buffer holding message. + * @param [in] mlen Length of message in buffer. + * @param [in, out] sk Secret/Private key. + * @param [out] sig Signature and message data. + * @return 0 on success. + * @return MEMORY_E on dynamic memory allocation failure. + * @return <0 on digest failure. + */ +int wc_xmssmt_sign(XmssState* state, const unsigned char* m, word32 mlen, + unsigned char* sk, unsigned char* sig) +{ + int ret = 0; + const XmssParams* params = state->params; + const word8 h = params->h; + const word8 idx_len = params->idx_len; + XmssIdx idx = 0; + byte* sig_mt = sig; + byte* wots_sigs; + BdsState* bds = NULL; + + /* Allocate memory for BDS states and tree hash instances. */ + ret = wc_xmss_bds_state_alloc(params, &bds); + if (ret == 0) { + /* Load the BDS state from secret/private key. */ + wc_xmss_bds_state_load(state, sk, bds, &wots_sigs); + + /* Copy the index into the signature data: Sig_MT = idx_sig. */ + XMEMCPY(sig_mt, sk, idx_len); + + /* Read index from the secret key. */ + xmss_idx_decode(&idx, idx_len, sk); + } + if ((ret == 0) && xmss_idx_invalid(idx, h)) { + /* Set index to maximum value to distinguish from valid value. */ + XMEMSET(sk, 0xFF, idx_len); + /* Zeroize the secret key. */ + ForceZero(sk + idx_len, params->sk_len - idx_len); + ret = KEY_EXHAUSTED_E; + } + + if (ret == 0) { + /* Increment the index in the secret key. */ + wc_idx_update(sk, idx_len); + + /* Compute signature. */ + ret = wc_xmssmt_sign_msg(state, bds, idx, wots_sigs, m, mlen, sk, sig); + } + + /* Only update if not last index. */ + if ((ret == 0) && (idx < (((XmssIdx)1 << h) - 1))) { + /* Update BDS state for signing next index. */ + ret = wc_xmssmt_sign_next_idx(state, bds, idx, wots_sigs, sk); + } + + if (ret == 0) { + /* Store BDS state back into secret/private key. */ + wc_xmss_bds_state_store(state, sk, bds); + } + + /* Dispose of allocated data of BDS states. */ + wc_xmss_bds_state_free(bds); + return ret; +} + +#endif /* WOLFSSL_WC_XMSS_SMALL */ + +/* Check if more signatures are possible with secret/private key. + * + * @param [in] params XMSS parameters + * @param [in] sk Secret/private key. + * @return 1 when signatures possible. + * @return 0 when key exhausted. + */ + +int wc_xmss_sigsleft(const XmssParams* params, unsigned char* sk) +{ + int ret = 0; + wc_Idx idx; + + WC_IDX_ZERO(idx); + /* Read index from the secret key. */ + WC_IDX_DECODE(idx, params->idx_len, sk, ret); + /* Check validity of index. */ + if ((ret == 0) && (WC_IDX_INVALID(idx, params->idx_len, params->h))) { + ret = KEY_EXHAUSTED_E; + } + + return ret == 0; +} +#endif /* !WOLFSSL_XMSS_VERIFY_ONLY */ + +/******************************************** + * SIGN OPEN - Verify + ********************************************/ + +#if !defined(WOLFSSL_WC_XMSS_SMALL) || defined(WOLFSSL_XMSS_VERIFY_ONLY) +/* Compute root node with leaf and authentication path. + * + * RFC 8391: 4.1.10, Algorithm 13: XMSS_rootFromSig + * ... + * for ( k = 0; k < h; k++ ) { + * ADRS.setTreeHeight(k); + * if ( (floor(idx_sig / (2^k)) % 2) == 0 ) { + * ADRS.setTreeIndex(ADRS.getTreeIndex() / 2); + * node[1] = RAND_HASH(node[0], auth[k], SEED, ADRS); + * } else { + * ADRS.setTreeIndex((ADRS.getTreeIndex() - 1) / 2); + * node[1] = RAND_HASH(auth[k], node[0], SEED, ADRS); + * } + * node[0] = node[1]; + * } + * return node[0]; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] idx_leaf Index of leaf node. + * @param [in] auth_path Authentication path. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [in, out] root On in, leaf node. On out, root node. + */ +static void wc_xmss_compute_root(XmssState* state, word32 idx_leaf, + const byte* auth_path, const byte* pk_seed, HashAddress addr, byte* root) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + const byte* b[2][2] = { { root, auth_path }, { auth_path, root } }; + word8 i; + + for (i = 0; i < params->sub_h; i++) { + /* Get which side the leaf is on. */ + word8 s = idx_leaf & 1; + /* Set tree height and index. */ + addr[XMSS_ADDR_TREE_HEIGHT] = i; + idx_leaf >>= 1; + addr[XMSS_ADDR_TREE_INDEX] = idx_leaf; + + /* Put the result into buffer position for next RAND_HASH. */ + wc_xmss_rand_hash_lr(state, b[s][0], b[s][1], pk_seed, addr, root); + /* Move to next auth path node. */ + b[0][1] += n; + b[1][0] += n; + } +} +#else +/* Compute root node with leaf and authentication path. + * + * RFC 8391: 4.1.10, Algorithm 13: XMSS_rootFromSig + * ... + * for ( k = 0; k < h; k++ ) { + * ADRS.setTreeHeight(k); + * if ( (floor(idx_sig / (2^k)) % 2) == 0 ) { + * ADRS.setTreeIndex(ADRS.getTreeIndex() / 2); + * node[1] = RAND_HASH(node[0], auth[k], SEED, ADRS); + * } else { + * ADRS.setTreeIndex((ADRS.getTreeIndex() - 1) / 2); + * node[1] = RAND_HASH(auth[k], node[0], SEED, ADRS); + * } + * node[0] = node[1]; + * } + * return node[0]; + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] idx_leaf Index of leaf node. + * @param [in] auth_path Authentication path. + * @param [in] pk_seed Random public seed. + * @param [in] addr Hash address. + * @param [in, out] node On in, leaf node. On out, root node. + */ +static void wc_xmss_compute_root(XmssState* state, word32 idx_leaf, + const byte* auth_path, const byte* pk_seed, HashAddress addr, byte* node) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + byte buffer[2 * WC_XMSS_MAX_N]; + byte* b[2][2] = { { buffer, buffer + n }, { buffer + n, buffer } }; + word8 i; + + /* Setup buffer for first RAND_HASH. */ + XMEMCPY(b[idx_leaf & 1][0], node, n); + XMEMCPY(b[idx_leaf & 1][1], auth_path, n); + auth_path += n; + + for (i = 0; i < params->sub_h - 1; i++) { + /* Set tree height and index. */ + addr[XMSS_ADDR_TREE_HEIGHT] = i; + idx_leaf >>= 1; + addr[XMSS_ADDR_TREE_INDEX] = idx_leaf; + + /* Put the result into buffer position for next RAND_HASH. */ + wc_xmss_rand_hash(state, buffer, pk_seed, addr, b[idx_leaf & 1][0]); + /* Put auth path node into other half of buffer. */ + XMEMCPY(b[idx_leaf & 1][1], auth_path, n); + /* Move to next auth path node. */ + auth_path += n; + } + + addr[XMSS_ADDR_TREE_HEIGHT] = i; + idx_leaf >>= 1; + addr[XMSS_ADDR_TREE_INDEX] = idx_leaf; + /* Last iteration into output node. */ + wc_xmss_rand_hash(state, buffer, pk_seed, addr, node); +} +#endif /* !WOLFSSL_WC_XMSS_SMALL || WOLFSSL_XMSS_VERIFY_ONLY */ + +/* Compute a root node from a tree signature. + * + * RFC 8391: 4.1.10, Algorithm 13: XMSS_rootFromSig + * ADRS.setType(0); # Type = OTS hash address + * ADRS.setOTSAddress(idx_sig); + * pk_ots = WOTS_pkFromSig(sig_ots, M', SEED, ADRS); + * ADRS.setType(1); # Type = L-tree address + * ADRS.setLTreeAddress(idx_sig); + * byte[n][2] node; + * node[0] = ltree(pk_ots, SEED, ADRS); + * ADRS.setType(2); # Type = hash tree address + * ADRS.setTreeIndex(idx_sig); + * [Compute root with leaf and authentication path] + * + * Computing the root from the leaf and authentication path can be implemented + * in different ways and is therefore extracted to its own function. + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] pk_seed Random public seed. + * @param [in] sig WOTS+ signature for this tree. + * @param [in] idx_sig Index of signature leaf in this tree. + * @param [in, out] addr Hash address. + * @param [in, out] node On in, previous root node. + * On out, root node of this subtree. + */ +static void wc_xmss_root_from_sig(XmssState* state, const byte* pk_seed, + const byte* sig, word32 idx_sig, HashAddress addr, byte* node) +{ + const XmssParams* params = state->params; + byte* wots_pk = state->pk; + const byte* auth_path = sig + params->wots_sig_len; + + /* Compute WOTS+ public key value from signature. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_OTS; + addr[XMSS_ADDR_OTS] = idx_sig; + wc_xmss_wots_pk_from_sig(state, sig, node, pk_seed, addr, wots_pk); + + /* Compute leaves of L-tree from WOTS+ public key. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_LTREE; + /* XMSS_ADDR_LTREE is same as XMSS_ADDR_OTS in index and value. */ + wc_xmss_ltree(state, wots_pk, pk_seed, addr, node); + + /* Compute root node from leaf and authentication path. */ + addr[XMSS_ADDR_TYPE] = WC_XMSS_ADDR_TYPE_TREE; + addr[XMSS_ADDR_TREE_ZERO] = 0; + wc_xmss_compute_root(state, idx_sig, auth_path, pk_seed, addr, node); +} + +/* Verify message with signature using XMSS/MT. + * + * RFC 8391: 4.2.5, Algorithm 17: XMSSMT_verify + * idx_sig = getIdx(Sig_MT); + * SEED = getSEED(PK_MT); + * ADRS = toByte(0, 32); + * + * byte[n] M' = H_msg(getR(Sig_MT) || getRoot(PK_MT) + * || (toByte(idx_sig, n)), M); + * + * unsigned int idx_leaf + * = (h / d) least significant bits of idx_sig; + * unsigned int idx_tree + * = (h - h / d) most significant bits of idx_sig; + * Sig' = getXMSSSignature(Sig_MT, 0); + * ADRS.setLayerAddress(0); + * ADRS.setTreeAddress(idx_tree); + * byte[n] node = XMSS_rootFromSig(idx_leaf, getSig_ots(Sig'), + * getAuth(Sig'), M', SEED, ADRS); + * for ( j = 1; j < d; j++ ) { + * idx_leaf = (h / d) least significant bits of idx_tree; + * idx_tree = (h - j * h / d) most significant bits of idx_tree; + * Sig' = getXMSSSignature(Sig_MT, j); + * ADRS.setLayerAddress(j); + * ADRS.setTreeAddress(idx_tree); + * node = XMSS_rootFromSig(idx_leaf, getSig_ots(Sig'), + * getAuth(Sig'), node, SEED, ADRS); + * } + * if ( node == getRoot(PK_MT) ) { + * return true; + * } else { + * return false; + * } + * + * @param [in] state XMSS/MT state including digest and parameters. + * @param [in] m Message buffer. + * @param [in] mlen Length of message in bytes. + * @param [in] sig Buffer holding signature. + * @param [in] pk Public key. + * @return 0 on success. + * @return MEMORY_E on dynamic memory allocation failure. + * @return SIG_VERIFY_E on verification failure. + * @return <0 on digest failure. + */ +int wc_xmssmt_verify(XmssState* state, const unsigned char* m, word32 mlen, + const unsigned char* sig, const unsigned char* pk) +{ + const XmssParams* params = state->params; + const word8 n = params->n; + int ret = 0; + const byte* pub_root = pk; + const byte* pk_seed = pk + n; + byte node[WC_XMSS_MAX_N]; + wc_Idx idx; + word32 idx_leaf = 0; + unsigned int i; + + /* Set 32/64-bit index to 0. */ + WC_IDX_ZERO(idx); + /* Set all address values to zero. */ + XMEMSET(state->addr, 0, sizeof(HashAddress)); + + if (ret == 0) { + /* Convert the index bytes from the signature to an integer. */ + WC_IDX_DECODE(idx, params->idx_len, sig, ret); + } + + if (ret == 0) { + const byte* sig_r = sig + params->idx_len; + /* byte[n] M' = H_msg(getR(Sig_MT) || getRoot(PK_MT) || + * (toByte(idx_sig, n)), M); + */ + wc_xmss_hash_message(state, sig_r, pub_root, sig, params->idx_len, m, + mlen, node); + ret = state->ret; + } + + if (ret == 0) { + /* Set tree of hash address. */ + WC_IDX_SET_ADDR_TREE(idx, params->idx_len, params->sub_h, state->addr, + idx_leaf); + + /* Skip to first WOTS+ signature and derive root. */ + sig += params->idx_len + n; + wc_xmss_root_from_sig(state, pk_seed, sig, idx_leaf, state->addr, + node); + ret = state->ret; + } + /* Calculate root of remaining subtrees up to top. */ + for (i = 1; (ret == 0) && (i < params->d); i++) { + /* Set layer and tree. */ + state->addr[XMSS_ADDR_LAYER] = i; + WC_IDX_SET_ADDR_TREE(idx, params->idx_len, params->sub_h, state->addr, + idx_leaf); + /* Skip to next WOTS+ signature and derive root. */ + sig += params->wots_sig_len + params->sub_h * n; + wc_xmss_root_from_sig(state, pk_seed, sig, idx_leaf, state->addr, + node); + ret = state->ret; + } + /* Compare calculated node with public key root. */ + if ((ret == 0) && (XMEMCMP(node, pub_root, n) != 0)) { + ret = SIG_VERIFY_E; + } + + return ret; +} +#endif /* WOLFSSL_HAVE_XMSS */ + diff --git a/src/wolfcrypt/src/wolfevent.c b/src/wolfcrypt/src/wolfevent.c index 01ddd11..4ed7b8f 100644 --- a/src/wolfcrypt/src/wolfevent.c +++ b/src/wolfcrypt/src/wolfevent.c @@ -55,7 +55,7 @@ int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context) int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags) { - int ret = BAD_COND_E; + int ret = WC_NO_ERR_TRACE(BAD_COND_E); /* Check hardware */ #ifdef WOLFSSL_ASYNC_CRYPT diff --git a/src/wolfcrypt/src/wolfmath.c b/src/wolfcrypt/src/wolfmath.c index 11e85cd..df5f0f8 100644 --- a/src/wolfcrypt/src/wolfmath.c +++ b/src/wolfcrypt/src/wolfmath.c @@ -167,7 +167,8 @@ int get_rand_digit(WC_RNG* rng, mp_digit* d) return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); } -#if defined(WC_RSA_BLINDING) || defined(WOLFCRYPT_HAVE_SAKKE) +#if defined(WC_RSA_BLINDING) || defined(WOLFCRYPT_HAVE_SAKKE) || \ + defined(WOLFSSL_ECC_BLIND_K) int mp_rand(mp_int* a, int digits, WC_RNG* rng) { int ret = 0; @@ -221,7 +222,7 @@ int mp_rand(mp_int* a, int digits, WC_RNG* rng) return ret; } -#endif /* WC_RSA_BLINDING || WOLFCRYPT_HAVE_SAKKE */ +#endif /* WC_RSA_BLINDING || WOLFCRYPT_HAVE_SAKKE || WOLFSSL_ECC_BLIND_K */ #endif /* !WC_NO_RNG */ #if defined(HAVE_ECC) || defined(WOLFSSL_EXPORT_INT) diff --git a/src/wolfssl/bio.c b/src/wolfssl/bio.c index 2dab43e..340cbfd 100644 --- a/src/wolfssl/bio.c +++ b/src/wolfssl/bio.c @@ -50,7 +50,7 @@ */ static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) { - word32 frmtSz = len; + word32 frmtSz = (word32)len; WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read"); @@ -77,6 +77,8 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) if (buf == NULL || len == 0) return 0; + /* default no retry */ + bio->flags &= ~(WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY); sz1 = wolfSSL_BIO_nread(bio, &pt, len); if (sz1 > 0) { XMEMCPY(buf, pt, sz1); @@ -91,8 +93,10 @@ static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) } } } - if (sz1 == 0) + if (sz1 == 0) { + bio->flags |= WOLFSSL_BIO_FLAG_READ|WOLFSSL_BIO_FLAG_RETRY; sz1 = -1; + } return sz1; } @@ -175,7 +179,7 @@ static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len) WOLFSSL_MSG("wolfSSL_BUF_MEM_resize error"); return WOLFSSL_BIO_ERROR; } - bio->mem_buf->length = bio->wrSz; + bio->mem_buf->length = (size_t)bio->wrSz; bio->ptr = bio->mem_buf->data; } } @@ -233,13 +237,13 @@ static int wolfSSL_BIO_MD_read(WOLFSSL_BIO* bio, void* buf, int sz) { if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, - sz) != WOLFSSL_SUCCESS) + (unsigned int)sz) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } } else { - if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, sz) + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, buf, (size_t)sz) != WOLFSSL_SUCCESS) { return WOLFSSL_FATAL_ERROR; } @@ -305,12 +309,12 @@ int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) case WOLFSSL_BIO_FILE: #ifndef NO_FILESYSTEM if (bio->ptr) { - ret = (int)XFREAD(buf, 1, len, (XFILE)bio->ptr); + ret = (int)XFREAD(buf, 1, (size_t)len, (XFILE)bio->ptr); } else { - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + #if defined(XREAD) && !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - ret = (int)XREAD(bio->num, buf, len); + ret = (int)XREAD(bio->num, buf, (size_t)len); #else WOLFSSL_MSG("No file pointer and XREAD not enabled"); ret = NOT_COMPILED_IN; @@ -399,7 +403,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, /* get the encoded length */ if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { if (Base64_Encode_NoNl((const byte*)data, inLen, NULL, - &sz) != LENGTH_ONLY_E) { + &sz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Error with base64 get length"); return WOLFSSL_FATAL_ERROR; } @@ -448,7 +452,7 @@ static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, (void)heap; - return inLen; + return (int)inLen; } #endif /* WOLFSSL_BASE64_ENCODE */ @@ -502,8 +506,11 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, if (bio == NULL || data == NULL || len == 0) return 0; + /* default no retry */ + bio->flags &= ~(WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY); sz1 = wolfSSL_BIO_nwrite(bio, &buf, len); if (sz1 == 0) { + bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY; WOLFSSL_MSG("No room left to write"); return WOLFSSL_BIO_ERROR; } @@ -521,6 +528,8 @@ static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, if (sz2 > 0) { XMEMCPY(buf, data, sz2); sz1 += sz2; + if (len > sz2) + bio->flags |= WOLFSSL_BIO_FLAG_WRITE|WOLFSSL_BIO_FLAG_RETRY; } } @@ -591,12 +600,12 @@ static int wolfSSL_BIO_MD_write(WOLFSSL_BIO* bio, const void* data, int len) if (wolfSSL_EVP_MD_CTX_type((WOLFSSL_EVP_MD_CTX*)bio->ptr) == NID_hmac) { if (wolfSSL_EVP_DigestSignUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, - len) != WOLFSSL_SUCCESS) { + (unsigned int)len) != WOLFSSL_SUCCESS) { ret = WOLFSSL_BIO_ERROR; } } else { - if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, len) + if (wolfSSL_EVP_DigestUpdate((WOLFSSL_EVP_MD_CTX*)bio->ptr, data, (size_t)len) != WOLFSSL_SUCCESS) { ret = WOLFSSL_BIO_ERROR; } @@ -652,7 +661,7 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) if (ret > 0) { /* change so that data is formatted buffer */ data = frmt; - len = frmtSz; + len = (int)frmtSz; } #else WOLFSSL_MSG("WOLFSSL_BIO_BASE64 used without " @@ -670,12 +679,12 @@ int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) case WOLFSSL_BIO_FILE: #ifndef NO_FILESYSTEM if (bio->ptr) { - ret = (int)XFWRITE(data, 1, len, (XFILE)bio->ptr); + ret = (int)XFWRITE(data, 1, (size_t)len, (XFILE)bio->ptr); } else { - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) && \ + #if defined(XWRITE) && !defined(NO_WOLFSSL_DIR) && \ !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) - ret = (int)XWRITE(bio->num, data, len); + ret = (int)XWRITE(bio->num, data, (size_t)len); #else WOLFSSL_MSG("No file pointer and XWRITE not enabled"); ret = NOT_COMPILED_IN; @@ -972,7 +981,7 @@ int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz) ret = wolfSSL_EVP_DigestFinal((WOLFSSL_EVP_MD_CTX*)bio->ptr, (unsigned char*)buf, &szOut); if (ret == WOLFSSL_SUCCESS) { - ret = szOut; + ret = (int)szOut; } } break; @@ -1257,8 +1266,8 @@ int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) bio->rdIdx = 0; if (bio->mem_buf != NULL) { bio->mem_buf->data = (char*)bio->ptr; - bio->mem_buf->length = bio->num; - bio->mem_buf->max = bio->num; + bio->mem_buf->length = (size_t)bio->num; + bio->mem_buf->max = (size_t)bio->num; } return WOLFSSL_SUCCESS; @@ -1608,7 +1617,12 @@ int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) XFCLOSE((XFILE)bio->ptr); } - bio->ptr = XFOPEN(name, "w"); + /* 'b' flag is ignored on POSIX targets, but on Windows it assures + * inhibition of LF<->CRLF rewriting, so that there is consistency + * between the size and contents of the representation in memory and on + * disk. + */ + bio->ptr = XFOPEN(name, "wb"); if (((XFILE)bio->ptr) == XBADFILE) { return WOLFSSL_FAILURE; } @@ -2637,7 +2651,7 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) len = (int)XSTRLEN((const char*)buf) + 1; } - if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, len) == 0) { + if (len > 0 && wolfSSL_BUF_MEM_resize(bio->mem_buf, (size_t)len) == 0) { wolfSSL_BIO_free(bio); return NULL; } diff --git a/src/wolfssl/certs_test.h b/src/wolfssl/certs_test.h index 09ed4b1..013b374 100644 --- a/src/wolfssl/certs_test.h +++ b/src/wolfssl/certs_test.h @@ -3451,7 +3451,7 @@ static const int sizeof_dh_key_der_4096 = sizeof(dh_key_der_4096); #endif /* USE_CERT_BUFFERS_4096 */ -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_FALCON) /* certs/falcon/bench_falcon_level1_key.der */ static const unsigned char bench_falcon_level1_key[] = @@ -4099,1767 +4099,1802 @@ static const unsigned char bench_falcon_level5_key[] = }; static const int sizeof_bench_falcon_level5_key = sizeof(bench_falcon_level5_key); -#endif /* HAVE_PQC && HAVE_FALCON */ +#endif /* HAVE_FALCON */ -#if defined (HAVE_PQC) && defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) -/* certs/dilithium/bench_dilithium_level2_key.der */ -static const unsigned char bench_dilithium_level2_key[] = -{ - 0x30, 0x82, 0x0F, 0x1A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, - 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, - 0x04, 0x04, 0x04, 0x82, 0x0F, 0x04, 0x04, 0x82, 0x0F, 0x00, - 0xA2, 0xBD, 0x74, 0xB9, 0x8E, 0x34, 0xF0, 0xEC, 0xF7, 0x40, - 0x22, 0x33, 0xE8, 0x50, 0x43, 0x66, 0xF0, 0x25, 0x41, 0x20, - 0xD9, 0x3F, 0x8A, 0xC6, 0xAD, 0x69, 0xC6, 0x9C, 0xD9, 0xE0, - 0x0D, 0xFF, 0x77, 0x85, 0xCD, 0x88, 0x58, 0x17, 0x6B, 0x85, - 0xD2, 0x5D, 0xF0, 0x41, 0xCE, 0x6D, 0x94, 0x7F, 0xF4, 0xDB, - 0xD3, 0x60, 0x52, 0x1A, 0x83, 0x42, 0xD8, 0x7C, 0x2D, 0xD9, - 0x55, 0x7B, 0xFB, 0xB8, 0x87, 0xAA, 0xDA, 0x75, 0x42, 0x86, - 0x3E, 0x5A, 0xE4, 0xD4, 0x7D, 0xC3, 0x38, 0xA2, 0xEE, 0x0D, - 0xF5, 0xAD, 0xDA, 0x12, 0x5B, 0xD6, 0x3A, 0x89, 0x87, 0xED, - 0x57, 0xD1, 0xA9, 0xC2, 0xB3, 0xC0, 0xDC, 0x90, 0x88, 0x0C, - 0x86, 0x48, 0xD2, 0xA6, 0x60, 0x1B, 0x22, 0x8C, 0x03, 0x34, - 0x69, 0x19, 0x96, 0x24, 0x04, 0xB3, 0x65, 0x10, 0x34, 0x31, - 0x09, 0x38, 0x31, 0x5C, 0x10, 0x8C, 0x02, 0x15, 0x66, 0xD0, - 0x48, 0x50, 0x53, 0x22, 0x41, 0xC4, 0x98, 0x41, 0xE2, 0x42, - 0x62, 0x42, 0x38, 0x45, 0xC2, 0xB8, 0x08, 0x20, 0x31, 0x21, - 0x13, 0x10, 0x88, 0x00, 0xB9, 0x24, 0x93, 0x06, 0x6D, 0x44, - 0x20, 0x64, 0x98, 0x84, 0x29, 0x91, 0x12, 0x6A, 0xC9, 0x14, - 0x10, 0x11, 0x40, 0x2A, 0x24, 0xC9, 0x85, 0xCC, 0x42, 0x2A, - 0x1C, 0x44, 0x28, 0xE0, 0xB4, 0x00, 0x20, 0x99, 0x11, 0x0B, - 0x09, 0x61, 0x24, 0x14, 0x10, 0x41, 0x94, 0x20, 0xC9, 0x46, - 0x64, 0x43, 0x02, 0x6E, 0x08, 0x39, 0x71, 0x81, 0x06, 0x2D, - 0x63, 0x14, 0x71, 0x62, 0xC0, 0x11, 0x20, 0xB2, 0x61, 0xD1, - 0x30, 0x24, 0x44, 0x06, 0x89, 0x04, 0x16, 0x88, 0x10, 0x33, - 0x48, 0x51, 0xB8, 0x00, 0x4A, 0x12, 0x68, 0x14, 0x04, 0x10, - 0xD8, 0x92, 0x8D, 0x22, 0x32, 0x61, 0x0C, 0x23, 0x91, 0x10, - 0x39, 0x24, 0x51, 0x80, 0x08, 0x0B, 0x30, 0x61, 0x00, 0x89, - 0x01, 0x98, 0x34, 0x05, 0x9A, 0xA2, 0x70, 0xC4, 0x46, 0x40, - 0x52, 0x38, 0x42, 0xC0, 0x92, 0x6D, 0xCC, 0x08, 0x22, 0xD4, - 0x42, 0x4A, 0x02, 0x23, 0x40, 0x40, 0x92, 0x25, 0x12, 0x36, - 0x65, 0x42, 0x06, 0x10, 0x02, 0x10, 0x10, 0x20, 0xA3, 0x41, - 0x0A, 0x15, 0x10, 0x20, 0x23, 0x80, 0x99, 0xB6, 0x0C, 0x11, - 0x26, 0x11, 0x9B, 0xC8, 0x44, 0x1C, 0xC9, 0x05, 0xA4, 0x38, - 0x11, 0x1B, 0xB0, 0x05, 0xDC, 0x22, 0x00, 0xC8, 0x22, 0x72, - 0xA3, 0x30, 0x2E, 0xC1, 0xA8, 0x41, 0x1C, 0xA6, 0x20, 0xE2, - 0xB0, 0x21, 0x9B, 0x10, 0x01, 0x61, 0x32, 0x46, 0xC1, 0x92, - 0x61, 0x1C, 0xA4, 0x85, 0x0A, 0xB7, 0x70, 0xE4, 0x26, 0x6C, - 0x58, 0xA4, 0x00, 0x19, 0x86, 0x4C, 0xDC, 0xA6, 0x40, 0xA1, - 0x32, 0x12, 0x04, 0x81, 0x90, 0x8C, 0x04, 0x05, 0x10, 0x30, - 0x26, 0x09, 0x31, 0x2C, 0x50, 0x88, 0x89, 0x82, 0x44, 0x62, - 0x10, 0x23, 0x8A, 0x04, 0x44, 0x22, 0x0A, 0x30, 0x4E, 0xA4, - 0x34, 0x32, 0x4C, 0x18, 0x8C, 0x21, 0x21, 0x41, 0x23, 0x13, - 0x72, 0x08, 0x84, 0x24, 0x1A, 0x04, 0x24, 0x14, 0x06, 0x02, - 0xC4, 0x40, 0x70, 0xCA, 0x00, 0x6E, 0xC1, 0xC6, 0x09, 0x83, - 0x42, 0x62, 0xA0, 0x30, 0x12, 0x1B, 0x14, 0x0C, 0x08, 0x03, - 0x22, 0xCA, 0x46, 0x65, 0x64, 0x46, 0x26, 0x10, 0x39, 0x20, - 0xCA, 0x80, 0x28, 0x62, 0x14, 0x6D, 0x10, 0x26, 0x11, 0x49, - 0xA2, 0x45, 0x53, 0x98, 0x0D, 0x64, 0x40, 0x05, 0x0C, 0x31, - 0x09, 0x13, 0x11, 0x60, 0xD8, 0x02, 0x50, 0x11, 0x41, 0x41, - 0x23, 0xC1, 0x4C, 0x22, 0xC6, 0x30, 0x99, 0x06, 0x08, 0xCA, - 0x40, 0x81, 0xCC, 0x32, 0x0E, 0x11, 0xC4, 0x20, 0xD9, 0x92, - 0x41, 0xC4, 0x20, 0x08, 0xE4, 0xA0, 0x00, 0xCB, 0x88, 0x21, - 0x03, 0x03, 0x90, 0x54, 0x00, 0x49, 0x14, 0x98, 0x04, 0xC8, - 0xC0, 0x31, 0x11, 0x31, 0x69, 0x04, 0x93, 0x90, 0x00, 0xB9, - 0x21, 0x22, 0x38, 0x48, 0x00, 0x34, 0x0C, 0x61, 0x98, 0x00, - 0x01, 0xB4, 0x69, 0x60, 0x26, 0x81, 0x1C, 0xA4, 0x10, 0x22, - 0xB6, 0x10, 0x21, 0xC6, 0x20, 0x4A, 0x22, 0x26, 0xD0, 0x92, - 0x41, 0xDA, 0x84, 0x69, 0x03, 0x42, 0x2A, 0x04, 0x09, 0x02, - 0xE1, 0x24, 0x42, 0xA2, 0x46, 0x28, 0x10, 0xB1, 0x08, 0x82, - 0x86, 0x84, 0xE0, 0x24, 0x51, 0x0A, 0xC9, 0x28, 0x59, 0x86, - 0x20, 0xDB, 0xB6, 0x40, 0x13, 0xC3, 0x40, 0x1C, 0xA9, 0x09, - 0x80, 0x34, 0x50, 0xDC, 0x84, 0x2C, 0x53, 0x24, 0x08, 0xC0, - 0xB4, 0x6D, 0x88, 0x26, 0x30, 0x82, 0xC8, 0x0D, 0x62, 0x22, - 0x28, 0x64, 0xA2, 0x09, 0x10, 0x25, 0x26, 0xDB, 0x34, 0x02, - 0x4A, 0x04, 0x11, 0x53, 0xB8, 0x28, 0x82, 0x34, 0x11, 0xC2, - 0x12, 0x25, 0x20, 0xB5, 0x40, 0x19, 0xA8, 0x31, 0x80, 0x22, - 0x66, 0x21, 0xB2, 0x10, 0x0B, 0x42, 0x2A, 0x61, 0x20, 0x50, - 0x40, 0x24, 0x4C, 0x99, 0x12, 0x48, 0x21, 0xB4, 0x11, 0xD1, - 0x44, 0x48, 0x00, 0x40, 0x0C, 0x58, 0x46, 0x68, 0x04, 0x12, - 0x12, 0x93, 0x22, 0x20, 0xC2, 0x32, 0x4C, 0x01, 0xB0, 0x88, - 0xE3, 0x20, 0x8E, 0x03, 0x00, 0x6C, 0x52, 0x14, 0x30, 0xD2, - 0x44, 0x88, 0x10, 0x44, 0x4A, 0x61, 0x86, 0x29, 0x14, 0x42, - 0x24, 0x24, 0x35, 0x2E, 0x11, 0xC4, 0x0D, 0x23, 0x24, 0x66, - 0x0A, 0x90, 0x71, 0xE0, 0xC2, 0x69, 0x48, 0x38, 0x91, 0x82, - 0xC8, 0x08, 0x1C, 0x93, 0x31, 0xD9, 0x06, 0x51, 0x8A, 0xA4, - 0x6C, 0x50, 0x34, 0x68, 0x5A, 0x18, 0x89, 0x4A, 0x96, 0x85, - 0x8A, 0x18, 0x44, 0x4A, 0x34, 0x40, 0x5B, 0x36, 0x80, 0xCC, - 0x20, 0x6E, 0x09, 0x19, 0x89, 0x02, 0x38, 0x6A, 0x24, 0xA3, - 0x69, 0x58, 0x32, 0x6D, 0x21, 0x01, 0x84, 0x88, 0x86, 0x28, - 0xA3, 0x22, 0x89, 0x93, 0xA6, 0x80, 0x00, 0x88, 0x81, 0xE1, - 0x48, 0x70, 0xA2, 0x34, 0x60, 0x18, 0x02, 0x04, 0x18, 0x29, - 0x01, 0x1B, 0x31, 0x51, 0xD4, 0xA4, 0x49, 0xCC, 0x08, 0x8C, - 0xDA, 0x36, 0x11, 0x01, 0x39, 0x26, 0x42, 0x92, 0x88, 0xC8, - 0x46, 0x52, 0x8C, 0xA4, 0x08, 0x14, 0x11, 0x52, 0xCA, 0x40, - 0x66, 0x8B, 0x32, 0x8E, 0x89, 0x44, 0x02, 0x9B, 0x42, 0x02, - 0x93, 0xA4, 0x01, 0x1A, 0x00, 0x50, 0x94, 0x44, 0x42, 0x08, - 0x09, 0x8C, 0xE2, 0xA8, 0x81, 0x98, 0x00, 0x48, 0x63, 0x02, - 0x85, 0x1B, 0x05, 0x2D, 0xC1, 0xBE, 0x5F, 0xA4, 0xAC, 0xB4, - 0xF0, 0xC7, 0x94, 0xBD, 0xEC, 0xFB, 0x09, 0xAF, 0x16, 0xF1, - 0x23, 0x58, 0xAB, 0x82, 0xFA, 0x74, 0xD1, 0x84, 0x51, 0xD0, - 0x58, 0x9B, 0xFA, 0xF4, 0x11, 0xC1, 0x17, 0x2F, 0xCE, 0xD1, - 0xCA, 0xC6, 0xCE, 0x1C, 0x8F, 0x8F, 0x1B, 0x43, 0xBF, 0xB9, - 0x43, 0x41, 0x02, 0x3E, 0x5D, 0xFA, 0x24, 0x88, 0x0E, 0xA5, - 0x36, 0xA9, 0x9B, 0x25, 0x43, 0xD6, 0xEE, 0xDE, 0xAE, 0x93, - 0x54, 0xC8, 0x6C, 0x55, 0xE9, 0x5C, 0xC8, 0xC1, 0xA5, 0xD7, - 0xFC, 0xDA, 0xAF, 0xF8, 0x40, 0x1F, 0x02, 0x5C, 0x8E, 0x48, - 0x51, 0x4B, 0x3F, 0xFD, 0x76, 0x9A, 0xD0, 0x87, 0xF4, 0xD0, - 0x68, 0x9C, 0x44, 0x3B, 0xB4, 0x4A, 0xAB, 0x34, 0x2A, 0xD4, - 0x0C, 0xA4, 0x7A, 0xBB, 0x98, 0x7F, 0x8D, 0xF6, 0xA7, 0x6A, - 0x42, 0x8C, 0x7A, 0xB4, 0x32, 0xC6, 0x8A, 0xD6, 0x5E, 0x06, - 0x50, 0xC0, 0xDD, 0x3E, 0xE2, 0x44, 0x5C, 0xB9, 0x83, 0xCF, - 0x92, 0x0C, 0x3C, 0xFB, 0x53, 0x0D, 0xF0, 0xD1, 0xED, 0x77, - 0xF3, 0x02, 0x9F, 0xA6, 0xC6, 0xFA, 0x30, 0xA5, 0xC7, 0x42, - 0x06, 0x1F, 0x38, 0xE5, 0xE1, 0x56, 0x01, 0x7A, 0xD1, 0xE1, - 0xC1, 0x20, 0x44, 0x37, 0xE6, 0x18, 0x8A, 0x7E, 0x70, 0xBA, - 0x6B, 0x1C, 0x99, 0x4E, 0xFB, 0xCA, 0xCF, 0x3D, 0x29, 0x26, - 0xF4, 0x12, 0x95, 0x74, 0x11, 0x23, 0x0E, 0x2E, 0x31, 0xCF, - 0x73, 0xE6, 0x99, 0xD0, 0x72, 0x23, 0x4A, 0x46, 0x07, 0xA1, - 0x03, 0x4C, 0x3A, 0x79, 0x72, 0x3B, 0xD1, 0x79, 0x5A, 0x66, - 0x29, 0xCD, 0x34, 0xB6, 0x6A, 0xA5, 0x6A, 0x4C, 0x71, 0xE5, - 0xB3, 0xA6, 0xAC, 0x4D, 0x13, 0xDC, 0x70, 0xE4, 0x0C, 0x6A, - 0x98, 0x48, 0x1C, 0xA0, 0x6C, 0xFC, 0xDD, 0x6A, 0x3F, 0x10, - 0x3B, 0xBD, 0xC9, 0xC8, 0xEA, 0x01, 0x86, 0x5B, 0x3B, 0x19, - 0x3E, 0x6F, 0xA9, 0x4A, 0xD4, 0x38, 0x1D, 0x9C, 0x2B, 0x19, - 0xAE, 0x47, 0x54, 0xE2, 0x4E, 0xB5, 0xDF, 0xA7, 0xBD, 0x6F, - 0x01, 0x8A, 0x10, 0x5B, 0x83, 0x17, 0xB3, 0x77, 0xE1, 0x9D, - 0xBF, 0x6B, 0x25, 0xBF, 0x90, 0xC4, 0x92, 0xE1, 0x5E, 0xE1, - 0xC3, 0x0C, 0xC5, 0x05, 0x24, 0x40, 0x61, 0xA1, 0x01, 0x4A, - 0x7B, 0xE4, 0x65, 0x73, 0x1F, 0x3C, 0xA2, 0xD8, 0x54, 0xA4, - 0x64, 0xA3, 0x06, 0xDA, 0x18, 0x9A, 0xD7, 0xE4, 0x90, 0x59, - 0xAF, 0xBC, 0x1A, 0x79, 0xC4, 0x08, 0xE9, 0x87, 0x95, 0x04, - 0x48, 0x18, 0xD2, 0x33, 0x15, 0x38, 0x9C, 0x00, 0x7B, 0x72, - 0x35, 0xC1, 0x03, 0x77, 0xF1, 0x0B, 0xEC, 0x38, 0x33, 0xB7, - 0xB4, 0xBC, 0xC4, 0xBD, 0xB3, 0xBB, 0x9C, 0x34, 0x0B, 0x28, - 0x03, 0x1D, 0x99, 0x7A, 0x12, 0x0C, 0x95, 0xFE, 0x0D, 0x53, - 0x79, 0xE7, 0xE6, 0x99, 0x3F, 0xA1, 0x31, 0x9E, 0xA9, 0xB8, - 0x9B, 0xB7, 0xC0, 0x3F, 0x9C, 0x18, 0x1B, 0xA2, 0x73, 0xBC, - 0x10, 0xDB, 0x1B, 0x09, 0xE7, 0x5E, 0x67, 0x8E, 0x69, 0x92, - 0xCF, 0x99, 0xC3, 0x97, 0x58, 0xE8, 0x9A, 0x40, 0x83, 0xF2, - 0x14, 0xA3, 0x25, 0xB5, 0x51, 0x30, 0xDA, 0x91, 0x87, 0x91, - 0x1E, 0xF2, 0x5E, 0x55, 0x49, 0x68, 0x5E, 0xC9, 0x21, 0x67, - 0x03, 0xBC, 0x21, 0xE4, 0xD1, 0xFC, 0x79, 0xC7, 0xDB, 0x44, - 0xB9, 0xAB, 0x1E, 0xB4, 0x65, 0x3D, 0x63, 0xCB, 0x64, 0x76, - 0xE4, 0x1B, 0x93, 0x91, 0xB0, 0xF3, 0x4F, 0xBA, 0xD3, 0x20, - 0x47, 0x37, 0x5A, 0xCA, 0x1B, 0xDB, 0xCA, 0xA1, 0xE7, 0xED, - 0x7D, 0x8D, 0x4E, 0x7C, 0x19, 0xB2, 0x73, 0x67, 0x55, 0x11, - 0xE4, 0xA1, 0x98, 0x44, 0x5F, 0x58, 0xF7, 0xAA, 0x09, 0xFD, - 0x09, 0x4A, 0x54, 0x68, 0x32, 0xD4, 0xCA, 0xE1, 0x96, 0xFD, - 0x27, 0x05, 0x88, 0x78, 0x7B, 0x83, 0x74, 0x78, 0x6F, 0x09, - 0xC7, 0x3C, 0x66, 0xA8, 0x17, 0x3A, 0xCF, 0xB3, 0x6E, 0x5A, - 0xD7, 0x16, 0xE5, 0x2E, 0x40, 0xD7, 0x30, 0x18, 0x47, 0x5F, - 0x95, 0x19, 0x4E, 0x0F, 0x69, 0xD3, 0x11, 0xDE, 0xBB, 0x55, - 0x1B, 0xD1, 0x13, 0x71, 0x3D, 0x45, 0x3E, 0xDC, 0x72, 0x4F, - 0x89, 0x34, 0x72, 0x96, 0x77, 0xBB, 0x42, 0x29, 0x4A, 0x88, - 0x44, 0xFB, 0x05, 0x57, 0x38, 0xA6, 0xAC, 0x3E, 0x03, 0xF6, - 0xE1, 0x9D, 0xE3, 0xE9, 0x5A, 0x1B, 0x64, 0xCE, 0xC8, 0x6E, - 0x1B, 0xE8, 0xE3, 0x78, 0xF8, 0xE9, 0xF1, 0x47, 0x09, 0x0E, - 0x66, 0x50, 0x7A, 0x10, 0x51, 0xE1, 0x60, 0x73, 0x78, 0x95, - 0x00, 0x2E, 0xB8, 0x05, 0x8C, 0x22, 0x72, 0xD9, 0x88, 0xC8, - 0x8D, 0x16, 0xEF, 0x18, 0x8F, 0xC6, 0x51, 0x1E, 0xC3, 0xBA, - 0x27, 0x57, 0xB4, 0xFE, 0x74, 0x0F, 0x54, 0x45, 0x5A, 0x0B, - 0xAC, 0x6C, 0xA7, 0x46, 0x95, 0xC7, 0x35, 0x3D, 0x38, 0xBE, - 0xC5, 0x4E, 0xE0, 0x83, 0xED, 0x68, 0x8D, 0x01, 0x31, 0x7D, - 0x90, 0xA7, 0x38, 0xEE, 0x57, 0x8E, 0xD2, 0xFB, 0x87, 0x08, - 0x7A, 0x44, 0x34, 0x0B, 0x99, 0x5E, 0x2F, 0xA8, 0x4E, 0xC0, - 0x80, 0xEF, 0x62, 0xFE, 0xFB, 0x3C, 0x73, 0xF1, 0x8C, 0x56, - 0x12, 0x08, 0x8C, 0xD3, 0x9F, 0xBA, 0x44, 0x90, 0xB7, 0xDB, - 0x9C, 0xD9, 0xB4, 0x91, 0xBA, 0xFF, 0x4A, 0xB0, 0x1C, 0x91, - 0x44, 0x34, 0x52, 0xBE, 0x0D, 0xBA, 0x72, 0x33, 0x5C, 0x36, - 0xB5, 0x5E, 0x91, 0xB7, 0xE9, 0xCE, 0xD0, 0x01, 0x61, 0x19, - 0xEE, 0x2D, 0x1F, 0xBE, 0x97, 0x7C, 0x8C, 0x30, 0x91, 0x8C, - 0xB1, 0x8A, 0x04, 0xCA, 0xB8, 0x33, 0xCB, 0xA9, 0x9A, 0x2C, - 0x1B, 0x25, 0xD2, 0xDB, 0x73, 0x95, 0x3F, 0x02, 0x67, 0xEB, - 0x2C, 0xEC, 0xCC, 0x92, 0xCD, 0x1E, 0x1F, 0xC2, 0xF2, 0xA7, - 0x23, 0xAD, 0x7C, 0xA5, 0x50, 0x44, 0x76, 0x7D, 0x74, 0x13, - 0x20, 0x21, 0xF2, 0x09, 0xD9, 0x70, 0x82, 0xB0, 0x30, 0xA3, - 0x8A, 0xC0, 0x9D, 0xD2, 0x16, 0x4F, 0x65, 0xDF, 0x42, 0x37, - 0xC2, 0x63, 0xD6, 0x6C, 0xA9, 0xD1, 0x95, 0x5D, 0x84, 0xD2, - 0xB5, 0xC7, 0x7A, 0x87, 0x9B, 0x9B, 0xAF, 0x21, 0x65, 0x64, - 0xF7, 0x0B, 0x21, 0xC7, 0xF6, 0xA5, 0x27, 0xEB, 0xAA, 0x8D, - 0xF2, 0x10, 0x60, 0xFB, 0xC9, 0xB3, 0xB0, 0x32, 0x7C, 0x9F, - 0xC1, 0xDE, 0xA8, 0x77, 0x6F, 0xCC, 0x35, 0x1F, 0xBD, 0x74, - 0x0E, 0xA9, 0x84, 0x3C, 0x05, 0x9D, 0xFF, 0xBC, 0x46, 0x9A, - 0x8E, 0x43, 0xB5, 0x8B, 0x1C, 0x24, 0xB5, 0xC3, 0xB0, 0xFE, - 0x14, 0xCC, 0x3C, 0xCF, 0xF2, 0x26, 0xCE, 0x0B, 0x3A, 0x5B, - 0x5C, 0x8E, 0x59, 0xBF, 0x0D, 0xDC, 0xA6, 0xCA, 0x78, 0xE5, - 0xD9, 0xC5, 0x46, 0x56, 0x38, 0x98, 0xC4, 0xAC, 0x43, 0x64, - 0xB1, 0x78, 0x0A, 0x81, 0x34, 0x7D, 0x3D, 0xC0, 0xF5, 0x25, - 0x14, 0x66, 0xA2, 0x2A, 0x81, 0x64, 0x82, 0x62, 0x86, 0xD0, - 0x65, 0xCB, 0x2A, 0x09, 0x01, 0xF5, 0x03, 0xEC, 0xB5, 0xD1, - 0xED, 0xC7, 0x60, 0x62, 0x3D, 0x38, 0x28, 0x9C, 0x32, 0xEE, - 0x9F, 0x45, 0x72, 0x71, 0xA9, 0x6D, 0x9A, 0x54, 0x83, 0xF9, - 0xE7, 0x37, 0xC7, 0xCC, 0x28, 0xC0, 0xC2, 0x24, 0x09, 0xC3, - 0x96, 0xF6, 0xED, 0x9B, 0x60, 0xF3, 0x24, 0x4C, 0xFC, 0xAB, - 0xD0, 0x38, 0x7A, 0x1C, 0x68, 0xED, 0x63, 0x83, 0x5A, 0x28, - 0x37, 0x70, 0x31, 0xBB, 0x9D, 0xC7, 0xAA, 0x3A, 0x5B, 0xAF, - 0x88, 0x82, 0xE2, 0x30, 0xCB, 0xF5, 0xC1, 0x63, 0x9C, 0x59, - 0x41, 0xD3, 0x24, 0x92, 0xB1, 0x71, 0xA4, 0x16, 0x26, 0x0B, - 0x9C, 0x96, 0x0B, 0xE9, 0x0B, 0x69, 0xFC, 0x1F, 0xD2, 0x99, - 0xC2, 0xB6, 0x7A, 0x24, 0x28, 0x5A, 0x3D, 0x88, 0x2C, 0xF0, - 0x76, 0xFC, 0x25, 0x04, 0xBE, 0xB6, 0x19, 0x94, 0xD1, 0xBA, - 0x1A, 0x58, 0x0E, 0x9A, 0xFB, 0x4C, 0x9D, 0x21, 0x34, 0x8D, - 0x45, 0xEC, 0x50, 0xC6, 0x94, 0x1B, 0x0B, 0x87, 0x36, 0x4E, - 0xE4, 0x96, 0xF6, 0x9A, 0x34, 0xEC, 0xD8, 0x65, 0x6A, 0x46, - 0xFA, 0xC5, 0x40, 0x35, 0xD0, 0x07, 0x74, 0x02, 0xA3, 0xCF, - 0x23, 0x60, 0x15, 0xAC, 0x54, 0x98, 0x59, 0xEF, 0x94, 0x17, - 0x0A, 0xEF, 0xBB, 0xC2, 0x7B, 0x3B, 0xEF, 0xF5, 0xD1, 0x9C, - 0xB7, 0xB1, 0xDF, 0x45, 0xF5, 0x57, 0xD1, 0x18, 0x05, 0x97, - 0x8F, 0x8C, 0x30, 0x8C, 0x11, 0xF4, 0x81, 0x4D, 0x75, 0x18, - 0x97, 0x9F, 0x30, 0x64, 0xE2, 0x5B, 0x18, 0x95, 0xAC, 0x4E, - 0xDC, 0x47, 0xB5, 0x45, 0xAA, 0xD4, 0x7E, 0xF4, 0x70, 0x46, - 0x34, 0xF3, 0xB3, 0x85, 0xC2, 0x46, 0x98, 0xB5, 0xB5, 0x33, - 0x52, 0xF4, 0x36, 0x39, 0xCA, 0x23, 0xF9, 0x66, 0xB9, 0xA4, - 0x63, 0xC6, 0x3D, 0x02, 0xE7, 0x8F, 0x95, 0xF3, 0x25, 0xFD, - 0x21, 0xD0, 0x62, 0xC2, 0xEE, 0xE2, 0x2F, 0x69, 0x55, 0x31, - 0x42, 0x78, 0x2D, 0x53, 0xDC, 0x7F, 0x0E, 0x93, 0xD5, 0x4D, - 0x21, 0x64, 0x8B, 0x9E, 0x2C, 0xBE, 0xBA, 0xD3, 0x39, 0x41, - 0xE3, 0x10, 0xE5, 0x07, 0xE4, 0x0E, 0x20, 0x38, 0x63, 0xF7, - 0x02, 0xF2, 0x17, 0x99, 0xEB, 0xC6, 0xE7, 0x5F, 0xBE, 0xAE, - 0x53, 0xD1, 0x12, 0xB2, 0x9A, 0x90, 0x25, 0x6A, 0xAA, 0xFD, - 0x5D, 0x69, 0x2F, 0x32, 0x33, 0x53, 0x57, 0x1B, 0xC4, 0x24, - 0xC0, 0xC5, 0x90, 0x04, 0x04, 0x67, 0xCA, 0x85, 0x1E, 0x94, - 0x31, 0x95, 0x78, 0x76, 0x5D, 0xCF, 0x15, 0xE6, 0x06, 0x6B, - 0x1A, 0x1D, 0x0E, 0xF6, 0x64, 0x91, 0x84, 0xAE, 0xE4, 0xF0, - 0x1F, 0x0A, 0x76, 0x1C, 0x74, 0xF3, 0xC1, 0x97, 0x80, 0x5B, - 0xD9, 0xC6, 0xB6, 0x2B, 0xA8, 0xD7, 0xD8, 0xD2, 0xB5, 0x8E, - 0x05, 0xB5, 0x16, 0x6A, 0xF7, 0xCB, 0xD2, 0xFE, 0xE0, 0xA7, - 0x3E, 0x1C, 0x3E, 0x84, 0xDC, 0x89, 0x33, 0xD7, 0x2F, 0x2A, - 0x40, 0x41, 0x18, 0xB8, 0x58, 0xB6, 0x54, 0xC6, 0xC9, 0xDF, - 0x24, 0x91, 0xCD, 0x62, 0xA0, 0x9D, 0x17, 0xCC, 0xA6, 0xCF, - 0xD9, 0x25, 0xA1, 0xBC, 0x63, 0x09, 0xFB, 0xD1, 0x65, 0x5C, - 0xFC, 0xB8, 0x3A, 0x3D, 0x50, 0xEC, 0x1A, 0x26, 0x37, 0xCB, - 0x9C, 0x29, 0x9E, 0x15, 0x06, 0xC9, 0x14, 0x45, 0x41, 0x5F, - 0x6C, 0x41, 0x46, 0xEA, 0xC6, 0xF8, 0x18, 0x01, 0x7D, 0xCD, - 0x30, 0xEE, 0x5D, 0xB5, 0xA0, 0x96, 0x19, 0x80, 0x96, 0xB1, - 0x03, 0x55, 0x86, 0x57, 0xBE, 0x19, 0x13, 0x46, 0x88, 0x00, - 0xCE, 0x5E, 0xD0, 0xBE, 0xEC, 0x13, 0x2B, 0x93, 0x3C, 0xE1, - 0xEC, 0xBD, 0x15, 0x6F, 0xA5, 0xF5, 0x20, 0x59, 0x3C, 0xDD, - 0xBD, 0xFD, 0xDF, 0x9D, 0x9F, 0x07, 0x73, 0x25, 0x93, 0x42, - 0x41, 0xCF, 0x4A, 0xE5, 0x8F, 0x04, 0xAC, 0x5F, 0x6A, 0x56, - 0x87, 0x49, 0xD5, 0x64, 0x00, 0x9D, 0xF4, 0xA5, 0x6B, 0xBE, - 0x8F, 0xC8, 0xE8, 0xBC, 0xC7, 0x1C, 0x99, 0xC0, 0x2F, 0xA1, - 0xDA, 0xDF, 0x6B, 0xE5, 0x62, 0x9D, 0xC9, 0x73, 0x5B, 0x2A, - 0x3E, 0xD7, 0x8A, 0xBE, 0x0A, 0x5F, 0x2B, 0x0B, 0x61, 0xEF, - 0x4A, 0x09, 0x15, 0x70, 0xE6, 0x5C, 0xA1, 0xB6, 0xDE, 0x54, - 0x71, 0x74, 0x55, 0x63, 0x77, 0x8F, 0xC9, 0xAF, 0x22, 0x9A, - 0xFE, 0x2C, 0x09, 0x62, 0x3E, 0xA1, 0xAA, 0x89, 0xB8, 0x6B, - 0x50, 0x84, 0x20, 0x66, 0x5D, 0x8F, 0x39, 0x7F, 0xC1, 0x2D, - 0xFA, 0x78, 0x8F, 0x8E, 0xD0, 0x39, 0x33, 0xD4, 0x9A, 0x40, - 0x56, 0xBC, 0x86, 0x22, 0x07, 0xEB, 0x22, 0xB8, 0x52, 0xC0, - 0x1A, 0xD2, 0x35, 0x1F, 0x56, 0x7E, 0xDA, 0x2B, 0xC1, 0x08, - 0xD2, 0x39, 0x28, 0x46, 0x63, 0x9A, 0xAD, 0x44, 0xB3, 0xEF, - 0x1C, 0x2A, 0xD6, 0x68, 0x67, 0xE4, 0x63, 0x73, 0x78, 0x29, - 0xA7, 0xA0, 0x70, 0x2E, 0xD9, 0xB4, 0x14, 0x4D, 0x04, 0xD3, - 0x2D, 0x8A, 0x70, 0x07, 0xAD, 0x8A, 0xC0, 0xA5, 0x1D, 0xE7, - 0x17, 0xD8, 0xBB, 0xAA, 0xB5, 0xF7, 0xC8, 0x8D, 0x29, 0x8E, - 0x49, 0x32, 0xA0, 0x40, 0x34, 0xBB, 0x2E, 0x10, 0x30, 0xDD, - 0xEA, 0x3E, 0xCC, 0xC1, 0xB9, 0xF2, 0x42, 0xCC, 0x4A, 0xF2, - 0xF4, 0x93, 0x2E, 0x3F, 0x0C, 0xE8, 0xE4, 0x96, 0x1F, 0x33, - 0x2D, 0x67, 0x4F, 0x8E, 0x1B, 0x01, 0xD6, 0xE2, 0xF2, 0xFD, - 0x5D, 0xCC, 0xFD, 0x18, 0x9C, 0xD6, 0x50, 0x1F, 0xE1, 0xC5, - 0x7C, 0xBE, 0x59, 0x95, 0x7D, 0x21, 0x25, 0x3E, 0xF3, 0xBC, - 0xCE, 0x31, 0x80, 0x79, 0x34, 0x0F, 0x86, 0x78, 0x18, 0xA6, - 0x36, 0x17, 0xD9, 0x70, 0xA7, 0x22, 0xA7, 0xE8, 0xA2, 0xBD, - 0x74, 0xB9, 0x8E, 0x34, 0xF0, 0xEC, 0xF7, 0x40, 0x22, 0x33, - 0xE8, 0x50, 0x43, 0x66, 0xF0, 0x25, 0x41, 0x20, 0xD9, 0x3F, - 0x8A, 0xC6, 0xAD, 0x69, 0xC6, 0x9C, 0xD9, 0xE0, 0x0D, 0xFF, - 0x93, 0x32, 0x5D, 0x57, 0x45, 0xCC, 0xA4, 0xF9, 0x32, 0xD4, - 0x5A, 0x49, 0x17, 0x1B, 0xFB, 0x2F, 0x91, 0xAA, 0x5B, 0xC5, - 0xC8, 0xC8, 0x2B, 0x20, 0x30, 0x1B, 0xB2, 0x01, 0xC3, 0xA7, - 0x8E, 0x6C, 0xB8, 0xF7, 0xB3, 0x95, 0x4A, 0x28, 0x82, 0xAA, - 0x0C, 0x4B, 0xDA, 0x26, 0x4A, 0x34, 0x7F, 0x17, 0x55, 0x4C, - 0x5D, 0x3C, 0x0B, 0x16, 0xA2, 0xEB, 0x33, 0xFB, 0x38, 0x63, - 0xF2, 0x15, 0x7D, 0xFA, 0x52, 0xA9, 0x58, 0xDD, 0x41, 0x58, - 0xA0, 0x13, 0xD2, 0x55, 0x22, 0xF9, 0xC2, 0xF8, 0x4E, 0x3F, - 0xAC, 0xDC, 0x11, 0x0A, 0xBB, 0x7C, 0xB1, 0x2B, 0xFB, 0x60, - 0xC5, 0x08, 0xB9, 0xB0, 0xED, 0xE8, 0xB9, 0x88, 0xBD, 0x07, - 0xDE, 0x53, 0xD0, 0x6B, 0xE5, 0x6E, 0xA0, 0x17, 0x8C, 0xCF, - 0x02, 0xF0, 0x64, 0xDE, 0xCE, 0x8C, 0x91, 0xED, 0xB4, 0x4F, - 0xB0, 0xEE, 0x12, 0x26, 0xC6, 0x55, 0xA0, 0x4D, 0xCC, 0xF3, - 0x1A, 0x86, 0x5A, 0x01, 0x53, 0x01, 0xAA, 0xED, 0x6D, 0x11, - 0xCD, 0x8A, 0x4A, 0xCA, 0x85, 0x35, 0x35, 0xFA, 0x22, 0x55, - 0xF3, 0xB8, 0xFA, 0x43, 0xD6, 0x9E, 0xB5, 0x0D, 0xD3, 0x85, - 0x59, 0xC9, 0xAF, 0xCD, 0xAB, 0xFA, 0xB6, 0x65, 0x20, 0xCC, - 0x11, 0xF1, 0xDE, 0x87, 0x6F, 0x58, 0xA1, 0x41, 0xF2, 0x80, - 0x75, 0xEA, 0x26, 0x72, 0x8C, 0xE9, 0x17, 0x1C, 0x2B, 0x4D, - 0xA4, 0x9C, 0xAA, 0x32, 0xAA, 0x2C, 0x84, 0xBA, 0x87, 0xAA, - 0x81, 0x66, 0x56, 0x76, 0x0F, 0x1C, 0x58, 0xFE, 0xD1, 0x7F, - 0x33, 0x59, 0xF1, 0xF0, 0x56, 0x50, 0x00, 0x4F, 0x96, 0xF7, - 0x1C, 0x11, 0x7C, 0x36, 0xD8, 0xAD, 0x3E, 0x82, 0x15, 0x68, - 0x40, 0x83, 0xFE, 0x62, 0x94, 0xD5, 0x2A, 0x43, 0x88, 0xD8, - 0x12, 0xE2, 0x37, 0x8A, 0x3E, 0x9E, 0x24, 0x8B, 0x70, 0x3C, - 0xBD, 0x97, 0x0B, 0x59, 0xAC, 0x4B, 0x88, 0x36, 0x2D, 0x2F, - 0xE9, 0x49, 0x14, 0xC0, 0x28, 0x7F, 0x0D, 0xE8, 0x93, 0x76, - 0x22, 0xF3, 0x08, 0x17, 0x34, 0x91, 0x39, 0xA6, 0x84, 0xCA, - 0xF1, 0xD2, 0x8A, 0x9D, 0xF1, 0xD4, 0xA4, 0x85, 0xA6, 0x1E, - 0xFB, 0x6B, 0x75, 0x07, 0x80, 0x84, 0x32, 0xF5, 0x51, 0xD6, - 0x42, 0xA8, 0x69, 0x96, 0xC3, 0xBD, 0xEF, 0x2F, 0xA4, 0x23, - 0x58, 0x07, 0xBC, 0xDE, 0x45, 0xD4, 0x1E, 0x67, 0xF1, 0x00, - 0x65, 0xB5, 0x03, 0xF3, 0x83, 0x9D, 0xE8, 0xDE, 0x63, 0x42, - 0x2B, 0xB6, 0xED, 0x7F, 0x63, 0xF6, 0xCF, 0x53, 0x1B, 0xBD, - 0x9D, 0x6C, 0x26, 0xBC, 0xC2, 0xC3, 0xAF, 0x86, 0x06, 0x5F, - 0x49, 0xBF, 0x7E, 0x76, 0xF5, 0x6C, 0x5B, 0x41, 0xF7, 0xAF, - 0x02, 0x1F, 0x35, 0x43, 0x0D, 0x64, 0x65, 0xFE, 0xD7, 0x9A, - 0x3F, 0x21, 0xD5, 0x74, 0x6E, 0x8A, 0xA8, 0xAF, 0x3B, 0xCE, - 0x85, 0xBB, 0xF7, 0x7B, 0xCA, 0xF7, 0x9D, 0x02, 0x52, 0x55, - 0xE9, 0x3E, 0x4A, 0x4B, 0x62, 0x85, 0x35, 0xFA, 0xBD, 0xEB, - 0x92, 0x25, 0x24, 0x01, 0xFF, 0xEE, 0xFB, 0x94, 0xF6, 0xE6, - 0x9F, 0xE3, 0x3D, 0x93, 0xCF, 0x69, 0xEB, 0x3D, 0x8F, 0x1F, - 0xBE, 0xAE, 0x85, 0x6F, 0x8F, 0x0B, 0x22, 0x57, 0x00, 0x3D, - 0x8E, 0xF4, 0x6B, 0x4D, 0x82, 0x76, 0x91, 0x25, 0x4B, 0x2C, - 0xF1, 0xBC, 0x64, 0x96, 0x54, 0x35, 0xFD, 0xBD, 0xFC, 0x71, - 0xF7, 0x48, 0x40, 0xEB, 0x4C, 0x1C, 0xC4, 0xAB, 0x4F, 0xC9, - 0xC7, 0xB0, 0x8C, 0xBF, 0x27, 0xE2, 0x18, 0xCA, 0x78, 0xAA, - 0xA0, 0x04, 0xAB, 0x6B, 0x6D, 0xBC, 0x89, 0xCB, 0x71, 0xA7, - 0xF8, 0x81, 0x0D, 0x4F, 0x2A, 0x9A, 0x37, 0x60, 0xA0, 0x6A, - 0x14, 0xE7, 0x30, 0x2E, 0x72, 0xF9, 0xE2, 0x39, 0x27, 0xD9, - 0xC6, 0xB2, 0x9E, 0xBC, 0x3D, 0xD6, 0x2D, 0xE4, 0xCD, 0xC2, - 0x40, 0x15, 0xC5, 0x7B, 0x8A, 0x06, 0x42, 0x46, 0xF2, 0x45, - 0x14, 0x83, 0x82, 0xAB, 0x30, 0x6C, 0x73, 0x92, 0x55, 0x51, - 0xE7, 0x8B, 0x3C, 0xD1, 0x2C, 0x8A, 0xC0, 0x16, 0x79, 0xC9, - 0xFD, 0x7C, 0x78, 0x1E, 0xE9, 0xDF, 0xF4, 0x08, 0xEF, 0x38, - 0xEC, 0xCB, 0x81, 0xF1, 0x87, 0x53, 0x8A, 0x0B, 0xF3, 0x56, - 0x0C, 0xBC, 0xEE, 0x03, 0xAE, 0xBC, 0xF8, 0x43, 0x3E, 0xA2, - 0xEA, 0x84, 0x37, 0x72, 0x8A, 0x80, 0x8D, 0x61, 0x1C, 0x79, - 0x3E, 0x4A, 0x5A, 0xC2, 0x73, 0xA0, 0x95, 0xDC, 0x46, 0x2B, - 0x5E, 0x4B, 0x89, 0xE3, 0x9F, 0xD7, 0x14, 0x61, 0x8B, 0x59, - 0xD1, 0x71, 0xB0, 0x04, 0xAA, 0x4B, 0x2A, 0xCA, 0xEF, 0x8D, - 0x3B, 0x4B, 0x52, 0x8F, 0x0B, 0x76, 0xB8, 0x38, 0xF8, 0xDD, - 0xD2, 0xE6, 0x46, 0x53, 0x1C, 0xD5, 0xC8, 0x1E, 0x85, 0x54, - 0x67, 0xC0, 0x77, 0x7E, 0x28, 0x2F, 0x91, 0xC5, 0xE5, 0x28, - 0x54, 0x37, 0xF6, 0x77, 0xEC, 0x6C, 0x36, 0x1D, 0x91, 0xA9, - 0x45, 0xCC, 0x85, 0x61, 0xAB, 0x14, 0xBE, 0x81, 0x6C, 0xFF, - 0x35, 0x8C, 0x13, 0x61, 0xE7, 0x66, 0x83, 0xFF, 0x67, 0x6C, - 0x80, 0x59, 0xD5, 0x6D, 0xAB, 0x5B, 0x81, 0x76, 0x39, 0x1B, - 0xBB, 0xD2, 0xFF, 0x1B, 0x7B, 0x66, 0xD6, 0x42, 0xD0, 0x86, - 0x62, 0x4A, 0xA1, 0x4F, 0x00, 0x41, 0x7E, 0x9C, 0xE5, 0xD6, - 0x82, 0x31, 0xA7, 0x34, 0x16, 0x20, 0x62, 0xFA, 0x1F, 0x6B, - 0x21, 0xBE, 0x62, 0x19, 0xE9, 0x56, 0x7A, 0x4C, 0xF0, 0x7B, - 0xB4, 0x2E, 0x4A, 0xA7, 0x20, 0xC3, 0x5F, 0x7F, 0x5A, 0xA2, - 0xAF, 0xF5, 0xC5, 0xFD, 0x1A, 0x7C, 0xB6, 0x06, 0xCA, 0xE3, - 0x74, 0x72, 0x4E, 0x77, 0xC9, 0xDD, 0x3B, 0x44, 0x16, 0x8C, - 0x45, 0x46, 0xC5, 0xE3, 0x81, 0x1E, 0x3C, 0x4D, 0xAC, 0x1A, - 0x7F, 0xAA, 0x6D, 0xFD, 0xE1, 0x45, 0x59, 0x11, 0x44, 0x48, - 0xB5, 0x09, 0xEF, 0x7E, 0xF2, 0x75, 0x0C, 0xBF, 0xC7, 0x17, - 0xB4, 0x9E, 0x10, 0xC0, 0x11, 0xDD, 0xB2, 0x59, 0xCF, 0x25, - 0x3B, 0xA8, 0x97, 0x56, 0x08, 0xE0, 0x65, 0x27, 0xC5, 0x29, - 0x34, 0xBD, 0x38, 0xB1, 0x39, 0xAA, 0x27, 0xFC, 0x96, 0xCB, - 0x9A, 0x2B, 0x92, 0x74, 0xDF, 0x0A, 0x52, 0xE4, 0x93, 0xA8, - 0x18, 0x15, 0x2C, 0x8C, 0x61, 0xD3, 0xBC, 0xD0, 0x9E, 0x9D, - 0x40, 0x1C, 0x69, 0x95, 0x0D, 0x52, 0x76, 0x3F, 0xD7, 0xD7, - 0xC1, 0x1C, 0x34, 0xE7, 0xD4, 0xD4, 0x17, 0x2D, 0xF0, 0x6A, - 0x1C, 0xE2, 0x53, 0x18, 0x60, 0xC6, 0xA1, 0xCD, 0x4F, 0xAA, - 0x16, 0xA0, 0xC3, 0x3B, 0xCE, 0x4D, 0x73, 0x0B, 0x63, 0x02, - 0x1C, 0xEE, 0x18, 0xBF, 0xF9, 0x33, 0x24, 0xD3, 0x02, 0x34, - 0xCC, 0xB9, 0xD7, 0xC2, 0x00, 0x7F, 0xB4, 0x08, 0x4B, 0xFC, - 0x1D, 0xDF, 0x42, 0x8C, 0x75, 0xEE, 0x13, 0x90, 0x37, 0x14, - 0x0D, 0xD2, 0xE0, 0x50, 0x90, 0x6A, 0xB9, 0xEF, 0x7F, 0x70, - 0x38, 0x2E, 0xCD, 0x39, 0x2E, 0x09, 0x51, 0xDF, 0x58, 0xBE, - 0x8E, 0x82, 0x91, 0xEB, 0xBC, 0xB4, 0x6B, 0x12, 0x40, 0x4E, - 0x44, 0xB8, 0x08, 0x97, 0x57, 0xF0, 0xFE, 0x61, 0xBD, 0x77, - 0xED, 0x46, 0xDA, 0xB7, 0xA4, 0xF5, 0x4F, 0xB2, 0xA6, 0xF1, - 0x47, 0x2D, 0x11, 0x26, 0x74, 0x55, 0x81, 0xFF, 0xFB, 0xEA, - 0x00, 0x03, 0x96, 0xD8, 0xE6, 0x6B, 0xEA, 0x3F, 0x0B, 0x0C, - 0xC0, 0xE4, 0x0A, 0x3D, 0x21, 0x3C, 0x99, 0x51, 0x91, 0x11, - 0xF0, 0x91, 0x68, 0xEE, 0xEE, 0xCD, 0x71, 0x42, 0xAD, 0xBA, - 0x34, 0x68, 0x9F, 0x67, 0xB1, 0xEE, 0x1C, 0x70, 0x7A, 0xFC, - 0x1E, 0x86, 0xF8, 0x96, 0x6C, 0x13, 0xD6, 0x36, 0x57, 0x5F, - 0x11, 0x2E, 0x1B, 0x97, 0xAB, 0x8B, 0x65, 0x3E, 0x8E, 0x91, - 0x69, 0x1C, 0x76, 0xAD, 0xB5, 0x8C, 0xE6, 0x02, 0x93, 0x16, - 0xA4, 0xF5, 0x14, 0x86, 0xB5, 0x16, 0x07, 0xF5, 0x0C, 0x01, - 0xE9, 0xDC, 0xEA, 0x86, 0x58, 0x98, 0xBA, 0x2C, 0x04, 0x0A, - 0x16, 0x8A, 0xF3, 0x10, 0x25, 0x48, 0x51, 0x21, 0x77, 0x69, - 0xF1, 0x22, 0xC3, 0xF4, 0x1D, 0xD5, 0x6D, 0x59, 0x1B, 0x44, - 0x88, 0xFC, 0xE5, 0x4B, 0xE1, 0xD6, 0xF4, 0x46, 0x4C, 0x9D, - 0x45, 0x93, 0xE1, 0xB5, 0x26, 0xDF, 0x48, 0x90, 0x13, 0xA6, - 0x65, 0x7E, 0x18, 0x6A, 0x79, 0x19, 0x81, 0x10, 0x08, 0x80, - 0xA4, 0x99, 0xD3, 0x98, 0x3C, 0x9E, 0x91, 0x31, 0xE9, 0x71, - 0xA0, 0x6A, 0xF9, 0x2F, 0x61, 0xA5, 0x72, 0x13, 0x6C, 0x4C, - 0xD2, 0xAF, 0x40, 0x8B, 0x0D, 0x3D, 0xE4, 0x24, 0x7B, 0x30, - 0x9C, 0xD0, 0x62, 0x42, 0x67, 0x54, 0xC6, 0x34, 0xF2, 0x55, - 0x70, 0x95, 0xAE, 0x16, 0x9F, 0xCC, 0x6F, 0xEA, 0x0B, 0x40, - 0x38, 0xAE, 0x74, 0x89, 0xCB, 0x64, 0x79, 0xF7, 0x08, 0x68, - 0x2C, 0x1E, 0xEE, 0x28, 0xEA, 0x77, 0xA2, 0xA3, 0x8E, 0xF4, - 0xEE, 0xFE, 0x62, 0x25, 0x98, 0xB1, 0xDE, 0x4B, 0x3A, 0x62, - 0xD9, 0x12, 0xD6, 0x09, 0x32, 0x6C, 0x80, 0x27, 0x21, 0x0A, - 0xFE, 0x4D, 0xBF, 0x29, 0x90, 0xCD, 0x6C, 0xE0, 0xAF, 0x06, - 0xB3, 0xC2, 0xDF, 0xB8, 0x50, 0x59, 0xD8, 0x0A, 0xB5, 0x98, - 0xC1, 0xA8, 0x80, 0xD7, 0x61, 0xFC, 0x59, 0xDB, 0xB1, 0x2A, - 0xA5, 0xD7, 0xFA, 0x9E, 0x93, 0x60, 0xD4, 0xB0, 0x6B, 0x44, - 0xB3, 0xC3, 0x3F, 0x9B, 0xEA, 0xD4, 0x8C, 0x08, 0x4B, 0x09, - 0x97, 0xC6, 0x2B, 0xC0, 0x8A, 0x92, 0x35, 0xCA, 0x6F, 0x93, - 0xD6, 0x71, 0x1E, 0xAB, 0x0F, 0x65, 0x42, 0xC2, 0x97, 0x77, - 0x10, 0x6E, 0xD4, 0xEE, 0x2A, 0xDF, 0x54, 0x2A, 0x5F, 0xB4, - 0xD4, 0x72, 0x18, 0x90, 0x42, 0x09, 0xAA, 0xC3, 0x31, 0x89 +#ifndef WOLFSSL_DILITHIUM_NO_SIGN +static const unsigned char bench_dilithium_level2_key[] = { + 0xea, 0x05, 0x24, 0x0d, 0x80, 0x72, 0x25, 0x55, 0xf4, 0x5b, + 0xc2, 0x13, 0x8b, 0x87, 0x5d, 0x31, 0x99, 0x2f, 0x1d, 0xa9, + 0x41, 0x09, 0x05, 0x76, 0xa7, 0xb7, 0x5e, 0x8c, 0x44, 0xe2, + 0x64, 0x79, 0xd8, 0x79, 0x4c, 0xee, 0x92, 0x2b, 0x37, 0xab, + 0xb1, 0x16, 0x65, 0x72, 0xc3, 0x49, 0xc2, 0xec, 0xfd, 0x9a, + 0xe6, 0x2d, 0x1e, 0x5b, 0xe3, 0x04, 0x96, 0x16, 0xad, 0x97, + 0x5d, 0xac, 0xf2, 0xcc, 0x62, 0x2e, 0x34, 0x5d, 0x67, 0x19, + 0x47, 0xee, 0x0f, 0x8b, 0x97, 0x60, 0xb4, 0x0b, 0xeb, 0x6a, + 0x7a, 0x75, 0x14, 0x27, 0x00, 0x39, 0xd6, 0x60, 0xce, 0x39, + 0x6e, 0x69, 0x46, 0xe1, 0x0d, 0xf9, 0xa6, 0xfa, 0x8c, 0xcf, + 0x65, 0x50, 0x59, 0x1d, 0xb0, 0x26, 0xc2, 0xe2, 0xf1, 0xb9, + 0xcd, 0x09, 0x60, 0xcc, 0xbb, 0x57, 0xd6, 0xac, 0xcc, 0xf9, + 0x58, 0x73, 0xa8, 0x81, 0x61, 0x2f, 0xd2, 0xa4, 0x5b, 0x98, + 0x0d, 0x12, 0x88, 0x51, 0x63, 0x38, 0x6e, 0xa2, 0x46, 0x64, + 0x52, 0xc0, 0x71, 0xc1, 0x42, 0x68, 0xd8, 0x42, 0x32, 0x5c, + 0xb4, 0x44, 0x08, 0x95, 0x48, 0xa2, 0x46, 0x6c, 0x0b, 0x10, + 0x09, 0xc8, 0x24, 0x4d, 0x18, 0x37, 0x4c, 0x4c, 0x82, 0x05, + 0x02, 0x22, 0x10, 0x4a, 0x86, 0x30, 0x03, 0x03, 0x11, 0x44, + 0x22, 0x62, 0x01, 0xa9, 0x51, 0x13, 0x02, 0x2c, 0x19, 0x85, + 0x65, 0x51, 0x14, 0x01, 0x9c, 0xb2, 0x81, 0x0a, 0x49, 0x52, + 0xa2, 0xb2, 0x4c, 0x98, 0x34, 0x01, 0x0a, 0x07, 0x06, 0x58, + 0xb2, 0x69, 0x51, 0x24, 0x2d, 0x59, 0x12, 0x52, 0xe0, 0xb4, + 0x04, 0x14, 0x40, 0x29, 0xa2, 0xb0, 0x31, 0x54, 0xc0, 0x40, + 0x63, 0x00, 0x69, 0x18, 0x47, 0x85, 0xc8, 0x30, 0x81, 0x0b, + 0x15, 0x0a, 0xd8, 0xa0, 0x0c, 0x5c, 0x20, 0x4a, 0x11, 0x38, + 0x64, 0x04, 0x94, 0x84, 0xd3, 0x24, 0x72, 0x58, 0x38, 0x28, + 0x18, 0x37, 0x6d, 0x94, 0xc0, 0x4d, 0xa0, 0xa6, 0x0c, 0x9a, + 0x82, 0x31, 0xc2, 0x40, 0x48, 0xda, 0x46, 0x85, 0x03, 0x00, + 0x05, 0xd8, 0x02, 0x4d, 0x0b, 0x85, 0x40, 0xe2, 0x32, 0x86, + 0x4c, 0xa0, 0x65, 0x8a, 0x36, 0x65, 0x42, 0x18, 0x6e, 0x60, + 0x36, 0x0d, 0x40, 0xc0, 0x01, 0x5a, 0x44, 0x42, 0xc4, 0xa4, + 0x0d, 0xd4, 0x88, 0x8d, 0x88, 0x22, 0x52, 0x00, 0xc0, 0x0c, + 0x5b, 0x36, 0x90, 0x09, 0x20, 0x22, 0x08, 0x03, 0x12, 0x90, + 0x12, 0x42, 0x04, 0x20, 0x29, 0x8c, 0x48, 0x6d, 0x20, 0x32, + 0x08, 0x94, 0x88, 0x6c, 0x10, 0x87, 0x21, 0xc1, 0x44, 0x02, + 0x52, 0x40, 0x12, 0xdb, 0xc8, 0x24, 0x14, 0x09, 0x2c, 0x93, + 0x40, 0x09, 0x64, 0xc8, 0x4c, 0x08, 0x48, 0x70, 0xa1, 0x10, + 0x81, 0x4a, 0x80, 0x8c, 0x20, 0x03, 0x31, 0x18, 0xb3, 0x80, + 0xd3, 0x82, 0x25, 0x4c, 0x94, 0x8c, 0x1c, 0x93, 0x89, 0x1a, + 0x91, 0x51, 0xd1, 0xb6, 0x68, 0x43, 0x14, 0x25, 0x84, 0x48, + 0x61, 0x82, 0x40, 0x24, 0xdb, 0x22, 0x4d, 0x63, 0x16, 0x66, + 0x62, 0x90, 0x50, 0xa1, 0x18, 0x86, 0x49, 0x28, 0x25, 0xa0, + 0x10, 0x68, 0x8c, 0x04, 0x00, 0x08, 0x32, 0x4e, 0x22, 0x43, + 0x31, 0x42, 0x96, 0x28, 0x11, 0x23, 0x89, 0xd2, 0xc4, 0x6d, + 0x11, 0x82, 0x8d, 0x8a, 0xa8, 0x90, 0xd2, 0x06, 0x29, 0x80, + 0x82, 0x89, 0x00, 0xa8, 0x41, 0x00, 0x13, 0x6a, 0x12, 0xa8, + 0x04, 0x83, 0xc2, 0x51, 0x13, 0x09, 0x08, 0x62, 0xb4, 0x8d, + 0x94, 0xc2, 0x44, 0x5a, 0xb4, 0x08, 0x0a, 0x10, 0x48, 0xa1, + 0x28, 0x20, 0x1b, 0xb7, 0x64, 0x60, 0x24, 0x25, 0x48, 0xc0, + 0x00, 0x0a, 0x10, 0x09, 0x64, 0xb8, 0x88, 0xcb, 0x44, 0x64, + 0x54, 0x90, 0x05, 0xd2, 0xb8, 0x21, 0x49, 0x28, 0x28, 0x49, + 0x42, 0x0d, 0x63, 0xa0, 0x65, 0xcb, 0x90, 0x30, 0x51, 0x82, + 0x8d, 0x5c, 0xc6, 0x0c, 0x51, 0x06, 0x6a, 0x1a, 0x27, 0x22, + 0x01, 0xa8, 0x24, 0x61, 0xb2, 0x84, 0x23, 0x40, 0x86, 0xa3, + 0xb4, 0x48, 0x19, 0x28, 0x0c, 0x14, 0x06, 0x2e, 0xe2, 0x02, + 0x0d, 0xc4, 0x90, 0x09, 0x08, 0x06, 0x66, 0x9b, 0xc8, 0x10, + 0x5c, 0x46, 0x21, 0xca, 0xa8, 0x30, 0x83, 0x20, 0x89, 0x03, + 0x83, 0x6c, 0xa1, 0x46, 0x8c, 0x90, 0x14, 0x4c, 0x99, 0x02, + 0x81, 0x53, 0x02, 0x10, 0x8b, 0x48, 0x91, 0xe4, 0x40, 0x4a, + 0x22, 0xb1, 0x88, 0xc1, 0x06, 0x0e, 0xc3, 0xa8, 0x08, 0xc8, + 0x46, 0x92, 0x03, 0xb5, 0x4c, 0x23, 0x03, 0x0c, 0xa4, 0x06, + 0x2e, 0xdc, 0x92, 0x81, 0x0c, 0x45, 0x22, 0x40, 0x34, 0x91, + 0x90, 0x96, 0x48, 0x81, 0x82, 0x31, 0xcb, 0x16, 0x72, 0x49, + 0xc8, 0x29, 0x44, 0x86, 0x90, 0x60, 0x22, 0x4e, 0x42, 0x42, + 0x09, 0x4b, 0x82, 0x20, 0x0a, 0xb2, 0x64, 0x20, 0x86, 0x70, + 0x1a, 0xc0, 0x00, 0x1c, 0x41, 0x49, 0x89, 0x84, 0x05, 0x0c, + 0x36, 0x49, 0x19, 0x99, 0x6d, 0x00, 0x08, 0x50, 0x23, 0x96, + 0x6c, 0xe0, 0x44, 0x08, 0x98, 0x24, 0x2c, 0x0a, 0x23, 0x20, + 0x12, 0x04, 0x31, 0xc9, 0x06, 0x32, 0x14, 0x01, 0x41, 0x08, + 0x37, 0x08, 0x58, 0x00, 0x0c, 0x19, 0x04, 0x29, 0x90, 0x18, + 0x05, 0xe1, 0x88, 0x44, 0xc2, 0x20, 0x6c, 0xd1, 0x46, 0x64, + 0xd9, 0x26, 0x62, 0x09, 0x88, 0x68, 0x02, 0x29, 0x29, 0xe1, + 0x18, 0x65, 0x98, 0x04, 0x24, 0xe4, 0x34, 0x0c, 0x12, 0x85, + 0x2d, 0x20, 0x14, 0x06, 0x24, 0x15, 0x82, 0x89, 0x08, 0x91, + 0x60, 0x84, 0x28, 0x24, 0x34, 0x41, 0x1b, 0x49, 0x22, 0xd3, + 0x96, 0x64, 0x1b, 0x86, 0x4c, 0x0c, 0xb9, 0x20, 0x20, 0x39, + 0x04, 0x04, 0x34, 0x6d, 0xc1, 0x28, 0x32, 0x08, 0x14, 0x44, + 0x81, 0x18, 0x2e, 0xda, 0x38, 0x41, 0x63, 0x18, 0x26, 0xd8, + 0x48, 0x26, 0x12, 0x20, 0x21, 0x09, 0xc5, 0x25, 0x92, 0x42, + 0x0c, 0x88, 0x04, 0x64, 0x11, 0x43, 0x8a, 0x19, 0x92, 0x60, + 0x5c, 0xc6, 0x31, 0xa1, 0x24, 0x6a, 0xd8, 0xb6, 0x49, 0x1b, + 0x81, 0x90, 0xe2, 0x32, 0x4e, 0x62, 0x44, 0x21, 0x80, 0xb8, + 0x10, 0x4b, 0x90, 0x49, 0x5c, 0x06, 0x09, 0x48, 0x20, 0x49, + 0xa2, 0x92, 0x71, 0x5c, 0x48, 0x02, 0xc8, 0x08, 0x81, 0xa4, + 0x32, 0x66, 0xc9, 0x30, 0x11, 0xca, 0x92, 0x91, 0xc0, 0x00, + 0x41, 0x44, 0x98, 0x4d, 0x98, 0x12, 0x4e, 0x92, 0x46, 0x8e, + 0x49, 0xb8, 0x64, 0xdc, 0x18, 0x50, 0x51, 0xb4, 0x48, 0x08, + 0x47, 0x24, 0x08, 0x46, 0x32, 0x1b, 0x23, 0x00, 0x09, 0xb8, + 0x04, 0x0a, 0x44, 0x0c, 0x0b, 0xc7, 0x8d, 0x19, 0xa4, 0x09, + 0x11, 0x30, 0x41, 0xe3, 0x24, 0x45, 0x89, 0x1f, 0x65, 0x54, + 0xf6, 0x38, 0x04, 0x37, 0xcc, 0x89, 0xc3, 0xc5, 0xdc, 0x43, + 0xd9, 0x13, 0x56, 0x06, 0x05, 0x50, 0x29, 0x4e, 0x0f, 0xa5, + 0x5c, 0x5d, 0xd7, 0x82, 0xa1, 0x63, 0x59, 0x0d, 0x3e, 0x5b, + 0x00, 0xe6, 0x0e, 0xd8, 0x1c, 0xc7, 0xaf, 0xc0, 0x48, 0xb6, + 0x07, 0x5c, 0x65, 0x00, 0x89, 0xb3, 0x09, 0xbc, 0x4a, 0xaa, + 0xa6, 0x72, 0xbe, 0x6b, 0x9a, 0xb3, 0x5b, 0x27, 0x82, 0x65, + 0x9b, 0xc9, 0x6f, 0x19, 0x88, 0x94, 0x0b, 0x37, 0x44, 0x2f, + 0xe3, 0x9a, 0x02, 0xda, 0xff, 0x11, 0xb0, 0x48, 0x89, 0x70, + 0x8c, 0x84, 0xc2, 0xc0, 0x31, 0x4a, 0xad, 0x70, 0xe1, 0xa7, + 0x15, 0xfd, 0xb2, 0x6d, 0x93, 0xda, 0x17, 0x68, 0xc4, 0xe3, + 0xfd, 0x2c, 0x08, 0x15, 0xb9, 0xa4, 0xc5, 0x1b, 0x97, 0xc9, + 0xa3, 0xaf, 0x0d, 0x21, 0x06, 0x3d, 0xf1, 0x05, 0xd4, 0x35, + 0x80, 0x2e, 0x23, 0x99, 0xbd, 0x3a, 0x1a, 0x6c, 0xad, 0xbf, + 0x56, 0xb5, 0xd3, 0x95, 0x1b, 0x30, 0x4d, 0x56, 0xc1, 0x77, + 0xe6, 0xd6, 0xab, 0x94, 0x46, 0x68, 0xd7, 0xb8, 0xe4, 0x9d, + 0xb2, 0x8d, 0xc4, 0xd1, 0xc8, 0x92, 0xbe, 0x5d, 0x1f, 0x58, + 0x55, 0x7f, 0x11, 0x55, 0xc5, 0x2e, 0xc3, 0x9e, 0x2a, 0x29, + 0x51, 0xe8, 0x75, 0x49, 0xa7, 0xa3, 0xda, 0x0b, 0xcf, 0xf8, + 0x3f, 0x78, 0xac, 0x4c, 0x4e, 0x78, 0x6f, 0x0e, 0x67, 0xad, + 0x94, 0x59, 0x20, 0x5e, 0x37, 0x18, 0xb9, 0x09, 0x87, 0xdb, + 0xdd, 0xf0, 0xc2, 0x4d, 0x03, 0xcc, 0x98, 0x22, 0x4b, 0xe5, + 0x7d, 0x8e, 0x74, 0x7e, 0xa9, 0x1b, 0xeb, 0x7a, 0xae, 0xaf, + 0x2e, 0x7c, 0x3c, 0xc0, 0x1a, 0x30, 0x40, 0x0d, 0x79, 0x86, + 0x53, 0xcc, 0x0b, 0x2b, 0xbe, 0xa5, 0x72, 0x3b, 0xbb, 0x53, + 0x9e, 0xd5, 0xc2, 0x23, 0x1d, 0x35, 0xcd, 0x22, 0x12, 0xed, + 0x9a, 0xee, 0xc8, 0xf9, 0x05, 0x27, 0xdb, 0x46, 0x56, 0xcc, + 0x24, 0x4d, 0xee, 0xaf, 0xab, 0xa9, 0x78, 0x75, 0x75, 0xb9, + 0xd1, 0xfd, 0x39, 0x3a, 0xb2, 0xa2, 0xeb, 0x87, 0x76, 0xb2, + 0x19, 0x47, 0x88, 0xab, 0x42, 0x85, 0x4b, 0xd9, 0x76, 0x22, + 0x68, 0x4b, 0xc9, 0x88, 0x38, 0x28, 0x0a, 0x34, 0x5d, 0x12, + 0x4f, 0xf5, 0x43, 0x64, 0x44, 0x8c, 0x3c, 0xc2, 0x99, 0x91, + 0x4e, 0xfd, 0xfd, 0x9c, 0x73, 0xbf, 0x85, 0xf9, 0x9f, 0xe1, + 0x53, 0x19, 0xc8, 0x19, 0xcb, 0x7c, 0xdb, 0x9a, 0x3a, 0x2c, + 0x34, 0x55, 0x8c, 0x64, 0x6f, 0xc5, 0xb7, 0x93, 0x53, 0xb4, + 0x97, 0x7e, 0xc2, 0xf8, 0x7e, 0x8d, 0x44, 0x10, 0xca, 0x49, + 0xf5, 0x5c, 0xe8, 0xce, 0xc4, 0xcc, 0x42, 0xf0, 0x85, 0xf1, + 0xf2, 0x10, 0xa7, 0x0b, 0x37, 0x6a, 0x8e, 0x50, 0x96, 0x96, + 0x9d, 0xd9, 0x8f, 0x54, 0x45, 0x56, 0xf8, 0x64, 0x88, 0xab, + 0x51, 0x4f, 0x9f, 0x61, 0xd9, 0x12, 0x87, 0xac, 0x1d, 0xc1, + 0x23, 0xea, 0xb3, 0x5d, 0xa4, 0x6d, 0xfa, 0x58, 0x92, 0x8f, + 0x77, 0x78, 0x61, 0xe5, 0xe4, 0x33, 0xdb, 0x10, 0x2d, 0xdd, + 0xb6, 0xd7, 0xb4, 0xd0, 0x8d, 0xd1, 0xa8, 0x0b, 0x94, 0xdf, + 0xcf, 0xd7, 0xac, 0xdf, 0x47, 0x0b, 0x38, 0xe0, 0xa5, 0xf8, + 0xc3, 0xd2, 0xc3, 0xfb, 0x0f, 0x98, 0x00, 0x2b, 0x17, 0x3c, + 0x44, 0x70, 0x36, 0x47, 0x27, 0x89, 0x41, 0xcb, 0x87, 0x5a, + 0xa4, 0x2c, 0x57, 0x6d, 0x8c, 0xcb, 0xc0, 0x7d, 0x6b, 0xf5, + 0xa1, 0x17, 0x39, 0x4a, 0xb5, 0xac, 0xc6, 0x41, 0x90, 0x66, + 0x85, 0xc4, 0x4b, 0x18, 0xc6, 0xe6, 0x09, 0x6d, 0x6e, 0xbb, + 0x7f, 0x72, 0x96, 0xd3, 0x21, 0x5a, 0x96, 0xaf, 0x9e, 0xb6, + 0x0b, 0x3f, 0xe8, 0x83, 0xe5, 0x53, 0x11, 0x81, 0xc6, 0xab, + 0x40, 0xa9, 0x09, 0xb6, 0x74, 0x5e, 0xe1, 0xc3, 0x82, 0x1e, + 0xda, 0x2f, 0x24, 0xe0, 0x94, 0x8f, 0x07, 0xb7, 0x9b, 0xc6, + 0x50, 0xef, 0x3a, 0x79, 0x89, 0x4d, 0x6f, 0x16, 0x33, 0x04, + 0x24, 0x7e, 0x4a, 0xab, 0x5d, 0x03, 0x29, 0xad, 0xba, 0xa3, + 0x6c, 0xe2, 0x05, 0xab, 0x4d, 0x69, 0xb6, 0x61, 0x39, 0x9d, + 0xc3, 0x53, 0x11, 0xc0, 0xe3, 0xaa, 0x2e, 0xdc, 0x74, 0x09, + 0xbd, 0x19, 0xb5, 0xbb, 0x51, 0x1e, 0x77, 0x3e, 0xce, 0x64, + 0x13, 0xeb, 0x74, 0x03, 0xb7, 0x49, 0x99, 0xb0, 0x71, 0x99, + 0xe6, 0x17, 0x3c, 0x80, 0xe6, 0xb5, 0x51, 0xe9, 0xb3, 0xe4, + 0x2b, 0xaa, 0x52, 0x15, 0x99, 0x4e, 0x46, 0x6d, 0x67, 0x8e, + 0x79, 0xc4, 0x3c, 0xa6, 0xdc, 0x8f, 0xed, 0x87, 0xb9, 0x68, + 0x6d, 0xdc, 0x19, 0xa1, 0x52, 0x37, 0x06, 0x76, 0xad, 0xe9, + 0x61, 0x5c, 0x82, 0x16, 0x81, 0xaf, 0x3a, 0x89, 0xbf, 0x72, + 0xb0, 0xc7, 0x88, 0x3c, 0x58, 0xfe, 0xe4, 0xa5, 0x41, 0x50, + 0xfc, 0x8a, 0x15, 0xb0, 0x78, 0xd4, 0x77, 0x06, 0x4b, 0xc4, + 0x21, 0x7f, 0xaa, 0x2b, 0x88, 0x7f, 0x8c, 0x3b, 0x9b, 0xbb, + 0x2e, 0x41, 0xcf, 0x9b, 0x06, 0xd3, 0x4d, 0xcf, 0xb2, 0x9c, + 0x91, 0x46, 0x35, 0x3a, 0x5a, 0x0b, 0xe4, 0xac, 0x96, 0x7c, + 0xe0, 0xd4, 0x34, 0xe5, 0xab, 0xae, 0xa7, 0x67, 0xbf, 0x4d, + 0xab, 0x48, 0xfd, 0xcb, 0x3f, 0x5c, 0xde, 0x3f, 0x83, 0xcc, + 0x52, 0x0f, 0xdd, 0x7f, 0x20, 0x25, 0xed, 0xee, 0xd0, 0x14, + 0x38, 0xf7, 0x33, 0x4c, 0x3c, 0x5e, 0x23, 0x80, 0xa3, 0x0a, + 0xe8, 0xb0, 0xef, 0x5b, 0xca, 0xc9, 0x97, 0x13, 0x98, 0xfe, + 0x91, 0x62, 0x14, 0xa8, 0x64, 0xf6, 0x20, 0xc9, 0xc9, 0x6f, + 0x8b, 0xc0, 0xec, 0x39, 0x15, 0xa7, 0x59, 0x62, 0x68, 0x21, + 0xe1, 0x5f, 0xf6, 0xa1, 0x76, 0xb0, 0xca, 0x1b, 0x2a, 0x71, + 0xe3, 0x1a, 0x24, 0x91, 0x1f, 0x3a, 0xbb, 0xf1, 0xc9, 0x09, + 0x42, 0x48, 0x7e, 0x19, 0x1b, 0xf1, 0xf0, 0x13, 0x33, 0xf1, + 0x62, 0x31, 0x00, 0x97, 0x73, 0x9b, 0x3c, 0x26, 0xf8, 0x42, + 0xd0, 0xd4, 0x41, 0x1b, 0x9f, 0x7e, 0x43, 0x4b, 0x0b, 0x08, + 0xd7, 0xa0, 0xa8, 0x32, 0x34, 0x0a, 0xc9, 0xef, 0xb8, 0xeb, + 0xe7, 0x64, 0x3b, 0x40, 0x88, 0xe0, 0x60, 0x59, 0x07, 0xef, + 0xb9, 0x5f, 0x71, 0x92, 0x90, 0xa4, 0x5f, 0x34, 0x38, 0x93, + 0x92, 0x43, 0x87, 0xaf, 0xdd, 0x87, 0x63, 0x8c, 0x1d, 0xe5, + 0x86, 0x9e, 0xe6, 0xde, 0x94, 0xdd, 0x33, 0x5d, 0x95, 0x64, + 0xd8, 0xc4, 0x8a, 0x3c, 0xe7, 0x4b, 0xd6, 0x3f, 0xc5, 0x69, + 0x6a, 0xa8, 0x7f, 0x0f, 0x93, 0x77, 0x02, 0x46, 0x66, 0xa5, + 0xa0, 0x60, 0x8b, 0xec, 0xb1, 0xa2, 0xfc, 0x2a, 0x09, 0xb8, + 0x08, 0x1c, 0x05, 0x6b, 0x78, 0xb7, 0x7a, 0xe5, 0x60, 0xa4, + 0xaf, 0x3a, 0x9d, 0xaa, 0xf5, 0x22, 0x9b, 0x5e, 0xef, 0xc3, + 0x46, 0xed, 0x67, 0xd0, 0x8b, 0xda, 0xb4, 0xa3, 0x34, 0x32, + 0x20, 0x9d, 0x88, 0x7e, 0x43, 0x42, 0x6f, 0x02, 0xf8, 0x48, + 0x9b, 0xc5, 0x02, 0xad, 0xaa, 0xa9, 0xee, 0x19, 0x1b, 0xde, + 0x02, 0x83, 0x81, 0x10, 0xa6, 0x79, 0x4e, 0xad, 0x15, 0xf7, + 0x3e, 0x4e, 0x1e, 0x72, 0xfe, 0x52, 0x49, 0x24, 0xce, 0x82, + 0x31, 0x59, 0x72, 0xae, 0xd5, 0x34, 0x50, 0x87, 0x8b, 0xe3, + 0x8e, 0xec, 0x61, 0x35, 0x13, 0x57, 0xb1, 0xe6, 0xac, 0xfb, + 0x16, 0xc3, 0x1a, 0x98, 0x92, 0xcb, 0xcd, 0xc9, 0xf7, 0x10, + 0x6a, 0x43, 0x96, 0x33, 0x2d, 0x6f, 0x6c, 0x76, 0xb0, 0xf6, + 0x48, 0x4c, 0xae, 0x13, 0x67, 0x5d, 0x42, 0x01, 0x8e, 0x54, + 0x51, 0xcc, 0x65, 0xf1, 0x95, 0x11, 0x3c, 0x96, 0x2a, 0x5a, + 0x42, 0x3d, 0x9b, 0xbb, 0xb7, 0x7b, 0x28, 0x96, 0x09, 0xbb, + 0xed, 0x2d, 0xbc, 0xb7, 0x90, 0x62, 0xd3, 0xbe, 0xbd, 0xae, + 0x50, 0x15, 0x96, 0xc1, 0x03, 0x91, 0x14, 0x34, 0x4f, 0x21, + 0xa5, 0x6e, 0x78, 0x4a, 0x5d, 0x8b, 0xcf, 0x5b, 0x1a, 0x8a, + 0x57, 0x43, 0xb8, 0x25, 0xd3, 0xa2, 0xcd, 0x78, 0xb4, 0x93, + 0x07, 0x7a, 0x14, 0xc1, 0x0c, 0x6f, 0x5f, 0x5e, 0xcb, 0x11, + 0x17, 0x81, 0x0d, 0x7d, 0x0f, 0xda, 0xd1, 0x92, 0x43, 0x56, + 0xaf, 0x75, 0x53, 0x44, 0x1f, 0xc7, 0x9c, 0xd3, 0xc5, 0x47, + 0xe0, 0xac, 0x4a, 0x11, 0xe4, 0xfe, 0x6c, 0x80, 0x79, 0xcc, + 0x60, 0x7a, 0xd9, 0x56, 0x65, 0x83, 0x5e, 0xcf, 0x37, 0x27, + 0x55, 0xe2, 0x4d, 0xf9, 0xd6, 0x09, 0x2d, 0xee, 0xda, 0x10, + 0x6b, 0xdc, 0xd2, 0x70, 0x46, 0x94, 0xaa, 0xf5, 0x21, 0xc5, + 0xf0, 0x79, 0xdb, 0x9b, 0x8e, 0x9a, 0xdb, 0x5a, 0x56, 0x41, + 0x43, 0xe7, 0x1f, 0x8d, 0xfd, 0xda, 0x12, 0x5f, 0xf7, 0x9e, + 0x47, 0x1a, 0xf7, 0x73, 0x40, 0x67, 0xc2, 0x61, 0x07, 0x33, + 0x16, 0x78, 0x60, 0x05, 0x85, 0x5c, 0x2f, 0x2b, 0xbf, 0x2c, + 0x7a, 0x39, 0xc6, 0xed, 0xcb, 0x43, 0x66, 0x27, 0x93, 0xcd, + 0x92, 0x8d, 0x62, 0x8c, 0xaa, 0x61, 0x1c, 0x9c, 0x4c, 0x90, + 0xba, 0xba, 0x4b, 0xc1, 0xf1, 0x22, 0xde, 0xe0, 0xf9, 0x3e, + 0x04, 0xb9, 0x56, 0xa3, 0x1c, 0xe8, 0xda, 0xd6, 0x09, 0x4a, + 0x7d, 0x89, 0xbc, 0xf4, 0xe8, 0x4d, 0xa1, 0xe8, 0x34, 0x90, + 0xa5, 0x31, 0x3a, 0xec, 0x56, 0xc5, 0xd2, 0x92, 0x0b, 0xe9, + 0x58, 0xbb, 0xb2, 0x84, 0x9b, 0xa9, 0x1d, 0x19, 0xdb, 0x7a, + 0x02, 0x75, 0x79, 0x16, 0x35, 0xee, 0x3a, 0x3f, 0x4e, 0x5e, + 0x11, 0x90, 0x04, 0x03, 0xce, 0x8b, 0xa0, 0xd8, 0xc1, 0xee, + 0x52, 0x33, 0x6e, 0xd2, 0x6e, 0x06, 0x5c, 0x99, 0x24, 0x6f, + 0x16, 0xd9, 0x90, 0x28, 0xe5, 0x2d, 0x91, 0x6f, 0x1a, 0x57, + 0xf0, 0x4c, 0x7c, 0x3f, 0x7b, 0xd7, 0x30, 0xed, 0x6d, 0x21, + 0xb7, 0xf8, 0xed, 0xf3, 0x34, 0x89, 0xfa, 0xf0, 0x51, 0x6f, + 0x99, 0xa0, 0x5e, 0xf8, 0x74, 0xc7, 0x4f, 0xb5, 0x59, 0x52, + 0xbe, 0x45, 0xac, 0x3f, 0x34, 0x51, 0x87, 0x6e, 0x84, 0xea, + 0xb0, 0x40, 0xe1, 0x84, 0x16, 0x66, 0x30, 0xf1, 0x5c, 0xb2, + 0x74, 0x25, 0x03, 0xe3, 0x2e, 0x82, 0xc5, 0x60, 0x9d, 0xe4, + 0xca, 0xec, 0x49, 0x6b, 0x4e, 0x5a, 0x09, 0xa8, 0xfe, 0xff, + 0x1d, 0xa1, 0xe8, 0xec, 0x9a, 0x22, 0x3b, 0xd6, 0x72, 0x93, + 0x6f, 0x6b, 0x5a, 0xfb, 0x2d, 0x5a, 0xde, 0x01, 0x3e, 0xf6, + 0xdc, 0x77, 0x55, 0x1e, 0x32, 0x19, 0xc8, 0xa1, 0xbb, 0xcf, + 0xcb, 0x41, 0x54, 0xa2, 0xcb, 0xe6, 0x61, 0xca, 0x43, 0x63, + 0xd2, 0x2c, 0xae, 0xf4, 0xd9, 0x49, 0xb1, 0x75, 0x1a, 0x06, + 0x92, 0x13, 0x90, 0x57, 0x89, 0x8e, 0x9f, 0x26, 0xc5, 0x14, + 0xd8, 0xc7, 0x93, 0xb2, 0xaa, 0x3a, 0x9c, 0x10, 0xd5, 0x68, + 0x52, 0x28, 0x39, 0xee, 0x30, 0xdc, 0x00, 0x4b, 0x65, 0x72, + 0x59, 0x98, 0xad, 0x2e, 0x8c, 0xaf, 0x4e, 0x79, 0x0a, 0x8c, + 0x0c, 0x9d, 0xb6, 0x43, 0x26, 0x83, 0x71, 0x7b, 0x1e, 0x86, + 0x4d, 0x33, 0xd7, 0x20, 0x29, 0x6a, 0xbf, 0x2f, 0x8e, 0x4b, + 0x13, 0x35, 0x65, 0xc8, 0xec, 0xe3, 0x2c, 0xde, 0xfb, 0x30, + 0x57, 0xa9, 0x92, 0x22, 0x5d, 0x79, 0x16, 0x07, 0x73, 0x9b, + 0xe2, 0x6e, 0xd4, 0x99, 0xb4, 0x35, 0xfd, 0xa2, 0xb5, 0xd9, + 0xe5, 0x74, 0xd1, 0xb2, 0xcf, 0x32, 0xf1, 0x19, 0x69, 0xcf, + 0x1e, 0x10, 0xcc, 0x3c, 0xaf, 0xbe, 0xa4, 0x33, 0x11, 0x83, + 0x64, 0xc0, 0x39, 0xe5, 0xb0, 0x8f, 0x32, 0xf4, 0x01, 0x6a, + 0x2a, 0x11, 0x8e, 0xdd, 0x03, 0x81, 0x39, 0xe7, 0x70, 0x16, + 0x2f, 0x0e, 0x24, 0xa9, 0x12, 0x0b, 0xdb, 0xa8, 0x6c, 0xb3, + 0xf3, 0x74, 0x95, 0xca, 0x64, 0x1d, 0xee, 0x25, 0xc5, 0x27, + 0xed, 0x0f, 0x82, 0xb5, 0x7a, 0x62, 0x27, 0xb2, 0x87, 0x53, + 0x11, 0x39, 0x5e, 0xb8, 0x11, 0xca, 0x25, 0xe8, 0x17, 0x46, + 0xd3, 0x0f, 0x5d, 0x70, 0x68, 0xe1, 0x5f, 0xd1, 0xab, 0x65, + 0xe5, 0x42, 0x87, 0x1e, 0x96, 0xaf, 0x13, 0x0c, 0x9b, 0x15, + 0x75, 0x14, 0x31, 0x75, 0xcc, 0x15, 0xbf, 0x2c, 0x74, 0xab, + 0xc9, 0x9c, 0xda, 0x62, 0x1d, 0xeb, 0x19, 0x81, 0x67, 0x5e, + 0xcd, 0x54, 0x87, 0x07, 0x67, 0xba, 0xe3, 0xf6, 0x03, 0xbe, + 0x6d, 0x64, 0x2d, 0xbc, 0xec, 0x54, 0x13, 0x12, 0x5b, 0x44, + 0x90, 0x95, 0x86, 0x77, 0x8c, 0x59, 0xbd, 0x8e, 0xba, 0xb1, + 0x12, 0xea, 0xc1, 0x94, 0x37, 0xa0, 0x11, 0xff, 0xb2, 0xa4, + 0xc3, 0x61, 0xf2, 0xa3, 0x49, 0xbe, 0xe7, 0xb6, 0x96, 0x2f, }; static const int sizeof_bench_dilithium_level2_key = sizeof(bench_dilithium_level2_key); -/* certs/dilithium/bench_dilithium_level3_key.der */ -static const unsigned char bench_dilithium_level3_key[] = -{ - 0x30, 0x82, 0x17, 0x5A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, - 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, - 0x06, 0x05, 0x04, 0x82, 0x17, 0x44, 0x04, 0x82, 0x17, 0x40, - 0x2E, 0xFE, 0x07, 0xDF, 0x5E, 0xF9, 0x18, 0xB4, 0x0E, 0xBF, - 0x9C, 0x1C, 0xCA, 0x84, 0xBA, 0x62, 0xB9, 0xA2, 0x96, 0x76, - 0xB6, 0xB7, 0x77, 0x9C, 0xBE, 0x0C, 0xF8, 0xA5, 0xEF, 0x74, - 0xB1, 0xC2, 0x8D, 0x95, 0x6D, 0x38, 0x49, 0x01, 0xA8, 0x3D, - 0x63, 0x0B, 0xDF, 0x4B, 0x5D, 0xF4, 0xC4, 0x98, 0x27, 0x77, - 0x88, 0xA0, 0xA9, 0xF2, 0x38, 0x32, 0x62, 0x17, 0x11, 0xD6, - 0xBE, 0xA0, 0xFD, 0xEB, 0xBF, 0x4A, 0xF2, 0x6C, 0x44, 0x62, - 0x2D, 0x87, 0x3D, 0xAD, 0x0C, 0x47, 0x06, 0x00, 0x7E, 0xAF, - 0x52, 0xE7, 0xA1, 0x8E, 0x7A, 0xA7, 0x7D, 0x3C, 0xE5, 0xB2, - 0x59, 0xDA, 0x89, 0x76, 0xF7, 0xD4, 0x73, 0x16, 0x33, 0x67, - 0x88, 0x46, 0x51, 0x13, 0x12, 0x38, 0x64, 0x76, 0x73, 0x40, - 0x16, 0x55, 0x70, 0x06, 0x32, 0x84, 0x47, 0x25, 0x33, 0x44, - 0x70, 0x68, 0x36, 0x25, 0x62, 0x47, 0x76, 0x65, 0x73, 0x11, - 0x28, 0x00, 0x75, 0x33, 0x81, 0x13, 0x62, 0x51, 0x31, 0x33, - 0x11, 0x41, 0x51, 0x62, 0x55, 0x33, 0x07, 0x60, 0x14, 0x18, - 0x30, 0x58, 0x22, 0x67, 0x26, 0x86, 0x12, 0x78, 0x17, 0x47, - 0x30, 0x06, 0x05, 0x36, 0x37, 0x23, 0x08, 0x67, 0x05, 0x05, - 0x06, 0x85, 0x33, 0x83, 0x14, 0x63, 0x44, 0x35, 0x00, 0x04, - 0x56, 0x03, 0x23, 0x03, 0x33, 0x13, 0x02, 0x23, 0x25, 0x80, - 0x22, 0x00, 0x53, 0x73, 0x13, 0x70, 0x03, 0x84, 0x15, 0x50, - 0x14, 0x20, 0x06, 0x74, 0x03, 0x41, 0x26, 0x74, 0x63, 0x65, - 0x42, 0x03, 0x00, 0x72, 0x66, 0x44, 0x36, 0x88, 0x60, 0x85, - 0x76, 0x86, 0x17, 0x72, 0x16, 0x37, 0x23, 0x82, 0x15, 0x84, - 0x57, 0x14, 0x20, 0x72, 0x15, 0x55, 0x26, 0x42, 0x82, 0x66, - 0x40, 0x54, 0x03, 0x54, 0x62, 0x61, 0x83, 0x35, 0x20, 0x76, - 0x62, 0x14, 0x37, 0x35, 0x42, 0x04, 0x32, 0x72, 0x08, 0x35, - 0x42, 0x74, 0x51, 0x24, 0x54, 0x86, 0x36, 0x56, 0x11, 0x83, - 0x64, 0x44, 0x54, 0x78, 0x80, 0x50, 0x55, 0x72, 0x84, 0x16, - 0x48, 0x13, 0x04, 0x17, 0x06, 0x36, 0x25, 0x48, 0x21, 0x33, - 0x45, 0x71, 0x21, 0x54, 0x10, 0x26, 0x13, 0x72, 0x12, 0x30, - 0x03, 0x73, 0x48, 0x84, 0x16, 0x22, 0x11, 0x38, 0x26, 0x43, - 0x53, 0x36, 0x56, 0x12, 0x15, 0x70, 0x07, 0x57, 0x00, 0x65, - 0x72, 0x11, 0x73, 0x48, 0x01, 0x13, 0x31, 0x58, 0x82, 0x60, - 0x61, 0x17, 0x78, 0x44, 0x48, 0x15, 0x48, 0x26, 0x62, 0x43, - 0x72, 0x44, 0x62, 0x76, 0x40, 0x15, 0x63, 0x26, 0x10, 0x51, - 0x82, 0x21, 0x05, 0x82, 0x30, 0x56, 0x58, 0x62, 0x76, 0x48, - 0x67, 0x82, 0x86, 0x51, 0x32, 0x37, 0x78, 0x38, 0x13, 0x82, - 0x55, 0x22, 0x45, 0x22, 0x68, 0x66, 0x15, 0x30, 0x35, 0x77, - 0x04, 0x28, 0x45, 0x85, 0x72, 0x48, 0x30, 0x26, 0x06, 0x24, - 0x12, 0x75, 0x42, 0x53, 0x88, 0x14, 0x15, 0x07, 0x08, 0x86, - 0x05, 0x08, 0x01, 0x56, 0x77, 0x44, 0x38, 0x53, 0x22, 0x21, - 0x20, 0x56, 0x25, 0x15, 0x72, 0x68, 0x27, 0x03, 0x71, 0x25, - 0x64, 0x11, 0x44, 0x34, 0x77, 0x60, 0x68, 0x58, 0x44, 0x74, - 0x76, 0x63, 0x86, 0x16, 0x01, 0x40, 0x68, 0x51, 0x20, 0x12, - 0x36, 0x55, 0x01, 0x84, 0x61, 0x80, 0x46, 0x36, 0x28, 0x82, - 0x44, 0x66, 0x14, 0x80, 0x50, 0x32, 0x34, 0x46, 0x21, 0x34, - 0x63, 0x04, 0x22, 0x20, 0x17, 0x84, 0x88, 0x88, 0x47, 0x02, - 0x52, 0x60, 0x45, 0x35, 0x86, 0x72, 0x71, 0x43, 0x30, 0x58, - 0x24, 0x11, 0x11, 0x64, 0x45, 0x36, 0x25, 0x18, 0x82, 0x18, - 0x16, 0x80, 0x27, 0x76, 0x53, 0x08, 0x70, 0x87, 0x64, 0x43, - 0x68, 0x86, 0x07, 0x04, 0x34, 0x10, 0x68, 0x30, 0x21, 0x01, - 0x86, 0x66, 0x06, 0x50, 0x41, 0x72, 0x18, 0x00, 0x05, 0x40, - 0x36, 0x35, 0x60, 0x50, 0x82, 0x82, 0x24, 0x73, 0x31, 0x35, - 0x81, 0x35, 0x02, 0x50, 0x22, 0x76, 0x44, 0x52, 0x27, 0x43, - 0x82, 0x66, 0x51, 0x38, 0x86, 0x72, 0x18, 0x54, 0x20, 0x65, - 0x45, 0x26, 0x03, 0x42, 0x24, 0x25, 0x27, 0x36, 0x02, 0x04, - 0x38, 0x77, 0x18, 0x44, 0x17, 0x78, 0x46, 0x34, 0x68, 0x00, - 0x72, 0x57, 0x72, 0x67, 0x53, 0x82, 0x51, 0x06, 0x34, 0x56, - 0x71, 0x26, 0x73, 0x55, 0x58, 0x11, 0x44, 0x15, 0x26, 0x81, - 0x14, 0x88, 0x25, 0x45, 0x52, 0x84, 0x13, 0x60, 0x12, 0x26, - 0x12, 0x36, 0x11, 0x61, 0x30, 0x25, 0x32, 0x83, 0x00, 0x71, - 0x73, 0x04, 0x48, 0x40, 0x70, 0x21, 0x36, 0x54, 0x45, 0x33, - 0x43, 0x00, 0x76, 0x62, 0x63, 0x71, 0x15, 0x35, 0x27, 0x50, - 0x06, 0x16, 0x30, 0x45, 0x08, 0x12, 0x51, 0x68, 0x38, 0x21, - 0x71, 0x61, 0x61, 0x18, 0x35, 0x15, 0x25, 0x47, 0x14, 0x62, - 0x51, 0x14, 0x76, 0x12, 0x62, 0x60, 0x63, 0x16, 0x20, 0x68, - 0x62, 0x31, 0x56, 0x64, 0x05, 0x84, 0x56, 0x26, 0x40, 0x42, - 0x88, 0x05, 0x60, 0x84, 0x82, 0x10, 0x23, 0x87, 0x63, 0x33, - 0x60, 0x40, 0x58, 0x12, 0x83, 0x26, 0x03, 0x13, 0x85, 0x23, - 0x02, 0x73, 0x05, 0x27, 0x40, 0x02, 0x75, 0x85, 0x46, 0x51, - 0x83, 0x71, 0x37, 0x16, 0x05, 0x86, 0x35, 0x01, 0x45, 0x00, - 0x53, 0x68, 0x27, 0x11, 0x06, 0x08, 0x82, 0x60, 0x58, 0x28, - 0x50, 0x07, 0x32, 0x56, 0x26, 0x46, 0x78, 0x63, 0x71, 0x16, - 0x48, 0x46, 0x86, 0x41, 0x37, 0x75, 0x06, 0x01, 0x11, 0x46, - 0x45, 0x21, 0x03, 0x82, 0x42, 0x75, 0x83, 0x30, 0x66, 0x00, - 0x74, 0x74, 0x46, 0x05, 0x33, 0x82, 0x33, 0x07, 0x34, 0x53, - 0x07, 0x78, 0x53, 0x07, 0x41, 0x37, 0x78, 0x54, 0x06, 0x11, - 0x42, 0x47, 0x05, 0x02, 0x62, 0x34, 0x27, 0x17, 0x78, 0x70, - 0x70, 0x46, 0x00, 0x38, 0x75, 0x48, 0x74, 0x46, 0x83, 0x35, - 0x08, 0x46, 0x14, 0x12, 0x20, 0x68, 0x00, 0x73, 0x57, 0x81, - 0x84, 0x62, 0x43, 0x11, 0x28, 0x87, 0x13, 0x30, 0x06, 0x70, - 0x15, 0x46, 0x51, 0x14, 0x74, 0x13, 0x53, 0x26, 0x84, 0x78, - 0x86, 0x15, 0x84, 0x18, 0x70, 0x56, 0x41, 0x33, 0x61, 0x56, - 0x28, 0x11, 0x30, 0x73, 0x82, 0x00, 0x57, 0x68, 0x61, 0x44, - 0x04, 0x64, 0x78, 0x68, 0x14, 0x02, 0x83, 0x88, 0x86, 0x88, - 0x40, 0x16, 0x81, 0x20, 0x68, 0x72, 0x67, 0x05, 0x76, 0x06, - 0x54, 0x74, 0x35, 0x71, 0x02, 0x67, 0x45, 0x24, 0x73, 0x64, - 0x87, 0x31, 0x60, 0x37, 0x04, 0x11, 0x85, 0x63, 0x40, 0x71, - 0x38, 0x46, 0x65, 0x16, 0x10, 0x85, 0x06, 0x37, 0x25, 0x53, - 0x05, 0x58, 0x45, 0x87, 0x17, 0x47, 0x78, 0x10, 0x22, 0x26, - 0x24, 0x86, 0x44, 0x63, 0x45, 0x00, 0x14, 0x77, 0x60, 0x04, - 0x54, 0x45, 0x40, 0x32, 0x45, 0x03, 0x60, 0x87, 0x05, 0x02, - 0x18, 0x22, 0x20, 0x61, 0x07, 0x36, 0x72, 0x52, 0x53, 0x65, - 0x27, 0x26, 0x37, 0x54, 0x31, 0x34, 0x22, 0x54, 0x37, 0x25, - 0x83, 0x14, 0x74, 0x75, 0x17, 0x61, 0x48, 0x74, 0x24, 0x43, - 0x80, 0x81, 0x15, 0x06, 0x88, 0x23, 0x84, 0x55, 0x20, 0x11, - 0x87, 0x83, 0x64, 0x36, 0x48, 0x88, 0x32, 0x20, 0x28, 0x54, - 0x88, 0x85, 0x35, 0x61, 0x00, 0x21, 0x01, 0x31, 0x44, 0x13, - 0x71, 0x48, 0x23, 0x47, 0x31, 0x62, 0x40, 0x18, 0x21, 0x78, - 0x34, 0x12, 0x88, 0x10, 0x76, 0x46, 0x72, 0x37, 0x70, 0x84, - 0x15, 0x41, 0x84, 0x22, 0x20, 0x22, 0x27, 0x44, 0x81, 0x03, - 0x46, 0x48, 0x26, 0x16, 0x21, 0x15, 0x31, 0x85, 0x73, 0x74, - 0x73, 0x06, 0x55, 0x21, 0x12, 0x53, 0x13, 0x34, 0x01, 0x64, - 0x40, 0x83, 0x08, 0x57, 0x24, 0x04, 0x18, 0x33, 0x70, 0x18, - 0x17, 0x06, 0x14, 0x28, 0x12, 0x58, 0x00, 0x25, 0x57, 0x20, - 0x00, 0x76, 0x73, 0x45, 0x68, 0x16, 0x60, 0x22, 0x17, 0x22, - 0x37, 0x75, 0x53, 0x48, 0x40, 0x21, 0x64, 0x27, 0x52, 0x48, - 0x53, 0x61, 0x64, 0x87, 0x57, 0x61, 0x13, 0x75, 0x80, 0x08, - 0x63, 0x33, 0x60, 0x26, 0x10, 0x25, 0x61, 0x78, 0x47, 0x78, - 0x07, 0x16, 0x00, 0x52, 0x31, 0x30, 0x63, 0x66, 0x46, 0x80, - 0x07, 0x10, 0x45, 0x11, 0x13, 0x80, 0x25, 0x61, 0x25, 0x53, - 0x80, 0x71, 0x38, 0x31, 0x47, 0x55, 0x02, 0x25, 0x50, 0x87, - 0x57, 0x35, 0x74, 0x11, 0x46, 0x44, 0x53, 0x24, 0x60, 0x33, - 0x15, 0x12, 0x77, 0x20, 0x36, 0x24, 0x70, 0x04, 0x87, 0x05, - 0x71, 0x07, 0x77, 0x36, 0x47, 0x01, 0x73, 0x61, 0x32, 0x62, - 0x28, 0x81, 0x67, 0x17, 0x38, 0x45, 0x21, 0x03, 0x24, 0x72, - 0x82, 0x64, 0x84, 0x43, 0x07, 0x11, 0x20, 0x72, 0x71, 0x04, - 0x58, 0x36, 0x22, 0x21, 0x33, 0x67, 0x55, 0x48, 0x03, 0x68, - 0x32, 0x70, 0x04, 0x63, 0x11, 0x34, 0x27, 0x82, 0x42, 0x56, - 0x28, 0x74, 0x77, 0x72, 0x18, 0x27, 0x35, 0x87, 0x03, 0x18, - 0x40, 0x32, 0x78, 0x07, 0x14, 0x43, 0x73, 0x73, 0x84, 0x63, - 0x78, 0x68, 0x03, 0x22, 0x55, 0x30, 0x18, 0x88, 0x15, 0x86, - 0x18, 0x51, 0x12, 0x42, 0x13, 0x60, 0x22, 0x44, 0x61, 0x44, - 0x35, 0x73, 0x08, 0x85, 0x53, 0x02, 0x73, 0x83, 0x25, 0x85, - 0x64, 0x78, 0x16, 0x12, 0x13, 0x63, 0x48, 0x35, 0x02, 0x71, - 0x72, 0x58, 0x12, 0x10, 0x65, 0x42, 0x22, 0x54, 0x80, 0x60, - 0x57, 0x84, 0x72, 0x76, 0x67, 0x35, 0x25, 0x14, 0x73, 0x70, - 0x48, 0x03, 0x78, 0x07, 0x74, 0x48, 0x67, 0x48, 0x01, 0x62, - 0x78, 0x05, 0x37, 0x66, 0x42, 0x45, 0x33, 0x65, 0x08, 0x70, - 0x42, 0x15, 0x72, 0x53, 0x13, 0x20, 0x14, 0x38, 0x05, 0x53, - 0x00, 0x45, 0x25, 0x20, 0x80, 0x75, 0x01, 0x65, 0x80, 0x70, - 0x61, 0x50, 0x15, 0x10, 0x77, 0x23, 0x38, 0x31, 0x21, 0x51, - 0x78, 0x11, 0x88, 0x71, 0x18, 0x06, 0x45, 0x62, 0x47, 0x35, - 0x43, 0x00, 0x52, 0x34, 0x41, 0x75, 0x18, 0x13, 0x51, 0x35, - 0x72, 0x11, 0x78, 0x17, 0x30, 0x44, 0x83, 0x25, 0x64, 0x42, - 0x65, 0x23, 0x50, 0x32, 0x85, 0x30, 0x67, 0x10, 0x70, 0x01, - 0x16, 0x62, 0x36, 0x46, 0x18, 0x53, 0x53, 0x80, 0x13, 0x65, - 0x66, 0x53, 0x61, 0x55, 0x07, 0x71, 0x34, 0x56, 0x31, 0x67, - 0x64, 0x42, 0x64, 0x41, 0x22, 0x56, 0x44, 0x67, 0x25, 0x52, - 0x08, 0x17, 0x38, 0x45, 0x76, 0x83, 0x37, 0x15, 0x76, 0x31, - 0x83, 0x47, 0x30, 0x21, 0x55, 0x73, 0x37, 0x82, 0x11, 0x56, - 0x67, 0x27, 0x23, 0x44, 0x72, 0x82, 0x10, 0x80, 0x43, 0x11, - 0x16, 0x02, 0x21, 0x40, 0x42, 0x10, 0x12, 0x74, 0x58, 0x40, - 0x74, 0x00, 0x66, 0x02, 0x85, 0x76, 0x21, 0x17, 0x83, 0x78, - 0x80, 0x40, 0x46, 0x87, 0x66, 0x24, 0x35, 0x80, 0x31, 0x77, - 0x87, 0x10, 0x47, 0x02, 0x20, 0x65, 0x43, 0x73, 0x41, 0x61, - 0x72, 0x18, 0x21, 0x52, 0x32, 0x82, 0x08, 0x82, 0x00, 0x57, - 0x52, 0x41, 0x45, 0x10, 0x51, 0x41, 0x28, 0x37, 0x72, 0x45, - 0x77, 0x10, 0x56, 0x06, 0x54, 0x30, 0x03, 0x74, 0x13, 0x56, - 0x77, 0x54, 0x04, 0x86, 0x13, 0x77, 0x81, 0x77, 0x57, 0x15, - 0x76, 0x13, 0x51, 0x75, 0x4C, 0xD3, 0x8C, 0xF8, 0x0F, 0x87, - 0x37, 0xBC, 0x26, 0x1B, 0x7A, 0x1C, 0xDC, 0x05, 0xFD, 0x9B, - 0x97, 0x8C, 0x4D, 0xE5, 0x06, 0xFF, 0x57, 0x65, 0xDC, 0xFC, - 0xBF, 0x55, 0x20, 0x8F, 0xC9, 0xAB, 0x63, 0x4C, 0x37, 0x02, - 0xB5, 0x51, 0x79, 0x6B, 0xC2, 0x02, 0x74, 0xE5, 0x74, 0x72, - 0xC4, 0x3C, 0x8F, 0xD2, 0x79, 0xCB, 0x65, 0x3C, 0xBD, 0xA6, - 0xC5, 0x19, 0xDF, 0xFC, 0x24, 0xB9, 0x91, 0x81, 0x41, 0x4D, - 0xDF, 0x2E, 0x6A, 0xBD, 0x5A, 0xC4, 0x04, 0x03, 0x7F, 0x71, - 0x7D, 0x51, 0xDD, 0x2F, 0xAE, 0x4C, 0x9A, 0xF8, 0x98, 0x11, - 0xA0, 0xCE, 0xF7, 0xDE, 0xF5, 0xC6, 0x91, 0xD3, 0xDC, 0xE7, - 0xAA, 0xD0, 0x7D, 0xDF, 0x5F, 0xF2, 0x5B, 0x55, 0x9C, 0xD6, - 0x8D, 0xC9, 0x1E, 0xC7, 0x80, 0xD9, 0xC5, 0xFA, 0x15, 0xEB, - 0xCE, 0x6B, 0x99, 0x71, 0xBD, 0xED, 0x0C, 0x24, 0x1B, 0x97, - 0x52, 0xFA, 0x54, 0xF5, 0x72, 0x48, 0x97, 0x05, 0x8B, 0x04, - 0xE5, 0xAA, 0xE0, 0xDC, 0x98, 0x13, 0xD2, 0x27, 0xB0, 0x0B, - 0x49, 0x8B, 0xA0, 0xD1, 0x2C, 0x18, 0xA5, 0xFA, 0x2A, 0x80, - 0x4B, 0xF7, 0x4B, 0x8C, 0xE0, 0xA4, 0xCD, 0xD0, 0x75, 0xE9, - 0x4A, 0x75, 0x15, 0x1B, 0xB8, 0x51, 0xD8, 0x8D, 0x1E, 0xA4, - 0xD1, 0xCD, 0x0E, 0xEE, 0xD4, 0xAA, 0x55, 0x0C, 0x6A, 0xB3, - 0xC9, 0x51, 0x66, 0x72, 0x76, 0xF4, 0xF9, 0xA4, 0xC2, 0x56, - 0x9D, 0xF9, 0x7C, 0x4C, 0x91, 0x27, 0xAC, 0xB3, 0x3E, 0x6B, - 0x2D, 0x5B, 0x84, 0xF3, 0x68, 0xD7, 0x28, 0xAE, 0xB6, 0x75, - 0x41, 0x46, 0xF2, 0x50, 0xF4, 0x20, 0x04, 0x4E, 0xB3, 0x0D, - 0xC3, 0xAE, 0xA9, 0x87, 0x9E, 0xB2, 0x05, 0xAE, 0x33, 0x76, - 0x76, 0x1A, 0x7A, 0xAB, 0xFD, 0x55, 0x77, 0x64, 0xF0, 0x0A, - 0x7C, 0x4F, 0x75, 0xE7, 0xBC, 0x09, 0x2D, 0x99, 0x4B, 0x90, - 0x13, 0x42, 0x62, 0xBD, 0x70, 0x14, 0x39, 0x23, 0x3A, 0x8A, - 0x32, 0x30, 0xEA, 0x66, 0x24, 0x85, 0xAF, 0x0B, 0xD7, 0x72, - 0xC4, 0xFC, 0x89, 0xD9, 0xB6, 0x9A, 0x1D, 0xA4, 0x10, 0x50, - 0x69, 0x98, 0x8E, 0x00, 0xA1, 0xCF, 0x94, 0x6C, 0x1B, 0x79, - 0x3A, 0xB7, 0xD8, 0x86, 0x1C, 0xD1, 0x95, 0x72, 0x0A, 0x3A, - 0xDA, 0xEF, 0x26, 0x15, 0xA5, 0xE4, 0x67, 0xD6, 0x04, 0xC5, - 0x0A, 0xBA, 0x50, 0x21, 0x9C, 0xB7, 0x1A, 0xF1, 0x1F, 0x1D, - 0x90, 0x5A, 0x6E, 0x40, 0xF8, 0xC1, 0xAB, 0xBD, 0x88, 0xA7, - 0xB8, 0x25, 0xBD, 0xCB, 0x93, 0xFA, 0x79, 0xAE, 0xAF, 0x1A, - 0xBD, 0x7B, 0xC4, 0x9F, 0x89, 0x7C, 0xFF, 0xFB, 0x0E, 0x27, - 0x32, 0x20, 0x6D, 0x47, 0x6B, 0x0E, 0x0D, 0xA1, 0x6A, 0x55, - 0x7F, 0xFD, 0x73, 0x9B, 0xC5, 0x3F, 0xF8, 0x08, 0xAA, 0xFE, - 0x0F, 0x7E, 0xAD, 0xB8, 0x13, 0x50, 0x79, 0x8D, 0x58, 0xAF, - 0xB2, 0xC6, 0x66, 0x24, 0xA8, 0x19, 0xD6, 0x90, 0x81, 0x54, - 0x92, 0x7B, 0xAF, 0xA8, 0xB8, 0x3D, 0x27, 0xD0, 0xC0, 0x08, - 0xB6, 0x45, 0x3D, 0x24, 0x46, 0xA0, 0x04, 0x8A, 0x26, 0x95, - 0xCF, 0x3F, 0x3C, 0x31, 0x43, 0x5D, 0xCA, 0x7A, 0xED, 0xF7, - 0xD3, 0xB5, 0xA0, 0xEE, 0xDC, 0x97, 0x76, 0xB3, 0x2F, 0x89, - 0x18, 0x62, 0xAC, 0x4B, 0x8B, 0xFC, 0x06, 0x1E, 0x15, 0xE5, - 0x25, 0x72, 0x46, 0xB9, 0x02, 0xD9, 0x0C, 0x38, 0xCF, 0x82, - 0x13, 0x19, 0x6E, 0x18, 0x85, 0xC6, 0x76, 0xF9, 0x10, 0xF9, - 0xCD, 0x72, 0x05, 0xED, 0x5E, 0xAE, 0xBB, 0xD2, 0xAB, 0x64, - 0x13, 0x3E, 0x9F, 0x20, 0xCF, 0x8C, 0xC0, 0x37, 0x71, 0x38, - 0x22, 0x49, 0x38, 0x9C, 0x23, 0xCB, 0x0B, 0xC3, 0xE8, 0xE5, - 0xEB, 0x31, 0x61, 0x07, 0xFE, 0x2A, 0xAC, 0xDE, 0x90, 0x35, - 0x24, 0xEB, 0x6B, 0xB6, 0x34, 0x51, 0x9C, 0xE2, 0x7D, 0xD0, - 0x8B, 0x38, 0xDB, 0x81, 0x7B, 0x24, 0x7B, 0x69, 0x84, 0x1D, - 0x17, 0x9F, 0x64, 0x63, 0x6F, 0x3F, 0x43, 0xFC, 0xFE, 0x07, - 0x72, 0x66, 0x84, 0xE3, 0xCD, 0x4F, 0x25, 0x70, 0x81, 0x64, - 0x66, 0x2C, 0xA8, 0x35, 0x11, 0x1B, 0xF3, 0x03, 0x1B, 0x5B, - 0xDC, 0xFB, 0x7D, 0xAD, 0x14, 0x11, 0xC8, 0xB1, 0x0C, 0x7E, - 0x36, 0x79, 0x34, 0x79, 0x1A, 0x88, 0x8A, 0x8F, 0xF6, 0x66, - 0xB4, 0x95, 0xD4, 0xA1, 0x02, 0xF9, 0x1D, 0x26, 0x53, 0x7A, - 0x34, 0x00, 0x36, 0x0E, 0xE7, 0xFB, 0x7A, 0x60, 0xF9, 0xC3, - 0xCF, 0x30, 0xCB, 0xF0, 0x27, 0xB5, 0xD6, 0xCF, 0x15, 0x33, - 0x53, 0x88, 0x7C, 0x50, 0x07, 0xF4, 0x27, 0xE0, 0x40, 0x47, - 0xFE, 0x86, 0x0E, 0xFF, 0x07, 0x5F, 0x55, 0xB8, 0x3B, 0xAA, - 0xFB, 0xB0, 0x6B, 0x98, 0x47, 0x59, 0xB8, 0x33, 0xAA, 0x67, - 0x6B, 0x36, 0xEB, 0x76, 0x43, 0xAF, 0x31, 0x52, 0x62, 0x3D, - 0x7F, 0x64, 0x6A, 0xFC, 0x36, 0x92, 0x96, 0xF8, 0xD9, 0xE7, - 0x13, 0x77, 0x1D, 0xD0, 0xFB, 0x0D, 0x70, 0x29, 0x61, 0x52, - 0x82, 0xF4, 0xE4, 0xA7, 0x08, 0x47, 0x4C, 0x67, 0xEE, 0x36, - 0xD1, 0x1C, 0x18, 0x8B, 0xF1, 0x2D, 0xE2, 0x47, 0x16, 0x4D, - 0x1F, 0x05, 0xC6, 0x4E, 0xFB, 0x35, 0x51, 0x3A, 0x9E, 0xF9, - 0xE0, 0x1E, 0xC1, 0x64, 0x21, 0x0B, 0x8A, 0xF0, 0x1D, 0x32, - 0x78, 0x18, 0xF2, 0xB3, 0xB5, 0xBD, 0x66, 0x6B, 0xAD, 0x92, - 0x4F, 0x22, 0xDC, 0xB9, 0xCC, 0xF4, 0x98, 0x22, 0x99, 0xF6, - 0x3D, 0xC6, 0x8F, 0x28, 0x77, 0x60, 0x34, 0xD0, 0x73, 0xF5, - 0x4D, 0x9F, 0x6C, 0x5D, 0x94, 0xC2, 0x3D, 0x19, 0xCD, 0xC2, - 0x18, 0x41, 0x9B, 0x5F, 0x32, 0x2D, 0x5E, 0x3D, 0x92, 0xBE, - 0x26, 0x39, 0x85, 0x50, 0xE6, 0xE2, 0x49, 0x17, 0x19, 0xD3, - 0x57, 0xAF, 0x45, 0x85, 0x74, 0xF7, 0x16, 0x35, 0x0A, 0x94, - 0x54, 0x64, 0x45, 0xD5, 0x31, 0x51, 0x49, 0x8F, 0xA4, 0x4C, - 0x33, 0xBB, 0x62, 0x59, 0x6B, 0x08, 0xBD, 0x1C, 0xDD, 0x38, - 0x93, 0x22, 0x0B, 0xCF, 0x9B, 0x23, 0x87, 0x30, 0xA2, 0xA0, - 0x6D, 0x97, 0x2D, 0xD7, 0x2B, 0x16, 0x88, 0x72, 0x01, 0x9A, - 0x51, 0xBA, 0x56, 0xCE, 0xDC, 0xDD, 0xF9, 0x87, 0x41, 0xC8, - 0x44, 0xF1, 0xA2, 0x20, 0x9A, 0x11, 0x44, 0x13, 0xDF, 0x49, - 0x04, 0x85, 0x4C, 0x01, 0x46, 0x3E, 0xD6, 0xB8, 0xE2, 0xC2, - 0x2E, 0xED, 0xA4, 0x07, 0x29, 0x89, 0xA2, 0x46, 0x23, 0x98, - 0xA5, 0xEF, 0x59, 0x1A, 0xE7, 0x67, 0x64, 0x59, 0xF7, 0x2C, - 0x5B, 0x30, 0x29, 0x57, 0xE3, 0xDE, 0x5C, 0x84, 0x1B, 0x8F, - 0x3E, 0xB3, 0x5B, 0xF5, 0x0C, 0x6E, 0xB1, 0x4E, 0x2F, 0xB6, - 0xB6, 0x5B, 0x29, 0xCD, 0xBB, 0xB8, 0xC9, 0xF0, 0x39, 0xF9, - 0xB9, 0x11, 0x47, 0xEF, 0xF8, 0x90, 0xE0, 0x0F, 0x91, 0x70, - 0x97, 0xB4, 0xFC, 0xFD, 0xB5, 0x69, 0x8C, 0x61, 0x9A, 0x26, - 0xD2, 0xC9, 0x47, 0x67, 0xB7, 0xDB, 0x73, 0x11, 0xA3, 0xC1, - 0x3B, 0x4E, 0x5F, 0x60, 0xDA, 0x73, 0x39, 0x9B, 0xD4, 0x3D, - 0x24, 0xA6, 0x8A, 0xB5, 0x56, 0x5D, 0xBD, 0x27, 0xDE, 0x6C, - 0x67, 0xA1, 0x4A, 0x77, 0xB7, 0x44, 0x1D, 0x28, 0x44, 0xA0, - 0xA3, 0xF2, 0xEB, 0x3A, 0x9F, 0xE5, 0x5C, 0xF5, 0xE3, 0xFE, - 0xD0, 0xC3, 0xCA, 0x2A, 0x1A, 0x72, 0x86, 0xB3, 0x4E, 0x9D, - 0x25, 0x0B, 0x4C, 0xFF, 0x45, 0xB7, 0xDE, 0xE8, 0x8C, 0x0A, - 0x06, 0xED, 0x30, 0x26, 0x8F, 0xA1, 0xBF, 0x74, 0x22, 0x3D, - 0x50, 0x39, 0x17, 0xA9, 0x6B, 0x7C, 0xAC, 0xA0, 0x6A, 0xEA, - 0x14, 0x95, 0x5F, 0xAD, 0x3C, 0xB1, 0x4E, 0xE1, 0x30, 0x2F, - 0x4A, 0x77, 0x72, 0xC1, 0x1F, 0x4C, 0x91, 0x6B, 0xCF, 0x81, - 0x46, 0xAF, 0x2D, 0xEC, 0x59, 0x9E, 0x99, 0xD9, 0x60, 0x23, - 0x95, 0x08, 0x0D, 0xBB, 0xFD, 0xEC, 0x2A, 0xF7, 0x7B, 0x73, - 0x53, 0xF3, 0x88, 0xB7, 0xAF, 0x51, 0x69, 0xD5, 0x08, 0xFC, - 0xCC, 0x03, 0xD3, 0x61, 0x5C, 0xDD, 0x39, 0x56, 0x6B, 0xE4, - 0xEE, 0x1F, 0x0A, 0xD6, 0x1A, 0x84, 0x65, 0x45, 0x0C, 0x0A, - 0x34, 0xDE, 0x96, 0x24, 0xBB, 0x74, 0xF4, 0xB7, 0xE5, 0x2F, - 0xB5, 0x1F, 0x85, 0x9D, 0xD7, 0xEA, 0xB3, 0x33, 0xBE, 0xCF, - 0x19, 0x45, 0xCE, 0xF9, 0x13, 0xF5, 0xFD, 0x65, 0x5D, 0xBB, - 0xDB, 0x64, 0x94, 0xAC, 0xB8, 0x39, 0xAF, 0x9B, 0x56, 0xE4, - 0x5C, 0x95, 0x85, 0xFD, 0xB3, 0xF8, 0x3C, 0x98, 0xD3, 0x58, - 0xCE, 0xAB, 0x09, 0x0E, 0xA7, 0x42, 0x9B, 0x16, 0xA7, 0x63, - 0xEB, 0xB8, 0x7C, 0x01, 0xA2, 0xD4, 0x3C, 0x2B, 0xA7, 0xA3, - 0x52, 0x8C, 0x08, 0xA5, 0xA9, 0xAF, 0x63, 0x07, 0xDA, 0x45, - 0x86, 0x91, 0x64, 0xE6, 0x41, 0x75, 0x78, 0x46, 0x6F, 0xB9, - 0xB4, 0xEA, 0x6A, 0xDD, 0xC7, 0x1A, 0x1F, 0xC0, 0x8A, 0x00, - 0x81, 0x70, 0x74, 0x37, 0xC8, 0x84, 0x3F, 0xA8, 0xC9, 0xC1, - 0xC1, 0x60, 0x2B, 0x25, 0x9B, 0x66, 0x5F, 0x73, 0x15, 0x51, - 0xE2, 0xE4, 0x49, 0x5B, 0xEE, 0x20, 0xC8, 0x18, 0xE7, 0x65, - 0xED, 0x29, 0xEA, 0x96, 0x85, 0xB5, 0x63, 0xFB, 0xA6, 0x23, - 0x22, 0xB7, 0x4F, 0x6E, 0xE3, 0xF2, 0x9C, 0x01, 0x23, 0x7A, - 0xB9, 0x16, 0x2A, 0x93, 0xAF, 0x4F, 0xEA, 0x05, 0x15, 0x84, - 0x46, 0x32, 0x2F, 0x99, 0xB8, 0x78, 0x20, 0x78, 0x93, 0xC9, - 0x42, 0x6D, 0xBC, 0x70, 0xCE, 0x88, 0x6F, 0x12, 0x92, 0x3F, - 0xDE, 0xFB, 0xDE, 0x8E, 0xD3, 0x69, 0x09, 0x54, 0x7D, 0x0A, - 0xE1, 0x93, 0x3D, 0x10, 0x04, 0xDE, 0x66, 0x9D, 0x2D, 0xAD, - 0xA4, 0x53, 0x4C, 0xF6, 0xFC, 0x08, 0xE4, 0x58, 0x05, 0x09, - 0x78, 0x09, 0xE6, 0xF3, 0xEE, 0x83, 0xC2, 0xD0, 0xA9, 0x04, - 0xE6, 0xAC, 0x30, 0xD7, 0x34, 0x52, 0xEB, 0xCD, 0x1A, 0x7E, - 0xB9, 0xCF, 0x18, 0x68, 0x16, 0xB9, 0x9A, 0x18, 0xDA, 0xC8, - 0xE3, 0x1C, 0xF0, 0x9A, 0x2E, 0x64, 0x28, 0xBE, 0xA4, 0x9F, - 0xCB, 0xC0, 0x53, 0xE6, 0x2A, 0x88, 0xB5, 0xE7, 0xF3, 0x6F, - 0x46, 0x1C, 0xBA, 0xAD, 0x76, 0x17, 0x85, 0xAE, 0x95, 0x13, - 0x7B, 0xF9, 0xB8, 0xD3, 0x08, 0x6A, 0x38, 0x63, 0x67, 0xD8, - 0x8B, 0x51, 0x8F, 0x49, 0x44, 0xB4, 0x10, 0xB8, 0x74, 0x38, - 0xDD, 0x17, 0xEA, 0x52, 0x67, 0xB2, 0xCC, 0xC9, 0x77, 0xDD, - 0x44, 0x2E, 0xDF, 0x03, 0xC7, 0xF4, 0x87, 0xF4, 0xBC, 0x6F, - 0x94, 0x9F, 0x58, 0xDB, 0xE2, 0x09, 0xA1, 0x4C, 0xCA, 0x89, - 0x9D, 0x04, 0x5A, 0xAB, 0xDF, 0x8B, 0x82, 0x3F, 0x0E, 0xF2, - 0xE7, 0xBD, 0x9A, 0x16, 0x3A, 0xAF, 0x72, 0x18, 0xB9, 0x47, - 0xB3, 0xBC, 0xFE, 0x84, 0x43, 0x92, 0x98, 0xF4, 0x3A, 0x49, - 0x3A, 0x26, 0xB7, 0xF3, 0x37, 0x54, 0x06, 0xD8, 0x92, 0x09, - 0xE6, 0xFE, 0x9A, 0xDB, 0x68, 0x16, 0x6F, 0x5D, 0x5D, 0x8E, - 0xBB, 0xFC, 0xAC, 0x5A, 0x72, 0xFE, 0x0B, 0xEB, 0xDB, 0x90, - 0xA4, 0x6C, 0x37, 0x1A, 0x8B, 0x5A, 0xD8, 0xE9, 0xF6, 0x15, - 0xFC, 0x54, 0x1B, 0x95, 0xE3, 0xAE, 0x08, 0x46, 0xB5, 0xFB, - 0xC5, 0x66, 0xC5, 0x79, 0x17, 0x9D, 0x5C, 0x45, 0xE5, 0x4E, - 0xFF, 0xA2, 0x86, 0xD7, 0x4F, 0xD4, 0x1D, 0x17, 0xA3, 0x77, - 0x00, 0x54, 0x70, 0xDF, 0x12, 0xCA, 0xD6, 0x71, 0x05, 0x54, - 0xFA, 0x47, 0x96, 0x38, 0x2D, 0x4D, 0x70, 0x3E, 0x2E, 0x40, - 0xE7, 0x52, 0x32, 0x66, 0x4D, 0x92, 0x1B, 0x76, 0x66, 0xF1, - 0xD4, 0x38, 0x8B, 0x76, 0x47, 0xE1, 0x66, 0xDE, 0xA2, 0x06, - 0xD7, 0xA7, 0x96, 0x52, 0xED, 0xC9, 0xF3, 0xD6, 0x99, 0xDF, - 0x2F, 0x98, 0xC5, 0xBF, 0x16, 0x95, 0x80, 0x41, 0xE4, 0xEB, - 0x8B, 0x16, 0xEF, 0x6A, 0x76, 0x84, 0xE7, 0x5F, 0x6C, 0xBD, - 0x1D, 0x2A, 0x74, 0x08, 0x5B, 0x4E, 0xCA, 0xE1, 0xF5, 0xD0, - 0x42, 0x2C, 0x03, 0x9B, 0x80, 0xBD, 0x05, 0x5F, 0x87, 0xF0, - 0x84, 0x08, 0x96, 0xBE, 0xAC, 0xBF, 0xF1, 0x8F, 0x51, 0x69, - 0x9E, 0xC2, 0xE9, 0x96, 0x9D, 0x97, 0xCD, 0x56, 0x32, 0x29, - 0xC8, 0x53, 0xC2, 0x1A, 0x5A, 0xD3, 0xDA, 0x31, 0x94, 0x09, - 0x35, 0x08, 0x75, 0x27, 0x66, 0xC5, 0x10, 0x5F, 0xD1, 0x94, - 0x12, 0x03, 0x8A, 0x1B, 0x69, 0x81, 0xEB, 0xBE, 0xBC, 0x6B, - 0xE4, 0xB9, 0x84, 0x65, 0x7D, 0xE3, 0xFE, 0xFB, 0x45, 0x58, - 0x31, 0xF3, 0x66, 0x13, 0x64, 0xB2, 0xBD, 0xBC, 0xF6, 0xA5, - 0x07, 0x07, 0x8A, 0xC8, 0x43, 0xCA, 0x38, 0x94, 0x70, 0xC0, - 0x25, 0xDA, 0xC6, 0xD9, 0x74, 0x5A, 0x60, 0xE3, 0x9D, 0x74, - 0x6C, 0x72, 0xF5, 0xAF, 0xD3, 0xD7, 0xF5, 0xBD, 0x17, 0x02, - 0xE5, 0x17, 0xEC, 0xBD, 0xCB, 0x5D, 0x1A, 0x8F, 0x39, 0x31, - 0x7E, 0x4B, 0x1F, 0x1A, 0x87, 0xE2, 0x69, 0x65, 0x07, 0x42, - 0x6D, 0xD2, 0x2D, 0x04, 0x52, 0x51, 0xA7, 0xF2, 0x23, 0xC6, - 0x01, 0xD1, 0x47, 0x5F, 0x42, 0x44, 0x2A, 0x88, 0x5E, 0xBB, - 0x98, 0x5A, 0x34, 0xBB, 0x0E, 0x05, 0xA7, 0x1D, 0x7E, 0xFB, - 0x3E, 0x85, 0xD8, 0x74, 0x70, 0xE8, 0x71, 0xC2, 0x31, 0x80, - 0x37, 0xF9, 0x15, 0xA4, 0xC1, 0xFC, 0x9B, 0x68, 0x2B, 0x54, - 0x9B, 0x37, 0x9C, 0xE7, 0x62, 0x80, 0x20, 0x1E, 0x27, 0x78, - 0xBF, 0x11, 0xC4, 0x86, 0xAC, 0x7B, 0x34, 0x57, 0x76, 0x86, - 0x77, 0x15, 0x51, 0x7C, 0xDC, 0x32, 0xDF, 0x48, 0xB9, 0xC6, - 0x63, 0xC6, 0x9A, 0xDE, 0x5E, 0x9D, 0xAB, 0x4A, 0x92, 0xEE, - 0x0C, 0x10, 0x7E, 0xB5, 0x33, 0x17, 0xF6, 0x0C, 0x8D, 0x26, - 0x89, 0xCD, 0x2B, 0xB8, 0x49, 0x4A, 0x4D, 0x5D, 0x66, 0x38, - 0x86, 0x42, 0x37, 0xC5, 0x1B, 0xE7, 0x78, 0x90, 0x21, 0xAE, - 0x8F, 0xE7, 0x0C, 0x01, 0xB9, 0x31, 0x6A, 0x50, 0x1A, 0x2B, - 0xDA, 0xC2, 0x99, 0xCB, 0xEB, 0xF9, 0xAE, 0x91, 0x8B, 0xB7, - 0x08, 0x01, 0x1E, 0xCC, 0x9E, 0x20, 0x05, 0xEC, 0x45, 0x21, - 0xBE, 0xDE, 0xFE, 0x06, 0x7D, 0x92, 0x9C, 0xE7, 0x47, 0xD9, - 0x85, 0x63, 0xC3, 0xBB, 0x38, 0x15, 0x2D, 0x94, 0xCA, 0xAF, - 0xCF, 0xCA, 0x1D, 0x53, 0x1A, 0xBD, 0x23, 0xF1, 0x87, 0x99, - 0x24, 0xF3, 0x16, 0xE9, 0x7F, 0xBE, 0x00, 0x8A, 0x61, 0xA7, - 0x65, 0xF7, 0xA9, 0x53, 0x2A, 0x29, 0x20, 0x3E, 0x0B, 0xCF, - 0x12, 0x69, 0x22, 0x84, 0x27, 0x5D, 0x1C, 0xC8, 0x45, 0xA1, - 0xA5, 0x5A, 0xB0, 0xDB, 0x95, 0x5D, 0xF7, 0xCE, 0xAC, 0x98, - 0x44, 0x3B, 0xE1, 0x27, 0x9A, 0x93, 0x5D, 0x2B, 0x8A, 0x20, - 0xB1, 0x82, 0x2C, 0xDD, 0xB8, 0xCC, 0xFA, 0x77, 0x0F, 0xA7, - 0x80, 0x00, 0x87, 0x54, 0x1C, 0xCC, 0x0B, 0x1E, 0xF6, 0x52, - 0x89, 0x03, 0x65, 0x83, 0xF1, 0x97, 0x4E, 0x81, 0x99, 0xE1, - 0xDD, 0x73, 0x30, 0x31, 0xEC, 0xA7, 0xD5, 0x76, 0x28, 0xC3, - 0xCE, 0x29, 0x30, 0x7B, 0xB1, 0x27, 0x3F, 0xC4, 0x6D, 0x54, - 0xAF, 0xE2, 0x84, 0xEA, 0xF5, 0x91, 0xBD, 0xB9, 0x6C, 0x4E, - 0x98, 0x0F, 0xFB, 0xDE, 0x7C, 0x32, 0xF8, 0xED, 0xEF, 0xD0, - 0xE9, 0xA3, 0x57, 0xC0, 0x91, 0x06, 0x4C, 0x43, 0x3F, 0x32, - 0x21, 0xB5, 0xF2, 0x11, 0x5A, 0xDF, 0xFC, 0x7E, 0x91, 0x10, - 0xC0, 0x4D, 0xD4, 0x4E, 0xA8, 0x38, 0xD6, 0xE0, 0xB6, 0x27, - 0x38, 0x63, 0xF2, 0xD3, 0xFD, 0x68, 0x4C, 0xDD, 0x76, 0xA9, - 0x89, 0xCE, 0xBE, 0x7C, 0xAD, 0x45, 0x4C, 0x8C, 0x24, 0xCC, - 0x32, 0x66, 0x3A, 0x1A, 0x45, 0xDA, 0x47, 0x5C, 0x4C, 0xC6, - 0x8A, 0x9A, 0xC3, 0x99, 0xFB, 0x4C, 0x94, 0xE2, 0x20, 0xD7, - 0xE4, 0x37, 0x22, 0x99, 0x32, 0x6F, 0xFB, 0x1C, 0xE5, 0x9B, - 0xB5, 0xFC, 0xBD, 0xD2, 0xA1, 0xDD, 0x66, 0xD5, 0x47, 0x2F, - 0x6A, 0xAA, 0x50, 0xF5, 0xE8, 0x1A, 0xDC, 0x74, 0x50, 0x6A, - 0x92, 0x23, 0x93, 0xED, 0xB0, 0x58, 0x61, 0x7D, 0xB6, 0x5C, - 0x22, 0x7B, 0x54, 0x75, 0xF0, 0x69, 0xD4, 0x27, 0x0B, 0x70, - 0x3F, 0xBB, 0x76, 0x63, 0xB3, 0x1D, 0x7E, 0x33, 0x96, 0xD6, - 0x84, 0x2D, 0x28, 0x4F, 0x97, 0x65, 0xC9, 0x95, 0xCF, 0x30, - 0xBA, 0xEA, 0x08, 0xF5, 0xC6, 0x24, 0x45, 0x20, 0x85, 0x67, - 0x9F, 0x34, 0x37, 0x72, 0x44, 0x17, 0x98, 0x5F, 0xD0, 0xCE, - 0xA8, 0x6E, 0x0E, 0x50, 0x22, 0x14, 0xE1, 0x6B, 0xCB, 0xA5, - 0x12, 0x2A, 0x36, 0xF1, 0x6E, 0x81, 0x5C, 0x5A, 0x77, 0x4F, - 0xD7, 0xF9, 0xCE, 0x7A, 0xC9, 0x30, 0x2C, 0x1E, 0x7E, 0xFC, - 0x24, 0xCB, 0xE4, 0x53, 0xC3, 0x4A, 0x03, 0xED, 0xD5, 0x77, - 0xC6, 0x55, 0xEB, 0xA2, 0xB4, 0x92, 0x35, 0xE3, 0x20, 0xDA, - 0xD2, 0x58, 0xE2, 0xCC, 0xC4, 0x4E, 0xBB, 0xE3, 0x8F, 0x75, - 0xB1, 0xDB, 0x97, 0x15, 0x86, 0x43, 0xE5, 0xD4, 0x4F, 0x44, - 0x3F, 0x20, 0xE3, 0xB9, 0xA5, 0xFB, 0x3F, 0x36, 0xC9, 0x9C, - 0xEF, 0x8C, 0xD1, 0x46, 0x67, 0x16, 0xB6, 0xA6, 0x24, 0x8A, - 0xE9, 0xD7, 0x29, 0x4B, 0x5F, 0x7C, 0x06, 0xEF, 0xD7, 0xBB, - 0x88, 0xCB, 0x2C, 0xFB, 0x85, 0x19, 0x9F, 0x97, 0x74, 0xFE, - 0x76, 0x46, 0x44, 0x1E, 0xAD, 0xF3, 0x62, 0xD2, 0xAA, 0x24, - 0x37, 0xD0, 0x1E, 0xF3, 0xCB, 0x68, 0xE3, 0x17, 0xFF, 0x81, - 0x90, 0xA3, 0xD6, 0x28, 0xE6, 0xCE, 0x6D, 0x99, 0xF4, 0x2D, - 0xC6, 0xAE, 0x40, 0x52, 0x32, 0xE9, 0xC1, 0xC6, 0x79, 0x5C, - 0xF7, 0x69, 0x29, 0x0C, 0x75, 0x9F, 0x48, 0x57, 0x75, 0x1F, - 0x2F, 0x71, 0x9F, 0x24, 0x90, 0x14, 0xAE, 0xDC, 0x75, 0x2E, - 0x5E, 0xDD, 0x85, 0xE5, 0x6C, 0xC4, 0x72, 0x58, 0xF0, 0x35, - 0xDC, 0xFE, 0x03, 0xB7, 0x2F, 0xBD, 0xC3, 0x8A, 0xA3, 0x2C, - 0x62, 0xE0, 0xCD, 0x37, 0xFA, 0x9E, 0x11, 0xC0, 0x1D, 0xEF, - 0xB0, 0x58, 0x58, 0x12, 0xAF, 0x25, 0x6D, 0x75, 0x0D, 0x2F, - 0xBC, 0x89, 0xE9, 0x2E, 0x1E, 0x58, 0x64, 0x35, 0xA8, 0x90, - 0xC2, 0x61, 0x4D, 0xCE, 0x96, 0xC5, 0xF2, 0x37, 0xBD, 0xB8, - 0xDE, 0xB4, 0x0E, 0xEB, 0xDD, 0xED, 0xE6, 0x47, 0x24, 0xE6, - 0x36, 0xC9, 0x22, 0xD3, 0xE7, 0x1A, 0xEF, 0x9E, 0x16, 0x89, - 0xB9, 0x5C, 0xF4, 0x3B, 0x09, 0x7E, 0x9B, 0x87, 0x7F, 0xD6, - 0x84, 0x06, 0xCA, 0x0E, 0xA8, 0x54, 0x79, 0xCF, 0x02, 0xF6, - 0x1B, 0x57, 0x34, 0x9D, 0x97, 0x00, 0x05, 0x8B, 0x75, 0xA3, - 0x5C, 0x7C, 0xBA, 0xA7, 0x51, 0x85, 0xBC, 0xE6, 0xAC, 0xD9, - 0xD4, 0x31, 0xB3, 0x3A, 0xBD, 0x82, 0xC8, 0x60, 0x74, 0x46, - 0xA9, 0x2F, 0xC2, 0x29, 0x08, 0x59, 0x6B, 0x14, 0x19, 0x19, - 0x39, 0x7F, 0x8B, 0xA2, 0x2A, 0xFD, 0xE3, 0x09, 0x72, 0x50, - 0x74, 0x88, 0xEE, 0xC6, 0xED, 0x28, 0x37, 0xCD, 0xA9, 0xBA, - 0x2E, 0xFE, 0x07, 0xDF, 0x5E, 0xF9, 0x18, 0xB4, 0x0E, 0xBF, - 0x9C, 0x1C, 0xCA, 0x84, 0xBA, 0x62, 0xB9, 0xA2, 0x96, 0x76, - 0xB6, 0xB7, 0x77, 0x9C, 0xBE, 0x0C, 0xF8, 0xA5, 0xEF, 0x74, - 0xB1, 0xC2, 0x85, 0xCD, 0xD1, 0x25, 0xD5, 0xFC, 0xFB, 0x2C, - 0xC7, 0xD6, 0x2F, 0x30, 0x3F, 0x10, 0xEA, 0xA2, 0x99, 0xC4, - 0x22, 0x58, 0xB3, 0xC4, 0x46, 0x3C, 0x41, 0xE9, 0xE9, 0xA0, - 0x39, 0x6C, 0x09, 0x89, 0xE3, 0xAE, 0x4E, 0x35, 0xAB, 0x27, - 0x71, 0x43, 0xEB, 0xA7, 0xFA, 0x68, 0xA8, 0x42, 0x49, 0x3C, - 0x53, 0x70, 0x35, 0xCA, 0x14, 0xB7, 0x1D, 0xF8, 0x7E, 0x65, - 0x05, 0x33, 0xE3, 0x5A, 0x86, 0xCD, 0xA5, 0x18, 0x02, 0x24, - 0x23, 0xAD, 0x52, 0x6A, 0x47, 0x13, 0x14, 0x95, 0xD2, 0xF1, - 0xE1, 0x6F, 0x61, 0x70, 0x4F, 0xDC, 0x1A, 0x03, 0x0E, 0xD7, - 0x07, 0xBD, 0x84, 0x43, 0x65, 0x76, 0x9F, 0xFB, 0x1E, 0x89, - 0xEB, 0x92, 0x5E, 0xDE, 0x5B, 0xAA, 0x54, 0xEE, 0x0A, 0xF5, - 0x4A, 0x79, 0x46, 0xDA, 0xC1, 0xEC, 0x2F, 0xBC, 0xDD, 0xE5, - 0x61, 0xFA, 0xED, 0xB6, 0x97, 0x9C, 0x90, 0xD8, 0xF3, 0x2E, - 0x04, 0xCF, 0xB5, 0x89, 0x74, 0xC2, 0xD1, 0x70, 0xE0, 0x0F, - 0x53, 0x14, 0x09, 0x6A, 0x19, 0x5A, 0x65, 0xAC, 0xAA, 0x3C, - 0x25, 0x79, 0x43, 0x27, 0x47, 0x18, 0x19, 0x7A, 0x74, 0xD7, - 0x73, 0x43, 0xBD, 0x50, 0x1F, 0x68, 0xAF, 0xDF, 0x3E, 0x2A, - 0xC4, 0xDC, 0x6F, 0x85, 0x2A, 0xBC, 0x0F, 0x39, 0x4B, 0x97, - 0x6D, 0x2D, 0x87, 0x5F, 0x9A, 0x07, 0x82, 0xC7, 0x69, 0xB9, - 0xF2, 0xEF, 0xE3, 0x3C, 0x3C, 0x74, 0xB2, 0xFD, 0x81, 0x6F, - 0xC3, 0xAC, 0x93, 0x22, 0x49, 0xB5, 0x73, 0x5C, 0x58, 0x6E, - 0x5F, 0x7A, 0x6B, 0x91, 0x02, 0x25, 0x3B, 0xC8, 0x24, 0xD7, - 0xEF, 0xC8, 0x10, 0xD7, 0x54, 0xD4, 0xA7, 0xC1, 0x88, 0x77, - 0xDD, 0xCD, 0x3A, 0x92, 0xE5, 0x1D, 0xA1, 0x33, 0x10, 0xA4, - 0xF6, 0xB4, 0x43, 0xA4, 0xDB, 0x77, 0x4C, 0x91, 0x7C, 0xED, - 0xDD, 0xC7, 0xB9, 0x5A, 0xB4, 0x2A, 0x6C, 0x78, 0x54, 0xCA, - 0xBD, 0x16, 0x0C, 0x8C, 0x68, 0xE8, 0xBC, 0xDE, 0x65, 0x2F, - 0xAF, 0xEF, 0x09, 0xDC, 0x7C, 0x17, 0x7D, 0x05, 0xF7, 0xB1, - 0x8D, 0x09, 0x94, 0xDC, 0xF2, 0xAE, 0xF4, 0x21, 0x54, 0xF9, - 0x3E, 0xB0, 0x2A, 0x73, 0xFE, 0x9C, 0x51, 0xEB, 0x1E, 0x7B, - 0xFE, 0x65, 0xCB, 0x53, 0x80, 0x5B, 0xD2, 0x05, 0xA1, 0xE9, - 0xCB, 0x75, 0x60, 0x46, 0x08, 0x07, 0x83, 0x27, 0x4E, 0xD4, - 0xBF, 0x70, 0x83, 0xDE, 0xA9, 0xB4, 0x22, 0x55, 0xF1, 0x5F, - 0x91, 0x88, 0x4A, 0x43, 0xC1, 0xBF, 0x0A, 0xEF, 0xA7, 0xFF, - 0xE5, 0xA6, 0x50, 0xDD, 0xFD, 0x6E, 0x22, 0xFF, 0xC1, 0x55, - 0x82, 0x0B, 0x42, 0x86, 0x42, 0xA7, 0x91, 0xD3, 0x62, 0x69, - 0xB2, 0x8D, 0x11, 0xC5, 0xB8, 0x4F, 0xBF, 0x4D, 0xFE, 0x37, - 0x12, 0x1F, 0xBF, 0xDE, 0xA5, 0x86, 0xAD, 0xC7, 0x2C, 0x7F, - 0x27, 0x01, 0xB0, 0xA1, 0xED, 0x7D, 0xCE, 0x33, 0x68, 0x97, - 0x2E, 0xA4, 0xF4, 0xEE, 0xA4, 0x36, 0x67, 0xE3, 0xAB, 0x89, - 0xF8, 0xCE, 0xF7, 0x01, 0xB1, 0x83, 0xFB, 0x54, 0xAA, 0x69, - 0x05, 0x76, 0x24, 0xD9, 0x76, 0x9F, 0xA3, 0x9C, 0x52, 0x8C, - 0x2E, 0x27, 0xB9, 0xA3, 0x6E, 0xE2, 0xC0, 0x02, 0x09, 0xC6, - 0x18, 0xAD, 0x42, 0x88, 0x6B, 0x2F, 0x5D, 0xB4, 0xF7, 0xC6, - 0xB4, 0x18, 0xB7, 0x88, 0x0B, 0x81, 0x2C, 0x25, 0xCE, 0xC3, - 0x7E, 0x9E, 0xAE, 0xBB, 0x35, 0x3C, 0xEC, 0x78, 0x46, 0x8F, - 0x03, 0x16, 0x5E, 0x5B, 0x08, 0x63, 0xFB, 0xBC, 0x78, 0x75, - 0xAB, 0x07, 0x1A, 0xA7, 0x96, 0x41, 0xCD, 0xDC, 0x3B, 0x59, - 0xDB, 0x02, 0xBE, 0x42, 0x09, 0xF5, 0x87, 0x96, 0x5D, 0x63, - 0xC9, 0x8E, 0x06, 0xA2, 0xFF, 0xCE, 0xCD, 0xF3, 0xDE, 0x93, - 0x79, 0x63, 0x92, 0xD2, 0xB9, 0x1D, 0x76, 0x7E, 0x4F, 0x36, - 0x2A, 0x89, 0x7B, 0x93, 0xC1, 0x35, 0x0A, 0x83, 0x8B, 0xD6, - 0xF4, 0xEA, 0x2A, 0x72, 0xA9, 0xE7, 0x6A, 0x77, 0x43, 0x14, - 0x49, 0x5B, 0x01, 0xD9, 0xE7, 0x72, 0x15, 0xD9, 0x9C, 0xBE, - 0x87, 0x90, 0x2A, 0x7F, 0x68, 0x02, 0x1C, 0xB5, 0xA1, 0xC6, - 0x7B, 0x24, 0x49, 0xBF, 0x8E, 0x3D, 0xE0, 0xBA, 0x1C, 0x78, - 0x0A, 0x7C, 0x69, 0x82, 0xA1, 0x2F, 0xB6, 0x52, 0xC5, 0x25, - 0xD8, 0x9D, 0x4B, 0x38, 0xAA, 0xBA, 0xF7, 0x4C, 0xC4, 0xC2, - 0xAE, 0xED, 0x6C, 0x28, 0x1C, 0x76, 0xA9, 0x96, 0x08, 0xAB, - 0xC4, 0x15, 0xBC, 0x3E, 0xD7, 0xCC, 0xC4, 0xA2, 0xD4, 0x93, - 0xD1, 0x3A, 0xF4, 0x2F, 0x17, 0xDB, 0x1C, 0xBD, 0xCA, 0x0D, - 0x5C, 0xF9, 0x69, 0x32, 0xAF, 0xC5, 0x27, 0x37, 0xFC, 0x1B, - 0xBB, 0x8A, 0x5D, 0x41, 0xA9, 0xC7, 0xE7, 0xC5, 0x2E, 0x78, - 0xE3, 0x7A, 0x5A, 0x25, 0x49, 0x2A, 0x06, 0x3D, 0x15, 0x58, - 0x56, 0xFB, 0x66, 0xEC, 0x30, 0x7D, 0xF4, 0x02, 0xF3, 0x53, - 0x3D, 0x0D, 0xDD, 0xFE, 0xB5, 0x66, 0xB0, 0xD0, 0xAA, 0x0E, - 0x6A, 0x76, 0xA6, 0xAB, 0x87, 0x14, 0xFB, 0x47, 0xAC, 0x26, - 0x53, 0xA9, 0x2C, 0xF3, 0xD5, 0xA6, 0x4F, 0xF0, 0x3A, 0x7E, - 0x78, 0xC5, 0x69, 0x1F, 0xB7, 0xDC, 0xC4, 0xE8, 0xD7, 0x44, - 0x7B, 0xB2, 0xC4, 0x50, 0x68, 0xF4, 0x33, 0xFC, 0x65, 0x0D, - 0xDC, 0xCD, 0x71, 0xCB, 0x9C, 0x65, 0x3B, 0x72, 0xB7, 0x19, - 0x70, 0x45, 0xA7, 0x36, 0xA4, 0xCF, 0xE7, 0x6F, 0xC8, 0xF9, - 0x67, 0x52, 0x22, 0x8F, 0x8F, 0x64, 0x89, 0xD3, 0x3E, 0x50, - 0xCC, 0xBE, 0x2B, 0xF3, 0x0A, 0x22, 0x96, 0x33, 0x56, 0x30, - 0x27, 0x3F, 0x42, 0xDE, 0x69, 0xA3, 0x63, 0xDE, 0x41, 0x94, - 0x02, 0x97, 0x9D, 0x58, 0xF3, 0x27, 0xE3, 0xFE, 0x94, 0x10, - 0x20, 0x55, 0x52, 0xD2, 0x46, 0xFB, 0x5E, 0x8C, 0xDF, 0x71, - 0x9B, 0xBF, 0x33, 0x79, 0x7C, 0xF3, 0x78, 0xA3, 0x75, 0x84, - 0x6C, 0x13, 0xEF, 0xC0, 0x43, 0x82, 0xAC, 0xF0, 0x97, 0x7D, - 0x2A, 0xBC, 0xA3, 0xB7, 0xCD, 0x4C, 0x99, 0xB9, 0xB1, 0xE9, - 0x38, 0x5C, 0x97, 0xB3, 0xC0, 0x2C, 0xBD, 0x6F, 0xF7, 0x14, - 0x26, 0x3A, 0x27, 0x31, 0x52, 0x81, 0x04, 0x88, 0xE6, 0xD8, - 0x43, 0x21, 0x78, 0x87, 0x7C, 0x7E, 0x28, 0x26, 0x4F, 0x93, - 0x9D, 0x7B, 0x2D, 0x02, 0x6E, 0x91, 0x74, 0xD9, 0x2C, 0xF7, - 0x43, 0xD8, 0x66, 0x81, 0x91, 0x21, 0xA1, 0xEE, 0xBC, 0x78, - 0x71, 0x80, 0x78, 0x54, 0x16, 0x59, 0x37, 0xB8, 0x69, 0xD3, - 0x49, 0x40, 0xAB, 0x03, 0x47, 0x36, 0xFD, 0x5D, 0x60, 0x57, - 0x8F, 0xBE, 0xA8, 0xA0, 0x21, 0x38, 0x43, 0xA9, 0x5C, 0x9F, - 0xAD, 0xD8, 0xAE, 0x97, 0xA3, 0x0F, 0xFC, 0xE4, 0x4A, 0xCF, - 0x9F, 0xE9, 0x75, 0x3D, 0x60, 0x91, 0x55, 0x5C, 0x0A, 0xB9, - 0x18, 0xEF, 0xD4, 0x08, 0x58, 0x06, 0x64, 0xA1, 0x45, 0xA7, - 0x5D, 0x3F, 0x13, 0x87, 0x49, 0x76, 0x8B, 0x1B, 0x54, 0x9C, - 0x61, 0x05, 0xC6, 0x2C, 0xED, 0x24, 0x1B, 0x7F, 0x9E, 0x9B, - 0x17, 0xBB, 0x84, 0xD8, 0xE2, 0x55, 0x69, 0x0E, 0xCF, 0xB2, - 0xC3, 0x61, 0x35, 0x0D, 0x86, 0xD7, 0x81, 0x75, 0x43, 0x98, - 0x29, 0xDF, 0x19, 0x9C, 0xFB, 0xC0, 0xC0, 0x5A, 0x7E, 0xF7, - 0xC6, 0x86, 0xEF, 0x6E, 0xBA, 0x26, 0x1D, 0x07, 0xF9, 0xC0, - 0x1F, 0xC0, 0x8E, 0x41, 0x8F, 0x1A, 0xE3, 0x51, 0xE2, 0xD7, - 0xCA, 0x28, 0x7D, 0x7A, 0xA7, 0x57, 0xA3, 0x2D, 0x98, 0x56, - 0x32, 0x9D, 0xC0, 0xF8, 0x23, 0x1D, 0x2C, 0xF6, 0x64, 0x1E, - 0x70, 0x33, 0xD4, 0x8F, 0xF9, 0xB0, 0xF4, 0x57, 0x7F, 0xD1, - 0x9A, 0xD4, 0x1A, 0x7E, 0xB6, 0x07, 0xAA, 0x54, 0x19, 0x0D, - 0x5D, 0xB8, 0x26, 0x45, 0x1B, 0x38, 0x14, 0x20, 0xFB, 0xAA, - 0x09, 0x71, 0xAF, 0x96, 0xB1, 0x17, 0xF3, 0x45, 0xA3, 0xA6, - 0x90, 0x52, 0x3C, 0x3B, 0x43, 0x9A, 0x8D, 0xE3, 0xB1, 0xC5, - 0xE4, 0x32, 0x6C, 0xE0, 0x17, 0x98, 0x43, 0x34, 0x54, 0x10, - 0x17, 0x82, 0x27, 0xE8, 0x8F, 0x99, 0x88, 0x98, 0x26, 0x70, - 0x19, 0xD1, 0x2D, 0x23, 0x02, 0x5F, 0x44, 0x71, 0x2A, 0xF6, - 0x48, 0x83, 0x34, 0x3A, 0x37, 0x11, 0x9C, 0xA1, 0xCE, 0xF0, - 0xD7, 0x6E, 0xF7, 0x2B, 0xA3, 0xFC, 0x07, 0x40, 0x64, 0x1A, - 0xF1, 0xF6, 0xF8, 0x90, 0x21, 0x1C, 0x0E, 0x85, 0xAA, 0xC1, - 0xF7, 0x16, 0xF5, 0x4D, 0x27, 0x8E, 0x91, 0x4E, 0x84, 0x19, - 0xDB, 0x8C, 0xEA, 0x00, 0xEA, 0xA6, 0x86, 0x18, 0x2C, 0x8B, - 0x46, 0x5F, 0xED, 0x61, 0x38, 0x28, 0x31, 0x4A, 0x1A, 0x12, - 0x19, 0x6C, 0x2D, 0x43, 0x0E, 0xD0, 0xDD, 0x4B, 0xFA, 0xA0, - 0x39, 0xC2, 0x4B, 0x31, 0xD9, 0x56, 0xB4, 0x9E, 0xB5, 0xD1, - 0x79, 0xA3, 0x35, 0xC7, 0xAF, 0xFD, 0x0E, 0x11, 0xC7, 0x0F, - 0x55, 0x1D, 0xCA, 0x71, 0xD1, 0x37, 0x3B, 0xC2, 0x72, 0xA0, - 0xDB, 0xEE, 0xA0, 0xF2, 0x28, 0xF4, 0x77, 0x34, 0x7D, 0x9F, - 0xE8, 0x38, 0xD0, 0xF1, 0xEB, 0x51, 0x95, 0x93, 0x5D, 0x7B, - 0x4F, 0xE7, 0x1A, 0xD5, 0xA1, 0xF1, 0xF1, 0x85, 0xF7, 0x58, - 0x5C, 0x2C, 0x49, 0xAF, 0xDC, 0x93, 0xFE, 0x73, 0x0F, 0xC8, - 0xC8, 0x26, 0x1B, 0xDE, 0xD8, 0xA6, 0x8A, 0x44, 0xB4, 0x2B, - 0x67, 0xBD, 0x8E, 0xFF, 0xA5, 0x8C, 0x18, 0x95, 0xD3, 0x02, - 0x7F, 0x28, 0x93, 0xAE, 0x84, 0x1E, 0xB0, 0x5C, 0x70, 0x57, - 0x1C, 0xFF, 0x75, 0x95, 0xBF, 0xAD, 0x95, 0xF3, 0x3C, 0x19, - 0xA0, 0x7A, 0x0F, 0x62, 0x65, 0xF0, 0x0F, 0x18, 0x1E, 0x48, - 0xB3, 0x85, 0x5D, 0x11, 0x47, 0xC9, 0x95, 0x75, 0xBE, 0xFA, - 0x2D, 0x56, 0x35, 0xD0, 0x7A, 0x75, 0x68, 0xEA, 0x7D, 0x01, - 0x9E, 0xD5, 0x28, 0x9E, 0x80, 0x09, 0xE5, 0xE9, 0xF8, 0xD3, - 0x11, 0xA6, 0xC7, 0x5E, 0xD6, 0x38, 0x8B, 0x96, 0x7A, 0xFB, - 0xD8, 0x27, 0xD4, 0x47, 0x6B, 0x50, 0xAB, 0x21, 0x4E, 0xFB, - 0xC2, 0xA1, 0x8C, 0xB7, 0x50, 0xE2, 0xF7, 0xC3, 0x4C, 0x66, - 0x04, 0x28, 0x17, 0x5D, 0x6F, 0x48, 0x39, 0x9A, 0x0B, 0x4A, - 0xB0, 0x75, 0xDF, 0xA9, 0x6E, 0xE0, 0x72, 0x20, 0x68, 0xC5, - 0x9C, 0xDB, 0x41, 0xA4, 0xF9, 0xA4, 0xF5, 0x1D, 0xDD, 0x89, - 0x83, 0x11, 0xDD, 0x3A, 0xA4, 0x76, 0x38, 0x62, 0x75, 0x4C, - 0x5D, 0xC7, 0xF5, 0x99, 0x75, 0xFB, 0xB7, 0x87, 0xB8, 0x77, - 0x2B, 0x45, 0xEF, 0xC5, 0xE5, 0x10, 0xD9, 0x6B, 0x4C, 0x72, - 0x4B, 0x42, 0x13, 0x71, 0x3C, 0x9C, 0x2C, 0x2E, 0xFB, 0xA2, - 0x3A, 0xCD, 0x2B, 0x83, 0x12, 0xA7, 0xF3, 0xA5, 0xCE, 0x4B, - 0x77, 0x2B, 0xF5, 0x71, 0xA0, 0x1A, 0x40, 0x7F, 0xED, 0x97, - 0x4B, 0x0C, 0xA0, 0x55, 0x6B, 0x69, 0x73, 0x52, 0x47, 0x6A, - 0x20, 0xCB, 0xEE, 0xE0, 0xBE, 0x97, 0x8F, 0x05, 0xE0, 0x84, - 0x4A, 0x6E, 0x40, 0xCC, 0x02, 0x2C, 0xA8, 0x45, 0xD4, 0x6B, - 0xD4, 0xCD, 0x41, 0x29, 0xBE, 0x99, 0x3B, 0x51, 0x0F, 0x9C, - 0x70, 0x75, 0x83, 0x3D, 0x42, 0xCF, 0xA9, 0x02, 0xF3, 0x68, - 0x3C, 0x96, 0xE1, 0x36, 0x46, 0xB7, 0x86, 0x16, 0x03, 0x2C, - 0xBB, 0x71, 0x21, 0xBF, 0x13, 0x52, 0x03, 0x42, 0x31, 0xE3, - 0xA3, 0x26, 0xEE, 0xD7, 0x86, 0x78, 0xDA, 0x9E, 0x9A, 0x50, - 0xD1, 0x9C, 0x5B, 0xB7, 0xEB, 0xCF, 0x0A, 0x6D, 0x10, 0xA0, - 0xAB, 0x8C, 0x65, 0x4B, 0xFA, 0x9E, 0xAC, 0x0B, 0x66, 0x56, - 0xC7, 0x5D, 0x85, 0x88, 0x53, 0x1B, 0xC2, 0x37, 0xCC, 0x94, - 0x2E, 0xE1, 0xB1, 0xF7, 0xCC, 0x1F, 0x59, 0x24, 0xEC, 0x1A, - 0x27, 0xFA, 0x8D, 0xE5, 0x86, 0x9E, 0x3F, 0x21, 0xDA, 0x15, - 0xAE, 0xC7, 0x6C, 0xFB, 0x17, 0x0D, 0xF5, 0xCB, 0xE3, 0xB8, - 0x36, 0x95, 0x0F, 0xBD, 0x84, 0x19, 0x1D, 0xF5, 0x4F, 0x17, - 0xB8, 0x71, 0x9C, 0x0E, 0x3D, 0xD8, 0xFD, 0x9B, 0xD4, 0x0D, - 0x2D, 0x16, 0x5D, 0x75, 0xE7, 0x25, 0x94, 0x3D, 0xD3, 0x0C, - 0x07, 0x3D, 0x04, 0x46, 0xC8, 0x8F, 0x65, 0x06, 0xC7, 0x11, - 0xB2, 0xAB, 0x41, 0x5E, 0x96, 0x0C, 0x68, 0x76, 0x7D, 0x6D, - 0xB8, 0xB5, 0x27, 0x01, 0x2C, 0x00, 0xC2, 0xA0, 0x40, 0xB8, - 0xF7, 0xC6, 0x39, 0x56, 0xCF, 0x25, 0x56, 0xB3, 0x10, 0x04, - 0xE9, 0xC3, 0x85, 0x47, 0xE8, 0x6E, 0xC7, 0x89, 0xFE, 0x80, - 0x9A, 0x50, 0x9E, 0xBD, 0xF3, 0x2E, 0x5E, 0x96, 0x0A, 0xA8, - 0xB7, 0x6C, 0x5B, 0x9E, 0x32, 0x1E, 0x75, 0x68, 0x5E, 0x74, - 0x88, 0xFC, 0xC5, 0x3D, 0xB9, 0x21, 0x0A, 0xAD, 0x6D, 0xF6, - 0xBE, 0x2D, 0x9A, 0x8A, 0xA5, 0x2A, 0x40, 0x3C, 0xF6, 0x4C, - 0xFE, 0x18, 0xE3, 0x44, 0x7A, 0x5F, 0x31, 0x1A, 0xEE, 0x95, - 0x07, 0x96, 0xC1, 0x27, 0x7F, 0x64, 0x4E, 0xF0, 0x19, 0x2D, - 0x36, 0x33, 0x5D, 0x23, 0xC9, 0xC2, 0x36, 0x91, 0x22, 0xC9, - 0x58, 0x8C, 0xE4, 0xF1, 0x19, 0xD0, 0xBF, 0x51, 0xAA, 0x14, - 0x4C, 0x15, 0x4A, 0x93, 0xF3, 0x16, 0x6A, 0x21, 0xBE, 0xDE, - 0xA5, 0x4C, 0x84, 0xC5, 0x65, 0x06, 0xA7, 0x11, 0xDC, 0x00, - 0x5F, 0x0F, 0xF1, 0xDA, 0xA2, 0x11, 0xAB, 0x64, 0xE0, 0x1F, - 0x1A, 0x65, 0x32, 0xA7, 0x69, 0x65, 0xAF, 0x64, 0x95, 0x90, - 0xF1, 0xA5, 0xFA, 0x32, 0x4C, 0x59, 0x61, 0x87, 0x3D, 0x94, - 0x82, 0x7E, 0xE4, 0x04, 0x7B, 0x8A, 0xCD, 0x54, 0x00, 0x2A, - 0xC5, 0xC3, 0xB7, 0x2F, 0x8A, 0xA8, 0x19, 0x39, 0x93, 0x53, - 0x3E, 0xEB, 0xE7, 0x8F, 0xF7, 0xCF, 0xDA, 0x8A, 0x4E, 0xAB, - 0x91, 0x3D, 0xA3, 0x40, 0x55, 0x64, 0xE7, 0x48, 0x90, 0x03, - 0xE5, 0xE6, 0x03, 0xE8, 0x2A, 0x23, 0x78, 0x6F, 0xCA, 0xDE, - 0x7C, 0x6E, 0x56, 0x5B, 0xC8, 0x6D, 0x8C, 0x2F, 0xC8, 0x6C, - 0x7D, 0xD8, 0x60, 0x43, 0x8C, 0xF3, 0xE9, 0x9E, 0x70, 0x73, - 0xAC, 0x85, 0xB4, 0xA3, 0x29, 0x86, 0x88, 0x60, 0x6D, 0xDD, - 0x21, 0x07, 0x09, 0x8B, 0xFB, 0xA1, 0x67, 0xA5, 0xDA, 0x9D, - 0xCC, 0x2E, 0xE3, 0xBE, 0xAE, 0x06, 0x0E, 0x41, 0x4E, 0xBE, - 0x5F, 0xE4, 0x93, 0x81, 0xE8, 0x06, 0xAA, 0x2C, 0xC9, 0x1B, - 0x1C, 0x5A, 0x9E, 0x01, 0xEF, 0xFF, 0x82, 0x84, 0xD9, 0x2B, - 0x05, 0x20, 0x0D, 0xE1, 0x14, 0x6C, 0x0A, 0x85, 0x16, 0x2E, - 0x79, 0xA3, 0x64, 0xBF, 0xFC, 0x89, 0xB8, 0xFD, 0xB0, 0xC8, - 0x39, 0x9A, 0x83, 0x1B, 0x74, 0x41, 0x7C, 0xEA, 0xFD, 0x5F, - 0x83, 0x19 +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY + +static const unsigned char bench_dilithium_level2_pubkey[] = { + 0xea, 0x05, 0x24, 0x0d, 0x80, 0x72, 0x25, 0x55, 0xf4, 0x5b, + 0xc2, 0x13, 0x8b, 0x87, 0x5d, 0x31, 0x99, 0x2f, 0x1d, 0xa9, + 0x41, 0x09, 0x05, 0x76, 0xa7, 0xb7, 0x5e, 0x8c, 0x44, 0xe2, + 0x64, 0x79, 0xa0, 0xec, 0x1f, 0x24, 0xb6, 0xc8, 0x05, 0x5b, + 0xc1, 0x18, 0xb0, 0xb7, 0xcf, 0x8c, 0x60, 0x67, 0x6b, 0x81, + 0x44, 0x27, 0xb6, 0x0e, 0xfd, 0x9b, 0xc3, 0xcb, 0x52, 0x31, + 0xfa, 0xc9, 0x34, 0x8d, 0x22, 0x1e, 0x07, 0x9d, 0x96, 0x6a, + 0x63, 0x83, 0x5c, 0xd7, 0x83, 0x2d, 0x7f, 0x48, 0x64, 0x79, + 0xca, 0xb4, 0x9f, 0xa2, 0x02, 0xb7, 0x86, 0x1d, 0x0e, 0xc7, + 0xf9, 0x6c, 0x07, 0xc0, 0x35, 0x6a, 0x34, 0x79, 0x7c, 0xb8, + 0x0f, 0xed, 0x98, 0x50, 0xfb, 0x51, 0xe0, 0x36, 0x44, 0x4c, + 0xc6, 0x35, 0xa2, 0xbb, 0x55, 0xb0, 0x5c, 0x39, 0x08, 0x02, + 0x20, 0x35, 0x5c, 0x56, 0x6d, 0x2e, 0xb9, 0xef, 0x21, 0x26, + 0x87, 0x87, 0x85, 0x8a, 0x32, 0xb5, 0xa7, 0x68, 0x70, 0x3a, + 0xfd, 0x0d, 0x21, 0x48, 0x91, 0xa3, 0x29, 0xc1, 0x2a, 0x38, + 0xe5, 0x26, 0x31, 0x1f, 0x42, 0xde, 0x0b, 0x25, 0xff, 0x1d, + 0x6b, 0xb4, 0xe0, 0x5d, 0x2d, 0xcf, 0x44, 0xd5, 0x7d, 0xc4, + 0xf6, 0x95, 0xf2, 0x06, 0x4f, 0x83, 0x88, 0x9d, 0x1e, 0xeb, + 0x1c, 0x09, 0x45, 0x62, 0x67, 0x3d, 0xff, 0x51, 0x47, 0xe8, + 0xbc, 0x9b, 0x03, 0x1f, 0xc7, 0x72, 0x65, 0xce, 0xa8, 0x8c, + 0xc2, 0xa0, 0xc2, 0xbd, 0x5b, 0x7c, 0x17, 0x16, 0x8b, 0x72, + 0xfa, 0xb1, 0xbd, 0xdf, 0x49, 0xd6, 0xa1, 0x00, 0x65, 0xbe, + 0x82, 0xe7, 0x68, 0xc7, 0xe7, 0xbc, 0xc2, 0xa4, 0xdb, 0xaa, + 0xcc, 0xea, 0x41, 0x52, 0x7f, 0x56, 0xb4, 0x68, 0x1f, 0x92, + 0x96, 0x0f, 0xce, 0xd4, 0xd0, 0x87, 0x4c, 0x4a, 0x73, 0xb5, + 0x6c, 0xd4, 0x69, 0x55, 0x15, 0x47, 0xdc, 0x94, 0x7f, 0xd2, + 0x54, 0x5e, 0xb2, 0x90, 0xc2, 0x47, 0xe4, 0xf5, 0xde, 0x8b, + 0x9b, 0xc6, 0x5d, 0x50, 0x95, 0x60, 0xe0, 0xf0, 0xa7, 0x4e, + 0xe0, 0xcd, 0x41, 0x09, 0xef, 0xb3, 0x3d, 0x90, 0x5c, 0x77, + 0x54, 0xec, 0x9e, 0x5d, 0x8a, 0xe7, 0x09, 0x5c, 0xc9, 0x58, + 0x0c, 0xd0, 0x42, 0x35, 0xd2, 0x14, 0x59, 0x38, 0x69, 0xad, + 0xf9, 0xb5, 0xbf, 0x8a, 0x8e, 0x33, 0xd8, 0x5e, 0x7a, 0x55, + 0xd0, 0x53, 0x15, 0x40, 0x4e, 0xc5, 0x86, 0xd7, 0x8f, 0x5f, + 0x2f, 0x55, 0x82, 0xc2, 0x4f, 0x16, 0xe5, 0xea, 0x1c, 0xbc, + 0xff, 0x5e, 0x1f, 0x39, 0x46, 0x70, 0x54, 0x7a, 0x3a, 0x27, + 0x16, 0x1a, 0x2b, 0x6c, 0xd2, 0xb7, 0x80, 0xd3, 0xd1, 0x9d, + 0x25, 0x59, 0xed, 0xe6, 0x51, 0xb1, 0xf2, 0xad, 0x7e, 0x51, + 0x78, 0x14, 0x2b, 0x19, 0xae, 0x64, 0x72, 0x0f, 0xd8, 0x18, + 0x79, 0x8e, 0x66, 0x88, 0xd3, 0xa4, 0xa3, 0xc3, 0x76, 0x21, + 0xcb, 0xe4, 0x79, 0x5e, 0x95, 0x74, 0xe3, 0x31, 0x18, 0x79, + 0xed, 0xc7, 0xe7, 0xfb, 0x86, 0x48, 0x1b, 0x7b, 0x75, 0x5b, + 0x7f, 0x7c, 0x82, 0xc5, 0xab, 0x11, 0xb4, 0x5d, 0x59, 0x6f, + 0x78, 0xb2, 0xa5, 0x39, 0xc6, 0x63, 0x38, 0x6c, 0xeb, 0x50, + 0x06, 0x14, 0x76, 0xf0, 0xe8, 0xfb, 0x11, 0x95, 0x1f, 0x9d, + 0x9c, 0xa6, 0xe1, 0xe2, 0x0d, 0xa3, 0x66, 0xfc, 0x20, 0x83, + 0x50, 0x0e, 0x53, 0x75, 0xb5, 0x12, 0xf4, 0xdf, 0x31, 0x46, + 0x83, 0xac, 0x5b, 0xf3, 0x99, 0xa6, 0xd1, 0x7b, 0x2b, 0xc5, + 0xdc, 0x71, 0x07, 0x27, 0x33, 0x35, 0x34, 0xf5, 0x30, 0x19, + 0xc1, 0x3b, 0xba, 0x8a, 0xaf, 0x7e, 0x49, 0x93, 0x48, 0x5b, + 0x38, 0xc0, 0xbc, 0x2e, 0xc7, 0x59, 0x1b, 0xd9, 0xf5, 0xcc, + 0x86, 0xf5, 0x7b, 0x4d, 0xd7, 0x39, 0xa7, 0xa2, 0x56, 0x20, + 0x48, 0x98, 0x7d, 0x4f, 0x75, 0x56, 0x9b, 0xb8, 0x95, 0x45, + 0x17, 0xf3, 0x86, 0x3d, 0x97, 0x0a, 0x49, 0x1b, 0xca, 0xff, + 0x20, 0xc0, 0x24, 0x2c, 0x51, 0xc2, 0x0a, 0x3c, 0xbf, 0x07, + 0x60, 0x1c, 0x88, 0x85, 0x9b, 0x85, 0x2d, 0x4a, 0xfe, 0x5a, + 0x1c, 0x90, 0xf5, 0x90, 0x12, 0xd3, 0x03, 0x3c, 0x8c, 0x2e, + 0x95, 0x4a, 0x47, 0x76, 0x0f, 0x1f, 0x5d, 0x9e, 0xed, 0xc5, + 0x64, 0xc4, 0x9b, 0xbf, 0x86, 0xc5, 0x63, 0x84, 0x33, 0x00, + 0xf1, 0x26, 0x18, 0x21, 0xf3, 0x88, 0x1a, 0x08, 0x18, 0x6d, + 0x2f, 0xef, 0xd5, 0xeb, 0x2f, 0x69, 0xc8, 0x6e, 0x92, 0x34, + 0xfc, 0x72, 0x3d, 0x9a, 0xa7, 0x9e, 0x51, 0xfb, 0x56, 0xe3, + 0xdc, 0xf4, 0x8f, 0x9b, 0x6d, 0x0d, 0x2a, 0xec, 0x66, 0x12, + 0x26, 0x35, 0xbd, 0x61, 0xc2, 0x67, 0x19, 0xf5, 0x7e, 0xa1, + 0x67, 0xa2, 0x9c, 0x3b, 0x67, 0xb0, 0xc2, 0x51, 0x6a, 0x37, + 0x7c, 0x48, 0xe9, 0x4b, 0xb9, 0xa3, 0x38, 0x2f, 0xfc, 0xde, + 0xb4, 0x7c, 0xda, 0x52, 0x84, 0x0b, 0xb0, 0xd9, 0x08, 0xe9, + 0x7a, 0x4a, 0x6f, 0x79, 0x29, 0x3d, 0xc4, 0x5c, 0x78, 0xee, + 0x63, 0xb6, 0x96, 0x68, 0xd9, 0x82, 0x4e, 0xc1, 0x1b, 0x6f, + 0x52, 0xf5, 0xb3, 0xfb, 0xe8, 0xc4, 0x2a, 0x07, 0xc6, 0x3b, + 0x85, 0x0d, 0xf4, 0xbf, 0xb0, 0x6b, 0xfb, 0xce, 0x1d, 0xb4, + 0xbf, 0x63, 0x0b, 0x91, 0x67, 0xc4, 0xa3, 0x06, 0xa4, 0xaf, + 0x6c, 0xd3, 0xe5, 0x8b, 0x87, 0x4e, 0x64, 0x9c, 0xb1, 0xf3, + 0x70, 0x7c, 0x68, 0x43, 0x46, 0x13, 0x46, 0xee, 0x27, 0x75, + 0x12, 0x45, 0x42, 0xde, 0xa5, 0x8d, 0xcf, 0xf7, 0x09, 0x87, + 0xa8, 0x80, 0x3d, 0xb6, 0x45, 0xee, 0x41, 0x2d, 0x7c, 0x45, + 0x01, 0x9d, 0xaa, 0x78, 0xa8, 0x10, 0xa4, 0xfd, 0xb5, 0x5f, + 0xee, 0x0f, 0x77, 0xba, 0x73, 0xff, 0x49, 0xdc, 0xfa, 0x39, + 0xd6, 0xa3, 0x6f, 0x25, 0xb9, 0x63, 0x2c, 0x92, 0xc5, 0xdf, + 0xfb, 0xba, 0x89, 0xf9, 0xfa, 0x94, 0x5b, 0x6f, 0x5a, 0x4d, + 0x1c, 0xe4, 0xc9, 0x10, 0xf9, 0xa0, 0xe8, 0xc4, 0xcb, 0x55, + 0x1a, 0xdb, 0x56, 0x5f, 0x8e, 0x91, 0x03, 0x23, 0xca, 0xb0, + 0x1f, 0xef, 0xb8, 0x6c, 0x13, 0x5a, 0x99, 0x25, 0xf0, 0x49, + 0xa9, 0x5a, 0x45, 0xf7, 0xfd, 0x1a, 0xc2, 0x71, 0x06, 0xe3, + 0x2d, 0x25, 0x64, 0xb0, 0x52, 0x12, 0x03, 0x62, 0xc7, 0xb6, + 0xf9, 0xdc, 0x1f, 0x78, 0xff, 0x8b, 0xfa, 0xde, 0x7f, 0x71, + 0xa6, 0x35, 0x3e, 0xac, 0x20, 0x54, 0x94, 0xa7, 0x2e, 0x9d, + 0x47, 0x17, 0x4b, 0xad, 0x92, 0xb3, 0x14, 0x26, 0x8c, 0x5a, + 0xd0, 0x16, 0x4b, 0x22, 0xe9, 0x0c, 0x79, 0x6b, 0x8e, 0xac, + 0x0d, 0x12, 0xf5, 0x66, 0x8e, 0x82, 0x1a, 0x44, 0xf3, 0xe9, + 0x56, 0x5a, 0xcd, 0x1c, 0x1b, 0x81, 0x7b, 0x63, 0x59, 0xfe, + 0xc8, 0xc0, 0xe3, 0xda, 0x16, 0x6b, 0x6f, 0x0d, 0xba, 0x0e, + 0x47, 0x12, 0x86, 0x9e, 0xf0, 0x3b, 0x4d, 0x87, 0x3b, 0xf2, + 0x75, 0x73, 0x2d, 0xdf, 0xca, 0x76, 0x0b, 0xbd, 0xe7, 0xb7, + 0x74, 0x24, 0xf3, 0xc6, 0xe6, 0x75, 0x3f, 0x8b, 0x6a, 0xd9, + 0xad, 0xed, 0xc0, 0x70, 0x04, 0x1e, 0x0b, 0x8e, 0x8b, 0x7f, + 0xea, 0xbc, 0x39, 0x6b, 0x8a, 0x44, 0xa6, 0x9a, 0x2d, 0x0d, + 0x8c, 0x21, 0x60, 0x09, 0xd2, 0x4a, 0xe0, 0x62, 0xcf, 0xfa, + 0xe8, 0x9b, 0x35, 0x6f, 0x23, 0x2f, 0xb5, 0x65, 0x08, 0x60, + 0x92, 0x15, 0xd0, 0x5b, 0x63, 0xcc, 0x65, 0x05, 0xd1, 0xef, + 0x0f, 0x7e, 0x1b, 0xb3, 0x8e, 0xc6, 0x12, 0x85, 0xc9, 0x82, + 0x53, 0x79, 0x2e, 0x80, 0x5f, 0x0c, 0x7b, 0xc7, 0x1c, 0x83, + 0x41, 0x06, 0xd8, 0x41, 0xc9, 0xe7, 0xb9, 0x4b, 0xa1, 0x61, + 0xc6, 0x86, 0x67, 0xf5, 0x10, 0xf7, 0x34, 0x0d, 0x39, 0x9e, + 0x2b, 0x5f, 0x19, 0x06, 0x02, 0xa5, 0x02, 0x23, 0x71, 0xc2, + 0x12, 0x65, 0xcc, 0x81, 0x06, 0xfd, 0x8d, 0x09, 0x68, 0x37, + 0x06, 0x3b, 0xff, 0xc4, 0x24, 0xb3, 0x1f, 0xd6, 0xe6, 0x8f, + 0x9c, 0x74, 0x2c, 0x5e, 0xc5, 0xf4, 0xe9, 0xeb, 0xca, 0xd3, + 0x04, 0x5b, 0x92, 0x9e, 0x5c, 0x1a, 0x1d, 0xa1, 0xa7, 0x34, + 0xd2, 0x05, 0xae, 0xdb, 0x3d, 0x71, 0x10, 0x6e, 0x30, 0xd9, + 0xa3, 0x44, 0xa0, 0xbd, 0x9e, 0x7b, 0xb5, 0x12, 0x8a, 0x12, + 0x07, 0x60, 0xd7, 0x1f, 0x92, 0xe6, 0xfe, 0x04, 0xa9, 0x3e, + 0x62, 0x64, 0x00, 0x5f, 0x7c, 0x7b, 0x34, 0x09, 0xeb, 0x4a, + 0x18, 0x9e, 0x77, 0x72, 0x3a, 0x31, 0x1a, 0x62, 0x2a, 0xb5, + 0xcb, 0x4e, 0x53, 0xce, 0xad, 0x8b, 0x5a, 0x20, 0x4f, 0xd7, + 0x3e, 0x16, 0xf8, 0x10, 0xe2, 0xae, 0xbd, 0x3f, 0x02, 0xa9, + 0x18, 0xa0, 0x01, 0x18, 0x84, 0x95, 0x22, 0x2e, 0x93, 0x76, + 0x44, 0x4e, 0x11, 0x7b, 0x03, 0x51, 0x50, 0x19, 0x79, 0xe7, + 0xbb, 0x5c, 0x7b, 0xca, 0x74, 0xb4, 0x25, 0x26, 0xdb, 0x66, + 0xaa, 0x0b, 0x21, 0x07, 0xfb, 0x7a, 0x96, 0x10, 0x7d, 0x99, + 0xa9, 0x16, 0xcb, 0x0e, 0xba, 0x63, 0xab, 0x95, 0xfc, 0x5a, + 0xbe, 0xa6, 0x7f, 0xd8, 0xb4, 0xcd, 0x7c, 0xc5, 0xd0, 0xb1, + 0x1b, 0x48, 0x40, 0xfb, 0xe6, 0x2f, 0x2b, 0x94, 0xfe, 0x68, + 0xa2, 0xc4, 0x36, 0xd9, 0xcd, 0xc1, 0x93, 0x6d, 0xef, 0x39, + 0x5e, 0x43, 0x30, 0x5a, 0x2e, 0x66, 0xb6, 0xf2, 0xed, 0x9a, + 0x8d, 0x12, 0xdf, 0x5c, 0xae, 0xad, 0x16, 0x12, 0x7e, 0x81, + 0x82, 0x91, 0x7d, 0x2b, 0x12, 0xe9, 0x96, 0xb8, 0xb7, 0x42, + 0xcb, 0x1f, 0xf8, 0xd1, 0xfd, 0x83, 0x7a, 0xe4, 0x36, 0x1d, + 0x04, 0x27, 0x4c, 0xe5, 0xbd, 0x75, 0x24, 0xf7, 0xbd, 0xb6, + 0x6a, 0x68, 0x4e, 0x2c, 0x1b, 0x56, 0x3e, 0x60, 0xa4, 0x42, + 0xca, 0x7a, 0x54, 0xe5, 0x06, 0xe3, 0xda, 0x05, 0xf7, 0x77, + 0x36, 0x8b, 0x81, 0x26, 0x99, 0x92, 0x42, 0xda, 0x45, 0xb1, + 0xfe, 0x4b, +}; +static const int sizeof_bench_dilithium_level2_pubkey = + sizeof(bench_dilithium_level2_pubkey); + +#endif /* !WOLFSSL_DILITHIUM_NO_VERIFY */ + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN + +static const unsigned char bench_dilithium_level3_key[] = { + 0x15, 0xc9, 0xe5, 0x53, 0x2f, 0xd8, 0x1f, 0xb4, 0xa3, 0x9f, + 0xae, 0xad, 0xb3, 0x10, 0xd0, 0x72, 0x69, 0xd3, 0x02, 0xf3, + 0xdf, 0x67, 0x5a, 0x31, 0x52, 0x19, 0xca, 0x39, 0x27, 0x77, + 0x61, 0x6d, 0x72, 0xdd, 0x85, 0x06, 0xf6, 0x94, 0x0a, 0x57, + 0x52, 0xcd, 0xac, 0x83, 0x4a, 0xe5, 0xbe, 0xa4, 0x30, 0x79, + 0x9e, 0xc6, 0xd6, 0x04, 0xc8, 0x73, 0xdc, 0x5e, 0x41, 0x75, + 0x2f, 0xac, 0x76, 0x57, 0x03, 0x08, 0x46, 0xcb, 0xaf, 0x4c, + 0x6a, 0x4f, 0x20, 0x18, 0xb3, 0x2e, 0x11, 0x54, 0xb5, 0x94, + 0xe6, 0x6f, 0x76, 0xf6, 0xb9, 0x73, 0x9a, 0x07, 0x73, 0xe8, + 0x90, 0xd1, 0x04, 0xda, 0xc5, 0x97, 0xb9, 0x52, 0x51, 0xc8, + 0xc9, 0xcc, 0x87, 0x29, 0xa1, 0xde, 0x79, 0x9b, 0xf8, 0x7f, + 0x80, 0x3f, 0xfd, 0xb3, 0x24, 0xa5, 0xba, 0xf5, 0xd6, 0xd4, + 0x07, 0xbd, 0xa7, 0x1b, 0xd0, 0xe1, 0xd0, 0x43, 0x14, 0x52, + 0x27, 0x03, 0x33, 0x76, 0x00, 0x67, 0x30, 0x23, 0x76, 0x34, + 0x72, 0x02, 0x41, 0x62, 0x12, 0x43, 0x86, 0x30, 0x18, 0x28, + 0x46, 0x27, 0x45, 0x20, 0x88, 0x33, 0x54, 0x10, 0x03, 0x81, + 0x44, 0x50, 0x06, 0x44, 0x56, 0x30, 0x37, 0x38, 0x38, 0x46, + 0x03, 0x85, 0x01, 0x86, 0x43, 0x80, 0x78, 0x28, 0x83, 0x55, + 0x37, 0x44, 0x80, 0x12, 0x17, 0x51, 0x78, 0x46, 0x22, 0x01, + 0x53, 0x54, 0x63, 0x87, 0x77, 0x38, 0x11, 0x81, 0x43, 0x30, + 0x15, 0x47, 0x66, 0x11, 0x40, 0x65, 0x70, 0x56, 0x62, 0x28, + 0x21, 0x65, 0x30, 0x45, 0x63, 0x53, 0x31, 0x80, 0x81, 0x71, + 0x23, 0x62, 0x85, 0x03, 0x07, 0x56, 0x16, 0x28, 0x18, 0x35, + 0x07, 0x38, 0x60, 0x68, 0x17, 0x30, 0x15, 0x20, 0x04, 0x13, + 0x13, 0x61, 0x51, 0x58, 0x00, 0x37, 0x51, 0x58, 0x14, 0x06, + 0x12, 0x55, 0x13, 0x46, 0x76, 0x05, 0x51, 0x87, 0x32, 0x62, + 0x50, 0x41, 0x88, 0x24, 0x50, 0x31, 0x65, 0x36, 0x31, 0x02, + 0x75, 0x35, 0x78, 0x27, 0x36, 0x08, 0x01, 0x77, 0x22, 0x77, + 0x30, 0x80, 0x11, 0x21, 0x28, 0x26, 0x68, 0x27, 0x13, 0x70, + 0x50, 0x44, 0x88, 0x20, 0x50, 0x67, 0x65, 0x74, 0x17, 0x46, + 0x50, 0x16, 0x42, 0x75, 0x35, 0x12, 0x60, 0x12, 0x17, 0x13, + 0x36, 0x72, 0x04, 0x77, 0x07, 0x55, 0x20, 0x27, 0x15, 0x02, + 0x25, 0x12, 0x57, 0x71, 0x37, 0x45, 0x43, 0x34, 0x40, 0x31, + 0x78, 0x50, 0x31, 0x28, 0x17, 0x84, 0x87, 0x43, 0x25, 0x75, + 0x58, 0x05, 0x61, 0x56, 0x41, 0x44, 0x57, 0x67, 0x85, 0x54, + 0x00, 0x88, 0x88, 0x50, 0x68, 0x11, 0x14, 0x42, 0x08, 0x74, + 0x73, 0x00, 0x38, 0x08, 0x45, 0x28, 0x62, 0x43, 0x36, 0x20, + 0x30, 0x10, 0x87, 0x83, 0x67, 0x62, 0x02, 0x48, 0x46, 0x50, + 0x08, 0x08, 0x41, 0x43, 0x78, 0x22, 0x65, 0x87, 0x43, 0x84, + 0x25, 0x36, 0x58, 0x64, 0x30, 0x10, 0x20, 0x68, 0x82, 0x47, + 0x60, 0x31, 0x76, 0x68, 0x74, 0x68, 0x75, 0x61, 0x16, 0x26, + 0x82, 0x50, 0x32, 0x61, 0x41, 0x22, 0x38, 0x20, 0x86, 0x75, + 0x74, 0x00, 0x77, 0x12, 0x81, 0x35, 0x51, 0x78, 0x88, 0x64, + 0x82, 0x00, 0x41, 0x55, 0x62, 0x87, 0x51, 0x41, 0x74, 0x51, + 0x53, 0x27, 0x33, 0x84, 0x68, 0x86, 0x57, 0x60, 0x44, 0x30, + 0x22, 0x32, 0x10, 0x52, 0x22, 0x83, 0x48, 0x53, 0x66, 0x74, + 0x14, 0x52, 0x32, 0x71, 0x41, 0x08, 0x83, 0x67, 0x41, 0x38, + 0x46, 0x80, 0x88, 0x14, 0x84, 0x30, 0x85, 0x35, 0x46, 0x20, + 0x54, 0x84, 0x56, 0x84, 0x54, 0x82, 0x14, 0x11, 0x52, 0x07, + 0x86, 0x46, 0x05, 0x82, 0x26, 0x85, 0x75, 0x07, 0x88, 0x75, + 0x51, 0x17, 0x54, 0x32, 0x68, 0x66, 0x08, 0x23, 0x66, 0x06, + 0x42, 0x28, 0x00, 0x84, 0x27, 0x27, 0x43, 0x47, 0x12, 0x27, + 0x13, 0x15, 0x17, 0x74, 0x85, 0x14, 0x12, 0x62, 0x06, 0x47, + 0x17, 0x60, 0x00, 0x10, 0x85, 0x16, 0x55, 0x64, 0x46, 0x62, + 0x77, 0x05, 0x51, 0x23, 0x52, 0x37, 0x51, 0x78, 0x35, 0x66, + 0x14, 0x15, 0x78, 0x40, 0x16, 0x54, 0x67, 0x30, 0x61, 0x24, + 0x26, 0x86, 0x56, 0x83, 0x62, 0x78, 0x88, 0x83, 0x50, 0x06, + 0x13, 0x21, 0x33, 0x73, 0x16, 0x44, 0x86, 0x77, 0x65, 0x28, + 0x12, 0x40, 0x62, 0x54, 0x55, 0x84, 0x00, 0x11, 0x77, 0x38, + 0x71, 0x51, 0x38, 0x32, 0x33, 0x67, 0x15, 0x77, 0x24, 0x33, + 0x44, 0x11, 0x05, 0x65, 0x13, 0x03, 0x72, 0x63, 0x81, 0x58, + 0x08, 0x03, 0x34, 0x23, 0x61, 0x00, 0x02, 0x63, 0x86, 0x40, + 0x03, 0x71, 0x34, 0x27, 0x45, 0x10, 0x34, 0x26, 0x83, 0x28, + 0x31, 0x35, 0x26, 0x05, 0x58, 0x41, 0x11, 0x10, 0x65, 0x35, + 0x22, 0x42, 0x28, 0x88, 0x46, 0x06, 0x57, 0x33, 0x88, 0x46, + 0x04, 0x86, 0x88, 0x88, 0x51, 0x74, 0x82, 0x27, 0x58, 0x14, + 0x11, 0x08, 0x13, 0x16, 0x61, 0x16, 0x14, 0x44, 0x83, 0x85, + 0x71, 0x44, 0x55, 0x82, 0x16, 0x62, 0x85, 0x05, 0x43, 0x41, + 0x73, 0x53, 0x60, 0x01, 0x80, 0x68, 0x33, 0x13, 0x43, 0x44, + 0x73, 0x36, 0x65, 0x35, 0x22, 0x26, 0x13, 0x31, 0x36, 0x83, + 0x30, 0x27, 0x15, 0x11, 0x54, 0x53, 0x24, 0x84, 0x75, 0x24, + 0x72, 0x78, 0x34, 0x24, 0x35, 0x80, 0x06, 0x38, 0x88, 0x11, + 0x41, 0x01, 0x34, 0x87, 0x77, 0x20, 0x14, 0x50, 0x55, 0x12, + 0x17, 0x48, 0x87, 0x74, 0x58, 0x42, 0x31, 0x46, 0x36, 0x37, + 0x26, 0x50, 0x04, 0x75, 0x77, 0x15, 0x41, 0x53, 0x04, 0x04, + 0x26, 0x61, 0x65, 0x87, 0x55, 0x56, 0x07, 0x81, 0x28, 0x21, + 0x41, 0x61, 0x41, 0x50, 0x17, 0x47, 0x25, 0x50, 0x20, 0x83, + 0x46, 0x87, 0x18, 0x45, 0x40, 0x21, 0x06, 0x08, 0x12, 0x25, + 0x71, 0x13, 0x35, 0x55, 0x54, 0x61, 0x00, 0x52, 0x74, 0x78, + 0x13, 0x84, 0x55, 0x40, 0x14, 0x40, 0x78, 0x12, 0x88, 0x43, + 0x33, 0x24, 0x66, 0x88, 0x22, 0x44, 0x15, 0x37, 0x81, 0x27, + 0x84, 0x18, 0x28, 0x11, 0x58, 0x51, 0x71, 0x21, 0x02, 0x83, + 0x70, 0x48, 0x32, 0x46, 0x00, 0x70, 0x17, 0x30, 0x63, 0x21, + 0x46, 0x60, 0x50, 0x72, 0x77, 0x45, 0x83, 0x75, 0x26, 0x31, + 0x47, 0x34, 0x47, 0x84, 0x87, 0x63, 0x22, 0x83, 0x21, 0x10, + 0x21, 0x51, 0x47, 0x46, 0x31, 0x06, 0x57, 0x82, 0x65, 0x24, + 0x61, 0x66, 0x24, 0x68, 0x14, 0x03, 0x43, 0x41, 0x04, 0x14, + 0x47, 0x61, 0x57, 0x87, 0x43, 0x83, 0x43, 0x25, 0x87, 0x36, + 0x72, 0x51, 0x38, 0x51, 0x54, 0x54, 0x84, 0x40, 0x15, 0x30, + 0x35, 0x34, 0x43, 0x61, 0x63, 0x42, 0x77, 0x31, 0x42, 0x06, + 0x61, 0x03, 0x01, 0x41, 0x08, 0x84, 0x02, 0x65, 0x04, 0x72, + 0x32, 0x00, 0x21, 0x10, 0x54, 0x73, 0x04, 0x42, 0x48, 0x11, + 0x74, 0x18, 0x63, 0x73, 0x28, 0x61, 0x36, 0x80, 0x20, 0x86, + 0x24, 0x42, 0x16, 0x11, 0x71, 0x83, 0x78, 0x38, 0x82, 0x47, + 0x67, 0x18, 0x56, 0x86, 0x85, 0x66, 0x18, 0x24, 0x50, 0x74, + 0x72, 0x02, 0x66, 0x83, 0x63, 0x08, 0x25, 0x32, 0x15, 0x78, + 0x33, 0x08, 0x34, 0x44, 0x08, 0x28, 0x10, 0x25, 0x40, 0x11, + 0x04, 0x76, 0x60, 0x16, 0x65, 0x16, 0x13, 0x30, 0x53, 0x14, + 0x77, 0x06, 0x06, 0x88, 0x64, 0x47, 0x08, 0x23, 0x11, 0x56, + 0x46, 0x61, 0x48, 0x64, 0x73, 0x66, 0x07, 0x65, 0x41, 0x24, + 0x67, 0x45, 0x42, 0x18, 0x62, 0x01, 0x70, 0x88, 0x03, 0x77, + 0x22, 0x85, 0x77, 0x02, 0x85, 0x03, 0x65, 0x15, 0x57, 0x51, + 0x28, 0x72, 0x53, 0x32, 0x05, 0x58, 0x84, 0x54, 0x03, 0x81, + 0x63, 0x23, 0x38, 0x27, 0x01, 0x85, 0x61, 0x12, 0x28, 0x62, + 0x22, 0x67, 0x56, 0x66, 0x63, 0x08, 0x74, 0x63, 0x21, 0x01, + 0x46, 0x10, 0x08, 0x18, 0x07, 0x86, 0x47, 0x70, 0x50, 0x25, + 0x45, 0x06, 0x55, 0x88, 0x46, 0x11, 0x23, 0x84, 0x70, 0x02, + 0x24, 0x88, 0x52, 0x60, 0x12, 0x72, 0x63, 0x05, 0x81, 0x21, + 0x26, 0x07, 0x64, 0x03, 0x56, 0x48, 0x27, 0x04, 0x38, 0x86, + 0x25, 0x65, 0x21, 0x25, 0x77, 0x21, 0x62, 0x28, 0x82, 0x71, + 0x85, 0x73, 0x78, 0x24, 0x78, 0x51, 0x61, 0x02, 0x81, 0x14, + 0x67, 0x61, 0x08, 0x88, 0x31, 0x77, 0x06, 0x24, 0x45, 0x13, + 0x67, 0x67, 0x54, 0x67, 0x00, 0x12, 0x62, 0x54, 0x11, 0x27, + 0x51, 0x48, 0x07, 0x33, 0x01, 0x24, 0x04, 0x64, 0x11, 0x83, + 0x18, 0x52, 0x55, 0x23, 0x24, 0x58, 0x53, 0x78, 0x30, 0x43, + 0x31, 0x76, 0x62, 0x01, 0x08, 0x73, 0x21, 0x32, 0x12, 0x78, + 0x22, 0x68, 0x33, 0x45, 0x33, 0x73, 0x02, 0x74, 0x21, 0x81, + 0x02, 0x16, 0x54, 0x31, 0x55, 0x76, 0x25, 0x76, 0x41, 0x36, + 0x75, 0x22, 0x78, 0x16, 0x60, 0x48, 0x58, 0x28, 0x83, 0x50, + 0x88, 0x66, 0x72, 0x70, 0x21, 0x21, 0x24, 0x16, 0x62, 0x57, + 0x20, 0x13, 0x80, 0x61, 0x15, 0x45, 0x42, 0x86, 0x00, 0x25, + 0x77, 0x58, 0x84, 0x01, 0x66, 0x16, 0x46, 0x56, 0x68, 0x57, + 0x12, 0x20, 0x75, 0x60, 0x41, 0x85, 0x02, 0x88, 0x12, 0x68, + 0x20, 0x02, 0x41, 0x18, 0x87, 0x13, 0x17, 0x33, 0x74, 0x11, + 0x08, 0x37, 0x47, 0x08, 0x31, 0x67, 0x08, 0x50, 0x61, 0x54, + 0x56, 0x71, 0x63, 0x26, 0x85, 0x22, 0x07, 0x87, 0x71, 0x28, + 0x20, 0x47, 0x48, 0x66, 0x54, 0x38, 0x03, 0x41, 0x38, 0x21, + 0x70, 0x50, 0x66, 0x53, 0x56, 0x70, 0x74, 0x55, 0x70, 0x28, + 0x52, 0x01, 0x42, 0x65, 0x53, 0x73, 0x32, 0x33, 0x67, 0x42, + 0x67, 0x85, 0x18, 0x45, 0x12, 0x37, 0x58, 0x82, 0x13, 0x73, + 0x78, 0x77, 0x03, 0x42, 0x04, 0x65, 0x55, 0x66, 0x07, 0x25, + 0x07, 0x37, 0x40, 0x78, 0x66, 0x71, 0x11, 0x21, 0x43, 0x25, + 0x87, 0x40, 0x58, 0x63, 0x33, 0x43, 0x52, 0x10, 0x31, 0x53, + 0x56, 0x48, 0x05, 0x55, 0x77, 0x77, 0x26, 0x87, 0x28, 0x43, + 0x61, 0x46, 0x11, 0x76, 0x82, 0x50, 0x42, 0x04, 0x32, 0x88, + 0x18, 0x66, 0x16, 0x36, 0x64, 0x41, 0x38, 0x17, 0x55, 0x43, + 0x06, 0x25, 0x80, 0x27, 0x21, 0x16, 0x81, 0x22, 0x64, 0x60, + 0x38, 0x16, 0x82, 0x40, 0x72, 0x34, 0x73, 0x52, 0x61, 0x85, + 0x11, 0x16, 0x00, 0x25, 0x03, 0x30, 0x06, 0x80, 0x21, 0x56, + 0x64, 0x52, 0x23, 0x26, 0x37, 0x75, 0x73, 0x65, 0x53, 0x27, + 0x37, 0x47, 0x56, 0x76, 0x80, 0x38, 0x53, 0x62, 0x14, 0x24, + 0x64, 0x03, 0x66, 0x21, 0x72, 0x16, 0x36, 0x34, 0x11, 0x65, + 0x61, 0x62, 0x86, 0x02, 0x83, 0x27, 0x80, 0x82, 0x70, 0x72, + 0x52, 0x60, 0x20, 0x87, 0x58, 0x58, 0x14, 0x38, 0x47, 0x03, + 0x10, 0x72, 0x60, 0x48, 0x02, 0x01, 0x17, 0x21, 0x61, 0x62, + 0x38, 0x64, 0x27, 0x53, 0x57, 0x13, 0x68, 0x18, 0x26, 0x62, + 0x43, 0x42, 0x21, 0x85, 0x70, 0x23, 0x58, 0x13, 0x72, 0x04, + 0x04, 0x08, 0x05, 0x82, 0x26, 0x18, 0x82, 0x47, 0x87, 0x71, + 0x32, 0x28, 0x68, 0x25, 0x87, 0x24, 0x06, 0x74, 0x41, 0x44, + 0x08, 0x64, 0x68, 0x30, 0x24, 0x44, 0x21, 0x73, 0x03, 0x45, + 0x70, 0x41, 0x06, 0x78, 0x38, 0x33, 0x88, 0x13, 0x31, 0x14, + 0x18, 0x17, 0x45, 0x06, 0x26, 0x67, 0x66, 0x73, 0x82, 0x56, + 0x66, 0x88, 0x70, 0x22, 0x55, 0x47, 0x27, 0x50, 0x86, 0x55, + 0x53, 0x00, 0x28, 0x55, 0x40, 0x62, 0xe9, 0x37, 0x65, 0xe1, + 0x30, 0x48, 0x6b, 0x35, 0x76, 0x96, 0x05, 0x21, 0xce, 0xed, + 0x46, 0xae, 0x7e, 0x6d, 0xc9, 0xf1, 0xc9, 0xb3, 0x7a, 0xa7, + 0xde, 0xa7, 0x62, 0x18, 0x11, 0xc0, 0xd8, 0xd0, 0x17, 0x0f, + 0x38, 0xaf, 0x0e, 0x3d, 0xaf, 0xe6, 0x63, 0xb0, 0xc4, 0x68, + 0x4e, 0x29, 0xa4, 0xf4, 0x20, 0x22, 0xbc, 0x82, 0x15, 0x1d, + 0x08, 0x39, 0x18, 0xfe, 0x69, 0x55, 0x06, 0x3d, 0xf4, 0xa3, + 0xe7, 0x29, 0x23, 0xa4, 0xd9, 0xa4, 0x22, 0x06, 0x2d, 0x5f, + 0x22, 0xb3, 0x9b, 0x1c, 0xb6, 0x3e, 0xf3, 0xf4, 0x8a, 0xb3, + 0x35, 0x18, 0x4c, 0x1f, 0xaf, 0xd4, 0xcf, 0x5b, 0x9b, 0xa7, + 0xf8, 0xd2, 0x86, 0x71, 0x8e, 0x64, 0x96, 0xd1, 0x6e, 0xad, + 0xd2, 0x7e, 0x16, 0x5b, 0x38, 0x91, 0x0e, 0x40, 0xaa, 0x07, + 0x6a, 0x63, 0x2a, 0xc0, 0x5b, 0x14, 0x79, 0x52, 0xcb, 0x23, + 0x6e, 0x76, 0x95, 0xd0, 0x90, 0x6c, 0x18, 0xe7, 0x89, 0xee, + 0xb9, 0x7f, 0x33, 0x08, 0x35, 0x8f, 0xa3, 0xaa, 0xaa, 0x10, + 0x2f, 0x8b, 0xc9, 0x6c, 0x1d, 0x95, 0xb5, 0xb8, 0x54, 0x0d, + 0x67, 0x86, 0xd4, 0x5d, 0xae, 0x8f, 0x33, 0x20, 0xe2, 0x35, + 0xda, 0x71, 0x53, 0x24, 0xad, 0x16, 0x84, 0x2e, 0x98, 0xcd, + 0x00, 0xa2, 0x69, 0x6a, 0x12, 0x9a, 0x86, 0xf3, 0x9f, 0x18, + 0x6c, 0x9f, 0x24, 0xbe, 0xb3, 0xf4, 0x90, 0xb3, 0xc4, 0xa4, + 0x8b, 0xce, 0x88, 0x60, 0xa0, 0x91, 0xb8, 0x9a, 0x52, 0xe5, + 0xfe, 0x16, 0x6d, 0xff, 0xb3, 0xdc, 0x50, 0x79, 0xfe, 0x31, + 0x24, 0xd4, 0x59, 0x5f, 0xf9, 0xb4, 0x70, 0x0b, 0x15, 0x93, + 0xd9, 0xe9, 0x92, 0xb6, 0xf5, 0x80, 0x34, 0x63, 0x66, 0x78, + 0xcf, 0xa9, 0xce, 0x48, 0xbf, 0xbe, 0x9e, 0xfa, 0xdd, 0x7d, + 0xf4, 0x16, 0xe2, 0xd2, 0x98, 0x13, 0xe2, 0x76, 0xdd, 0x0a, + 0xc7, 0x2d, 0xe8, 0x88, 0x8e, 0x1a, 0xc0, 0xfc, 0xe8, 0x35, + 0xaf, 0x5d, 0xe2, 0x4c, 0x96, 0x82, 0x4c, 0xe5, 0x89, 0x14, + 0xb8, 0x27, 0x39, 0xb5, 0x55, 0xc5, 0xa5, 0x8a, 0x01, 0xcc, + 0xfd, 0xbd, 0xa9, 0xec, 0xae, 0xc0, 0xe7, 0xd7, 0xf8, 0x11, + 0x84, 0x35, 0x99, 0x26, 0xb6, 0xc6, 0xf7, 0x35, 0xe0, 0x93, + 0xd8, 0xd7, 0xbf, 0xc0, 0xc8, 0x44, 0xfd, 0x46, 0xf5, 0xb7, + 0xc5, 0x5a, 0x75, 0xd3, 0xc7, 0xfa, 0xf4, 0xe1, 0xc0, 0x84, + 0x5e, 0x31, 0xfe, 0x69, 0x80, 0x5a, 0xe5, 0x4b, 0x9b, 0x5b, + 0xa4, 0x5c, 0x23, 0xaa, 0x85, 0xc9, 0x9a, 0xbd, 0x71, 0x49, + 0x11, 0x30, 0x8b, 0x81, 0xa1, 0xdd, 0xf8, 0xb8, 0x74, 0x91, + 0xe7, 0xf7, 0x82, 0x42, 0x70, 0x22, 0x95, 0xf0, 0xcc, 0x9f, + 0x02, 0x33, 0x0f, 0x08, 0x3b, 0x04, 0x31, 0xd7, 0x4f, 0x86, + 0x78, 0x49, 0xb9, 0x90, 0xf5, 0x8f, 0xec, 0x12, 0x84, 0x52, + 0x03, 0x1f, 0x64, 0x5e, 0xf0, 0x2a, 0xeb, 0x87, 0xa5, 0xec, + 0x95, 0x25, 0x64, 0x25, 0x49, 0x3b, 0x3c, 0x30, 0xed, 0x3b, + 0xe9, 0x36, 0xfd, 0xae, 0xa6, 0x26, 0xd3, 0x45, 0xbc, 0x1b, + 0x78, 0x5f, 0xce, 0x27, 0x45, 0x1c, 0xd5, 0xf9, 0xa7, 0xda, + 0x62, 0xe6, 0x7e, 0xd3, 0xbb, 0xd8, 0x0a, 0xfd, 0xf5, 0xa5, + 0x31, 0x09, 0x6e, 0x40, 0xe8, 0xcf, 0xc1, 0x42, 0x8e, 0x2e, + 0x75, 0x65, 0xaa, 0x91, 0x6f, 0xc7, 0x75, 0x3a, 0x1e, 0x40, + 0x99, 0x71, 0x5e, 0x00, 0xae, 0x07, 0xad, 0x43, 0x49, 0xdd, + 0x6d, 0x36, 0xe3, 0xa8, 0xdf, 0x2c, 0x39, 0xa2, 0x57, 0xd7, + 0x93, 0xa1, 0x16, 0x80, 0x89, 0xa6, 0x56, 0x69, 0x75, 0xea, + 0xb8, 0xb2, 0x43, 0x0c, 0xdf, 0x46, 0x05, 0x9a, 0x39, 0x08, + 0x3b, 0xb6, 0x76, 0xe3, 0x5b, 0x98, 0x5b, 0x48, 0xc0, 0x11, + 0x14, 0x6f, 0xcd, 0xb7, 0xaa, 0x08, 0x1e, 0x53, 0x9b, 0x94, + 0x9d, 0xa2, 0xe6, 0x99, 0xcb, 0x1c, 0xb4, 0xbf, 0x55, 0x84, + 0x12, 0xc9, 0xf1, 0xf0, 0x94, 0xd9, 0x7d, 0x61, 0xa9, 0xe7, + 0xe6, 0xc1, 0xe2, 0xca, 0x6b, 0x36, 0x80, 0x72, 0x31, 0x79, + 0xbf, 0xe7, 0x3e, 0x99, 0x9e, 0xd5, 0x59, 0xd4, 0x97, 0x14, + 0xd5, 0xfa, 0x93, 0x37, 0x8a, 0x65, 0xa5, 0xb6, 0x4e, 0xba, + 0xb3, 0x84, 0xf2, 0xc1, 0x55, 0xb6, 0x94, 0x31, 0x30, 0xe7, + 0xb2, 0x71, 0x4e, 0xc6, 0x21, 0x50, 0xf3, 0xcf, 0x7c, 0xbc, + 0x26, 0xb7, 0x20, 0xcb, 0x2d, 0x9e, 0x55, 0x23, 0x7c, 0xf0, + 0x97, 0x16, 0x57, 0x5b, 0xcc, 0xc5, 0x48, 0xc9, 0xc8, 0xee, + 0x1e, 0x11, 0x6b, 0x72, 0x3b, 0x29, 0x71, 0xa4, 0xed, 0x08, + 0x6c, 0x38, 0xc6, 0x2e, 0x64, 0x3b, 0x16, 0xd8, 0x4d, 0x19, + 0xe8, 0x94, 0xd3, 0xd5, 0xb4, 0x18, 0xb4, 0x03, 0x24, 0x62, + 0xe7, 0x44, 0x5e, 0x09, 0x60, 0xc6, 0xa9, 0xa6, 0xca, 0xbe, + 0x83, 0xe5, 0xf1, 0xbd, 0x04, 0x22, 0x4b, 0x1b, 0x08, 0x0b, + 0xa6, 0x20, 0x95, 0xf2, 0x78, 0x8c, 0x3e, 0x73, 0x03, 0x7b, + 0x75, 0x2c, 0xe5, 0x72, 0xec, 0xc9, 0x25, 0x06, 0x6b, 0x3a, + 0x5e, 0x0e, 0x96, 0xd0, 0xe3, 0x85, 0xb0, 0xb5, 0x6a, 0x83, + 0x40, 0x41, 0x94, 0xce, 0xa1, 0x07, 0x79, 0x07, 0xe2, 0x50, + 0xa4, 0xde, 0x7d, 0x64, 0x2f, 0x7e, 0x43, 0xd5, 0x72, 0xd1, + 0xa7, 0xb9, 0x76, 0xa3, 0xfc, 0x25, 0x33, 0xd7, 0x95, 0xb5, + 0xd9, 0x94, 0x93, 0x55, 0xaf, 0x04, 0x86, 0x4a, 0xfc, 0x2f, + 0x5f, 0x3d, 0x34, 0x86, 0xf2, 0x9a, 0x31, 0x4c, 0xc9, 0xad, + 0x08, 0xa5, 0x03, 0x91, 0x8a, 0x7e, 0x46, 0xc9, 0x44, 0x61, + 0x11, 0x59, 0x4f, 0xbb, 0x70, 0xf9, 0x9d, 0x3e, 0x6d, 0x53, + 0xb4, 0x16, 0x28, 0xd3, 0x67, 0x52, 0x14, 0xad, 0xba, 0xb1, + 0x21, 0xaf, 0x84, 0x18, 0xc9, 0x37, 0x78, 0xb3, 0x78, 0x92, + 0x95, 0xad, 0x1b, 0xc0, 0x70, 0xe7, 0xe9, 0x06, 0x02, 0xed, + 0x6c, 0x99, 0x4e, 0x43, 0xc0, 0xa4, 0x6f, 0x23, 0xa8, 0x02, + 0xc4, 0xbd, 0xc0, 0x16, 0xc4, 0xed, 0xe0, 0xe1, 0x56, 0x06, + 0x3f, 0xf4, 0x77, 0x12, 0x72, 0x52, 0x04, 0xe8, 0xe4, 0x26, + 0xe5, 0x01, 0x47, 0x5b, 0x8a, 0xca, 0x07, 0x3b, 0xc9, 0xb1, + 0x42, 0x8f, 0x7d, 0x64, 0x7d, 0x5d, 0x6a, 0x95, 0xde, 0x4d, + 0x4b, 0xd3, 0xfa, 0xcf, 0xf0, 0x25, 0x27, 0x96, 0x48, 0xb6, + 0xcc, 0x68, 0x29, 0x37, 0x95, 0xcd, 0x36, 0xb7, 0xb0, 0xd6, + 0xf1, 0xfc, 0x4f, 0xe9, 0xa8, 0x6b, 0x9d, 0x75, 0xc7, 0x9b, + 0x19, 0xaf, 0xbb, 0x8a, 0xaf, 0x4b, 0xb8, 0xe2, 0xeb, 0x8d, + 0xd9, 0xf5, 0x75, 0xc5, 0xc8, 0x0b, 0xf2, 0x1c, 0xf9, 0x9e, + 0xc7, 0x4d, 0x7c, 0x71, 0x47, 0xbd, 0x57, 0x7e, 0xe6, 0x59, + 0xca, 0x8c, 0xf2, 0x0c, 0x47, 0x4a, 0x90, 0xa7, 0xf5, 0xb8, + 0xb2, 0x43, 0x97, 0xdb, 0xbe, 0x76, 0x37, 0x29, 0x36, 0x40, + 0xaa, 0x7a, 0x81, 0xf0, 0xa0, 0xd0, 0x81, 0x39, 0x88, 0xf0, + 0x23, 0xb0, 0xa4, 0xbe, 0x5e, 0xd8, 0x33, 0x98, 0x5d, 0x9d, + 0xb5, 0xd4, 0x1c, 0x00, 0xe2, 0x30, 0xb8, 0x68, 0x58, 0x65, + 0x30, 0x94, 0x3d, 0xf2, 0x75, 0x0c, 0x8e, 0x3b, 0xee, 0x9b, + 0xce, 0x6c, 0x67, 0x68, 0x54, 0x86, 0x7d, 0x27, 0x2a, 0x2f, + 0xf7, 0x25, 0xff, 0x22, 0x1e, 0x74, 0xbd, 0x72, 0x11, 0xf4, + 0x47, 0x8e, 0x2f, 0x0d, 0xb9, 0x31, 0xac, 0x5c, 0x1d, 0xa0, + 0x11, 0xea, 0x16, 0x24, 0x86, 0x76, 0xbd, 0xa3, 0x41, 0x7f, + 0x00, 0xe6, 0xe2, 0x86, 0x93, 0xff, 0x02, 0x07, 0xce, 0x49, + 0xe4, 0xaf, 0x00, 0x9b, 0x15, 0xa6, 0x05, 0xf7, 0x54, 0xd1, + 0xbb, 0xa7, 0x09, 0x67, 0xe6, 0x99, 0xf9, 0x23, 0xe6, 0xaa, + 0x6f, 0xcb, 0xe1, 0xc1, 0xac, 0x7b, 0x98, 0xa9, 0x14, 0x43, + 0x55, 0x22, 0x2c, 0x7a, 0x4a, 0x4a, 0x63, 0xc1, 0xfe, 0x5c, + 0xca, 0xf4, 0x91, 0x3b, 0x6f, 0xf8, 0x7e, 0x2a, 0xa1, 0x4a, + 0xc3, 0x16, 0x1c, 0x1d, 0x53, 0x7d, 0x0e, 0x77, 0x0d, 0x72, + 0x07, 0x78, 0xea, 0xce, 0xe4, 0x0c, 0xf7, 0xce, 0xa0, 0xef, + 0xa1, 0xdb, 0x6b, 0x5f, 0xfd, 0xeb, 0x68, 0xc7, 0x76, 0xfd, + 0x35, 0xd2, 0xcb, 0xa4, 0xf6, 0xe6, 0x6b, 0xdb, 0xe9, 0xd5, + 0x1e, 0x05, 0x8a, 0xba, 0xed, 0x77, 0x94, 0x36, 0x6c, 0x3c, + 0xe2, 0x23, 0xf8, 0x84, 0xa1, 0xe3, 0xcd, 0xfa, 0x1d, 0x31, + 0x52, 0x4d, 0xbc, 0x16, 0x31, 0x92, 0xd7, 0xbe, 0x2e, 0xd6, + 0x6d, 0x1d, 0x58, 0x4e, 0xd8, 0x06, 0x8f, 0xb3, 0xe6, 0x79, + 0x60, 0x92, 0x71, 0x1f, 0x72, 0x84, 0x55, 0x7b, 0xfa, 0xc8, + 0xcf, 0x20, 0x16, 0x2f, 0xc7, 0x13, 0x17, 0xd1, 0x2d, 0xd1, + 0x0d, 0x84, 0x48, 0x08, 0x69, 0xd1, 0x55, 0xb1, 0x08, 0xb6, + 0x17, 0x8c, 0x38, 0x31, 0xa4, 0x77, 0x73, 0xc0, 0xe9, 0xfc, + 0x5f, 0x8e, 0xb3, 0x74, 0x1f, 0xab, 0xcf, 0xf5, 0x26, 0x26, + 0x20, 0x80, 0xd8, 0x13, 0x42, 0xcf, 0xc7, 0x9d, 0xd6, 0x5b, + 0x1a, 0xfd, 0x46, 0x83, 0xba, 0xc1, 0xe5, 0x92, 0xe9, 0x27, + 0xa8, 0xa0, 0x36, 0xd5, 0x31, 0x75, 0x7b, 0x8f, 0x53, 0xf6, + 0xbd, 0x08, 0x1a, 0x86, 0x81, 0x83, 0x85, 0x07, 0x44, 0x3e, + 0xf9, 0x72, 0x47, 0xe0, 0xf1, 0xbe, 0x43, 0x6a, 0xc3, 0x00, + 0x94, 0xd3, 0x19, 0x81, 0xde, 0xf3, 0xfd, 0x57, 0x98, 0xdc, + 0x57, 0xfe, 0x9f, 0x4b, 0x38, 0x23, 0xad, 0xa8, 0xd4, 0x07, + 0x07, 0x5c, 0xca, 0x25, 0xb8, 0x77, 0x7e, 0x45, 0x01, 0x9b, + 0xd4, 0x45, 0x5b, 0x94, 0x47, 0x18, 0x35, 0x66, 0xad, 0x0a, + 0x97, 0x06, 0xc6, 0xa7, 0xaa, 0x50, 0xbf, 0x07, 0x90, 0xfe, + 0x50, 0x8d, 0xd9, 0x1f, 0xdd, 0x33, 0xa4, 0xa7, 0x23, 0x48, + 0xa3, 0xd6, 0x5d, 0xb8, 0x9e, 0x97, 0x22, 0x32, 0xd3, 0x8a, + 0xb0, 0x5e, 0xb3, 0xc9, 0x0b, 0x24, 0x09, 0x66, 0x2e, 0xea, + 0x94, 0x9c, 0x90, 0x4f, 0x3e, 0x93, 0xcf, 0x30, 0x3f, 0xb4, + 0xbe, 0x5e, 0x6c, 0xaf, 0x1a, 0xff, 0x00, 0xc7, 0x74, 0x2e, + 0x8b, 0x08, 0xe9, 0x22, 0x61, 0xc5, 0xd1, 0x21, 0x15, 0xa1, + 0xba, 0x37, 0xd2, 0x24, 0xfd, 0xa5, 0x63, 0x9a, 0x97, 0xfa, + 0xfe, 0xb2, 0xa5, 0x1b, 0x3b, 0xbd, 0xb7, 0xb3, 0x2f, 0x3d, + 0xf1, 0x5a, 0xf2, 0xf6, 0xe4, 0x12, 0xe4, 0x3a, 0x26, 0x3c, + 0x21, 0x5c, 0xd6, 0x83, 0x65, 0x26, 0x86, 0xcc, 0x47, 0x84, + 0xd7, 0x26, 0x31, 0x31, 0xcf, 0x1d, 0xd6, 0xc4, 0xa4, 0xf2, + 0xd4, 0x25, 0x54, 0x2b, 0x81, 0x00, 0x1d, 0xd8, 0xdf, 0x04, + 0xb8, 0x4b, 0xcf, 0xe5, 0x16, 0xf4, 0x4a, 0x17, 0xc5, 0xd8, + 0xd3, 0xdf, 0xe4, 0xb7, 0xd3, 0x98, 0xb6, 0x73, 0xa0, 0x37, + 0x67, 0xbb, 0x8b, 0xc3, 0xfc, 0xac, 0x6e, 0x6c, 0x0e, 0x5d, + 0x44, 0xb0, 0x9d, 0xf8, 0xae, 0x17, 0x9b, 0xf9, 0xcb, 0xe8, + 0xfe, 0xc1, 0x7b, 0x78, 0x16, 0xf6, 0x74, 0x04, 0x7d, 0x38, + 0x17, 0x36, 0x09, 0xe3, 0x73, 0xa1, 0x76, 0x78, 0x7c, 0x14, + 0xb3, 0x83, 0x91, 0x59, 0x27, 0xea, 0x8c, 0x69, 0xe6, 0xa5, + 0x21, 0xcd, 0x78, 0xc7, 0x26, 0xa2, 0xfb, 0xd4, 0xf3, 0xaf, + 0x3f, 0xcf, 0x51, 0x10, 0xcc, 0x4b, 0xdd, 0x14, 0xf4, 0xf3, + 0xb8, 0xea, 0x07, 0xa7, 0x76, 0xe7, 0xbe, 0xec, 0x01, 0xb5, + 0x1e, 0xdc, 0xc3, 0x55, 0x19, 0xb1, 0x16, 0x3f, 0xfe, 0xd4, + 0x15, 0x49, 0xaf, 0x04, 0x9d, 0x38, 0xdd, 0x86, 0x53, 0x2a, + 0x80, 0x62, 0x42, 0xb7, 0x98, 0x42, 0x38, 0xaf, 0x9d, 0x87, + 0xe2, 0x3f, 0xea, 0x7e, 0x0a, 0x35, 0xb8, 0xee, 0xa5, 0x48, + 0x09, 0x08, 0xc5, 0x0d, 0xae, 0x01, 0xd5, 0xec, 0x43, 0x29, + 0x3b, 0xfb, 0x78, 0xc4, 0x96, 0x01, 0x1c, 0x21, 0xf2, 0xc9, + 0x44, 0x68, 0x24, 0x66, 0x86, 0x96, 0xb8, 0xc8, 0xe9, 0xd0, + 0x38, 0x0e, 0x96, 0x4d, 0xcc, 0x45, 0xab, 0xe1, 0xca, 0x50, + 0x10, 0x20, 0x01, 0xbe, 0x89, 0xc0, 0x43, 0x84, 0xd8, 0x38, + 0x52, 0xc0, 0xaf, 0x4d, 0x6b, 0x99, 0x0b, 0xc0, 0xc2, 0x99, + 0x07, 0xc6, 0x78, 0xa8, 0xf7, 0x32, 0x84, 0x86, 0xc5, 0x1a, + 0x95, 0x81, 0xa6, 0x6a, 0x05, 0xa7, 0x9d, 0x81, 0x0e, 0x32, + 0x18, 0x11, 0x4a, 0x0f, 0xfc, 0x17, 0x9e, 0xf7, 0xbf, 0x54, + 0x82, 0xed, 0xba, 0x6f, 0xbd, 0x41, 0xc1, 0xca, 0x55, 0x6c, + 0xff, 0x32, 0x6b, 0xa2, 0x59, 0xae, 0xae, 0x92, 0xc1, 0xb5, + 0xa6, 0xfc, 0xaf, 0x09, 0x48, 0x57, 0xd6, 0xee, 0x38, 0x99, + 0xb4, 0xe3, 0x8f, 0xb7, 0xfc, 0x6a, 0x0a, 0x3b, 0x08, 0xe1, + 0x81, 0x46, 0x11, 0xeb, 0x4a, 0x98, 0x43, 0x16, 0x16, 0x1f, + 0x68, 0xdb, 0xb9, 0x71, 0x19, 0xfe, 0x8b, 0xe6, 0xb7, 0x8b, + 0xc1, 0x3b, 0x90, 0xc5, 0x89, 0x1d, 0xca, 0xd9, 0x19, 0x6c, + 0xe8, 0x01, 0xf4, 0x19, 0x50, 0x3e, 0x93, 0x84, 0xbf, 0xaa, + 0x9a, 0x3d, 0x20, 0x4c, 0x4e, 0x79, 0x83, 0xec, 0x46, 0x83, + 0x09, 0x00, 0xc3, 0x8a, 0xad, 0xd5, 0x2b, 0x08, 0xd1, 0x47, + 0xac, 0x96, 0x0e, 0x34, 0xf0, 0x89, 0x1a, 0x0f, 0xf2, 0x51, + 0x8d, 0x2c, 0xb5, 0xf2, 0xfe, 0x8c, 0xdc, 0xed, 0x41, 0x51, + 0x8c, 0x71, 0x12, 0x05, 0xec, 0x68, 0x21, 0x86, 0x94, 0xf4, + 0xfb, 0xfc, 0xaa, 0xc7, 0xc7, 0xbb, 0x74, 0xa2, 0x8b, 0x76, + 0x62, 0x1c, 0x64, 0x11, 0xa0, 0xd0, 0x5f, 0x46, 0x64, 0xd4, + 0x47, 0xbc, 0x8a, 0x5b, 0x2b, 0xc2, 0xc1, 0x88, 0xb2, 0x30, + 0xbd, 0x02, 0x17, 0x18, 0x0a, 0xd7, 0x9b, 0x3d, 0x91, 0xb9, + 0x2c, 0x83, 0x24, 0xb4, 0x8b, 0x9d, 0x02, 0xaf, 0xb2, 0x4e, + 0x57, 0xe1, 0xb0, 0xa2, 0xf3, 0x7c, 0xde, 0x15, 0xba, 0x60, + 0xbd, 0x80, 0xbe, 0x6d, 0x6f, 0x16, 0xb3, 0xb9, 0xb8, 0x6a, + 0x55, 0xb4, 0xad, 0xf1, 0x01, 0x63, 0x40, 0x01, 0xba, 0x5b, + 0x5d, 0x9a, 0xbc, 0xf0, 0x58, 0xa8, 0xf7, 0xbb, 0x8e, 0x91, + 0xa0, 0xfd, 0x8c, 0x49, 0x8f, 0x1a, 0xbb, 0x2a, 0x28, 0x0d, + 0x7a, 0xa6, 0xc2, 0xd7, 0x41, 0x16, 0xed, 0x61, 0x5d, 0xc4, + 0xe7, 0xcf, 0x2b, 0xb4, 0xb9, 0x10, 0x6f, 0x38, 0x42, 0x88, + 0x94, 0x6e, 0x75, 0x2c, 0x89, 0xac, 0xa0, 0xe9, 0x81, 0xec, + 0x2d, 0x62, 0xa3, 0xba, 0x3c, 0x40, 0xdb, 0x65, 0x56, 0x8e, + 0xc7, 0xd8, 0xb0, 0xd4, 0xf9, 0x04, 0x2b, 0x4c, 0x83, 0x20, + 0xbe, 0xad, 0xb8, 0x66, 0x1c, 0x20, 0x32, 0xb3, 0xf6, 0xf1, + 0xac, 0xa5, 0x8a, 0x72, 0x9a, 0x41, 0x1d, 0x6e, 0xa0, 0x16, + 0xe0, 0x0c, 0x39, 0xb6, 0x06, 0x96, 0x55, 0xb7, 0xda, 0x1c, + 0x54, 0x08, 0xf6, 0x30, 0x1b, 0xb6, 0x57, 0xca, 0x7d, 0xb0, + 0xdc, 0x9e, 0xfa, 0x5c, 0x38, 0x7f, 0xac, 0x37, 0x80, 0x26, + 0xba, 0xdc, 0x7a, 0x95, 0xe5, 0x7b, 0x90, 0xf3, 0x1a, 0xc7, + 0x31, 0x8e, 0x97, 0x07, 0x9a, 0xb8, 0xbe, 0xae, 0x16, 0x11, + 0x44, 0xb0, 0x01, 0xf5, 0xe8, 0x37, 0x1a, 0x67, 0xfe, 0x00, + 0x8f, 0xa1, 0xf5, 0x03, 0x7c, 0xed, 0xbf, 0x42, 0xf4, 0x78, + 0x2b, 0xfb, 0x9f, 0x8c, 0xb3, 0x63, 0x0b, 0x42, 0xbf, 0xae, + 0x8e, 0xf7, 0x6f, 0xb4, 0xb1, 0xe8, 0x75, 0x8c, 0xdf, 0x69, + 0xc6, 0xe1, 0x3a, 0x26, 0x05, 0x47, 0x03, 0x61, 0xfc, 0xc5, + 0xa9, 0xc1, 0x4f, 0x70, 0xce, 0x18, 0xbb, 0x01, 0xe6, 0x11, + 0xc9, 0xa7, 0x7e, 0x65, 0xb8, 0xdc, 0x61, 0x3d, 0x9b, 0x47, + 0x2e, 0x34, 0x16, 0xa1, 0x73, 0x61, 0x91, 0xed, 0x45, 0xe3, + 0x01, 0x26, 0xee, 0x16, 0x76, 0x0e, 0xb7, 0xa1, 0xc0, 0xb3, + 0xac, 0xf0, 0xa5, 0x3b, 0xf6, 0x64, 0x1b, 0x93, 0x94, 0x5c, + 0x8f, 0x4c, 0x25, 0x89, 0xa1, 0x92, 0x32, 0x50, 0x28, 0x03, + 0x8b, 0xff, 0xc4, 0xf6, 0x2a, 0xe8, 0xda, 0x8d, 0xfe, 0x49, + 0xb5, 0x33, 0x01, 0xca, 0x2d, 0x2d, 0x60, 0x33, 0xd6, 0x30, + 0x38, 0x8a, 0x1e, 0x38, 0x3d, 0x78, 0x11, 0xff, 0xef, 0x1c, + 0x82, 0x33, 0xbb, 0xfc, 0x95, 0xef, 0x79, 0xb0, 0x59, 0xbd, + 0x2c, 0xfd, 0x1c, 0x3f, 0x42, 0xda, 0xdf, 0xbd, 0x56, 0xf2, + 0xd6, 0xae, 0x2d, 0x23, 0x36, 0xed, 0xb1, 0x8d, 0x62, 0x58, + 0x71, 0x66, 0x21, 0xe0, 0x4d, 0xee, 0xf4, 0x16, 0x48, 0xa6, + 0xcf, 0x1a, 0x8a, 0xf0, 0x8a, 0xd1, 0x53, 0xf6, 0xe5, 0x4e, + 0x98, 0x9d, 0x7d, 0x6c, 0xd2, 0xdf, 0xb8, 0x2d, 0xa6, 0xe5, + 0x8a, 0xd6, 0xb5, 0xae, 0x61, 0x96, 0xfa, 0x6b, 0xca, 0x7f, + 0x08, 0xc2, 0x2b, 0x67, 0x30, 0x5e, 0x21, 0x3b, 0xa4, 0x84, + 0x95, 0xc6, 0x2f, 0x2c, 0x1f, 0xe2, 0x0e, 0x1a, 0xc3, 0x89, + 0x6a, 0x6a, 0xe7, 0x08, 0xf9, 0x74, 0xee, 0x4f, 0xcd, 0x5e, + 0xe8, 0xce, 0x55, 0x4d, 0x38, 0xed, 0x62, 0x35, 0xee, 0xfc, + 0x14, 0x56, 0xb9, 0xf0, 0xce, 0x29, 0x1c, 0x21, 0x40, 0x51, + 0xe4, 0x76, 0xe3, 0xa6, 0xd8, 0x3d, 0x54, 0x58, 0x51, 0xe5, + 0xf0, 0xdc, 0x50, 0x39, 0x43, 0x67, 0x44, 0x14, 0xcc, 0x6e, + 0x5a, 0xb1, 0x15, 0xec, 0xb4, 0x3e, 0x0e, 0xef, 0x8e, 0x72, + 0x6a, 0xdf, 0xba, 0x37, 0x27, 0x15, 0x62, 0xc3, 0xbd, 0xee, + 0x1d, 0xb1, 0x24, 0x2f, 0x57, 0x51, 0xf1, 0x8f, 0xfb, 0xd1, + 0x10, 0x6f, 0x11, 0xb9, 0x94, 0x5c, 0x9c, 0x12, 0x26, 0x46, + 0x46, 0x7b, 0x31, 0x0e, 0xad, 0x93, 0xe4, 0x4f, 0x09, 0xe3, + 0xbf, 0xc5, 0xe3, 0x11, 0xa4, 0x25, 0x8d, 0x9b, 0x8e, 0x26, + 0x02, 0xaa, 0x72, 0x18, 0xce, 0x89, 0x67, 0xfc, 0x1c, 0x28, + 0xab, 0x11, 0x5a, 0x84, 0x23, 0x7c, 0x91, 0xac, 0x6b, 0x48, + 0x9c, 0x39, 0x14, 0xa3, 0xac, 0xc6, 0x30, 0xbc, 0x1e, 0x0c, + 0xd3, 0x34, 0x19, 0xa9, 0x2b, 0xe7, 0xa4, 0xf8, 0xc1, 0xf0, + 0x3c, 0x60, 0xa2, 0xf7, 0x51, 0x86, 0xcf, 0x42, 0xad, 0x34, + 0x81, 0xa6, 0x93, 0x0b, 0x88, 0x4c, 0xbf, 0xd2, 0x4f, 0xe0, + 0xdb, 0xb2, 0x1d, 0x6d, 0xb2, 0x5c, 0xac, 0xd8, 0x64, 0x85, + 0xc3, 0x35, 0x6e, 0x5d, 0xaf, 0x63, 0x3e, 0x47, 0xb7, 0x5d, + 0x39, 0x21, 0x36, 0xa6, 0xd4, 0xef, 0x9e, 0x1c, 0x1f, 0xd6, + 0xa4, 0xe0, 0xe4, 0x22, 0x75, 0x1e, 0xeb, 0x15, 0xb4, 0xee, + 0x43, 0x37, 0x06, 0xf9, 0x77, 0xbf, 0x68, 0x9b, 0x9a, 0x7f, + 0x38, 0x30, 0x87, 0xde, 0x0c, 0x6a, 0x39, 0x41, 0xe1, 0xed, + 0xf4, 0x18, 0x6e, 0x29, 0x44, 0xf0, 0xfc, 0xb6, 0x09, 0x5b, + 0xb3, 0x30, 0xc9, 0x0a, 0x8c, 0x41, 0x6f, 0x1e, 0x95, 0xbe, + 0x93, 0x3c, 0x11, 0x9b, 0x24, 0xf7, 0x57, 0xb8, 0xc5, 0x9b, + 0x08, 0xaa, 0xcd, 0x24, 0x86, 0x98, 0x59, 0x0f, 0xc6, 0x0e, + 0xd2, 0x71, 0xb2, 0x5e, 0xae, 0x72, 0xc9, 0x69, 0x3b, 0x80, + 0xc2, 0x27, }; static const int sizeof_bench_dilithium_level3_key = sizeof(bench_dilithium_level3_key); -/* certs/dilithium/bench_dilithium_level5_key.der */ -static const unsigned char bench_dilithium_level5_key[] = -{ - 0x30, 0x82, 0x1D, 0x3A, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, - 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x02, 0x82, 0x0B, 0x07, - 0x08, 0x07, 0x04, 0x82, 0x1D, 0x24, 0x04, 0x82, 0x1D, 0x20, - 0x0A, 0xDB, 0x85, 0x3A, 0x41, 0x2C, 0x30, 0x56, 0x65, 0x04, - 0x0A, 0x20, 0x31, 0x2A, 0xF3, 0x88, 0x4C, 0x38, 0x64, 0x86, - 0x14, 0x06, 0xF5, 0xF0, 0x7F, 0x63, 0xC1, 0x87, 0x24, 0x39, - 0xFB, 0xC0, 0x28, 0x0C, 0xBE, 0x81, 0xF7, 0xCD, 0x25, 0x8B, - 0x86, 0x42, 0xAD, 0x74, 0x54, 0xCB, 0xA4, 0xDA, 0xC7, 0x94, - 0x70, 0xA3, 0x41, 0xDA, 0x1F, 0xD8, 0x4F, 0x94, 0x5C, 0x0B, - 0xA5, 0x35, 0x60, 0xB2, 0x8C, 0x50, 0xED, 0x0B, 0xCB, 0x75, - 0x6F, 0x14, 0x64, 0x48, 0x86, 0x21, 0xBC, 0x4A, 0x4C, 0xC5, - 0x22, 0xBC, 0x2D, 0x28, 0x32, 0x39, 0x13, 0x57, 0xC9, 0xE5, - 0x74, 0xF4, 0xE6, 0x3A, 0xC2, 0xE2, 0x49, 0x24, 0x31, 0x88, - 0x82, 0x08, 0x03, 0x89, 0x6C, 0x8B, 0x84, 0x08, 0x81, 0xC2, - 0x08, 0xDB, 0x44, 0x60, 0xA0, 0xB2, 0x91, 0x88, 0x36, 0x28, - 0x12, 0x89, 0x89, 0x4B, 0xA4, 0x01, 0x62, 0x12, 0x4C, 0x08, - 0x02, 0x44, 0x19, 0x15, 0x64, 0x8B, 0x04, 0x65, 0xE4, 0x14, - 0x06, 0x08, 0xC7, 0x04, 0x5B, 0x28, 0x81, 0x89, 0xC2, 0x70, - 0xD0, 0xB4, 0x71, 0x4C, 0x24, 0x80, 0xA1, 0x28, 0x86, 0xD1, - 0x06, 0x25, 0x13, 0x03, 0x84, 0x8C, 0x18, 0x41, 0x49, 0x34, - 0x09, 0xCB, 0x22, 0x71, 0x0C, 0xA3, 0x90, 0x22, 0x94, 0x51, - 0x58, 0x02, 0x2D, 0x53, 0x30, 0x00, 0xC2, 0x06, 0x42, 0x48, - 0xC4, 0x70, 0x8A, 0x32, 0x89, 0x80, 0x16, 0x06, 0x90, 0x44, - 0x91, 0xCB, 0xC8, 0x71, 0xA2, 0xB6, 0x64, 0xD0, 0x26, 0x0A, - 0x21, 0x05, 0x88, 0x0C, 0xB0, 0x6C, 0x03, 0x49, 0x24, 0x80, - 0x02, 0x11, 0xD1, 0x36, 0x06, 0x84, 0x32, 0x11, 0x81, 0x44, - 0x91, 0x9B, 0xB0, 0x01, 0x91, 0x02, 0x25, 0x44, 0x92, 0x69, - 0x5A, 0x08, 0x6C, 0x90, 0x00, 0x0D, 0x09, 0x17, 0x64, 0x89, - 0xB2, 0x2D, 0x02, 0x06, 0x2C, 0xDC, 0x92, 0x45, 0xE1, 0x34, - 0x31, 0x11, 0x03, 0x2D, 0x00, 0x94, 0x29, 0xCA, 0x34, 0x89, - 0xA3, 0x40, 0x22, 0xC4, 0x30, 0x08, 0x02, 0x33, 0x6E, 0x1C, - 0x85, 0x10, 0xE4, 0x92, 0x30, 0xC4, 0x46, 0x84, 0xE0, 0x26, - 0x28, 0xC3, 0x10, 0x65, 0x51, 0x06, 0x4A, 0x03, 0xC1, 0x11, - 0x48, 0x32, 0x4E, 0x9A, 0xC4, 0x6C, 0x91, 0x38, 0x40, 0xC0, - 0x92, 0x64, 0xE3, 0xA4, 0x85, 0x22, 0x32, 0x52, 0x92, 0x08, - 0x20, 0x82, 0x22, 0x12, 0x49, 0x20, 0x6C, 0x91, 0x06, 0x01, - 0x1B, 0x30, 0x06, 0x12, 0xC3, 0x41, 0x4B, 0x40, 0x42, 0x0B, - 0xA7, 0x01, 0x60, 0x12, 0x89, 0x24, 0x98, 0x30, 0x99, 0xA6, - 0x64, 0x61, 0x26, 0x6A, 0x91, 0xB0, 0x11, 0x03, 0xC2, 0x2D, - 0x41, 0xC8, 0x6D, 0xD8, 0x38, 0x28, 0x4B, 0x98, 0x04, 0x98, - 0x18, 0x09, 0x18, 0xA6, 0x65, 0x81, 0x38, 0x69, 0x5B, 0xC4, - 0x6D, 0x98, 0x26, 0x0D, 0x62, 0xC6, 0x71, 0xC3, 0xC6, 0x4C, - 0xC2, 0x02, 0x46, 0x5B, 0x94, 0x65, 0x09, 0x29, 0x0E, 0xA2, - 0xA2, 0x41, 0xE4, 0x02, 0x69, 0xA3, 0x90, 0x4D, 0x8B, 0xA6, - 0x70, 0xA3, 0x40, 0x85, 0x5C, 0x36, 0x48, 0x22, 0xC5, 0x84, - 0x19, 0x91, 0x25, 0x00, 0xC2, 0x65, 0xC4, 0x46, 0x2E, 0xDC, - 0xB0, 0x51, 0x94, 0x28, 0x01, 0x9B, 0x22, 0x66, 0x01, 0xA8, - 0x90, 0x9A, 0xC4, 0x08, 0xD1, 0x22, 0x41, 0x42, 0x34, 0x62, - 0x60, 0x40, 0x92, 0x93, 0xC8, 0x45, 0xD8, 0x04, 0x20, 0x8A, - 0x30, 0x25, 0xE1, 0x14, 0x40, 0x11, 0x13, 0x00, 0x54, 0x22, - 0x62, 0x50, 0x10, 0x22, 0x03, 0xA9, 0x85, 0x9B, 0x42, 0x4D, - 0x50, 0xB2, 0x41, 0x10, 0x13, 0x48, 0x63, 0x38, 0x68, 0xA1, - 0xB0, 0x0D, 0x1B, 0x88, 0x84, 0x8A, 0x28, 0x51, 0xD4, 0x38, - 0x2A, 0x12, 0x43, 0x61, 0x80, 0x38, 0x32, 0x18, 0xC6, 0x29, - 0x22, 0xB5, 0x21, 0x02, 0x99, 0x28, 0xCC, 0x18, 0x85, 0x83, - 0xB4, 0x8C, 0x81, 0x24, 0x51, 0x10, 0x83, 0x68, 0x1C, 0x47, - 0x71, 0x8C, 0x40, 0x6C, 0x00, 0xB6, 0x0D, 0x88, 0x22, 0x90, - 0x0C, 0xC7, 0x49, 0xC0, 0x82, 0x89, 0xDA, 0x22, 0x4A, 0xC8, - 0x18, 0x08, 0xD1, 0x00, 0x2C, 0xDA, 0x30, 0x49, 0x49, 0xC8, - 0x91, 0x5A, 0x96, 0x64, 0x11, 0x96, 0x20, 0xD2, 0xC4, 0x60, - 0xE0, 0x46, 0x6A, 0x02, 0xB5, 0x21, 0x19, 0xB9, 0x81, 0x23, - 0x00, 0x22, 0x11, 0x37, 0x32, 0x19, 0xA4, 0x0D, 0x51, 0x96, - 0x89, 0x1B, 0x11, 0x11, 0xC3, 0x14, 0x88, 0x4C, 0x96, 0x0C, - 0x01, 0x13, 0x72, 0x83, 0x16, 0x12, 0x24, 0x38, 0x51, 0x40, - 0x34, 0x89, 0xD9, 0x26, 0x01, 0x54, 0x42, 0x8D, 0x00, 0xC1, - 0x85, 0x13, 0x14, 0x84, 0x82, 0x16, 0x25, 0x88, 0xB0, 0x51, - 0x11, 0x80, 0x30, 0x23, 0x25, 0x46, 0x04, 0x27, 0x66, 0x11, - 0x28, 0x30, 0xD4, 0x94, 0x84, 0x10, 0xA0, 0x8C, 0xC1, 0x36, - 0x0C, 0x14, 0x98, 0x28, 0x5B, 0x02, 0x90, 0xD9, 0x90, 0x31, - 0xD3, 0x28, 0x68, 0x23, 0x90, 0x80, 0x24, 0xC7, 0x84, 0xA1, - 0x00, 0x09, 0xC1, 0x36, 0x84, 0x58, 0xB6, 0x28, 0x4A, 0xB0, - 0x69, 0x08, 0x10, 0x51, 0x1C, 0xB6, 0x84, 0x83, 0x84, 0x81, - 0x03, 0x39, 0x90, 0x81, 0x42, 0x12, 0x13, 0xB4, 0x49, 0x0A, - 0x20, 0x09, 0x93, 0x22, 0x42, 0xD4, 0x26, 0x21, 0xA3, 0x32, - 0x89, 0x89, 0x84, 0x81, 0x0B, 0x02, 0x21, 0x64, 0x28, 0x90, - 0x89, 0xB2, 0x29, 0xE1, 0x36, 0x2C, 0x11, 0x30, 0x51, 0x21, - 0x83, 0x2C, 0x04, 0x36, 0x26, 0x61, 0x12, 0x8C, 0x19, 0x43, - 0x52, 0x89, 0x90, 0x88, 0x43, 0xB8, 0x71, 0x0C, 0x43, 0x09, - 0x84, 0x26, 0x6A, 0x50, 0x36, 0x20, 0x00, 0xC3, 0x68, 0x91, - 0x38, 0x0E, 0x12, 0x12, 0x52, 0x82, 0xC4, 0x4D, 0x64, 0x90, - 0x4D, 0x8C, 0x30, 0x22, 0x14, 0x26, 0x6E, 0x10, 0x46, 0x8E, - 0x58, 0x34, 0x46, 0x22, 0x97, 0x68, 0x02, 0x43, 0x61, 0x41, - 0x06, 0x01, 0x88, 0x42, 0x40, 0x08, 0x06, 0x6D, 0x80, 0x42, - 0x22, 0x84, 0x48, 0x89, 0xDB, 0x84, 0x90, 0xC0, 0x22, 0x71, - 0x43, 0x96, 0x45, 0x0A, 0xA3, 0x30, 0x12, 0x28, 0x44, 0x51, - 0x00, 0x52, 0x99, 0xA0, 0x8D, 0xC2, 0x28, 0x00, 0xC8, 0x18, - 0x6E, 0xA2, 0x40, 0x8E, 0x03, 0x47, 0x31, 0x61, 0x22, 0x41, - 0xD3, 0xB4, 0x01, 0x48, 0x14, 0x40, 0x4C, 0x06, 0x0C, 0x41, - 0x06, 0x2A, 0x5B, 0x90, 0x25, 0xCC, 0xC6, 0x41, 0xC3, 0x86, - 0x28, 0x99, 0x26, 0x50, 0x11, 0xC4, 0x8D, 0x8C, 0x30, 0x68, - 0x8C, 0x08, 0x0C, 0x50, 0x38, 0x86, 0xDC, 0x10, 0x92, 0xD4, - 0x18, 0x72, 0x02, 0xA8, 0x2C, 0x42, 0x82, 0x44, 0x53, 0x36, - 0x0E, 0x90, 0x32, 0x49, 0x84, 0x24, 0x09, 0x12, 0xA2, 0x41, - 0x82, 0x10, 0x4D, 0x01, 0xA0, 0x8C, 0x11, 0xB2, 0x80, 0x21, - 0x89, 0x69, 0x24, 0x21, 0x28, 0x02, 0x03, 0x6E, 0x49, 0x32, - 0x0C, 0x08, 0x88, 0x84, 0x91, 0x80, 0x10, 0x0C, 0x33, 0x12, - 0x43, 0x24, 0x8A, 0x82, 0x26, 0x10, 0x60, 0xC6, 0x60, 0x48, - 0xA2, 0x10, 0x12, 0x83, 0x24, 0x0B, 0x03, 0x40, 0xCA, 0x08, - 0x20, 0x99, 0x36, 0x86, 0x5B, 0x24, 0x41, 0x10, 0x87, 0x04, - 0x0C, 0x15, 0x04, 0x14, 0xB2, 0x68, 0x0B, 0x89, 0x29, 0x99, - 0x16, 0x8D, 0x00, 0x42, 0x00, 0x9B, 0x48, 0x44, 0x12, 0x45, - 0x6C, 0x0A, 0x25, 0x92, 0xC0, 0xC4, 0x00, 0x1A, 0xC8, 0x31, - 0x21, 0x26, 0x8A, 0x81, 0xA0, 0x2C, 0x11, 0x85, 0x65, 0x9A, - 0x08, 0x61, 0xD9, 0x22, 0x12, 0xCB, 0x36, 0x71, 0xA2, 0x08, - 0x0A, 0xE4, 0x06, 0x32, 0x19, 0x19, 0x4A, 0x1B, 0x34, 0x45, - 0x51, 0x06, 0x6E, 0x48, 0x02, 0x68, 0x13, 0xB7, 0x10, 0x44, - 0xC8, 0x85, 0x13, 0x81, 0x2C, 0xC4, 0x40, 0x45, 0x42, 0x98, - 0x21, 0x62, 0x18, 0x92, 0x9B, 0x44, 0x25, 0xA1, 0x06, 0x28, - 0x52, 0x82, 0x11, 0x44, 0x24, 0x32, 0x02, 0xC6, 0x80, 0x10, - 0x45, 0x4E, 0x22, 0x93, 0x0D, 0x44, 0x02, 0x68, 0x4A, 0x30, - 0x81, 0xC9, 0x94, 0x85, 0x08, 0x07, 0x08, 0x24, 0x39, 0x64, - 0xD2, 0x08, 0x22, 0xD0, 0xA0, 0x41, 0x81, 0x92, 0x91, 0x8C, - 0x24, 0x6A, 0xCA, 0x36, 0x32, 0x1C, 0x12, 0x45, 0x92, 0x94, - 0x80, 0x82, 0x86, 0x4C, 0xDA, 0xA2, 0x84, 0x98, 0x24, 0x49, - 0x0A, 0x13, 0x90, 0x1B, 0xC3, 0x01, 0x49, 0x28, 0x60, 0x08, - 0x21, 0x92, 0x0B, 0xB0, 0x20, 0x52, 0x90, 0x84, 0x8A, 0x32, - 0x11, 0x50, 0x28, 0x8C, 0x5B, 0x38, 0x2E, 0xDC, 0xB4, 0x08, - 0x12, 0x20, 0x84, 0xD1, 0x12, 0x22, 0x99, 0x08, 0x11, 0x19, - 0x95, 0x10, 0x80, 0x44, 0x6A, 0xE1, 0x12, 0x85, 0xCC, 0xB0, - 0x24, 0x23, 0x15, 0x4C, 0x63, 0x34, 0x68, 0x5C, 0xB6, 0x65, - 0x42, 0xC2, 0x4D, 0x20, 0x95, 0x84, 0x8A, 0x42, 0x00, 0x4C, - 0x24, 0x50, 0x98, 0x02, 0x6C, 0x21, 0x44, 0x84, 0x20, 0x85, - 0x21, 0x80, 0x48, 0x6C, 0x9C, 0x14, 0x86, 0x81, 0x86, 0x91, - 0x1C, 0x09, 0x04, 0xDC, 0xC6, 0x28, 0x09, 0x27, 0x30, 0x4B, - 0x02, 0x64, 0x44, 0x46, 0x30, 0x9C, 0xA2, 0x8C, 0x20, 0x11, - 0x68, 0x11, 0x24, 0x51, 0x0B, 0x02, 0x00, 0xD2, 0x82, 0x4D, - 0xC3, 0x80, 0x71, 0xE0, 0x48, 0x2C, 0x4A, 0x88, 0x50, 0xA0, - 0x20, 0x49, 0x4B, 0xB4, 0x31, 0x08, 0x12, 0x71, 0x90, 0xA2, - 0x89, 0xCA, 0x46, 0x85, 0x91, 0x96, 0x91, 0x8A, 0x30, 0x31, - 0x0B, 0xC2, 0x21, 0x61, 0x10, 0x49, 0x10, 0x99, 0x81, 0x53, - 0x36, 0x0C, 0x23, 0x81, 0x88, 0x62, 0x28, 0x0A, 0x12, 0x43, - 0x70, 0x02, 0xC7, 0x51, 0x14, 0x34, 0x88, 0x23, 0x84, 0x49, - 0x23, 0x86, 0x08, 0x0C, 0x28, 0x28, 0x94, 0xA0, 0x8D, 0x11, - 0x33, 0x60, 0xA3, 0x38, 0x6E, 0xC0, 0x42, 0x2E, 0x52, 0xB4, - 0x40, 0x0A, 0x25, 0x4D, 0x1C, 0x10, 0x2A, 0x9A, 0x96, 0x64, - 0x10, 0xC1, 0x60, 0x8C, 0x46, 0x60, 0x5A, 0x24, 0x89, 0x42, - 0x40, 0x86, 0xD0, 0x34, 0x89, 0x5C, 0x02, 0x02, 0x00, 0x34, - 0x21, 0x00, 0x24, 0x00, 0xA0, 0x20, 0x60, 0x03, 0xA6, 0x40, - 0xDC, 0x30, 0x80, 0x4B, 0xA8, 0x20, 0x0B, 0xA2, 0x24, 0xE2, - 0xB0, 0x89, 0xA2, 0xB2, 0x65, 0xD4, 0xA6, 0x68, 0x20, 0xA3, - 0x04, 0x4C, 0xC2, 0x11, 0x4A, 0x38, 0x24, 0x08, 0x17, 0x4D, - 0xE2, 0xA2, 0x00, 0x02, 0xC8, 0x00, 0x08, 0x00, 0x30, 0xA4, - 0xB6, 0x25, 0x5A, 0x30, 0x01, 0x40, 0x92, 0x4C, 0xC8, 0x44, - 0x92, 0x43, 0xC8, 0x60, 0xA3, 0x86, 0x84, 0x18, 0x04, 0x70, - 0x53, 0xB2, 0x40, 0x4C, 0x04, 0x84, 0x09, 0xC8, 0x48, 0x21, - 0x13, 0x31, 0x04, 0xA5, 0x0D, 0x90, 0x92, 0x88, 0xC1, 0x10, - 0x8D, 0xE0, 0x88, 0x28, 0x0B, 0x06, 0x84, 0x23, 0x22, 0x6C, - 0xDB, 0xB2, 0x05, 0xC8, 0x08, 0x6E, 0x93, 0x86, 0x4C, 0x0C, - 0x37, 0x86, 0xDA, 0x16, 0x51, 0x9B, 0x08, 0x32, 0x00, 0x91, - 0x45, 0xA4, 0x00, 0x2D, 0x14, 0x02, 0x0E, 0x60, 0x90, 0x4C, - 0x23, 0xB4, 0x09, 0x00, 0xA5, 0x81, 0x19, 0x21, 0x32, 0xC2, - 0x00, 0x02, 0x18, 0x10, 0x50, 0x08, 0xA2, 0x6D, 0x20, 0x31, - 0x6A, 0x90, 0x46, 0x90, 0x8B, 0x94, 0x30, 0x21, 0x44, 0x52, - 0x10, 0x19, 0x51, 0x94, 0xC0, 0x29, 0xC8, 0x20, 0x4E, 0x48, - 0xA6, 0x4C, 0x11, 0xC4, 0x64, 0xDC, 0x34, 0x10, 0x48, 0xC4, - 0x84, 0xCA, 0x46, 0x0C, 0x58, 0x12, 0x49, 0x0B, 0x16, 0x00, - 0x20, 0x42, 0x50, 0x04, 0x00, 0x46, 0xF8, 0x68, 0xB1, 0xA7, - 0x5E, 0xA7, 0xE6, 0xCE, 0xF5, 0x88, 0x8A, 0x5F, 0x79, 0xC9, - 0x3A, 0x5F, 0xF2, 0x7F, 0x5A, 0xED, 0xB4, 0xB4, 0x25, 0x44, - 0xD2, 0x7E, 0xED, 0xCE, 0x46, 0x40, 0xAC, 0xC2, 0x53, 0xD0, - 0xD3, 0xE7, 0xF6, 0x1C, 0xFA, 0x23, 0x4A, 0xB0, 0xEA, 0x32, - 0x91, 0xB7, 0xDA, 0x8B, 0x72, 0x35, 0xB7, 0x74, 0xD5, 0x9A, - 0x9B, 0x22, 0x3D, 0x49, 0x08, 0xBA, 0xD1, 0x7D, 0x9F, 0x64, - 0xD5, 0xAD, 0x7A, 0x37, 0xBD, 0x11, 0xD0, 0xA0, 0x7C, 0x53, - 0x05, 0x1A, 0x66, 0x6C, 0x5D, 0x42, 0x45, 0x55, 0x34, 0xC0, - 0x1F, 0xCA, 0xDB, 0x0D, 0x4F, 0x75, 0x95, 0x9F, 0x10, 0x9A, - 0x8D, 0x54, 0xCE, 0xC2, 0x5C, 0xF0, 0xCE, 0xBD, 0x39, 0x70, - 0xB0, 0x52, 0x2E, 0x4B, 0x11, 0x0D, 0x25, 0xD7, 0xE5, 0x4B, - 0xF1, 0xE3, 0x4F, 0xBE, 0xF2, 0x73, 0xA6, 0xDE, 0xB6, 0xC4, - 0x61, 0x71, 0xCC, 0x5C, 0xFE, 0x55, 0xF0, 0x50, 0xBA, 0x9C, - 0x18, 0x44, 0x13, 0xDD, 0xCB, 0x7A, 0xD2, 0xA2, 0xDC, 0xBF, - 0xF2, 0xC8, 0x84, 0xFF, 0x5B, 0xA7, 0xFA, 0x8D, 0x18, 0xF2, - 0x55, 0xD0, 0x3C, 0x4E, 0xB3, 0x77, 0x7C, 0x95, 0x91, 0x98, - 0x52, 0xF2, 0xB6, 0xCF, 0xFC, 0x45, 0xF4, 0x71, 0x62, 0x24, - 0xE2, 0x7B, 0xF7, 0x85, 0x08, 0x17, 0x6A, 0x62, 0xB4, 0xE9, - 0x08, 0x3E, 0xA1, 0xC6, 0x27, 0x8E, 0xB3, 0x26, 0xA5, 0x95, - 0x91, 0x84, 0xD0, 0xA0, 0xCD, 0xBF, 0x45, 0xD0, 0xE2, 0x26, - 0x65, 0x74, 0xD6, 0x49, 0x50, 0xF2, 0x6B, 0xAE, 0xF1, 0x8A, - 0x2A, 0x18, 0xDA, 0xF0, 0xAD, 0xE7, 0xF3, 0x0A, 0x0E, 0x33, - 0xA5, 0xCA, 0x11, 0x16, 0xCC, 0xD6, 0x81, 0x89, 0x83, 0x27, - 0x32, 0x97, 0x61, 0x48, 0x0D, 0x89, 0x3E, 0xB7, 0x7E, 0x02, - 0xC8, 0x96, 0x93, 0xFA, 0xD0, 0x1D, 0x76, 0xB4, 0xA4, 0x38, - 0x4C, 0xE3, 0xB4, 0x6F, 0xCE, 0x66, 0x90, 0x53, 0xDC, 0xCE, - 0xD6, 0x10, 0x16, 0x3E, 0xB8, 0xBD, 0xD9, 0x8C, 0xA9, 0x90, - 0x54, 0xAF, 0x86, 0x07, 0xB3, 0xC1, 0x82, 0xFB, 0x41, 0x61, - 0xB8, 0x6D, 0x8E, 0xA5, 0xA8, 0xEB, 0xE3, 0xC0, 0xCF, 0x51, - 0xAA, 0x94, 0x7A, 0x7F, 0x9C, 0x48, 0xA3, 0x40, 0x83, 0x33, - 0x22, 0x41, 0x61, 0x4C, 0xD4, 0x62, 0xD7, 0xC6, 0xC6, 0x5B, - 0xF3, 0x48, 0x42, 0xA7, 0x18, 0xD5, 0xAF, 0x05, 0xF6, 0x7A, - 0xF6, 0x6D, 0x82, 0xFF, 0x89, 0x68, 0x21, 0x13, 0x62, 0xA5, - 0x7E, 0xC9, 0x43, 0x03, 0x73, 0xF7, 0xD1, 0x01, 0x7D, 0xD9, - 0x13, 0x03, 0x9C, 0x99, 0x74, 0xD4, 0x92, 0x2E, 0xD1, 0xD3, - 0xCB, 0x53, 0x6C, 0xF9, 0xFE, 0xB4, 0x3D, 0x51, 0xF1, 0x63, - 0x42, 0x5B, 0xB2, 0x5D, 0x70, 0x03, 0xE5, 0x46, 0x5B, 0xC1, - 0xEB, 0x27, 0x11, 0x22, 0x15, 0x73, 0x6C, 0xF8, 0x51, 0x0A, - 0xFF, 0xD8, 0xFE, 0xB6, 0xE1, 0xBD, 0x42, 0xC0, 0x4C, 0xEB, - 0xCD, 0x1E, 0x3C, 0xD5, 0x7C, 0xEA, 0xC6, 0xD4, 0x34, 0xD2, - 0x8D, 0x99, 0xC4, 0x99, 0xA8, 0x8E, 0x9F, 0x60, 0xA8, 0xE8, - 0x7B, 0x1E, 0x7E, 0x50, 0x14, 0xAD, 0xFC, 0xDB, 0xA6, 0x00, - 0xE9, 0x00, 0x7A, 0x5A, 0xCD, 0x01, 0x26, 0xBB, 0x4E, 0x00, - 0x9E, 0xCC, 0xD3, 0x2D, 0x49, 0x1B, 0xB8, 0x60, 0x2C, 0x59, - 0x2A, 0x95, 0x8C, 0x92, 0x4D, 0x1A, 0x57, 0x3B, 0xEF, 0x6E, - 0xC4, 0x91, 0xE4, 0x99, 0x5E, 0xAE, 0x1B, 0xAF, 0x1E, 0x14, - 0x51, 0x38, 0x19, 0xBC, 0x33, 0x5C, 0x21, 0x4D, 0xAD, 0xA1, - 0x12, 0x17, 0xE6, 0xF5, 0x37, 0x98, 0xF6, 0xE6, 0x38, 0x4D, - 0x07, 0x80, 0x1D, 0xD8, 0x5E, 0xCC, 0x58, 0xDB, 0x7E, 0x3A, - 0x8F, 0x90, 0xDF, 0x9E, 0x80, 0xFB, 0xFC, 0x10, 0xEC, 0x7E, - 0x81, 0x53, 0x37, 0xC1, 0x66, 0xEE, 0xD7, 0x80, 0x0F, 0x0C, - 0xEB, 0xE8, 0x85, 0x2E, 0x37, 0x61, 0x8B, 0x9C, 0x63, 0xF6, - 0x27, 0x77, 0x16, 0x44, 0x61, 0x66, 0xC9, 0x79, 0x31, 0xDD, - 0xB4, 0x94, 0x9D, 0x8C, 0x8B, 0x1D, 0x28, 0xC2, 0x84, 0xC9, - 0x30, 0x71, 0xF4, 0x9E, 0xEF, 0x00, 0x2B, 0xA2, 0x9F, 0x38, - 0x65, 0xE6, 0xD1, 0x80, 0x26, 0x9B, 0xC4, 0xE8, 0x83, 0xCE, - 0x64, 0xD0, 0x8A, 0x9A, 0x1E, 0xEF, 0xA3, 0xB6, 0xD2, 0x0B, - 0x9C, 0x14, 0xF3, 0x08, 0xF1, 0x73, 0xD1, 0x34, 0xAE, 0x83, - 0xE7, 0x97, 0x5B, 0x97, 0x35, 0x0E, 0x35, 0xDC, 0x22, 0xD5, - 0xAA, 0xD1, 0xBC, 0xC7, 0x40, 0x20, 0xAD, 0x43, 0x36, 0x24, - 0x66, 0x7A, 0xB7, 0x1F, 0xF9, 0x1A, 0x1F, 0x37, 0xCE, 0xC2, - 0xFC, 0x98, 0xB1, 0x6A, 0x9A, 0x81, 0xD9, 0x4B, 0x53, 0x68, - 0xC5, 0xF3, 0xE6, 0x69, 0x76, 0xA6, 0x8B, 0x98, 0xFB, 0x84, - 0x2E, 0xD3, 0x4F, 0x77, 0xF9, 0x24, 0xF9, 0x13, 0x89, 0x8D, - 0xF6, 0x80, 0x2E, 0x0E, 0xA1, 0xCD, 0x90, 0x58, 0xCE, 0x63, - 0x36, 0x95, 0x8C, 0xF6, 0x68, 0xC3, 0x84, 0xF8, 0xB4, 0x5E, - 0x9E, 0x6C, 0x19, 0x32, 0x90, 0xA7, 0xD0, 0x2D, 0x47, 0x6B, - 0xCB, 0xAF, 0x85, 0x65, 0x92, 0x83, 0x11, 0x8E, 0xCC, 0x88, - 0xB1, 0x0B, 0xB8, 0x1E, 0x55, 0x4F, 0x18, 0x2A, 0xC4, 0x02, - 0xA8, 0x45, 0x6A, 0xCD, 0x75, 0x58, 0x6A, 0xAF, 0x83, 0x94, - 0x38, 0x1D, 0xA9, 0x09, 0x29, 0x1E, 0x0E, 0x43, 0xA9, 0x04, - 0x26, 0xF6, 0x1C, 0xC7, 0xCB, 0xC1, 0x10, 0xB9, 0x86, 0xC1, - 0xA2, 0xEC, 0x03, 0xDE, 0xF7, 0x53, 0x67, 0x2B, 0xDF, 0xEE, - 0xAF, 0xD2, 0xF2, 0xA8, 0xBD, 0xD9, 0x21, 0xCC, 0x8C, 0x72, - 0x02, 0x44, 0xF5, 0xA5, 0xED, 0x88, 0x5B, 0xAC, 0x5F, 0x5A, - 0x15, 0x81, 0xCC, 0x95, 0x15, 0x2E, 0x34, 0x72, 0x59, 0x6C, - 0x03, 0x36, 0x5E, 0x22, 0x7E, 0x3F, 0x65, 0xA6, 0x8C, 0x4F, - 0x89, 0xC1, 0xE7, 0x63, 0xB6, 0x1B, 0xE5, 0x41, 0xC7, 0xF8, - 0x96, 0xA4, 0x8F, 0x4F, 0x47, 0x59, 0x3E, 0x9D, 0x45, 0xCE, - 0xE4, 0x1B, 0xF1, 0x69, 0x0C, 0x39, 0x34, 0x16, 0x77, 0x6A, - 0xF5, 0xB5, 0x9E, 0x8B, 0x63, 0x86, 0x35, 0xFD, 0x4F, 0x2A, - 0x4B, 0x49, 0x21, 0x7C, 0xE3, 0xEA, 0x5C, 0xDE, 0x98, 0xE4, - 0x58, 0x32, 0x67, 0x98, 0xFC, 0x8F, 0xAB, 0x01, 0x0E, 0xA4, - 0x8B, 0x39, 0xA3, 0x55, 0x4C, 0x8E, 0x98, 0xBA, 0xCD, 0x3B, - 0xDB, 0x91, 0x8D, 0x94, 0x98, 0xBE, 0x37, 0x7B, 0xDB, 0x58, - 0xFC, 0xC1, 0x88, 0x7D, 0xD3, 0xBC, 0x8F, 0xB4, 0x7C, 0xB2, - 0xFE, 0x3E, 0x26, 0x36, 0x95, 0x7E, 0xDB, 0xD1, 0x38, 0x29, - 0xD9, 0xCF, 0x5D, 0x0E, 0xD1, 0xDF, 0x7F, 0xD1, 0x68, 0x04, - 0x70, 0x6F, 0x61, 0x39, 0x49, 0x44, 0xD2, 0x5C, 0x0C, 0xC3, - 0xD6, 0xF8, 0x1E, 0x96, 0x36, 0x43, 0x79, 0xB2, 0xE5, 0x1A, - 0xF1, 0x32, 0x03, 0xE1, 0x22, 0x45, 0x20, 0x1B, 0x36, 0x6A, - 0xB8, 0x62, 0xA5, 0xC5, 0x85, 0x8B, 0xED, 0x42, 0x69, 0xC6, - 0x30, 0x36, 0xA1, 0xF6, 0x22, 0x8D, 0x37, 0xD8, 0xE4, 0xBD, - 0x26, 0x8B, 0x89, 0xC2, 0xA9, 0x10, 0x82, 0xDD, 0x0C, 0x2D, - 0x04, 0x39, 0xB7, 0x59, 0x0B, 0x30, 0x2A, 0x6D, 0x84, 0x4A, - 0x74, 0xB9, 0x3F, 0xEA, 0xA5, 0x34, 0x76, 0xFA, 0xAD, 0x99, - 0xB0, 0xEF, 0xA0, 0xF1, 0x85, 0x3D, 0x00, 0x76, 0x00, 0xF8, - 0xFA, 0x1B, 0xAA, 0xB7, 0x5A, 0x62, 0x0E, 0xFD, 0xDC, 0x7A, - 0xCA, 0x18, 0x43, 0x32, 0x02, 0xB7, 0x20, 0x38, 0x0B, 0x50, - 0x4E, 0x57, 0xBF, 0x88, 0xBA, 0x09, 0xD3, 0x9D, 0x8B, 0x3A, - 0x88, 0x82, 0xD9, 0xC3, 0x60, 0x89, 0x10, 0xF5, 0x09, 0x61, - 0x72, 0x41, 0x83, 0xCB, 0x29, 0x38, 0xB3, 0x75, 0xD8, 0xBB, - 0x7E, 0x3F, 0x4A, 0x3C, 0x6B, 0xE5, 0xAE, 0xB7, 0x18, 0xC1, - 0x52, 0x3C, 0x8D, 0x8B, 0xF3, 0x8B, 0x84, 0x98, 0x3E, 0xE3, - 0x5F, 0x5B, 0x89, 0xB7, 0x07, 0x58, 0xD3, 0x7B, 0x84, 0x38, - 0x57, 0x3B, 0xF7, 0x59, 0x22, 0x6B, 0xA7, 0x31, 0x1D, 0xAF, - 0xBF, 0xFA, 0x15, 0x8B, 0xE0, 0x72, 0xFA, 0xCA, 0xB6, 0xC2, - 0xD6, 0x42, 0x43, 0x27, 0xF6, 0xAA, 0x3E, 0x5B, 0x07, 0x12, - 0x5C, 0xEF, 0xED, 0xCB, 0xDF, 0xAA, 0x5F, 0xF8, 0x77, 0xD0, - 0x8E, 0xC7, 0x03, 0x1E, 0x23, 0x5A, 0xF1, 0x3A, 0xA9, 0x10, - 0x6F, 0x05, 0x46, 0x04, 0x72, 0x63, 0xAC, 0xAE, 0x4B, 0x3D, - 0x1E, 0x2D, 0xC2, 0xE9, 0x38, 0x6A, 0xA9, 0x11, 0x1E, 0xE0, - 0xCA, 0x06, 0x7A, 0x5A, 0x45, 0xB2, 0x82, 0x0C, 0x10, 0xEB, - 0x0D, 0x10, 0x26, 0x74, 0xA5, 0x07, 0x1B, 0xBA, 0x61, 0xFD, - 0x8C, 0x73, 0xCB, 0x96, 0xFC, 0xF8, 0x98, 0x2D, 0x83, 0x12, - 0x0B, 0x6A, 0x9C, 0xA4, 0x70, 0x95, 0x4B, 0xD8, 0x11, 0x71, - 0x8F, 0x22, 0x89, 0xA2, 0x6A, 0x0A, 0xB0, 0x17, 0x93, 0x46, - 0x89, 0x60, 0x58, 0x2E, 0x1F, 0x3B, 0xE1, 0x6F, 0x49, 0x47, - 0xBC, 0x93, 0xD2, 0x14, 0x3D, 0xF2, 0x21, 0xA4, 0xFA, 0x1F, - 0x9D, 0x3F, 0x08, 0x40, 0x17, 0x77, 0x58, 0x7F, 0x65, 0xB4, - 0xFD, 0x01, 0x67, 0xF1, 0x62, 0x77, 0xD8, 0x6D, 0x46, 0x42, - 0x30, 0x52, 0x64, 0x4C, 0x76, 0x64, 0x7E, 0x09, 0xDD, 0x57, - 0x04, 0xB8, 0x4A, 0x7F, 0x8A, 0x68, 0xC3, 0x0D, 0xD9, 0xBE, - 0xF6, 0x61, 0x1C, 0x4D, 0x30, 0x80, 0x18, 0x83, 0xD6, 0x3F, - 0xB9, 0x58, 0x52, 0x20, 0xB9, 0x60, 0xEA, 0x22, 0xD0, 0xD0, - 0x61, 0x1A, 0x3B, 0x32, 0x69, 0x35, 0x8B, 0x22, 0x6E, 0x27, - 0x2E, 0xE2, 0x6D, 0xBA, 0xC7, 0x17, 0x02, 0xDA, 0x83, 0x22, - 0x5C, 0x31, 0x60, 0xD6, 0x78, 0x78, 0xBF, 0x0B, 0xEE, 0xD4, - 0x68, 0x32, 0xAE, 0x17, 0x80, 0x04, 0x7F, 0xD9, 0xA9, 0xA0, - 0xC9, 0xB7, 0x98, 0xEE, 0x9C, 0x8C, 0x61, 0x70, 0xBB, 0x2F, - 0x10, 0x39, 0x3E, 0xCC, 0x6E, 0xC8, 0x0A, 0x0F, 0xA2, 0x1E, - 0x31, 0x01, 0x75, 0x1E, 0x41, 0x9E, 0x63, 0x14, 0xC2, 0x3A, - 0xD9, 0x1A, 0x8B, 0x52, 0x0D, 0xFD, 0xDC, 0xE6, 0x23, 0x35, - 0xF1, 0x17, 0xE4, 0xA6, 0xDB, 0xAC, 0x3F, 0x67, 0x59, 0x02, - 0x8E, 0x20, 0x6F, 0x55, 0x69, 0xF8, 0x16, 0xFC, 0x33, 0x53, - 0xCA, 0xE8, 0x4E, 0x3F, 0xA4, 0x5C, 0xA6, 0xA4, 0x95, 0xCD, - 0xB7, 0x9D, 0x14, 0x79, 0xAE, 0x82, 0xF8, 0x2F, 0xE2, 0x13, - 0x0D, 0xDE, 0x75, 0x19, 0xA4, 0x0C, 0x32, 0x83, 0xD0, 0x14, - 0x35, 0xE7, 0x77, 0xD0, 0x18, 0x9C, 0xEF, 0xCC, 0xD5, 0xDA, - 0x39, 0x3B, 0xFF, 0x11, 0x39, 0x20, 0x3D, 0x5A, 0xB1, 0x16, - 0x2A, 0x57, 0x6B, 0x27, 0xC1, 0xB6, 0x69, 0xB5, 0x9B, 0x78, - 0x6F, 0x6B, 0x8A, 0xEF, 0x3F, 0x8F, 0xB8, 0x37, 0xBF, 0xCA, - 0x2D, 0x27, 0x25, 0x12, 0xC9, 0x81, 0x3A, 0x4C, 0x1A, 0x94, - 0xDF, 0x6D, 0x27, 0xF8, 0x85, 0x26, 0xA0, 0x88, 0x56, 0x7B, - 0x62, 0x5E, 0x84, 0xCF, 0x84, 0xAB, 0x81, 0xA3, 0xD4, 0xEB, - 0xE9, 0x85, 0x96, 0xED, 0x27, 0x42, 0xF6, 0x86, 0x28, 0xF1, - 0x8C, 0x69, 0x81, 0xD9, 0xAC, 0x1E, 0x9F, 0x12, 0xA4, 0x9E, - 0x78, 0xC5, 0x2E, 0x07, 0x66, 0xFF, 0x2F, 0xED, 0x93, 0xD2, - 0x62, 0x30, 0x30, 0x81, 0xE5, 0x76, 0x7A, 0x2A, 0x8E, 0xF3, - 0xC0, 0x21, 0x9C, 0xE8, 0xE3, 0x51, 0x4F, 0xDA, 0x96, 0xCF, - 0x6A, 0x0A, 0xC9, 0x90, 0x64, 0x93, 0x70, 0xE2, 0xAD, 0x6E, - 0x17, 0x06, 0x5E, 0xBD, 0x5C, 0x40, 0x4B, 0x43, 0x78, 0x1F, - 0x40, 0x55, 0x36, 0xBD, 0x2B, 0xD6, 0x92, 0x88, 0x02, 0xAA, - 0x3E, 0xDF, 0x3B, 0xC9, 0x90, 0x69, 0x28, 0xE6, 0xE1, 0x7D, - 0xBD, 0x2A, 0xC1, 0x6F, 0x70, 0x6D, 0xB8, 0x1A, 0xAD, 0x66, - 0x4F, 0x78, 0xF7, 0x00, 0x57, 0xED, 0xA8, 0xC3, 0x87, 0x8A, - 0x27, 0x2E, 0xFC, 0xC4, 0x37, 0xB9, 0xED, 0xAE, 0x06, 0x05, - 0x19, 0x60, 0x53, 0x85, 0x54, 0x83, 0x52, 0xEC, 0xBF, 0xA5, - 0x79, 0xFC, 0x18, 0xC3, 0xD8, 0x98, 0xC5, 0xD8, 0x81, 0x78, - 0x4F, 0xDA, 0x24, 0xAD, 0x6F, 0xF4, 0x78, 0x56, 0x79, 0x9F, - 0x5D, 0xE3, 0x6D, 0x35, 0x93, 0xEA, 0xA8, 0xB5, 0x44, 0x1A, - 0xDA, 0x87, 0xBD, 0x06, 0x4D, 0xFF, 0x35, 0x2A, 0x76, 0x51, - 0xD3, 0xC2, 0x73, 0x20, 0x93, 0x33, 0xC0, 0xEA, 0x88, 0xA0, - 0xCD, 0xE1, 0xEA, 0x79, 0x86, 0x32, 0xA7, 0xCE, 0xBA, 0x73, - 0xE9, 0x82, 0x32, 0x64, 0x88, 0x44, 0x66, 0x8A, 0x8C, 0xCB, - 0xF1, 0xDB, 0x42, 0x91, 0x3E, 0x78, 0x3A, 0x77, 0xEB, 0x4C, - 0xFD, 0xFE, 0x43, 0xD8, 0xEA, 0x9E, 0xED, 0x19, 0xAD, 0xA8, - 0x64, 0x1A, 0x12, 0xC3, 0x81, 0x75, 0xA0, 0x61, 0xAF, 0x4F, - 0x71, 0x25, 0x94, 0x76, 0x31, 0x9A, 0xF6, 0x14, 0x3F, 0x6D, - 0x36, 0xC0, 0x2F, 0x52, 0x3B, 0x4B, 0xCB, 0x2B, 0xCF, 0xB8, - 0x70, 0x19, 0x0D, 0x15, 0x1A, 0xF9, 0x48, 0xA8, 0x3A, 0x55, - 0xAF, 0x18, 0x66, 0x50, 0xC8, 0x32, 0x97, 0x43, 0x1E, 0x9F, - 0x8B, 0x66, 0xC1, 0x2E, 0x37, 0x69, 0xB8, 0x97, 0xF9, 0x6A, - 0x1E, 0x69, 0xBA, 0x5C, 0xEC, 0x6F, 0xFD, 0x99, 0x71, 0xB8, - 0xC4, 0x05, 0xB9, 0xB9, 0xE6, 0x4D, 0xA7, 0x01, 0x2D, 0xEB, - 0x26, 0x23, 0x40, 0x4D, 0x79, 0x1B, 0xE4, 0xD9, 0xAB, 0x9F, - 0xE9, 0x9B, 0x35, 0x78, 0xC0, 0x32, 0x8E, 0xF7, 0x5F, 0x7E, - 0xB5, 0x56, 0xD2, 0xA1, 0x35, 0x81, 0x72, 0xD2, 0x6A, 0x0A, - 0xC9, 0x6D, 0x0D, 0xDB, 0x2B, 0xA4, 0x02, 0x92, 0x76, 0x26, - 0xAF, 0x36, 0x27, 0x01, 0xDF, 0xA5, 0x5B, 0x09, 0x97, 0x06, - 0x5E, 0x80, 0xB0, 0x32, 0xFC, 0x1F, 0x72, 0x4E, 0x93, 0x2F, - 0x12, 0xF3, 0xA2, 0x60, 0x19, 0x74, 0x69, 0x03, 0x8B, 0x7D, - 0x6B, 0x2C, 0xE9, 0x54, 0x91, 0xF1, 0x3F, 0x2B, 0xF1, 0x65, - 0x71, 0x0B, 0x24, 0xEF, 0xCC, 0xB8, 0x79, 0x8E, 0x9B, 0x03, - 0xC1, 0xFF, 0xAC, 0xF0, 0x04, 0xEA, 0x92, 0xA3, 0x86, 0x64, - 0x6B, 0x63, 0x43, 0xA6, 0xC3, 0xCB, 0x43, 0xBE, 0xB0, 0xA9, - 0x11, 0x1B, 0x74, 0xC0, 0x87, 0x61, 0x5C, 0xDB, 0xF4, 0xA3, - 0x0E, 0xA6, 0x36, 0xEE, 0x41, 0x7F, 0xA8, 0xA6, 0xDF, 0x1B, - 0x05, 0xAE, 0x77, 0x90, 0x6A, 0xD4, 0x5B, 0x8E, 0x27, 0xE2, - 0xC0, 0x3E, 0x99, 0xAB, 0xFD, 0xFE, 0x6B, 0x71, 0xB4, 0x22, - 0x77, 0x7A, 0xB0, 0x43, 0x8B, 0x81, 0x33, 0x4D, 0x51, 0xD4, - 0xAB, 0xD9, 0xA0, 0x7C, 0xA7, 0x8A, 0x39, 0x92, 0x45, 0x39, - 0xAC, 0x54, 0x13, 0x6E, 0xA5, 0x22, 0x28, 0xC8, 0xAD, 0x3D, - 0xB1, 0xB2, 0xF3, 0x6B, 0xF6, 0x51, 0x17, 0xA3, 0x37, 0xE9, - 0xC9, 0x94, 0x54, 0xD7, 0x64, 0xC6, 0x04, 0xE7, 0xFA, 0x93, - 0xC1, 0xFA, 0xBA, 0xCA, 0x21, 0x1B, 0xF0, 0x6C, 0x99, 0x22, - 0x52, 0x53, 0xEF, 0xC2, 0xA2, 0x19, 0xB3, 0xCA, 0xF5, 0x30, - 0xC1, 0xD1, 0x24, 0x7F, 0x3A, 0x28, 0x8F, 0xAA, 0x70, 0xD2, - 0xBB, 0x7A, 0xF5, 0x8A, 0x23, 0x57, 0xE9, 0x79, 0x00, 0xF4, - 0x1C, 0x1D, 0xB1, 0x42, 0x0C, 0x53, 0x99, 0x7B, 0x99, 0x68, - 0x6E, 0x71, 0xD9, 0xD4, 0xE9, 0xC1, 0xA7, 0x5B, 0x05, 0xA7, - 0x6F, 0xF2, 0xE7, 0x11, 0x3B, 0x70, 0x5F, 0x11, 0x98, 0xBE, - 0xB5, 0xF8, 0x78, 0x5F, 0x5C, 0x19, 0xAC, 0x92, 0x4D, 0x18, - 0x0D, 0x7B, 0x6F, 0x8C, 0x90, 0xAB, 0x6B, 0x32, 0x3D, 0x51, - 0x11, 0xBC, 0x80, 0xC4, 0xCF, 0x4A, 0xF4, 0x7F, 0xCC, 0x68, - 0x92, 0x76, 0xF7, 0x9D, 0xF7, 0x07, 0x44, 0x8C, 0xB5, 0x4D, - 0x53, 0x7E, 0xE2, 0x58, 0x42, 0xB5, 0x8E, 0xB3, 0xC7, 0x0C, - 0x2F, 0xCA, 0x77, 0x2D, 0x56, 0x84, 0xCA, 0x98, 0x05, 0x09, - 0x43, 0xA9, 0x0E, 0x92, 0x4B, 0x57, 0x27, 0x46, 0x31, 0xF0, - 0xE3, 0xA4, 0x48, 0xD9, 0x42, 0x51, 0x32, 0xF0, 0x70, 0xA1, - 0x72, 0xA9, 0x2B, 0x1D, 0xB1, 0x2A, 0x09, 0x96, 0xAE, 0x3E, - 0x83, 0x41, 0x7B, 0x9B, 0x28, 0x6E, 0x85, 0xB7, 0xAD, 0x7F, - 0x10, 0xA3, 0x54, 0xBF, 0x24, 0xB6, 0xFB, 0x6D, 0xA5, 0x9F, - 0xE6, 0xBB, 0x33, 0x8A, 0x04, 0x83, 0x53, 0xFB, 0xB9, 0x79, - 0xF7, 0x76, 0xC9, 0x43, 0xC7, 0xE4, 0xB5, 0xE7, 0x19, 0x56, - 0x72, 0x55, 0xAC, 0x1D, 0xA8, 0xE4, 0xD8, 0x0C, 0x66, 0x15, - 0x7F, 0x17, 0x08, 0xB9, 0x33, 0x4B, 0x9C, 0x84, 0xDA, 0x49, - 0x9F, 0x1B, 0x42, 0x85, 0x0F, 0x4B, 0xC0, 0x70, 0x35, 0x23, - 0x34, 0xD9, 0x3C, 0x76, 0xF9, 0x22, 0x5C, 0x1A, 0xE9, 0x81, - 0xE5, 0x31, 0xA3, 0xF1, 0xB7, 0x7F, 0xE2, 0x75, 0x42, 0x27, - 0x82, 0xC7, 0xBA, 0x68, 0x20, 0x0E, 0xAC, 0xD0, 0x32, 0x28, - 0xB5, 0x99, 0x71, 0xBA, 0x48, 0x2C, 0x95, 0xA5, 0xC8, 0x65, - 0x2E, 0x19, 0x70, 0xAD, 0x12, 0x3A, 0xAD, 0x83, 0x87, 0x15, - 0xA7, 0xEA, 0x9D, 0x6E, 0x11, 0x94, 0x95, 0x23, 0x51, 0xDA, - 0x5F, 0x67, 0xBD, 0xDD, 0xA7, 0xF9, 0xF8, 0x76, 0xE4, 0x3C, - 0x83, 0x0A, 0xAB, 0xBE, 0x6A, 0xB0, 0xC5, 0xA8, 0xBE, 0xD9, - 0xDD, 0xBC, 0x4E, 0xA6, 0xCF, 0x91, 0xB3, 0x42, 0x30, 0x96, - 0x8E, 0x45, 0xC6, 0x1F, 0x55, 0x6B, 0x2C, 0x0A, 0xBC, 0x9F, - 0x69, 0x65, 0x98, 0x34, 0x95, 0x6A, 0x1E, 0x86, 0x78, 0x8B, - 0x26, 0x4F, 0x05, 0x76, 0x03, 0x22, 0xCB, 0x72, 0xF1, 0xD0, - 0x1A, 0x64, 0x19, 0xC7, 0x21, 0x5C, 0x51, 0xD0, 0x6C, 0x0B, - 0xDA, 0xB9, 0x67, 0x7A, 0x83, 0xC3, 0x1E, 0x16, 0x27, 0x4A, - 0x00, 0x5F, 0xBA, 0x0E, 0x45, 0x81, 0x6E, 0xE7, 0x5B, 0x5A, - 0x8F, 0x0D, 0x6D, 0x47, 0xB1, 0x30, 0xA7, 0x42, 0x1E, 0xA9, - 0x8A, 0x27, 0x4A, 0xB0, 0x60, 0x2F, 0xA9, 0x12, 0x42, 0xD6, - 0x7F, 0x10, 0x01, 0xF3, 0x59, 0xD2, 0x40, 0x11, 0x19, 0x92, - 0xFE, 0x80, 0x25, 0x1B, 0x60, 0xDC, 0x02, 0x7B, 0x10, 0x45, - 0x17, 0x66, 0x70, 0xB9, 0x64, 0x4A, 0xBA, 0xAD, 0xBF, 0x55, - 0x7C, 0xB3, 0xD8, 0x18, 0x6D, 0x16, 0x53, 0xED, 0x89, 0xE5, - 0xD2, 0x50, 0xFA, 0xA8, 0xFE, 0x74, 0x67, 0xC4, 0x35, 0x4C, - 0xC4, 0xBE, 0x52, 0x9A, 0x8E, 0xBB, 0xB6, 0xE0, 0xAF, 0x52, - 0x57, 0x3D, 0x99, 0x79, 0x10, 0xB8, 0xE6, 0xAB, 0x24, 0x9E, - 0x75, 0xC2, 0x2A, 0xFB, 0xDB, 0xF8, 0xE0, 0x02, 0xCB, 0x49, - 0x56, 0x52, 0x6B, 0x8C, 0xFA, 0x8E, 0xCF, 0xFA, 0x18, 0x50, - 0xDD, 0x98, 0x49, 0xEC, 0xA8, 0x08, 0x6C, 0x60, 0xC0, 0x68, - 0xBF, 0x7B, 0x49, 0xB4, 0xE6, 0x49, 0x59, 0x6E, 0x65, 0x0E, - 0x41, 0xEA, 0x64, 0xC8, 0xD3, 0x1A, 0x9F, 0x39, 0xAE, 0xEB, - 0x3C, 0x88, 0xFB, 0x40, 0xDC, 0xB8, 0x07, 0x82, 0x56, 0x01, - 0xAC, 0x04, 0x0B, 0x6B, 0x0B, 0x15, 0xAA, 0x4F, 0xD2, 0x04, - 0xF3, 0x65, 0xCD, 0xF7, 0x32, 0xB1, 0x95, 0xC4, 0x91, 0xB8, - 0x63, 0x02, 0x26, 0x47, 0x1D, 0x6E, 0x6D, 0xCF, 0x3D, 0x39, - 0x3D, 0xDC, 0x18, 0x33, 0xD8, 0xF5, 0x8C, 0xB0, 0x69, 0x53, - 0x48, 0x86, 0x14, 0x50, 0xA3, 0x65, 0xEE, 0x2C, 0x2F, 0x72, - 0xF7, 0x43, 0xE7, 0xEA, 0xA0, 0x3E, 0x3C, 0x30, 0x33, 0xD9, - 0x1D, 0x6E, 0x5D, 0xCB, 0xE1, 0xE0, 0x8D, 0x95, 0xD2, 0x58, - 0x8D, 0xD5, 0xB3, 0x1C, 0x22, 0x28, 0x6A, 0xBB, 0xB3, 0x09, - 0xB1, 0x91, 0x60, 0xE2, 0xC6, 0x48, 0x11, 0xF0, 0x49, 0xB6, - 0xE9, 0xEF, 0x4B, 0xC6, 0xDB, 0xB1, 0xBF, 0x6C, 0xB2, 0x92, - 0x5C, 0x65, 0x91, 0x67, 0x81, 0x9C, 0x71, 0x5A, 0x2C, 0xFE, - 0xC8, 0xF9, 0xF5, 0x96, 0x7D, 0x3E, 0xBB, 0x7F, 0xEF, 0xF7, - 0xBF, 0xF8, 0xAC, 0xCF, 0xA6, 0x6F, 0x28, 0x9C, 0x09, 0x65, - 0x8F, 0xF7, 0xDC, 0xEF, 0x3E, 0x4B, 0xCD, 0x6D, 0x97, 0xD3, - 0xCC, 0x9C, 0xF7, 0xF2, 0x4C, 0xE6, 0x64, 0x31, 0xE8, 0x1E, - 0xDE, 0x56, 0xAE, 0xA6, 0x04, 0xFB, 0xED, 0x2E, 0x3F, 0x23, - 0x7D, 0xBC, 0x6D, 0xCC, 0x4B, 0xD4, 0x9E, 0x06, 0x83, 0xE1, - 0x95, 0xAE, 0xC4, 0xAA, 0x6E, 0xFF, 0x9E, 0x1C, 0xB9, 0x07, - 0x60, 0x6D, 0xD5, 0x09, 0x06, 0x30, 0x0C, 0x3F, 0xB5, 0xE8, - 0x8B, 0x01, 0x94, 0x1B, 0x84, 0xE9, 0xB7, 0x37, 0x03, 0xA7, - 0xAF, 0x4B, 0x63, 0x3F, 0xD2, 0x57, 0xBB, 0xB8, 0xBF, 0xE2, - 0x53, 0x4F, 0xA1, 0x9E, 0xC7, 0x4C, 0xDA, 0x89, 0x25, 0x0E, - 0x7E, 0xC9, 0x44, 0x7F, 0x4C, 0x02, 0x7F, 0xA4, 0x08, 0xEC, - 0x7F, 0x44, 0xEA, 0xF7, 0xCF, 0x1B, 0x19, 0xFA, 0x6A, 0x0A, - 0x3E, 0xE1, 0xF4, 0x78, 0xDF, 0x93, 0xAB, 0x86, 0x9E, 0xE1, - 0x31, 0xBF, 0x70, 0x20, 0x8B, 0x87, 0xCE, 0xFC, 0x84, 0x03, - 0x8D, 0xF1, 0x25, 0xE6, 0x88, 0x30, 0x79, 0x63, 0xAF, 0x5C, - 0x3B, 0x84, 0xA9, 0xB8, 0x89, 0xB4, 0x23, 0x58, 0x78, 0xF9, - 0xAB, 0x76, 0x1B, 0x20, 0x56, 0xDB, 0x9E, 0xFE, 0x59, 0x29, - 0xB9, 0x8C, 0xD7, 0x4E, 0xA4, 0x5C, 0x7F, 0x40, 0xA8, 0xEB, - 0x0D, 0x90, 0xBA, 0x30, 0x68, 0x5E, 0x9C, 0x90, 0xBE, 0xD4, - 0x43, 0x4B, 0x67, 0x27, 0xE7, 0x7D, 0x06, 0xB8, 0xF0, 0x96, - 0xEF, 0xF4, 0x47, 0x5F, 0x8E, 0xCA, 0x46, 0x85, 0x3C, 0x94, - 0x9E, 0xDE, 0x09, 0x40, 0x45, 0xB3, 0x69, 0xF1, 0x8F, 0x90, - 0xF5, 0x5C, 0x22, 0x69, 0xBF, 0x5F, 0x11, 0x66, 0xD9, 0xDC, - 0x37, 0x6A, 0x2C, 0xAF, 0x72, 0x66, 0xC8, 0x28, 0xEA, 0x59, - 0x71, 0xB1, 0x7F, 0x10, 0xA5, 0xBC, 0x42, 0x99, 0xF6, 0xD6, - 0xB4, 0xC4, 0x18, 0x49, 0x72, 0x37, 0xF3, 0xCD, 0x01, 0xD6, - 0xAB, 0x2A, 0xFE, 0x1A, 0xBC, 0x52, 0x15, 0x38, 0x30, 0xF2, - 0x4F, 0xC0, 0xD3, 0x5B, 0x91, 0x5A, 0x55, 0xD1, 0x82, 0x5A, - 0x50, 0xE8, 0x16, 0x8C, 0x3D, 0xC8, 0x97, 0x3D, 0x2A, 0xA9, - 0xF3, 0xEA, 0x48, 0x57, 0x51, 0x29, 0xB0, 0x81, 0x4D, 0x6B, - 0x69, 0xFE, 0xF8, 0xA8, 0xE0, 0x5F, 0xF4, 0x98, 0xBE, 0x3D, - 0x39, 0xB6, 0x10, 0x3E, 0x70, 0x16, 0x60, 0x46, 0xA1, 0x74, - 0x5C, 0xF5, 0x53, 0x24, 0xF4, 0x56, 0x33, 0x97, 0x18, 0xB6, - 0x4A, 0x91, 0xE1, 0xF4, 0x36, 0x11, 0x80, 0xCF, 0xDE, 0xE3, - 0x7C, 0x8C, 0x27, 0xC9, 0x29, 0xA6, 0xCC, 0xA2, 0xE3, 0x61, - 0xED, 0x46, 0x10, 0x0D, 0x43, 0x1D, 0x63, 0xB2, 0x4B, 0xC0, - 0xFF, 0x79, 0x2D, 0x6D, 0xD1, 0x0E, 0xD4, 0x73, 0x24, 0xE2, - 0xFE, 0x07, 0x15, 0xC4, 0xB3, 0xFC, 0xDA, 0x14, 0x44, 0x81, - 0x89, 0xA9, 0x16, 0xEF, 0x8C, 0x60, 0xEE, 0x2D, 0xBC, 0x81, - 0xF1, 0xD8, 0xE1, 0x37, 0x5D, 0xC0, 0xD2, 0xA5, 0x8C, 0xF9, - 0xAF, 0xAA, 0xBE, 0xF6, 0x46, 0x65, 0xEB, 0x53, 0x97, 0x2F, - 0xDA, 0x28, 0x66, 0x29, 0x67, 0x1F, 0x1F, 0x0A, 0x61, 0x61, - 0x66, 0x61, 0xF2, 0xA7, 0x1F, 0x1C, 0x30, 0x1F, 0xDD, 0xDE, - 0xAB, 0xC7, 0x6C, 0x1C, 0xED, 0xC8, 0xDC, 0x09, 0xBA, 0xF9, - 0x93, 0x76, 0x4C, 0xCC, 0xAE, 0xF5, 0x2D, 0xA4, 0xAB, 0x3F, - 0xA0, 0x42, 0x4E, 0x8F, 0x28, 0x87, 0xE1, 0x64, 0xCA, 0xF4, - 0xB6, 0xAC, 0x39, 0x1E, 0x1C, 0xF2, 0x69, 0xFF, 0x30, 0x3B, - 0x2F, 0x5C, 0xB2, 0x82, 0xD8, 0x28, 0x2D, 0xA8, 0x2C, 0xDA, - 0x6D, 0x76, 0x38, 0xFC, 0x50, 0x6F, 0xA4, 0xB9, 0x52, 0x9F, - 0xD5, 0xFA, 0x94, 0xDC, 0x54, 0xED, 0xD9, 0x10, 0x6F, 0xDA, - 0x7E, 0x5E, 0x8A, 0xFB, 0xB3, 0x68, 0xD0, 0xD1, 0x25, 0x77, - 0x7E, 0x8B, 0x91, 0x68, 0x4E, 0xF4, 0x74, 0x99, 0x77, 0xB8, - 0x5C, 0xCE, 0xCC, 0x3D, 0x54, 0xA8, 0xD8, 0x4F, 0x01, 0x30, - 0x37, 0xB0, 0x82, 0x42, 0xB9, 0xB1, 0xBF, 0x83, 0xC8, 0xB6, - 0x40, 0x7F, 0xF2, 0xD8, 0x3C, 0xBD, 0x63, 0xCB, 0x23, 0x34, - 0xA4, 0xFB, 0x4C, 0xE0, 0x8B, 0x85, 0xA4, 0xA9, 0x7B, 0xA4, - 0x78, 0x86, 0xD4, 0xE9, 0x68, 0xA4, 0x40, 0x8D, 0xBC, 0x56, - 0x44, 0x8B, 0x24, 0x80, 0x6B, 0xC1, 0x84, 0xEC, 0xB3, 0x70, - 0x01, 0x0A, 0xFE, 0xED, 0x7D, 0xD9, 0x7E, 0xAB, 0x89, 0xDB, - 0xE3, 0x90, 0x5C, 0x6A, 0x75, 0x8E, 0x16, 0xF2, 0x0A, 0xFE, - 0x9E, 0x08, 0xC8, 0xB2, 0x35, 0x3C, 0xC3, 0x20, 0x29, 0xD4, - 0x8A, 0xA6, 0x58, 0x25, 0x43, 0x9B, 0x27, 0xAE, 0xBF, 0xC7, - 0x50, 0x82, 0x9F, 0x04, 0x88, 0x4C, 0xB0, 0x4E, 0x38, 0xA5, - 0x84, 0xC1, 0xBA, 0x6A, 0xA7, 0x16, 0x85, 0x76, 0xF5, 0x21, - 0x15, 0x3F, 0x00, 0x2C, 0x0A, 0xBD, 0x18, 0x66, 0x0C, 0xD1, - 0x46, 0x33, 0x1A, 0xF3, 0x85, 0x34, 0x68, 0x49, 0x05, 0x10, - 0x85, 0xF9, 0x61, 0xD6, 0xB6, 0x97, 0xFC, 0xAA, 0x2C, 0xBC, - 0xF1, 0x75, 0xF3, 0xFC, 0x57, 0x20, 0x54, 0xF2, 0x02, 0x5E, - 0xAB, 0xDD, 0x19, 0x31, 0xAB, 0x97, 0x5F, 0x11, 0x4F, 0xCE, - 0x4F, 0xB9, 0xBB, 0xA2, 0x01, 0x51, 0x48, 0x5A, 0x2C, 0x52, - 0xAD, 0x58, 0x00, 0x22, 0x41, 0x4D, 0x24, 0x68, 0x9F, 0xD9, - 0x13, 0x5C, 0x55, 0x0A, 0x62, 0xAD, 0x3E, 0x29, 0x86, 0x34, - 0x3B, 0x2D, 0x34, 0xBE, 0x0A, 0xDB, 0x85, 0x3A, 0x41, 0x2C, - 0x30, 0x56, 0x65, 0x04, 0x0A, 0x20, 0x31, 0x2A, 0xF3, 0x88, - 0x4C, 0x38, 0x64, 0x86, 0x14, 0x06, 0xF5, 0xF0, 0x7F, 0x63, - 0xC1, 0x87, 0x24, 0x39, 0xFB, 0xC0, 0xC2, 0x6B, 0x57, 0xB3, - 0xA9, 0x7C, 0x21, 0xD7, 0x17, 0xB5, 0x23, 0x89, 0x8B, 0x9A, - 0x53, 0xC6, 0x26, 0xD6, 0xC1, 0xD8, 0x3B, 0xD2, 0x30, 0x0B, - 0x30, 0x76, 0xB3, 0x21, 0x2B, 0xCF, 0x64, 0xB8, 0xCD, 0x8C, - 0xB9, 0x33, 0x73, 0xA5, 0x19, 0x5C, 0xBB, 0x4A, 0x6F, 0x9E, - 0xA7, 0x62, 0x61, 0x1C, 0x32, 0xBB, 0x3E, 0x1B, 0x8A, 0xAC, - 0xE5, 0xE1, 0xA9, 0xDD, 0x50, 0xFB, 0x3B, 0xCF, 0xB6, 0x49, - 0x7B, 0xED, 0x1A, 0x7E, 0x8E, 0x73, 0xAE, 0x8B, 0x31, 0x06, - 0x11, 0xC4, 0x84, 0x4C, 0xCA, 0x6D, 0x5A, 0x79, 0x50, 0x2E, - 0x66, 0x90, 0x0A, 0x13, 0x86, 0x15, 0x78, 0x06, 0xAD, 0x5D, - 0x8C, 0x5E, 0xC8, 0x73, 0xB0, 0x82, 0xFB, 0x03, 0xE6, 0x30, - 0xE7, 0x0B, 0x99, 0xF0, 0xD9, 0x8C, 0x2C, 0xFA, 0x34, 0xAB, - 0x8B, 0xDD, 0x06, 0x2F, 0x39, 0xE0, 0x53, 0x37, 0x61, 0x3D, - 0xC3, 0x77, 0x4C, 0x9F, 0x66, 0x95, 0x81, 0x94, 0x0A, 0xE5, - 0xCE, 0x59, 0xA1, 0x83, 0x5C, 0x77, 0xBD, 0xF5, 0xAD, 0xE2, - 0x9C, 0x10, 0x64, 0x22, 0xAD, 0x99, 0x02, 0x3F, 0x6A, 0xB2, - 0x96, 0x2C, 0xF3, 0x21, 0xEB, 0x5A, 0x7D, 0xFC, 0x02, 0x9B, - 0x53, 0x94, 0xB1, 0x88, 0x3E, 0x07, 0x78, 0x31, 0x8F, 0xDF, - 0xDA, 0xAF, 0xB7, 0x55, 0xC9, 0x30, 0x74, 0x61, 0xD1, 0x75, - 0x15, 0xF1, 0x29, 0xB0, 0x8B, 0xD9, 0x19, 0xB3, 0x2E, 0x8C, - 0x3C, 0x4C, 0xED, 0x22, 0x0B, 0x07, 0xEC, 0xA8, 0x2B, 0x26, - 0xBA, 0x2A, 0xE3, 0xEB, 0x91, 0x2C, 0xDF, 0x28, 0xFD, 0xE3, - 0x12, 0x6D, 0xA8, 0x8C, 0xA9, 0xA0, 0x18, 0xAE, 0x18, 0xC4, - 0x05, 0x53, 0xF6, 0xF7, 0x69, 0xEF, 0xBB, 0xF8, 0xFF, 0x55, - 0xD9, 0x4E, 0xA0, 0xC9, 0x58, 0x38, 0x67, 0x31, 0xE7, 0x5C, - 0x46, 0x41, 0x58, 0x26, 0x48, 0x8C, 0x82, 0x91, 0xE4, 0x46, - 0x91, 0xE0, 0xA4, 0x4F, 0xA5, 0xFD, 0x28, 0x14, 0xC8, 0x07, - 0x73, 0xB9, 0x20, 0x7D, 0x94, 0xAF, 0xDC, 0xBF, 0x4A, 0x55, - 0xA8, 0x82, 0xBF, 0x6D, 0x22, 0xD2, 0xFF, 0x18, 0x5E, 0xFB, - 0xC4, 0xDE, 0x8B, 0x12, 0x58, 0x1E, 0x05, 0x51, 0x4A, 0x31, - 0x54, 0x26, 0xA5, 0xFD, 0x36, 0xED, 0x14, 0x80, 0x4E, 0x3F, - 0xB2, 0x4F, 0x43, 0x70, 0xAF, 0x63, 0x77, 0x86, 0x68, 0xF4, - 0x35, 0xC2, 0x4E, 0x57, 0x43, 0x63, 0x06, 0x07, 0x21, 0xCE, - 0x61, 0xDD, 0x5D, 0x1D, 0xA3, 0xF7, 0x24, 0x72, 0xED, 0x73, - 0x6A, 0xA0, 0xE6, 0x9C, 0x1A, 0xA3, 0xCF, 0x98, 0x47, 0xC2, - 0xE1, 0x29, 0x22, 0x1B, 0x7C, 0x14, 0x0E, 0xE2, 0x6B, 0x58, - 0x54, 0xA7, 0x3E, 0x0F, 0x07, 0x1D, 0xAB, 0xFD, 0x1C, 0x1E, - 0xE0, 0x24, 0xCB, 0x2B, 0xC8, 0x7D, 0x90, 0x83, 0x8D, 0x46, - 0x43, 0xB4, 0x30, 0x39, 0x26, 0x29, 0xEE, 0xAF, 0x67, 0x61, - 0x4C, 0x16, 0xF1, 0xF4, 0x01, 0x55, 0x71, 0x30, 0x1B, 0x18, - 0xC2, 0xF3, 0x8A, 0x26, 0x52, 0x63, 0xD0, 0xEA, 0x66, 0x04, - 0xD7, 0xCC, 0x09, 0xF1, 0x66, 0x62, 0xD1, 0x29, 0xFD, 0xCE, - 0x0A, 0x85, 0xD5, 0x2C, 0x5B, 0x0D, 0xC3, 0x53, 0x8F, 0x45, - 0xA1, 0x95, 0xEE, 0xAF, 0xC3, 0xC5, 0xEE, 0xE6, 0xCE, 0x4A, - 0x33, 0xDB, 0x8B, 0x29, 0x79, 0xBC, 0xF7, 0xC5, 0x33, 0xCD, - 0xC1, 0x74, 0x25, 0x69, 0xEC, 0x75, 0xA4, 0x05, 0x1D, 0x6D, - 0x6E, 0xEC, 0x77, 0xDC, 0xF9, 0x08, 0xB1, 0xFA, 0x38, 0x7F, - 0x8E, 0xDF, 0x74, 0x10, 0x27, 0x19, 0x52, 0xAB, 0x6B, 0x08, - 0xEB, 0x51, 0x22, 0xE7, 0x79, 0xDA, 0x9F, 0xC0, 0xD2, 0x5E, - 0x5C, 0x2A, 0xC7, 0xF8, 0x6B, 0xB6, 0x63, 0x06, 0x49, 0xB4, - 0xDD, 0xEB, 0x20, 0x6F, 0x5A, 0x5E, 0x78, 0x79, 0xA5, 0xAF, - 0x35, 0x6D, 0x36, 0xBA, 0xA4, 0x38, 0x98, 0x38, 0xD9, 0x59, - 0x81, 0x16, 0x8C, 0xCE, 0x78, 0xCA, 0xD1, 0x86, 0x8B, 0x3A, - 0xD9, 0xA5, 0x5B, 0x7C, 0x53, 0x24, 0xB8, 0xD2, 0x2B, 0x09, - 0x73, 0x04, 0x87, 0x3E, 0x39, 0x64, 0x42, 0x5A, 0xE1, 0xC8, - 0x72, 0xD5, 0x00, 0x06, 0x06, 0x81, 0x91, 0x7A, 0x12, 0xA1, - 0x91, 0xEC, 0xBF, 0xD6, 0xBC, 0xFD, 0x82, 0xDA, 0xEE, 0x3A, - 0xB7, 0xF1, 0x54, 0xE3, 0xBD, 0xE5, 0xC0, 0x18, 0xE9, 0x5C, - 0x49, 0x0C, 0xFA, 0x64, 0x80, 0x98, 0x5C, 0x44, 0x9B, 0x4A, - 0x48, 0x3E, 0x0C, 0xBE, 0x5E, 0xBB, 0x68, 0xDA, 0x09, 0xD7, - 0x00, 0x51, 0x5B, 0x13, 0x96, 0xC2, 0x8A, 0xCE, 0xB0, 0x8F, - 0xDF, 0x84, 0x77, 0x70, 0x4B, 0x0F, 0x6E, 0xC7, 0x62, 0x47, - 0xFA, 0xA8, 0x35, 0x18, 0x43, 0x93, 0x4C, 0x83, 0x13, 0x45, - 0x74, 0x76, 0x19, 0xA7, 0x71, 0x98, 0x8C, 0x2E, 0xFC, 0xA9, - 0x83, 0x64, 0xD1, 0xA3, 0x95, 0x33, 0x31, 0xDB, 0xA8, 0xC3, - 0xB9, 0x72, 0x80, 0x58, 0xEC, 0xEB, 0xFC, 0xF3, 0x03, 0x44, - 0xDC, 0x11, 0x06, 0x3A, 0x95, 0x81, 0x28, 0xDB, 0xAB, 0x36, - 0xC4, 0x37, 0x0C, 0xD4, 0x6B, 0xAF, 0x04, 0xD0, 0x23, 0x3F, - 0xDD, 0x08, 0x88, 0x06, 0x23, 0x39, 0xCF, 0xB2, 0xCF, 0x13, - 0x27, 0xE1, 0x4E, 0x21, 0xDA, 0x81, 0x58, 0x29, 0x70, 0x2B, - 0x26, 0xB7, 0xA7, 0x69, 0xA1, 0x86, 0xBC, 0xD9, 0x88, 0xED, - 0x70, 0x61, 0x94, 0x2D, 0xCD, 0x47, 0x57, 0xD0, 0xBD, 0x07, - 0x05, 0x7E, 0xA5, 0x35, 0x29, 0x15, 0xFA, 0x62, 0x7E, 0xB7, - 0x2A, 0xEB, 0x4F, 0xC4, 0x0D, 0x6D, 0x2E, 0x6D, 0x8F, 0x53, - 0x7C, 0x0B, 0x62, 0x72, 0xA5, 0x01, 0x5D, 0xD9, 0x52, 0xAF, - 0x60, 0x22, 0x90, 0xD0, 0xE6, 0x37, 0x25, 0x57, 0x73, 0x66, - 0xD5, 0x96, 0x6A, 0x23, 0x75, 0x43, 0xF7, 0x6A, 0xC8, 0x3E, - 0xAC, 0x20, 0xC8, 0x8A, 0xE3, 0xD1, 0xB4, 0x07, 0x87, 0x8E, - 0x3A, 0xEB, 0x43, 0x10, 0x91, 0x7F, 0x17, 0x96, 0x4B, 0x7A, - 0x31, 0x2A, 0x84, 0xFC, 0xFE, 0xB1, 0x26, 0x67, 0xD6, 0xAD, - 0xB8, 0xB7, 0x3D, 0x3A, 0x2F, 0xEE, 0x94, 0x2F, 0x05, 0xF1, - 0xD8, 0x8E, 0xD4, 0x97, 0xAF, 0x36, 0xCE, 0x01, 0x18, 0x0B, - 0x68, 0x41, 0x26, 0xEB, 0x38, 0x2B, 0xF6, 0xD2, 0x8A, 0x5A, - 0x79, 0x02, 0xA1, 0xE4, 0x49, 0x48, 0xCF, 0x55, 0x2B, 0x74, - 0x16, 0x63, 0x27, 0x9D, 0x25, 0xAA, 0x7F, 0x8A, 0x5D, 0x96, - 0x68, 0xF3, 0x58, 0x7C, 0x10, 0xCF, 0x6A, 0xE3, 0xE2, 0x80, - 0x90, 0xD3, 0x39, 0xF5, 0x62, 0x01, 0x33, 0x5F, 0xC2, 0xFD, - 0xAD, 0xE6, 0x2A, 0xB2, 0x3D, 0x89, 0x99, 0x7B, 0x17, 0x35, - 0xE4, 0x5C, 0x62, 0x10, 0x69, 0x10, 0x93, 0x57, 0x92, 0x15, - 0x53, 0xEC, 0x82, 0x17, 0x00, 0xFC, 0x13, 0x49, 0x58, 0x79, - 0x90, 0x36, 0x0D, 0x50, 0xA5, 0xFE, 0xAE, 0xE1, 0xB3, 0xAF, - 0x40, 0x98, 0x3C, 0xB7, 0xAB, 0xC9, 0x0B, 0x2B, 0xE8, 0x31, - 0x71, 0x0D, 0x47, 0xE1, 0xE0, 0x3D, 0xCB, 0xB0, 0x3E, 0x44, - 0x00, 0x18, 0x66, 0xD5, 0x44, 0xEF, 0x58, 0x6A, 0xC3, 0x98, - 0x86, 0x19, 0xBA, 0xCE, 0x24, 0xF0, 0x9A, 0xED, 0x55, 0xA9, - 0x1F, 0x52, 0xB2, 0xBA, 0x1A, 0x2C, 0x71, 0x9F, 0xD7, 0xE6, - 0xA1, 0x01, 0x64, 0x8B, 0x22, 0x22, 0x23, 0xC8, 0x2A, 0xBA, - 0x13, 0x5A, 0xDD, 0xC4, 0x0C, 0x1A, 0x3C, 0x4F, 0x1E, 0x0B, - 0x5B, 0xB5, 0x45, 0xA3, 0xDD, 0x4D, 0xE9, 0x00, 0x06, 0x60, - 0x59, 0xFC, 0x48, 0xB2, 0x3E, 0x32, 0xBF, 0xF8, 0x74, 0x4E, - 0x65, 0x9F, 0x89, 0x8D, 0xE4, 0x0C, 0xC1, 0x89, 0xCF, 0x19, - 0xF0, 0xBC, 0x75, 0xDC, 0xE4, 0xEA, 0x23, 0x18, 0x23, 0xC2, - 0xD2, 0xA4, 0x96, 0xA6, 0xC2, 0x73, 0x41, 0x1E, 0xD8, 0x9D, - 0x02, 0x02, 0x35, 0x16, 0x61, 0x9B, 0x6F, 0xCC, 0x16, 0x80, - 0x2B, 0xA5, 0xE2, 0x9B, 0x63, 0x9B, 0x4E, 0x75, 0xBD, 0xBD, - 0xF3, 0x36, 0x16, 0x53, 0x6B, 0x34, 0x33, 0xF4, 0xBC, 0x05, - 0x79, 0x8A, 0x1F, 0x23, 0xD8, 0x36, 0xCC, 0xDB, 0x37, 0x5A, - 0x1E, 0xCE, 0x6D, 0x27, 0x7B, 0x6C, 0x66, 0x11, 0xE3, 0x96, - 0xAD, 0xC3, 0xF9, 0x57, 0xF9, 0xA7, 0x4C, 0x4F, 0x8E, 0x97, - 0x70, 0xB1, 0x70, 0xE9, 0x77, 0xF0, 0xC2, 0xD0, 0x79, 0x12, - 0x79, 0x3F, 0xDB, 0x71, 0x66, 0x48, 0xDB, 0x5A, 0xFC, 0xA7, - 0x8E, 0xE4, 0x1A, 0x93, 0xFE, 0x49, 0xF5, 0x7D, 0xEF, 0xC4, - 0x4B, 0xC1, 0x10, 0x2A, 0xD6, 0xF0, 0x5D, 0xC4, 0x80, 0x8B, - 0x9C, 0x2E, 0x44, 0xFB, 0x71, 0xD3, 0xA3, 0x80, 0xFB, 0x77, - 0x60, 0x16, 0xAD, 0x0B, 0xEC, 0x75, 0x9A, 0x58, 0x4B, 0x6E, - 0xD8, 0xFD, 0xE9, 0x41, 0x46, 0x85, 0x43, 0xFD, 0x82, 0x53, - 0x51, 0x65, 0xF8, 0xD0, 0x26, 0x2B, 0xF2, 0xF9, 0xE9, 0x26, - 0xD7, 0x15, 0x84, 0x31, 0x80, 0xAE, 0xFD, 0xA5, 0x30, 0x65, - 0xEE, 0x52, 0xCA, 0x3C, 0x76, 0x16, 0x91, 0x5A, 0x26, 0x49, - 0x1A, 0x28, 0xC7, 0x81, 0x10, 0x95, 0xB8, 0x96, 0x09, 0x50, - 0x6D, 0xB1, 0x64, 0xA2, 0x87, 0xCF, 0x38, 0x3C, 0x3C, 0x6E, - 0x0B, 0x96, 0x97, 0xFC, 0x81, 0xBD, 0x7D, 0xE7, 0xCC, 0xB6, - 0xF7, 0xE8, 0x15, 0x05, 0xAF, 0xDE, 0x1C, 0x68, 0xC0, 0xCF, - 0xF8, 0x68, 0x94, 0x90, 0x7B, 0x7D, 0x98, 0x57, 0xDC, 0x86, - 0x6D, 0x69, 0xD6, 0x98, 0x62, 0x0F, 0x38, 0x99, 0x93, 0x99, - 0x55, 0xD6, 0xA5, 0x8C, 0x94, 0x62, 0xCB, 0xD9, 0xE8, 0xA4, - 0x7C, 0xDF, 0x21, 0xF4, 0x36, 0x65, 0xCF, 0x3F, 0xE4, 0x10, - 0xA5, 0xB4, 0x71, 0x08, 0x65, 0x98, 0x59, 0x70, 0x19, 0x7E, - 0x27, 0x13, 0x71, 0x3F, 0xD2, 0x91, 0x20, 0xFF, 0x53, 0xDB, - 0xD2, 0xD4, 0x07, 0x3A, 0x49, 0x72, 0x05, 0x66, 0xED, 0x7D, - 0xBC, 0x61, 0x70, 0x7F, 0x64, 0x41, 0xDD, 0xB3, 0x1B, 0x03, - 0xB8, 0x20, 0xE1, 0x5D, 0x07, 0x39, 0xFC, 0xD2, 0x30, 0x72, - 0xE8, 0x0F, 0xA7, 0xA2, 0x71, 0xE8, 0x3D, 0xD9, 0x2B, 0x5B, - 0xB4, 0x97, 0x2B, 0xC3, 0x58, 0xE1, 0x2B, 0x0F, 0xAA, 0x8C, - 0x5A, 0x72, 0xC7, 0xBB, 0xB6, 0x59, 0x2B, 0x73, 0x39, 0x9A, - 0x20, 0xE5, 0x9A, 0x70, 0x30, 0x7B, 0x28, 0xBE, 0xD6, 0x6A, - 0x04, 0x18, 0x41, 0xEF, 0x18, 0xCD, 0xB5, 0x69, 0xB6, 0x00, - 0x50, 0xEE, 0xF9, 0x45, 0x2F, 0x86, 0xEE, 0x04, 0xBE, 0xF8, - 0x88, 0x9E, 0x0D, 0xAC, 0x1B, 0xA9, 0xD1, 0xC1, 0xA5, 0x3E, - 0xF6, 0xD9, 0x78, 0x99, 0x9D, 0x2E, 0x26, 0x6C, 0xCA, 0x7C, - 0x4C, 0xC7, 0xAF, 0xAB, 0xF0, 0xBB, 0x93, 0x32, 0x03, 0x22, - 0xAF, 0x27, 0x6A, 0x9F, 0x53, 0x77, 0xA9, 0x6C, 0x83, 0xA2, - 0x46, 0x15, 0x61, 0x6C, 0xB3, 0x08, 0x6F, 0x5B, 0x85, 0x73, - 0x8A, 0xCD, 0x8A, 0xB0, 0x70, 0xAC, 0xA5, 0x22, 0x18, 0x87, - 0x54, 0x91, 0x6B, 0x34, 0x7F, 0x0B, 0x4E, 0xCA, 0x44, 0xB3, - 0xBE, 0xB0, 0x77, 0x28, 0x85, 0x73, 0xDD, 0x29, 0x70, 0x53, - 0xD9, 0xA2, 0x4F, 0x12, 0xCB, 0x41, 0xFD, 0x99, 0x27, 0xC7, - 0xA9, 0xCF, 0xB7, 0x5B, 0xFB, 0xCC, 0x77, 0xBA, 0x12, 0xE1, - 0xD6, 0xF6, 0x7C, 0x22, 0xB4, 0xED, 0xB0, 0xA0, 0x71, 0x59, - 0xD2, 0xF3, 0x14, 0xB2, 0x7C, 0x4A, 0x0A, 0xD6, 0x43, 0x10, - 0xA0, 0xF6, 0xC0, 0x6F, 0xB4, 0x31, 0x8F, 0x7B, 0xF8, 0x5A, - 0xC9, 0x91, 0x0F, 0x7A, 0xE5, 0xDF, 0x29, 0x11, 0x66, 0xFF, - 0x4C, 0x73, 0xA6, 0xC7, 0xA0, 0xCC, 0x7B, 0x73, 0x79, 0x36, - 0x1D, 0x5E, 0x7C, 0xE2, 0xC9, 0xF7, 0x56, 0xC4, 0x88, 0x71, - 0xC1, 0x03, 0xEE, 0xE7, 0xE0, 0xEE, 0x12, 0xD7, 0x3D, 0x3A, - 0xB2, 0x91, 0x51, 0xE1, 0x18, 0xFE, 0x66, 0x22, 0x84, 0xA6, - 0xC3, 0xD2, 0x54, 0xE9, 0xE5, 0xF8, 0xDB, 0xF1, 0xF9, 0x6A, - 0x01, 0x61, 0xCF, 0x3D, 0xDA, 0x89, 0x5B, 0xED, 0x89, 0x10, - 0xBA, 0x18, 0xB8, 0xBA, 0x66, 0x38, 0x0D, 0x37, 0xEC, 0x1E, - 0xF7, 0x06, 0xD6, 0xC0, 0x84, 0x06, 0x2F, 0x43, 0xBD, 0x50, - 0xA0, 0x05, 0x9B, 0x50, 0xCD, 0xBB, 0xB7, 0x93, 0xF0, 0x70, - 0x50, 0xB7, 0x03, 0x0F, 0x27, 0x70, 0x47, 0x8E, 0xEB, 0x14, - 0xE0, 0x81, 0xBC, 0x7F, 0xA5, 0x60, 0xB0, 0x09, 0xCA, 0x38, - 0xCB, 0x59, 0x85, 0x49, 0xB3, 0xD4, 0x29, 0x50, 0xE1, 0x04, - 0xBD, 0x9F, 0x6C, 0xA5, 0x76, 0xCB, 0xE6, 0x79, 0xED, 0xDD, - 0xB8, 0x98, 0xA9, 0x94, 0xDD, 0xD3, 0x2E, 0xE0, 0xEA, 0xCD, - 0xD3, 0x34, 0xDA, 0x78, 0xBE, 0x7A, 0xC9, 0x8C, 0xD6, 0x12, - 0x5B, 0xD0, 0x36, 0x11, 0x79, 0x52, 0xCA, 0xA1, 0xCC, 0x3D, - 0x5B, 0x1F, 0x35, 0x80, 0xCC, 0x56, 0xDA, 0xC9, 0x88, 0xB7, - 0xD3, 0x28, 0x86, 0x6F, 0x4E, 0x20, 0x56, 0x56, 0x62, 0x12, - 0x79, 0xDA, 0x3F, 0x75, 0xEC, 0x89, 0xDC, 0x90, 0x44, 0xAE, - 0xB8, 0x0E, 0x34, 0x76, 0xF9, 0xAE, 0xDF, 0x2C, 0x28, 0x0F, - 0xCF, 0x28, 0x0B, 0x7B, 0x8A, 0xC4, 0x9B, 0x0B, 0x3C, 0x3E, - 0xC2, 0x70, 0x88, 0x71, 0xED, 0x3B, 0x3D, 0x61, 0x73, 0xDC, - 0x1B, 0x1A, 0x89, 0x16, 0xE2, 0x36, 0x50, 0x96, 0x38, 0x44, - 0xB1, 0xB6, 0x23, 0xB1, 0x83, 0x51, 0x43, 0x7C, 0x37, 0x9C, - 0x83, 0xDB, 0x63, 0x3E, 0x02, 0x42, 0xFA, 0xE9, 0x0B, 0x22, - 0xCB, 0xA5, 0x1F, 0x09, 0x03, 0x1C, 0xD0, 0xAD, 0xCB, 0xEE, - 0xB5, 0x3F, 0xFC, 0xCD, 0x80, 0x04, 0x63, 0x44, 0x4F, 0x3F, - 0x2B, 0x17, 0x66, 0xE0, 0xA7, 0x1E, 0xA2, 0xB5, 0xE3, 0xD3, - 0x23, 0x76, 0xF9, 0x75, 0x7C, 0x39, 0x5C, 0x6A, 0x64, 0xF8, - 0x61, 0xDE, 0x66, 0x3F, 0xCD, 0x4F, 0x06, 0xEF, 0x9C, 0xCA, - 0x43, 0xA9, 0x32, 0x30, 0xDC, 0xB8, 0xA2, 0xE0, 0xAA, 0xEB, - 0x4D, 0x30, 0x8D, 0x0C, 0xD1, 0x5E, 0x04, 0xEE, 0xED, 0x46, - 0x07, 0x9C, 0xF4, 0xD8, 0xD5, 0x78, 0x9A, 0x51, 0x93, 0xC6, - 0x95, 0x5C, 0x12, 0x48, 0x2B, 0x92, 0x7A, 0xE4, 0x57, 0x3D, - 0x37, 0xEC, 0xA0, 0x19, 0xEC, 0x0A, 0x45, 0x0B, 0xFE, 0x9F, - 0x5F, 0xA0, 0xB3, 0x05, 0xEE, 0xF9, 0x87, 0x76, 0x5C, 0xC1, - 0xAD, 0x92, 0x79, 0x50, 0xAC, 0x70, 0xB6, 0xE8, 0xBB, 0x7C, - 0xCA, 0xC2, 0x49, 0xAD, 0xB0, 0xDA, 0xD0, 0x28, 0x90, 0xC2, - 0xEE, 0x3D, 0x4C, 0xCD, 0xC8, 0x41, 0x89, 0x5C, 0x65, 0xB9, - 0x1C, 0xCA, 0x67, 0x7B, 0xEF, 0x0D, 0x7B, 0x69, 0x4B, 0x8E, - 0x51, 0x0D, 0xF7, 0x70, 0xB7, 0xB3, 0x4E, 0xC8, 0x87, 0x8D, - 0xD1, 0xDD, 0x20, 0x11, 0x3C, 0x34, 0xA3, 0x3B, 0x6F, 0xDD, - 0xF5, 0xB2, 0xB1, 0x21, 0x9A, 0xE0, 0x4A, 0xF0, 0xB9, 0xEB, - 0x64, 0xDB, 0xC6, 0xD6, 0x64, 0x8F, 0x1A, 0x2C, 0x40, 0x0A, - 0x24, 0xF4, 0x0C, 0x0F, 0x60, 0x04, 0xBA, 0x9D, 0x3A, 0xE7, - 0x05, 0x58, 0xB5, 0x29, 0xD4, 0xD3, 0x64, 0xED, 0xCE, 0x47, - 0x7B, 0xB0, 0x6E, 0xCC, 0x2F, 0x46, 0x3A, 0xFE, 0x11, 0xC6, - 0x6B, 0x91, 0x51, 0x6A, 0x17, 0xCD, 0x03, 0x35, 0x0E, 0x1C, - 0x0E, 0x8B, 0xDD, 0x46, 0x4F, 0x5D, 0x9A, 0x5C, 0xE1, 0x14, - 0x99, 0xE8, 0xF2, 0xA4, 0xED, 0xCF, 0x6F, 0xC6, 0xC1, 0x67, - 0x36, 0x49, 0x1F, 0x1E, 0x42, 0x92, 0x4D, 0x32, 0x05, 0x4E, - 0xA6, 0xD7, 0xC0, 0xEC, 0xB0, 0x3E, 0xFD, 0xA1, 0xA7, 0x08, - 0x6B, 0xE8, 0x7F, 0xCD, 0xF8, 0x3C, 0x53, 0x58, 0x4C, 0x97, - 0xE6, 0x8D, 0xFE, 0xA9, 0x49, 0x61, 0xD1, 0xF0, 0xA0, 0xC7, - 0xB4, 0x4F, 0xBE, 0xDD, 0x90, 0x92, 0x0B, 0xA0, 0x5E, 0x69, - 0xAC, 0xDA, 0x26, 0x99, 0xF8, 0xE3, 0x07, 0xB5, 0xB9, 0xB7, - 0x48, 0xC7, 0xA3, 0x64, 0x3E, 0xA0, 0xB6, 0xC1, 0xF8, 0x6E, - 0x23, 0xA3, 0x11, 0x52, 0xA8, 0x26, 0xBD, 0x1C, 0xAD, 0xEB, - 0xF7, 0xDF, 0xC6, 0x35, 0xB4, 0x92, 0xE5, 0xB0, 0x5B, 0x53, - 0x55, 0xAA, 0x6E, 0xAD, 0x36, 0x4B, 0xF0, 0xE5, 0x9E, 0x32, - 0xB6, 0xFF, 0x1C, 0x01, 0x35, 0x20, 0x5E, 0xAD, 0x3E, 0xA3, - 0x01, 0x5D, 0xA0, 0xC5, 0x1B, 0xC8, 0x69, 0xB8, 0xF2, 0x2B, - 0x2B, 0x69, 0xC4, 0x4E, 0xA3, 0xC6, 0x1C, 0xFE, 0xCC, 0x0C, - 0x79, 0x6E, 0xDD, 0xD4, 0x59, 0x93, 0x51, 0xA2, 0x41, 0x3A, - 0x7A, 0x7D, 0x19, 0x5C, 0x1A, 0x91, 0x3C, 0x68, 0x00, 0x42, - 0x58, 0x51, 0x26, 0x11, 0x1A, 0x1E, 0xDE, 0x3B, 0x64, 0x16, - 0xBC, 0xDC, 0x5A, 0xF7, 0x7E, 0x80, 0x04, 0x63, 0xED, 0xDB, - 0x68, 0x74, 0xC2, 0x6B, 0x36, 0x67, 0xFC, 0x81, 0xB3, 0x64, - 0xBC, 0xAC, 0xA4, 0x56, 0x55, 0x77, 0x86, 0x74, 0xE2, 0x68, - 0x02, 0xD5, 0x5A, 0x84, 0x8F, 0x0E, 0x7F, 0xA1, 0xE9, 0xA5, - 0x30, 0xEB, 0xB4, 0x3E, 0x31, 0x09, 0x7F, 0xE2, 0x21, 0x35, - 0x4F, 0xFA, 0x61, 0xD2, 0x42, 0xB5, 0xCC, 0x31, 0xDE, 0x9C, - 0xDD, 0x39, 0x71, 0x90, 0x69, 0x9C, 0xF3, 0x7B, 0x91, 0xB1, - 0x65, 0x44, 0x10, 0xEC, 0x5C, 0x31, 0xF5, 0xA5, 0x37, 0xFF, - 0x52, 0xDF, 0x21, 0x85, 0x8A, 0x08, 0x77, 0xD7, 0xEE, 0xCC, - 0xD8, 0x58, 0xEF, 0x5B, 0xDD, 0x12, 0xC0, 0x4E, 0xC2, 0x20, - 0xAD, 0x5E, 0x74, 0x37, 0xE0, 0x70, 0x1B, 0xBA, 0xA3, 0x84, - 0x39, 0x2C, 0x4F, 0x63, 0x77, 0x69, 0x6C, 0x60, 0x69, 0x00, - 0xF0, 0xCE, 0x19, 0x29, 0x62, 0xDA, 0x10, 0xD9, 0x15, 0x79, - 0xC5, 0x2B, 0xB0, 0xB3, 0x97, 0x8C, 0x98, 0x83, 0x9F, 0x25, - 0x3F, 0x56, 0x1F, 0x2C, 0x63, 0x77, 0xFA, 0xDB, 0x27, 0xDF, - 0x94, 0xAE, 0x08, 0x44, 0x75, 0x8A, 0xE8, 0x91, 0x72, 0xB0, - 0xD0, 0x93, 0xC5, 0x7B, 0xB1, 0xD0, 0xEB, 0xD8, 0xDD, 0x88, - 0x29, 0xF8, 0x36, 0xE7, 0x7C, 0xFD, 0x88, 0xFE, 0xA1, 0xEE, - 0x12, 0x9A, 0x0E, 0x84, 0x75, 0x15, 0xA8, 0xA0, 0xD7, 0xBC, - 0x72, 0x75, 0x7D, 0x4E, 0xDF, 0xEE, 0x30, 0x30, 0x23, 0x6D, - 0xCC, 0xE5, 0xD7, 0xFD, 0x11, 0xE0, 0x87, 0x65, 0xDE, 0xAA, - 0xF4, 0x2C, 0x64, 0x74, 0x1A, 0x0C, 0x7A, 0x0A, 0x5B, 0x85, - 0xF3, 0x35, 0xB8, 0x41, 0x27, 0x14, 0xFC, 0x2A, 0x8D, 0x28, - 0xD0, 0xA7, 0xDB, 0xB0, 0xD9, 0x5A, 0xA9, 0x0F, 0x0B, 0x2F, - 0xE0, 0x8E, 0x37, 0x82, 0x5E, 0x8E, 0x1E, 0x2F, 0xC2, 0xA6, - 0xF5, 0x89, 0x54, 0x77, 0x49, 0x49, 0xDC, 0xF4, 0x03, 0xF2, - 0x04, 0xD6, 0xC0, 0x43, 0xB1, 0x13, 0x2B, 0x0C, 0xC2, 0x14, - 0x93, 0x5A, 0x90, 0x20, 0x87, 0xA0, 0x4A, 0xB2, 0xD7, 0x25, - 0x81, 0x79, 0x3C, 0x9C, 0xF6, 0x92, 0xBB, 0x26, 0xB0, 0x25, - 0x93, 0x05, 0x60, 0xEC, 0x56, 0x3C, 0x92, 0x41, 0x63, 0x52, - 0x0F, 0x95, 0x06, 0x7D, 0xE8, 0x46, 0x90, 0x39, 0x69, 0xEA, - 0x6B, 0xA6, 0x64, 0x09, 0x7B, 0x2F, 0x34, 0xE0, 0x21, 0x29, - 0xDA, 0xE3, 0xCF, 0xFE, 0xA7, 0x8E, 0x14, 0x3A, 0xD7, 0x53, - 0x26, 0xD7, 0x82, 0x0E, 0x2A, 0x00, 0x43, 0xEB, 0x6A, 0x23, - 0x75, 0x28, 0xD0, 0x9B, 0x85, 0xE0, 0xFB, 0x14, 0x19, 0xF3, - 0x6A, 0x73, 0x6C, 0x97, 0x0E, 0x21, 0xFC, 0x0F, 0x26, 0xC5, - 0xCE, 0xB7, 0xC6, 0x59, 0xA2, 0xE6, 0x4C, 0xF4, 0xC7, 0xBB, - 0x9B, 0xA8, 0xFA, 0x12, 0xC7, 0xDA, 0x33, 0x26, 0x69, 0x83, - 0x49, 0xA8, 0x0A, 0x3E, 0xF0, 0xD4 +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY + +static const unsigned char bench_dilithium_level3_pubkey[] = { + 0x15, 0xc9, 0xe5, 0x53, 0x2f, 0xd8, 0x1f, 0xb4, 0xa3, 0x9f, + 0xae, 0xad, 0xb3, 0x10, 0xd0, 0x72, 0x69, 0xd3, 0x02, 0xf3, + 0xdf, 0x67, 0x5a, 0x31, 0x52, 0x19, 0xca, 0x39, 0x27, 0x77, + 0x61, 0x6d, 0x0f, 0xc1, 0x33, 0x26, 0x09, 0xf0, 0xf9, 0x4d, + 0x12, 0x7a, 0xef, 0xf7, 0x21, 0x26, 0x2c, 0xe0, 0xe2, 0x92, + 0x1f, 0x9d, 0xd1, 0xaa, 0xaf, 0x08, 0x14, 0xf2, 0xaa, 0x24, + 0x99, 0x0f, 0x20, 0x57, 0x35, 0x04, 0x32, 0x96, 0x8e, 0x6e, + 0x10, 0x64, 0xe3, 0xe3, 0x57, 0x26, 0x33, 0x32, 0x7b, 0xe4, + 0x18, 0x41, 0x77, 0xd3, 0x24, 0x63, 0x3d, 0x11, 0xea, 0xdc, + 0xbe, 0x59, 0xff, 0x8d, 0xc2, 0xe4, 0xc7, 0x04, 0xf3, 0xd4, + 0xe0, 0x1d, 0x5e, 0x09, 0x46, 0xbf, 0x02, 0x05, 0xc7, 0xa6, + 0xb7, 0x82, 0x40, 0x1f, 0x55, 0xe9, 0x77, 0x82, 0xc0, 0xcc, + 0x86, 0x99, 0x19, 0x99, 0xa2, 0xc9, 0x1b, 0x4f, 0xdd, 0x49, + 0x4c, 0x78, 0x0a, 0x58, 0xb8, 0xf0, 0x23, 0xac, 0x1a, 0x71, + 0x57, 0x6d, 0xd6, 0x3a, 0x3a, 0x6f, 0x93, 0xb3, 0x2b, 0x09, + 0xbe, 0xec, 0x7b, 0x5b, 0xf7, 0x3a, 0xed, 0xf9, 0xd0, 0xb1, + 0xfe, 0x9f, 0x9b, 0xec, 0x11, 0xb6, 0x6b, 0xd1, 0xb6, 0x00, + 0x72, 0x7f, 0x68, 0x9a, 0x61, 0xa5, 0xf5, 0x6e, 0xe9, 0x46, + 0xa4, 0x82, 0x08, 0x9f, 0x50, 0x4c, 0x75, 0xc3, 0x48, 0x85, + 0x76, 0x39, 0xea, 0x0c, 0xf2, 0xe8, 0x7e, 0x48, 0x69, 0xd9, + 0x6f, 0x9a, 0x89, 0x7d, 0x98, 0xc1, 0x16, 0xdc, 0x2f, 0xc7, + 0x0a, 0x11, 0xa8, 0xbb, 0xe7, 0x91, 0xb1, 0x0f, 0x0e, 0xf0, + 0xb4, 0xc8, 0x41, 0x7e, 0x62, 0x9e, 0x3c, 0x30, 0x4c, 0xbc, + 0x4c, 0xeb, 0x37, 0xaf, 0x48, 0x72, 0x59, 0x64, 0x8e, 0xfb, + 0x77, 0x11, 0x28, 0xdd, 0x30, 0x52, 0x8e, 0x69, 0x8c, 0x9f, + 0x3d, 0xec, 0xdf, 0xa7, 0x5f, 0x42, 0x18, 0xda, 0xba, 0x1a, + 0x96, 0x91, 0x7d, 0x62, 0xd5, 0x52, 0xff, 0x44, 0xc9, 0x1d, + 0x29, 0xa6, 0xb9, 0x03, 0x9a, 0x26, 0x26, 0xcf, 0x57, 0x40, + 0x70, 0x7e, 0x2b, 0xbd, 0xf0, 0x81, 0x71, 0x0f, 0x0b, 0x2e, + 0x9b, 0x03, 0xba, 0x31, 0x41, 0x68, 0x37, 0xc8, 0xff, 0xea, + 0xc4, 0x73, 0xa5, 0xf9, 0xc2, 0x92, 0x78, 0x0c, 0xe7, 0xfd, + 0x5d, 0xb2, 0x01, 0xb5, 0x8d, 0xeb, 0x64, 0xd4, 0x14, 0xea, + 0x7a, 0xd1, 0x42, 0xc8, 0x99, 0xe4, 0x7d, 0x5b, 0x7e, 0x3b, + 0x8f, 0xab, 0x82, 0x12, 0xdf, 0xbb, 0xa1, 0x45, 0x30, 0xc9, + 0x0f, 0xb9, 0xe5, 0xba, 0xe6, 0x8a, 0xf3, 0x78, 0x61, 0xcc, + 0x9f, 0xe1, 0x46, 0x2a, 0x9a, 0x18, 0x0e, 0x2a, 0x57, 0xf3, + 0xe5, 0x56, 0xd1, 0x42, 0x48, 0xe1, 0x5a, 0x8e, 0x33, 0xce, + 0x19, 0xe5, 0x3e, 0x7f, 0x00, 0x70, 0x9c, 0x4c, 0xd3, 0xe1, + 0x0c, 0xa1, 0x7e, 0xd4, 0xa9, 0x9e, 0x8b, 0xe2, 0xf0, 0xac, + 0xdb, 0xa6, 0x72, 0x75, 0x67, 0xa6, 0x57, 0xed, 0x79, 0x2e, + 0xca, 0x8d, 0xeb, 0x9b, 0x9e, 0xb7, 0xbf, 0x30, 0x02, 0x2b, + 0xb3, 0x43, 0x89, 0x9b, 0xa8, 0x88, 0xa5, 0xbb, 0x33, 0xd9, + 0x99, 0x30, 0x7c, 0xc7, 0xd4, 0x28, 0x5e, 0x5e, 0x3f, 0x9d, + 0x6d, 0x35, 0x75, 0x33, 0x8e, 0xff, 0x84, 0x2e, 0x2d, 0xda, + 0xf0, 0xff, 0x70, 0xe5, 0xb5, 0x62, 0x96, 0x33, 0x3a, 0xd9, + 0xb5, 0x82, 0x25, 0x81, 0x81, 0x40, 0x5d, 0x4f, 0x11, 0x86, + 0x63, 0x1a, 0x06, 0xc1, 0x67, 0xc7, 0x49, 0x03, 0xc7, 0xe4, + 0x6f, 0xb4, 0x13, 0x3e, 0x57, 0x62, 0xfd, 0x8a, 0xc6, 0x2b, + 0x65, 0x5b, 0xa4, 0x29, 0x57, 0x8d, 0xde, 0xa5, 0xee, 0x32, + 0xc2, 0x76, 0x03, 0xca, 0xce, 0xc1, 0x48, 0xec, 0x45, 0xcf, + 0x30, 0x21, 0x28, 0x7f, 0x10, 0x47, 0xd2, 0xdb, 0xee, 0xca, + 0x5b, 0x0f, 0xd5, 0x39, 0x3a, 0xc3, 0xa6, 0x78, 0xb2, 0x15, + 0xaf, 0x82, 0x3c, 0x2f, 0xc4, 0x51, 0x5c, 0x52, 0xad, 0xf2, + 0x89, 0x92, 0x8e, 0xf3, 0x50, 0x38, 0xed, 0xf8, 0xc9, 0x14, + 0x4c, 0xe4, 0xa3, 0x9a, 0xaf, 0xc4, 0x5c, 0xf3, 0x9f, 0xc3, + 0xa3, 0xc0, 0xbe, 0x45, 0x1b, 0x21, 0x63, 0xfa, 0xe0, 0xe0, + 0x91, 0x2b, 0x42, 0xca, 0x91, 0xfb, 0x5e, 0x97, 0x9a, 0x0a, + 0xd4, 0x88, 0xba, 0xb8, 0x22, 0xc6, 0xbf, 0x56, 0x58, 0x1e, + 0x92, 0xa9, 0x9d, 0xa7, 0xed, 0xc9, 0xab, 0x54, 0x4f, 0x75, + 0x8d, 0x42, 0xc1, 0xe1, 0x61, 0xd0, 0x91, 0x9a, 0x3a, 0x40, + 0x9a, 0xa3, 0xfb, 0x7b, 0x4e, 0xf0, 0x85, 0xf0, 0xdc, 0x40, + 0x72, 0x9f, 0x05, 0xa8, 0xbe, 0x95, 0x5a, 0x7f, 0xba, 0x75, + 0x00, 0x6e, 0x95, 0x76, 0xbd, 0xb2, 0x40, 0xf5, 0xb0, 0x64, + 0x0a, 0x2f, 0x06, 0x3d, 0x9f, 0xac, 0x6a, 0xa5, 0x46, 0x5a, + 0x85, 0xa4, 0x6f, 0xee, 0x27, 0xa0, 0xeb, 0x5f, 0x1f, 0x91, + 0xbd, 0x2b, 0x02, 0x16, 0xdf, 0x74, 0x97, 0x2c, 0xd0, 0xa8, + 0x9f, 0x3a, 0x7b, 0xdf, 0x3e, 0x98, 0x4a, 0x91, 0xdc, 0x19, + 0x96, 0x88, 0x75, 0x21, 0x1a, 0x6a, 0xa8, 0x4b, 0x1f, 0x35, + 0xd1, 0x92, 0xf5, 0x76, 0xf4, 0x72, 0x55, 0x13, 0xdb, 0x5d, + 0x07, 0x8d, 0xd9, 0x72, 0xe4, 0x75, 0xde, 0x80, 0xbc, 0xe9, + 0x9c, 0xf0, 0x5c, 0x6a, 0x8a, 0x0e, 0x34, 0xf6, 0x3f, 0x5c, + 0xef, 0x0e, 0xcc, 0x52, 0x38, 0x2d, 0x7b, 0xc2, 0x1b, 0x69, + 0x9f, 0xe5, 0xed, 0x14, 0xb0, 0x91, 0x0b, 0xe9, 0x4d, 0x34, + 0xd5, 0xaa, 0xd4, 0xd2, 0x46, 0x39, 0x45, 0x7e, 0x85, 0x2f, + 0xdb, 0x89, 0xf4, 0xff, 0x05, 0x74, 0x51, 0xba, 0xdd, 0xee, + 0xf6, 0xc2, 0xc1, 0x0a, 0x8f, 0xd9, 0xeb, 0xc7, 0x61, 0x30, + 0x8f, 0x86, 0x8b, 0x1f, 0x82, 0xc1, 0x22, 0xfd, 0x83, 0xf4, + 0x5d, 0xc5, 0x94, 0xf5, 0xd7, 0x17, 0xc7, 0x7b, 0x71, 0xf5, + 0x5e, 0x15, 0x49, 0x70, 0xb2, 0x57, 0xa0, 0xc0, 0x57, 0x63, + 0x53, 0x35, 0xb6, 0x52, 0x20, 0x7b, 0x83, 0xd4, 0x57, 0x63, + 0x25, 0x8e, 0x83, 0xb3, 0x8e, 0x26, 0x1f, 0x09, 0xde, 0x14, + 0xd6, 0xa6, 0xfc, 0xe5, 0x93, 0x3c, 0x88, 0x8e, 0xf5, 0x10, + 0x57, 0xb9, 0xc9, 0x9b, 0xff, 0x72, 0x9d, 0x3d, 0x3f, 0x97, + 0xd9, 0x3c, 0x20, 0xe2, 0x57, 0xfd, 0x2a, 0x5c, 0x17, 0x12, + 0xe6, 0x08, 0xaf, 0xe4, 0x26, 0x96, 0xb9, 0x6d, 0xc3, 0xac, + 0x22, 0xf3, 0x8b, 0x89, 0xde, 0xc7, 0x8a, 0x93, 0x06, 0xf7, + 0x1d, 0x08, 0x21, 0x36, 0x16, 0x74, 0x2b, 0x97, 0x23, 0xe4, + 0x79, 0x31, 0x08, 0x23, 0x62, 0x30, 0x67, 0xe2, 0xed, 0x30, + 0x9b, 0x0c, 0xf9, 0x08, 0x7a, 0x29, 0x73, 0xc6, 0x77, 0x8a, + 0xbb, 0x2a, 0x1c, 0x66, 0xd0, 0xdd, 0x9e, 0xa3, 0xe9, 0x62, + 0xcc, 0xb7, 0x88, 0x25, 0x4a, 0x5f, 0xbc, 0xaa, 0xe3, 0xe4, + 0x4f, 0xec, 0xa6, 0x8e, 0xa6, 0xa4, 0x1b, 0x22, 0x2b, 0x2c, + 0x8f, 0x57, 0x7f, 0xb7, 0x33, 0xfe, 0x16, 0x43, 0x85, 0xc5, + 0xd2, 0x95, 0xe6, 0xb9, 0x21, 0x68, 0x88, 0x98, 0x33, 0x8c, + 0x1d, 0x15, 0x9c, 0x4d, 0x62, 0x1f, 0x6b, 0xe8, 0x7a, 0x2d, + 0x6b, 0x0e, 0xc3, 0xde, 0x1a, 0xa8, 0xed, 0x67, 0xb3, 0xb3, + 0x36, 0x5b, 0x4b, 0xcb, 0xe8, 0xa8, 0x5c, 0x0b, 0x2f, 0xca, + 0xd7, 0x71, 0xe8, 0x85, 0xe7, 0x4d, 0xe5, 0x7b, 0x45, 0xed, + 0xb2, 0x4c, 0x69, 0x04, 0x7e, 0x4f, 0xc0, 0xef, 0x1a, 0xca, + 0x0d, 0xa6, 0xc4, 0x79, 0x15, 0x78, 0x9c, 0xd2, 0x91, 0x3c, + 0x32, 0x55, 0x40, 0xe7, 0xcb, 0x7e, 0xde, 0x07, 0xa6, 0x97, + 0x00, 0x2d, 0x70, 0xf6, 0x3d, 0x15, 0xdf, 0x29, 0x8e, 0xa3, + 0x96, 0x6d, 0xf2, 0xbb, 0xa5, 0x1b, 0x7b, 0x58, 0x30, 0xf6, + 0x17, 0xbd, 0xda, 0x13, 0xf7, 0x33, 0xc2, 0x62, 0x32, 0xd4, + 0x1c, 0x2e, 0x31, 0x74, 0x92, 0xad, 0x99, 0x8c, 0x0e, 0x7c, + 0x50, 0x21, 0xcd, 0xff, 0x41, 0xeb, 0xd1, 0xca, 0x14, 0xb7, + 0xb2, 0x31, 0x2f, 0xbe, 0x16, 0xce, 0x4f, 0x26, 0x16, 0x04, + 0xc2, 0xaf, 0xbe, 0x0d, 0x24, 0xab, 0x9a, 0x21, 0x37, 0x06, + 0xac, 0x50, 0x23, 0xf1, 0xbe, 0x5c, 0xbb, 0x64, 0xf3, 0xd3, + 0x66, 0xa3, 0xb8, 0xbe, 0x8b, 0x49, 0x8d, 0xf6, 0xc7, 0xb9, + 0x8f, 0x4e, 0x31, 0x06, 0x51, 0xe5, 0xf3, 0x0e, 0x56, 0xc4, + 0x24, 0x30, 0xf5, 0xe9, 0x36, 0x71, 0xbc, 0xc9, 0x70, 0x2c, + 0x6c, 0x4c, 0x15, 0x43, 0x44, 0xa4, 0xfc, 0xf1, 0xd2, 0x71, + 0x6c, 0x4c, 0xce, 0x30, 0x6c, 0x05, 0x7d, 0x2e, 0xb7, 0xbc, + 0xe4, 0x65, 0x76, 0x24, 0x75, 0x36, 0xdf, 0x28, 0xfc, 0xcd, + 0x9a, 0xba, 0xc2, 0xcd, 0xb0, 0x30, 0xdb, 0xe7, 0x2e, 0x3c, + 0x92, 0x63, 0x1d, 0x30, 0x23, 0x74, 0xb1, 0xb8, 0xcc, 0xd7, + 0xb6, 0x90, 0x65, 0x73, 0xa2, 0x2a, 0x6e, 0x49, 0x95, 0x0d, + 0xab, 0x24, 0xdf, 0x2d, 0xbf, 0x76, 0x46, 0x01, 0x44, 0xe4, + 0x18, 0x8e, 0xd5, 0x9a, 0x76, 0xc9, 0xc6, 0xbc, 0xdb, 0x7f, + 0x80, 0x52, 0xc6, 0x40, 0x41, 0x12, 0x36, 0x7c, 0x80, 0x69, + 0xce, 0x7b, 0xe1, 0xa0, 0x53, 0xa2, 0xd6, 0x8f, 0x3f, 0xf7, + 0xd7, 0x61, 0x09, 0x70, 0xa2, 0xa0, 0xc6, 0xaf, 0xa0, 0xd0, + 0xfa, 0x13, 0xbf, 0xc0, 0x69, 0x15, 0xce, 0x15, 0xec, 0x24, + 0x4b, 0x6b, 0xdc, 0x93, 0x51, 0xc6, 0x82, 0x19, 0x92, 0x84, + 0x5d, 0x99, 0xb0, 0x90, 0x2c, 0xcc, 0x2a, 0x81, 0x6b, 0x22, + 0x64, 0x0a, 0xcb, 0x51, 0x25, 0x82, 0x50, 0x02, 0x2d, 0x3e, + 0xd4, 0x72, 0xb3, 0x0c, 0x15, 0x77, 0xd2, 0xca, 0x98, 0x2f, + 0x41, 0x93, 0x14, 0xb2, 0x7f, 0xa1, 0x97, 0xa3, 0xb8, 0x8a, + 0x56, 0x24, 0x38, 0xa7, 0x36, 0xc5, 0x01, 0xc0, 0x9f, 0x3f, + 0x3e, 0x9a, 0xf6, 0xe9, 0x16, 0x82, 0x01, 0x58, 0x70, 0x0e, + 0x0d, 0xbc, 0xfa, 0x03, 0x57, 0x65, 0xa8, 0x5a, 0x3d, 0x57, + 0x81, 0x23, 0xbe, 0x6e, 0xa9, 0xe8, 0x22, 0xdf, 0x2f, 0x70, + 0xeb, 0x0a, 0x03, 0x96, 0x6b, 0xef, 0x20, 0x9f, 0xf2, 0x62, + 0xe7, 0xb2, 0x6e, 0x3a, 0x1e, 0x40, 0x1f, 0xd2, 0x97, 0x48, + 0xd1, 0x18, 0xf0, 0xeb, 0x52, 0x58, 0x02, 0x26, 0xce, 0x75, + 0xb1, 0x3a, 0x9d, 0x5b, 0x52, 0x94, 0xb2, 0x6e, 0x0e, 0x3f, + 0x39, 0xb6, 0xd9, 0x8a, 0x9d, 0xe8, 0x7c, 0x83, 0x32, 0xcc, + 0x43, 0x35, 0x9b, 0x7a, 0xed, 0xb2, 0x1e, 0x51, 0x37, 0x6c, + 0x14, 0xd8, 0xb8, 0x55, 0xb3, 0x91, 0xef, 0x0c, 0x3a, 0xe5, + 0x77, 0xd0, 0xbd, 0xb0, 0x7d, 0x38, 0x84, 0x2a, 0x47, 0xb2, + 0xb6, 0xda, 0xd7, 0x75, 0xd6, 0x2e, 0x60, 0xc7, 0x10, 0x52, + 0xf7, 0xdd, 0x09, 0x15, 0x6f, 0x04, 0x31, 0xc3, 0x5a, 0x6b, + 0x0c, 0x60, 0x10, 0xa8, 0x6e, 0x20, 0xa9, 0xdd, 0xb7, 0x72, + 0xc3, 0x9e, 0x85, 0xd2, 0x8f, 0x16, 0x7e, 0x3d, 0xe0, 0x63, + 0x81, 0x32, 0xfd, 0xca, 0xbc, 0x0f, 0xef, 0x3e, 0x74, 0x6a, + 0xb1, 0x60, 0xc1, 0x10, 0x50, 0x7c, 0x67, 0xa4, 0x19, 0xa7, + 0xb8, 0xed, 0xe6, 0xf5, 0x4e, 0x41, 0x53, 0xa6, 0x72, 0x1b, + 0x2c, 0x33, 0x6a, 0x37, 0xf1, 0xb5, 0x1c, 0x01, 0x7d, 0xa2, + 0x1f, 0x2c, 0x4e, 0x0a, 0xbf, 0xd4, 0x2c, 0x24, 0x91, 0x58, + 0x62, 0xfb, 0xf8, 0x63, 0xd9, 0xf8, 0x78, 0xf5, 0xc7, 0x78, + 0x32, 0xda, 0x99, 0xeb, 0x58, 0x20, 0x25, 0x19, 0xb1, 0x06, + 0x7f, 0x6a, 0x29, 0x20, 0xdb, 0xc8, 0x22, 0x48, 0xa9, 0x7f, + 0x24, 0x54, 0x8d, 0x7d, 0x8d, 0xb1, 0x69, 0xb2, 0xa3, 0x98, + 0x14, 0x0f, 0xba, 0xfa, 0xb6, 0x15, 0xe8, 0x28, 0x99, 0x3f, + 0x30, 0x04, 0x50, 0xab, 0x5a, 0x3c, 0xf1, 0x97, 0xe1, 0xc8, + 0x0f, 0x0e, 0xb4, 0x11, 0x63, 0x5a, 0x79, 0x08, 0x48, 0x75, + 0xaf, 0x9b, 0xca, 0xd9, 0x13, 0x18, 0xcc, 0xb1, 0xb3, 0xee, + 0xdd, 0x63, 0xdd, 0xf4, 0x21, 0x98, 0x76, 0xe2, 0x3e, 0xd5, + 0x86, 0x23, 0x33, 0x7e, 0xc7, 0xb4, 0x35, 0x4b, 0xc2, 0x2d, + 0xe1, 0xe2, 0xb0, 0x6c, 0x8b, 0x9b, 0x20, 0x3d, 0x48, 0x24, + 0x7c, 0xea, 0xa1, 0x75, 0x27, 0xe5, 0xf4, 0x70, 0xeb, 0x3b, + 0xc7, 0x26, 0x37, 0x04, 0xff, 0x8a, 0x7a, 0xd0, 0xc2, 0xb7, + 0x84, 0xb7, 0x29, 0xfb, 0x0e, 0xa3, 0xa8, 0x71, 0xcd, 0x58, + 0x06, 0x36, 0xe2, 0xf2, 0x77, 0xcc, 0x0f, 0x78, 0x08, 0x2b, + 0xbb, 0xe3, 0x53, 0x05, 0x71, 0xdc, 0x6c, 0x37, 0x32, 0x91, + 0x46, 0x42, 0x4f, 0x21, 0xe0, 0x34, 0xad, 0x3f, 0x30, 0x5a, + 0xc7, 0x0d, 0x17, 0x19, 0x39, 0x31, 0x58, 0x69, 0x3c, 0x8c, + 0xbe, 0xe7, 0xa6, 0x3b, 0xad, 0xfb, 0x46, 0x89, 0x06, 0xc1, + 0x8c, 0x16, 0x9a, 0x06, 0x3a, 0xd0, 0x7e, 0xd6, 0xb0, 0x7b, + 0x7d, 0xf8, 0x91, 0x7c, 0xfa, 0xd9, 0x66, 0x39, 0xfa, 0xbc, + 0x57, 0xa7, 0x78, 0x8b, 0x36, 0x78, 0xc0, 0x1c, 0x0e, 0x23, + 0x05, 0x0e, 0x04, 0x61, 0x16, 0x34, 0xf9, 0xc6, 0x63, 0x58, + 0xdf, 0xf4, 0x52, 0xce, 0xd0, 0x0f, 0x0c, 0xec, 0xb1, 0x82, + 0xf4, 0x72, 0x73, 0x72, 0x3f, 0x02, 0xbe, 0xe3, 0x9c, 0x63, + 0x73, 0xc8, 0x21, 0x65, 0xba, 0x57, 0x52, 0xa9, 0x19, 0xac, + 0x68, 0x50, 0xbd, 0x2d, 0x72, 0x5b, 0x93, 0x0f, 0x1c, 0x81, + 0x77, 0xd7, 0x2e, 0xc3, 0x93, 0x52, 0x6e, 0xdc, 0x79, 0x52, + 0x9f, 0xe3, 0xde, 0xe1, 0xba, 0x58, 0x55, 0xab, 0x8a, 0xf2, + 0x35, 0x6a, 0xcf, 0x94, 0x1f, 0x17, 0xa4, 0x23, 0x2e, 0x8e, + 0x18, 0x21, 0xbe, 0x14, 0xfa, 0xe7, 0x59, 0xc5, 0x44, 0x34, + 0xce, 0x03, 0xf4, 0xb7, 0x75, 0xd3, 0x51, 0x55, 0xdf, 0xff, + 0xcf, 0x4f, 0x44, 0xee, 0x13, 0x9b, 0xcb, 0x12, 0xae, 0xe5, + 0x5b, 0x44, 0x65, 0x28, 0xcb, 0x6a, 0x9c, 0x24, 0x1d, 0xea, + 0x2d, 0x5e, 0xa5, 0xc3, 0x78, 0xad, 0xed, 0x0c, 0x05, 0xa6, + 0xaf, 0x95, 0x04, 0xd2, 0xb5, 0x91, 0x0e, 0xa0, 0x06, 0x77, + 0xc5, 0x82, 0xf6, 0xdd, 0x72, 0x83, 0x04, 0xcc, 0xb0, 0xab, + 0x7a, 0xf0, 0xb4, 0x4d, 0x36, 0x71, 0x72, 0x1a, 0x9a, 0x0d, + 0xcd, 0xa3, 0x11, 0xa8, 0x0d, 0x7d, 0x49, 0xce, 0x9c, 0x09, + 0x1d, 0x08, 0xa4, 0x39, 0x2e, 0x03, 0xdf, 0x3a, 0xc8, 0xfe, + 0x6a, 0x2b, 0x0b, 0x07, 0x80, 0x55, 0x8a, 0xa8, 0xe6, 0x0e, + 0xc9, 0x7e, 0x83, 0xce, 0x3a, 0x98, 0x98, 0x4e, 0x3e, 0x08, + 0x20, 0x8f, 0x10, 0xfc, 0xc1, 0xc4, 0xcf, 0x37, 0x8d, 0x69, + 0xd8, 0x57, 0x9d, 0x48, 0x80, 0x6a, 0xef, 0x0c, 0xdd, 0x27, + 0x99, 0xf9, 0xe7, 0xd0, 0xd2, 0x36, 0xd8, 0xed, 0x41, 0x14, + 0x1b, 0x10, +}; +static const int sizeof_bench_dilithium_level3_pubkey = + sizeof(bench_dilithium_level3_pubkey); + +#endif /* !WOLFSSL_DILITHIUM_NO_VERIFY */ + +#ifndef WOLFSSL_DILITHIUM_NO_SIGN + +static const unsigned char bench_dilithium_level5_key[] = { + 0xef, 0x49, 0x79, 0x47, 0x15, 0xc4, 0x8a, 0xa9, 0x74, 0x2a, + 0xf0, 0x36, 0x94, 0x5c, 0x91, 0x1c, 0x5d, 0xff, 0x2c, 0x83, + 0xf2, 0x8b, 0x04, 0xfc, 0x5d, 0x64, 0xbd, 0x49, 0x73, 0xcd, + 0xcc, 0x99, 0xfd, 0x0f, 0x8f, 0x6e, 0xad, 0x75, 0x9b, 0xc9, + 0xb1, 0xb9, 0x90, 0x93, 0xbf, 0xce, 0x02, 0x2d, 0x12, 0x0c, + 0x54, 0x2e, 0xe2, 0x3e, 0x52, 0xff, 0xe0, 0x7a, 0xca, 0x2d, + 0x81, 0x84, 0xea, 0x16, 0x1f, 0x10, 0xc4, 0xc9, 0xde, 0xcd, + 0xf6, 0xbd, 0x60, 0xc9, 0xb3, 0xd0, 0x0f, 0x57, 0xeb, 0x71, + 0x78, 0x9b, 0xb5, 0x72, 0x2a, 0x65, 0x11, 0x14, 0xff, 0x63, + 0x8d, 0x38, 0xcf, 0xa4, 0xf4, 0xad, 0xd0, 0x68, 0x84, 0x97, + 0xfe, 0xd3, 0x91, 0xa0, 0xe4, 0xc3, 0x74, 0xcf, 0x20, 0x87, + 0x89, 0x84, 0x1f, 0x75, 0x91, 0xe3, 0xb3, 0x47, 0x8b, 0xfe, + 0x76, 0xb7, 0x2d, 0x30, 0x89, 0x02, 0x04, 0xc9, 0x93, 0xa8, + 0x31, 0xd3, 0x84, 0x2d, 0xe4, 0x26, 0x12, 0xdb, 0x94, 0x08, + 0x12, 0x45, 0x45, 0xca, 0x44, 0x89, 0x52, 0xc4, 0x28, 0x41, + 0x46, 0x01, 0x1c, 0x93, 0x20, 0x8b, 0x40, 0x6d, 0x09, 0x36, + 0x65, 0x4c, 0xa2, 0x40, 0x62, 0xb8, 0x2c, 0x1b, 0x00, 0x20, + 0x61, 0x42, 0x8c, 0x24, 0xa7, 0x10, 0x19, 0x27, 0x25, 0x22, + 0x14, 0x31, 0x13, 0x33, 0x46, 0x0c, 0x22, 0x22, 0x18, 0xa7, + 0x91, 0x0c, 0x24, 0x61, 0xd9, 0x32, 0x46, 0xc8, 0x96, 0x49, + 0x5c, 0x90, 0x89, 0x9b, 0x84, 0x01, 0x5c, 0x08, 0x42, 0x64, + 0x84, 0x85, 0x0c, 0x42, 0x21, 0x20, 0x48, 0x21, 0x92, 0x00, + 0x28, 0x83, 0x20, 0x4c, 0x08, 0xc7, 0x51, 0x99, 0x06, 0x66, + 0x01, 0x18, 0x51, 0x13, 0x48, 0x0a, 0x0b, 0x42, 0x90, 0x4c, + 0x14, 0x08, 0x83, 0x14, 0x6d, 0x10, 0x10, 0x91, 0xe2, 0xc4, + 0x8d, 0xe1, 0x12, 0x11, 0x10, 0x40, 0x29, 0x99, 0x92, 0x30, + 0x12, 0x39, 0x6c, 0x91, 0x86, 0x68, 0x08, 0x83, 0x0c, 0x54, + 0x80, 0x80, 0xa2, 0x08, 0x52, 0x09, 0x30, 0x71, 0x0c, 0x10, + 0x04, 0x53, 0x00, 0x65, 0x91, 0x12, 0x2d, 0x0c, 0xa2, 0x8c, + 0x18, 0x14, 0x45, 0xd8, 0x14, 0x06, 0xe4, 0x36, 0x72, 0x93, + 0x10, 0x68, 0x09, 0xc2, 0x08, 0x51, 0x14, 0x8c, 0x13, 0x39, + 0x11, 0xd8, 0x44, 0x02, 0x18, 0x39, 0x29, 0x98, 0x16, 0x71, + 0x82, 0x40, 0x70, 0x01, 0x10, 0x8c, 0x1a, 0x30, 0x08, 0x02, + 0x03, 0x41, 0x5a, 0x00, 0x40, 0xa4, 0x16, 0x90, 0x20, 0x26, + 0x32, 0x00, 0x49, 0x61, 0x20, 0x20, 0x0c, 0x1a, 0xb0, 0x10, + 0x63, 0x10, 0x11, 0x58, 0x30, 0x0d, 0x59, 0x80, 0x68, 0x90, + 0x46, 0x2a, 0x91, 0xa8, 0x71, 0x98, 0x20, 0x40, 0x21, 0x83, + 0x6c, 0xc0, 0x48, 0x0d, 0x8b, 0x90, 0x11, 0x08, 0x09, 0x31, + 0x8c, 0x00, 0x12, 0x10, 0x14, 0x6e, 0xc2, 0x06, 0x32, 0x1a, + 0x26, 0x10, 0x0a, 0x91, 0x44, 0x08, 0x99, 0x8d, 0x60, 0x86, + 0x28, 0x11, 0x20, 0x6d, 0xa3, 0x12, 0x81, 0x8b, 0xc6, 0x51, + 0xcb, 0xa0, 0x61, 0x09, 0x97, 0x61, 0x48, 0xb6, 0x0d, 0x21, + 0x49, 0x51, 0x08, 0x13, 0x0c, 0x0a, 0x34, 0x86, 0x49, 0x80, + 0x65, 0x14, 0x39, 0x04, 0x21, 0x01, 0x81, 0x9a, 0xb8, 0x4d, + 0x04, 0x41, 0x48, 0x03, 0x92, 0x81, 0x62, 0x14, 0x6c, 0x10, + 0x16, 0x11, 0xe2, 0xa2, 0x49, 0xe3, 0x30, 0x65, 0x04, 0x93, + 0x8d, 0x1c, 0x33, 0x70, 0x1b, 0x15, 0x50, 0xe4, 0x38, 0x80, + 0x21, 0x37, 0x06, 0x20, 0xc6, 0x24, 0xc8, 0x22, 0x88, 0x4a, + 0x44, 0x80, 0x14, 0x43, 0x88, 0x54, 0x44, 0x42, 0x11, 0x49, + 0x41, 0x19, 0xb9, 0x2d, 0xcc, 0x04, 0x0d, 0x19, 0xc1, 0x65, + 0x5b, 0xa0, 0x11, 0x94, 0x00, 0x84, 0xe4, 0xb6, 0x41, 0xc2, + 0x18, 0x72, 0x5c, 0x02, 0x69, 0x11, 0x85, 0x24, 0x13, 0x35, + 0x00, 0x62, 0x34, 0x04, 0x58, 0x40, 0x21, 0x00, 0xc4, 0x28, + 0x0c, 0x17, 0x30, 0x10, 0x47, 0x60, 0x4b, 0xc2, 0x61, 0x9c, + 0x80, 0x2c, 0x20, 0x94, 0x31, 0x58, 0x92, 0x09, 0xcc, 0x00, + 0x02, 0x42, 0x94, 0x69, 0x99, 0x28, 0x06, 0x98, 0x02, 0x52, + 0x90, 0x32, 0x6e, 0x8a, 0x18, 0x2e, 0x54, 0x94, 0x81, 0x03, + 0xc6, 0x89, 0x03, 0xa1, 0x84, 0x48, 0x82, 0x48, 0x52, 0xc4, + 0x00, 0x91, 0x30, 0x24, 0x20, 0x12, 0x0d, 0x83, 0x80, 0x05, + 0x92, 0x48, 0x61, 0x98, 0x46, 0x92, 0xe1, 0xa6, 0x25, 0x20, + 0x93, 0x4d, 0x1c, 0x37, 0x2c, 0x9b, 0x94, 0x8d, 0xc8, 0x88, + 0x80, 0xa2, 0x18, 0x72, 0x0c, 0x09, 0x70, 0x81, 0x36, 0x90, + 0x24, 0x45, 0x69, 0x53, 0x36, 0x6c, 0xd2, 0x20, 0x51, 0x23, + 0xc1, 0x8c, 0x62, 0xb0, 0x70, 0x11, 0xb2, 0x70, 0xcb, 0x84, + 0x69, 0x4b, 0x32, 0x89, 0x01, 0x21, 0x81, 0x02, 0x38, 0x66, + 0xa3, 0x26, 0x12, 0x24, 0xa3, 0x30, 0x22, 0x24, 0x84, 0x18, + 0xb9, 0x84, 0x40, 0x16, 0x50, 0x22, 0x44, 0x31, 0x1b, 0x13, + 0x8d, 0x53, 0x02, 0x89, 0x4a, 0x22, 0x10, 0x53, 0x18, 0x01, + 0x58, 0x30, 0x2d, 0x00, 0x05, 0x08, 0x13, 0x80, 0x84, 0xc2, + 0x22, 0x0e, 0x88, 0x26, 0x2a, 0x04, 0xc4, 0x4c, 0x19, 0x43, + 0x01, 0xc8, 0x38, 0x4c, 0xd1, 0xb2, 0x90, 0x13, 0x29, 0x10, + 0x12, 0x48, 0x22, 0x01, 0xa8, 0x51, 0xd1, 0x92, 0x40, 0x11, + 0x27, 0x62, 0x10, 0x01, 0x0c, 0x0c, 0xc6, 0x28, 0xe3, 0x46, + 0x60, 0x24, 0x01, 0x8d, 0x14, 0xb6, 0x10, 0x50, 0xb6, 0x25, + 0x44, 0x38, 0x40, 0x44, 0xc2, 0x0c, 0x19, 0xc0, 0x64, 0x9c, + 0x44, 0x02, 0x21, 0x25, 0x65, 0x02, 0x23, 0x86, 0x1a, 0x12, + 0x70, 0x51, 0x24, 0x91, 0x09, 0x08, 0x44, 0x09, 0x35, 0x66, + 0x91, 0x04, 0x12, 0x43, 0x42, 0x8d, 0x22, 0xa0, 0x70, 0x14, + 0x91, 0x25, 0xa0, 0x00, 0x80, 0xe4, 0x00, 0x90, 0x44, 0xb2, + 0x61, 0x14, 0x20, 0x6e, 0xca, 0x14, 0x0d, 0x23, 0x85, 0x68, + 0xda, 0x40, 0x92, 0x0b, 0xb1, 0x20, 0x92, 0x04, 0x46, 0xc0, + 0x08, 0x8a, 0x40, 0xc4, 0x4d, 0x0c, 0x17, 0x45, 0xd3, 0x18, + 0x52, 0x1b, 0x46, 0x24, 0xc2, 0x24, 0x71, 0x83, 0x10, 0x80, + 0xc8, 0x82, 0x68, 0xc2, 0x96, 0x81, 0x0a, 0x01, 0x92, 0x60, + 0xb4, 0x84, 0x09, 0xc6, 0x00, 0x04, 0x37, 0x90, 0x0b, 0xa0, + 0x28, 0x12, 0x27, 0x09, 0x94, 0x80, 0x50, 0xd8, 0x04, 0x86, + 0x08, 0x13, 0x8a, 0x4a, 0x06, 0x89, 0x9b, 0xc4, 0x60, 0xe3, + 0xa2, 0x20, 0xe0, 0x38, 0x21, 0x22, 0xb4, 0x68, 0x0a, 0xa1, + 0x0c, 0x01, 0x24, 0x32, 0x4c, 0x48, 0x30, 0xa2, 0x80, 0x8d, + 0x58, 0x44, 0x10, 0xc8, 0x94, 0x6d, 0x21, 0xc3, 0x61, 0xcb, + 0x98, 0x24, 0xdc, 0x38, 0x11, 0xc9, 0x18, 0x11, 0x20, 0x01, + 0x50, 0x1c, 0x34, 0x8d, 0x02, 0x03, 0x09, 0x0a, 0x40, 0x61, + 0xd4, 0xb8, 0x84, 0x9c, 0xc2, 0x09, 0x04, 0xb1, 0x89, 0x83, + 0x86, 0x84, 0x19, 0x83, 0x0c, 0x5a, 0x86, 0x89, 0x10, 0x21, + 0x0d, 0xd1, 0xc2, 0x80, 0x18, 0x29, 0x2a, 0x0c, 0x01, 0x50, + 0x89, 0x88, 0x48, 0x03, 0xa7, 0x85, 0x21, 0x92, 0x64, 0xc4, + 0x16, 0x81, 0x94, 0x06, 0x6c, 0x53, 0x26, 0x12, 0x90, 0xb6, + 0x21, 0x0b, 0xa8, 0x64, 0x43, 0x96, 0x84, 0x41, 0x88, 0x70, + 0xe3, 0xa6, 0x44, 0x12, 0xc0, 0x09, 0x01, 0xc7, 0x60, 0xc3, + 0x20, 0x42, 0xc3, 0x40, 0x68, 0x10, 0xa6, 0x51, 0xa4, 0xa0, + 0x71, 0x54, 0x98, 0x04, 0x88, 0xb2, 0x00, 0x54, 0x18, 0x6a, + 0x48, 0x98, 0x20, 0x21, 0xb2, 0x8d, 0x82, 0x20, 0x81, 0x99, + 0x16, 0x81, 0x0a, 0xc5, 0x88, 0x0a, 0x23, 0x11, 0x8a, 0x16, + 0x44, 0x24, 0xc9, 0x29, 0x59, 0x08, 0x91, 0x1c, 0x29, 0x05, + 0x14, 0xc9, 0x44, 0xe3, 0x20, 0x10, 0x1b, 0xa1, 0x64, 0x82, + 0xa2, 0x90, 0x00, 0x00, 0x82, 0x98, 0xb2, 0x85, 0xc8, 0x04, + 0x28, 0xc8, 0xb2, 0x65, 0xc9, 0xc6, 0x88, 0xcc, 0x08, 0x91, + 0x84, 0x08, 0x30, 0x94, 0x94, 0x8d, 0xc0, 0x18, 0x46, 0x82, + 0x36, 0x4c, 0x83, 0x10, 0x72, 0x23, 0xb1, 0x88, 0x81, 0x20, + 0x8e, 0x19, 0x03, 0x8a, 0x94, 0x46, 0x22, 0x21, 0x35, 0x8e, + 0x04, 0xc0, 0x88, 0x5b, 0xb6, 0x09, 0x0a, 0x18, 0x44, 0x21, + 0x90, 0x65, 0x03, 0xb2, 0x21, 0xc4, 0x10, 0x50, 0xc1, 0x80, + 0x0c, 0x09, 0x40, 0x49, 0xe4, 0xa8, 0x8c, 0xa4, 0x36, 0x61, + 0x59, 0x12, 0x86, 0x20, 0x08, 0x2d, 0x10, 0x19, 0x85, 0xe4, + 0x34, 0x60, 0xc4, 0xb6, 0x60, 0x00, 0x18, 0x06, 0x8c, 0xb8, + 0x45, 0x19, 0x13, 0x4a, 0x53, 0xc4, 0x40, 0xc9, 0x38, 0x71, + 0xd9, 0x48, 0x10, 0x59, 0x08, 0x02, 0x02, 0x10, 0x69, 0x53, + 0x28, 0x80, 0x22, 0x81, 0x4c, 0xc9, 0x16, 0x26, 0xa1, 0x48, + 0x64, 0x19, 0x21, 0x11, 0x1c, 0x37, 0x88, 0x4b, 0x94, 0x2c, + 0x48, 0xc8, 0x6c, 0x63, 0x88, 0x65, 0x81, 0x40, 0x61, 0xa1, + 0x44, 0x31, 0x82, 0x18, 0x08, 0x80, 0x00, 0x26, 0x50, 0x14, + 0x49, 0xa1, 0x32, 0x50, 0x02, 0xc8, 0x45, 0x0c, 0x07, 0x24, + 0x13, 0x01, 0x6d, 0x0a, 0xb3, 0x90, 0x64, 0x30, 0x85, 0x21, + 0x09, 0x61, 0x44, 0x44, 0x72, 0x08, 0x32, 0x06, 0xe1, 0xa2, + 0x21, 0xdb, 0xa4, 0x09, 0x5a, 0xb4, 0x71, 0x43, 0xb2, 0x09, + 0x82, 0xc4, 0x64, 0x88, 0xa0, 0x91, 0xca, 0x14, 0x90, 0xa4, + 0xa8, 0x41, 0xc1, 0x38, 0x85, 0x12, 0x32, 0x60, 0x1a, 0x11, + 0x72, 0x53, 0x32, 0x2c, 0xe3, 0x08, 0x4d, 0x24, 0xc6, 0x28, + 0x0a, 0x03, 0x8c, 0x88, 0x06, 0x05, 0xa0, 0xa8, 0x05, 0x84, + 0xa2, 0x4c, 0x80, 0x40, 0x62, 0xda, 0x24, 0x81, 0x9a, 0x16, + 0x91, 0x24, 0x81, 0x04, 0xa4, 0x46, 0x51, 0xc2, 0xa8, 0x25, + 0x20, 0x28, 0x42, 0x13, 0x46, 0x2c, 0x63, 0x42, 0x72, 0x03, + 0x88, 0x28, 0xa3, 0x22, 0x24, 0x1a, 0x02, 0x26, 0x42, 0xa2, + 0x11, 0x11, 0xb0, 0x51, 0x92, 0xb4, 0x6c, 0xe2, 0x32, 0x85, + 0x10, 0xc2, 0x41, 0xc1, 0x40, 0x46, 0x4c, 0x26, 0x01, 0x1c, + 0x35, 0x02, 0x0c, 0x14, 0x0c, 0x18, 0x81, 0x00, 0x10, 0x26, + 0x02, 0xc8, 0x32, 0x8c, 0xe4, 0x02, 0x68, 0xcc, 0x14, 0x2e, + 0x89, 0x38, 0x60, 0x10, 0x12, 0x24, 0x93, 0x42, 0x65, 0xe3, + 0x24, 0x29, 0x08, 0x80, 0x41, 0x09, 0x29, 0x46, 0x5b, 0x26, + 0x49, 0x5b, 0x30, 0x80, 0x03, 0xc1, 0x2c, 0x04, 0x09, 0x82, + 0x4c, 0x48, 0x2d, 0x1c, 0x36, 0x4d, 0xdb, 0x02, 0x86, 0x21, + 0xb5, 0x51, 0x81, 0x80, 0x2d, 0xcb, 0x20, 0x81, 0x5b, 0x34, + 0x41, 0x89, 0x36, 0x48, 0x44, 0xa0, 0x05, 0x59, 0xb6, 0x64, + 0x12, 0x45, 0x21, 0x20, 0x31, 0x51, 0x0a, 0xc3, 0x8c, 0x14, + 0x48, 0x71, 0x18, 0x35, 0x24, 0x20, 0x45, 0x05, 0x88, 0x20, + 0x09, 0x08, 0xb1, 0x29, 0x18, 0xa0, 0x09, 0x4a, 0x00, 0x8a, + 0xe2, 0xb8, 0x45, 0x02, 0x27, 0x89, 0xd8, 0x10, 0x25, 0x51, + 0x82, 0x8c, 0x13, 0x92, 0x30, 0x1c, 0x24, 0x8e, 0x1c, 0x93, + 0x4d, 0xa3, 0x48, 0x51, 0x93, 0xa8, 0x69, 0xe2, 0x04, 0x89, + 0x13, 0x13, 0x61, 0xcb, 0x98, 0x8c, 0x09, 0x21, 0x62, 0x4b, + 0x14, 0x4e, 0x11, 0xa3, 0x09, 0x98, 0x40, 0x42, 0x91, 0x12, + 0x08, 0x80, 0x84, 0x2d, 0xc0, 0x12, 0x60, 0x03, 0xa4, 0x29, + 0x18, 0x80, 0x01, 0x94, 0x44, 0x8a, 0x12, 0x11, 0x72, 0xc4, + 0x22, 0x32, 0x9a, 0x46, 0x88, 0x1b, 0x16, 0x4d, 0x4b, 0x08, + 0x11, 0x02, 0x48, 0x45, 0x81, 0xa4, 0x64, 0xe1, 0x88, 0x0c, + 0x63, 0x10, 0x70, 0x48, 0x98, 0x05, 0x9b, 0xb8, 0x84, 0x03, + 0x14, 0x05, 0x44, 0x86, 0x0c, 0x20, 0x11, 0x68, 0xbe, 0x71, + 0x83, 0xc2, 0x69, 0xde, 0x49, 0xad, 0xb4, 0xdb, 0x93, 0xcb, + 0x20, 0x2b, 0xbd, 0x95, 0x97, 0x57, 0x7e, 0xcb, 0xbc, 0x73, + 0xb6, 0x3d, 0x16, 0x4a, 0x0e, 0xe4, 0x9c, 0x81, 0xb1, 0x5d, + 0x27, 0x64, 0xa2, 0x14, 0x12, 0x1b, 0x8e, 0xd0, 0xd8, 0x38, + 0xf6, 0xc7, 0xbb, 0x9f, 0x77, 0x3c, 0x62, 0x04, 0x92, 0xe1, + 0x97, 0xaf, 0x24, 0xa7, 0xf9, 0xf0, 0x8d, 0x3a, 0xbf, 0x5d, + 0xab, 0x5c, 0x97, 0x0f, 0xfc, 0x35, 0xbc, 0x62, 0xd8, 0x42, + 0xfd, 0xc7, 0x8b, 0xf7, 0x80, 0xd1, 0x38, 0x68, 0x14, 0x5e, + 0x4f, 0x99, 0x31, 0xc7, 0xaf, 0xbd, 0x27, 0xce, 0x1c, 0x5b, + 0x09, 0x1b, 0xcf, 0xbb, 0xfb, 0xf9, 0xf4, 0x90, 0x4c, 0xc1, + 0xa2, 0x12, 0xf9, 0xd0, 0xa5, 0x2c, 0xfd, 0x7b, 0x55, 0xb0, + 0xb1, 0xc6, 0x42, 0xe6, 0xeb, 0x10, 0x5e, 0xe9, 0x00, 0xe8, + 0x46, 0xe4, 0xe0, 0x8b, 0x21, 0xbc, 0xb1, 0xa9, 0x9e, 0x75, + 0x66, 0xf0, 0xb8, 0x87, 0xb9, 0x11, 0x7e, 0x28, 0x6c, 0x4d, + 0x58, 0xcd, 0x54, 0x71, 0x0c, 0x6a, 0xcc, 0xfb, 0x52, 0xc2, + 0x5b, 0xcc, 0x19, 0x67, 0x4f, 0xc2, 0x2f, 0x09, 0x62, 0x51, + 0x82, 0xeb, 0x9b, 0x94, 0x11, 0xb4, 0x5a, 0x67, 0x7f, 0x58, + 0x18, 0xb2, 0x3f, 0x37, 0x1f, 0x94, 0x44, 0x73, 0x6a, 0x02, + 0xf5, 0xfb, 0x5b, 0x03, 0xac, 0x5d, 0xc6, 0xa9, 0x79, 0x8f, + 0x0f, 0x50, 0xa0, 0x57, 0x46, 0x05, 0x6d, 0x58, 0xde, 0x6e, + 0x8d, 0x9c, 0x0e, 0x6a, 0xb5, 0x9b, 0x1b, 0x22, 0x74, 0xad, + 0x00, 0x55, 0x27, 0x46, 0xce, 0xbb, 0x82, 0x77, 0x4e, 0x6e, + 0x59, 0x38, 0x26, 0xb3, 0xc7, 0xbc, 0x97, 0x54, 0x83, 0x69, + 0x1f, 0x3e, 0xbd, 0x0f, 0xff, 0x2f, 0xca, 0xb9, 0xea, 0x91, + 0x26, 0x8e, 0x0a, 0x78, 0x25, 0xf6, 0x6b, 0x11, 0x30, 0xd7, + 0xe2, 0xf4, 0x2b, 0xda, 0xcf, 0xe1, 0x4a, 0x47, 0xab, 0x5f, + 0x54, 0x34, 0x38, 0xac, 0xd1, 0xbf, 0x45, 0xad, 0x4b, 0x52, + 0x0f, 0x4c, 0xa2, 0xac, 0x22, 0x7c, 0xb6, 0xed, 0x7f, 0xd5, + 0x63, 0x3b, 0x1a, 0x3b, 0xf2, 0x3d, 0x9b, 0x96, 0x92, 0x08, + 0xb9, 0x95, 0x13, 0xaf, 0x20, 0x26, 0x8b, 0x15, 0x97, 0x89, + 0xa5, 0x88, 0x8f, 0x78, 0xb4, 0x57, 0x9d, 0x51, 0x96, 0x9c, + 0x98, 0x93, 0xd5, 0x83, 0xf9, 0xff, 0x94, 0x29, 0x1e, 0xa5, + 0x28, 0xa4, 0x0c, 0x22, 0xab, 0xbc, 0x70, 0x48, 0xa2, 0x16, + 0x1c, 0xa4, 0xba, 0x8b, 0xfe, 0xb2, 0xa9, 0x03, 0x96, 0x5f, + 0xb4, 0x84, 0x8e, 0xb4, 0xbb, 0x7b, 0x11, 0xc5, 0xc2, 0xdb, + 0xe3, 0x88, 0xb5, 0xd3, 0xac, 0x07, 0x33, 0x53, 0xe8, 0x10, + 0x9e, 0xc5, 0x81, 0xb0, 0x77, 0x2f, 0x4f, 0x6d, 0x0d, 0x89, + 0xb4, 0x04, 0x98, 0x05, 0xe6, 0xd3, 0x36, 0x97, 0xcd, 0x3e, + 0x4d, 0xc6, 0x21, 0xe4, 0x0b, 0xcf, 0xed, 0xa7, 0x4d, 0xd9, + 0xd3, 0x25, 0xec, 0xec, 0x47, 0xfd, 0x06, 0x92, 0x77, 0x25, + 0x3c, 0x44, 0xe6, 0x5d, 0xb4, 0x35, 0x2b, 0x5d, 0x05, 0x65, + 0x63, 0x0b, 0xd9, 0xb8, 0x28, 0xdf, 0xdd, 0xfd, 0x64, 0x18, + 0x42, 0x19, 0x7f, 0x12, 0x78, 0xdd, 0xf0, 0x64, 0xd6, 0x99, + 0xb8, 0x74, 0x81, 0xe2, 0xb9, 0xc8, 0x67, 0x6d, 0x31, 0x22, + 0xa5, 0x68, 0xa1, 0x8d, 0x3e, 0x49, 0xbe, 0x10, 0x68, 0xa8, + 0x74, 0x1d, 0x18, 0xcf, 0x00, 0xe1, 0x4f, 0x77, 0xd8, 0xc6, + 0xe3, 0x08, 0xbb, 0x4c, 0xed, 0xff, 0xd9, 0x9b, 0xb0, 0xd1, + 0x50, 0xbb, 0x8b, 0x91, 0xcd, 0x5f, 0x2a, 0xfb, 0x8f, 0x4d, + 0x3c, 0x98, 0xba, 0xd7, 0x98, 0x99, 0xa7, 0x22, 0x14, 0xd7, + 0x94, 0xb5, 0xb8, 0xa4, 0x52, 0x31, 0xa7, 0xa1, 0xa4, 0x28, + 0xee, 0x31, 0xb5, 0xd0, 0xc1, 0x07, 0x05, 0x16, 0x1d, 0x53, + 0x45, 0x62, 0x23, 0x05, 0x44, 0xb6, 0x4f, 0x92, 0x03, 0x53, + 0x9a, 0x71, 0x56, 0xae, 0x16, 0x81, 0xb4, 0xc9, 0x98, 0xf4, + 0x7f, 0x11, 0x37, 0xc2, 0xc8, 0xf2, 0xe4, 0x48, 0xe3, 0xcc, + 0xf1, 0xe3, 0x3d, 0x8e, 0x13, 0x5b, 0x25, 0xad, 0xce, 0x6f, + 0xed, 0x60, 0x4f, 0x7d, 0x51, 0xe1, 0xd0, 0x74, 0xf4, 0xed, + 0xf3, 0x84, 0xa6, 0x0e, 0xba, 0xb4, 0x8e, 0x5a, 0xb9, 0x12, + 0x70, 0x43, 0x4c, 0xb5, 0xa5, 0x1e, 0x86, 0xa5, 0xe3, 0x4d, + 0x76, 0x95, 0xce, 0x2c, 0x53, 0x3a, 0x4e, 0x3f, 0x47, 0x73, + 0x85, 0x88, 0xd9, 0x39, 0x21, 0x83, 0x24, 0x68, 0x6a, 0x1e, + 0x77, 0xdf, 0x59, 0xc5, 0x1b, 0xe2, 0xb1, 0x47, 0x9d, 0xee, + 0x45, 0x1e, 0xc6, 0xd4, 0x43, 0xe2, 0xc7, 0x1c, 0x98, 0x84, + 0xe0, 0x39, 0xe9, 0x9f, 0xa0, 0xa2, 0x24, 0x4a, 0x88, 0x46, + 0xf3, 0x50, 0x52, 0xb5, 0xae, 0x37, 0x5c, 0xa1, 0x7d, 0xad, + 0x7c, 0x30, 0x3e, 0xcd, 0x80, 0x1c, 0xac, 0xf4, 0xe6, 0xb5, + 0x9f, 0x22, 0xb6, 0xfb, 0x0e, 0x6d, 0x80, 0x10, 0xf7, 0x3f, + 0xdd, 0x5b, 0xd9, 0xd4, 0x03, 0x14, 0x41, 0x90, 0x88, 0xa8, + 0xcf, 0x50, 0xa2, 0xf2, 0x7e, 0xf0, 0x0a, 0x7f, 0xed, 0x77, + 0x09, 0x48, 0x32, 0x55, 0xe9, 0x93, 0xe7, 0x27, 0x18, 0x46, + 0x17, 0x03, 0x25, 0x8e, 0x17, 0x5d, 0xe8, 0x9e, 0xb1, 0xb4, + 0x9d, 0x1a, 0x5e, 0xbe, 0xa8, 0xb8, 0x45, 0x30, 0xc6, 0xa5, + 0xb4, 0xaf, 0xf3, 0x0d, 0x91, 0x9c, 0xa9, 0x5b, 0x4c, 0xbb, + 0x19, 0x19, 0x39, 0x51, 0x36, 0x80, 0xf7, 0x10, 0xf7, 0x73, + 0x49, 0x17, 0xec, 0xbc, 0x92, 0x08, 0x21, 0xb1, 0x0c, 0x23, + 0xc4, 0xd6, 0xd2, 0xb3, 0xfd, 0xae, 0xe7, 0x71, 0xf3, 0x50, + 0x11, 0x27, 0x1a, 0x85, 0xf0, 0xab, 0xd8, 0x16, 0x64, 0xcb, + 0xad, 0xbb, 0xae, 0x54, 0x37, 0xa3, 0xa8, 0xf4, 0x09, 0x67, + 0x54, 0x61, 0x86, 0x0f, 0x0e, 0x25, 0x0d, 0xda, 0x4a, 0xc7, + 0xe7, 0x02, 0x80, 0x6b, 0x59, 0xd2, 0xc8, 0x88, 0x4d, 0x7d, + 0xfd, 0x3d, 0x48, 0x04, 0x6d, 0x95, 0xdf, 0xc2, 0x8b, 0x23, + 0x70, 0x4a, 0xf5, 0xdc, 0xc9, 0x24, 0x8d, 0x7e, 0x52, 0x22, + 0x7e, 0x9c, 0x5c, 0x32, 0xa5, 0xd5, 0xf2, 0x11, 0x08, 0xa0, + 0xd4, 0xa2, 0xd8, 0xdb, 0x1d, 0x9f, 0x1b, 0x54, 0x8f, 0xb5, + 0xf6, 0x71, 0x71, 0x49, 0xbc, 0x38, 0x09, 0xb6, 0x24, 0x94, + 0x80, 0x1f, 0x2d, 0x0c, 0xc7, 0xe4, 0xd6, 0xcd, 0xab, 0x53, + 0x79, 0x28, 0xed, 0x48, 0x23, 0x14, 0x2f, 0x0b, 0x3a, 0xd0, + 0xa7, 0x08, 0xe1, 0xfd, 0x1e, 0xb6, 0xdd, 0x12, 0x93, 0x2d, + 0x95, 0x06, 0xba, 0x95, 0xcb, 0x1a, 0xed, 0xfb, 0x60, 0xe7, + 0xf1, 0x1c, 0xad, 0xc3, 0xea, 0x8d, 0x3c, 0x53, 0x32, 0xb5, + 0x38, 0x26, 0xdd, 0x39, 0xf0, 0x39, 0x4e, 0x6f, 0x3e, 0xa9, + 0xea, 0x25, 0x29, 0xb8, 0x6c, 0x7d, 0x0a, 0x91, 0xd4, 0xb9, + 0x7b, 0x67, 0xe4, 0xe5, 0x63, 0xd7, 0x6b, 0x03, 0xa5, 0xd7, + 0xe8, 0xd2, 0xc0, 0x34, 0x53, 0xa6, 0x16, 0x21, 0x2a, 0x2a, + 0x09, 0xd3, 0xad, 0xa1, 0x2c, 0x6a, 0x88, 0x2d, 0x90, 0x06, + 0xba, 0x0b, 0xaa, 0xd1, 0xdb, 0xa4, 0xd0, 0x49, 0x0f, 0x42, + 0xe1, 0xca, 0xf0, 0x69, 0x15, 0x63, 0xcb, 0x0b, 0x4c, 0x2e, + 0x99, 0x20, 0x44, 0xe3, 0x6e, 0x32, 0x8a, 0xa1, 0x5c, 0x5b, + 0x03, 0xeb, 0xb5, 0x05, 0xff, 0x1a, 0x76, 0x38, 0x1c, 0xb0, + 0x74, 0xf1, 0x5a, 0x0d, 0x8a, 0xd2, 0x4e, 0x38, 0x11, 0x86, + 0xb0, 0x2d, 0xd3, 0x88, 0xe2, 0x0f, 0x51, 0x68, 0xb9, 0x79, + 0x96, 0x50, 0x95, 0xdc, 0x69, 0xcb, 0xa6, 0x25, 0x4a, 0xdf, + 0xa1, 0x39, 0x13, 0x47, 0x0a, 0xf0, 0xeb, 0xcb, 0x14, 0x01, + 0x28, 0x9c, 0x0f, 0xe2, 0x62, 0xca, 0xb5, 0x40, 0x51, 0x45, + 0x8e, 0x18, 0x88, 0xc9, 0x58, 0xaf, 0xb3, 0x48, 0xd5, 0x20, + 0xe8, 0xd8, 0x5b, 0xa2, 0x98, 0x74, 0x25, 0xfa, 0x25, 0x19, + 0x82, 0x22, 0xfa, 0x82, 0x7c, 0x38, 0x8d, 0x62, 0x86, 0x01, + 0x63, 0x20, 0x36, 0x8e, 0xaf, 0x15, 0x8a, 0x74, 0x1e, 0xfd, + 0x7f, 0xbe, 0x60, 0xc3, 0x65, 0x31, 0xce, 0xdb, 0x92, 0xb9, + 0x13, 0x2a, 0x78, 0xa9, 0xfc, 0x6a, 0x7b, 0x18, 0xec, 0x0c, + 0x7b, 0x4c, 0x86, 0xaf, 0xea, 0x6d, 0x52, 0x09, 0x76, 0x52, + 0x87, 0x8a, 0x0b, 0x2a, 0xf3, 0x93, 0x35, 0x92, 0x8b, 0x60, + 0x42, 0x2e, 0x12, 0xa9, 0xf7, 0x7c, 0x61, 0x5c, 0x8f, 0xc0, + 0xaa, 0x6e, 0x6a, 0xf6, 0x48, 0x48, 0xc6, 0x3e, 0xe0, 0x1d, + 0xb4, 0xfb, 0xc4, 0xd8, 0x01, 0xb8, 0xf2, 0xf4, 0xdf, 0xc1, + 0xba, 0xb5, 0xf2, 0x27, 0x3f, 0xdb, 0x78, 0x62, 0x1c, 0x0a, + 0xbe, 0xdb, 0xdd, 0x3c, 0x0c, 0x29, 0x85, 0xf1, 0x44, 0x5f, + 0x2b, 0x43, 0x80, 0x57, 0xa7, 0x5a, 0x4d, 0x1b, 0xbe, 0x03, + 0xe7, 0x55, 0x7b, 0x91, 0x9d, 0x4c, 0x8b, 0xd7, 0xfd, 0xde, + 0x65, 0x7e, 0xa8, 0x48, 0xbb, 0xa9, 0x96, 0x06, 0x7f, 0xc0, + 0x6c, 0xed, 0x87, 0x53, 0x77, 0xb4, 0x5a, 0x7c, 0xbb, 0xce, + 0xcf, 0x01, 0x08, 0x45, 0x61, 0xc1, 0x28, 0xb6, 0xf2, 0xb4, + 0x5b, 0x6b, 0x84, 0xfe, 0x18, 0x09, 0x39, 0xc1, 0xc8, 0x96, + 0x36, 0x6e, 0xba, 0x7e, 0x48, 0x12, 0xe6, 0xdc, 0x22, 0x48, + 0x17, 0x0b, 0xbd, 0x92, 0x64, 0xfa, 0xc9, 0x9b, 0x07, 0xda, + 0xed, 0x04, 0x68, 0x42, 0x15, 0x8c, 0xf9, 0xd8, 0xc3, 0x0d, + 0x21, 0x9d, 0x96, 0xbc, 0xc3, 0x07, 0x1a, 0x2c, 0x59, 0x3f, + 0x1a, 0x83, 0x43, 0xf0, 0xe0, 0xde, 0xe3, 0x40, 0x8e, 0x04, + 0x66, 0x3c, 0x87, 0x1e, 0xfa, 0x7b, 0x8a, 0x7b, 0xd2, 0x9e, + 0x15, 0xf5, 0xec, 0x3c, 0x72, 0x7e, 0x2d, 0x19, 0xf8, 0xfd, + 0xf0, 0x28, 0x71, 0x8a, 0xf5, 0xcb, 0x4c, 0x61, 0x5f, 0x85, + 0xe0, 0x6f, 0xb8, 0xf3, 0x17, 0x10, 0xcb, 0x44, 0x45, 0x8c, + 0x96, 0x08, 0xa1, 0xf1, 0x48, 0xa4, 0x1d, 0xea, 0x35, 0x2f, + 0x82, 0x2b, 0xc2, 0x0b, 0xef, 0x73, 0xe1, 0xc2, 0x35, 0xdb, + 0xe7, 0x68, 0xfd, 0xb0, 0xe8, 0x7b, 0x2d, 0x0f, 0xfd, 0x53, + 0x1b, 0xb8, 0x36, 0x54, 0xd6, 0x43, 0x30, 0xcf, 0x83, 0xb0, + 0x18, 0xda, 0x9b, 0x86, 0x82, 0xfa, 0xe6, 0x37, 0x5b, 0x9e, + 0xa4, 0xdb, 0x7c, 0x59, 0x25, 0x59, 0xc6, 0x46, 0x36, 0x72, + 0xc5, 0x72, 0xd8, 0x2f, 0x26, 0xe2, 0xee, 0xe3, 0xcb, 0xe5, + 0x33, 0x1f, 0x18, 0x2e, 0x16, 0xce, 0xd2, 0x9c, 0x89, 0x6e, + 0xd5, 0x21, 0xfa, 0x58, 0x83, 0xa9, 0x4c, 0x69, 0x97, 0x7d, + 0xae, 0x1f, 0x65, 0xd5, 0xdb, 0xf0, 0xfe, 0xd5, 0x32, 0xb1, + 0x50, 0x72, 0xdf, 0x2b, 0xe2, 0xc1, 0xe6, 0x2e, 0x8b, 0x87, + 0xa8, 0x4e, 0x84, 0xbe, 0xc9, 0x27, 0xb5, 0x74, 0x7e, 0x13, + 0x17, 0x57, 0x9c, 0xc6, 0xd3, 0x9f, 0xcd, 0x86, 0x50, 0x4b, + 0x6c, 0x50, 0xa2, 0xba, 0xfe, 0xf6, 0xd5, 0x85, 0x68, 0x31, + 0x89, 0xfb, 0xeb, 0xfe, 0x92, 0xb0, 0xd0, 0x4c, 0xbc, 0x65, + 0x4b, 0x62, 0xe2, 0xdf, 0x88, 0x7e, 0x90, 0xe0, 0xb3, 0xec, + 0x13, 0x69, 0x33, 0xea, 0x53, 0x69, 0x9a, 0x0b, 0x27, 0xfb, + 0xca, 0x9f, 0x9e, 0x1f, 0xcf, 0xb1, 0xeb, 0xf4, 0x8f, 0xe2, + 0x53, 0xc8, 0xe6, 0x51, 0x75, 0xee, 0xb1, 0x34, 0x3e, 0x37, + 0xdd, 0x2d, 0x3a, 0x72, 0x76, 0x33, 0xc1, 0x27, 0xe7, 0xbd, + 0xc1, 0x7f, 0xcb, 0x53, 0x5d, 0xdf, 0xc4, 0x1f, 0x36, 0xdb, + 0x6a, 0x91, 0x1f, 0x6a, 0xa5, 0xc6, 0xe2, 0x37, 0x68, 0x1a, + 0x7d, 0xf7, 0xed, 0x2a, 0xc7, 0x99, 0x5e, 0xbd, 0x59, 0x57, + 0x09, 0x22, 0x7e, 0x9c, 0xbd, 0x8e, 0xad, 0xbe, 0xee, 0xa5, + 0x2a, 0xe3, 0x9f, 0xff, 0x14, 0xda, 0xba, 0x90, 0x37, 0xba, + 0x3a, 0x42, 0xcd, 0x4a, 0x28, 0x47, 0x27, 0x58, 0x7a, 0x33, + 0x93, 0x77, 0x83, 0x29, 0xab, 0x47, 0x19, 0x43, 0x00, 0x6f, + 0xe7, 0x77, 0xc1, 0xaa, 0xd6, 0xbc, 0xc0, 0x1b, 0xd0, 0xdf, + 0xf9, 0x40, 0x4d, 0xb2, 0x60, 0xce, 0x59, 0x17, 0x0a, 0xa9, + 0x14, 0x4e, 0x6a, 0x30, 0x1b, 0x26, 0x68, 0x55, 0x12, 0x19, + 0x62, 0x85, 0x5d, 0xa6, 0xb4, 0x48, 0x4a, 0xe9, 0xe1, 0x57, + 0xb1, 0x48, 0xf3, 0x86, 0xd1, 0x50, 0x2e, 0x1d, 0x57, 0xbe, + 0x09, 0xf8, 0x53, 0x40, 0xd9, 0x55, 0xd9, 0x71, 0x4c, 0xa7, + 0xdb, 0x61, 0x82, 0x4e, 0x00, 0x58, 0xe4, 0x89, 0xae, 0xa6, + 0x1a, 0x4b, 0xe3, 0x9d, 0xec, 0x65, 0xee, 0xe1, 0x7b, 0xdb, + 0x4f, 0x8d, 0xf3, 0xd9, 0x89, 0xaa, 0xd1, 0x31, 0x30, 0xde, + 0xc3, 0x5c, 0xbc, 0xb9, 0x60, 0x0a, 0xe0, 0x13, 0x14, 0x85, + 0x08, 0x60, 0xc5, 0x1c, 0xc2, 0x9d, 0x8b, 0x6e, 0xb8, 0x94, + 0x11, 0x6f, 0xd3, 0xee, 0xfb, 0xf8, 0x15, 0xd8, 0xa4, 0x0b, + 0x92, 0xdf, 0x7c, 0x9a, 0xa2, 0xec, 0xa3, 0x3d, 0xbc, 0xcd, + 0xe8, 0xb5, 0xb3, 0xf5, 0xe8, 0xee, 0x2a, 0x57, 0xf7, 0x58, + 0xc4, 0xaa, 0xeb, 0x33, 0x44, 0x5f, 0x62, 0xbe, 0x90, 0x48, + 0xe5, 0xcb, 0x6a, 0xcb, 0x55, 0x94, 0x6d, 0xe6, 0x22, 0x03, + 0xeb, 0xcb, 0x05, 0xb8, 0xb4, 0xa5, 0xbe, 0xec, 0x79, 0x21, + 0x0d, 0xb3, 0x5c, 0x74, 0x11, 0xcb, 0xb3, 0xa6, 0x06, 0x2f, + 0x73, 0xd1, 0x14, 0xd9, 0x70, 0x4e, 0xc5, 0xf5, 0xff, 0xfd, + 0x49, 0x3b, 0xa9, 0x22, 0x80, 0x2a, 0x5e, 0xf9, 0xae, 0xa5, + 0xd4, 0x3c, 0x74, 0xd7, 0x5a, 0x5d, 0x88, 0x6f, 0x99, 0xe2, + 0x4c, 0xa3, 0x9b, 0x15, 0xb8, 0xfd, 0x0b, 0x0d, 0x57, 0x03, + 0xe8, 0xda, 0x78, 0xc4, 0x63, 0x49, 0x48, 0x7a, 0x39, 0xcd, + 0xfa, 0xad, 0x92, 0x55, 0x4a, 0x0e, 0x68, 0x08, 0xb9, 0x34, + 0xe0, 0x14, 0x6e, 0x19, 0xed, 0x69, 0x14, 0x7f, 0xc1, 0x7d, + 0x12, 0xac, 0x5d, 0xf7, 0x62, 0x6f, 0x77, 0x65, 0xa3, 0xc2, + 0xf9, 0xda, 0x43, 0x9e, 0x6b, 0x82, 0xd9, 0x14, 0x57, 0x02, + 0x09, 0x9f, 0xa7, 0x15, 0x27, 0xe8, 0xad, 0xa1, 0x73, 0xc7, + 0xb6, 0x11, 0x4c, 0x5e, 0xf4, 0x1a, 0x0a, 0x97, 0x98, 0x5e, + 0x29, 0x8a, 0x8b, 0xa5, 0xbd, 0x86, 0x7f, 0x6d, 0x31, 0x72, + 0x6d, 0xe5, 0xcf, 0x13, 0xff, 0xb9, 0x4e, 0x69, 0x66, 0x37, + 0x1b, 0xfb, 0xe8, 0xb7, 0x60, 0xfe, 0xbf, 0xaa, 0x06, 0x88, + 0xa4, 0xa2, 0x0b, 0x33, 0x55, 0xac, 0x61, 0x77, 0x0a, 0x6f, + 0x1f, 0xaf, 0xd8, 0x9b, 0xc7, 0x26, 0x13, 0xf6, 0xc4, 0xef, + 0xce, 0x0f, 0x16, 0x86, 0x64, 0x1b, 0xc0, 0x71, 0x35, 0xf9, + 0x1f, 0xaf, 0xc4, 0x7a, 0xa3, 0x3b, 0x89, 0x40, 0xcb, 0x09, + 0x11, 0x7b, 0x01, 0x54, 0xd5, 0xd2, 0x2a, 0xc8, 0xfe, 0x0e, + 0xef, 0x8c, 0xfb, 0x2b, 0x08, 0x12, 0x6d, 0xbb, 0xa8, 0x2e, + 0x7a, 0x2b, 0xc2, 0x91, 0x2a, 0x76, 0x0b, 0x31, 0x30, 0x4a, + 0x5b, 0xca, 0x96, 0xc9, 0x89, 0xa0, 0x12, 0x40, 0x76, 0xbe, + 0xcd, 0x59, 0x5f, 0xc2, 0x7b, 0xaf, 0xf6, 0x29, 0xde, 0xe9, + 0x24, 0x61, 0x3f, 0x46, 0x78, 0xa7, 0xda, 0x65, 0xb0, 0xb3, + 0xae, 0xf3, 0x72, 0x6e, 0x37, 0x6e, 0xae, 0xb1, 0x3b, 0xf6, + 0x60, 0xa1, 0x92, 0x86, 0x9e, 0x97, 0x4f, 0x5e, 0x86, 0x88, + 0x32, 0x06, 0x7c, 0xe3, 0x37, 0x7e, 0xb1, 0x83, 0xf5, 0x83, + 0x05, 0x43, 0xb3, 0xe3, 0xa1, 0x68, 0xe5, 0x4c, 0x92, 0x9c, + 0x61, 0xa3, 0x5d, 0xcf, 0x23, 0xe7, 0xce, 0xf5, 0x7f, 0xbb, + 0xf7, 0x89, 0x5e, 0xa8, 0xf0, 0xa1, 0xff, 0x1a, 0xaf, 0x15, + 0xc8, 0x3d, 0x8b, 0xce, 0x06, 0xa4, 0x60, 0xd6, 0x40, 0x19, + 0x48, 0x33, 0x53, 0x34, 0x9e, 0xd8, 0x75, 0xfc, 0x45, 0x73, + 0x35, 0x8f, 0x70, 0x04, 0x80, 0xa1, 0xe5, 0xfc, 0x98, 0xb0, + 0x52, 0x63, 0x41, 0x84, 0x57, 0xa2, 0x85, 0x4e, 0x68, 0x13, + 0x2d, 0x3e, 0x4b, 0x68, 0x7f, 0x43, 0x04, 0x05, 0x02, 0x5a, + 0x16, 0x67, 0x5a, 0xc5, 0xea, 0xac, 0x25, 0x61, 0xd4, 0xa4, + 0xe7, 0xbe, 0x13, 0x95, 0xbd, 0x03, 0xb4, 0x26, 0xe3, 0xbf, + 0x7e, 0xe5, 0x0b, 0x34, 0xeb, 0x59, 0x5d, 0xd7, 0xdb, 0x1e, + 0x07, 0xfc, 0x63, 0xab, 0xbb, 0xc6, 0x7a, 0x51, 0x50, 0x59, + 0x13, 0x4b, 0x27, 0x88, 0x98, 0xdc, 0x01, 0x37, 0xeb, 0x58, + 0x75, 0xde, 0x5a, 0xa4, 0x6b, 0xdd, 0xba, 0x01, 0x40, 0xf7, + 0x1c, 0x0a, 0xf3, 0x02, 0x3d, 0x54, 0x64, 0xf2, 0x85, 0x43, + 0x90, 0xc0, 0x69, 0x18, 0x94, 0x95, 0x6e, 0x57, 0x14, 0xda, + 0x27, 0x0a, 0x42, 0xb2, 0x5a, 0x78, 0xe4, 0xf1, 0x45, 0x85, + 0x54, 0xec, 0x44, 0xa0, 0xcb, 0xf4, 0xd1, 0x3a, 0x85, 0x74, + 0x0f, 0x04, 0x67, 0xf4, 0x42, 0x01, 0xc4, 0x04, 0x66, 0x48, + 0x6c, 0xbe, 0x84, 0x38, 0x6e, 0xda, 0x23, 0xd0, 0xd1, 0x26, + 0x94, 0x11, 0x65, 0x2e, 0xc6, 0xd8, 0x6e, 0x25, 0x17, 0x43, + 0x9f, 0x55, 0x2d, 0x1d, 0x55, 0xa9, 0xdd, 0x3b, 0xc7, 0x09, + 0xde, 0x26, 0x64, 0xd4, 0x85, 0x21, 0x15, 0x0d, 0x4a, 0x45, + 0x4d, 0xba, 0x13, 0x9e, 0x3b, 0x5e, 0xc2, 0xf7, 0xc1, 0x34, + 0xc5, 0x74, 0xd4, 0x95, 0x19, 0x3d, 0x69, 0x9c, 0xae, 0xef, + 0x13, 0x95, 0x2c, 0x77, 0xdd, 0x64, 0x2c, 0x12, 0x31, 0x7d, + 0xb5, 0x55, 0xde, 0x69, 0x35, 0x3f, 0x77, 0x72, 0xc6, 0x21, + 0x22, 0x23, 0x7a, 0x05, 0xbf, 0x92, 0xae, 0x49, 0x7f, 0x74, + 0x17, 0x97, 0x5f, 0x5b, 0x4d, 0x7d, 0x86, 0x23, 0x04, 0xe0, + 0xff, 0x10, 0x06, 0xc3, 0xd3, 0x05, 0xde, 0xc4, 0xae, 0xaf, + 0x3d, 0x2d, 0xaf, 0x3c, 0xaf, 0xd3, 0xd5, 0xfd, 0x84, 0xd8, + 0x3b, 0x6c, 0x8e, 0x8b, 0x23, 0x8b, 0x16, 0xaa, 0x67, 0xf1, + 0xde, 0xa4, 0x4b, 0x5a, 0x39, 0x60, 0x73, 0xd2, 0x9f, 0x1f, + 0x8c, 0xcf, 0xbc, 0xaa, 0x74, 0x9e, 0x8d, 0xfd, 0xc3, 0xb7, + 0x86, 0xe5, 0xbb, 0x5a, 0x4d, 0x3d, 0xe2, 0xc3, 0x28, 0x78, + 0x26, 0xd4, 0xb3, 0x45, 0x94, 0xd3, 0x2d, 0xbf, 0x8c, 0x92, + 0x56, 0x3c, 0x6e, 0xea, 0x53, 0x38, 0x7f, 0x22, 0x67, 0xc9, + 0xa7, 0x14, 0x20, 0xb9, 0x13, 0xc4, 0xa0, 0x44, 0x83, 0xc4, + 0x19, 0xca, 0x98, 0x71, 0xc7, 0x13, 0x70, 0x3a, 0xa7, 0xfb, + 0x9e, 0xc4, 0x94, 0x8c, 0xfd, 0x21, 0x36, 0x88, 0xea, 0x23, + 0xc7, 0x43, 0x52, 0x9f, 0xf4, 0x9e, 0xb1, 0xb4, 0xd3, 0x20, + 0x65, 0xd8, 0x18, 0x25, 0x80, 0xb7, 0xe4, 0x5c, 0x96, 0x3a, + 0xa3, 0xb5, 0x40, 0x63, 0xac, 0x02, 0x34, 0x51, 0xf7, 0x12, + 0xea, 0x97, 0x9d, 0x3e, 0xe7, 0xcb, 0x88, 0x15, 0xaa, 0xe3, + 0xfe, 0xe5, 0x42, 0xe5, 0x48, 0xcf, 0xc6, 0x8e, 0x0e, 0xc6, + 0x48, 0xdb, 0xe5, 0x1e, 0x79, 0x99, 0xed, 0x78, 0xa6, 0x37, + 0xdd, 0xe3, 0x7b, 0x01, 0xdd, 0x20, 0x63, 0x45, 0x57, 0xd1, + 0x0f, 0x05, 0x5d, 0x29, 0xad, 0x99, 0x6c, 0x27, 0xa3, 0x0c, + 0x72, 0x81, 0xb1, 0x26, 0x16, 0xaf, 0x11, 0x65, 0xba, 0x79, + 0xbc, 0xb8, 0xfe, 0xe7, 0xc5, 0xe6, 0x4c, 0xfa, 0x37, 0xc5, + 0xe0, 0x2e, 0x4e, 0xef, 0x75, 0xe4, 0x04, 0xaf, 0xfa, 0x41, + 0x7f, 0x58, 0x2e, 0x8f, 0x95, 0x5f, 0x15, 0x5c, 0x15, 0x23, + 0x81, 0xb7, 0x2c, 0x81, 0x70, 0xf5, 0xcc, 0x60, 0x09, 0x7e, + 0xf1, 0x0d, 0x9c, 0x9d, 0xcc, 0xa0, 0x30, 0xa8, 0x82, 0x23, + 0x5f, 0x94, 0xcb, 0x18, 0xc4, 0x32, 0xe6, 0xab, 0xcd, 0x96, + 0x9e, 0xab, 0xcd, 0x68, 0x6f, 0x88, 0xb7, 0x72, 0x65, 0xbc, + 0x1e, 0x05, 0x60, 0xfe, 0x6b, 0x77, 0x2a, 0x11, 0x63, 0x59, + 0x29, 0xdb, 0xba, 0xe0, 0x50, 0xd5, 0x51, 0x77, 0x16, 0xb8, + 0xb7, 0xf4, 0xa9, 0xbe, 0xf0, 0xa5, 0xaa, 0x20, 0x50, 0x2e, + 0x73, 0x21, 0xee, 0x77, 0xa3, 0xc8, 0xbc, 0x0c, 0x16, 0x0f, + 0x83, 0x7b, 0xaf, 0xbb, 0x91, 0x95, 0xd3, 0x6e, 0xe7, 0x28, + 0x77, 0x00, 0xbc, 0x83, 0x46, 0xa5, 0x0a, 0x19, 0xe8, 0x10, + 0xfb, 0x24, 0xeb, 0x27, 0xc2, 0xa3, 0xdd, 0xb8, 0x5b, 0x27, + 0xb9, 0xbb, 0x49, 0xd9, 0xd0, 0x32, 0x94, 0x48, 0x1b, 0xb8, + 0xf8, 0xb2, 0x30, 0xf4, 0x1f, 0x3d, 0xbf, 0xe6, 0xf3, 0x34, + 0xd3, 0x32, 0x85, 0x67, 0x85, 0x13, 0x3e, 0x20, 0xb7, 0xfa, + 0x74, 0x27, 0x74, 0x8f, 0x55, 0x47, 0x15, 0x91, 0x0b, 0x3f, + 0xb1, 0x18, 0xe7, 0x11, 0x1e, 0x52, 0xd8, 0xd1, 0x3f, 0xb9, + 0x5d, 0x4f, 0x88, 0xb9, 0x1e, 0x5a, 0xb6, 0x90, 0x64, 0xad, + 0x6f, 0x8d, 0x33, 0xb3, 0x57, 0xde, 0x3e, 0x13, 0xb3, 0x9f, + 0x2d, 0x00, 0xb1, 0x79, 0x84, 0x60, 0x6d, 0x3c, 0x5f, 0xc0, + 0x34, 0x08, 0x4b, 0x58, 0x33, 0x59, 0xfe, 0xe5, 0xed, 0xd3, + 0x10, 0xd8, 0xd8, 0x85, 0xc3, 0xc9, 0x71, 0xcf, 0x40, 0x96, + 0xc0, 0xd5, 0x5e, 0x62, 0xe7, 0xcb, 0x33, 0xee, 0x72, 0xb5, + 0xb8, 0x6e, 0xea, 0x13, 0xde, 0xeb, 0x82, 0x03, 0x8e, 0x6c, + 0xb3, 0x67, 0xb1, 0x5f, 0xd4, 0xe1, 0xd9, 0xc2, 0x7a, 0x97, + 0xbb, 0xd4, 0x5e, 0x0b, 0xfe, 0xc1, 0xb3, 0x1f, 0x2b, 0x1a, + 0x37, 0x98, 0x26, 0x27, 0xb1, 0xaf, 0x4c, 0x55, 0xe1, 0xae, + 0x4c, 0x86, 0x80, 0x4b, 0xc5, 0xf2, 0x35, 0x48, 0x81, 0xf7, + 0x83, 0x75, 0x63, 0x08, 0x0d, 0x77, 0x41, 0x14, 0xbc, 0xf3, + 0x6e, 0x46, 0xbd, 0x9c, 0x5a, 0x4f, 0x5c, 0x89, 0x26, 0xb6, + 0x6c, 0xde, 0x0d, 0x15, 0x31, 0xec, 0x7e, 0x13, 0xf2, 0x99, + 0x74, 0x40, 0x3c, 0xe1, 0xea, 0xa0, 0xc9, 0x99, 0x0a, 0x4b, + 0x17, 0x74, 0xff, 0x47, 0x15, 0x76, 0x5e, 0x44, 0xa2, 0x1c, + 0x93, 0xd3, 0xe6, 0xa2, 0x82, 0x0f, 0x7f, 0x55, 0xa8, 0xf3, + 0x79, 0xc3, 0xa8, 0x9f, 0x37, 0x2b, 0x97, 0x7e, 0x90, 0x71, + 0xfc, 0xa7, 0xff, 0xc6, 0xc7, 0x93, 0x5c, 0xc9, 0xed, 0x20, + 0x60, 0xbd, 0x5c, 0x36, 0x05, 0x55, 0x51, 0x55, 0x51, 0x15, + 0x36, 0x01, 0x17, 0xa9, 0x56, 0x27, 0x44, 0x66, 0xc9, 0x3a, + 0xb9, 0xbb, 0xee, 0x04, 0xb6, 0x2a, 0xfd, 0x10, 0x9a, 0x46, + 0xdd, 0x5d, 0x6d, 0xad, 0x21, 0x86, 0x6d, 0x62, 0x8a, 0x4a, + 0xbc, 0x73, 0xf0, 0x9d, 0x93, 0x0d, 0xf1, 0x62, 0xfa, 0x58, + 0x64, 0x37, 0x4f, 0x0b, 0xa3, 0xa1, 0x52, 0xce, 0x03, 0xce, + 0x0f, 0x77, 0x29, 0xad, 0x47, 0x38, 0xca, 0xbc, 0x61, 0xe6, + 0xad, 0xe4, 0x8b, 0xf1, 0x82, 0xa8, 0xd5, 0xe3, 0x8c, 0xd3, + 0xa0, 0xc4, 0xc0, 0x5e, 0x3b, 0xa1, 0x66, 0x2a, 0x6e, 0x88, + 0x24, 0x56, 0xe4, 0x84, 0x0a, 0x36, 0x72, 0xf3, 0x5c, 0x11, + 0xd9, 0x66, 0xd8, 0x45, 0x5c, 0x83, 0x9e, 0x1c, 0x8c, 0xc6, + 0xf6, 0x6e, 0x6a, 0xb1, 0x52, 0xed, 0x6c, 0x6a, 0x6d, 0x23, + 0xb9, 0x0b, 0x66, 0x26, 0x5a, 0x16, 0x16, 0x90, 0x43, 0xb9, + 0xc3, 0x02, 0xc1, 0x43, 0x93, 0x13, 0x94, 0xfe, 0xc3, 0x59, + 0x49, 0xbe, 0x1e, 0x26, 0x1b, 0x9d, 0x8e, 0xba, 0xc4, 0x29, + 0x51, 0x05, 0x28, 0x1f, 0x55, 0x59, 0x1c, 0x3e, 0x25, 0x86, + 0xcc, 0xc7, 0xd9, 0xd3, 0xa8, 0xe7, 0x10, 0xa0, 0xb6, 0x23, + 0xb9, 0xaf, 0x00, 0x8b, 0x7d, 0xf1, 0x5b, 0xd6, 0xb7, 0x56, + 0x44, 0x9b, 0x0a, 0xec, 0xa6, 0x2b, 0xb4, 0x4e, 0x1d, 0x4f, + 0xc5, 0x0b, 0x45, 0xd2, 0x3a, 0xc5, 0xc0, 0xbf, 0xb9, 0xdd, + 0x59, 0x21, 0xf2, 0x67, 0x25, 0x88, 0x9b, 0xb6, 0x66, 0x83, + 0xbf, 0x62, 0xfe, 0x7c, 0xfa, 0x9e, 0x50, 0xed, 0x15, 0x93, + 0xb6, 0x7a, 0xb0, 0xc4, 0xbe, 0xcf, 0x2a, 0x70, 0x4e, 0x52, + 0x20, 0xc1, 0x24, 0x08, 0x49, 0xd9, 0x05, 0x04, 0x53, 0x73, + 0xf3, 0xcf, 0x14, 0x70, 0xac, 0x3c, 0x45, 0x0f, 0x08, 0xa3, + 0xae, 0x43, 0xe7, 0x7f, 0x1f, 0xe2, 0x14, 0xf1, 0xbb, 0x25, + 0x20, 0xfd, 0xe4, 0xaf, 0x44, 0x9e, 0x77, 0x88, 0x4d, 0x26, + 0x09, 0xb1, 0xb0, 0x12, 0xf5, 0xdf, 0x3c, 0x53, 0x48, 0x78, + 0xb9, 0x60, 0x41, 0xd3, 0x8f, 0x8d, 0x11, 0x63, 0x60, 0x28, + 0x30, 0x07, 0xa2, 0x14, 0x3b, 0x8c, 0x50, 0xe2, 0xee, 0x73, + 0x39, 0x66, 0xd1, 0x51, 0x87, 0xac, 0x90, 0x9b, 0x2c, 0x6d, + 0x8d, 0xd5, 0x75, 0x3f, 0xc6, 0xf1, 0x8f, 0xdf, 0xdb, 0x45, + 0x38, 0xf8, 0xd6, 0x7e, 0xc7, 0x7c, 0x44, 0x08, 0x4a, 0x14, + 0xa0, 0x84, 0x7c, 0x8b, 0x88, 0x40, 0x93, 0x89, 0xae, 0x2c, + 0x20, 0x07, 0x80, 0xec, 0xce, 0x4c, 0x2c, 0x4e, 0x49, 0x79, + 0x53, 0xe7, 0xde, 0xa2, 0x9e, 0x67, 0x21, 0x53, 0x7c, 0x85, + 0xe7, 0x6f, 0xbd, 0x93, 0xab, 0x63, 0xba, 0xf0, 0xbd, 0xea, + 0x39, 0x16, 0x47, 0xbf, 0xe6, 0x0c, 0xcb, 0x63, 0xc7, 0xc5, + 0xf1, 0xdc, 0x5a, 0x52, 0xcd, 0x4c, 0x53, 0x8b, 0x7e, 0xb1, + 0xc3, 0x4e, 0xe7, 0x61, 0x25, 0x01, 0xec, 0xae, 0x06, 0x74, + 0x9f, 0xbc, 0xbb, 0x2a, 0x47, 0x46, 0xe8, 0xae, 0xf2, 0xab, + 0x15, 0xed, 0xa6, 0x86, 0x8f, 0x2f, 0xe5, 0x67, 0x0f, 0xdd, + 0xbf, 0x70, 0x53, 0xaa, 0x9b, 0x74, }; static const int sizeof_bench_dilithium_level5_key = sizeof(bench_dilithium_level5_key); -#endif /* HAVE_PQC && HAVE_DILITHIUM */ +#endif /* !WOLFSSL_DILITHIUM_NO_SIGN */ + +#ifndef WOLFSSL_DILITHIUM_NO_VERIFY + +static const unsigned char bench_dilithium_level5_pubkey[] = { + 0xef, 0x49, 0x79, 0x47, 0x15, 0xc4, 0x8a, 0xa9, 0x74, 0x2a, + 0xf0, 0x36, 0x94, 0x5c, 0x91, 0x1c, 0x5d, 0xff, 0x2c, 0x83, + 0xf2, 0x8b, 0x04, 0xfc, 0x5d, 0x64, 0xbd, 0x49, 0x73, 0xcd, + 0xcc, 0x99, 0x50, 0x5f, 0x2b, 0x16, 0x3a, 0xbb, 0x98, 0xc0, + 0xa7, 0x69, 0x0e, 0x95, 0x99, 0x0b, 0xa2, 0x6c, 0xfe, 0x6c, + 0xdb, 0xc8, 0xa7, 0x09, 0x46, 0x6c, 0x90, 0x50, 0xa4, 0x75, + 0x30, 0xf7, 0x90, 0xac, 0x31, 0xb6, 0xdd, 0x21, 0xaf, 0xc6, + 0xf9, 0xfe, 0xee, 0xc6, 0x5b, 0xa8, 0x8f, 0x0a, 0x2e, 0xd0, + 0x42, 0xab, 0xa8, 0x3c, 0x8d, 0xbf, 0xf7, 0x44, 0xbd, 0x0d, + 0xcf, 0xf4, 0x68, 0xfc, 0x16, 0x67, 0xf7, 0x39, 0x48, 0x5f, + 0x56, 0xd1, 0xe7, 0x1f, 0x49, 0x80, 0x50, 0xbe, 0x54, 0xd1, + 0xb7, 0xc9, 0xd2, 0x32, 0xc7, 0x08, 0x8c, 0xde, 0x2c, 0x31, + 0xf6, 0x1d, 0xc7, 0xac, 0xb3, 0x79, 0xd7, 0x4b, 0x1b, 0x23, + 0x89, 0x0a, 0xdc, 0x8e, 0x44, 0x41, 0x14, 0x28, 0x99, 0x13, + 0xb3, 0x26, 0xa6, 0x0e, 0x83, 0x60, 0xaa, 0x8d, 0x7c, 0x23, + 0x13, 0xba, 0x6c, 0x28, 0x90, 0x56, 0x84, 0xa1, 0x23, 0x8b, + 0x81, 0x20, 0x97, 0x7c, 0x66, 0x3f, 0xed, 0x5d, 0xd0, 0xe4, + 0x5d, 0xee, 0x46, 0xbc, 0x4b, 0x3c, 0x03, 0xb5, 0xbc, 0x4d, + 0x8d, 0x37, 0xa3, 0x56, 0x4b, 0x33, 0xad, 0xef, 0xd4, 0xb6, + 0xec, 0xdb, 0x04, 0x9a, 0x19, 0x58, 0x57, 0xd8, 0x00, 0x3a, + 0x92, 0x61, 0x0c, 0x0b, 0xc8, 0x52, 0xe5, 0x04, 0x02, 0x9a, + 0x00, 0x7e, 0xec, 0x7e, 0x94, 0xaa, 0xef, 0x2d, 0x7f, 0xb6, + 0x2e, 0x7c, 0xb0, 0x73, 0xa2, 0x20, 0xc0, 0x07, 0x30, 0x41, + 0x50, 0x20, 0x14, 0x18, 0x21, 0x5e, 0x2a, 0x6f, 0x70, 0x21, + 0xd6, 0x97, 0x13, 0xb9, 0xc1, 0x9e, 0x90, 0x67, 0xcc, 0x55, + 0x8a, 0xec, 0xec, 0x0a, 0x1e, 0x90, 0xdc, 0x3f, 0xb0, 0x4d, + 0xd1, 0x18, 0xea, 0x4f, 0xcb, 0x5d, 0x15, 0x4c, 0xb8, 0x35, + 0x9b, 0x34, 0x24, 0x30, 0x06, 0x53, 0x17, 0xf0, 0xbe, 0x27, + 0x36, 0xb3, 0x04, 0x6a, 0xbd, 0xbf, 0xa7, 0x39, 0xee, 0xa9, + 0x8f, 0x0e, 0x98, 0xc5, 0xf5, 0x9f, 0x46, 0x25, 0x93, 0xc9, + 0xf2, 0xf6, 0x2b, 0x8e, 0x92, 0x06, 0x01, 0x3d, 0x81, 0x18, + 0xf2, 0xec, 0xf1, 0x05, 0x4c, 0xad, 0x4b, 0xcb, 0x98, 0xa4, + 0xb5, 0x61, 0x20, 0xda, 0x81, 0xa1, 0xfb, 0x92, 0x4c, 0xaf, + 0x87, 0x6f, 0x6e, 0xd2, 0x57, 0xec, 0xcd, 0x94, 0xb3, 0x79, + 0xbf, 0x59, 0x88, 0x17, 0x81, 0xce, 0x8a, 0x57, 0xce, 0x57, + 0xae, 0x3e, 0x82, 0x81, 0x2f, 0x83, 0x61, 0xd8, 0xf9, 0x68, + 0x21, 0xe7, 0x72, 0x5b, 0xd6, 0x80, 0x55, 0x68, 0x5d, 0x67, + 0x15, 0x0c, 0x8b, 0xdc, 0x4f, 0xc3, 0x89, 0x36, 0x3c, 0xac, + 0xaf, 0x16, 0x5e, 0x1c, 0xfa, 0x68, 0x74, 0x6a, 0xab, 0x68, + 0xd8, 0x59, 0x96, 0x2d, 0x33, 0x62, 0xe4, 0xbd, 0xb3, 0xb7, + 0x4d, 0x88, 0x35, 0xb8, 0xed, 0xb2, 0x16, 0x85, 0x97, 0x08, + 0x71, 0x71, 0x39, 0x7e, 0x0c, 0x53, 0x16, 0xda, 0x38, 0xe5, + 0x28, 0x09, 0x9c, 0xd9, 0x46, 0xec, 0x68, 0xda, 0x8d, 0xd0, + 0xad, 0xb2, 0x79, 0x28, 0x3b, 0x1e, 0x12, 0xc9, 0xdf, 0xa9, + 0x6d, 0x3d, 0x29, 0x99, 0x2f, 0x53, 0xc2, 0xd0, 0xf9, 0x88, + 0x26, 0x94, 0x47, 0xaf, 0xf6, 0x96, 0xf3, 0xe1, 0x11, 0xa6, + 0x82, 0x3d, 0x43, 0x3f, 0x1f, 0xbc, 0xf6, 0x98, 0xbe, 0xff, + 0x06, 0x86, 0x61, 0x27, 0xdc, 0x91, 0x54, 0xd4, 0xfc, 0x68, + 0x83, 0xe8, 0x35, 0x3e, 0xee, 0x94, 0x59, 0x28, 0x2f, 0xde, + 0xdd, 0x03, 0x60, 0x66, 0xc1, 0x49, 0x57, 0xdd, 0xbc, 0xd5, + 0x0a, 0x67, 0x34, 0xf1, 0xa6, 0x0a, 0x57, 0x94, 0x65, 0x02, + 0x2c, 0x52, 0x43, 0x70, 0x3b, 0xc1, 0x9a, 0xff, 0xda, 0x6f, + 0xb9, 0x54, 0x47, 0x01, 0xda, 0x27, 0xe4, 0x48, 0x4a, 0x90, + 0x9f, 0xb5, 0xc3, 0xee, 0x0e, 0x09, 0x57, 0xfe, 0x48, 0x51, + 0x08, 0x34, 0x5e, 0x8f, 0x16, 0xc9, 0x0b, 0x74, 0xd9, 0x7d, + 0x22, 0x3f, 0xd6, 0xb7, 0x5d, 0xd6, 0x76, 0x00, 0x8d, 0x4e, + 0x78, 0x73, 0x86, 0xd6, 0xdb, 0x2a, 0x65, 0xab, 0xdf, 0xb0, + 0xea, 0x11, 0xad, 0xdf, 0xba, 0x43, 0xdb, 0xa8, 0x0a, 0xfb, + 0x04, 0x38, 0x81, 0x2b, 0xa3, 0x29, 0xfc, 0x95, 0x73, 0x9a, + 0x0c, 0x6c, 0x9e, 0xcd, 0xdc, 0xcf, 0x0a, 0x0c, 0x18, 0x41, + 0x6f, 0x1d, 0xa3, 0xf6, 0x12, 0x4c, 0x13, 0xf2, 0x02, 0xc6, + 0x50, 0x99, 0x86, 0x73, 0xa7, 0xf9, 0x7e, 0x84, 0x7f, 0x4c, + 0x00, 0xce, 0x2e, 0x21, 0x76, 0x8e, 0x17, 0x7a, 0x87, 0x6f, + 0x81, 0xe6, 0xc0, 0x52, 0xa5, 0xa0, 0x3c, 0x54, 0x3c, 0xec, + 0xb0, 0x9d, 0x1c, 0x3b, 0xec, 0xe5, 0x4e, 0x4a, 0x37, 0xe7, + 0xd5, 0xa9, 0x07, 0x87, 0x23, 0x28, 0x5d, 0x3d, 0x22, 0x02, + 0x79, 0x40, 0x3f, 0x2d, 0x40, 0xc9, 0xe5, 0xa6, 0x9b, 0xa8, + 0xb8, 0x76, 0xf6, 0x77, 0x5b, 0x8d, 0x72, 0x96, 0x3e, 0x13, + 0xbf, 0x76, 0xfa, 0x7b, 0xb7, 0x82, 0x5f, 0xe7, 0x9d, 0x54, + 0x0e, 0x05, 0x1a, 0x9f, 0xa4, 0x42, 0xa5, 0xb4, 0x93, 0x23, + 0x06, 0x59, 0x43, 0xa8, 0xe8, 0x5c, 0xfc, 0x18, 0x97, 0xdb, + 0xad, 0x9a, 0x80, 0x0a, 0xf2, 0x20, 0x50, 0xac, 0xc1, 0x13, + 0x3e, 0x98, 0x09, 0xde, 0xf2, 0x70, 0x9e, 0x14, 0xc2, 0x5c, + 0xec, 0x65, 0x07, 0x0b, 0xfa, 0x02, 0x5c, 0xf8, 0x71, 0xaa, + 0x9b, 0x45, 0x62, 0xe2, 0x27, 0xaf, 0x77, 0xf8, 0xe3, 0xeb, + 0x7b, 0x24, 0x7b, 0x3c, 0x67, 0xc2, 0x6d, 0x6e, 0x17, 0xae, + 0x6e, 0x86, 0x6f, 0x98, 0xc9, 0xac, 0x13, 0x9f, 0x87, 0x64, + 0x3d, 0x4d, 0x6f, 0xa0, 0xb3, 0x39, 0xc6, 0x68, 0x1b, 0xa7, + 0xeb, 0x3e, 0x0f, 0x6b, 0xc7, 0xa4, 0xe2, 0x20, 0x27, 0x75, + 0x3f, 0x09, 0x16, 0xff, 0x1a, 0xcc, 0xa7, 0xc4, 0x6d, 0xc2, + 0xfc, 0xc3, 0x0b, 0x37, 0x63, 0xff, 0x9b, 0x10, 0xe6, 0x00, + 0xf7, 0x18, 0x43, 0x9f, 0x07, 0x50, 0x31, 0x51, 0xd4, 0xfd, + 0xad, 0xa2, 0x0f, 0x77, 0xda, 0x41, 0xc1, 0x0a, 0x6f, 0x86, + 0xd7, 0xdc, 0x8a, 0x52, 0xd6, 0xa1, 0x27, 0xdb, 0x14, 0x67, + 0x26, 0x91, 0xb3, 0xcd, 0x01, 0x5f, 0x60, 0xa1, 0x7f, 0x43, + 0x15, 0x1a, 0x82, 0x0f, 0xd3, 0x66, 0x5f, 0x60, 0x57, 0x2f, + 0xb2, 0x8c, 0x27, 0x2a, 0x9d, 0x1b, 0xf9, 0xf2, 0x59, 0x20, + 0x39, 0xd9, 0xc5, 0xaf, 0xf2, 0x36, 0x8c, 0x58, 0x00, 0x1b, + 0xd0, 0xc5, 0x8e, 0x1a, 0x49, 0xa8, 0x60, 0xbe, 0xd1, 0xd7, + 0x2a, 0xb0, 0xc2, 0xab, 0x58, 0x8a, 0x7a, 0xa9, 0x41, 0x68, + 0x70, 0xbd, 0xea, 0x73, 0xa5, 0x03, 0x11, 0xb2, 0x27, 0xd9, + 0xcd, 0xf5, 0x09, 0xe8, 0x1c, 0xe2, 0x4f, 0x50, 0x6a, 0x84, + 0x34, 0x62, 0x2e, 0x36, 0xaa, 0x4c, 0xc1, 0x83, 0x78, 0x98, + 0x35, 0x7a, 0x27, 0x7e, 0xfe, 0xf1, 0x6f, 0x59, 0x27, 0x35, + 0x73, 0xce, 0x74, 0xaa, 0xb4, 0x72, 0x82, 0xa8, 0xe2, 0x81, + 0x7a, 0x6b, 0xca, 0x33, 0xa5, 0xda, 0xa2, 0x63, 0xca, 0x2e, + 0x90, 0x03, 0x32, 0xec, 0x63, 0xdb, 0x52, 0x7b, 0x16, 0xfc, + 0x01, 0x2d, 0x30, 0x12, 0x1e, 0xf9, 0xa3, 0x72, 0x21, 0x3c, + 0x75, 0x0c, 0x61, 0x9c, 0x7e, 0x73, 0x04, 0x71, 0x41, 0x45, + 0x5d, 0x7f, 0x49, 0x1c, 0x09, 0x08, 0xa4, 0xec, 0x2f, 0xfd, + 0xc4, 0xfb, 0x59, 0x6a, 0x27, 0x7a, 0xd4, 0xfc, 0x5f, 0x20, + 0x04, 0x34, 0x7d, 0x08, 0xed, 0x82, 0x5a, 0x90, 0xe1, 0xab, + 0xfd, 0x35, 0x3a, 0x8d, 0xbb, 0x0a, 0x9d, 0x73, 0xff, 0x69, + 0xe5, 0xe9, 0x09, 0x55, 0x14, 0xd9, 0x7b, 0x6f, 0x0d, 0x99, + 0xd2, 0x7e, 0x71, 0xf8, 0x4f, 0x72, 0x2f, 0xbb, 0xc6, 0xc4, + 0x36, 0xc9, 0x01, 0xd3, 0x9b, 0x94, 0xab, 0x41, 0x0f, 0x4a, + 0x61, 0x5c, 0x68, 0xe5, 0xd7, 0x0d, 0x94, 0xaa, 0xee, 0xba, + 0x95, 0xcb, 0x8c, 0x0e, 0x85, 0x3a, 0x02, 0x6b, 0x95, 0x50, + 0xfd, 0x02, 0xfd, 0xa4, 0x58, 0x29, 0x78, 0x4f, 0xd0, 0xae, + 0x66, 0xd6, 0x5c, 0xe7, 0x45, 0xfe, 0x98, 0xb0, 0xa3, 0xe2, + 0x87, 0xc0, 0xd2, 0x81, 0x08, 0xf1, 0xf1, 0xe7, 0xda, 0x62, + 0x9e, 0xa0, 0x34, 0x86, 0xeb, 0xa1, 0x6e, 0x4a, 0x26, 0x8e, + 0x39, 0x0c, 0x51, 0x10, 0x33, 0x11, 0x87, 0xf8, 0x79, 0x3c, + 0x49, 0x7a, 0x8b, 0xce, 0xc1, 0x0a, 0x0e, 0xe1, 0xd5, 0x2a, + 0xac, 0xf0, 0x3a, 0x1d, 0x6a, 0x6a, 0xe5, 0xe1, 0x81, 0x70, + 0xad, 0xaf, 0x15, 0x4c, 0x2a, 0x70, 0x2a, 0x6b, 0x22, 0x0d, + 0x30, 0xe7, 0x56, 0xed, 0x2d, 0x4b, 0x85, 0x17, 0x49, 0x72, + 0x3a, 0x1b, 0x6f, 0x57, 0x1c, 0xf7, 0x72, 0x9e, 0x20, 0xdb, + 0x57, 0x1c, 0xfb, 0x36, 0x50, 0x52, 0xec, 0x5b, 0xd6, 0x6a, + 0x1b, 0xf8, 0x74, 0xad, 0xe6, 0x00, 0x74, 0x04, 0xc5, 0x99, + 0x83, 0xe4, 0x5a, 0x0c, 0xc3, 0xe8, 0x6d, 0x3a, 0xd7, 0x3c, + 0x3c, 0xc0, 0x1a, 0x28, 0xb3, 0x29, 0x7a, 0x10, 0x9e, 0x39, + 0x66, 0x5b, 0xc1, 0x38, 0xac, 0x21, 0x4e, 0xcd, 0x01, 0xf2, + 0xf6, 0x30, 0x2c, 0x2b, 0xb6, 0xbf, 0xf5, 0xea, 0x61, 0xaf, + 0x0c, 0xa6, 0x01, 0x11, 0x15, 0x19, 0x09, 0x8c, 0x7e, 0x69, + 0xdf, 0x3b, 0xea, 0xd3, 0x0a, 0x3a, 0xd7, 0xbd, 0xe1, 0x17, + 0xaf, 0x92, 0x3c, 0xf5, 0xfe, 0x35, 0xd6, 0xcf, 0x07, 0xa6, + 0xf7, 0xe9, 0xc1, 0x99, 0xed, 0x80, 0xe3, 0x12, 0xd5, 0x4b, + 0xb9, 0xdf, 0xaf, 0x4e, 0x52, 0xad, 0x8e, 0x66, 0x87, 0xe5, + 0x2c, 0xd0, 0x45, 0x70, 0xd9, 0x78, 0x8f, 0x4b, 0xf4, 0xe1, + 0xf1, 0x22, 0xf2, 0xe3, 0xed, 0x1f, 0xeb, 0xe9, 0x70, 0x31, + 0x4c, 0x65, 0x5f, 0x55, 0xee, 0x5d, 0xaa, 0x83, 0x87, 0x76, + 0xbe, 0x11, 0xae, 0xd7, 0xf2, 0xfb, 0x43, 0xe7, 0x17, 0x81, + 0x33, 0x15, 0x47, 0xa0, 0xf3, 0x8e, 0x84, 0x57, 0xff, 0x35, + 0x9e, 0x4a, 0x8a, 0xab, 0x50, 0x3a, 0x45, 0xe0, 0xc3, 0x73, + 0xca, 0x77, 0x61, 0x68, 0x38, 0xd0, 0xa3, 0x5f, 0x03, 0x8d, + 0x41, 0xc2, 0xd3, 0x4a, 0x17, 0xe0, 0xa8, 0xaa, 0x00, 0xf3, + 0xf2, 0x5b, 0xa8, 0xe1, 0x06, 0xa6, 0x2b, 0xdb, 0xe1, 0x74, + 0xbd, 0xc4, 0xd2, 0x2b, 0x55, 0x9a, 0xb0, 0xf8, 0x35, 0xd8, + 0x6b, 0xec, 0xdb, 0xc5, 0xf4, 0x6c, 0x40, 0x90, 0x6a, 0x68, + 0xc9, 0xb5, 0xcb, 0xbb, 0xd0, 0xb0, 0xbc, 0x9f, 0xb9, 0xaa, + 0x50, 0x14, 0x93, 0x3b, 0x9f, 0x25, 0xcb, 0x40, 0xb8, 0x08, + 0xcc, 0x13, 0xe5, 0xdc, 0x3f, 0x84, 0x96, 0xe0, 0x73, 0x7b, + 0x7d, 0x9e, 0x41, 0x92, 0x5d, 0xcc, 0xa4, 0xea, 0x4f, 0x93, + 0x0c, 0x40, 0x2e, 0x42, 0x8a, 0xe9, 0xb9, 0x12, 0x74, 0xbb, + 0x79, 0x7c, 0xb0, 0x37, 0x20, 0xb6, 0xaf, 0x43, 0x3a, 0x88, + 0x59, 0x7c, 0x68, 0x28, 0x5f, 0x98, 0xc2, 0xf0, 0x2a, 0xbc, + 0xa1, 0x61, 0x88, 0x1f, 0x43, 0xbc, 0x42, 0x8f, 0x43, 0xf3, + 0x7e, 0x16, 0x96, 0xfa, 0x92, 0x70, 0xaf, 0x3c, 0x9f, 0x4b, + 0xd9, 0x60, 0xe9, 0xf6, 0x2e, 0x84, 0xda, 0x88, 0x31, 0x34, + 0xa6, 0x85, 0x10, 0x05, 0xef, 0x40, 0xa8, 0xa5, 0x4f, 0x92, + 0x59, 0xf7, 0xe0, 0xc4, 0x2b, 0x12, 0x17, 0x71, 0xbe, 0x8c, + 0x4a, 0x02, 0xfe, 0x12, 0xb6, 0x3b, 0x85, 0x75, 0x37, 0xf3, + 0x73, 0x2d, 0x9c, 0x00, 0x5d, 0x80, 0xad, 0x20, 0x2f, 0x5a, + 0x0b, 0x17, 0x7e, 0x67, 0x72, 0x24, 0x5a, 0xb9, 0xf3, 0xb1, + 0x33, 0xa4, 0x57, 0x1d, 0x49, 0x72, 0x2c, 0x7f, 0x47, 0x15, + 0x07, 0xe0, 0x45, 0x14, 0xdd, 0x77, 0x86, 0x6d, 0x03, 0xbe, + 0x57, 0xd0, 0xaa, 0x18, 0xa6, 0xdd, 0x94, 0x18, 0x3f, 0x8a, + 0xf3, 0xb5, 0xd7, 0x5a, 0xec, 0xc8, 0x79, 0x7f, 0x51, 0x61, + 0x3c, 0x9b, 0xb2, 0x9b, 0xf3, 0xb4, 0x35, 0xd1, 0x38, 0xbf, + 0x37, 0xce, 0x54, 0xd1, 0xf8, 0xb6, 0x45, 0xeb, 0x52, 0x0d, + 0x9a, 0x09, 0x58, 0x0d, 0x2c, 0x0b, 0xb1, 0xf2, 0x30, 0x3a, + 0x95, 0xc1, 0x13, 0x91, 0xd2, 0x9f, 0x8d, 0x8d, 0xd0, 0x38, + 0x3e, 0x4c, 0xae, 0x4a, 0x55, 0xa7, 0x42, 0x11, 0x83, 0xc4, + 0x70, 0xf0, 0x2b, 0x68, 0x9e, 0x07, 0xad, 0xb7, 0x83, 0xc6, + 0x53, 0x3c, 0xfb, 0x0a, 0x5d, 0x24, 0xdc, 0xe1, 0x55, 0x72, + 0xcf, 0xce, 0x3e, 0xc8, 0xd0, 0x57, 0x8a, 0x82, 0x5e, 0x78, + 0x2b, 0x80, 0xc5, 0xb9, 0x09, 0x46, 0xf8, 0x90, 0x39, 0x52, + 0xa9, 0xce, 0x3f, 0x3d, 0x41, 0x3b, 0x28, 0x45, 0xa3, 0xb3, + 0x21, 0xc2, 0xcd, 0x14, 0x49, 0x41, 0x6c, 0x38, 0xda, 0x1b, + 0x5f, 0x16, 0x49, 0xf9, 0x65, 0x00, 0x4e, 0xb4, 0x20, 0x55, + 0x70, 0xe8, 0x58, 0x1a, 0x18, 0xbf, 0x41, 0xef, 0x31, 0xb1, + 0xe7, 0x8d, 0x89, 0xc1, 0x48, 0xe8, 0xf5, 0x57, 0x35, 0xfa, + 0xc1, 0x79, 0xee, 0x2c, 0xe8, 0x7d, 0xb6, 0x03, 0xcc, 0x66, + 0x09, 0x6f, 0x52, 0x84, 0x0a, 0x34, 0x18, 0x2c, 0x01, 0x45, + 0x81, 0x00, 0xe5, 0x5e, 0x8d, 0xae, 0x1c, 0x96, 0x8b, 0x45, + 0x73, 0x00, 0x0a, 0xb5, 0xcf, 0x8d, 0x0e, 0x35, 0x5d, 0x1a, + 0x0e, 0xbf, 0x64, 0x9a, 0x52, 0x20, 0x48, 0xc6, 0xb9, 0x40, + 0xd3, 0x2c, 0x52, 0xca, 0x93, 0xcf, 0xbb, 0x94, 0x06, 0xf3, + 0x97, 0xee, 0xcc, 0x5d, 0xa3, 0xea, 0xf8, 0x5a, 0x39, 0x77, + 0x34, 0xd7, 0xf6, 0x4e, 0xbe, 0x8a, 0x07, 0x5f, 0x51, 0x53, + 0xc5, 0x1b, 0x8c, 0x47, 0x8f, 0x34, 0x0e, 0x60, 0x0a, 0x90, + 0xe2, 0xda, 0x7b, 0xef, 0xd6, 0xf5, 0x5d, 0xe5, 0x32, 0x37, + 0x75, 0x99, 0x81, 0x4a, 0x2a, 0x78, 0x71, 0xdc, 0xf4, 0xe5, + 0xca, 0xd8, 0x6b, 0x3b, 0x90, 0x68, 0x2e, 0x93, 0xc5, 0x10, + 0x42, 0x5d, 0x38, 0x90, 0x32, 0x46, 0xea, 0x87, 0xe0, 0xbc, + 0xb8, 0x9a, 0x18, 0x20, 0x68, 0x85, 0x6d, 0x9b, 0xc9, 0x8f, + 0x9b, 0xd2, 0xbe, 0x15, 0x12, 0x68, 0xd0, 0xb0, 0x16, 0x5f, + 0xe2, 0x69, 0x1d, 0x04, 0x00, 0xfc, 0x63, 0x33, 0xcd, 0x1f, + 0x89, 0xcd, 0x52, 0xff, 0xec, 0x19, 0x69, 0x74, 0xa3, 0xce, + 0x4d, 0xab, 0x93, 0xe4, 0xc6, 0x13, 0x56, 0x27, 0xc9, 0x25, + 0x5a, 0x01, 0xb2, 0x36, 0x8b, 0x61, 0xe5, 0x8b, 0x98, 0xac, + 0xe4, 0x2a, 0xb6, 0x40, 0x9f, 0x42, 0xe4, 0x1b, 0x52, 0xf7, + 0xfd, 0xd8, 0x30, 0x07, 0x33, 0xf9, 0x47, 0xcb, 0x3c, 0xad, + 0x12, 0xc1, 0xcc, 0x29, 0x62, 0x49, 0x04, 0x0c, 0x23, 0x97, + 0x5a, 0xa4, 0x84, 0x67, 0xde, 0x5a, 0xe5, 0x36, 0xd2, 0x88, + 0xf1, 0xd4, 0xeb, 0x13, 0x81, 0x54, 0x51, 0x11, 0xe3, 0xba, + 0xbc, 0xee, 0xdd, 0x6c, 0xcd, 0xe6, 0xb4, 0xa1, 0x8b, 0x0b, + 0x66, 0xfb, 0x8e, 0x50, 0xa0, 0xda, 0x69, 0x8d, 0xcc, 0x2d, + 0xe4, 0x2c, 0xc4, 0x37, 0xdf, 0x61, 0xc0, 0x03, 0xbd, 0x8b, + 0x28, 0xca, 0xd2, 0x8c, 0x1c, 0xf1, 0xa4, 0x26, 0x69, 0xe5, + 0xcf, 0x45, 0xdb, 0x5a, 0x47, 0x79, 0xed, 0x9f, 0xf7, 0xd2, + 0xdb, 0xba, 0x46, 0x53, 0x4f, 0xce, 0xa8, 0xbe, 0x8f, 0x4a, + 0xd6, 0xdf, 0x2e, 0x06, 0xe6, 0x4c, 0x9a, 0xc1, 0xb6, 0x49, + 0xed, 0xc4, 0xeb, 0xaa, 0xa4, 0x29, 0x6d, 0xd4, 0xcc, 0x8c, + 0xb6, 0x40, 0x11, 0x39, 0x69, 0xf7, 0x75, 0xcd, 0xb1, 0x99, + 0x46, 0x4e, 0xde, 0xcb, 0xf6, 0x9d, 0x32, 0xf3, 0xc9, 0x47, + 0x47, 0x7a, 0xcb, 0xfb, 0xa3, 0x0c, 0x3b, 0xdf, 0xb7, 0xde, + 0xec, 0x99, 0xde, 0xb0, 0x26, 0x04, 0x34, 0xae, 0x6b, 0xfc, + 0x99, 0xbc, 0xde, 0xd5, 0xbe, 0xe7, 0xeb, 0xf9, 0xe7, 0xa6, + 0x01, 0x9a, 0x0c, 0x5e, 0x66, 0xe6, 0x53, 0xe4, 0xd1, 0x58, + 0xac, 0xda, 0x69, 0x77, 0x7b, 0x68, 0xd6, 0x30, 0x2a, 0x9c, + 0x6b, 0xbe, 0x9f, 0x3d, 0x71, 0xd6, 0x54, 0xcd, 0x59, 0x4e, + 0x1f, 0xe3, 0x83, 0x4e, 0xd1, 0x8e, 0xaf, 0x97, 0xa8, 0xe5, + 0xb6, 0x59, 0x77, 0xa8, 0x02, 0x20, 0xe4, 0xeb, 0x44, 0x71, + 0xbc, 0x07, 0x14, 0x79, 0x4f, 0x0c, 0x27, 0x06, 0x39, 0xcf, + 0x7c, 0xef, 0x2b, 0x9b, 0x5e, 0xc4, 0x6d, 0x79, 0x13, 0x00, + 0x43, 0x6f, 0x51, 0x77, 0xb5, 0xc3, 0x72, 0xad, 0x13, 0xa9, + 0xe5, 0x9a, 0x5b, 0x1a, 0x99, 0x74, 0xc0, 0x7a, 0xf9, 0xc5, + 0xb0, 0x58, 0x35, 0x1c, 0xa5, 0x51, 0xdb, 0xa1, 0x14, 0xcd, + 0x26, 0x71, 0xb1, 0xe7, 0xaa, 0x14, 0xa7, 0x46, 0x93, 0xd3, + 0x5c, 0x8c, 0x1a, 0x91, 0x77, 0x46, 0x2e, 0x15, 0xaa, 0x9e, + 0xf7, 0x2b, 0x79, 0x41, 0x76, 0xf7, 0x22, 0x53, 0x7d, 0x51, + 0xdb, 0x98, 0x3d, 0x5b, 0x78, 0x5f, 0xc3, 0xc9, 0x29, 0xa3, + 0xff, 0x75, 0x82, 0x06, 0x9a, 0x16, 0x5e, 0xa4, 0x79, 0x0d, + 0xd1, 0x6d, 0x08, 0xff, 0x43, 0xef, 0x9c, 0xf3, 0x1b, 0x7a, + 0x3f, 0x34, 0xbe, 0x19, 0x15, 0x06, 0x33, 0xdb, 0xa5, 0x71, + 0xcb, 0x5f, 0x6b, 0x8d, 0xbd, 0x5b, 0x32, 0x91, 0xb2, 0x37, + 0x3d, 0xb4, 0x40, 0x9e, 0x02, 0x9b, 0xb7, 0x68, 0x20, 0x58, + 0x5c, 0xab, 0xcb, 0xc8, 0x23, 0x2d, 0x77, 0xcc, 0x0b, 0xf6, + 0x78, 0x6b, 0x80, 0x06, 0x91, 0xa9, 0xfd, 0x7e, 0xfa, 0x25, + 0x98, 0x9f, 0xcc, 0x79, 0x0a, 0x1a, 0x54, 0x83, 0xac, 0x64, + 0x16, 0x90, 0xe5, 0xd9, 0xa7, 0xd7, 0x1b, 0x86, 0x0d, 0xe6, + 0xe6, 0x22, 0x2b, 0x1f, 0x44, 0x49, 0x98, 0x9c, 0x51, 0x6f, + 0xcf, 0x58, 0x4a, 0xfa, 0xfa, 0x84, 0x12, 0xa5, 0x10, 0xf4, + 0xca, 0xf0, 0x98, 0x2b, 0xc9, 0x03, 0x71, 0x37, 0xe7, 0xdc, + 0xc2, 0xb1, 0x4e, 0x64, 0xde, 0x4f, 0x46, 0x0d, 0x6b, 0x25, + 0x88, 0x5d, 0xd6, 0xff, 0x23, 0x46, 0x57, 0x36, 0x14, 0x18, + 0xa7, 0xcb, 0xb8, 0xbd, 0xf0, 0xc5, 0x37, 0x36, 0xee, 0xe1, + 0xed, 0x9f, 0x4d, 0xd4, 0x39, 0xe5, 0x92, 0xcf, 0x95, 0x4d, + 0x66, 0x36, 0x5d, 0xd0, 0xcc, 0x07, 0xcf, 0x15, 0x5a, 0xce, + 0x14, 0xb8, 0xda, 0x0d, 0x3d, 0x1b, 0x45, 0xc5, 0x2e, 0x34, + 0x43, 0x25, 0x02, 0x3a, 0xcd, 0x14, 0x45, 0xfb, 0x3e, 0xf9, + 0x88, 0x5d, 0x0d, 0x29, 0x31, 0xb9, 0xa1, 0xe6, 0x31, 0x18, + 0x52, 0x46, 0x3f, 0x22, 0x4f, 0x9f, 0x7a, 0x65, 0x36, 0x88, + 0xa3, 0x1c, 0x3e, 0x6f, 0x50, 0x7a, 0x36, 0xbe, 0x56, 0x7e, + 0x50, 0xcb, 0x7a, 0x10, 0xa0, 0xec, 0xf6, 0x82, 0xd6, 0x30, + 0x1c, 0xe8, 0x4c, 0x50, 0xf9, 0x3e, 0xdb, 0xac, 0xbe, 0x4f, + 0x90, 0xb1, 0xd5, 0x1b, 0x12, 0x95, 0xfb, 0xe8, 0x08, 0x64, + 0x56, 0x7c, 0x96, 0xcc, 0x90, 0xb1, 0xbc, 0xa0, 0xf5, 0x32, + 0x69, 0xb3, 0x5f, 0x27, 0x0f, 0xbe, 0xc9, 0xbd, 0xeb, 0xfa, + 0x4b, 0x5c, 0xc5, 0x99, 0x9e, 0x5a, 0x04, 0xcc, 0xd0, 0x4d, + 0x29, 0xe8, 0x84, 0x55, 0x8c, 0xd7, 0xc4, 0x06, 0x13, 0x4d, + 0x92, 0xe5, 0x98, 0x9c, 0x4c, 0xc1, 0xf7, 0xaf, 0x7b, 0xd5, + 0x2b, 0x92, 0x68, 0x68, 0x19, 0x70, 0x4c, 0x9e, 0x46, 0xb8, + 0x34, 0xeb, 0x01, 0x47, 0xbe, 0x59, 0xab, 0x0b, 0x22, 0x25, + 0xe7, 0x56, 0xa8, 0xb4, 0x93, 0x3c, 0xd5, 0x98, 0x9f, 0x61, + 0x2e, 0xfa, 0xcb, 0x5f, 0x5b, 0xd8, 0x09, 0x83, 0xe9, 0x40, + 0xe9, 0x0e, 0x42, 0xdd, 0x17, 0xd7, 0x6e, 0x19, 0x8d, 0x95, + 0x0a, 0x93, +}; +static const int sizeof_bench_dilithium_level5_pubkey = + sizeof(bench_dilithium_level5_pubkey); + +#endif /* !WOLFSSL_DILITHIUM_NO_VERIFY */ + +#endif /* HAVE_DILITHIUM */ -#if defined(HAVE_PQC) && defined(HAVE_SPHINCS) +#if defined(HAVE_SPHINCS) /* certs/sphincs/bench_sphincs_fast_level1_key.der */ static const unsigned char bench_sphincs_fast_level1_key[] = @@ -5999,7 +6034,7 @@ static const unsigned char bench_sphincs_small_level5_key[] = }; static const int sizeof_bench_sphincs_small_level5_key = sizeof(bench_sphincs_small_level5_key); -#endif /* HAVE_PQC && HAVE_SPHINCS */ +#endif /* HAVE_SPHINCS */ #if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) diff --git a/src/wolfssl/error-ssl.h b/src/wolfssl/error-ssl.h index e579bfb..724d7de 100644 --- a/src/wolfssl/error-ssl.h +++ b/src/wolfssl/error-ssl.h @@ -30,6 +30,10 @@ extern "C" { #endif +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES_H + #include +#endif + enum wolfSSL_ErrorCodes { INPUT_CASE_ERROR = -301, /* process input state error */ PREFIX_ERROR = -302, /* bad index to key rounds */ @@ -211,6 +215,9 @@ enum wolfSSL_ErrorCodes { WOLFSSL_LOCAL void SetErrorString(int err, char* buff); +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES + #include +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wolfssl/evp.c b/src/wolfssl/evp.c index a365ff6..42949fc 100644 --- a/src/wolfssl/evp.c +++ b/src/wolfssl/evp.c @@ -711,8 +711,19 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { - byte* tmp = (byte*)XREALLOC(ctx->authIn, + byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authInSz + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authIn, (size_t)ctx->authInSz); + XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authIn = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authIn, (size_t)(ctx->authInSz + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { ctx->authIn = tmp; XMEMCPY(ctx->authIn + ctx->authInSz, in, (size_t)inl); @@ -745,9 +756,19 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, /* Buffer input for one-shot API */ if (inl > 0) { byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authBufferLen + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authBuffer, (size_t)ctx->authBufferLen); + XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authBuffer = NULL; + } + #else tmp = (byte*)XREALLOC(ctx->authBuffer, (size_t)(ctx->authBufferLen + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { XMEMCPY(tmp + ctx->authBufferLen, in, (size_t)inl); ctx->authBufferLen += inl; @@ -817,8 +838,19 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, static int wolfSSL_EVP_CipherUpdate_CCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { - byte* tmp = (byte*)XREALLOC(ctx->authIn, + byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authInSz + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authIn, (size_t)ctx->authInSz); + XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authIn = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authIn, (size_t)(ctx->authInSz + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { ctx->authIn = tmp; XMEMCPY(ctx->authIn + ctx->authInSz, in, (size_t)inl); @@ -843,9 +875,19 @@ static int wolfSSL_EVP_CipherUpdate_CCM(WOLFSSL_EVP_CIPHER_CTX *ctx, /* Buffer input for one-shot API */ if (inl > 0) { byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)(ctx->authBufferLen + inl), NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authBuffer, (size_t)ctx->authBufferLen); + XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authBuffer = NULL; + } + #else tmp = (byte*)XREALLOC(ctx->authBuffer, (size_t)(ctx->authBufferLen + inl), NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { XMEMCPY(tmp + ctx->authBufferLen, in, (size_t)inl); ctx->authBufferLen += inl; @@ -875,8 +917,19 @@ static int wolfSSL_EVP_CipherUpdate_AriaGCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int inl) { if (in && inl > 0) { - byte* tmp = (byte*)XREALLOC(ctx->authIn, + byte* tmp; + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)ctx->authInSz + inl, NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authIn, (size_t)ctx->authInSz); + XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authIn = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authIn, (size_t)ctx->authInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { ctx->authIn = tmp; XMEMCPY(ctx->authIn + ctx->authInSz, in, (size_t)inl); @@ -905,9 +958,18 @@ static int wolfSSL_EVP_CipherUpdate_AriaGCM(WOLFSSL_EVP_CIPHER_CTX *ctx, if (ctx->enc == 0) { /* Append extra space for the tag */ size = WC_ARIA_GCM_GET_CIPHERTEXT_SIZE(size); } - tmp = (byte*)XREALLOC(ctx->authBuffer, - (size_t)size, NULL, - DYNAMIC_TYPE_OPENSSL); + #ifdef WOLFSSL_NO_REALLOC + tmp = (byte*)XMALLOC((size_t)size, NULL, + DYNAMIC_TYPE_OPENSSL); + if (tmp != NULL) { + XMEMCPY(tmp, ctx->authBuffer, (size_t)ctx->authBufferLen); + XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->authBuffer = NULL; + } + #else + tmp = (byte*)XREALLOC(ctx->authBuffer, (size_t)size, NULL, + DYNAMIC_TYPE_OPENSSL); + #endif if (tmp) { XMEMCPY(tmp + ctx->authBufferLen, in, (size_t)inl); ctx->authBufferLen += inl; @@ -2693,9 +2755,19 @@ int wolfSSL_EVP_PKEY_CTX_add1_hkdf_info(WOLFSSL_EVP_PKEY_CTX* ctx, if (ret == WOLFSSL_SUCCESS && info != NULL && infoSz > 0) { unsigned char* p; /* If there's already info in the buffer, append. */ + #ifdef WOLFSSL_NO_REALLOC + p = (byte*)XMALLOC((size_t)(ctx->pkey->hkdfInfoSz + (word32)infoSz), NULL, + DYNAMIC_TYPE_INFO); + if (p != NULL) { + XMEMCPY(p, ctx->pkey->hkdfInfo, (size_t)ctx->pkey->hkdfInfoSz); + XFREE(ctx->pkey->hkdfInfo, NULL, DYNAMIC_TYPE_INFO); + ctx->pkey->hkdfInfo = NULL; + } + #else p = (byte*)XREALLOC(ctx->pkey->hkdfInfo, (size_t)(ctx->pkey->hkdfInfoSz + (word32)infoSz), NULL, DYNAMIC_TYPE_INFO); + #endif if (p == NULL) { WOLFSSL_MSG("Failed to reallocate larger HKDF info buffer."); ret = WOLFSSL_FAILURE; @@ -3211,6 +3283,8 @@ int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey) if (pkey == NULL) return 0; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_bits"); if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0; + if (bytes < 0) + return 0; return bytes*8; } @@ -4275,23 +4349,39 @@ static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx, int ret; if (ctx->isHMAC) { - Hmac hmacCopy; - - if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS) +#ifdef WOLFSSL_SMALL_STACK + Hmac *hmacCopy = (Hmac *)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_OPENSSL); + if (hmacCopy == NULL) return WOLFSSL_FAILURE; - ret = wc_HmacFinal(&hmacCopy, md) == 0; - wc_HmacFree(&hmacCopy); +#else + Hmac hmacCopy[1]; +#endif + ret = wolfSSL_HmacCopy(hmacCopy, &ctx->hash.hmac); + if (ret == WOLFSSL_SUCCESS) + ret = wc_HmacFinal(hmacCopy, md) == 0; + wc_HmacFree(hmacCopy); +#ifdef WOLFSSL_SMALL_STACK + XFREE(hmacCopy, NULL, DYNAMIC_TYPE_OPENSSL); +#endif return ret; } else { - WOLFSSL_EVP_MD_CTX ctxCopy; - wolfSSL_EVP_MD_CTX_init(&ctxCopy); - - if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS) +#ifdef WOLFSSL_SMALL_STACK + WOLFSSL_EVP_MD_CTX *ctxCopy = (WOLFSSL_EVP_MD_CTX *)XMALLOC(sizeof(WOLFSSL_EVP_MD_CTX), NULL, DYNAMIC_TYPE_OPENSSL); + if (ctxCopy == NULL) return WOLFSSL_FAILURE; +#else + WOLFSSL_EVP_MD_CTX ctxCopy[1]; +#endif + wolfSSL_EVP_MD_CTX_init(ctxCopy); - ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen); - wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy); + ret = wolfSSL_EVP_MD_CTX_copy_ex(ctxCopy, ctx); + if (ret == WOLFSSL_SUCCESS) + ret = wolfSSL_EVP_DigestFinal(ctxCopy, md, mdlen); + wolfSSL_EVP_MD_CTX_cleanup(ctxCopy); +#ifdef WOLFSSL_SMALL_STACK + XFREE(ctxCopy, NULL, DYNAMIC_TYPE_OPENSSL); +#endif return ret; } } @@ -5468,7 +5558,7 @@ void wolfSSL_EVP_init(void) #endif /* HAVE_AES_CBC */ #ifdef WOLFSSL_AES_CFB -#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) +#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(6,0,0)) #ifdef WOLFSSL_AES_128 const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cfb1(void) { @@ -8465,7 +8555,7 @@ void wolfSSL_EVP_init(void) } if (ret < 0) { - if (ret == AES_GCM_AUTH_E) { + if (ret == WC_NO_ERR_TRACE(AES_GCM_AUTH_E)) { WOLFSSL_MSG("wolfSSL_EVP_Cipher failure: bad AES-GCM tag."); } WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); @@ -8543,7 +8633,7 @@ static int PopulateRSAEvpPkeyDer(WOLFSSL_EVP_PKEY *pkey) if (key->pkcs8HeaderSz) { ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, NULL, (word32)derSz, RSAk, NULL, 0); - if (ret == LENGTH_ONLY_E) + if (ret == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) ret = 0; } #endif @@ -8917,7 +9007,7 @@ int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) ret = wc_DhParamsToDer(dhkey,NULL,&derSz); } - if (derSz == 0 || ret != LENGTH_ONLY_E) { + if (derSz == 0 || ret != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { WOLFSSL_MSG("Failed to get size of DH Key"); return WOLFSSL_FAILURE; } @@ -9060,7 +9150,7 @@ static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) #ifdef HAVE_PKCS8 if (key->pkcs8HeaderSz) { /* when key has pkcs8 header the pkey should too */ - if (wc_EccKeyToPKCS8(ecc, NULL, (word32*)&derSz) == LENGTH_ONLY_E) { + if (wc_EccKeyToPKCS8(ecc, NULL, (word32*)&derSz) == WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { derBuf = (byte*)XMALLOC((size_t)derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); if (derBuf) { @@ -9112,8 +9202,17 @@ static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) } else if (ecc->type == ECC_PUBLICKEY) { if ((derSz = wc_EccPublicKeyDerSize(ecc, 1)) > 0) { - derBuf = (byte*)XREALLOC(pkey->pkey.ptr, (size_t)derSz, NULL, + #ifdef WOLFSSL_NO_REALLOC + derBuf = (byte*)XMALLOC((size_t)derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); + if (derBuf != NULL) { + XMEMCPY(derBuf, pkey->pkey.ptr, (size_t)pkey->pkey_sz); + XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_OPENSSL); + pkey->pkey.ptr = NULL; + } + #else + derBuf = (byte*)XREALLOC(pkey->pkey.ptr, (size_t)derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); + #endif if (derBuf != NULL) { pkey->pkey.ptr = (char*)derBuf; if ((derSz = wc_EccPublicKeyToDer(ecc, derBuf, (word32)derSz, @@ -9205,7 +9304,7 @@ const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) int wolfSSL_EVP_MD_pkey_type(const WOLFSSL_EVP_MD* type) { - int ret = BAD_FUNC_ARG; + int ret = WC_NO_ERR_TRACE(BAD_FUNC_ARG); WOLFSSL_ENTER("wolfSSL_EVP_MD_pkey_type"); @@ -9229,6 +9328,9 @@ int wolfSSL_EVP_MD_pkey_type(const WOLFSSL_EVP_MD* type) ret = NID_sha512WithRSAEncryption; } } + else { + ret = BAD_FUNC_ARG; + } WOLFSSL_LEAVE("wolfSSL_EVP_MD_pkey_type", ret); @@ -12432,7 +12534,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, (word32)(BASE64_DECODE_BLOCK_SIZE - ctx->remaining), (word32)inl); for ( i = 0; cpySz > 0 && inLen > 0; i++) { - if (Base64_SkipNewline(in, &inLen, &j) == ASN_INPUT_E) { + if (Base64_SkipNewline(in, &inLen, &j) == WC_NO_ERR_TRACE(ASN_INPUT_E)) { return -1; /* detected an illegal char in input */ } c = in[j++]; @@ -12472,7 +12574,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, */ while (inLen > 3) { if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12486,7 +12588,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, } inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12497,7 +12599,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, e[1] = in[j++]; inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12508,7 +12610,7 @@ int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, e[2] = in[j++]; inLen--; if ((res = Base64_SkipNewline(in, &inLen, &j)) != 0) { - if (res == BUFFER_E) { + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { break; } else { @@ -12615,8 +12717,10 @@ int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, inLen = (word32)ctx->remaining; if ((res = Base64_SkipNewline(ctx->data, &inLen, &j)) != 0) { *outl = 0; - if (res == BUFFER_E) /* means no valid data to decode in buffer */ + if (res == WC_NO_ERR_TRACE(BUFFER_E)) { + /* means no valid data to decode in buffer */ return 1; /* returns as success with no output */ + } else return -1; } diff --git a/src/wolfssl/internal.h b/src/wolfssl/internal.h index 258cb03..390b21b 100644 --- a/src/wolfssl/internal.h +++ b/src/wolfssl/internal.h @@ -122,8 +122,10 @@ #ifdef HAVE_CURVE448 #include #endif -#ifdef HAVE_PQC +#ifdef HAVE_FALCON #include +#endif +#ifdef HAVE_DILITHIUM #include #endif #ifdef HAVE_HKDF @@ -206,7 +208,12 @@ #endif #elif defined(WOLFSSL_ZEPHYR) #ifndef SINGLE_THREADED - #include + #include + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #else + #include + #endif #endif #elif defined(WOLFSSL_TELIT_M2MB) /* do nothing */ @@ -343,7 +350,7 @@ #endif #endif - #if !defined(NO_RSA) && !defined(NO_DES3) + #if !defined(NO_RSA) && !defined(NO_DES3) && !defined(NO_DES3_TLS_SUITES) #if !defined(NO_SHA) #if defined(WOLFSSL_STATIC_RSA) #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA @@ -500,7 +507,7 @@ #if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA #endif - #if !defined(NO_DES3) + #if !defined(NO_DES3) && !defined(NO_DES3_TLS_SUITES) #define BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA #endif #endif @@ -686,7 +693,8 @@ #endif #endif #if !defined(NO_DES3) && !(defined(WSSL_HARDEN_TLS) && \ - WSSL_HARDEN_TLS > 112) + WSSL_HARDEN_TLS > 112) && \ + !defined(NO_DES3_TLS_SUITES) /* 3DES offers only 112 bits of security. * Using guidance from section 5.6.1 * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r5.pdf */ @@ -1548,7 +1556,7 @@ enum Misc { MAXEARLYDATASZ_LEN = 4, /* maxEarlyDataSz size in ticket */ #endif #endif -#ifdef HAVE_PQC +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) ENCRYPT_LEN = 5120, /* Allow 5k byte buffer for dilithium and * hybridization with other algs. */ #else @@ -1560,7 +1568,6 @@ enum Misc { #endif SIZEOF_SENDER = 4, /* clnt or srvr */ FINISHED_SZ = 36, /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */ - MAX_RECORD_SIZE = 16384, /* 2^14, max size by standard */ MAX_PLAINTEXT_SZ = (1 << 14), /* Max plaintext sz */ MAX_TLS_CIPHER_SZ = (1 << 14) + 2048, /* Max TLS encrypted data sz */ #ifdef WOLFSSL_TLS13 @@ -1726,10 +1733,12 @@ enum Misc { 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_IMP_IV_SZ = 4, /* Size of GCM AEAD implicit IV */ + AESCCM_IMP_IV_SZ = 4, /* Size of 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, - GCM_IMP_IV_SZ = 4, /* Size of GCM/CCM AEAD implicit IV */ + GCM_IMP_IV_SZ = 4, /* Size of GCM AEAD implicit IV */ + CCM_IMP_IV_SZ = 4, /* Size of CCM AEAD implicit IV */ GCM_EXP_IV_SZ = 8, /* Size of GCM/CCM AEAD explicit IV */ GCM_NONCE_SZ = GCM_EXP_IV_SZ + GCM_IMP_IV_SZ, @@ -1768,7 +1777,7 @@ enum Misc { ECDHE_SIZE = 32, /* ECDHE server size defaults to 256 bit */ #endif MAX_EXPORT_ECC_SZ = 256, /* Export ANSI X9.62 max future size */ - MAX_CURVE_NAME_SZ = 16, /* Maximum size of curve name string */ + MAX_CURVE_NAME_SZ = 18, /* Maximum size of curve name string */ NEW_SA_MAJOR = 8, /* Most significant byte used with new sig algos */ ED25519_SA_MAJOR = 8, /* Most significant byte for ED25519 */ @@ -1787,16 +1796,16 @@ enum Misc { FALCON_LEVEL5_SA_MINOR = 0xB1, DILITHIUM_LEVEL2_SA_MAJOR = 0xFE, - DILITHIUM_LEVEL2_SA_MINOR = 0xA0, + DILITHIUM_LEVEL2_SA_MINOR = 0xD0, DILITHIUM_LEVEL3_SA_MAJOR = 0xFE, - DILITHIUM_LEVEL3_SA_MINOR = 0xA3, + DILITHIUM_LEVEL3_SA_MINOR = 0xD1, DILITHIUM_LEVEL5_SA_MAJOR = 0xFE, - DILITHIUM_LEVEL5_SA_MINOR = 0xA5, + DILITHIUM_LEVEL5_SA_MINOR = 0xD2, MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */ MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */ -#if defined(HAVE_PQC) +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) MAX_CERT_VERIFY_SZ = 6000, /* For Dilithium */ #elif defined(WOLFSSL_CERT_EXT) MAX_CERT_VERIFY_SZ = 2048, /* For larger extensions */ @@ -1848,13 +1857,13 @@ enum Misc { #define WOLFSSL_NAMED_GROUP_IS_FFHDE(group) \ (MIN_FFHDE_GROUP <= (group) && (group) <= MAX_FFHDE_GROUP) -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER #define WOLFSSL_NAMED_GROUP_IS_PQC(group) \ ((WOLFSSL_PQC_SIMPLE_MIN <= (group) && (group) <= WOLFSSL_PQC_SIMPLE_MAX) || \ (WOLFSSL_PQC_HYBRID_MIN <= (group) && (group) <= WOLFSSL_PQC_HYBRID_MAX)) #else #define WOLFSSL_NAMED_GROUP_IS_PQC(group) ((void)(group), 0) -#endif /* HAVE_PQC */ +#endif /* WOLFSSL_HAVE_KYBER */ /* minimum Downgrade Minor version */ #ifndef WOLFSSL_MIN_DOWNGRADE @@ -1884,7 +1893,7 @@ enum Misc { /* number of items in the signature algo list */ #ifndef WOLFSSL_MAX_SIGALGO -#ifdef HAVE_PQC +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) /* If we are building with post-quantum algorithms, we likely want to * inter-op with OQS's OpenSSL and they send a lot more sigalgs. */ @@ -1913,12 +1922,14 @@ enum Misc { #endif #define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8) -#ifdef HAVE_PQC +#ifdef HAVE_FALCON #ifndef MIN_FALCONKEY_SZ - #define MIN_FALCONKEY_SZ 897 + #define MIN_FALCONKEY_SZ 1281 +#endif #endif +#ifdef HAVE_DILITHIUM #ifndef MIN_DILITHIUMKEY_SZ - #define MIN_DILITHIUMKEY_SZ 1312 + #define MIN_DILITHIUMKEY_SZ 2528 #endif #endif @@ -1961,7 +1972,7 @@ enum Misc { #endif #ifndef MAX_X509_SIZE - #if defined(HAVE_PQC) + #if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) #define MAX_X509_SIZE (8*1024) /* max static x509 buffer size; dilithium is big */ #elif defined(WOLFSSL_HAPROXY) #define MAX_X509_SIZE 3072 /* max static x509 buffer size */ @@ -2169,17 +2180,22 @@ WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutI WOLFSSL_LOCAL int CompleteServerHello(WOLFSSL *ssl); WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); WOLFSSL_LOCAL int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, - word32 hashSigAlgoSz); + word32 hashSigAlgoSz, int matchSuites); #if defined(WOLF_PRIVATE_KEY_ID) && !defined(NO_CHECK_PRIVATE_KEY) WOLFSSL_LOCAL int CreateDevPrivateKey(void** pkey, byte* data, word32 length, int hsType, int label, int id, void* heap, int devId); #endif -WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length); +#ifdef WOLFSSL_BLIND_PRIVATE_KEY +WOLFSSL_LOCAL int wolfssl_priv_der_blind(WC_RNG* rng, DerBuffer* key, + DerBuffer** mask); +WOLFSSL_LOCAL void wolfssl_priv_der_unblind(DerBuffer* key, DerBuffer* mask); +#endif +WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word32* length); #ifdef WOLFSSL_DUAL_ALG_CERTS -WOLFSSL_LOCAL int DecodeAltPrivateKey(WOLFSSL *ssl, word16* length); +WOLFSSL_LOCAL int DecodeAltPrivateKey(WOLFSSL *ssl, word32* length); #endif -#ifdef WOLF_PRIVATE_KEY_ID +#if defined(WOLF_PRIVATE_KEY_ID) || defined(HAVE_PK_CALLBACKS) WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl); #ifndef NO_ASN WOLFSSL_LOCAL int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx); @@ -2195,9 +2211,9 @@ WOLFSSL_LOCAL void FreeAsyncCtx(WOLFSSL* ssl, byte freeAsync); WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl); WOLFSSL_LOCAL void FreeSuites(WOLFSSL* ssl); WOLFSSL_LOCAL int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz); -WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str); +WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str, word32 strLen); #ifndef NO_CERTS -WOLFSSL_LOCAL int CheckForAltNames(DecodedCert* dCert, const char* domain, int* checkCN); +WOLFSSL_LOCAL int CheckForAltNames(DecodedCert* dCert, const char* domain, word32 domainLen, int* checkCN); WOLFSSL_LOCAL int CheckIPAddr(DecodedCert* dCert, const char* ipasc); WOLFSSL_LOCAL void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nameType); #endif @@ -2273,6 +2289,8 @@ enum { /* determine maximum record size */ +#define MAX_RECORD_SIZE 16384 /* 2^14, max size by standard */ + #ifdef RECORD_SIZE /* user supplied value */ #if RECORD_SIZE < 128 || RECORD_SIZE > MAX_RECORD_SIZE @@ -2353,16 +2371,8 @@ typedef struct CipherSuite { #endif } CipherSuite; -WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, - int haveRSAsig, int haveFalconSig, - int haveDilithiumSig, int haveAnon, - int tls1_2, int keySz); -WOLFSSL_LOCAL void InitSuitesHashSigAlgo_ex(byte* hashSigAlgo, int haveECDSAsig, - int haveRSAsig, int haveFalconSig, - int haveDilithiumSig, int haveAnon, - int tls1_2, int keySz, word16* len); /* use wolfSSL_API visibility to be able to test in tests/api.c */ -WOLFSSL_API void InitSuitesHashSigAlgo_ex2(byte* hashSigAlgo, int have, +WOLFSSL_API void InitSuitesHashSigAlgo(byte* hashSigAlgo, int have, int tls1_2, int keySz, word16* len); WOLFSSL_LOCAL int AllocateCtxSuites(WOLFSSL_CTX* ctx); @@ -2631,8 +2641,10 @@ struct WOLFSSL_CERT_MANAGER { /* with CTX free. */ #endif wolfSSL_Ref ref; -#ifdef HAVE_PQC +#ifdef HAVE_FALCON short minFalconKeySz; /* minimum allowed Falcon key size */ +#endif +#ifdef HAVE_DILITHIUM short minDilithiumKeySz; /* minimum allowed Dilithium key size */ #endif #if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \ @@ -2683,6 +2695,14 @@ typedef struct ProcPeerCertArgs { } ProcPeerCertArgs; WOLFSSL_LOCAL int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, int ret, ProcPeerCertArgs* args); +WOLFSSL_LOCAL void DoCrlCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, + ProcPeerCertArgs* args, int* outRet); + +WOLFSSL_LOCAL int SetupStoreCtxCallback(WOLFSSL_X509_STORE_CTX** store_pt, + WOLFSSL* ssl, WOLFSSL_CERT_MANAGER* cm, ProcPeerCertArgs* args, + int cert_err, void* heap, int* x509Free); +WOLFSSL_LOCAL void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store, + WOLFSSL* ssl, void* heap, int x509Free); #endif /* !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) */ #endif /* !defined NO_CERTS */ @@ -2806,74 +2826,108 @@ typedef struct Options Options; /** TLS Extensions - RFC 6066 */ #ifdef HAVE_TLS_EXTENSIONS +#define TLSXT_SERVER_NAME 0x0000 /* a.k.a. SNI */ +#define TLSXT_MAX_FRAGMENT_LENGTH 0x0001 +#define TLSXT_TRUSTED_CA_KEYS 0x0003 +#define TLSXT_TRUNCATED_HMAC 0x0004 +#define TLSXT_STATUS_REQUEST 0x0005 /* a.k.a. OCSP stapling */ +#define TLSXT_SUPPORTED_GROUPS 0x000a /* a.k.a. Supported Curves */ +#define TLSXT_EC_POINT_FORMATS 0x000b +#define TLSXT_SIGNATURE_ALGORITHMS 0x000d /* HELLO_EXT_SIG_ALGO */ +#define TLSXT_USE_SRTP 0x000e /* 14 */ +#define TLSXT_APPLICATION_LAYER_PROTOCOL 0x0010 /* a.k.a. ALPN */ +#define TLSXT_STATUS_REQUEST_V2 0x0011 /* a.k.a. OCSP stapling v2 */ +#define TLSXT_CLIENT_CERTIFICATE 0x0013 /* RFC8446 */ +#define TLSXT_SERVER_CERTIFICATE 0x0014 /* RFC8446 */ +#define TLSXT_ENCRYPT_THEN_MAC 0x0016 /* RFC 7366 */ +#define TLSXT_EXTENDED_MASTER_SECRET 0x0017 /* HELLO_EXT_EXTMS */ +#define TLSXT_SESSION_TICKET 0x0023 +#define TLSXT_PRE_SHARED_KEY 0x0029 +#define TLSXT_EARLY_DATA 0x002a +#define TLSXT_SUPPORTED_VERSIONS 0x002b +#define TLSXT_COOKIE 0x002c +#define TLSXT_PSK_KEY_EXCHANGE_MODES 0x002d +#define TLSXT_CERTIFICATE_AUTHORITIES 0x002f +#define TLSXT_POST_HANDSHAKE_AUTH 0x0031 +#define TLSXT_SIGNATURE_ALGORITHMS_CERT 0x0032 +#define TLSXT_KEY_SHARE 0x0033 +#define TLSXT_CONNECTION_ID 0x0036 +#define TLSXT_KEY_QUIC_TP_PARAMS 0x0039 /* RFC 9001, ch. 8.2 */ +#define TLSXT_ECH 0xfe0d /* from */ + /* draft-ietf-tls-esni-13 */ +/* The 0xFF section is experimental/custom/personal use */ +#define TLSXT_CKS 0xff92 /* X9.146 */ +#define TLSXT_RENEGOTIATION_INFO 0xff01 +#define TLSXT_KEY_QUIC_TP_PARAMS_DRAFT 0xffa5 /* from */ + /* draft-ietf-quic-tls-27 */ + typedef enum { #ifdef HAVE_SNI - TLSX_SERVER_NAME = 0x0000, /* a.k.a. SNI */ -#endif - TLSX_MAX_FRAGMENT_LENGTH = 0x0001, - TLSX_TRUSTED_CA_KEYS = 0x0003, - TLSX_TRUNCATED_HMAC = 0x0004, - TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */ - TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ - TLSX_EC_POINT_FORMATS = 0x000b, + TLSX_SERVER_NAME = TLSXT_SERVER_NAME, +#endif + TLSX_MAX_FRAGMENT_LENGTH = TLSXT_MAX_FRAGMENT_LENGTH, + TLSX_TRUSTED_CA_KEYS = TLSXT_TRUSTED_CA_KEYS, + TLSX_TRUNCATED_HMAC = TLSXT_TRUNCATED_HMAC, + TLSX_STATUS_REQUEST = TLSXT_STATUS_REQUEST, + TLSX_SUPPORTED_GROUPS = TLSXT_SUPPORTED_GROUPS, + TLSX_EC_POINT_FORMATS = TLSXT_EC_POINT_FORMATS, #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) - TLSX_SIGNATURE_ALGORITHMS = 0x000d, /* HELLO_EXT_SIG_ALGO */ + TLSX_SIGNATURE_ALGORITHMS = TLSXT_SIGNATURE_ALGORITHMS, #endif #ifdef WOLFSSL_SRTP - TLSX_USE_SRTP = 0x000e, /* 14 */ + TLSX_USE_SRTP = TLSXT_USE_SRTP, #endif - TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ - TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ + TLSX_APPLICATION_LAYER_PROTOCOL = TLSXT_APPLICATION_LAYER_PROTOCOL, + TLSX_STATUS_REQUEST_V2 = TLSXT_STATUS_REQUEST_V2, #ifdef HAVE_RPK - TLSX_CLIENT_CERTIFICATE_TYPE = 0x0013, /* RFC8446 */ - TLSX_SERVER_CERTIFICATE_TYPE = 0x0014, /* RFC8446 */ + TLSX_CLIENT_CERTIFICATE_TYPE = TLSXT_CLIENT_CERTIFICATE, + TLSX_SERVER_CERTIFICATE_TYPE = TLSXT_SERVER_CERTIFICATE, #endif #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) - TLSX_ENCRYPT_THEN_MAC = 0x0016, /* RFC 7366 */ + TLSX_ENCRYPT_THEN_MAC = TLSXT_ENCRYPT_THEN_MAC, #endif - TLSX_EXTENDED_MASTER_SECRET = 0x0017, /* HELLO_EXT_EXTMS */ - TLSX_SESSION_TICKET = 0x0023, + TLSX_EXTENDED_MASTER_SECRET = TLSXT_EXTENDED_MASTER_SECRET, + TLSX_SESSION_TICKET = TLSXT_SESSION_TICKET, #ifdef WOLFSSL_TLS13 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - TLSX_PRE_SHARED_KEY = 0x0029, + TLSX_PRE_SHARED_KEY = TLSXT_PRE_SHARED_KEY, #endif #ifdef WOLFSSL_EARLY_DATA - TLSX_EARLY_DATA = 0x002a, + TLSX_EARLY_DATA = TLSXT_EARLY_DATA, #endif - TLSX_SUPPORTED_VERSIONS = 0x002b, + TLSX_SUPPORTED_VERSIONS = TLSXT_SUPPORTED_VERSIONS, #ifdef WOLFSSL_SEND_HRR_COOKIE - TLSX_COOKIE = 0x002c, + TLSX_COOKIE = TLSXT_COOKIE, #endif #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d, + TLSX_PSK_KEY_EXCHANGE_MODES = TLSXT_PSK_KEY_EXCHANGE_MODES, #endif #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CA_NAMES) - TLSX_CERTIFICATE_AUTHORITIES = 0x002f, + TLSX_CERTIFICATE_AUTHORITIES = TLSXT_CERTIFICATE_AUTHORITIES, #endif #ifdef WOLFSSL_POST_HANDSHAKE_AUTH - TLSX_POST_HANDSHAKE_AUTH = 0x0031, + TLSX_POST_HANDSHAKE_AUTH = TLSXT_POST_HANDSHAKE_AUTH, #endif #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_SIGALG) - TLSX_SIGNATURE_ALGORITHMS_CERT = 0x0032, + TLSX_SIGNATURE_ALGORITHMS_CERT = TLSXT_SIGNATURE_ALGORITHMS_CERT, #endif - TLSX_KEY_SHARE = 0x0033, + TLSX_KEY_SHARE = TLSXT_KEY_SHARE, #if defined(WOLFSSL_DTLS_CID) - TLSX_CONNECTION_ID = 0x0036, + TLSX_CONNECTION_ID = TLSXT_CONNECTION_ID, #endif /* defined(WOLFSSL_DTLS_CID) */ #ifdef WOLFSSL_QUIC - TLSX_KEY_QUIC_TP_PARAMS = 0x0039, /* RFC 9001, ch. 8.2 */ + TLSX_KEY_QUIC_TP_PARAMS = TLSXT_KEY_QUIC_TP_PARAMS, #endif - #ifdef WOLFSSL_DUAL_ALG_CERTS - TLSX_CKS = 0xff92, /* X9.146; ff indcates personal - * use and 92 is hex for 146. */ + #ifdef HAVE_ECH + TLSX_ECH = TLSXT_ECH, #endif #endif - TLSX_RENEGOTIATION_INFO = 0xff01, -#ifdef WOLFSSL_QUIC - TLSX_KEY_QUIC_TP_PARAMS_DRAFT = 0xffa5, /* from draft-ietf-quic-tls-27 */ +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS) + TLSX_CKS = TLSXT_CKS, #endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) - TLSX_ECH = 0xfe0d, /* from draft-ietf-tls-esni-13 */ + TLSX_RENEGOTIATION_INFO = TLSXT_RENEGOTIATION_INFO, +#ifdef WOLFSSL_QUIC + TLSX_KEY_QUIC_TP_PARAMS_DRAFT = TLSXT_KEY_QUIC_TP_PARAMS_DRAFT, #endif } TLSX_Type; @@ -2986,9 +3040,9 @@ WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest); #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) WOLFSSL_LOCAL int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, - word16* pLength); + word32* pLength); WOLFSSL_LOCAL int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, - byte msgType, word16* pOffset); + byte msgType, word32* pOffset); #endif #if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) @@ -3044,7 +3098,7 @@ WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, void* heap); WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type); WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, - void** data); + void** data, byte ignoreStatus); #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type, @@ -3140,11 +3194,17 @@ typedef struct CSRIv2 { OcspRequest ocsp[1 + MAX_CHAIN_DEPTH]; } request; struct CSRIv2* next; + Signer *pendingSigners; } CertificateStatusRequestItemV2; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, byte options, void* heap, int devId); #ifndef NO_CERTS +WOLFSSL_LOCAL int TLSX_CSR2_IsMulti(TLSX *extensions); +WOLFSSL_LOCAL int TLSX_CSR2_AddPendingSigner(TLSX *extensions, Signer *s); +WOLFSSL_LOCAL Signer* TLSX_CSR2_GetPendingSigners(TLSX *extensions); +WOLFSSL_LOCAL int TLSX_CSR2_ClearPendingCA(WOLFSSL *ssl); +WOLFSSL_LOCAL int TLSX_CSR2_MergePendingCA(WOLFSSL* ssl); WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap); #endif @@ -3369,7 +3429,7 @@ typedef struct KeyShareEntry { word32 keyLen; /* Key size (bytes) */ byte* pubKey; /* Public key */ word32 pubKeyLen; /* Public key length */ -#if !defined(NO_DH) || defined(HAVE_PQC) +#if !defined(NO_DH) || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) byte* privKey; /* Private key - DH and PQ KEMs only */ word32 privKeyLen;/* Only for PQ KEMs. */ #endif @@ -3575,7 +3635,10 @@ struct WOLFSSL_CTX { int certChainCnt; #endif DerBuffer* privateKey; - byte privateKeyType:6; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* privateKeyMask; /* Mask of private key DER. */ +#endif + byte privateKeyType; byte privateKeyId:1; byte privateKeyLabel:1; int privateKeySz; @@ -3583,8 +3646,14 @@ struct WOLFSSL_CTX { #ifdef WOLFSSL_DUAL_ALG_CERTS DerBuffer* altPrivateKey; +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* altPrivateKeyMask; /* Mask of alt private key DER. */ +#endif byte altPrivateKeyType; + byte altPrivateKeyId:1; + byte altPrivateKeyLabel:1; int altPrivateKeySz; + int altPrivateKeyDevId; #endif /* WOLFSSL_DUAL_ALG_CERTS */ #ifdef OPENSSL_ALL WOLFSSL_EVP_PKEY* privateKeyPKey; @@ -3693,8 +3762,10 @@ struct WOLFSSL_CTX { #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum ECC key size */ #endif -#ifdef HAVE_PQC +#ifdef HAVE_FALCON short minFalconKeySz; /* minimum Falcon key size */ +#endif +#ifdef HAVE_DILITHIUM short minDilithiumKeySz;/* minimum Dilithium key size */ #endif unsigned long mask; /* store SSL_OP_ flags */ @@ -3989,6 +4060,7 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 inSz, word16 sz); #ifndef NO_CERTS + WOLFSSL_LOCAL int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s); WOLFSSL_LOCAL int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); WOLFSSL_LOCAL @@ -4035,13 +4107,16 @@ enum KeyExchangeAlgorithm { ecc_static_diffie_hellman_kea /* for verify suite only */ }; -/* Used with InitSuitesHashSigAlgo_ex2 */ +/* Used with InitSuitesHashSigAlgo */ #define SIG_ECDSA 0x01 #define SIG_RSA 0x02 #define SIG_SM2 0x04 #define SIG_FALCON 0x08 #define SIG_DILITHIUM 0x10 #define SIG_ANON 0x20 +/* SIG_ANON is omitted by default */ +#define SIG_ALL (SIG_ECDSA | SIG_RSA | SIG_SM2 | SIG_FALCON | \ + SIG_DILITHIUM) /* Supported Authentication Schemes */ enum SignatureAlgorithm { @@ -4406,6 +4481,10 @@ struct WOLFSSL_SESSION { #endif #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; +#endif +#ifdef HAVE_MAX_FRAGMENT + byte mfl; /* max fragment length negotiated i.e. + * WOLFSSL_MFL_2_8 (6) */ #endif byte isSetup:1; }; @@ -4548,15 +4627,24 @@ typedef struct Buffers { #ifndef NO_CERTS DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ - byte keyType:6; /* Type of key: RSA, ECC, Ed25519 */ +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* keyMask; /* Mask of private key DER. */ +#endif + byte keyType; /* Type of key */ byte keyId:1; /* Key data is an id not data */ byte keyLabel:1; /* Key data is a label not data */ int keySz; /* Size of RSA key */ int keyDevId; /* Device Id for key */ #ifdef WOLFSSL_DUAL_ALG_CERTS DerBuffer* altKey; /* WOLFSSL_CTX owns, unless we own */ - byte altKeyType; /* Type of key: dilithium, falcon */ - int altKeySz; /* Size of key */ +#ifdef WOLFSSL_BLIND_PRIVATE_KEY + DerBuffer* altKeyMask; /* Mask of alt private key DER. */ +#endif + byte altKeyType; /* Type of alt key */ + byte altKeyId:1; /* Key data is an id not data */ + byte altKeyLabel:1; /* Key data is a label not data */ + int altKeySz; /* Size of alt key */ + int altKeyDevId; /* Device Id for alt key */ #endif DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ /* chain after self, in DER, with leading size for each cert */ @@ -4841,8 +4929,10 @@ struct Options { #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) short minEccKeySz; /* minimum ECC key size */ #endif -#if defined(HAVE_PQC) +#if defined(HAVE_FALCON) short minFalconKeySz; /* minimum Falcon key size */ +#endif +#if defined(HAVE_DILITHIUM) short minDilithiumKeySz;/* minimum Dilithium key size */ #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -5036,9 +5126,9 @@ struct WOLFSSL_X509 { int pubKeyOID; DNS_entry* altNamesNext; /* hint for retrieval */ #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ - defined(HAVE_PQC) + defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) word32 pkCurveOID; -#endif /* HAVE_ECC || HAVE_PQC */ +#endif #ifndef NO_CERTS DerBuffer* derCert; /* may need */ #endif @@ -5631,9 +5721,11 @@ struct WOLFSSL { curve448_key* peerX448Key; byte peerX448KeyPresent; #endif -#ifdef HAVE_PQC +#ifdef HAVE_FALCON falcon_key* peerFalconKey; byte peerFalconKeyPresent; +#endif +#ifdef HAVE_DILITHIUM dilithium_key* peerDilithiumKey; byte peerDilithiumKeyPresent; #endif @@ -5861,6 +5953,10 @@ struct WOLFSSL { #ifdef HAVE_SECRET_CALLBACK SessionSecretCb sessionSecretCb; void* sessionSecretCtx; + TicketParseCb ticketParseCb; + void* ticketParseCtx; + TlsSecretCb tlsSecretCb; + void* tlsSecretCtx; #ifdef WOLFSSL_TLS13 Tls13SecretCb tls13SecretCb; void* tls13SecretCtx; @@ -6110,16 +6206,11 @@ typedef struct { int name_len; const char *name; int nid; + word16 curve; } WOLF_EC_NIST_NAME; extern const WOLF_EC_NIST_NAME kNistCurves[]; -/* This is the longest and shortest curve name in the kNistCurves list. Note we - * also have quantum-safe group names as well. */ -#define kNistCurves_MIN_NAME_LEN 5 -#ifdef HAVE_PQC -#define kNistCurves_MAX_NAME_LEN 32 -#else -#define kNistCurves_MAX_NAME_LEN 7 -#endif +WOLFSSL_LOCAL int set_curves_list(WOLFSSL* ssl, WOLFSSL_CTX *ctx, + const char* names, byte curves_only); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ /* internal functions */ @@ -6179,6 +6270,7 @@ WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); +WOLFSSL_LOCAL int IsTLS_ex(const ProtocolVersion pv); WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_3(ProtocolVersion pv); WOLFSSL_LOCAL int IsEncryptionOn(const WOLFSSL* ssl, int isSend); @@ -6407,6 +6499,7 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); WOLFSSL_LOCAL word32 LowResTimer(void); WOLFSSL_LOCAL int FindSuiteSSL(const WOLFSSL* ssl, byte* suite); +WOLFSSL_LOCAL int FindSuite(const Suites* suites, byte first, byte second); WOLFSSL_LOCAL void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType); @@ -6741,6 +6834,11 @@ WOLFSSL_LOCAL int tls13ShowSecrets(WOLFSSL* ssl, int id, const unsigned char* se int secretSz, void* ctx); #endif +#if defined(SHOW_SECRETS) +WOLFSSL_LOCAL int tlsShowSecrets(WOLFSSL* ssl, void* secret, + int secretSz, void* ctx); +#endif + /* Optional Pre-Master-Secret logging for Wireshark */ #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) #ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT diff --git a/src/wolfssl/openssl/bn.h b/src/wolfssl/openssl/bn.h index 973b855..d5ad52b 100644 --- a/src/wolfssl/openssl/bn.h +++ b/src/wolfssl/openssl/bn.h @@ -40,7 +40,9 @@ typedef struct WOLFSSL_BIGNUM { int neg; /* openssh deference */ void *internal; /* our big num */ +#if !defined(NO_BIG_INT) || defined(WOLFSSL_SP_MATH) mp_int mpi; +#endif } WOLFSSL_BIGNUM; #define WOLFSSL_BN_ULONG unsigned long diff --git a/src/wolfssl/openssl/ec.h b/src/wolfssl/openssl/ec.h index 23ef5e9..da988c6 100644 --- a/src/wolfssl/openssl/ec.h +++ b/src/wolfssl/openssl/ec.h @@ -74,9 +74,15 @@ enum { #ifdef HAVE_ED448 NID_ED448 = ED448k, #endif +#ifdef HAVE_CURVE448 + NID_X448 = X448k, +#endif #ifdef HAVE_ED25519 NID_ED25519 = ED25519k, #endif +#ifdef HAVE_CURVE25519 + NID_X25519 = X25519k, +#endif OPENSSL_EC_EXPLICIT_CURVE = 0x000, OPENSSL_EC_NAMED_CURVE = 0x001, @@ -138,6 +144,12 @@ struct WOLFSSL_EC_BUILTIN_CURVE { typedef int point_conversion_form_t; +typedef struct WOLFSSL_EC_KEY_METHOD { + /* Not implemented */ + /* Just here so that some C compilers don't complain. To be removed. */ + void* dummy_member; +} WOLFSSL_EC_KEY_METHOD; + WOLFSSL_API size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r,size_t nitems); @@ -306,12 +318,29 @@ WOLFSSL_API int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, const WOLFSSL_EC_POINT *a); -#ifndef HAVE_SELFTEST WOLFSSL_API char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx); -#endif +WOLFSSL_API +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_hex2point + (const WOLFSSL_EC_GROUP *group, const char *hex, + WOLFSSL_EC_POINT *p, WOLFSSL_BN_CTX *ctx); + +WOLFSSL_API const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_OpenSSL(void); +WOLFSSL_API WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_METHOD_new( + const WOLFSSL_EC_KEY_METHOD *meth); +WOLFSSL_API void wolfSSL_EC_KEY_METHOD_free(WOLFSSL_EC_KEY_METHOD *meth); +/* TODO when implementing change the types to the real callback signatures + * and use real parameter names */ +WOLFSSL_API void wolfSSL_EC_KEY_METHOD_set_init(WOLFSSL_EC_KEY_METHOD *meth, + void* a1, void* a2, void* a3, void* a4, void* a5, void* a6); +WOLFSSL_API void wolfSSL_EC_KEY_METHOD_set_sign(WOLFSSL_EC_KEY_METHOD *meth, + void* a1, void* a2, void* a3); +WOLFSSL_API const WOLFSSL_EC_KEY_METHOD *wolfSSL_EC_KEY_get_method( + const WOLFSSL_EC_KEY *key); +WOLFSSL_API int wolfSSL_EC_KEY_set_method(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_KEY_METHOD *meth); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -320,6 +349,7 @@ typedef WOLFSSL_EC_GROUP EC_GROUP; typedef WOLFSSL_EC_GROUP EC_METHOD; typedef WOLFSSL_EC_POINT EC_POINT; typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; +typedef WOLFSSL_EC_KEY_METHOD EC_KEY_METHOD; #ifndef HAVE_ECC #define OPENSSL_NO_EC @@ -395,9 +425,8 @@ typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; #define EC_KEY_set_conv_form wolfSSL_EC_KEY_set_conv_form #define EC_KEY_get_conv_form wolfSSL_EC_KEY_get_conv_form -#ifndef HAVE_SELFTEST - #define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex -#endif +#define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex +#define EC_POINT_hex2point wolfSSL_EC_POINT_hex2point #define EC_POINT_dump wolfSSL_EC_POINT_dump #define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves @@ -405,6 +434,14 @@ typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; #define EC_curve_nid2nist wolfSSL_EC_curve_nid2nist #define EC_curve_nist2nid wolfSSL_EC_curve_nist2nid +#define EC_KEY_OpenSSL wolfSSL_EC_KEY_OpenSSL +#define EC_KEY_METHOD_new wolfSSL_EC_KEY_METHOD_new +#define EC_KEY_METHOD_free wolfSSL_EC_KEY_METHOD_free +#define EC_KEY_METHOD_set_init wolfSSL_EC_KEY_METHOD_set_init +#define EC_KEY_METHOD_set_sign wolfSSL_EC_KEY_METHOD_set_sign +#define EC_KEY_get_method wolfSSL_EC_KEY_get_method +#define EC_KEY_set_method wolfSSL_EC_KEY_set_method + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #ifdef __cplusplus diff --git a/src/wolfssl/openssl/evp.h b/src/wolfssl/openssl/evp.h index bdeabf2..346cefc 100644 --- a/src/wolfssl/openssl/evp.h +++ b/src/wolfssl/openssl/evp.h @@ -401,6 +401,7 @@ typedef union { #define NID_X9_62_id_ecPublicKey EVP_PKEY_EC #define NID_rsaEncryption EVP_PKEY_RSA +#define NID_rsa EVP_PKEY_RSA #define NID_dsa EVP_PKEY_DSA #define EVP_PKEY_OP_SIGN (1 << 3) diff --git a/src/wolfssl/openssl/hmac.h b/src/wolfssl/openssl/hmac.h index 427a3d6..818c860 100644 --- a/src/wolfssl/openssl/hmac.h +++ b/src/wolfssl/openssl/hmac.h @@ -45,7 +45,7 @@ WOLFSSL_API unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, int key_len, - const unsigned char* d, int n, unsigned char* md, + const unsigned char* d, size_t n, unsigned char* md, unsigned int* md_len); WOLFSSL_API WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void); @@ -69,7 +69,7 @@ WOLFSSL_API const WOLFSSL_EVP_MD *wolfSSL_HMAC_CTX_get_md(const WOLFSSL_HMAC_CTX 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 wolfSSL_HMAC #define HMAC_CTX_new wolfSSL_HMAC_CTX_new #define HMAC_CTX_init wolfSSL_HMAC_CTX_Init diff --git a/src/wolfssl/openssl/opensslv.h b/src/wolfssl/openssl/opensslv.h index 57404c9..f68b6ca 100644 --- a/src/wolfssl/openssl/opensslv.h +++ b/src/wolfssl/openssl/opensslv.h @@ -25,6 +25,7 @@ #define WOLFSSL_OPENSSLV_H_ #include +#include #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) diff --git a/src/wolfssl/openssl/sha.h b/src/wolfssl/openssl/sha.h index c364414..ab38c5c 100644 --- a/src/wolfssl/openssl/sha.h +++ b/src/wolfssl/openssl/sha.h @@ -27,7 +27,7 @@ #include #include - +#include #ifdef WOLFSSL_PREFIX #include "prefix_sha.h" #endif @@ -151,7 +151,7 @@ typedef WOLFSSL_SHA224_CTX SHA224_CTX; * to Sha256, is expected to also be 16 byte aligned addresses. */ typedef struct WOLFSSL_SHA256_CTX { /* big enough to hold wolfcrypt Sha256, but check on init */ - ALIGN16 void* holder[(274 + CTX_SHA_HW_ADDER + WC_ASYNC_DEV_SIZE) / + ALIGN16 void* holder[sizeof(wc_Sha256) / sizeof(void*)]; #if defined(WOLFSSL_DEVCRYPTO_HASH) || defined(WOLFSSL_HASH_KEEP) ALIGN16 void* keephash_holder[sizeof(void*) + (2 * sizeof(unsigned int))]; diff --git a/src/wolfssl/openssl/sha3.h b/src/wolfssl/openssl/sha3.h index 1b0d63b..4407bca 100644 --- a/src/wolfssl/openssl/sha3.h +++ b/src/wolfssl/openssl/sha3.h @@ -27,6 +27,7 @@ #include #include +#include #ifdef WOLFSSL_PREFIX #include "prefix_sha.h" @@ -41,7 +42,11 @@ * to Sha3 is expected to also be 16 byte aligned addresses. */ struct WOLFSSL_SHA3_CTX { /* big enough to hold wolfcrypt Sha3, but check on init */ +#ifdef WOLFSSL_SHA3 + ALIGN16 void* holder[sizeof(wc_Sha3)]; +#else ALIGN16 void* holder[(424 + WC_ASYNC_DEV_SIZE) / sizeof(void*)]; +#endif }; #ifndef WOLFSSL_NOSHA3_224 diff --git a/src/wolfssl/openssl/ssl.h b/src/wolfssl/openssl/ssl.h index 5cd96e2..0fbf621 100644 --- a/src/wolfssl/openssl/ssl.h +++ b/src/wolfssl/openssl/ssl.h @@ -210,6 +210,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define i2d_PKCS8PrivateKey_bio wolfSSL_PEM_write_bio_PKCS8PrivateKey #define PKCS8_PRIV_KEY_INFO_free wolfSSL_EVP_PKEY_free #define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp +#define SSL_set_ecdh_auto wolfSSL_set_ecdh_auto #define SSL_CTX_set_ecdh_auto wolfSSL_CTX_set_ecdh_auto #define i2d_PUBKEY wolfSSL_i2d_PUBKEY @@ -366,6 +367,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define SSL_SESSION_dup wolfSSL_SESSION_dup #define SSL_SESSION_free wolfSSL_SESSION_free #define SSL_SESSION_set_cipher wolfSSL_SESSION_set_cipher +#define SSL_SESSION_get_max_fragment_length \ + wolfSSL_SESSION_get_max_fragment_length #define SSL_is_init_finished wolfSSL_is_init_finished #define SSL_SESSION_set1_id wolfSSL_SESSION_set1_id @@ -500,6 +503,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_set_pubkey wolfSSL_X509_set_pubkey #define X509_set_notAfter wolfSSL_X509_set_notAfter #define X509_set_notBefore wolfSSL_X509_set_notBefore +#define X509_set1_notAfter wolfSSL_X509_set1_notAfter +#define X509_set1_notBefore wolfSSL_X509_set1_notBefore #define X509_set_serialNumber wolfSSL_X509_set_serialNumber #define X509_set_version wolfSSL_X509_set_version #define X509_REQ_set_version wolfSSL_X509_set_version @@ -634,6 +639,9 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK #define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL +#define X509_V_FLAG_PARTIAL_CHAIN 0 +#define X509_V_FLAG_TRUSTED_FIRST 0 + #define X509_V_FLAG_USE_CHECK_TIME WOLFSSL_USE_CHECK_TIME #define X509_V_FLAG_NO_CHECK_TIME WOLFSSL_NO_CHECK_TIME #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT WOLFSSL_ALWAYS_CHECK_SUBJECT @@ -674,10 +682,13 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_CTX_verify_cb)(c)) #define X509_STORE_set_verify_cb_func(s, c) \ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_CTX_verify_cb)(c)) +#define X509_STORE_set_get_crl wolfSSL_X509_STORE_set_get_crl +#define X509_STORE_set_check_crl wolfSSL_X509_STORE_set_check_crl #define X509_STORE_new wolfSSL_X509_STORE_new #define X509_STORE_free wolfSSL_X509_STORE_free +#define X509_STORE_up_ref wolfSSL_X509_STORE_up_ref #define X509_STORE_add_lookup wolfSSL_X509_STORE_add_lookup #define X509_STORE_add_cert wolfSSL_X509_STORE_add_cert #define X509_STORE_add_crl wolfSSL_X509_STORE_add_crl @@ -686,8 +697,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_STORE_get_by_subject wolfSSL_X509_STORE_get_by_subject #define X509_STORE_set_ex_data wolfSSL_X509_STORE_set_ex_data #define X509_STORE_get_ex_data wolfSSL_X509_STORE_get_ex_data +#define X509_STORE_get0_param wolfSSL_X509_STORE_get0_param #define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer #define X509_STORE_CTX_set_time wolfSSL_X509_STORE_CTX_set_time +#define X509_STORE_CTX_get0_param wolfSSL_X509_STORE_CTX_get0_param #define X509_VERIFY_PARAM_new wolfSSL_X509_VERIFY_PARAM_new #define X509_VERIFY_PARAM_free wolfSSL_X509_VERIFY_PARAM_free #define X509_VERIFY_PARAM_set_flags wolfSSL_X509_VERIFY_PARAM_set_flags @@ -711,6 +724,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define d2i_X509_CRL_fp wolfSSL_d2i_X509_CRL_fp #define PEM_read_X509_CRL wolfSSL_PEM_read_X509_CRL +#define X509_CRL_dup wolfSSL_X509_CRL_dup #define X509_CRL_free wolfSSL_X509_CRL_free #define X509_CRL_get_lastUpdate wolfSSL_X509_CRL_get_lastUpdate #define X509_CRL_get0_lastUpdate wolfSSL_X509_CRL_get_lastUpdate @@ -822,6 +836,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define COMP_rle wolfSSL_COMP_rle #define SSL_COMP_add_compression_method wolfSSL_COMP_add_compression_method +#define SSL_get_current_compression(ssl) 0 +#define SSL_get_current_expansion(ssl) 0 +#define SSL_COMP_get_name wolfSSL_COMP_get_name + #define SSL_get_ex_new_index wolfSSL_get_ex_new_index #define RSA_get_ex_new_index wolfSSL_get_ex_new_index @@ -835,18 +853,21 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #ifndef NO_ASN_TIME #define ASN1_TIME_new wolfSSL_ASN1_TIME_new #define ASN1_UTCTIME_new wolfSSL_ASN1_TIME_new +#define ASN1_GENERALIZEDTIME_new wolfSSL_ASN1_TIME_new #define ASN1_TIME_free wolfSSL_ASN1_TIME_free #define ASN1_UTCTIME_free wolfSSL_ASN1_TIME_free +#define ASN1_GENERALIZEDTIME_free wolfSSL_ASN1_TIME_free #define ASN1_TIME_adj wolfSSL_ASN1_TIME_adj #define ASN1_TIME_print wolfSSL_ASN1_TIME_print #define ASN1_TIME_to_string wolfSSL_ASN1_TIME_to_string #define ASN1_TIME_to_tm wolfSSL_ASN1_TIME_to_tm #define ASN1_TIME_to_generalizedtime wolfSSL_ASN1_TIME_to_generalizedtime +#define ASN1_UTCTIME_set wolfSSL_ASN1_UTCTIME_set #endif #define ASN1_TIME_set wolfSSL_ASN1_TIME_set #define ASN1_TIME_set_string wolfSSL_ASN1_TIME_set_string +#define ASN1_GENERALIZEDTIME_set_string wolfSSL_ASN1_TIME_set_string #define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print -#define ASN1_GENERALIZEDTIME_free wolfSSL_ASN1_GENERALIZEDTIME_free #define ASN1_tag2str wolfSSL_ASN1_tag2str @@ -916,7 +937,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #endif #define SSL_set0_verify_cert_store wolfSSL_set0_verify_cert_store #define SSL_set1_verify_cert_store wolfSSL_set1_verify_cert_store -#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) +#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((x)) #define SSL_get_client_CA_list wolfSSL_get_client_CA_list #define SSL_set_client_CA_list wolfSSL_set_client_CA_list #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx @@ -937,7 +958,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_alert_type_string wolfSSL_alert_type_string #define SSL_alert_desc_string wolfSSL_alert_desc_string -#define SSL_state_string wolfSSL_state_string +#define SSL_state_string wolfSSL_state_string_long #define RSA_free wolfSSL_RSA_free #define RSA_generate_key wolfSSL_RSA_generate_key @@ -1212,6 +1233,7 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #define TLSEXT_STATUSTYPE_ocsp 1 +#define TLSEXT_max_fragment_length_DISABLED WOLFSSL_MFL_DISABLED #define TLSEXT_max_fragment_length_512 WOLFSSL_MFL_2_9 #define TLSEXT_max_fragment_length_1024 WOLFSSL_MFL_2_10 #define TLSEXT_max_fragment_length_2048 WOLFSSL_MFL_2_11 @@ -1337,6 +1359,10 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #define SSL_CONF_TYPE_FILE WOLFSSL_CONF_TYPE_FILE #define SSL_CONF_TYPE_DIR WOLFSSL_CONF_TYPE_DIR +#define OPENSSL_INIT_new wolfSSL_OPENSSL_INIT_new +#define OPENSSL_INIT_free wolfSSL_OPENSSL_INIT_free +#define OPENSSL_INIT_set_config_appname wolfSSL_OPENSSL_INIT_set_config_appname + #if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) @@ -1511,7 +1537,8 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE SRTP_PROTECTION_PROFILE; #define OPENSSL_STRING WOLFSSL_STRING #define OPENSSL_CSTRING WOLFSSL_STRING -#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 +#define TLSEXT_TYPE_application_layer_protocol_negotiation \ + TLSXT_APPLICATION_LAYER_PROTOCOL #define OPENSSL_NPN_UNSUPPORTED 0 #define OPENSSL_NPN_NEGOTIATED 1 diff --git a/src/wolfssl/openssl/tls1.h b/src/wolfssl/openssl/tls1.h index dc4a27c..843696a 100644 --- a/src/wolfssl/openssl/tls1.h +++ b/src/wolfssl/openssl/tls1.h @@ -45,8 +45,10 @@ #ifdef WOLFSSL_QUIC /* from rfc9001 */ -#define TLSEXT_TYPE_quic_transport_parameters_draft 0xffa5 -#define TLSEXT_TYPE_quic_transport_parameters 0x0039 +#define TLSEXT_TYPE_quic_transport_parameters_draft \ + TLSXT_KEY_QUIC_TP_PARAMS_DRAFT +#define TLSEXT_TYPE_quic_transport_parameters \ + TLSXT_KEY_QUIC_TP_PARAMS #endif #endif /* WOLFSSL_OPENSSL_TLS1_H_ */ diff --git a/src/wolfssl/openssl/x509.h b/src/wolfssl/openssl/x509.h index a603ce6..9afb8e0 100644 --- a/src/wolfssl/openssl/x509.h +++ b/src/wolfssl/openssl/x509.h @@ -50,7 +50,6 @@ #define X509_FLAG_NO_IDS (1UL << 12) #define XN_FLAG_FN_SN 0 -#define XN_FLAG_ONELINE 0 #define XN_FLAG_COMPAT 0 #define XN_FLAG_RFC2253 1 #define XN_FLAG_SEP_COMMA_PLUS (1 << 16) @@ -68,6 +67,7 @@ #define XN_FLAG_FN_ALIGN (1 << 25) #define XN_FLAG_MULTILINE 0xFFFF +#define XN_FLAG_ONELINE (XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_SPC_EQ | XN_FLAG_FN_SN) /* * All of these aren't actually used in wolfSSL. Some are included to diff --git a/src/wolfssl/openssl/x509v3.h b/src/wolfssl/openssl/x509v3.h index c9c9ad8..51b4e65 100644 --- a/src/wolfssl/openssl/x509v3.h +++ b/src/wolfssl/openssl/x509v3.h @@ -145,7 +145,7 @@ WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_a2i_IPADDRESS(const char* ipa); #define BASIC_CONSTRAINTS_free wolfSSL_BASIC_CONSTRAINTS_free #define AUTHORITY_KEYID_free wolfSSL_AUTHORITY_KEYID_free -#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) +#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((x)) #define ASN1_INTEGER WOLFSSL_ASN1_INTEGER #define ASN1_OCTET_STRING WOLFSSL_ASN1_STRING #define X509V3_EXT_get wolfSSL_X509V3_EXT_get diff --git a/src/wolfssl/ssl.h b/src/wolfssl/ssl.h index 804ec44..d1a88bd 100644 --- a/src/wolfssl/ssl.h +++ b/src/wolfssl/ssl.h @@ -37,6 +37,7 @@ #include #include #include +#include /* For the types */ #include @@ -152,8 +153,6 @@ typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; typedef struct WOLFSSL_CRL WOLFSSL_CRL; typedef struct WOLFSSL_X509_STORE_CTX WOLFSSL_X509_STORE_CTX; -typedef int (*WOLFSSL_X509_STORE_CTX_verify_cb)(int, WOLFSSL_X509_STORE_CTX *); - typedef struct WOLFSSL_BY_DIR_HASH WOLFSSL_BY_DIR_HASH; typedef struct WOLFSSL_BY_DIR_entry WOLFSSL_BY_DIR_entry; typedef struct WOLFSSL_BY_DIR WOLFSSL_BY_DIR; @@ -228,6 +227,12 @@ typedef struct WOLFSSL_DIST_POINT WOLFSSL_DIST_POINT; typedef struct WOLFSSL_CONF_CTX WOLFSSL_CONF_CTX; +typedef int (*WOLFSSL_X509_STORE_CTX_verify_cb)(int, WOLFSSL_X509_STORE_CTX *); +typedef int (*WOLFSSL_X509_STORE_CTX_get_crl_cb)(WOLFSSL_X509_STORE_CTX *, + WOLFSSL_X509_CRL **, WOLFSSL_X509 *); +typedef int (*WOLFSSL_X509_STORE_CTX_check_crl_cb)(WOLFSSL_X509_STORE_CTX *, + WOLFSSL_X509_CRL *); + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || defined(HAVE_CURL) struct WOLFSSL_OBJ_NAME { @@ -603,6 +608,7 @@ struct WOLFSSL_X509_STORE { #endif #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; + WOLFSSL_X509_STORE_CTX_get_crl_cb get_crl_cb; #endif #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; @@ -704,6 +710,7 @@ struct WOLFSSL_X509_STORE_CTX { int totalCerts; /* number of peer cert buffers */ WOLFSSL_BUFFER_INFO* certs; /* peer certs */ WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */ + void* heap; }; typedef char* WOLFSSL_STRING; @@ -793,9 +800,9 @@ enum SNICbReturn { * functions should use this macro to fill this gap. Users who want them * to return the same return value as OpenSSL can define * WOLFSSL_ERR_CODE_OPENSSL. - * Give item1 a variable that contains the potentially negative + * Give rc a variable that contains the potentially negative * wolfSSL-defined return value or the return value itself, and - * give item2 the openSSL-defined return value. + * give fail_rc the openSSL-defined return value. * Note that this macro replaces only negative return values with the * specified value. * Since wolfSSL 4.7.0, the following functions use this macro: @@ -804,11 +811,15 @@ enum SNICbReturn { * - wolfSSL_EVP_PKEY_cmp */ #if defined(WOLFSSL_ERROR_CODE_OPENSSL) - #define WS_RETURN_CODE(item1,item2) \ - (((item1) < 0) ? (int)(item2) : (int)(item1)) + #define WS_RETURN_CODE(rc, fail_rc) \ + (((rc) < 0) ? (int)(fail_rc) : (int)(rc)) #else - #define WS_RETURN_CODE(item1,item2) (item1) + #define WS_RETURN_CODE(rc, fail_rc) (rc) #endif +#define WS_RC(rc) \ + (((rc) == 1) ? 1 : 0) +#define WC_TO_WS_RC(ret) \ + (((ret) == 0) ? 1 : (ret)) /* Maximum master key length (SECRET_LEN) */ #define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 @@ -1130,6 +1141,7 @@ WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap); WOLFSSL_ABI WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method); WOLFSSL_API int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx); #ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_set_ecdh_auto(WOLFSSL* ssl, int onoff); WOLFSSL_API int wolfSSL_CTX_set_ecdh_auto(WOLFSSL_CTX* ctx, int onoff); WOLFSSL_API int wolfSSL_get_signature_nid(WOLFSSL* ssl, int* nid); WOLFSSL_API int wolfSSL_get_signature_type_nid(const WOLFSSL* ssl, int* nid); @@ -1141,7 +1153,7 @@ WOLFSSL_API int wolfSSL_CTX_set1_sigalgs_list(WOLFSSL_CTX* ctx, WOLFSSL_API int wolfSSL_set1_sigalgs_list(WOLFSSL* ssl, const char* list); #endif WOLFSSL_ABI WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx); -WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl); +WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(const WOLFSSL* ssl); WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_CTX_get0_param(WOLFSSL_CTX* ctx); WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PARAM *vpm); @@ -1177,6 +1189,21 @@ WOLFSSL_API int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz); WOLFSSL_ABI WOLFSSL_API int wolfSSL_accept(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req); WOLFSSL_API int wolfSSL_mutual_auth(WOLFSSL* ssl, int req); + +WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); +#if defined(OPENSSL_EXTRA) && defined(HAVE_SUPPORTED_CURVES) +WOLFSSL_API int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count); + +#ifdef HAVE_ECC +WOLFSSL_API int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list); +WOLFSSL_API int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list); +#endif +#endif + #ifdef WOLFSSL_TLS13 WOLFSSL_API int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret, unsigned int secretSz); @@ -1194,20 +1221,6 @@ WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_preferred_group(WOLFSSL* ssl); -WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, - int count); -WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); - -#if defined(OPENSSL_EXTRA) && defined(HAVE_SUPPORTED_CURVES) -WOLFSSL_API int wolfSSL_CTX_set1_groups(WOLFSSL_CTX* ctx, int* groups, - int count); -WOLFSSL_API int wolfSSL_set1_groups(WOLFSSL* ssl, int* groups, int count); - -#ifdef HAVE_ECC -WOLFSSL_API int wolfSSL_CTX_set1_groups_list(WOLFSSL_CTX *ctx, const char *list); -WOLFSSL_API int wolfSSL_set1_groups_list(WOLFSSL *ssl, const char *list); -#endif -#endif WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL* ssl); @@ -1236,6 +1249,7 @@ WOLFSSL_API unsigned int wolfSSL_SESSION_get_max_early_data(const WOLFSSL_SESSIO WOLFSSL_ABI WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX* ctx); WOLFSSL_ABI WOLFSSL_API void wolfSSL_free(WOLFSSL* ssl); WOLFSSL_ABI WOLFSSL_API int wolfSSL_shutdown(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SendUserCanceled(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags); WOLFSSL_API int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags); @@ -1361,8 +1375,17 @@ WOLFSSL_ABI WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx #ifdef HAVE_SECRET_CALLBACK typedef int (*SessionSecretCb)(WOLFSSL* ssl, void* secret, int* secretSz, void* ctx); -WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb, - void*); +/* This callback is used to set the master secret during resumption */ +WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, + void* ctx); +typedef int (*TicketParseCb)(WOLFSSL *ssl, const unsigned char *data, + int len, void *ctx); +WOLFSSL_API int wolfSSL_set_session_ticket_ext_cb(WOLFSSL* ssl, + TicketParseCb cb, void *ctx); +typedef int (*TlsSecretCb)(WOLFSSL* ssl, void* secret, int secretSz, + void* ctx); +/* This callback is used to log the secret for TLS <= 1.2 */ +WOLFSSL_API int wolfSSL_set_secret_cb(WOLFSSL* ssl, TlsSecretCb cb, void* ctx); #ifdef WOLFSSL_TLS13 typedef int (*Tls13SecretCb)(WOLFSSL* ssl, int id, const unsigned char* secret, int secretSz, void* ctx); @@ -1659,6 +1682,11 @@ WOLFSSL_API int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned cha WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_session_reused(WOLFSSL* ssl); +#ifdef OPENSSL_EXTRA +/* using unsigned char instead of uint8_t here to avoid stdint include */ +WOLFSSL_API unsigned char wolfSSL_SESSION_get_max_fragment_length( + WOLFSSL_SESSION* session); +#endif WOLFSSL_API int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_SESSION_new(void); @@ -1687,6 +1715,7 @@ WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(const WOLFSSL_SESSION* WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL* ssl); WOLFSSL_API void wolfSSL_sk_CIPHER_free(WOLF_STACK_OF(WOLFSSL_CIPHER)* sk); WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SessionIsSetup(WOLFSSL_SESSION* session); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new_ex(void* heap); @@ -1866,6 +1895,10 @@ WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *c WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); WOLFSSL_API void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st, WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); +WOLFSSL_API void wolfSSL_X509_STORE_set_get_crl(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_get_crl_cb get_cb); +WOLFSSL_API void wolfSSL_X509_STORE_set_check_crl(WOLFSSL_X509_STORE *st, + WOLFSSL_X509_STORE_CTX_check_crl_cb check_crl); WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n, unsigned char** out); WOLFSSL_API int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, @@ -1927,8 +1960,12 @@ WOLFSSL_API int wolfSSL_X509_set_issuer_name(WOLFSSL_X509* cert, WOLFSSL_API int wolfSSL_X509_set_pubkey(WOLFSSL_X509* cert, WOLFSSL_EVP_PKEY* pkey); WOLFSSL_API int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t); +WOLFSSL_API int wolfSSL_X509_set1_notAfter(WOLFSSL_X509* x509, + const WOLFSSL_ASN1_TIME *t); WOLFSSL_API int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t); +WOLFSSL_API int wolfSSL_X509_set1_notBefore(WOLFSSL_X509* x509, + const WOLFSSL_ASN1_TIME *t); WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509* x509); WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509* x509); WOLFSSL_API int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, @@ -1985,6 +2022,8 @@ WOLFSSL_API void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store); WOLFSSL_API int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store); WOLFSSL_API int wolfSSL_X509_STORE_add_cert( WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509); +WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_get0_param( + const WOLFSSL_X509_STORE *ctx); WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( WOLFSSL_X509_STORE_CTX* ctx); WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain( @@ -1996,7 +2035,10 @@ WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, WOLFSSL_API int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store); WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj); +WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_CTX_get0_param( + WOLFSSL_X509_STORE_CTX *ctx); WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void); +WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new_ex(void* heap); WOLFSSL_API int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)*); WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx); @@ -2540,7 +2582,8 @@ enum { /* ssl Constants */ WOLFSSL_FAILURE = 0, /* for some functions */ WOLFSSL_SUCCESS = 1, -/* WOLFSSL_SHUTDOWN_NOT_DONE is returned by wolfSSL_shutdown when the other end +/* WOLFSSL_SHUTDOWN_NOT_DONE is returned by wolfSSL_shutdown and + * wolfSSL_SendUserCanceled when the other end * of the connection has yet to send its close notify alert as part of the * bidirectional shutdown. To complete the shutdown, either keep calling * wolfSSL_shutdown until it returns WOLFSSL_SUCCESS or call wolfSSL_read until @@ -2924,6 +2967,7 @@ WOLFSSL_API int wolfSSL_X509_REVOKED_get_serial_number(RevokedCert* rev, byte* in, int* inOutSz); #endif #if defined(HAVE_CRL) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) +WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_X509_CRL_dup(const WOLFSSL_X509_CRL* crl); WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl); #endif @@ -2964,7 +3008,6 @@ WOLFSSL_API int wolfSSL_connect_cert(WOLFSSL* ssl); /* PKCS12 compatibility */ -typedef struct WC_PKCS12 WC_PKCS12; WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12); WOLFSSL_API int wolfSSL_i2d_PKCS12_bio(WOLFSSL_BIO *bio, WC_PKCS12 *pkcs12); @@ -3096,6 +3139,17 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len, const unsigned char* in, long sz, int format); WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx, const unsigned char* in, long sz); +#ifdef WOLFSSL_DUAL_ALG_CERTS + WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format); + WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_id(WOLFSSL_CTX* ctx, + const unsigned char* id, long sz, + int devId, long keySz); + WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, + const unsigned char* id, long sz, int devId); + WOLFSSL_API int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, + const char* label, int devId); +#endif /* SSL versions */ WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, const unsigned char* in, @@ -3114,6 +3168,17 @@ WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* key, unsigned int len, WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, const unsigned char* in, long sz); WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl); +#ifdef WOLFSSL_DUAL_ALG_CERTS + WOLFSSL_API int wolfSSL_use_AltPrivateKey_buffer(WOLFSSL* ssl, + const unsigned char* in, long sz, int format); + WOLFSSL_API int wolfSSL_use_AltPrivateKey_id(WOLFSSL* ssl, + const unsigned char* id, long sz, + int devId, long keySz); + WOLFSSL_API int wolfSSL_use_AltPrivateKey_Id(WOLFSSL* ssl, + const unsigned char* id, long sz, int devId); + WOLFSSL_API int wolfSSL_use_AltPrivateKey_Label(WOLFSSL* ssl, + const char* label, int devId); +#endif #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ defined(KEEP_OUR_CERT) @@ -3753,7 +3818,6 @@ WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl); /* SNI types */ enum { WOLFSSL_SNI_HOST_NAME = 0, - WOLFSSL_SNI_HOST_NAME_OUTER = 0, }; WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type, @@ -3858,6 +3922,7 @@ WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list); /* Fragment lengths */ enum { + WOLFSSL_MFL_DISABLED = 0, WOLFSSL_MFL_2_9 = 1, /* 512 bytes */ WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */ WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */ @@ -4435,7 +4500,7 @@ WOLFSSL_API int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str); WOLFSSL_API int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str); -WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ defined(HAVE_SECRET_CALLBACK) @@ -4531,7 +4596,7 @@ WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NA WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne); WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void); 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_certificate(WOLFSSL_CTX* ctx, WOLFSSL_X509* x); WOLFSSL_API int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509); WOLFSSL_API int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509); WOLFSSL_API int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509); @@ -4815,14 +4880,17 @@ typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg); WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb); -WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, - CallbackSniRecv cb); WOLFSSL_API int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg); #endif -#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \ - || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) + +#ifdef HAVE_SNI +WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, + CallbackSniRecv cb); +#endif WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void* pid); @@ -4858,10 +4926,11 @@ WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_X509_OBJECT_get0_X509_CRL(WOLFSSL_X509_OBJ WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void (*f) (WOLFSSL_X509*)); #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ -#if (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && defined(HAVE_ECC) +#if (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && (defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, const char* names); WOLFSSL_API int wolfSSL_set1_curves_list(WOLFSSL* ssl, const char* names); -#endif /* (OPENSSL_EXTRA || HAVE_CURL) && HAVE_ECC */ +#endif #if defined(OPENSSL_ALL) || \ defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ @@ -4985,6 +5054,10 @@ WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); #ifdef OPENSSL_EXTRA WOLFSSL_API int wolfSSL_OPENSSL_init_ssl(word64 opts, const OPENSSL_INIT_SETTINGS *settings); +WOLFSSL_API OPENSSL_INIT_SETTINGS* wolfSSL_OPENSSL_INIT_new(void); +WOLFSSL_API void wolfSSL_OPENSSL_INIT_free(OPENSSL_INIT_SETTINGS* init); +WOLFSSL_API int wolfSSL_OPENSSL_INIT_set_config_appname( + OPENSSL_INIT_SETTINGS* init, char* appname); #endif #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L WOLFSSL_API int wolfSSL_SSL_in_init(const WOLFSSL* ssl); @@ -5051,7 +5124,7 @@ WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, WOLFSSL_API long wolfSSL_CTX_get_tlsext_ticket_keys(WOLFSSL_CTX *ctx, unsigned char *keys, int keylen); WOLFSSL_API long wolfSSL_CTX_set_tlsext_ticket_keys(WOLFSSL_CTX *ctx, - unsigned char *keys, int keylen); + const void *keys_vp, int keylen); #endif WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, @@ -5134,6 +5207,7 @@ WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, WOLFSSL_ASN1_OBJECT *a) WOLFSSL_API int wolfSSL_i2d_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT *a, unsigned char **pp); WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +WOLFSSL_API const char* wolfSSL_COMP_get_name(const void* comp); WOLFSSL_API int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str, const char *file, const char *dir); WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x); WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const WOLF_STACK_OF(WOLFSSL_CIPHER)* p); @@ -5153,6 +5227,7 @@ WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(const WOLFSSL_ASN1_TIME *t); WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(const WOLFSSL_ASN1_TIME *t); WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, WOLFSSL_ASN1_TIME **out); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_UTCTIME_set(WOLFSSL_ASN1_TIME *s, time_t t); WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp); WOLFSSL_API int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, char *buf, int size); @@ -5303,6 +5378,247 @@ WOLFSSL_API int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buffer, #define DTLS1_2_VERSION 0xFEFD #define DTLS1_3_VERSION 0xFEFC +/* These minimums where determined whilst referencing their RFC specs. The + * values represent the minimum sizes of the data types in the required struct + * for the `extension_data` field. A length of 0 was assumed when necassary. + * + * Documents Used for the respective extension: + * - https://datatracker.ietf.org/doc/html/rfc6066 + * - Server Name Indication (SNI) + * - Maximum Fragment Length Negotiation (MFL) + * - Trusted CA Indication (TCA) + * - Certificate Status Request (CSR) + * - Truncate HMAC (THM) + * - https://datatracker.ietf.org/doc/html/rfc8446 + * - Early Data Indication (EDI) + * - Pre-Shared Key (PSK) + * - Pre-Shared Key Exchange Modes (PKM) + * - Key Share (KS) + * - Post-Handshake Authentication (PHA) + * - Signature Algorithms (SA) + * - Signature Algorithms Certificate (SAC) + * - Support Groups (EC) + * - Cookie (CKE) + * - Supported Versions (SV) + * - Certificate Authorities (CAN) + * - https://datatracker.ietf.org/doc/html/rfc6961 + * - Certificate Status Request v2 (CSR2) + * - https://datatracker.ietf.org/doc/rfc9146/ + * - Connection Identifier (CID) + * - https://datatracker.ietf.org/doc/rfc7301/ + * - Application-Layer Protocol Negotiation (ALPN) + * - https://datatracker.ietf.org/doc/html/rfc3711 + * - Secure Real-time Transport Protocol (SRTP) + * - https://datatracker.ietf.org/doc/html/rfc7366 + * - Encrypt Then Mac (ETM) + * - https://datatracker.ietf.org/doc/html/rfc7250 + * - Client Certificate Type (CCT) + * - Server Certificate Type (SCT) + * - https://datatracker.ietf.org/doc/draft-ietf-tls-esni/ + * - Encrypted Client Hello (ECH) + * - https://datatracker.ietf.org/doc/html/rfc5746 + * - Secure Renegotiation (SCR) + * - https://datatracker.ietf.org/doc/rfc4492/ + * - Point Frame (PF) + * - https://datatracker.ietf.org/doc/rfc9000/ + * - QUIC (QTP) + * - https://datatracker.ietf.org/doc/html/rfc5077 + * - Session Ticket (STK) + * Example: + * For `WOLFSSL_CSR_MIN_SIZE_CLIENT = 5`, 5 was determined by looking at the + * struct below defined in its respective RFC. + * The below struct for `CertificateStatusRequest` is made up of the types: + * `CertificateStatusType` is an enum with a max value of 255, thus its + * length is 1 byte. + * `OCSPStatusRequest` is a struct of the following: + * - `responder_id_list`: which is 2 bytes + * - `request_extensions`: which is 2 bytes + * This then gives the minimum size/length of 5 bytes for this extension + * for the client + * struct { + * CertificateStatusType status_type; + * select (status_type) { + * case ocsp: OCSPStatusRequest; + * } request; + * } CertificateStatusRequest; + * enum { ocsp(1), (255) } CertificateStatusType; + * struct { + * ResponderID responder_id_list<0..2^16-1>; + * Extensions request_extensions; + * } OCSPStatusRequest; + * opaque ResponderID<1..2^16-1>; + * opaque Extensions<0..2^16-1>; + */ + +#ifndef WOLFSSL_SNI_MIN_SIZE_CLIENT + #define WOLFSSL_SNI_MIN_SIZE_CLIENT 4 +#endif +#ifndef WOLFSSL_SNI_MIN_SIZE_SERVER + #define WOLFSSL_SNI_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_EDI_MIN_SIZE_CLIENT + #define WOLFSSL_EDI_MIN_SIZE_CLIENT 0 +#endif +#ifndef WOLFSSL_EDI_MIN_SIZE_SERVER + #define WOLFSSL_EDI_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_TCA_MIN_SIZE_CLIENT + #define WOLFSSL_TCA_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_TCA_MIN_SIZE_SERVER + #define WOLFSSL_TCA_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_CSR_MIN_SIZE_CLIENT + #define WOLFSSL_CSR_MIN_SIZE_CLIENT 5 +#endif +#ifndef WOLFSSL_CSR_MIN_SIZE_SERVER + #define WOLFSSL_CSR_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_PKM_MIN_SIZE_CLIENT + #define WOLFSSL_PKM_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_PKM_MIN_SIZE_SERVER + #define WOLFSSL_PKM_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_CSR2_MIN_SIZE_CLIENT + #define WOLFSSL_CSR2_MIN_SIZE_CLIENT 7 +#endif +#ifndef WOLFSSL_CSR2_MIN_SIZE_SERVER + #define WOLFSSL_CSR2_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_CID_MIN_SIZE_CLIENT + #define WOLFSSL_CID_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_CID_MIN_SIZE_SERVER + #define WOLFSSL_CID_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_ALPN_MIN_SIZE_CLIENT + #define WOLFSSL_ALPN_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_ALPN_MIN_SIZE_SERVER + #define WOLFSSL_ALPN_MIN_SIZE_SERVER 2 +#endif +#ifndef WOLFSSL_SRTP_MIN_SIZE_CLIENT + #define WOLFSSL_SRTP_MIN_SIZE_CLIENT 3 +#endif +#ifndef WOLFSSL_SRTP_MIN_SIZE_SERVER + #define WOLFSSL_SRTP_MIN_SIZE_SERVER 3 +#endif +#ifndef WOLFSSL_KS_MIN_SIZE_CLIENT + #define WOLFSSL_KS_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_KS_MIN_SIZE_SERVER + #define WOLFSSL_KS_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_ETM_MIN_SIZE_CLIENT + #define WOLFSSL_ETM_MIN_SIZE_CLIENT 0 +#endif +#ifndef WOLFSSL_ETM_MIN_SIZE_SERVER + #define WOLFSSL_ETM_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_PSK_MIN_SIZE_CLIENT + #define WOLFSSL_PSK_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_PSK_MIN_SIZE_SERVER + #define WOLFSSL_PSK_MIN_SIZE_SERVER 2 +#endif +#ifndef WOLFSSL_CCT_MIN_SIZE_CLIENT + #define WOLFSSL_CCT_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_CCT_MIN_SIZE_SERVER + #define WOLFSSL_CCT_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_SCT_MIN_SIZE_CLIENT + #define WOLFSSL_SCT_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_SCT_MIN_SIZE_SERVER + #define WOLFSSL_SCT_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_PHA_MIN_SIZE_CLIENT + #define WOLFSSL_PHA_MIN_SIZE_CLIENT 0 +#endif +#ifndef WOLFSSL_PHA_MIN_SIZE_SERVER + #define WOLFSSL_PHA_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_THM_MIN_SIZE_CLIENT + #define WOLFSSL_THM_MIN_SIZE_CLIENT 0 +#endif +#ifndef WOLFSSL_THM_MIN_SIZE_SERVER + #define WOLFSSL_THM_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_SA_MIN_SIZE_CLIENT + #define WOLFSSL_SA_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_SA_MIN_SIZE_SERVER + #define WOLFSSL_SA_MIN_SIZE_SERVER 2 +#endif +#ifndef WOLFSSL_SAC_MIN_SIZE_CLIENT + #define WOLFSSL_SAC_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_SAC_MIN_SIZE_SERVER + #define WOLFSSL_SAC_MIN_SIZE_SERVER 2 +#endif +#ifndef WOLFSSL_EC_MIN_SIZE_CLIENT + #define WOLFSSL_EC_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_EC_MIN_SIZE_SERVER + #define WOLFSSL_EC_MIN_SIZE_SERVER 2 +#endif +#ifndef WOLFSSL_ECH_MIN_SIZE_CLIENT + #define WOLFSSL_ECH_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_ECH_MIN_SIZE_SERVER + #define WOLFSSL_ECH_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_MFL_MIN_SIZE_CLIENT + #define WOLFSSL_MFL_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_MFL_MIN_SIZE_SERVER + #define WOLFSSL_MFL_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_CKE_MIN_SIZE_CLIENT + #define WOLFSSL_CKE_MIN_SIZE_CLIENT 3 +#endif +#ifndef WOLFSSL_CKE_MIN_SIZE_SERVER + #define WOLFSSL_CKE_MIN_SIZE_SERVER 3 +#endif +#ifndef WOLFSSL_SV_MIN_SIZE_CLIENT + #define WOLFSSL_SV_MIN_SIZE_CLIENT 2 +#endif +#ifndef WOLFSSL_SV_MIN_SIZE_SERVER + #define WOLFSSL_SV_MIN_SIZE_SERVER 2 +#endif +#ifndef WOLFSSL_SCR_MIN_SIZE_CLIENT + #define WOLFSSL_SCR_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_SCR_MIN_SIZE_SERVER + #define WOLFSSL_SCR_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_PF_MIN_SIZE_CLIENT + #define WOLFSSL_PF_MIN_SIZE_CLIENT 1 +#endif +#ifndef WOLFSSL_PF_MIN_SIZE_SERVER + #define WOLFSSL_PF_MIN_SIZE_SERVER 1 +#endif +#ifndef WOLFSSL_CAN_MIN_SIZE_CLIENT + #define WOLFSSL_CAN_MIN_SIZE_CLIENT 3 +#endif +#ifndef WOLFSSL_CAN_MIN_SIZE_SERVER + #define WOLFSSL_CAN_MIN_SIZE_SERVER 3 +#endif +#ifndef WOLFSSL_QTP_MIN_SIZE_CLIENT + #define WOLFSSL_QTP_MIN_SIZE_CLIENT 0 +#endif +#ifndef WOLFSSL_QTP_MIN_SIZE_SERVER + #define WOLFSSL_QTP_MIN_SIZE_SERVER 0 +#endif +#ifndef WOLFSSL_STK_MIN_SIZE_CLIENT + #define WOLFSSL_STK_MIN_SIZE_CLIENT 0 +#endif +#ifndef WOLFSSL_STK_MIN_SIZE_SERVER + #define WOLFSSL_STK_MIN_SIZE_SERVER 0 +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/wolfssl/test.h b/src/wolfssl/test.h index 47abb74..4dd6320 100644 --- a/src/wolfssl/test.h +++ b/src/wolfssl/test.h @@ -143,9 +143,26 @@ #include #define SOCKET_T int #elif defined(WOLFSSL_ZEPHYR) + #include #include #include - #include + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #ifdef CONFIG_POSIX_API + #include + #include + #include + #include + #endif + #else + #include + #ifdef CONFIG_POSIX_API + #include + #include + #include + #include + #endif + #endif #define SOCKET_T int #define SOL_SOCKET 1 #define WOLFSSL_USE_GETADDRINFO @@ -985,11 +1002,11 @@ static WC_INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userda (void)rw; (void)userdata; if (userdata != NULL) { - strncpy(passwd, (char*)userdata, sz); + strncpy(passwd, (char*)userdata, (size_t) sz); return (int)XSTRLEN((char*)userdata); } else { - strncpy(passwd, "yassl123", sz); + strncpy(passwd, "yassl123", (size_t) sz); return 8; } } @@ -1312,7 +1329,7 @@ static WC_INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, if (entry) { XMEMCPY(&addr->sin_addr.s_addr, entry->h_addr_list[0], - entry->h_length); + (size_t) entry->h_length); useLookup = 1; } #else @@ -1850,7 +1867,7 @@ static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; - key[i] = b; + key[i] = (unsigned char) b; } ret = 32; /* length of key in octets or 0 for error */ @@ -1894,7 +1911,7 @@ static WC_INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identit for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; - key[i] = b; + key[i] = (unsigned char) b; } ret = 32; /* length of key in octets or 0 for error */ @@ -1927,7 +1944,7 @@ static WC_INLINE unsigned int my_psk_client_tls13_cb(WOLFSSL* ssl, for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; - key[i] = b; + key[i] = (unsigned char) b; } *ciphersuite = userCipher ? userCipher : "TLS13-AES128-GCM-SHA256"; @@ -1950,7 +1967,7 @@ static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, unsigned int ret; int i; int b = 0x01; - int kIdLen = (int)XSTRLEN(kIdentityStr); + size_t kIdLen = XSTRLEN(kIdentityStr); const char* userCipher = (const char*)wolfSSL_get_psk_callback_ctx(ssl); (void)ssl; @@ -1966,7 +1983,7 @@ static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; - key[i] = b; + key[i] = (unsigned char) b; } *ciphersuite = userCipher ? userCipher : "TLS13-AES128-GCM-SHA256"; @@ -2029,7 +2046,7 @@ static WC_INLINE int my_psk_use_session_cb(WOLFSSL* ssl, for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; - local_psk[i] = b; + local_psk[i] = (unsigned char) b; } *id = local_psk; @@ -2082,7 +2099,7 @@ static WC_INLINE unsigned int my_psk_client_cs_cb(WOLFSSL* ssl, for (i = 0; i < 32; i++, b += 0x22) { if (b >= 0x100) b = 0x01; - key[i] = b; + key[i] = (unsigned char) b; } return 32; /* length of key in octets or 0 for error */ @@ -2416,7 +2433,7 @@ static WC_INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) */ fprintf(stderr, "In verification callback, error = %d, %s\n", store->error, - wolfSSL_ERR_error_string(store->error, buffer)); + wolfSSL_ERR_error_string((unsigned long) store->error, buffer)); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) peer = store->current_cert; if (peer) { @@ -2707,7 +2724,7 @@ static WC_INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, if (ret != 0) return ret; ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl)); + wolfSSL_GetMacSecret(ssl, macVerify), (word32) wolfSSL_GetHmacSize(ssl)); if (ret != 0) return ret; ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); @@ -2741,7 +2758,7 @@ static WC_INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, fprintf(stderr, "AesInit failed in myMacEncryptCb\n"); return ret; } - ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION); + ret = wc_AesSetKey(&encCtx->aes, key, (word32) keyLen, iv, AES_ENCRYPTION); if (ret != 0) { fprintf(stderr, "AesSetKey failed in myMacEncryptCb\n"); return ret; @@ -2760,7 +2777,7 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, { AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx; int ret = 0; - int macInSz = 0; + unsigned int macInSz = 0; int ivExtra = 0; int digestSz = wolfSSL_GetHmacSize(ssl); unsigned int pad = 0; @@ -2802,7 +2819,7 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, fprintf(stderr, "AesInit failed in myDecryptVerifyCb\n"); return ret; } - ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION); + ret = wc_AesSetKey(&decCtx->aes, key, (word32) keyLen, iv, AES_DECRYPTION); if (ret != 0) { fprintf(stderr, "AesSetKey failed in myDecryptVerifyCb\n"); return ret; @@ -2816,7 +2833,7 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, return ret; if (wolfSSL_GetCipherType(ssl) == WOLFSSL_AEAD_TYPE) { - *padSz = wolfSSL_GetAeadMacSize(ssl); + *padSz = (unsigned int)wolfSSL_GetAeadMacSize(ssl); return 0; /* hmac, not needed if aead mode */ } @@ -2827,8 +2844,8 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, ivExtra = wolfSSL_GetCipherBlockSize(ssl); } - *padSz = wolfSSL_GetHmacSize(ssl) + pad + padByte; - macInSz = decSz - ivExtra - digestSz - pad - padByte; + *padSz = (unsigned int)wolfSSL_GetHmacSize(ssl) + pad + padByte; + macInSz = decSz - (unsigned int)ivExtra - (unsigned int)digestSz - pad - padByte; wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); @@ -2836,7 +2853,7 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, if (ret != 0) return ret; ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, macVerify), digestSz); + wolfSSL_GetMacSecret(ssl, macVerify), (unsigned int) digestSz); if (ret != 0) return ret; ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); @@ -2850,7 +2867,7 @@ static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, return ret; if (XMEMCMP(verify, decOut + decSz - digestSz - pad - padByte, - digestSz) != 0) { + (size_t) digestSz) != 0) { printf("myDecryptVerify verify failed\n"); return -1; } @@ -2901,7 +2918,7 @@ static WC_INLINE int myEncryptMacCb(WOLFSSL* ssl, unsigned char* macOut, fprintf(stderr, "AesInit failed in myMacEncryptCb\n"); return ret; } - ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION); + ret = wc_AesSetKey(&encCtx->aes, key, (word32) keyLen, iv, AES_ENCRYPTION); if (ret != 0) { fprintf(stderr, "AesSetKey failed in myMacEncryptCb\n"); return ret; @@ -2921,7 +2938,7 @@ static WC_INLINE int myEncryptMacCb(WOLFSSL* ssl, unsigned char* macOut, if (ret != 0) return ret; ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl)); + wolfSSL_GetMacSecret(ssl, macVerify), (word32) wolfSSL_GetHmacSize(ssl)); if (ret != 0) return ret; ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); @@ -2965,7 +2982,7 @@ static WC_INLINE int myVerifyDecryptCb(WOLFSSL* ssl, if (ret != 0) return ret; ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, macVerify), digestSz); + wolfSSL_GetMacSecret(ssl, macVerify), (word32) digestSz); if (ret != 0) return ret; ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); @@ -2978,7 +2995,7 @@ static WC_INLINE int myVerifyDecryptCb(WOLFSSL* ssl, if (ret != 0) return ret; - if (XMEMCMP(verify, decOut + decSz, digestSz) != 0) { + if (XMEMCMP(verify, decOut + decSz, (size_t) digestSz) != 0) { printf("myDecryptVerify verify failed\n"); return -1; } @@ -3004,7 +3021,7 @@ static WC_INLINE int myVerifyDecryptCb(WOLFSSL* ssl, fprintf(stderr, "AesInit failed in myDecryptVerifyCb\n"); return ret; } - ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION); + ret = wc_AesSetKey(&decCtx->aes, key, (word32) keyLen, iv, AES_DECRYPTION); if (ret != 0) { fprintf(stderr, "AesSetKey failed in myDecryptVerifyCb\n"); return ret; @@ -3085,7 +3102,7 @@ static WC_INLINE void FreeAtomicUser(WOLFSSL* ssl) #endif /* ATOMIC_USER */ -#ifdef WOLFSSL_STATIC_MEMORY +#if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY_LEAN) static WC_INLINE int wolfSSL_PrintStats(WOLFSSL_MEM_STATS* stats) { word16 i; @@ -3167,7 +3184,7 @@ static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz, WC_RNG *rng = wolfSSL_GetRNG(ssl); /* create new key */ - ret = wc_ecc_make_key_ex(rng, keySz, new_key, ecc_curve); + ret = wc_ecc_make_key_ex(rng, (int) keySz, new_key, ecc_curve); #ifdef TEST_PK_PRIVKEY if (ret == 0 && new_key != key) { @@ -3363,7 +3380,7 @@ static WC_INLINE int myHkdfExtract(byte* prk, const byte* salt, word32 saltLen, byte* ikm, word32 ikmLen, int digest, void* ctx) { int ret; - int len = 0; + word32 len = 0; switch (digest) { #ifndef NO_SHA256 @@ -3494,7 +3511,7 @@ static WC_INLINE int myX25519KeyGen(WOLFSSL* ssl, curve25519_key* key, if (ret != 0) return ret; - ret = wc_curve25519_make_key(&rng, keySz, key); + ret = wc_curve25519_make_key(&rng, (int) keySz, key); wc_FreeRng(&rng); @@ -3665,7 +3682,7 @@ static WC_INLINE int myX448KeyGen(WOLFSSL* ssl, curve448_key* key, if (ret != 0) return ret; - ret = wc_curve448_make_key(&rng, keySz, key); + ret = wc_curve448_make_key(&rng, (int) keySz, key); wc_FreeRng(&rng); @@ -3798,7 +3815,7 @@ static WC_INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret == 0) ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); if (ret > 0) { /* save and convert to 0 success */ - *outSz = ret; + *outSz = (word32) ret; ret = 0; } wc_FreeRsaKey(&myKey); @@ -3932,7 +3949,7 @@ static WC_INLINE int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz, &rng); } if (ret > 0) { /* save and convert to 0 success */ - *outSz = ret; + *outSz = (word32) ret; ret = 0; } wc_FreeRsaKey(&myKey); @@ -4083,7 +4100,7 @@ static WC_INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, if (ret == 0) { ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); if (ret > 0) { - *outSz = ret; + *outSz = (word32) ret; ret = 0; /* reset to success */ } } diff --git a/src/wolfssl/version.h b/src/wolfssl/version.h index d6193c4..2da6e5e 100644 --- a/src/wolfssl/version.h +++ b/src/wolfssl/version.h @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "5.7.0" -#define LIBWOLFSSL_VERSION_HEX 0x05007000 +#define LIBWOLFSSL_VERSION_STRING "5.7.2" +#define LIBWOLFSSL_VERSION_HEX 0x05007002 #ifdef __cplusplus } diff --git a/src/wolfssl/wolfcrypt/aes.h b/src/wolfssl/wolfcrypt/aes.h index 1c369ce..46687da 100644 --- a/src/wolfssl/wolfcrypt/aes.h +++ b/src/wolfssl/wolfcrypt/aes.h @@ -55,6 +55,11 @@ typedef struct Gcm { #endif /* GCM_TABLE */ } Gcm; +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_aes_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_AES_sanity(void); +#endif + WOLFSSL_LOCAL void GenerateM0(Gcm* gcm); #ifdef WOLFSSL_ARMASM WOLFSSL_LOCAL void GMULT(byte* X, byte* Y); @@ -256,7 +261,7 @@ struct Aes { ALIGN16 bs_word bs_key[15 * AES_BLOCK_SIZE * BS_WORD_SIZE]; #endif word32 rounds; -#ifdef WC_AES_C_DYNAMIC_FALLBACK +#ifdef WC_C_DYNAMIC_FALLBACK word32 key_C_fallback[60]; #endif int keylen; @@ -400,15 +405,37 @@ struct Aes { #endif #ifdef WOLFSSL_AES_XTS -typedef struct XtsAes { - Aes aes; -#ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS - Aes aes_decrypt; -#endif - Aes tweak; -} XtsAes; + #if FIPS_VERSION3_GE(6,0,0) + /* SP800-38E - Restrict data unit to 2^20 blocks per key. A block is + * AES_BLOCK_SIZE or 16-bytes (128-bits). So each key may only be used to + * protect up to 1,048,576 blocks of AES_BLOCK_SIZE (16,777,216 bytes) + */ + #define FIPS_AES_XTS_MAX_BYTES_PER_TWEAK 16777216 + #endif + struct XtsAes { + Aes aes; + #ifdef WC_AES_XTS_SUPPORT_SIMULTANEOUS_ENC_AND_DEC_KEYS + Aes aes_decrypt; + #endif + Aes tweak; + }; + + #ifdef WOLFSSL_AESXTS_STREAM + struct XtsAesStreamData { + byte tweak_block[AES_BLOCK_SIZE]; + word32 bytes_crypted_with_this_tweak; + }; + #endif + + #ifndef WC_AESXTS_TYPE_DEFINED + typedef struct XtsAes XtsAes; + typedef struct XtsAesStreamData XtsAesStreamData; + #define WC_AESXTS_TYPE_DEFINED + #endif + #endif + #if (!defined(WC_AESFREE_IS_MANDATORY)) && \ (defined(WC_DEBUG_CIPHER_LIFECYCLE) || \ (defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES)) || \ @@ -430,9 +457,15 @@ typedef struct XtsAes { #endif #ifdef HAVE_AESGCM -typedef struct Gmac { +struct Gmac { Aes aes; -} Gmac; +}; + +#ifndef WC_AESGCM_TYPE_DEFINED + typedef struct Gmac Gmac; + #define WC_AESGCM_TYPE_DEFINED +#endif + #endif /* HAVE_AESGCM */ #endif /* HAVE_FIPS */ @@ -658,6 +691,28 @@ WOLFSSL_API int wc_AesXtsDecryptConsecutiveSectors(XtsAes* aes, byte* out, const byte* in, word32 sz, word64 sector, word32 sectorSz); +#ifdef WOLFSSL_AESXTS_STREAM + +WOLFSSL_API int wc_AesXtsEncryptInit(XtsAes* aes, const byte* i, word32 iSz, + struct XtsAesStreamData *stream); + +WOLFSSL_API int wc_AesXtsDecryptInit(XtsAes* aes, const byte* i, word32 iSz, + struct XtsAesStreamData *stream); + +WOLFSSL_API int wc_AesXtsEncryptUpdate(XtsAes* aes, byte* out, + const byte* in, word32 sz, struct XtsAesStreamData *stream); + +WOLFSSL_API int wc_AesXtsDecryptUpdate(XtsAes* aes, byte* out, + const byte* in, word32 sz, struct XtsAesStreamData *stream); + +WOLFSSL_API int wc_AesXtsEncryptFinal(XtsAes* aes, byte* out, + const byte* in, word32 sz, struct XtsAesStreamData *stream); + +WOLFSSL_API int wc_AesXtsDecryptFinal(XtsAes* aes, byte* out, + const byte* in, word32 sz, struct XtsAesStreamData *stream); + +#endif /* WOLFSSL_AESXTS_STREAM */ + WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); #endif diff --git a/src/wolfssl/wolfcrypt/asn.h b/src/wolfssl/wolfcrypt/asn.h index 01eb03c..503c985 100644 --- a/src/wolfssl/wolfcrypt/asn.h +++ b/src/wolfssl/wolfcrypt/asn.h @@ -780,6 +780,20 @@ extern const WOLFSSL_ObjectInfo wolfssl_object_info[]; #define WOLFSSL_TLS_FEATURE_SUM 92 #endif +/* Maximum number of allowed subject alternative names in a certificate. + * Any certificate containing more than this number of subject + * alternative names will cause an error when attempting to parse. */ +#ifndef WOLFSSL_MAX_ALT_NAMES +#define WOLFSSL_MAX_ALT_NAMES 128 +#endif + +/* Maximum number of allowed name constraints in a certificate. + * Any certificate containing more than this number of name constraints + * will cause an error when attempting to parse. */ +#ifndef WOLFSSL_MAX_NAME_CONSTRAINTS +#define WOLFSSL_MAX_NAME_CONSTRAINTS 128 +#endif + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* NIDs */ #define NID_undef 0 @@ -934,7 +948,7 @@ enum Misc_ASN { ASN_GEN_TIME_SZ = 15, /* 7 numbers * 2 + Zulu tag */ #ifdef HAVE_SPHINCS MAX_ENCODED_SIG_SZ = 51200, -#elif defined(HAVE_PQC) +#elif defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) MAX_ENCODED_SIG_SZ = 5120, #elif !defined(NO_RSA) #ifdef WOLFSSL_HAPROXY @@ -969,6 +983,9 @@ enum Misc_ASN { MAX_DSA_PRIVKEY_SZ = (DSA_INTS * MAX_DSA_INT_SZ) + MAX_SEQ_SZ + MAX_VERSION_SZ, /* Maximum size of a DSA Private key taken from DsaKeyIntsToDer. */ +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) + MAX_PQC_PUBLIC_KEY_SZ = 2592, /* Maximum size of a Dilithium public key. */ +#endif MAX_RSA_E_SZ = 16, /* Max RSA public e size */ MAX_CA_SZ = 32, /* Max encoded CA basic constraint length */ MAX_SN_SZ = 35, /* Max encoded serial number (INT) length */ @@ -1015,7 +1032,11 @@ enum Misc_ASN { 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 */ +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) + MAX_PUBLIC_KEY_SZ = MAX_PQC_PUBLIC_KEY_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2, +#else MAX_PUBLIC_KEY_SZ = MAX_DSA_PUBKEY_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2, +#endif #ifdef WOLFSSL_ENCRYPTED_KEYS HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */ #else @@ -1143,9 +1164,9 @@ enum Key_Sum { DHk = 647, /* dhKeyAgreement OID: 1.2.840.113549.1.3.1 */ FALCON_LEVEL1k = 273, /* 1.3.9999.3.6 */ FALCON_LEVEL5k = 276, /* 1.3.9999.3.9 */ - DILITHIUM_LEVEL2k = 213, /* 1.3.6.1.4.1.2.267.7.4.4 */ - DILITHIUM_LEVEL3k = 216, /* 1.3.6.1.4.1.2.267.7.6.5 */ - DILITHIUM_LEVEL5k = 220, /* 1.3.6.1.4.1.2.267.7.8.7 */ + DILITHIUM_LEVEL2k = 218, /* 1.3.6.1.4.1.2.267.12.4.4 */ + DILITHIUM_LEVEL3k = 221, /* 1.3.6.1.4.1.2.267.12.6.5 */ + DILITHIUM_LEVEL5k = 225, /* 1.3.6.1.4.1.2.267.12.8.7 */ SPHINCS_FAST_LEVEL1k = 281, /* 1 3 9999 6 7 4 */ SPHINCS_FAST_LEVEL3k = 283, /* 1 3 9999 6 8 3 + 2 (See GetOID() in asn.c) */ SPHINCS_FAST_LEVEL5k = 282, /* 1 3 9999 6 9 3 */ @@ -1476,9 +1497,13 @@ struct SignatureCtx { #ifdef HAVE_ED448 struct ed448_key* ed448; #endif - #ifdef HAVE_PQC + #if defined(HAVE_FALCON) struct falcon_key* falcon; + #endif + #if defined(HAVE_DILITHIUM) struct dilithium_key* dilithium; + #endif + #if defined(HAVE_SPHINCS) struct sphincs_key* sphincs; #endif void* ptr; @@ -2017,10 +2042,9 @@ struct Signer { word32 cm_idx; #endif #ifdef WOLFSSL_DUAL_ALG_CERTS - /* The Subject Alternative Public Key Info (SAPKI) will NOT be cached. - * Caching of it is NOT SUPPORTED yet. */ - byte *sapkiDer; - int sapkiLen; + word32 sapkiOID; /* key type */ + byte* sapkiDer; + int sapkiLen; #endif /* WOLFSSL_DUAL_ALG_CERTS */ byte type; @@ -2107,6 +2131,7 @@ WOLFSSL_LOCAL int StreamOctetString(const byte* inBuf, word32 inBufSz, WOLFSSL_ASN_API void FreeAltNames(DNS_entry* altNames, void* heap); WOLFSSL_ASN_API DNS_entry* AltNameNew(void* heap); +WOLFSSL_ASN_API DNS_entry* AltNameDup(DNS_entry* from, void* heap); #ifndef IGNORE_NAME_CONSTRAINTS WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry* names, void* heap); #endif /* IGNORE_NAME_CONSTRAINTS */ @@ -2128,14 +2153,20 @@ WOLFSSL_LOCAL int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz); WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap); -WOLFSSL_API int CheckCertSignature(const byte*,word32,void*,void* cm); WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); -#ifdef OPENSSL_EXTRA -WOLFSSL_API int wc_CheckCertSigPubKey(const byte* cert, word32 certSz, - void* heap, const byte* pubKey, - word32 pubKeySz, int pubKeyOID); -#endif +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SMALL_CERT_VERIFY) + WOLFSSL_API int wc_CheckCertSignature(const byte* cert, word32 certSz, + void* heap, void* cm); + /* Depricated public API name kept for backwards build compatibility */ + #define CheckCertSignature(cert, certSz, heap, cm) \ + wc_CheckCertSignature(cert, certSz, heap, cm) + + WOLFSSL_API int wc_CheckCertSigPubKey(const byte* cert, word32 certSz, + void* heap, const byte* pubKey, + word32 pubKeySz, int pubKeyOID); +#endif /* OPENSSL_EXTRA || WOLFSSL_SMALL_CERT_VERIFY */ + #ifdef WOLFSSL_DUAL_ALG_CERTS WOLFSSL_LOCAL int wc_ConfirmAltSignature( const byte* buf, word32 bufSz, @@ -2156,7 +2187,7 @@ WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, WOLFSSL_ASN_API int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz, int sigAlgoType); WOLFSSL_LOCAL int ParseCertRelative(DecodedCert* cert, int type, int verify, - void* cm); + void* cm, Signer *extraCa); WOLFSSL_LOCAL int DecodeToKey(DecodedCert* cert, int verify); #ifdef WOLFSSL_ASN_TEMPLATE WOLFSSL_LOCAL int DecodeCert(DecodedCert* cert, int verify, int* criticalExt); @@ -2165,6 +2196,8 @@ WOLFSSL_LOCAL int TryDecodeRPKToKey(DecodedCert* cert); WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate); WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz); +WOLFSSL_LOCAL Signer* findSignerByName(Signer *list, byte *hash); +WOLFSSL_LOCAL int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der); WOLFSSL_LOCAL Signer* MakeSigner(void* heap); WOLFSSL_LOCAL void FreeSigner(Signer* signer, void* heap); WOLFSSL_LOCAL void FreeSignerTable(Signer** table, int rows, void* heap); @@ -2308,7 +2341,8 @@ WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx); WOLFSSL_LOCAL int GetNameHash_ex(const byte* source, word32* idx, byte* hash, int maxIdx, word32 sigOID); -WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, + DecodedCert* der, int checkAlt); WOLFSSL_LOCAL int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz, const byte* pubKey, word32 pubKeySz, enum Key_Sum ks); WOLFSSL_LOCAL int StoreDHparams(byte* out, word32* outLen, mp_int* p, mp_int* g); @@ -2347,8 +2381,11 @@ WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); WOLFSSL_LOCAL int SetAsymKeyDerPublic(const byte* pubKey, word32 pubKeyLen, byte* output, word32 outLen, int keyType, int withHeader); -WOLFSSL_LOCAL int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, word32 inSz, - byte* pubKey, word32* pubKeyLen, int keyType); +WOLFSSL_LOCAL int DecodeAsymKeyPublic_Assign(const byte* input, + word32* inOutIdx, word32 inSz, const byte** pubKey, word32* pubKeyLen, + int keyType); +WOLFSSL_LOCAL int DecodeAsymKeyPublic(const byte* input, word32* inOutIdx, + word32 inSz, byte* pubKey, word32* pubKeyLen, int keyType); #ifndef NO_CERTS @@ -2358,7 +2395,10 @@ WOLFSSL_LOCAL int wc_EncryptedInfoParse(EncryptedInfo* info, WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type, DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey); -WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap); +WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, + void* heap); +WOLFSSL_LOCAL int AllocCopyDer(DerBuffer** der, const unsigned char* buff, + word32 length, int type, void* heap); WOLFSSL_LOCAL void FreeDer(DerBuffer** der); #if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) || \ @@ -2527,7 +2567,7 @@ struct OcspResponse { byte* source; /* pointer to source buffer, not owned */ word32 maxIdx; /* max offset based on init size */ - + Signer* pendingCAs; #ifdef OPENSSL_EXTRA int verifyError; #endif @@ -2652,9 +2692,10 @@ WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL* dcrl); || (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) \ || (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) \ || (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) \ - || (defined(HAVE_PQC) && defined(HAVE_FALCON)) \ - || (defined(HAVE_PQC) && defined(HAVE_DILITHIUM)) \ - || (defined(HAVE_PQC) && defined(HAVE_SPHINCS))) + || defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)) +WOLFSSL_LOCAL int DecodeAsymKey_Assign(const byte* input, word32* inOutIdx, + word32 inSz, const byte** privKey, word32* privKeyLen, const byte** pubKey, + word32* pubKeyLen, int keyType); WOLFSSL_LOCAL int DecodeAsymKey(const byte* input, word32* inOutIdx, word32 inSz, byte* privKey, word32* privKeyLen, byte* pubKey, word32* pubKeyLen, int keyType); diff --git a/src/wolfssl/wolfcrypt/asn_public.h b/src/wolfssl/wolfcrypt/asn_public.h index 0f58152..f233004 100644 --- a/src/wolfssl/wolfcrypt/asn_public.h +++ b/src/wolfssl/wolfcrypt/asn_public.h @@ -218,9 +218,9 @@ enum Ctc_SigType { CTC_FALCON_LEVEL1 = 273, CTC_FALCON_LEVEL5 = 276, - CTC_DILITHIUM_LEVEL2 = 213, - CTC_DILITHIUM_LEVEL3 = 216, - CTC_DILITHIUM_LEVEL5 = 220, + CTC_DILITHIUM_LEVEL2 = 218, + CTC_DILITHIUM_LEVEL3 = 221, + CTC_DILITHIUM_LEVEL5 = 225, CTC_SPHINCS_FAST_LEVEL1 = 281, CTC_SPHINCS_FAST_LEVEL3 = 283, @@ -516,7 +516,7 @@ typedef struct Cert { #endif #ifdef WOLFSSL_DUAL_ALG_CERTS /* These will not point to managed buffers. They will point to buffers that - * are managed by others. No cleanup neccessary. */ + * are managed by others. No cleanup necessary. */ /* Subject Alternative Public Key Info */ byte *sapkiDer; int sapkiLen; @@ -799,8 +799,7 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_EXPORT)) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT)) || \ (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_EXPORT)) || \ - (defined(HAVE_PQC) && (defined(HAVE_FALCON) || \ - defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)))) + (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS))) #define WC_ENABLE_ASYM_KEY_EXPORT #endif @@ -809,8 +808,7 @@ WOLFSSL_API int wc_DhPrivKeyToDer(DhKey* key, byte* out, word32* outSz); (defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)) || \ (defined(HAVE_CURVE448) && defined(HAVE_CURVE448_KEY_IMPORT)) || \ - (defined(HAVE_PQC) && (defined(HAVE_FALCON) || \ - defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS)))) + (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || defined(HAVE_SPHINCS))) #define WC_ENABLE_ASYM_KEY_IMPORT #endif diff --git a/src/wolfssl/wolfcrypt/chacha.h b/src/wolfssl/wolfcrypt/chacha.h index 848edf6..6c9577b 100644 --- a/src/wolfssl/wolfcrypt/chacha.h +++ b/src/wolfssl/wolfcrypt/chacha.h @@ -77,7 +77,7 @@ enum { typedef struct ChaCha { word32 X[CHACHA_CHUNK_WORDS]; /* state of cipher */ -#ifdef HAVE_INTEL_AVX1 +#if defined(USE_INTEL_CHACHA_SPEEDUP) /* vpshufd reads 16 bytes but we only use bottom 4. */ byte extra[12]; #endif diff --git a/src/wolfssl/wolfcrypt/cmac.h b/src/wolfssl/wolfcrypt/cmac.h index e59df28..a92e832 100644 --- a/src/wolfssl/wolfcrypt/cmac.h +++ b/src/wolfssl/wolfcrypt/cmac.h @@ -38,8 +38,7 @@ #endif /* avoid redefinition of structs */ -#if !defined(HAVE_FIPS) || \ - (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(2,0,0) #ifndef WC_CMAC_TYPE_DEFINED typedef struct Cmac Cmac; @@ -82,6 +81,11 @@ typedef enum CmacType { #define WC_CMAC_TAG_MAX_SZ AES_BLOCK_SIZE #define WC_CMAC_TAG_MIN_SZ (AES_BLOCK_SIZE/4) +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_cmac_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_CMAC_sanity(void); +#endif + #endif /* HAVE_FIPS */ WOLFSSL_API diff --git a/src/wolfssl/wolfcrypt/cryptocb.h b/src/wolfssl/wolfcrypt/cryptocb.h index 8f66777..29580ea 100644 --- a/src/wolfssl/wolfcrypt/cryptocb.h +++ b/src/wolfssl/wolfcrypt/cryptocb.h @@ -71,7 +71,7 @@ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) #include #endif -#ifdef HAVE_PQC +#ifdef WOLFSSL_HAVE_KYBER #include #ifdef WOLFSSL_WC_KYBER #include @@ -79,10 +79,10 @@ #include #endif #endif -#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) #include #endif -#if defined(HAVE_PQC) && defined(HAVE_FALCON) +#if defined(HAVE_FALCON) #include #endif @@ -216,7 +216,7 @@ typedef struct wc_CryptoInfo { byte contextLen; } ed25519verify; #endif - #if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) + #if defined(WOLFSSL_HAVE_KYBER) struct { WC_RNG* rng; int size; @@ -241,8 +241,7 @@ typedef struct wc_CryptoInfo { int type; /* enum wc_PqcKemType */ } pqc_decaps; #endif - #if defined(HAVE_PQC) && \ - (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) + #if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) struct { WC_RNG* rng; int size; @@ -399,6 +398,9 @@ typedef struct wc_CryptoInfo { #endif #ifdef WOLFSSL_SHA512 wc_Sha512* sha512; + #endif + #ifdef WOLFSSL_SHA3 + wc_Sha3* sha3; #endif void* ctx; #if HAVE_ANONYMOUS_INLINE_AGGREGATES @@ -525,7 +527,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_Ed25519Verify(const byte* sig, word32 sigLen, const byte* context, byte contextLen); #endif /* HAVE_ED25519 */ -#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) +#if defined(WOLFSSL_HAVE_KYBER) WOLFSSL_LOCAL int wc_CryptoCb_PqcKemGetDevId(int type, void* key); WOLFSSL_LOCAL int wc_CryptoCb_MakePqcKemKey(WC_RNG* rng, int type, @@ -538,9 +540,9 @@ WOLFSSL_LOCAL int wc_CryptoCb_PqcEncapsulate(byte* ciphertext, WOLFSSL_LOCAL int wc_CryptoCb_PqcDecapsulate(const byte* ciphertext, word32 ciphertextLen, byte* sharedSecret, word32 sharedSecretLen, int type, void* key); -#endif /* HAVE_PQC && WOLFSSL_HAVE_KYBER */ +#endif /* WOLFSSL_HAVE_KYBER */ -#if defined(HAVE_PQC) && (defined(HAVE_FALCON) || defined(HAVE_DILITHIUM)) +#if defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) WOLFSSL_LOCAL int wc_CryptoCb_PqcSigGetDevId(int type, void* key); WOLFSSL_LOCAL int wc_CryptoCb_MakePqcSignatureKey(WC_RNG* rng, int type, @@ -554,7 +556,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_PqcVerify(const byte* sig, word32 siglen, WOLFSSL_LOCAL int wc_CryptoCb_PqcSignatureCheckPrivKey(void* key, int type, const byte* pubKey, word32 pubKeySz); -#endif /* HAVE_PQC && (HAVE_FALCON || HAVE_DILITHIUM) */ +#endif /* HAVE_FALCON || HAVE_DILITHIUM */ #ifndef NO_AES #ifdef HAVE_AESGCM @@ -623,6 +625,11 @@ WOLFSSL_LOCAL int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in, word32 inSz, byte* digest); #endif +#ifdef WOLFSSL_SHA3 +WOLFSSL_LOCAL int wc_CryptoCb_Sha3Hash(wc_Sha3* sha3, int type, const byte* in, + word32 inSz, byte* digest); +#endif + #ifndef NO_HMAC WOLFSSL_LOCAL int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, byte* digest); diff --git a/src/wolfssl/wolfcrypt/dh.h b/src/wolfssl/wolfcrypt/dh.h index e94cb59..93e8475 100644 --- a/src/wolfssl/wolfcrypt/dh.h +++ b/src/wolfssl/wolfcrypt/dh.h @@ -30,8 +30,7 @@ #ifndef NO_DH -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif /* HAVE_FIPS_VERSION >= 2 */ @@ -120,6 +119,11 @@ enum { #endif #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_dh_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_DH_sanity(void); +#endif + #ifdef HAVE_PUBLIC_FFDHE #ifdef HAVE_FFDHE_2048 WOLFSSL_API const DhParams* wc_Dh_ffdhe2048_Get(void); diff --git a/src/wolfssl/wolfcrypt/dilithium.h b/src/wolfssl/wolfcrypt/dilithium.h index 5472d09..8b336cf 100644 --- a/src/wolfssl/wolfcrypt/dilithium.h +++ b/src/wolfssl/wolfcrypt/dilithium.h @@ -35,34 +35,458 @@ #include #endif -#if defined(HAVE_PQC) && defined(HAVE_DILITHIUM) +#if defined(HAVE_DILITHIUM) #ifdef HAVE_LIBOQS #include #include #endif +#if defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) && \ + defined(WOLFSSL_DILITHIUM_NO_SIGN) && \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) && \ + !defined(WOLFSSL_DILITHIUM_VERIFY_ONLY) + #define WOLFSSL_DILITHIUM_VERIFY_ONLY +#endif +#ifdef WOLFSSL_DILITHIUM_VERIFY_ONLY + #ifndef WOLFSSL_DILITHIUM_NO_MAKE_KEY + #define WOLFSSL_DILITHIUM_NO_MAKE_KEY + #endif + #ifndef WOLFSSL_DILITHIUM_NO_SIGN + #define WOLFSSL_DILITHIUM_NO_SIGN + #endif +#endif + +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + !defined(WOLFSSL_DILITHIUM_NO_VERIFY) + #define WOLFSSL_DILITHIUM_PUBLIC_KEY +#endif +#if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ + !defined(WOLFSSL_DILITHIUM_NO_SIGN) + #define WOLFSSL_DILITHIUM_PRIVATE_KEY +#endif + +#if defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) && \ + defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) && \ + !defined(WOLFSSL_DILITHIUM_NO_CHECK_KEY) && \ + !defined(WOLFSSL_DILITHIUM_CHECK_KEY) + #define WOLFSSL_DILITHIUM_CHECK_KEY +#endif + +#ifdef WOLFSSL_WC_DILITHIUM + #include +#ifndef WOLFSSL_DILITHIUM_VERIFY_ONLY + #include +#endif +#endif + +#if defined(WC_DILITHIUM_CACHE_PRIV_VECTORS) && \ + !defined(WC_DILITHIUM_CACHE_MATRIX_A) + #define WC_DILITHIUM_CACHE_MATRIX_A +#endif +#if defined(WC_DILITHIUM_CACHE_PUB_VECTORS) && \ + !defined(WC_DILITHIUM_CACHE_MATRIX_A) + #define WC_DILITHIUM_CACHE_MATRIX_A +#endif + #ifdef __cplusplus extern "C" { #endif /* Macros Definitions */ -#ifdef HAVE_LIBOQS -#define DILITHIUM_LEVEL2_KEY_SIZE OQS_SIG_dilithium_2_length_secret_key -#define DILITHIUM_LEVEL2_SIG_SIZE OQS_SIG_dilithium_2_length_signature -#define DILITHIUM_LEVEL2_PUB_KEY_SIZE OQS_SIG_dilithium_2_length_public_key -#define DILITHIUM_LEVEL2_PRV_KEY_SIZE (DILITHIUM_LEVEL2_PUB_KEY_SIZE+DILITHIUM_LEVEL2_KEY_SIZE) +#ifdef WOLFSSL_WC_DILITHIUM + +#ifndef WOLFSSL_DILITHIUM_ALIGNMENT + #if defined(__arch64__) + #define WOLFSSL_DILITHIUM_ALIGNMENT 8 + #elif defined(__arm__) + #define WOLFSSL_DILITHIUM_ALIGNMENT 4 + #elif !defined(WOLFSSL_AESNI) && defined(WOLFSSL_GENERAL_ALIGNMENT) + #define WOLFSSL_DILITHIUM_ALIGNMENT WOLFSSL_GENERAL_ALIGNMENT + #else + #define WOLFSSL_DILITHIUM_ALIGNMENT 8 + #endif +#endif /* WOLFSSL_DILITHIUM_ALIGNMENT */ + +#define DILITHIUM_LEVEL2_KEY_SIZE 2560 +#define DILITHIUM_LEVEL2_SIG_SIZE 2420 +#define DILITHIUM_LEVEL2_PUB_KEY_SIZE 1312 +#define DILITHIUM_LEVEL2_PRV_KEY_SIZE \ + (DILITHIUM_LEVEL2_PUB_KEY_SIZE + DILITHIUM_LEVEL2_KEY_SIZE) + +#define DILITHIUM_LEVEL3_KEY_SIZE 4032 +#define DILITHIUM_LEVEL3_SIG_SIZE 3309 +#define DILITHIUM_LEVEL3_PUB_KEY_SIZE 1952 +#define DILITHIUM_LEVEL3_PRV_KEY_SIZE \ + (DILITHIUM_LEVEL3_PUB_KEY_SIZE + DILITHIUM_LEVEL3_KEY_SIZE) + +#define DILITHIUM_LEVEL5_KEY_SIZE 4896 +#define DILITHIUM_LEVEL5_SIG_SIZE 4627 +#define DILITHIUM_LEVEL5_PUB_KEY_SIZE 2592 +#define DILITHIUM_LEVEL5_PRV_KEY_SIZE \ + (DILITHIUM_LEVEL5_PUB_KEY_SIZE + DILITHIUM_LEVEL5_KEY_SIZE) + + +/* Modulus. */ +#define DILITHIUM_Q 0x7fe001 +/* Number of bits in modulus. */ +#define DILITHIUM_Q_BITS 23 +/* Number of elements in polynomial. */ +#define DILITHIUM_N 256 + +/* Number of dropped bits. */ +#define DILITHIUM_D 13 +/* Maximum value of dropped bits. */ +#define DILITHIUM_D_MAX (1 << DILITHIUM_D) +/* Half maximum value. */ +#define DILITHIUM_D_MAX_HALF (1 << (DILITHIUM_D - 1)) +/* Number of undropped bits. */ +#define DILITHIUM_U (DILITHIUM_Q_BITS - DILITHIUM_D) + +/* Bits in coefficient range of y, GAMMA1, of 2^17 is 17. */ +#define DILITHIUM_GAMMA1_BITS_17 17 +/* Coefficient range of y, GAMMA1, of 2^17. */ +#define DILITHIUM_GAMMA1_17 (1 << 17) +/* # encoding bits of y is GAMMA1 + 1. */ +#define DILITHIUM_GAMMA1_17_ENC_BITS 18 +/* Coefficient range of y, GAMMA1, of 2^17. */ +/* Bits in coefficient range of y, GAMMA1, of 2^19 is 19. */ +#define DILITHIUM_GAMMA1_BITS_19 19 +/* Coefficient range of y, GAMMA1, of 2^19. */ +#define DILITHIUM_GAMMA1_19 (1 << 19) +/* # encoding bits of y is GAMMA1 + 1. */ +#define DILITHIUM_GAMMA1_19_ENC_BITS 20 + +/* Low-order rounding range, GAMMA2, is Q divided by 88. */ +#define DILITHIUM_Q_LOW_88 ((DILITHIUM_Q - 1) / 88) +/* Absolute low-order rounding range, GAMMA2, is Q divided by 88. */ +#define DILITHIUM_Q_LOW_88_2 (((DILITHIUM_Q - 1) / 88) * 2) +/* # encoding bits of w1 when range is 88. */ +#define DILITHIUM_Q_HI_88_ENC_BITS 6 +/* Low-order rounding range, GAMMA2, is Q divided by 32. */ +#define DILITHIUM_Q_LOW_32 ((DILITHIUM_Q - 1) / 32) +/* Absolute low-order rounding range, GAMMA2, is Q divided by 32. */ +#define DILITHIUM_Q_LOW_32_2 (((DILITHIUM_Q - 1) / 32) * 2) +/* # encoding bits of w1 when range is 32. */ +#define DILITHIUM_Q_HI_32_ENC_BITS 4 + +/* Private key range, eta, of 2. */ +#define DILITHIUM_ETA_2 2 +/* Bits needed to encode values in range -2..2 as a positive number. */ +#define DILITHIUM_ETA_2_BITS 3 +/* Extract count of valid values. */ +#define DILITHIUM_ETA_2_MOD 15 +/* Private key range, eta, of 4. */ +#define DILITHIUM_ETA_4 4 +/* Bits needed to encode values in range -4..4 as a positive number. */ +#define DILITHIUM_ETA_4_BITS 4 +/* Extract count of valid values. */ +#define DILITHIUM_ETA_4_MOD 9 + +/* Number of bytes in a polynomial in memory. */ +#define DILITHIUM_POLY_SIZE (DILITHIUM_N * sizeof(sword32)) + +#ifndef WOLFSSL_NO_ML_DSA_44 + +/* Fist dimension of A, k, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_K 4 +/* Second dimension of A, l, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_L 4 +/* Private key range, ETA, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_ETA DILITHIUM_ETA_2 +/* Number of bits in private key for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_ETA_BITS DILITHIUM_ETA_2_BITS +/* Collision strength of c-tilde, LAMBDA, in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_LAMBDA 16 +/* # +/-1's in polynomial c, TAU, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_TAU 39 +/* BETA = TAU * ETA for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_BETA \ + (PARAMS_ML_DSA_44_TAU * PARAMS_ML_DSA_44_ETA) +/* Max # 1's in the hint h, OMEGA, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_OMEGA 80 +/* Bits in coefficient range of y, GAMMA1, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_GAMMA1_BITS DILITHIUM_GAMMA1_BITS_17 +/* Ccoefficient range of y, GAMMA1, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_GAMMA1 (1 << PARAMS_ML_DSA_44_GAMMA1_BITS) +/* Low-order rounding range, GAMMA2, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_GAMMA2 DILITHIUM_Q_LOW_88 +/* Bits in high-order rounding range, GAMMA2, for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_GAMMA2_HI_BITS 6 +/* Encoding size of w1 in bytes for ML-DSA-44. + * K * N / 8 * 6 - 6 bits as max value is 43 in high bits. */ +#define PARAMS_ML_DSA_44_W1_ENC_SZ \ + (PARAMS_ML_DSA_44_K * DILITHIUM_N / 8 * PARAMS_ML_DSA_44_GAMMA2_HI_BITS) +/* Size of memory used for matrix a in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_A_SIZE \ + (PARAMS_ML_DSA_44_K * PARAMS_ML_DSA_44_L * DILITHIUM_POLY_SIZE) +/* Size of memory used for vector s1 in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_S1_SIZE \ + (PARAMS_ML_DSA_44_L * DILITHIUM_POLY_SIZE) +/* Encoding size of s1 in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_S1_ENC_SIZE \ + (PARAMS_ML_DSA_44_S1_SIZE / sizeof(sword32) * PARAMS_ML_DSA_44_ETA_BITS / 8) +/* Size of memory used for vector s2 in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_S2_SIZE \ + (PARAMS_ML_DSA_44_K * DILITHIUM_POLY_SIZE) +/* Encoding size of s2 in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_S2_ENC_SIZE \ + (PARAMS_ML_DSA_44_S2_SIZE / sizeof(sword32) * PARAMS_ML_DSA_44_ETA_BITS / 8) +/* Encoding size of z in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_Z_ENC_SIZE \ + (PARAMS_ML_DSA_44_S1_SIZE / sizeof(sword32) / 8 * \ + (PARAMS_ML_DSA_44_GAMMA1_BITS + 1)) +/* Encoding size of public key in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_PK_SIZE \ + (DILITHIUM_PUB_SEED_SZ + PARAMS_ML_DSA_44_K * DILITHIUM_N * DILITHIUM_U / 8) +/* Encoding size of signature in bytes for ML-DSA-44. */ +#define PARAMS_ML_DSA_44_SIG_SIZE \ + ((PARAMS_ML_DSA_44_LAMBDA * 2) + \ + PARAMS_ML_DSA_44_L * DILITHIUM_N/8 * (PARAMS_ML_DSA_44_GAMMA1_BITS + 1) + \ + PARAMS_ML_DSA_44_OMEGA + PARAMS_ML_DSA_44_K) + +#endif /* WOLFSSL_NO_ML_DSA_44 */ + +#ifndef WOLFSSL_NO_ML_DSA_65 + +/* Fist dimension of A, k, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_K 6 +/* Second dimension of A, l, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_L 5 +/* Private key range, ETA, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_ETA DILITHIUM_ETA_4 +/* Number of bits in private key for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_ETA_BITS DILITHIUM_ETA_4_BITS +/* Collision strength of c-tilde, LAMBDA, in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_LAMBDA 24 +/* # +/-1's in polynomial c, TAU, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_TAU 49 +/* BETA = TAU * ETA for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_BETA \ + (PARAMS_ML_DSA_65_TAU * PARAMS_ML_DSA_65_ETA) +/* Max # 1's in the hint h, OMEGA, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_OMEGA 55 +/* Bits in coefficient range of y, GAMMA1, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_GAMMA1_BITS DILITHIUM_GAMMA1_BITS_19 +/* Ccoefficient range of y, GAMMA1, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_GAMMA1 (1 << PARAMS_ML_DSA_65_GAMMA1_BITS) +/* Low-order rounding range, GAMMA2, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_GAMMA2 DILITHIUM_Q_LOW_32 +/* Bits in high-order rounding range, GAMMA2, for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_GAMMA2_HI_BITS 4 +/* Encoding size of w1 in bytes for ML-DSA-65. + * K * N / 8 * 4 - 4 bits as max value is 15 in high bits. */ +#define PARAMS_ML_DSA_65_W1_ENC_SZ \ + (PARAMS_ML_DSA_65_K * DILITHIUM_N / 8 * PARAMS_ML_DSA_65_GAMMA2_HI_BITS) +/* Size of memory used for matrix a in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_A_SIZE \ + (PARAMS_ML_DSA_65_K * PARAMS_ML_DSA_65_L * DILITHIUM_POLY_SIZE) +/* Size of memory used for vector s1 in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_S1_SIZE \ + (PARAMS_ML_DSA_65_L * DILITHIUM_POLY_SIZE) +/* Encoding size of s1 in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_S1_ENC_SIZE \ + (PARAMS_ML_DSA_65_S1_SIZE / sizeof(sword32) * PARAMS_ML_DSA_65_ETA_BITS / 8) +/* Size of memory used for vector s2 in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_S2_SIZE \ + (PARAMS_ML_DSA_65_K * DILITHIUM_POLY_SIZE) +/* Encoding size of s2 in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_S2_ENC_SIZE \ + (PARAMS_ML_DSA_65_S2_SIZE / sizeof(sword32) * PARAMS_ML_DSA_65_ETA_BITS / 8) +/* Encoding size of z in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_Z_ENC_SIZE \ + (PARAMS_ML_DSA_65_S1_SIZE / sizeof(sword32) / 8 * \ + (PARAMS_ML_DSA_65_GAMMA1_BITS + 1)) +/* Encoding size of public key in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_PK_SIZE \ + (DILITHIUM_PUB_SEED_SZ + PARAMS_ML_DSA_65_K * DILITHIUM_N * DILITHIUM_U / 8) +/* Encoding size of signature in bytes for ML-DSA-65. */ +#define PARAMS_ML_DSA_65_SIG_SIZE \ + ((PARAMS_ML_DSA_65_LAMBDA * 2) + \ + PARAMS_ML_DSA_65_L * DILITHIUM_N/8 * (PARAMS_ML_DSA_65_GAMMA1_BITS + 1) + \ + PARAMS_ML_DSA_65_OMEGA + PARAMS_ML_DSA_65_K) + +#endif /* WOLFSSL_NO_ML_DSA_65 */ + +#ifndef WOLFSSL_NO_ML_DSA_87 + +/* Fist dimension of A, k, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_K 8 +/* Second dimension of A, l, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_L 7 +/* Private key range, ETA, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_ETA DILITHIUM_ETA_2 +/* Number of bits in private key for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_ETA_BITS DILITHIUM_ETA_2_BITS +/* Collision strength of c-tilde, LAMBDA, in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_LAMBDA 32 +/* # +/-1's in polynomial c, TAU, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_TAU 60 +/* BETA = TAU * ETA for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_BETA \ + (PARAMS_ML_DSA_87_TAU * PARAMS_ML_DSA_87_ETA) +/* Max # 1's in the hint h, OMEGA, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_OMEGA 75 +/* Bits in coefficient range of y, GAMMA1, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_GAMMA1_BITS DILITHIUM_GAMMA1_BITS_19 +/* Ccoefficient range of y, GAMMA1, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_GAMMA1 (1 << PARAMS_ML_DSA_87_GAMMA1_BITS) +/* Low-order rounding range, GAMMA2, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_GAMMA2 DILITHIUM_Q_LOW_32 +/* Bits in high-order rounding range, GAMMA2, for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_GAMMA2_HI_BITS 4 +/* Encoding size of w1 in bytes for ML-DSA-87. + * K * N / 8 * 4 - 4 bits as max value is 15 in high bits. */ +#define PARAMS_ML_DSA_87_W1_ENC_SZ \ + (PARAMS_ML_DSA_87_K * DILITHIUM_N / 8 * PARAMS_ML_DSA_87_GAMMA2_HI_BITS) +/* Size of memory used for matrix A in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_A_SIZE \ + (PARAMS_ML_DSA_87_K * PARAMS_ML_DSA_87_L * DILITHIUM_POLY_SIZE) +#define PARAMS_ML_DSA_87_S_SIZE 4 +/* Size of memory used for vector s1 in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_S1_SIZE \ + (PARAMS_ML_DSA_87_L * DILITHIUM_POLY_SIZE) +/* Encoding size of s1 in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_S1_ENC_SIZE \ + (PARAMS_ML_DSA_87_S1_SIZE / sizeof(sword32) * PARAMS_ML_DSA_87_ETA_BITS / 8) +/* Size of memory used for vector s2 in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_S2_SIZE \ + (PARAMS_ML_DSA_87_K * DILITHIUM_POLY_SIZE) +/* Encoding size of s2 in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_S2_ENC_SIZE \ + (PARAMS_ML_DSA_87_S2_SIZE / sizeof(sword32) * PARAMS_ML_DSA_87_ETA_BITS / 8) +/* Encoding size of z in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_Z_ENC_SIZE \ + (PARAMS_ML_DSA_87_S1_SIZE / sizeof(sword32) / 8 * \ + (PARAMS_ML_DSA_87_GAMMA1_BITS + 1)) +/* Encoding size of public key in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_PK_SIZE \ + (DILITHIUM_PUB_SEED_SZ + PARAMS_ML_DSA_87_K * DILITHIUM_N * DILITHIUM_U / 8) +/* Encoding size of signature in bytes for ML-DSA-87. */ +#define PARAMS_ML_DSA_87_SIG_SIZE \ + ((PARAMS_ML_DSA_87_LAMBDA * 2) + \ + PARAMS_ML_DSA_87_L * DILITHIUM_N/8 * (PARAMS_ML_DSA_87_GAMMA1_BITS + 1) + \ + PARAMS_ML_DSA_87_OMEGA + PARAMS_ML_DSA_87_K) + +#endif /* WOLFSSL_NO_ML_DSA_87 */ + + +#ifndef WOLFSSL_NO_ML_DSA_87 + +#define DILITHIUM_MAX_W1_ENC_SZ PARAMS_ML_DSA_87_W1_ENC_SZ +/* Maximum collision strength of c-tilde in bytes. */ +#define DILITHIUM_MAX_LAMBDA PARAMS_ML_DSA_87_LAMBDA + +/* Maximum count of elements of a vector with dimension K. */ +#define DILITHIUM_MAX_K_VECTOR_COUNT \ + (PARAMS_ML_DSA_87_K * DILITHIUM_N) +/* Maximum count of elements of a vector with dimension L. */ +#define DILITHIUM_MAX_L_VECTOR_COUNT \ + (PARAMS_ML_DSA_87_L * DILITHIUM_N) + +#elif !defined(WOLFSSL_NO_ML_DSA_65) + +/* Maximum w1 encoding size in bytes. */ +#define DILITHIUM_MAX_W1_ENC_SZ PARAMS_ML_DSA_65_W1_ENC_SZ +/* Maximum collision strength of c-tilde in bytes. */ +#define DILITHIUM_MAX_LAMBDA PARAMS_ML_DSA_65_LAMBDA + +/* Maximum count of elements of a vector with dimension K. */ +#define DILITHIUM_MAX_K_VECTOR_COUNT \ + (PARAMS_ML_DSA_65_K * DILITHIUM_N) +/* Maximum count of elements of a vector with dimension L. */ +#define DILITHIUM_MAX_L_VECTOR_COUNT \ + (PARAMS_ML_DSA_65_L * DILITHIUM_N) + +#else + +/* Maximum w1 encoding size in bytes. */ +#define DILITHIUM_MAX_W1_ENC_SZ PARAMS_ML_DSA_44_W1_ENC_SZ +/* Maximum collision strength of c-tilde in bytes. */ +#define DILITHIUM_MAX_LAMBDA PARAMS_ML_DSA_44_LAMBDA + +/* Maximum count of elements of a vector with dimension K. */ +#define DILITHIUM_MAX_K_VECTOR_COUNT \ + (PARAMS_ML_DSA_44_K * DILITHIUM_N) +/* Maximum count of elements of a vector with dimension L. */ +#define DILITHIUM_MAX_L_VECTOR_COUNT \ + (PARAMS_ML_DSA_44_L * DILITHIUM_N) -#define DILITHIUM_LEVEL3_KEY_SIZE OQS_SIG_dilithium_3_length_secret_key -#define DILITHIUM_LEVEL3_SIG_SIZE OQS_SIG_dilithium_3_length_signature -#define DILITHIUM_LEVEL3_PUB_KEY_SIZE OQS_SIG_dilithium_3_length_public_key -#define DILITHIUM_LEVEL3_PRV_KEY_SIZE (DILITHIUM_LEVEL3_PUB_KEY_SIZE+DILITHIUM_LEVEL3_KEY_SIZE) +#endif + +/* Length of K in bytes. */ +#define DILITHIUM_K_SZ 32 +/* Length of TR in bytes. */ +#define DILITHIUM_TR_SZ 64 +/* Length of public key seed in bytes when expanding a. */ +#define DILITHIUM_PUB_SEED_SZ 32 +/* Length of private key seed in bytes when generating a key. */ +#define DILITHIUM_PRIV_SEED_SZ 64 + +/* Length of seed when creating vector c. */ +#define DILITHIUM_SEED_SZ 32 +/* Length of seeds created when making a key. */ +#define DILITHIUM_SEEDS_SZ 128 + +/* Length of MU in bytes. */ +#define DILITHIUM_MU_SZ 64 +/* Length of random in bytes when generating a signature. */ +#define DILITHIUM_RND_SZ 32 +/* Length of private random in bytes when generating a signature. */ +#define DILITHIUM_PRIV_RAND_SEED_SZ 64 + +/* 5 blocks, each block 21 * 8 bytes = 840 bytes. + * Minimum required is 256 * 3 = 768. */ +#define DILITHIUM_GEN_A_NBLOCKS 5 +/* Number of bytes to generate with Shake128 when generating A. */ +#define DILITHIUM_GEN_A_BYTES \ + (DILITHIUM_GEN_A_NBLOCKS * WC_SHA3_128_COUNT * 8) +/* Number of bytes to a block of SHAKE-128 when generating A. */ +#define DILITHIUM_GEN_A_BLOCK_BYTES (WC_SHA3_128_COUNT * 8) + +/* Number of bytes to a block of SHAKE-256 when generating c. */ +#define DILITHIUM_GEN_C_BLOCK_BYTES (WC_SHA3_256_COUNT * 8) + + +#ifndef WOLFSSL_DILITHIUM_SMALL +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* A block SHAKE-128 output plus one for reading 4 bytes at a time. */ + #define DILITHIUM_REJ_NTT_POLY_H_SIZE (DILITHIUM_GEN_A_BYTES + 1) +#else + /* A block SHAKE-128 output. */ + #define DILITHIUM_REJ_NTT_POLY_H_SIZE DILITHIUM_GEN_A_BYTES +#endif /* LITTLE_ENDIAN_ORDER && WOLFSSL_DILITHIUM_ALIGNMENT == 0 */ +#else +#if defined(LITTLE_ENDIAN_ORDER) && (WOLFSSL_DILITHIUM_ALIGNMENT == 0) + /* A block SHAKE-128 output plus one for reading 4 bytes at a time. */ + #define DILITHIUM_REJ_NTT_POLY_H_SIZE (DILITHIUM_GEN_A_BLOCK_BYTES + 1) +#else + /* A block SHAKE-128 output. */ + #define DILITHIUM_REJ_NTT_POLY_H_SIZE DILITHIUM_GEN_A_BLOCK_BYTES +#endif /* LITTLE_ENDIAN_ORDER && WOLFSSL_DILITHIUM_ALIGNMENT == 0 */ +#endif + +#elif defined(HAVE_LIBOQS) + +#define DILITHIUM_LEVEL2_KEY_SIZE OQS_SIG_ml_dsa_44_ipd_length_secret_key +#define DILITHIUM_LEVEL2_SIG_SIZE OQS_SIG_ml_dsa_44_ipd_length_signature +#define DILITHIUM_LEVEL2_PUB_KEY_SIZE OQS_SIG_ml_dsa_44_ipd_length_public_key +#define DILITHIUM_LEVEL2_PRV_KEY_SIZE \ + (DILITHIUM_LEVEL2_PUB_KEY_SIZE+DILITHIUM_LEVEL2_KEY_SIZE) + +#define DILITHIUM_LEVEL3_KEY_SIZE OQS_SIG_ml_dsa_65_ipd_length_secret_key +#define DILITHIUM_LEVEL3_SIG_SIZE OQS_SIG_ml_dsa_65_ipd_length_signature +#define DILITHIUM_LEVEL3_PUB_KEY_SIZE OQS_SIG_ml_dsa_65_ipd_length_public_key +#define DILITHIUM_LEVEL3_PRV_KEY_SIZE \ + (DILITHIUM_LEVEL3_PUB_KEY_SIZE+DILITHIUM_LEVEL3_KEY_SIZE) + +#define DILITHIUM_LEVEL5_KEY_SIZE OQS_SIG_ml_dsa_87_ipd_length_secret_key +#define DILITHIUM_LEVEL5_SIG_SIZE OQS_SIG_ml_dsa_87_ipd_length_signature +#define DILITHIUM_LEVEL5_PUB_KEY_SIZE OQS_SIG_ml_dsa_87_ipd_length_public_key +#define DILITHIUM_LEVEL5_PRV_KEY_SIZE \ + (DILITHIUM_LEVEL5_PUB_KEY_SIZE+DILITHIUM_LEVEL5_KEY_SIZE) -#define DILITHIUM_LEVEL5_KEY_SIZE OQS_SIG_dilithium_5_length_secret_key -#define DILITHIUM_LEVEL5_SIG_SIZE OQS_SIG_dilithium_5_length_signature -#define DILITHIUM_LEVEL5_PUB_KEY_SIZE OQS_SIG_dilithium_5_length_public_key -#define DILITHIUM_LEVEL5_PRV_KEY_SIZE (DILITHIUM_LEVEL5_PUB_KEY_SIZE+DILITHIUM_LEVEL5_KEY_SIZE) #endif #define DILITHIUM_MAX_KEY_SIZE DILITHIUM_LEVEL5_KEY_SIZE @@ -77,9 +501,34 @@ /* Structs */ +#ifdef WOLFSSL_WC_DILITHIUM +typedef struct wc_dilithium_params { + byte level; + byte k; + byte l; + byte eta; + byte eta_bits; + byte tau; + byte beta; + byte omega; + byte lambda; + byte gamma1_bits; + word32 gamma2; + word32 w1EncSz; + word16 aSz; + word16 s1Sz; + word16 s1EncSz; + word16 s2Sz; + word16 s2EncSz; + word16 zEncSz; + word16 pkSz; + word16 sigSz; +} wc_dilithium_params; +#endif + struct dilithium_key { - bool pubKeySet; - bool prvKeySet; + byte pubKeySet; + byte prvKeySet; byte level; /* 2,3 or 5 */ #ifdef WOLF_CRYPTO_CB @@ -93,8 +542,43 @@ struct dilithium_key { int labelLen; #endif +#ifndef WOLFSSL_DILITHIUM_ASSIGN_KEY byte p[DILITHIUM_MAX_PUB_KEY_SIZE]; - byte k[DILITHIUM_MAX_PRV_KEY_SIZE]; + byte k[DILITHIUM_MAX_KEY_SIZE]; +#else + const byte* p; + const byte* k; +#endif + +#ifdef WOLFSSL_WC_DILITHIUM + const wc_dilithium_params* params; + wc_Shake shake; +#ifdef WC_DILITHIUM_CACHE_MATRIX_A + sword32* a; + byte aSet; +#endif +#ifdef WC_DILITHIUM_CACHE_PRIV_VECTORS + sword32* s1; + sword32* s2; + sword32* t0; + byte privVecsSet; +#endif +#ifdef WC_DILITHIUM_CACHE_PUB_VECTORS + sword32* t1; + byte pubVecSet; +#endif +#if defined(WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC) && \ + defined(WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM) + sword32 z[DILITHIUM_MAX_L_VECTOR_COUNT]; + sword32 c[DILITHIUM_N]; + sword32 w[DILITHIUM_N]; + sword32 t1[DILITHIUM_N]; + byte w1e[DILITHIUM_MAX_W1_ENC_SZ]; + byte h[DILITHIUM_REJ_NTT_POLY_H_SIZE]; + byte block[DILITHIUM_GEN_C_BLOCK_BYTES]; +#endif /* WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC && + * WOLFSSL_DILITHIUM_VERIFY_SMALL_MEM */ +#endif /* WOLFSSL_WC_DILITHIUM */ }; #ifndef WC_DILITHIUMKEY_TYPE_DEFINED @@ -104,12 +588,22 @@ struct dilithium_key { /* Functions */ +#ifndef WOLFSSL_DILITHIUM_VERIFY_ONLY +WOLFSSL_API +int wc_dilithium_make_key(dilithium_key* key, WC_RNG* rng); WOLFSSL_API -int wc_dilithium_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, - dilithium_key* key, WC_RNG* rng); +int wc_dilithium_make_key_from_seed(dilithium_key* key, const byte* seed); + +WOLFSSL_API +int wc_dilithium_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, dilithium_key* key, WC_RNG* rng); +WOLFSSL_API +int wc_dilithium_sign_msg_with_seed(const byte* in, word32 inLen, byte* out, + word32 *outLen, dilithium_key* key, byte* seed); +#endif WOLFSSL_API int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, - word32 msgLen, int* res, dilithium_key* key); + word32 msgLen, int* res, dilithium_key* key); WOLFSSL_API int wc_dilithium_init(dilithium_key* key); @@ -120,10 +614,10 @@ int wc_dilithium_init_ex(dilithium_key* key, void* heap, int devId); #ifdef WOLF_PRIVATE_KEY_ID WOLFSSL_API int wc_dilithium_init_id(dilithium_key* key, const unsigned char* id, int len, - void* heap, int devId); + void* heap, int devId); WOLFSSL_API int wc_dilithium_init_label(dilithium_key* key, const char* label, void* heap, - int devId); + int devId); #endif WOLFSSL_API @@ -133,54 +627,140 @@ int wc_dilithium_get_level(dilithium_key* key, byte* level); WOLFSSL_API void wc_dilithium_free(dilithium_key* key); +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY WOLFSSL_API -int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key); -WOLFSSL_API -int wc_dilithium_import_private_only(const byte* priv, word32 privSz, - dilithium_key* key); -WOLFSSL_API -int wc_dilithium_import_private_key(const byte* priv, word32 privSz, - const byte* pub, word32 pubSz, - dilithium_key* key); - -WOLFSSL_API -int wc_dilithium_export_public(dilithium_key* key, byte* out, word32* outLen); +int wc_dilithium_size(dilithium_key* key); +#endif +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) && \ + defined(WOLFSSL_DILITHIUM_PUBLIC_KEY) WOLFSSL_API -int wc_dilithium_export_private_only(dilithium_key* key, byte* out, word32* outLen); +int wc_dilithium_priv_size(dilithium_key* key); +#endif +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY WOLFSSL_API -int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen); +int wc_dilithium_pub_size(dilithium_key* key); +#endif +#if !defined(WOLFSSL_DILITHIUM_NO_SIGN) || !defined(WOLFSSL_DILITHIUM_NO_VERIFY) WOLFSSL_API -int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, - byte* pub, word32 *pubSz); +int wc_dilithium_sig_size(dilithium_key* key); +#endif +#ifdef WOLFSSL_DILITHIUM_CHECK_KEY WOLFSSL_API int wc_dilithium_check_key(dilithium_key* key); +#endif +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY WOLFSSL_API -int wc_dilithium_size(dilithium_key* key); +int wc_dilithium_import_public(const byte* in, word32 inLen, + dilithium_key* key); +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY WOLFSSL_API -int wc_dilithium_priv_size(dilithium_key* key); +int wc_dilithium_import_private(const byte* priv, word32 privSz, + dilithium_key* key); +#define wc_dilithium_import_private_only wc_dilithium_import_private WOLFSSL_API -int wc_dilithium_pub_size(dilithium_key* key); +int wc_dilithium_import_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, dilithium_key* key); +#endif + +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY WOLFSSL_API -int wc_dilithium_sig_size(dilithium_key* key); +int wc_dilithium_export_public(dilithium_key* key, byte* out, word32* outLen); +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY +WOLFSSL_API +int wc_dilithium_export_private(dilithium_key* key, byte* out, word32* outLen); +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY +WOLFSSL_API +int wc_dilithium_export_key(dilithium_key* key, byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); +#endif +#ifndef WOLFSSL_DILITHIUM_NO_ASN1 +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) WOLFSSL_API int wc_Dilithium_PrivateKeyDecode(const byte* input, - word32* inOutIdx, - dilithium_key* key, word32 inSz); + word32* inOutIdx, dilithium_key* key, word32 inSz); +#endif +#ifdef WOLFSSL_DILITHIUM_PUBLIC_KEY WOLFSSL_API int wc_Dilithium_PublicKeyDecode(const byte* input, - word32* inOutIdx, - dilithium_key* key, word32 inSz); + word32* inOutIdx, dilithium_key* key, word32 inSz); +#endif + +#ifdef WC_ENABLE_ASYM_KEY_EXPORT +WOLFSSL_API int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, + word32 inLen, int withAlg); +#endif +#if defined(WOLFSSL_DILITHIUM_PRIVATE_KEY) WOLFSSL_API int wc_Dilithium_KeyToDer(dilithium_key* key, byte* output, - word32 inLen); + word32 inLen); +#endif +#ifdef WOLFSSL_DILITHIUM_PRIVATE_KEY WOLFSSL_API int wc_Dilithium_PrivateKeyToDer(dilithium_key* key, byte* output, - word32 inLen); -WOLFSSL_API int wc_Dilithium_PublicKeyToDer(dilithium_key* key, byte* output, - word32 inLen, int withAlg); + word32 inLen); +#endif +#endif /* WOLFSSL_DILITHIUM_NO_ASN1 */ + + + +#define WC_ML_DSA_44 2 +#define WC_ML_DSA_65 3 +#define WC_ML_DSA_87 5 + +#define DILITHIUM_ML_DSA_44_KEY_SIZE 2560 +#define DILITHIUM_ML_DSA_44_SIG_SIZE 2420 +#define DILITHIUM_ML_DSA_44_PUB_KEY_SIZE 1312 +#define DILITHIUM_ML_DSA_44_PRV_KEY_SIZE \ + (DILITHIUM_ML_DSA_44_PUB_KEY_SIZE + DILITHIUM_ML_DSA_44_KEY_SIZE) + +#define DILITHIUM_ML_DSA_65_KEY_SIZE 4032 +#define DILITHIUM_ML_DSA_65_SIG_SIZE 3309 +#define DILITHIUM_ML_DSA_65_PUB_KEY_SIZE 1952 +#define DILITHIUM_ML_DSA_65_PRV_KEY_SIZE \ + (DILITHIUM_ML_DSA_65_PUB_KEY_SIZE + DILITHIUM_ML_DSA_65_KEY_SIZE) + +#define DILITHIUM_ML_DSA_87_KEY_SIZE 4896 +#define DILITHIUM_ML_DSA_87_SIG_SIZE 4627 +#define DILITHIUM_ML_DSA_87_PUB_KEY_SIZE 2592 +#define DILITHIUM_ML_DSA_87_PRV_KEY_SIZE \ + (DILITHIUM_ML_DSA_87_PUB_KEY_SIZE + DILITHIUM_ML_DSA_87_KEY_SIZE) + + +#define MlDsaKey dilithium_key + + +#define wc_MlDsaKey_Init(key, heap, devId) \ + wc_dilithium_init_ex(key, heap, devId) +#define wc_MlDsaKey_SetParams(key, id) \ + wc_dilithium_set_level(key, id) +#define wc_MlDsaKey_GetParams(key, id) \ + wc_dilithium_get_level(key, id) +#define wc_MlDsaKey_MakeKey(key, rng) \ + wc_dilithium_make_key(key, rng) +#define wc_MlDsaKey_ExportPrivRaw(key, out, outLen) \ + wc_dilithium_export_private_only(key, out, outLen) +#define wc_MlDsaKey_ImportPrivRaw(key, in, inLen) \ + wc_dilithium_import_private_only(out, outLen, key) +#define wc_MlDsaKey_Sign(key, sig, sigSz, msg, msgSz, rng) \ + wc_dilithium_sign_msg(msg, msgSz, sig, sigSz, key, rng) +#define wc_MlDsaKey_Free(key) \ + wc_dilithium_free(key) +#define wc_MlDsaKey_ExportPubRaw(key, out, outLen) \ + wc_dilithium_export_public(key, out, outLen) +#define wc_MlDsaKey_ImportPubRaw(key, in, inLen) \ + wc_dilithium_import_public(out, outLen, key) +#define wc_MlDsaKey_Verify(key, sig, sigSz, msg, msgSz, res) \ + wc_dilithium_verify_msg(sig, sigSz, msg, msgSz, res, key) + +int wc_MlDsaKey_GetPrivLen(MlDsaKey* key, int* len); +int wc_MlDsaKey_GetPubLen(MlDsaKey* key, int* len); +int wc_MlDsaKey_GetSigLen(MlDsaKey* key, int* len); #ifdef __cplusplus } /* extern "C" */ #endif -#endif /* HAVE_PQC && HAVE_DILITHIUM */ +#endif /* HAVE_DILITHIUM */ #endif /* WOLF_CRYPT_DILITHIUM_H */ diff --git a/src/wolfssl/wolfcrypt/ecc.h b/src/wolfssl/wolfcrypt/ecc.h index 2d7ee32..4a198a6 100644 --- a/src/wolfssl/wolfcrypt/ecc.h +++ b/src/wolfssl/wolfcrypt/ecc.h @@ -31,8 +31,7 @@ #ifdef HAVE_ECC -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif /* HAVE_FIPS_VERSION >= 2 */ @@ -83,6 +82,10 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_ecc_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_ECC_sanity(void); +#endif /* Enable curve B parameter if needed */ #if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE) @@ -131,6 +134,14 @@ #endif #endif +#if FIPS_VERSION3_GE(6,0,0) + #define WC_ECC_FIPS_SIG_MIN 224 + #define WC_ECC_FIPS_GEN_MIN (WC_ECC_FIPS_SIG_MIN/8) +#endif + +#ifdef WOLFSSL_SM2 + #define WOLFSSL_SM2_KEY_BITS 256 +#endif /* calculate max ECC bytes */ #if ((MAX_ECC_BITS * 2) % 8) == 0 @@ -209,13 +220,13 @@ typedef enum ecc_curve_id { ECC_CURVE_DEF = 0, /* NIST or SECP */ /* NIST Prime Curves */ - ECC_SECP192R1, + ECC_SECP192R1, /* 1 */ ECC_PRIME192V2, ECC_PRIME192V3, ECC_PRIME239V1, ECC_PRIME239V2, ECC_PRIME239V3, - ECC_SECP256R1, + ECC_SECP256R1, /* 7 */ /* SECP Curves */ ECC_SECP112R1, @@ -224,9 +235,9 @@ typedef enum ecc_curve_id { ECC_SECP128R2, ECC_SECP160R1, ECC_SECP160R2, - ECC_SECP224R1, - ECC_SECP384R1, - ECC_SECP521R1, + ECC_SECP224R1, /* 14 */ + ECC_SECP384R1, /* 15 */ + ECC_SECP521R1, /* 16 */ /* Koblitz */ ECC_SECP160K1, @@ -286,7 +297,7 @@ typedef byte ecc_oid_t; /* ECC set type defined a GF(p) curve */ #ifndef WOLFSSL_ECC_CURVE_STATIC -typedef struct ecc_set_type { +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 */ @@ -300,13 +311,13 @@ typedef struct ecc_set_type { word32 oidSz; word32 oidSum; /* sum of encoded OID bytes */ int cofactor; -} ecc_set_type; +}; #else #define MAX_ECC_NAME 16 #define MAX_ECC_STRING ((MAX_ECC_BYTES * 2) + 2) /* The values are stored as text strings. */ -typedef struct ecc_set_type { +struct ecc_set_type { int size; /* The size of the curve in octets */ int id; /* id of this curve */ char name[MAX_ECC_NAME]; /* name of this curve */ @@ -320,7 +331,7 @@ typedef struct ecc_set_type { word32 oidSz; word32 oidSum; /* sum of encoded OID bytes */ int cofactor; -} ecc_set_type; +}; #endif @@ -430,10 +441,19 @@ typedef struct alt_fp_int { #define WC_ECCKEY_TYPE_DEFINED #endif +#ifndef WC_ECCPOINT_TYPE_DEFINED + typedef struct ecc_point ecc_point; + #define WC_ECCPOINT_TYPE_DEFINED +#endif + +#ifndef WC_ECCSET_TYPE_DEFINED + typedef struct ecc_set_type ecc_set_type; + #define WC_ECCSET_TYPE_DEFINED +#endif /* A point on an ECC curve, stored in Jacobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ -typedef struct { +struct ecc_point { #ifndef ALT_ECC_SIZE mp_int x[1]; /* The x coordinate */ mp_int y[1]; /* The y coordinate */ @@ -447,7 +467,7 @@ typedef struct { #if defined(WOLFSSL_SMALL_STACK_CACHE) && !defined(WOLFSSL_ECC_NO_SMALL_STACK) ecc_key* key; #endif -} ecc_point; +}; /* ECC Flags */ enum { @@ -490,6 +510,17 @@ struct ecc_key { mp_int* k; alt_fp_int ka[1]; #endif +#ifdef WOLFSSL_ECC_BLIND_K +#ifndef ALT_ECC_SIZE + mp_int kb[1]; + mp_int ku[1]; +#else + mp_int* kb; + mp_int* ku; + alt_fp_int kba[1]; + alt_fp_int kua[1]; +#endif +#endif #ifdef WOLFSSL_CAAM word32 blackKey; /* address of key encrypted and in secure memory */ @@ -508,9 +539,6 @@ struct ecc_key { void* devCtx; int devId; #endif -#if defined(HAVE_PKCS11) - byte isPkcs11 : 1; /* indicate if PKCS11 is preferred */ -#endif #ifdef WOLFSSL_SILABS_SE_ACCEL sl_se_command_context_t cmd_ctx; sl_se_key_descriptor_t key; @@ -590,7 +618,20 @@ struct ecc_key { #endif }; -#define wc_ecc_key_get_priv(key) ((key)->k) +#ifndef WOLFSSL_ECC_BLIND_K +#define ecc_get_k(key) (key)->k +#define ecc_blind_k(key, b) (void)b +#define ecc_blind_k_rng(key, rng) 0 + +#define wc_ecc_key_get_priv(key) (key)->k +#else +mp_int* ecc_get_k(ecc_key* key); +void ecc_blind_k(ecc_key* key, mp_int* b); +int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng); + +WOLFSSL_API mp_int* wc_ecc_key_get_priv(ecc_key* key); +#endif + #define WOLFSSL_HAVE_ECC_KEY_GET_PRIV @@ -946,6 +987,8 @@ const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx); WOLFSSL_API int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt); WOLFSSL_API +int wc_ecc_ctx_set_own_salt(ecEncCtx* ctx, const byte* salt, word32 sz); +WOLFSSL_API int wc_ecc_ctx_set_kdf_salt(ecEncCtx* ctx, const byte* salt, word32 sz); WOLFSSL_API int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz); diff --git a/src/wolfssl/wolfcrypt/ed25519.h b/src/wolfssl/wolfcrypt/ed25519.h index 9748d6d..efba650 100644 --- a/src/wolfssl/wolfcrypt/ed25519.h +++ b/src/wolfssl/wolfcrypt/ed25519.h @@ -45,6 +45,10 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_ed25519_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_ED25519_sanity(void); +#endif /* info about EdDSA curve specifically ed25519, defined as an elliptic curve over GF(p) */ @@ -70,11 +74,6 @@ enum { Ed25519ph = 1 }; -#ifndef WC_ED25519KEY_TYPE_DEFINED - typedef struct ed25519_key ed25519_key; - #define WC_ED25519KEY_TYPE_DEFINED -#endif - /* ED25519 Flags */ enum { WC_ED25519_FLAG_NONE = 0x00, @@ -111,6 +110,11 @@ struct ed25519_key { #endif }; +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif + WOLFSSL_API int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey, diff --git a/src/wolfssl/wolfcrypt/ed448.h b/src/wolfssl/wolfcrypt/ed448.h index 48011fc..5884bda 100644 --- a/src/wolfssl/wolfcrypt/ed448.h +++ b/src/wolfssl/wolfcrypt/ed448.h @@ -47,6 +47,10 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_ed448_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_ED448_sanity(void); +#endif /* info about EdDSA curve specifically ed448, defined as an elliptic curve * over GF(p) @@ -72,11 +76,6 @@ enum { Ed448ph = 1 }; -#ifndef WC_ED448KEY_TYPE_DEFINED - typedef struct ed448_key ed448_key; - #define WC_ED448KEY_TYPE_DEFINED -#endif - /* An ED448 Key */ struct ed448_key { byte p[ED448_PUB_KEY_SIZE]; /* compressed public key */ @@ -102,6 +101,10 @@ struct ed448_key { #endif }; +#ifndef WC_ED448KEY_TYPE_DEFINED + typedef struct ed448_key ed448_key; + #define WC_ED448KEY_TYPE_DEFINED +#endif WOLFSSL_API int wc_ed448_make_public(ed448_key* key, unsigned char* pubKey, diff --git a/src/wolfssl/wolfcrypt/error-crypt.h b/src/wolfssl/wolfcrypt/error-crypt.h index 99afb96..dbe0553 100644 --- a/src/wolfssl/wolfcrypt/error-crypt.h +++ b/src/wolfssl/wolfcrypt/error-crypt.h @@ -73,8 +73,8 @@ enum { VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */ FIPS_DEGRADED_E = -127, /* FIPS Module in degraded mode */ - /* -128 unused. */ - /* -129 unused. */ + FIPS_CODE_SZ_E = -128, /* Module CODE too big */ + FIPS_DATA_SZ_E = -129, /* Module DATA too big */ RSA_WRONG_TYPE_E = -130, /* RSA wrong block type for RSA function */ RSA_BUFFER_E = -131, /* RSA buffer error, output too small or @@ -107,12 +107,14 @@ enum { ASN_SIG_HASH_E = -156, /* ASN sig error, unsupported hash type */ ASN_SIG_KEY_E = -157, /* ASN sig error, unsupported key type */ ASN_DH_KEY_E = -158, /* ASN key init error, invalid input */ - /* -159 unused. */ + KDF_SRTP_KAT_FIPS_E = -159, /* SRTP-KDF Known Answer Test Failure */ ASN_CRIT_EXT_E = -160, /* ASN unsupported critical extension */ ASN_ALT_NAME_E = -161, /* ASN alternate name error */ ASN_NO_PEM_HEADER = -162, /* ASN no PEM header found */ - - /* -163..-169 unused. */ + ED25519_KAT_FIPS_E = -163, /* Ed25519 Known answer test failure */ + ED448_KAT_FIPS_E = -164, /* Ed448 Known answer test failure */ + PBKDF2_KAT_FIPS_E = -165, /* PBKDF2 Known answer test failure */ + /* -166..-169 unused. */ ECC_BAD_ARG_E = -170, /* ECC input argument of wrong type */ ASN_ECC_KEY_E = -171, /* ASN ECC bad input */ @@ -188,10 +190,11 @@ enum { WC_INIT_E = -228, /* wolfcrypt failed to initialize */ SIG_VERIFY_E = -229, /* wolfcrypt signature verify error */ BAD_COND_E = -230, /* Bad condition variable operation */ - SIG_TYPE_E = -231, /* Signature Type not enabled/available */ + SIG_TYPE_E = -231, /* Signature Type not enabled/available + * NOTE: 1024-bit sign disabled in FIPS mode */ HASH_TYPE_E = -232, /* Hash Type not enabled/available */ - /* -233 unused. */ + FIPS_INVALID_VER_E = -233, /* Invalid FIPS Version defined */ WC_KEY_SIZE_E = -234, /* Key size error, either too small or large */ ASN_COUNTRY_SIZE_E = -235, /* ASN Cert Gen, invalid country code size */ @@ -291,6 +294,22 @@ WOLFSSL_API void wc_ErrorString(int err, char* buff); WOLFSSL_ABI WOLFSSL_API const char* wc_GetErrorString(int error); #endif +#if defined(WOLFSSL_DEBUG_TRACE_ERROR_CODES) && !defined(BUILDING_WOLFSSL) + #undef WOLFSSL_DEBUG_TRACE_ERROR_CODES +#endif +#ifdef WOLFSSL_DEBUG_TRACE_ERROR_CODES + #define WC_NO_ERR_TRACE(label) (CONST_NUM_ERR_ ## label) + #ifndef WC_ERR_TRACE + #define WC_ERR_TRACE(label) \ + ( fprintf(stderr, \ + "ERR TRACE: %s L %d " #label " (%d)\n", \ + __FILE__, __LINE__, label), label) + #endif + #include +#else + #define WC_NO_ERR_TRACE(label) (label) +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/wolfssl/wolfcrypt/ext_lms.h b/src/wolfssl/wolfcrypt/ext_lms.h index ccdfdcb..fae812f 100644 --- a/src/wolfssl/wolfcrypt/ext_lms.h +++ b/src/wolfssl/wolfcrypt/ext_lms.h @@ -53,8 +53,8 @@ struct LmsKey { unsigned char pub[HSS_MAX_PUBLIC_KEY_LEN]; #ifndef WOLFSSL_LMS_VERIFY_ONLY hss_working_key * working_key; - write_private_key_cb write_private_key; /* Callback to write/update key. */ - read_private_key_cb read_private_key; /* Callback to read key. */ + wc_lms_write_private_key_cb write_private_key; /* Callback to write/update key. */ + wc_lms_read_private_key_cb read_private_key; /* Callback to read key. */ void * context; /* Context arg passed to callbacks. */ hss_extra_info info; #endif /* ifndef WOLFSSL_LMS_VERIFY_ONLY */ diff --git a/src/wolfssl/wolfcrypt/ext_xmss.h b/src/wolfssl/wolfcrypt/ext_xmss.h index 9abf158..5f51bf5 100644 --- a/src/wolfssl/wolfcrypt/ext_xmss.h +++ b/src/wolfssl/wolfcrypt/ext_xmss.h @@ -45,8 +45,8 @@ struct XmssKey { /* The secret key length is a function of xmss_params. */ unsigned char * sk; word32 sk_len; - write_private_key_cb write_private_key; /* Callback to write/update key. */ - read_private_key_cb read_private_key; /* Callback to read key. */ + wc_xmss_write_private_key_cb write_private_key; /* Callback to write/update key. */ + wc_xmss_read_private_key_cb read_private_key; /* Callback to read key. */ void * context; /* Context arg passed to callbacks. */ #endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */ enum wc_XmssState state; diff --git a/src/wolfssl/wolfcrypt/fe_operations.h b/src/wolfssl/wolfcrypt/fe_operations.h index cdd27db..8a1cab7 100644 --- a/src/wolfssl/wolfcrypt/fe_operations.h +++ b/src/wolfssl/wolfcrypt/fe_operations.h @@ -116,8 +116,8 @@ WOLFSSL_LOCAL void fe_cmov(fe f, const fe g, int b); WOLFSSL_LOCAL void fe_pow22523(fe out,const fe z); /* 64 type needed for SHA512 */ -WOLFSSL_LOCAL word64 load_3(const unsigned char *in); -WOLFSSL_LOCAL word64 load_4(const unsigned char *in); +WOLFSSL_LOCAL sword64 load_3(const unsigned char *in); +WOLFSSL_LOCAL sword64 load_4(const unsigned char *in); #ifdef CURVED25519_ASM WOLFSSL_LOCAL void fe_cmov_table(fe* r, fe* base, signed char b); diff --git a/src/wolfssl/wolfcrypt/fips_test.h b/src/wolfssl/wolfcrypt/fips_test.h index dc37477..452e651 100644 --- a/src/wolfssl/wolfcrypt/fips_test.h +++ b/src/wolfssl/wolfcrypt/fips_test.h @@ -51,39 +51,44 @@ enum FipsCastId { - FIPS_CAST_AES_CBC, - FIPS_CAST_AES_GCM, - FIPS_CAST_HMAC_SHA1, - FIPS_CAST_HMAC_SHA2_256, - FIPS_CAST_HMAC_SHA2_512, - FIPS_CAST_HMAC_SHA3_256, - FIPS_CAST_DRBG, - FIPS_CAST_RSA_SIGN_PKCS1v15, - FIPS_CAST_ECC_CDH, - FIPS_CAST_ECC_PRIMITIVE_Z, - FIPS_CAST_DH_PRIMITIVE_Z, - FIPS_CAST_ECDSA, - FIPS_CAST_KDF_TLS12, - FIPS_CAST_KDF_TLS13, - FIPS_CAST_KDF_SSH, - FIPS_CAST_COUNT + /* v5.2.0 & v5.2.1 + */ + FIPS_CAST_AES_CBC = 0, + FIPS_CAST_AES_GCM = 1, + FIPS_CAST_HMAC_SHA1 = 2, + FIPS_CAST_HMAC_SHA2_256 = 3, + FIPS_CAST_HMAC_SHA2_512 = 4, + FIPS_CAST_HMAC_SHA3_256 = 5, + FIPS_CAST_DRBG = 6, + FIPS_CAST_RSA_SIGN_PKCS1v15 = 7, + FIPS_CAST_ECC_CDH = 8, + FIPS_CAST_ECC_PRIMITIVE_Z = 9, + FIPS_CAST_DH_PRIMITIVE_Z = 10, + FIPS_CAST_ECDSA = 11, + FIPS_CAST_KDF_TLS12 = 12, + FIPS_CAST_KDF_TLS13 = 13, + FIPS_CAST_KDF_SSH = 14, + /* v6.0.0 + */ + FIPS_CAST_KDF_SRTP = 15, + FIPS_CAST_ED25519 = 16, + FIPS_CAST_ED448 = 17, + FIPS_CAST_PBKDF2 = 18, + FIPS_CAST_COUNT = 19 }; enum FipsCastStateId { - FIPS_CAST_STATE_INIT, - FIPS_CAST_STATE_PROCESSING, - FIPS_CAST_STATE_SUCCESS, - FIPS_CAST_STATE_FAILURE + FIPS_CAST_STATE_INIT = 0, + FIPS_CAST_STATE_PROCESSING = 1, + FIPS_CAST_STATE_SUCCESS = 2, + FIPS_CAST_STATE_FAILURE = 3 }; enum FipsModeId { - FIPS_MODE_INIT = 0, - FIPS_MODE_NORMAL = 1, - FIPS_MODE_DEGRADED = 2, - FIPS_MODE_FAILED = 3 + FIPS_MODE_INIT = 0, + FIPS_MODE_NORMAL = 1, + FIPS_MODE_DEGRADED = 2, + FIPS_MODE_FAILED = 3 }; - /* FIPS failure callback */ typedef void(*wolfCrypt_fips_cb)(int ok, int err, const char* hash); @@ -94,6 +99,7 @@ WOLFSSL_API int wolfCrypt_SetCb_fips(wolfCrypt_fips_cb cbf); WOLFSSL_API int wolfCrypt_GetStatus_fips(void); WOLFSSL_API int wolfCrypt_GetMode_fips(void); WOLFSSL_API const char* wolfCrypt_GetCoreHash_fips(void); +WOLFSSL_API const char* wolfCrypt_GetRawComputedHash_fips(void); #ifdef HAVE_FORCE_FIPS_FAILURE /* Public function to force failure mode for operational testing */ diff --git a/src/wolfssl/wolfcrypt/hmac.h b/src/wolfssl/wolfcrypt/hmac.h index 929d8b2..0d0844e 100644 --- a/src/wolfssl/wolfcrypt/hmac.h +++ b/src/wolfssl/wolfcrypt/hmac.h @@ -30,8 +30,7 @@ #ifndef NO_HMAC -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif @@ -39,9 +38,17 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_hmac_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_HMAC_sanity(void); +#endif + +#if FIPS_VERSION3_GE(6,0,0) + #define FIPS_ALLOW_SHORT 1 +#endif + /* avoid redefinition of structs */ -#if !defined(HAVE_FIPS) || \ - (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +#if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(2,0,0) #ifdef WOLFSSL_ASYNC_CRYPT #include @@ -184,7 +191,10 @@ struct Hmac { #endif /* HAVE_FIPS */ /* does init */ -WOLFSSL_API int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz); +WOLFSSL_API int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, + word32 keySz); +WOLFSSL_API int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, + word32 length, int allowFlag); WOLFSSL_API int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz); WOLFSSL_API int wc_HmacFinal(Hmac* hmac, byte* out); #ifdef WOLFSSL_KCAPI_HMAC diff --git a/src/wolfssl/wolfcrypt/kdf.h b/src/wolfssl/wolfcrypt/kdf.h index 7fa3c7e..ad107e5 100644 --- a/src/wolfssl/wolfcrypt/kdf.h +++ b/src/wolfssl/wolfcrypt/kdf.h @@ -39,6 +39,11 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_kdf_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_KDF_sanity(void); +#endif + enum max_prf { #ifdef HAVE_FFDHE_8192 MAX_PRF_HALF = 516, /* Maximum half secret len */ @@ -132,6 +137,12 @@ WOLFSSL_API int wc_SSH_KDF(byte hashId, byte keyId, /* Length of index for SRTCP KDF. */ #define WC_SRTCP_INDEX_LEN 4 +/* Indicators */ +enum { + WC_SRTCP_32BIT_IDX = 0, + WC_SRTCP_48BIT_IDX = 1, +}; + /* Maximum length of salt that can be used with SRTP/SRTCP. */ #define WC_SRTP_MAX_SALT 14 @@ -141,6 +152,9 @@ WOLFSSL_API int wc_SRTP_KDF(const byte* key, word32 keySz, const byte* salt, WOLFSSL_API int wc_SRTCP_KDF(const byte* key, word32 keySz, const byte* salt, word32 saltSz, int kdrIdx, const byte* index, byte* key1, word32 key1Sz, byte* key2, word32 key2Sz, byte* key3, word32 key3Sz); +WOLFSSL_API int wc_SRTCP_KDF_ex(const byte* key, word32 keySz, const byte* salt, + word32 saltSz, int kdrIdx, const byte* index, byte* key1, word32 key1Sz, + byte* key2, word32 key2Sz, byte* key3, word32 key3Sz, int idxLenIndicator); WOLFSSL_API int wc_SRTP_KDF_label(const byte* key, word32 keySz, const byte* salt, word32 saltSz, int kdrIdx, const byte* index, byte label, byte* outKey, word32 outKeySz); @@ -152,6 +166,11 @@ WOLFSSL_API int wc_SRTP_KDF_kdr_to_idx(word32 kdr); #endif /* WC_SRTP_KDF */ +#ifdef WC_KDF_NIST_SP_800_56C +WOLFSSL_API int wc_KDA_KDF_onestep(const byte* z, word32 zSz, + const byte* fixedInfo, word32 fixedInfoSz, word32 derivedSecretSz, + enum wc_HashType hashType, byte* output, word32 outputSz); +#endif #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/wolfssl/wolfcrypt/kyber.h b/src/wolfssl/wolfcrypt/kyber.h index 5132e12..8e9a7b3 100644 --- a/src/wolfssl/wolfcrypt/kyber.h +++ b/src/wolfssl/wolfcrypt/kyber.h @@ -201,10 +201,10 @@ WOLFSSL_API int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, WOLFSSL_API int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, const unsigned char* ct, word32 len); -WOLFSSL_API int wc_KyberKey_DecodePrivateKey(KyberKey* key, unsigned char* in, - word32 len); -WOLFSSL_API int wc_KyberKey_DecodePublicKey(KyberKey* key, unsigned char* in, - word32 len); +WOLFSSL_API int wc_KyberKey_DecodePrivateKey(KyberKey* key, + const unsigned char* in, word32 len); +WOLFSSL_API int wc_KyberKey_DecodePublicKey(KyberKey* key, + const unsigned char* in, word32 len); WOLFSSL_API int wc_KyberKey_PrivateKeySize(KyberKey* key, word32* len); WOLFSSL_API int wc_KyberKey_PublicKeySize(KyberKey* key, word32* len); diff --git a/src/wolfssl/wolfcrypt/lms.h b/src/wolfssl/wolfcrypt/lms.h index 483f349..fe87388 100644 --- a/src/wolfssl/wolfcrypt/lms.h +++ b/src/wolfssl/wolfcrypt/lms.h @@ -34,8 +34,8 @@ typedef struct LmsKey LmsKey; /* Private key write and read callbacks. */ -typedef int (*write_private_key_cb)(const byte * priv, word32 privSz, void *context); -typedef int (*read_private_key_cb)(byte * priv, word32 privSz, void *context); +typedef int (*wc_lms_write_private_key_cb)(const byte * priv, word32 privSz, void *context); +typedef int (*wc_lms_read_private_key_cb)(byte * priv, word32 privSz, void *context); /* Return codes returned by private key callbacks. */ enum wc_LmsRc { @@ -75,20 +75,45 @@ enum wc_LmsRc { /* Predefined LMS/HSS parameter sets for convenience. * - * Not predefining a set with Winternitz=1, because the signatures + * Not predefining many sets with Winternitz=1, because the signatures * will be large. */ enum wc_LmsParm { - WC_LMS_PARM_NONE = 0, - WC_LMS_PARM_L1_H15_W2 = 1, /* 1 level Merkle tree of 15 height. */ - WC_LMS_PARM_L1_H15_W4 = 2, - WC_LMS_PARM_L2_H10_W2 = 3, /* 2 level Merkle tree of 10 height. */ - WC_LMS_PARM_L2_H10_W4 = 4, - WC_LMS_PARM_L2_H10_W8 = 5, - WC_LMS_PARM_L3_H5_W2 = 6, /* 3 level Merkle tree of 5 height. */ - WC_LMS_PARM_L3_H5_W4 = 7, - WC_LMS_PARM_L3_H5_W8 = 8, - WC_LMS_PARM_L3_H10_W4 = 9, /* 3 level Merkle tree of 10 height. */ - WC_LMS_PARM_L4_H5_W8 = 10, /* 4 level Merkle tree of 5 height. */ + WC_LMS_PARM_NONE = 0, + WC_LMS_PARM_L1_H5_W1 = 1, + WC_LMS_PARM_L1_H5_W2 = 2, + WC_LMS_PARM_L1_H5_W4 = 3, + WC_LMS_PARM_L1_H5_W8 = 4, + WC_LMS_PARM_L1_H10_W2 = 5, + WC_LMS_PARM_L1_H10_W4 = 6, + WC_LMS_PARM_L1_H10_W8 = 7, + WC_LMS_PARM_L1_H15_W2 = 8, + WC_LMS_PARM_L1_H15_W4 = 9, + WC_LMS_PARM_L1_H15_W8 = 10, + WC_LMS_PARM_L1_H20_W2 = 11, + WC_LMS_PARM_L1_H20_W4 = 12, + WC_LMS_PARM_L1_H20_W8 = 13, + WC_LMS_PARM_L2_H5_W2 = 14, + WC_LMS_PARM_L2_H5_W4 = 15, + WC_LMS_PARM_L2_H5_W8 = 16, + WC_LMS_PARM_L2_H10_W2 = 17, + WC_LMS_PARM_L2_H10_W4 = 18, + WC_LMS_PARM_L2_H10_W8 = 19, + WC_LMS_PARM_L2_H15_W2 = 20, + WC_LMS_PARM_L2_H15_W4 = 21, + WC_LMS_PARM_L2_H15_W8 = 22, + WC_LMS_PARM_L2_H20_W2 = 23, + WC_LMS_PARM_L2_H20_W4 = 24, + WC_LMS_PARM_L2_H20_W8 = 25, + WC_LMS_PARM_L3_H5_W2 = 26, + WC_LMS_PARM_L3_H5_W4 = 27, + WC_LMS_PARM_L3_H5_W8 = 28, + WC_LMS_PARM_L3_H10_W4 = 29, + WC_LMS_PARM_L3_H10_W8 = 30, + WC_LMS_PARM_L4_H5_W2 = 31, + WC_LMS_PARM_L4_H5_W4 = 32, + WC_LMS_PARM_L4_H5_W8 = 33, + WC_LMS_PARM_L4_H10_W4 = 34, + WC_LMS_PARM_L4_H10_W8 = 35, }; /* enum wc_LmsState is to help track the state of an LMS/HSS Key. */ @@ -113,9 +138,9 @@ WOLFSSL_API int wc_LmsKey_GetParameters(const LmsKey * key, int * levels, int * height, int * winternitz); #ifndef WOLFSSL_LMS_VERIFY_ONLY WOLFSSL_API int wc_LmsKey_SetWriteCb(LmsKey * key, - write_private_key_cb write_cb); + wc_lms_write_private_key_cb write_cb); WOLFSSL_API int wc_LmsKey_SetReadCb(LmsKey * key, - read_private_key_cb read_cb); + wc_lms_read_private_key_cb read_cb); WOLFSSL_API int wc_LmsKey_SetContext(LmsKey * key, void * context); WOLFSSL_API int wc_LmsKey_MakeKey(LmsKey * key, WC_RNG * rng); WOLFSSL_API int wc_LmsKey_Reload(LmsKey * key); diff --git a/src/wolfssl/wolfcrypt/logging.h b/src/wolfssl/wolfcrypt/logging.h index 4eee1fa..d17f834 100644 --- a/src/wolfssl/wolfcrypt/logging.h +++ b/src/wolfssl/wolfcrypt/logging.h @@ -181,6 +181,25 @@ WOLFSSL_API void wolfSSL_SetLoggingPrefix(const char* prefix); #define WOLFSSL_MSG_EX(...) WC_DO_NOTHING #endif WOLFSSL_API void WOLFSSL_MSG(const char* msg); +#ifdef WOLFSSL_DEBUG_CODEPOINTS + WOLFSSL_API void WOLFSSL_MSG2( + const char *file, int line, const char* msg); + WOLFSSL_API void WOLFSSL_ENTER2( + const char *file, int line, const char* msg); + WOLFSSL_API void WOLFSSL_LEAVE2( + const char *file, int line, const char* msg, int ret); + #define WOLFSSL_MSG(msg) WOLFSSL_MSG2(__FILE__, __LINE__, msg) + #define WOLFSSL_ENTER(msg) WOLFSSL_ENTER2(__FILE__, __LINE__, msg) + #define WOLFSSL_LEAVE(msg, ret) WOLFSSL_LEAVE2(__FILE__, __LINE__, msg, ret) + #ifdef XVSNPRINTF + WOLFSSL_API void WOLFSSL_MSG_EX2( + const char *file, int line, const char* fmt, ...); + #define WOLFSSL_MSG_EX(fmt, args...) \ + WOLFSSL_MSG_EX2(__FILE__, __LINE__, fmt, ## args) + #else + #define WOLFSSL_MSG_EX2(...) WC_DO_NOTHING + #endif +#endif WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length); #else diff --git a/src/wolfssl/wolfcrypt/mem_track.h b/src/wolfssl/wolfcrypt/mem_track.h index 5857564..c6d8163 100644 --- a/src/wolfssl/wolfcrypt/mem_track.h +++ b/src/wolfssl/wolfcrypt/mem_track.h @@ -177,30 +177,34 @@ static WC_INLINE void* TrackMalloc(size_t sz) (void)line; #endif #endif +#if defined(DO_MEM_LIST) || defined(DO_MEM_STATS) + if (pthread_mutex_lock(&memLock) == 0) + { +#endif #ifdef DO_MEM_STATS - ourMemStats.totalAllocs++; - ourMemStats.totalBytes += sz; - ourMemStats.currentBytes += sz; -#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE - if (ourMemStats.peakAllocsTripOdometer < ourMemStats.totalAllocs - - ourMemStats.totalDeallocs) { - ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - - ourMemStats.totalDeallocs; - } - if (ourMemStats.peakBytesTripOdometer < ourMemStats.currentBytes) -#endif - { + ourMemStats.totalAllocs++; + ourMemStats.totalBytes += sz; + ourMemStats.currentBytes += sz; #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE - ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; + if (ourMemStats.peakAllocsTripOdometer < ourMemStats.totalAllocs - + ourMemStats.totalDeallocs) { + ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - + ourMemStats.totalDeallocs; + } + if (ourMemStats.peakBytesTripOdometer < ourMemStats.currentBytes) #endif - if (ourMemStats.currentBytes > ourMemStats.peakBytes) - ourMemStats.peakBytes = ourMemStats.currentBytes; - } + { + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; + #endif + if (ourMemStats.currentBytes > ourMemStats.peakBytes) + ourMemStats.peakBytes = ourMemStats.currentBytes; + } + #endif /* DO_MEM_STATS */ #ifdef DO_MEM_LIST - if (pthread_mutex_lock(&memLock) == 0) { #ifdef WOLFSSL_DEBUG_MEMORY header->func = func; header->line = line; @@ -218,7 +222,8 @@ static WC_INLINE void* TrackMalloc(size_t sz) } ourMemList.tail = header; /* add to the end either way */ ourMemList.count++; - +#endif +#if defined(DO_MEM_LIST) || defined(DO_MEM_STATS) pthread_mutex_unlock(&memLock); } #endif /* DO_MEM_LIST */ @@ -245,7 +250,7 @@ static WC_INLINE void TrackFree(void* ptr) header = &mt->u.hint; sz = header->thisSize; -#ifdef DO_MEM_LIST +#if defined(DO_MEM_LIST) || defined(DO_MEM_STATS) if (pthread_mutex_lock(&memLock) == 0) { #endif @@ -277,7 +282,9 @@ static WC_INLINE void TrackFree(void* ptr) prev->next = next; } ourMemList.count--; +#endif +#if defined(DO_MEM_LIST) || defined(DO_MEM_STATS) pthread_mutex_unlock(&memLock); } #endif diff --git a/src/wolfssl/wolfcrypt/memory.h b/src/wolfssl/wolfcrypt/memory.h index 9a1d7b0..31b6a28 100644 --- a/src/wolfssl/wolfcrypt/memory.h +++ b/src/wolfssl/wolfcrypt/memory.h @@ -101,48 +101,72 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, #ifndef WOLFSSL_STATIC_ALIGN #define WOLFSSL_STATIC_ALIGN 16 #endif +/* WOLFMEM_BUCKETS - list of the sizes of buckets in the pool + * WOLFMEM_DIST - list of quantities of buffers in the buckets + * WOLFMEM_DEF_BUCKETS - number of values in WOLFMEM_BUCKETS and WOLFMEM_DIST + * WOLFMEM_MAX_BUCKETS - size of the arrays used to store the buckets and + * dists in the memory pool; defaults to WOLFMEM_DEF_BUCKETS + * + * The following defines provide a reasonable set of buckets in the memory + * pool for running wolfSSL on a Linux box. The bucket and dist lists below + * have nine items each, so WOLFMEM_DEF_BUCKETS is set to 9. + * + * If WOLFMEM_DEF_BUCKETS is less then WOLFMEM_MAX_BUCKETS, the unused values + * are set to zero and ignored. If WOLFMEM_MAX_BUCKETS is less than + * WOLFMEM_DEF_BUCKETS, not all the buckets will be created in the pool. + */ + #ifndef WOLFMEM_DEF_BUCKETS + #define WOLFMEM_DEF_BUCKETS 9 /* number of default memory blocks */ + #endif + #ifndef WOLFMEM_MAX_BUCKETS - #define WOLFMEM_MAX_BUCKETS 9 + #define WOLFMEM_MAX_BUCKETS WOLFMEM_DEF_BUCKETS #endif - #define WOLFMEM_DEF_BUCKETS 9 /* number of default memory blocks */ + + #if WOLFMEM_MAX_BUCKETS < WOLFMEM_DEF_BUCKETS + #warning "ignoring excess buckets, MAX_BUCKETS less than DEF_BUCKETS" + #endif + #ifndef WOLFMEM_IO_SZ #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ #endif + + #ifndef LARGEST_MEM_BUCKET + #ifndef SESSION_CERTS + #define LARGEST_MEM_BUCKET 16128 + #elif defined(OPENSSL_EXTRA) + #ifdef WOLFSSL_TLS13 + #define LARGEST_MEM_BUCKET 30400 + #else + #define LARGEST_MEM_BUCKET 25600 + #endif + #elif defined(WOLFSSL_CERT_EXT) + /* certificate extensions requires 24k for the SSL struct */ + #define LARGEST_MEM_BUCKET 24576 + #else + /* increase 23k for object member of WOLFSSL_X509_NAME_ENTRY */ + #define LARGEST_MEM_BUCKET 23440 + #endif + #endif + #ifndef WOLFMEM_BUCKETS #ifndef SESSION_CERTS /* default size of chunks of memory to separate into */ - #ifndef LARGEST_MEM_BUCKET - #define LARGEST_MEM_BUCKET 16128 - #endif #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\ LARGEST_MEM_BUCKET - #elif defined (OPENSSL_EXTRA) + #elif defined(OPENSSL_EXTRA) /* extra storage in structs for multiple attributes and order */ - #ifndef LARGEST_MEM_BUCKET - #ifdef WOLFSSL_TLS13 - #define LARGEST_MEM_BUCKET 30400 - #else - #define LARGEST_MEM_BUCKET 25600 - #endif - #endif #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3360,4480,\ LARGEST_MEM_BUCKET - #elif defined (WOLFSSL_CERT_EXT) - /* certificate extensions requires 24k for the SSL struct */ - #ifndef LARGEST_MEM_BUCKET - #define LARGEST_MEM_BUCKET 24576 - #endif + #elif defined(WOLFSSL_CERT_EXT) #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\ LARGEST_MEM_BUCKET #else - /* increase 23k for object member of WOLFSSL_X509_NAME_ENTRY */ - #ifndef LARGEST_MEM_BUCKET - #define LARGEST_MEM_BUCKET 23440 - #endif #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\ LARGEST_MEM_BUCKET #endif #endif + #ifndef WOLFMEM_DIST #ifndef WOLFSSL_STATIC_MEMORY_SMALL #define WOLFMEM_DIST 49,10,6,14,5,6,9,1,1 @@ -190,7 +214,14 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, typedef struct wc_Memory wc_Memory; /* internal structure for mem bucket */ typedef struct WOLFSSL_HEAP { wc_Memory* ava[WOLFMEM_MAX_BUCKETS]; + #ifndef WOLFSSL_STATIC_MEMORY_LEAN wc_Memory* io; /* list of buffers to use for IO */ + #endif + + #ifdef WOLFSSL_STATIC_MEMORY_LEAN + word16 sizeList[WOLFMEM_MAX_BUCKETS];/* memory sizes in ava list */ + byte distList[WOLFMEM_MAX_BUCKETS];/* general distribution */ + #else word32 maxHa; /* max concurrent handshakes */ word32 curHa; word32 maxIO; /* max concurrent IO connections */ @@ -199,10 +230,16 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, word32 distList[WOLFMEM_MAX_BUCKETS];/* general distribution */ word32 inUse; /* amount of memory currently in use */ word32 ioUse; + #endif + + #ifndef WOLFSSL_STATIC_MEMORY_LEAN word32 alloc; /* total number of allocs */ word32 frAlc; /* total number of frees */ int flag; + #endif + #ifndef SINGLE_THREADED wolfSSL_Mutex memory_mutex; + #endif } WOLFSSL_HEAP; /* structure passed into XMALLOC as heap hint @@ -211,22 +248,41 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, typedef struct WOLFSSL_HEAP_HINT { WOLFSSL_HEAP* memory; WOLFSSL_MEM_CONN_STATS* stats; /* hold individual connection stats */ + #ifndef WOLFSSL_STATIC_MEMORY_LEAN wc_Memory* outBuf; /* set if using fixed io buffers */ wc_Memory* inBuf; byte haFlag; /* flag used for checking handshake count */ + #endif } WOLFSSL_HEAP_HINT; + WOLFSSL_API void* wolfSSL_SetGlobalHeapHint(void* heap); + WOLFSSL_API void* wolfSSL_GetGlobalHeapHint(void); + WOLFSSL_API int wc_LoadStaticMemory_ex(WOLFSSL_HEAP_HINT** pHint, + unsigned int listSz, const unsigned int *sizeList, + const unsigned int *distList, unsigned char* buf, unsigned int sz, + int flag, int max); +#ifdef WOLFSSL_STATIC_MEMORY_DEBUG_CALLBACK + #define WOLFSSL_DEBUG_MEMORY_ALLOC 0 + #define WOLFSSL_DEBUG_MEMORY_FAIL 1 + #define WOLFSSL_DEBUG_MEMORY_FREE 2 + #define WOLFSSL_DEBUG_MEMORY_INIT 3 + + + typedef void (*DebugMemoryCb)(size_t sz, int bucketSz, byte st, int type); + WOLFSSL_API void wolfSSL_SetDebugMemoryCb(DebugMemoryCb cb); +#endif WOLFSSL_API int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, unsigned char* buf, unsigned int sz, int flag, int max); + WOLFSSL_API void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap); - WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap); - WOLFSSL_LOCAL int wolfSSL_load_static_memory(byte* buffer, word32 sz, - int flag, WOLFSSL_HEAP* heap); - WOLFSSL_LOCAL int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, + WOLFSSL_API int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats); WOLFSSL_LOCAL int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); WOLFSSL_LOCAL int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); + WOLFSSL_API int wolfSSL_StaticBufferSz_ex(unsigned int listSz, + const unsigned int *sizeList, const unsigned int *distList, + byte* buffer, word32 sz, int flag); WOLFSSL_API int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag); WOLFSSL_API int wolfSSL_MemoryPaddingSz(void); #endif /* WOLFSSL_STATIC_MEMORY */ @@ -272,6 +328,9 @@ WOLFSSL_LOCAL int wc_debug_CipherLifecycleFree(void **CipherLifecycleTag, #ifndef WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED #define WC_DEBUG_VECTOR_REGISTERS_FUZZING_SEED 0 #endif + #ifndef CAN_SAVE_VECTOR_REGISTERS + #define CAN_SAVE_VECTOR_REGISTERS() (SAVE_VECTOR_REGISTERS2_fuzzer() == 0) + #endif #endif #ifdef DEBUG_VECTOR_REGISTER_ACCESS diff --git a/src/wolfssl/wolfcrypt/misc.h b/src/wolfssl/wolfcrypt/misc.h index 2685c6c..9761d68 100644 --- a/src/wolfssl/wolfcrypt/misc.h +++ b/src/wolfssl/wolfcrypt/misc.h @@ -135,6 +135,8 @@ WOLFSSL_LOCAL byte ctSetLTE(int a, int b); WOLFSSL_LOCAL void ctMaskCopy(byte mask, byte* dst, byte* src, word16 size); WOLFSSL_LOCAL word32 MakeWordFromHash(const byte* hashID); WOLFSSL_LOCAL word32 HashObject(const byte* o, word32 len, int* error); +WOLFSSL_LOCAL char* CopyString(const char* src, int srcLen, void* heap, + int type); WOLFSSL_LOCAL void w64Increment(w64wrapper *n); WOLFSSL_LOCAL void w64Decrement(w64wrapper *n); diff --git a/src/wolfssl/wolfcrypt/pkcs12.h b/src/wolfssl/wolfcrypt/pkcs12.h index f302354..dc06c9d 100644 --- a/src/wolfssl/wolfcrypt/pkcs12.h +++ b/src/wolfssl/wolfcrypt/pkcs12.h @@ -29,9 +29,7 @@ extern "C" { #endif -#ifndef WOLFSSL_TYPES_DEFINED /* do not redeclare from ssl.h */ - typedef struct WC_PKCS12 WC_PKCS12; -#endif +typedef struct WC_PKCS12 WC_PKCS12; typedef struct WC_DerCertList { /* dereferenced in ssl.c */ byte* buffer; @@ -47,6 +45,7 @@ enum { }; WOLFSSL_API WC_PKCS12* wc_PKCS12_new(void); +WOLFSSL_API WC_PKCS12* wc_PKCS12_new_ex(void* heap); WOLFSSL_API void wc_PKCS12_free(WC_PKCS12* pkcs12); WOLFSSL_API int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12); #ifndef NO_FILESYSTEM @@ -67,7 +66,7 @@ WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, WOLFSSL_LOCAL int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap); WOLFSSL_LOCAL void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12); -WOLFSSL_LOCAL void wc_FreeCertList(WC_DerCertList* list, void* heap); +WOLFSSL_API void wc_FreeCertList(WC_DerCertList* list, void* heap); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wolfssl/wolfcrypt/poly1305.h b/src/wolfssl/wolfcrypt/poly1305.h index c0a5b8d..cc31254 100644 --- a/src/wolfssl/wolfcrypt/poly1305.h +++ b/src/wolfssl/wolfcrypt/poly1305.h @@ -48,7 +48,14 @@ #define WC_HAS_GCC_4_4_64BIT #endif -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef WOLFSSL_X86_64_BUILD +#if defined(USE_INTEL_SPEEDUP) && !defined(NO_POLY1305_ASM) + #define USE_INTEL_POLY1305_SPEEDUP + #define HAVE_INTEL_AVX1 +#endif +#endif + +#if defined(USE_INTEL_POLY1305_SPEEDUP) #elif (defined(WC_HAS_SIZEOF_INT128_64BIT) || defined(WC_HAS_MSVC_64BIT) || \ defined(WC_HAS_GCC_4_4_64BIT)) #define POLY130564 @@ -67,7 +74,7 @@ enum { /* Poly1305 state */ typedef struct Poly1305 { -#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) +#ifdef USE_INTEL_POLY1305_SPEEDUP word64 r[3]; word64 h[3]; word64 pad[2]; diff --git a/src/wolfssl/wolfcrypt/port/Espressif/esp-sdk-lib.h b/src/wolfssl/wolfcrypt/port/Espressif/esp-sdk-lib.h new file mode 100644 index 0000000..55ff661 --- /dev/null +++ b/src/wolfssl/wolfcrypt/port/Espressif/esp-sdk-lib.h @@ -0,0 +1,229 @@ +/* esp-sdk-lib.h + * + * Copyright (C) 2006-2024 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 __ESP_SDK_LIB_H__ + +#define __ESP_SDK_LIB_H__ + +/* Always include wolfcrypt/settings.h before any other wolfSSL file. */ +/* Reminder: settings.h pulls in user_settings.h; don't include it here. */ +#include + +#if defined(WOLFSSL_ESPIDF) /* Entire file is only for Espressif EDP-IDF */ + +/* WOLFSSL_USER_SETTINGS must be defined, typically in the CMakeLists.txt: */ +/* set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS") */ +#ifndef WOLFSSL_USER_SETTINGS + #error "WOLFSSL_USER_SETTINGS must be defined for Espressif targts" +#endif + +/* FreeRTOS */ +#include +#include +#include + +/* Espressif */ +#include "sdkconfig.h" /* ensure ESP-IDF settings are available everywhere */ +#include +#include + +#define ESP_SDK_MEM_LIB_VERSION 1 + +/** + ****************************************************************************** + ****************************************************************************** + ** USER APPLICATION SETTINGS BEGIN + ****************************************************************************** + ****************************************************************************** + **/ + +/* when using a private config with plain text passwords, + * file my_private_config.h should be excluded from git updates */ +/* #define USE_MY_PRIVATE_CONFIG */ + +/* Note that IntelliSense may not work properly in the next section for the + * Espressif SDK 3.4 on the ESP8266. Macros should still be defined. + * See the project-level Makefile. Example found in: + * https://github.com/wolfSSL/wolfssl/tree/master/IDE/Espressif/ESP-IDF/examples/template + * + * The USE_MY_PRIVATE_[OS]_CONFIG is typically an environment variable that + * triggers the make (not cmake) to add compiler defines. + */ +#if defined(USE_MY_PRIVATE_WINDOWS_CONFIG) + #include "/workspace/my_private_config.h" +#elif defined(USE_MY_PRIVATE_WSL_CONFIG) + #include "/mnt/c/workspace/my_private_config.h" +#elif defined(USE_MY_PRIVATE_LINUX_CONFIG) + #include "~/workspace/my_private_config.h" +#elif defined(USE_MY_PRIVATE_MAC_CONFIG) + #include "~/Documents/my_private_config.h" +#elif defined(USE_MY_PRIVATE_CONFIG) + /* This section works best with cmake & non-environment variable setting */ + #if defined(WOLFSSL_CMAKE_SYSTEM_NAME_WINDOWS) + #define WOLFSSL_CMAKE + #include "/workspace/my_private_config.h" + #elif defined(WOLFSSL_MAKE_SYSTEM_NAME_WINDOWS) + #define WOLFSSL_MAKE + #include "/workspace/my_private_config.h" + #elif defined(WOLFSSL_CMAKE_SYSTEM_NAME_WSL) + #define WOLFSSL_CMAKE + #include "/mnt/c/workspace/my_private_config.h" + #elif defined(WOLFSSL_MAKE_SYSTEM_NAME_WSL) + #define WOLFSSL_MAKE + #include "/mnt/c/workspace/my_private_config.h" + #elif defined(WOLFSSL_CMAKE_SYSTEM_NAME_LINUX) + #define WOLFSSL_CMAKE + #include "~/workspace/my_private_config.h" + #elif defined(WOLFSSL_MAKE_SYSTEM_NAME_LINUX) + #define WOLFSSL_MAKE + #include "~/workspace/my_private_config.h" + #elif defined(WOLFSSL_CMAKE_SYSTEM_NAME_APPLE) + #include "~/Documents/my_private_config.h" + #elif defined(WOLFSSL_MAKE_SYSTEM_NAME_APPLE) + #define WOLFSSL_MAKE + #include "~/Documents/my_private_config.h" + #elif defined(OS_WINDOWS) + #include "/workspace/my_private_config.h" + #else + /* Edit as needed for your private config: */ + #warning "default private config using /workspace/my_private_config.h" + #include "/workspace/my_private_config.h" + #endif +#else + + /* + ** The examples use WiFi configuration that you can set via project + ** configuration menu + ** + ** If you'd rather not, just change the below entries to strings with + ** the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" + */ + #if defined(CONFIG_ESP_WIFI_SSID) + /* tyically from ESP32 with ESP-IDF v4 ot v5 */ + #define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID + #elif defined(CONFIG_EXAMPLE_WIFI_SSID) + /* typically from ESP8266 rtos-sdk/v3.4 */ + #undef EXAMPLE_ESP_WIFI_SSID + #define EXAMPLE_ESP_WIFI_SSID CONFIG_EXAMPLE_WIFI_SSID + #else + #define EXAMPLE_ESP_WIFI_SSID "MYSSID_WIFI_CONNECT" + #endif + + #if defined(CONFIG_ESP_WIFI_PASSWORD) + /* tyically from ESP32 with ESP-IDF v4 or v5 */ + #define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD + #elif defined(CONFIG_EXAMPLE_WIFI_SSID) + /* typically from ESP8266 rtos-sdk/v3.4 */ + #undef EXAMPLE_ESP_WIFI_PASS + #define EXAMPLE_ESP_WIFI_PASS CONFIG_EXAMPLE_WIFI_PASSWORD + #else + #define EXAMPLE_ESP_WIFI_PASS "MYPASSWORD_WIFI_CONNECT" + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +WOLFSSL_LOCAL esp_err_t esp_sdk_time_mem_init(void); + +WOLFSSL_LOCAL esp_err_t sdk_var_whereis(const char* v_name, void* v); + +WOLFSSL_LOCAL intptr_t esp_sdk_stack_pointer(void); + +/****************************************************************************** +* Time helpers +******************************************************************************/ +WOLFSSL_LOCAL esp_err_t esp_sdk_time_lib_init(void); + +/* a function to show the current data and time */ +WOLFSSL_LOCAL esp_err_t esp_show_current_datetime(void); + +/* worst case, if GitHub time not available, used fixed time */ +WOLFSSL_LOCAL esp_err_t set_fixed_default_time(void); + +/* set time from string (e.g. GitHub commit time) */ +WOLFSSL_LOCAL esp_err_t set_time_from_string(const char* time_buffer); + +/* set time from NTP servers, + * also initially calls set_fixed_default_time or set_time_from_string */ +WOLFSSL_LOCAL esp_err_t set_time(void); + +/* wait NTP_RETRY_COUNT seconds before giving up on NTP time */ +WOLFSSL_LOCAL esp_err_t set_time_wait_for_ntp(void); + +#ifndef NO_ESP_SDK_WIFI + +/****************************************************************************** +* WiFi helpers +******************************************************************************/ +/* ESP lwip */ +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +#define TLS_SMP_WIFI_SSID CONFIG_WIFI_SSID +#define TLS_SMP_WIFI_PASS CONFIG_WIFI_PASSWORD + +/* Optionally enable WiFi. Typically not used for wolfcrypt tests */ +/* #define USE_WIFI_EXAMPLE */ +#ifdef USE_WIFI_EXAMPLE + #include "esp_netif.h" + #if defined(CONFIG_IDF_TARGET_ESP8266) + /* TODO find and implement ESP8266 example include */ + #else + #include "protocol_examples_common.h" /* see project CMakeLists.txt */ + #endif +#endif + + +/* ESP lwip */ +#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY + +WOLFSSL_LOCAL esp_err_t esp_sdk_wifi_lib_init(void); + +WOLFSSL_LOCAL esp_err_t esp_sdk_wifi_init_sta(void); + +WOLFSSL_LOCAL esp_err_t esp_sdk_wifi_show_ip(void); + +#endif /* !NO_ESP_SDK_WIFI */ + + +/****************************************************************************** +* Debug helpers +******************************************************************************/ +WOLFSSL_LOCAL esp_err_t sdk_init_meminfo(void); +WOLFSSL_LOCAL void* wc_debug_pvPortMalloc(size_t size, + const char* file, int line, const char* fname); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* Check for traps */ +#if defined(CONFIG_IDF_TARGET_ESP8266) + #if !defined(NO_SESSION_CACHE) && \ + !defined(MICRO_SESSION_CACHE) && \ + !defined(SMALL_SESSION_CACHE) + #warning "Limited DRAM/IRAM on ESP8266. Check session cache settings" + #endif +#endif + +#endif /* WOLFSSL_ESPIDF */ + +#endif /* __ESP_SDK_LIB_H__ */ diff --git a/src/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h b/src/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h index 72905c9..9a33bf5 100644 --- a/src/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h +++ b/src/wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h @@ -1,6 +1,6 @@ /* esp32-crypt.h * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -44,6 +44,18 @@ #include #include +#ifndef _INTPTR_T_DECLARED + #define intptr_t (void*) +#endif + +#ifndef _UINTPTR_T_DECLARED + #define uintptr_t (void*) +#endif + +#ifndef NULLPTR + #define NULLPTR ((uintptr_t)NULL) +#endif + #if ESP_IDF_VERSION_MAJOR >= 4 #define WOLFSSL_ESPIDF_BLANKLINE_MESSAGE "" #else @@ -51,13 +63,34 @@ #define WOLFSSL_ESPIDF_BLANKLINE_MESSAGE "." #endif +#if defined(WOLFSSL_STACK_CHECK) + #define CTX_STACK_CHECK(ctx) esp_sha_stack_check(ctx) +#else + #define CTX_STACK_CHECK(ctx) {} +#endif + +#if defined(CONFIG_IDF_TARGET) + #define FOUND_CONFIG_IDF_TARGET CONFIG_IDF_TARGET +#else + #define FOUND_CONFIG_IDF_TARGET "(unknown device)" +#endif + /* Optional exit message. * The WOLFSSL_COMPLETE keyword exits wolfSSL test harness script. */ #define WOLFSSL_ESPIDF_EXIT_MESSAGE \ + "\n\nDevice: " FOUND_CONFIG_IDF_TARGET \ "\n\nDone!" \ "\n\nWOLFSSL_COMPLETE" \ "\n\nIf running from idf.py monitor, press twice: Ctrl+]" +#define WOLFSSL_ESPIDF_VERBOSE_EXIT_MESSAGE(s, err) \ + "\n\nDevice: " FOUND_CONFIG_IDF_TARGET \ + "\n\nExit code: %d " \ + "\n\n"s \ + "\n\nWOLFSSL_COMPLETE" \ + "\n\nIf running from idf.py monitor, press twice: Ctrl+]", \ + (err) + /* exit codes to be used in tfm.c, sp_int.c, integer.c, etc. * * see wolfssl/wolfcrypt/error-crypt.h @@ -200,7 +233,7 @@ enum { ** Even if HW is enabled, do not run HW math tests. See HW_MATH_ENABLED. ** ** NO_ESP_MP_MUL_EVEN_ALT_CALC -** Used during Z = X × Y mod M +** Used during Z = X * Y mod M ** By default, even moduli use a two step HW esp_mp_mul with SW mp_mod. ** Enable this to instead fall back to pure software mp_mulmod. ** @@ -306,11 +339,16 @@ enum { /* #define NO_ESP32_CRYPT */ /* #define NO_WOLFSSL_ESP32_CRYPT_HASH */ - #define NO_WOLFSSL_ESP32_CRYPT_AES /* No AES HW */ - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI /* No RSA HW*/ - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL /* No RSA, so no mp_mul */ - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD /* No RSA, so no mp_mulmod */ - #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD /* No RSA, no mp_exptmod */ + /* No AES HW */ + #define NO_WOLFSSL_ESP32_CRYPT_AES + /* No RSA HW: */ + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /* No RSA, so no mp_mul: */ + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + /* No RSA, so no mp_mulmod: */ + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD + /* No RSA, no mp_exptmod: */ + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD #include #include @@ -419,6 +457,11 @@ enum { #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512 /***** END CONFIG_IDF_TARGET_ESP32C6 *****/ +#elif defined(CONFIG_IDF_TARGET_ESP32H2) + /* wolfSSL Hardware Acceleration not yet implemented. Note: no WiFi. */ + #define NO_ESP32_CRYPT + /***** END CONFIG_IDF_TARGET_ESP32H2 *****/ + #elif defined(CONFIG_IDF_TARGET_ESP32S2) #include "soc/dport_reg.h" #include @@ -439,9 +482,26 @@ enum { #include #endif #define ESP_PROHIBIT_SMALL_X 0 - + /***** END CONFIG_IDF_TARGET_ESP32S3 *****/ #else - /* not yet supported. no HW */ + /* Unknown: Not yet supported. Assume no HW. */ + #define NO_ESP32_CRYPT + /***** END CONFIG_IDF_TARGET_[x] config unknown *****/ + +#endif /* CONFIG_IDF_TARGET target check */ + +#ifdef NO_ESP32_CRYPT + /* There's no hardware acceleration, so ensure everything is disabled: */ + #undef NO_WOLFSSL_ESP32_CRYPT_HASH + #define NO_WOLFSSL_ESP32_CRYPT_HASH + #undef NO_WOLFSSL_ESP32_CRYPT_AES + #define NO_WOLFSSL_ESP32_CRYPT_AES + #undef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI +#endif + +#ifdef NO_WOLFSSL_ESP32_CRYPT_HASH + /* There's no SHA hardware acceleration, so ensure all are disabled: */ #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA #undef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224 @@ -456,7 +516,15 @@ enum { #endif /* CONFIG_IDF_TARGET target check */ -#ifndef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI +#ifdef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI + /* With RSA disabled (or not available), explicitly disable each: */ + #undef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL + #undef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD + #undef NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD + #define NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD +#else #if defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MP_MUL) && \ defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_MULMOD) && \ defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD) @@ -482,6 +550,19 @@ enum { #endif #endif +/* Resulting settings review for syntax highlighter review only: */ +#if defined(NO_ESP32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_AES) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_RSA_PRI) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384) || \ + defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) || \ + defined(WOLFSSL_ESP32_CRYPT_DEBUG) +#endif + #ifdef __cplusplus extern "C" { @@ -495,6 +576,10 @@ extern "C" WOLFSSL_LOCAL int esp_ShowExtendedSystemInfo(void); + WOLFSSL_LOCAL esp_err_t esp_DisableWatchdog(void); + + WOLFSSL_LOCAL esp_err_t esp_EnableWatchdog(void); + /* Compare MATH_INT_T A to MATH_INT_T B * During debug, the strings name_A and name_B can help * identify variable name. */ @@ -620,6 +705,8 @@ extern "C" #include "rom/sha.h" #define WC_ESP_SHA_TYPE SHA_TYPE #endif + #elif defined(CONFIG_IDF_TARGET_ESP8266) + /* there's no HW to include */ #else #include "rom/sha.h" #endif @@ -638,11 +725,14 @@ extern "C" typedef struct { - /* pointer to object the initialized HW; to track copies */ - void* initializer; -#if !defined(SINGLE_THREADED) || defined(ESP_MONITOR_HW_TASK_LOCK) - void* task_owner; -#endif + #if defined(WOLFSSL_STACK_CHECK) + word32 first_word; + #endif + /* Pointer to object that initialized HW, to track copies: */ + uintptr_t initializer; + #if defined(ESP_MONITOR_HW_TASK_LOCK) && !defined(SINGLE_THREADED) + TaskHandle_t task_owner; + #endif /* an ESP32_MODE value; typically: ** 0 init, @@ -666,6 +756,9 @@ extern "C" /* 0 (false) this is NOT first block. ** 1 (true ) this is first block. */ byte isfirstblock : 1; /* 1 bit only for true / false */ + #if defined(WOLFSSL_STACK_CHECK) + word32 last_word; + #endif } WC_ESP32SHA; WOLFSSL_LOCAL int esp_sha_need_byte_reversal(WC_ESP32SHA* ctx); @@ -676,20 +769,25 @@ extern "C" WOLFSSL_LOCAL int esp_sha_hw_unlock(WC_ESP32SHA* ctx); /* esp_sha_hw_islocked: returns 0 if not locked, otherwise owner address */ - WOLFSSL_LOCAL int esp_sha_hw_islocked(WC_ESP32SHA* ctx); - WOLFSSL_LOCAL int esp_sha_call_count(); - WOLFSSL_LOCAL int esp_sha_lock_count(); - WOLFSSL_LOCAL int esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx); - WOLFSSL_LOCAL int esp_sha_set_stray(WC_ESP32SHA* ctx); + WOLFSSL_LOCAL uintptr_t esp_sha_hw_islocked(WC_ESP32SHA* ctx); + + /* esp_sha_hw_in_use returns 1 (true) if SHA HW in use, otherwise 0 */ + WOLFSSL_LOCAL int esp_sha_hw_in_use(void); + WOLFSSL_LOCAL int esp_sha_call_count(void); + WOLFSSL_LOCAL int esp_sha_lock_count(void); + WOLFSSL_LOCAL uintptr_t esp_sha_release_unfinished_lock(WC_ESP32SHA* ctx); + WOLFSSL_LOCAL uintptr_t esp_sha_set_stray(WC_ESP32SHA* ctx); +#ifndef NO_SHA struct wc_Sha; WOLFSSL_LOCAL int esp_sha_ctx_copy(struct wc_Sha* src, struct wc_Sha* dst); WOLFSSL_LOCAL int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess); WOLFSSL_LOCAL int esp_sha_process(struct wc_Sha* sha, const byte* data); +#endif /* NO_SHA */ #ifdef WOLFSSL_DEBUG_MUTEX - /* testing HW release in task that did not lock */ + /* Testing HW release in task that did not lock: */ extern WC_ESP32SHA* stray_ctx; #endif @@ -788,7 +886,7 @@ extern "C" #define WOLFSSL_HAS_METRICS /* Allow sha256 code to keep track of SW fallback during active HW */ - WOLFSSL_LOCAL int esp_sw_sha256_count_add(); + WOLFSSL_LOCAL int esp_sw_sha256_count_add(void); /* show MP HW Metrics*/ WOLFSSL_LOCAL int esp_hw_show_mp_metrics(void); @@ -800,6 +898,13 @@ extern "C" WOLFSSL_LOCAL int esp_hw_show_metrics(void); #endif + +#if defined(WOLFSSL_STACK_CHECK) + +WOLFSSL_LOCAL int esp_sha_stack_check(WC_ESP32SHA* sha); + +#endif /* WOLFSSL_STACK_CHECK */ + /* * Errata Mitigation. See * https://www.espressif.com/sites/default/files/documentation/esp32_errata_en.pdf @@ -820,8 +925,8 @@ extern "C" /* Non-FIFO read may not be needed in chip revision v3.0. */ #define ESP_EM__READ_NON_FIFO_REG {DPORT_SEQUENCE_REG_READ(0x3FF40078);} - /* When the CPU frequency is 160 MHz, add six �nop� between two consecutive - ** FIFO reads. When the CPU frequency is 240 MHz, add seven �nop� between + /* When the CPU frequency is 160 MHz, add six nops between two consecutive + ** FIFO reads. When the CPU frequency is 240 MHz, add seven nops between ** two consecutive FIFO reads. See 3.16 */ #if defined(CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80) #define ESP_EM__3_16 { \ @@ -881,16 +986,6 @@ extern "C" } #endif -/* Compatibility checks */ -#if defined(DEBUG_WOLFSSH) || defined(ESP_ENABLE_WOLFSSH) || \ - defined(WOLFSSH_TERM) || defined(WOLFSSH_TEST_SERVER) - #ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 - /* need to add this line to wolfssl component user_settings.h - * #define NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256 */ - #error "ESP32_CRYPT_HASH_SHA256 not supported on wolfSSL at this time" - #endif -#endif /* SSH SHA256 HW check */ - #endif /* WOLFSSL_ESPIDF (entire contents excluded when not Espressif ESP-IDF) */ #endif /* __ESP32_CRYPT_H__ */ diff --git a/src/wolfssl/wolfcrypt/pwdbased.h b/src/wolfssl/wolfcrypt/pwdbased.h index fb75f44..bcf0939 100644 --- a/src/wolfssl/wolfcrypt/pwdbased.h +++ b/src/wolfssl/wolfcrypt/pwdbased.h @@ -35,6 +35,10 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_pbkdf_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_PBKDF_sanity(void); +#endif /* * hashType renamed to typeH to avoid shadowing global declaration here: * wolfssl/wolfcrypt/asn.h line 173 in enum Oid_Types diff --git a/src/wolfssl/wolfcrypt/random.h b/src/wolfssl/wolfcrypt/random.h index d4ab8e3..9dd6163 100644 --- a/src/wolfssl/wolfcrypt/random.h +++ b/src/wolfssl/wolfcrypt/random.h @@ -30,8 +30,7 @@ #include -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif /* HAVE_FIPS_VERSION >= 2 */ @@ -39,6 +38,11 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_drbg_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_DRBG_sanity(void); +#endif + /* Maximum generate block length */ #ifndef RNG_MAX_BLOCK_LEN #ifdef HAVE_INTEL_QA @@ -242,8 +246,8 @@ WOLFSSL_API int wc_FreeRng(WC_RNG* rng); #endif #ifdef HAVE_HASHDRBG - WOLFSSL_LOCAL int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, - word32 entropySz); + WOLFSSL_API int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, + word32 entropySz); WOLFSSL_API int wc_RNG_TestSeed(const byte* seed, word32 seedSz); WOLFSSL_API int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, diff --git a/src/wolfssl/wolfcrypt/rsa.h b/src/wolfssl/wolfcrypt/rsa.h index 3daa02c..f73974d 100644 --- a/src/wolfssl/wolfcrypt/rsa.h +++ b/src/wolfssl/wolfcrypt/rsa.h @@ -97,6 +97,11 @@ RSA keys can be used to encrypt, decrypt, sign and verify data. extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_rsa_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_RSA_sanity(void); +#endif + #ifndef RSA_MIN_SIZE #define RSA_MIN_SIZE 512 #endif @@ -136,6 +141,11 @@ RSA keys can be used to encrypt, decrypt, sign and verify data. #endif #endif +#if FIPS_VERSION3_GE(6,0,0) + #define WC_RSA_FIPS_GEN_MIN 2048 + #define WC_RSA_FIPS_SIG_MIN (WC_RSA_FIPS_GEN_MIN/8) +#endif + enum { RSA_PUBLIC = 0, RSA_PRIVATE = 1, @@ -207,9 +217,6 @@ struct RsaKey { void* devCtx; int devId; #endif -#if defined(HAVE_PKCS11) - byte isPkcs11 : 1; /* indicate if PKCS11 is preferred */ -#endif #ifdef WOLFSSL_ASYNC_CRYPT WC_ASYNC_DEV asyncDev; #ifdef WOLFSSL_CERT_GEN @@ -235,8 +242,8 @@ struct RsaKey { char label[RSA_MAX_LABEL_LEN]; int labelLen; #endif -#if defined(WOLFSSL_ASYNC_CRYPT) || !defined(WOLFSSL_RSA_VERIFY_INLINE) && \ - !defined(WOLFSSL_NO_MALLOC) +#if !defined(WOLFSSL_NO_MALLOC) && (defined(WOLFSSL_ASYNC_CRYPT) || \ + (!defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE))) byte dataIsAlloc; #endif #ifdef WC_RSA_NONBLOCK @@ -434,19 +441,24 @@ WOLFSSL_API int wc_RsaExportKey(RsaKey* key, int nlen, int* isPrime); #endif -WOLFSSL_LOCAL int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, - word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType, - enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, - int saltLen, int bits, void* heap); -WOLFSSL_LOCAL int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, - byte padValue, int padType, enum wc_HashType hType, - int mgf, byte* optLabel, word32 labelLen, int saltLen, - int bits, void* heap); +WOLFSSL_API int wc_RsaPad_ex(const byte* input, word32 inputLen, + byte* pkcsBlock, word32 pkcsBlockLen, byte padValue, + WC_RNG* rng, int padType, enum wc_HashType hType, int mgf, + byte* optLabel, word32 labelLen, int saltLen, int bits, void* heap); +WOLFSSL_API int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, + byte** out, byte padValue, int padType, enum wc_HashType hType, int mgf, + byte* optLabel, word32 labelLen, int saltLen, int bits, void* heap); WOLFSSL_LOCAL int wc_hash2mgf(enum wc_HashType hType); WOLFSSL_LOCAL int RsaFunctionCheckIn(const byte* in, word32 inLen, RsaKey* key, int checkSmallCt); +WOLFSSL_API int wc_RsaPrivateKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, const byte* d, word32 dSz, + const byte* u, word32 uSz, const byte* p, word32 pSz, + const byte* q, word32 qSz, const byte* dP, word32 dPSz, + const byte* dQ, word32 dQSz, RsaKey* key); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/wolfssl/wolfcrypt/settings.h b/src/wolfssl/wolfcrypt/settings.h index bc544c7..a4302c7 100644 --- a/src/wolfssl/wolfcrypt/settings.h +++ b/src/wolfssl/wolfcrypt/settings.h @@ -1,6 +1,6 @@ /* settings.h * - * Copyright (C) 2006-2023 wolfSSL Inc. + * Copyright (C) 2006-2024 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -265,6 +265,23 @@ /* Uncomment next line if using MAXQ108x */ /* #define WOLFSSL_MAXQ108X */ +/* Check PLATFORMIO first, as it may define other known environments. */ +#ifdef PLATFORMIO + #ifdef ESP_PLATFORM + /* Turn on the wolfSSL ESPIDF flag for the PlatformIO ESP-IDF detect */ + #define WOLFSSL_ESPIDF + #endif /* ESP_PLATFORM */ + + /* Ensure all PlatformIO boards have the wolfSSL user_setting.h enabled. */ + #ifndef WOLFSSL_USER_SETTINGS + #define WOLFSSL_USER_SETTINGS + #endif /* WOLFSSL_USER_SETTINGS */ + + /* Similar to Arduino we have limited build control, so suppress warning */ + #undef WOLFSSL_IGNORE_FILE_WARN + #define WOLFSSL_IGNORE_FILE_WARN +#endif + #if defined(ARDUINO) /* Due to limited build control, we'll ignore file warnings. */ /* See https://github.com/arduino/arduino-cli/issues/631 */ @@ -306,22 +323,61 @@ #include -#define WOLFSSL_MAKE_FIPS_VERSION(major, minor) (((major) * 256) + (minor)) +/*------------------------------------------------------------*/ +#define WOLFSSL_MAKE_FIPS_VERSION3(major, minor, patch) \ + (((major) * 65536) + ((minor) * 256) + (patch)) +#define WOLFSSL_MAKE_FIPS_VERSION(major, minor) \ + WOLFSSL_MAKE_FIPS_VERSION3(major, minor, 0) + #if !defined(HAVE_FIPS) - #define WOLFSSL_FIPS_VERSION_CODE WOLFSSL_MAKE_FIPS_VERSION(0,0) + #define WOLFSSL_FIPS_VERSION_CODE WOLFSSL_MAKE_FIPS_VERSION3(0,0,0) + #define WOLFSSL_FIPS_VERSION2_CODE WOLFSSL_FIPS_VERSION_CODE #elif !defined(HAVE_FIPS_VERSION) - #define WOLFSSL_FIPS_VERSION_CODE WOLFSSL_MAKE_FIPS_VERSION(1,0) + #define WOLFSSL_FIPS_VERSION_CODE WOLFSSL_MAKE_FIPS_VERSION3(1,0,0) + #define WOLFSSL_FIPS_VERSION2_CODE WOLFSSL_FIPS_VERSION_CODE #elif !defined(HAVE_FIPS_VERSION_MINOR) - #define WOLFSSL_FIPS_VERSION_CODE WOLFSSL_MAKE_FIPS_VERSION(HAVE_FIPS_VERSION,0) + #define WOLFSSL_FIPS_VERSION_CODE \ + WOLFSSL_MAKE_FIPS_VERSION3(HAVE_FIPS_VERSION,0,0) + #define WOLFSSL_FIPS_VERSION2_CODE WOLFSSL_FIPS_VERSION_CODE +#elif !defined(HAVE_FIPS_VERSION_PATCH) + #define WOLFSSL_FIPS_VERSION_CODE \ + WOLFSSL_MAKE_FIPS_VERSION3(HAVE_FIPS_VERSION, \ + HAVE_FIPS_VERSION_MINOR, 0) + #define WOLFSSL_FIPS_VERSION2_CODE WOLFSSL_FIPS_VERSION_CODE #else - #define WOLFSSL_FIPS_VERSION_CODE WOLFSSL_MAKE_FIPS_VERSION(HAVE_FIPS_VERSION,HAVE_FIPS_VERSION_MINOR) -#endif + #define WOLFSSL_FIPS_VERSION_CODE \ + WOLFSSL_MAKE_FIPS_VERSION3(HAVE_FIPS_VERSION,\ + HAVE_FIPS_VERSION_MINOR, \ + HAVE_FIPS_VERSION_PATCH) + #define WOLFSSL_FIPS_VERSION2_CODE \ + WOLFSSL_MAKE_FIPS_VERSION3(HAVE_FIPS_VERSION,\ + HAVE_FIPS_VERSION_MINOR, \ + 0) +#endif + +#define FIPS_VERSION_LT(major,minor) \ + (WOLFSSL_FIPS_VERSION2_CODE < WOLFSSL_MAKE_FIPS_VERSION(major,minor)) +#define FIPS_VERSION_LE(major,minor) \ + (WOLFSSL_FIPS_VERSION2_CODE <= WOLFSSL_MAKE_FIPS_VERSION(major,minor)) +#define FIPS_VERSION_EQ(major,minor) \ + (WOLFSSL_FIPS_VERSION2_CODE == WOLFSSL_MAKE_FIPS_VERSION(major,minor)) +#define FIPS_VERSION_GE(major,minor) \ + (WOLFSSL_FIPS_VERSION2_CODE >= WOLFSSL_MAKE_FIPS_VERSION(major,minor)) +#define FIPS_VERSION_GT(major,minor) \ + (WOLFSSL_FIPS_VERSION2_CODE > WOLFSSL_MAKE_FIPS_VERSION(major,minor)) + +#define FIPS_VERSION3_LT(major,minor,patch) \ + (WOLFSSL_FIPS_VERSION_CODE < WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch)) +#define FIPS_VERSION3_LE(major,minor,patch) \ + (WOLFSSL_FIPS_VERSION_CODE <= WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch)) +#define FIPS_VERSION3_EQ(major,minor,patch) \ + (WOLFSSL_FIPS_VERSION_CODE == WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch)) +#define FIPS_VERSION3_GE(major,minor,patch) \ + (WOLFSSL_FIPS_VERSION_CODE >= WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch)) +#define FIPS_VERSION3_GT(major,minor,patch) \ + (WOLFSSL_FIPS_VERSION_CODE > WOLFSSL_MAKE_FIPS_VERSION3(major,minor,patch)) +/*------------------------------------------------------------*/ -#define FIPS_VERSION_LT(major,minor) (WOLFSSL_FIPS_VERSION_CODE < WOLFSSL_MAKE_FIPS_VERSION(major,minor)) -#define FIPS_VERSION_LE(major,minor) (WOLFSSL_FIPS_VERSION_CODE <= WOLFSSL_MAKE_FIPS_VERSION(major,minor)) -#define FIPS_VERSION_EQ(major,minor) (WOLFSSL_FIPS_VERSION_CODE == WOLFSSL_MAKE_FIPS_VERSION(major,minor)) -#define FIPS_VERSION_GE(major,minor) (WOLFSSL_FIPS_VERSION_CODE >= WOLFSSL_MAKE_FIPS_VERSION(major,minor)) -#define FIPS_VERSION_GT(major,minor) (WOLFSSL_FIPS_VERSION_CODE > WOLFSSL_MAKE_FIPS_VERSION(major,minor)) /* make sure old RNG name is used with CTaoCrypt FIPS */ #ifdef HAVE_FIPS @@ -332,7 +388,7 @@ * system or other set of headers included by wolfSSL already defines * RNG. Examples are: * wolfEngine, wolfProvider and potentially other use-cases */ - #ifndef RNG + #if !defined(RNG) && !defined(NO_OLD_RNGNAME) #define RNG WC_RNG #endif #endif @@ -452,6 +508,9 @@ /* WC_RSA_BLINDING takes up extra space! */ #define WC_RSA_BLINDING + + /* Cache Resistant features are on by default, but has performance + * penalty on embedded systems. May not be needed here. Disabled: */ #define WC_NO_CACHE_RESISTANT #endif /* !WOLFSSL_ESPIDF_NO_DEFAULT */ @@ -977,7 +1036,7 @@ extern void uITRON4_free(void *p) ; #if defined(WOLFSSL_LEANPSK) && !defined(XMALLOC_USER) && \ - !defined(NO_WOLFSSL_MEMORY) + !defined(NO_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) #include #define XMALLOC(s, h, type) ((void)(h), (void)(type), malloc((s))) #define XFREE(p, h, type) ((void)(h), (void)(type), free((p))) @@ -995,22 +1054,45 @@ extern void uITRON4_free(void *p) ; #ifdef FREERTOS - #include "FreeRTOS.h" - #include + + #ifdef PLATFORMIO + #include + #include + #else + #include "FreeRTOS.h" + #include + #endif #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \ !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_TRACK_MEMORY) - #define XMALLOC(s, h, type) ((void)(h), (void)(type), pvPortMalloc((s))) + + /* XMALLOC */ + #if defined(WOLFSSL_ESPIDF) && \ + (defined(DEBUG_WOLFSSL) || defined(DEBUG_WOLFSSL_MALLOC)) + #include + #define XMALLOC(s, h, type) \ + ((void)(h), (void)(type), wc_debug_pvPortMalloc( \ + (s), (__FILE__), (__LINE__), (__FUNCTION__) )) + #else + #define XMALLOC(s, h, type) \ + ((void)(h), (void)(type), pvPortMalloc((s))) + #endif + + /* XFREE */ #define XFREE(p, h, type) ((void)(h), (void)(type), vPortFree((p))) + + /* XREALLOC */ #if defined(WOLFSSL_ESPIDF) - /* In IDF, realloc(p, n) is equivalent to - * heap_caps_realloc(p, s, MALLOC_CAP_8BIT) - * there's no pvPortRealloc available */ - #define XREALLOC(p, n, h, t) ((void)(h), (void)(t), realloc((p), (n))) - /* FreeRTOS pvPortRealloc() implementation can be found here: - * https://github.com/wolfSSL/wolfssl-freertos/pull/3/files */ + /* In the Espressif EDP-IDF, realloc(p, n) is equivalent to + * heap_caps_realloc(p, s, MALLOC_CAP_8BIT) + * There's no pvPortRealloc available: */ + #define XREALLOC(p, n, h, t) ((void)(h), (void)(t), realloc((p), (n))) #elif defined(USE_INTEGER_HEAP_MATH) || defined(OPENSSL_EXTRA) - #define XREALLOC(p, n, h, t) ((void)(h), (void)(t), pvPortRealloc((p), (n))) + /* FreeRTOS pvPortRealloc() implementation can be found here: + * https://github.com/wolfSSL/wolfssl-freertos/pull/3/files */ + #define XREALLOC(p, n, h, t) ((void)(h), (void)(t), pvPortRealloc((p), (n))) + #else + /* no XREALLOC available */ #endif #endif @@ -1034,7 +1116,11 @@ extern void uITRON4_free(void *p) ; #endif #ifndef SINGLE_THREADED - #include "semphr.h" + #ifdef PLATFORMIO + #include + #else + #include "semphr.h" + #endif #endif #endif @@ -1241,8 +1327,10 @@ extern void uITRON4_free(void *p) ; /* Copy data out of flash memory and into SRAM */ #define XMEMCPY_P(pdest, psrc, size) memcpy_P((pdest), (psrc), (size)) #else +#ifndef FLASH_QUALIFIER #define FLASH_QUALIFIER #endif +#endif #ifdef FREESCALE_MQX_5_0 /* use normal Freescale MQX port, but with minor changes for 5.0 */ @@ -2000,14 +2088,22 @@ extern void uITRON4_free(void *p) ; #endif /*(WOLFSSL_APACHE_MYNEWT)*/ #ifdef WOLFSSL_ZEPHYR + #include +#if KERNEL_VERSION_NUMBER >= 0x30100 #include #include #include +#else + #include + #include + #include +#endif #include #define WOLFSSL_DH_CONST #define WOLFSSL_HAVE_MAX #define NO_WRITEV + #define NO_STDLIB_ISASCII #define USE_FLAT_BENCHMARK_H #define USE_FLAT_TEST_H @@ -2692,7 +2788,9 @@ extern void uITRON4_free(void *p) ; #endif /* Enable ECC_CACHE_CURVE for ASYNC */ - #if !defined(ECC_CACHE_CURVE) + #if !defined(ECC_CACHE_CURVE) && !defined(NO_ECC_CACHE_CURVE) + /* Enabled by default for increased async performance, + * but not required */ #define ECC_CACHE_CURVE #endif #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2719,9 +2817,6 @@ extern void uITRON4_free(void *p) ; !defined(WOLFSSL_SP_MATH) && !defined(NO_BIG_INT) #error The static memory option is only supported for fast math or SP Math #endif - #ifdef WOLFSSL_SMALL_STACK - #error static memory does not support small stack please undefine - #endif #endif /* WOLFSSL_STATIC_MEMORY */ #ifdef HAVE_AES_KEYWRAP @@ -2833,6 +2928,9 @@ extern void uITRON4_free(void *p) ; #ifndef WOLFSSL_SP_DIV_WORD_HALF #define WOLFSSL_SP_DIV_WORD_HALF #endif + #ifdef __PIE__ + #define WC_NO_INTERNAL_FUNCTION_POINTERS + #endif #endif @@ -2865,6 +2963,9 @@ extern void uITRON4_free(void *p) ; #ifndef HAVE_SNI #define HAVE_SNI #endif + #ifndef WOLFSSL_RSA_KEY_CHECK + #define WOLFSSL_RSA_KEY_CHECK + #endif #endif /* Make sure setting OPENSSL_ALL also sets OPENSSL_EXTRA. */ @@ -3159,8 +3260,10 @@ extern void uITRON4_free(void *p) ; /* Do not allow using small stack with no malloc */ #if defined(WOLFSSL_NO_MALLOC) && \ - (defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) - #error Small stack cannot be used with no malloc (WOLFSSL_NO_MALLOC) + (defined(WOLFSSL_SMALL_STACK) || defined(WOLFSSL_SMALL_STACK_CACHE)) && \ + !defined(WOLFSSL_STATIC_MEMORY) + #error Small stack cannot be used with no malloc (WOLFSSL_NO_MALLOC) and \ + without staticmemory (WOLFSSL_STATIC_MEMORY) #endif /* If malloc is disabled make sure it is also disabled in SP math */ @@ -3194,6 +3297,13 @@ extern void uITRON4_free(void *p) ; #define HAVE_ONE_TIME_AUTH #endif +/* This is checked for in configure.ac, so might want to do it in here as well. + */ +#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION) + #error HAVE_RENEGOTIATION_INDICATION cannot be defined together with \ + HAVE_SECURE_RENEGOTIATION +#endif + /* Check for insecure build combination: * secure renegotiation [enabled] * extended master secret [disabled] @@ -3242,7 +3352,9 @@ extern void uITRON4_free(void *p) ; #ifdef HAVE_LIBOQS #define HAVE_PQC #define HAVE_FALCON -#define HAVE_DILITHIUM +#ifndef HAVE_DILITHIUM + #define HAVE_DILITHIUM +#endif #ifndef WOLFSSL_NO_SPHINCS #define HAVE_SPHINCS #endif @@ -3264,6 +3376,7 @@ extern void uITRON4_free(void *p) ; #if (defined(HAVE_LIBOQS) || \ defined(WOLFSSL_WC_KYBER) || \ + defined(WOLFSSL_WC_DILITHIUM) || \ defined(HAVE_LIBXMSS) || \ defined(HAVE_LIBLMS) || \ defined(WOLFSSL_DUAL_ALG_CERTS)) && \ @@ -3294,6 +3407,11 @@ extern void uITRON4_free(void *p) ; #error The SRTP extension requires DTLS #endif +/* FIPS v5 and older doesn't support WOLF_PRIVATE_KEY_ID with PK callbacks */ +#if defined(HAVE_FIPS) && FIPS_VERSION_LT(5,3) && defined(HAVE_PK_CALLBACKS) + #define NO_WOLF_PRIVATE_KEY_ID +#endif + /* Are we using an external private key store like: * PKCS11 / HSM / crypto callback / PK callback */ #if !defined(WOLF_PRIVATE_KEY_ID) && !defined(NO_WOLF_PRIVATE_KEY_ID) && \ @@ -3312,11 +3430,19 @@ extern void uITRON4_free(void *p) ; /* (D)TLS v1.3 requires 64-bit number wrappers as does XMSS and LMS. */ #if defined(WOLFSSL_TLS13) || defined(WOLFSSL_DTLS_DROP_STATS) || \ - defined(WOLFSSL_WC_XMSS) || defined(WOLFSSL_WC_LMS) + (defined(WOLFSSL_WC_XMSS) && (!defined(WOLFSSL_XMSS_MAX_HEIGHT) || \ + WOLFSSL_XMSS_MAX_HEIGHT > 32)) || (defined(WOLFSSL_WC_LMS) && \ + !defined(WOLFSSL_LMS_VERIFY_ONLY)) #undef WOLFSSL_W64_WRAPPER #define WOLFSSL_W64_WRAPPER #endif +/* wc_xmss and wc_lms require these misc.c functions. */ +#if defined(WOLFSSL_WC_XMSS) || defined(WOLFSSL_WC_LMS) + #undef WOLFSSL_NO_INT_ENCODE + #undef WOLFSSL_NO_INT_DECODE +#endif + /* DTLS v1.3 requires AES ECB if using AES */ #if defined(WOLFSSL_DTLS13) && !defined(NO_AES) && \ !defined(WOLFSSL_AES_DIRECT) @@ -3434,10 +3560,32 @@ extern void uITRON4_free(void *p) ; #endif /* Some final sanity checks */ +#ifdef WOLFSSL_APPLE_HOMEKIT + #ifndef WOLFCRYPT_HAVE_SRP + #error "WOLFCRYPT_HAVE_SRP is required for Apple Homekit" + #endif + #ifndef HAVE_CHACHA + #error "HAVE_CHACHA is required for Apple Homekit" + #endif + #ifdef USE_FAST_MATH + #ifdef FP_MAX_BITS + #if FP_MAX_BITS < (8192 * 2) + #error "HomeKit FP_MAX_BITS must at least (8192 * 2)" + #endif + #else + #error "HomeKit FP_MAX_BITS must be assigned a value (8192 * 2)" + #endif + #endif +#endif + #if defined(WOLFSSL_ESPIDF) && defined(ARDUINO) #error "Found both ESPIDF and ARDUINO. Pick one." #endif +#if defined(HAVE_FIPS) && defined(HAVE_PKCS11) + #error "PKCS11 not allowed with FIPS enabled (Crypto outside boundary)" +#endif + #if defined(WOLFSSL_CAAM_BLOB) #ifndef WOLFSSL_CAAM #error "WOLFSSL_CAAM_BLOB requires WOLFSSL_CAAM" @@ -3450,6 +3598,29 @@ extern void uITRON4_free(void *p) ; #endif #endif +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + defined(OPENSSL_COEXIST) + #error "OPENSSL_EXTRA can not be defined with OPENSSL_COEXIST" +#endif + +#if !defined(NO_DSA) && defined(NO_SHA) + #error "Please disable DSA if disabling SHA-1" +#endif + +/* if configure.ac turned on this feature, HAVE_ENTROPY_MEMUSE will be set, + * also define HAVE_WOLFENTROPY */ +#ifdef HAVE_ENTROPY_MEMUSE + #ifndef HAVE_WOLFENTROPY + #define HAVE_WOLFENTROPY + #endif +#elif defined(HAVE_WOLFENTROPY) + /* else if user_settings.h only defined HAVE_WOLFENTROPY + * also define HAVE_ENTROPY_MEMUSE */ + #ifndef HAVE_ENTROPY_MEMUSE + #define HAVE_ENTROPY_MEMUSE + #endif +#endif /* HAVE_ENTROPY_MEMUSE */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/wolfssl/wolfcrypt/sha.h b/src/wolfssl/wolfcrypt/sha.h index e8bcc9b..eb599ab 100644 --- a/src/wolfssl/wolfcrypt/sha.h +++ b/src/wolfssl/wolfcrypt/sha.h @@ -31,8 +31,7 @@ #ifndef NO_SHA -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif /* HAVE_FIPS_VERSION >= 2 */ @@ -53,6 +52,11 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_sha_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_SHA_sanity(void); +#endif + /* avoid redefinition of structs */ #if !defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) diff --git a/src/wolfssl/wolfcrypt/sha256.h b/src/wolfssl/wolfcrypt/sha256.h index 323c53a..a6c4ea4 100644 --- a/src/wolfssl/wolfcrypt/sha256.h +++ b/src/wolfssl/wolfcrypt/sha256.h @@ -32,8 +32,7 @@ #ifndef NO_SHA256 -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif /* HAVE_FIPS_VERSION >= 2 */ @@ -61,6 +60,11 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_sha256_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_SHA256_sanity(void); +#endif + /* avoid redefinition of structs */ #if !defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) @@ -175,13 +179,23 @@ struct wc_Sha256 { #elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH) psa_hash_operation_t psa_ctx; #else +#ifdef WC_64BIT_CPU /* alignment on digest and buffer speeds up ARMv8 crypto operations */ ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; ALIGN16 word32 buffer[WC_SHA256_BLOCK_SIZE / sizeof(word32)]; +#else + word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; + word32 buffer[WC_SHA256_BLOCK_SIZE / sizeof(word32)]; +#endif word32 buffLen; /* in bytes */ word32 loLen; /* length in bytes */ word32 hiLen; /* length in bytes */ void* heap; + +#ifdef WC_C_DYNAMIC_FALLBACK + int sha_method; +#endif + #endif #ifdef WOLFSSL_PIC32MZ_HASH hashUpdCache cache; /* cache for updates */ diff --git a/src/wolfssl/wolfcrypt/sha3.h b/src/wolfssl/wolfcrypt/sha3.h index 2b9283a..e1ce33a 100644 --- a/src/wolfssl/wolfcrypt/sha3.h +++ b/src/wolfssl/wolfcrypt/sha3.h @@ -36,6 +36,11 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_sha3_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_SHA3_sanity(void); +#endif + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif @@ -119,6 +124,16 @@ struct wc_Sha3 { void* heap; +#ifdef WOLF_CRYPTO_CB + int devId; +#endif + +#ifdef WC_C_DYNAMIC_FALLBACK + void (*sha3_block)(word64 *s); + void (*sha3_block_n)(word64 *s, const byte* data, word32 n, + word64 c); +#endif + #ifdef WOLFSSL_ASYNC_CRYPT WC_ASYNC_DEV asyncDev; #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -135,7 +150,10 @@ struct wc_Sha3 { #endif #if defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256) -typedef wc_Sha3 wc_Shake; + #ifndef WC_SHAKE_TYPE_DEFINED + typedef wc_Sha3 wc_Shake; + #define WC_SHAKE_TYPE_DEFINED + #endif #endif WOLFSSL_API int wc_InitSha3_224(wc_Sha3* sha3, void* heap, int devId); @@ -202,7 +220,8 @@ WOLFSSL_LOCAL void sha3_block_bmi2(word64* s); WOLFSSL_LOCAL void sha3_block_avx2(word64* s); WOLFSSL_LOCAL void BlockSha3(word64 *s); #endif -#if defined(WOLFSSL_ARMASM) && defined(WOLFSSL_ARMASM_CRYPTO_SHA3) +#if defined(WOLFSSL_ARMASM) && (defined(__arm__) || \ + defined(WOLFSSL_ARMASM_CRYPTO_SHA3)) WOLFSSL_LOCAL void BlockSha3(word64 *s); #endif diff --git a/src/wolfssl/wolfcrypt/sha512.h b/src/wolfssl/wolfcrypt/sha512.h index 7592c46..bf3cff6 100644 --- a/src/wolfssl/wolfcrypt/sha512.h +++ b/src/wolfssl/wolfcrypt/sha512.h @@ -32,8 +32,7 @@ #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) -#if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#if FIPS_VERSION3_GE(2,0,0) #include #endif /* HAVE_FIPS_VERSION >= 2 */ @@ -41,6 +40,11 @@ extern "C" { #endif +#if FIPS_VERSION3_GE(6,0,0) + extern const unsigned int wolfCrypt_FIPS_sha512_ro_sanity[2]; + WOLFSSL_LOCAL int wolfCrypt_FIPS_SHA512_sanity(void); +#endif + /* avoid redefinition of structs */ #if !defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) @@ -147,15 +151,20 @@ struct wc_Sha512 { #ifdef USE_INTEL_SPEEDUP const byte* data; #endif +#ifdef WC_C_DYNAMIC_FALLBACK + int sha_method; +#endif #ifdef WOLFSSL_ASYNC_CRYPT WC_ASYNC_DEV asyncDev; #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_SMALL_STACK_CACHE word64* W; #endif + #if defined(WOLFSSL_ESP32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \ - !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) + (!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA512) || \ + !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA384)) WC_ESP32SHA ctx; #endif #if defined(WOLFSSL_SILABS_SE_ACCEL) diff --git a/src/wolfssl/wolfcrypt/sp_int.h b/src/wolfssl/wolfcrypt/sp_int.h index cf7b8f2..ba16895 100644 --- a/src/wolfssl/wolfcrypt/sp_int.h +++ b/src/wolfssl/wolfcrypt/sp_int.h @@ -695,9 +695,11 @@ typedef struct sp_ecc_ctx { #define sp_clamp(a) \ do { \ int ii; \ - for (ii = (int)(a)->used - 1; ii >= 0 && (a)->dp[ii] == 0; ii--) { \ + if ((a)->used > 0) { \ + for (ii = (int)(a)->used - 1; ii >= 0 && (a)->dp[ii] == 0; ii--) { \ + } \ + (a)->used = (unsigned int)ii + 1; \ } \ - (a)->used = (unsigned int)ii + 1; \ } while (0) /* Check the compiled and linked math implementation are the same. @@ -996,6 +998,9 @@ MP_API int sp_submod_ct(const sp_int* a, const sp_int* b, const sp_int* m, MP_API int sp_addmod_ct(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r); #endif +#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) +MP_API void sp_xor_ct(const sp_int* a, const sp_int* b, int len, sp_int* r); +#endif MP_API int sp_lshd(sp_int* a, int s); #ifdef WOLFSSL_SP_MATH_ALL @@ -1144,6 +1149,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp); #define mp_submod sp_submod #define mp_addmod_ct sp_addmod_ct #define mp_submod_ct sp_submod_ct +#define mp_xor_ct sp_xor_ct #define mp_lshd sp_lshd #define mp_rshd sp_rshd #define mp_div sp_div diff --git a/src/wolfssl/wolfcrypt/types.h b/src/wolfssl/wolfcrypt/types.h index 01ed929..9dd2f75 100644 --- a/src/wolfssl/wolfcrypt/types.h +++ b/src/wolfssl/wolfcrypt/types.h @@ -303,7 +303,8 @@ typedef struct w64wrapper { #ifndef WARN_UNUSED_RESULT #if defined(WOLFSSL_LINUXKM) && defined(__must_check) #define WARN_UNUSED_RESULT __must_check - #elif defined(__GNUC__) && (__GNUC__ >= 4) + #elif (defined(__GNUC__) && (__GNUC__ >= 4)) || \ + (defined(__IAR_SYSTEMS_ICC__) && (__VER__ >= 9040001)) #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define WARN_UNUSED_RESULT @@ -311,7 +312,7 @@ typedef struct w64wrapper { #endif /* WARN_UNUSED_RESULT */ #ifndef WC_MAYBE_UNUSED - #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) + #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) || defined(__IAR_SYSTEMS_ICC__) #define WC_MAYBE_UNUSED __attribute__((unused)) #else #define WC_MAYBE_UNUSED @@ -430,6 +431,9 @@ typedef struct w64wrapper { #define XELEM_CNT(x) (sizeof((x))/sizeof(*(x))) + #define WC_SAFE_SUM_WORD32(in1, in2, out) ((in2) <= 0xffffffffU - (in1) ? \ + ((out) = (in1) + (in2), 1) : ((out) = 0xffffffffU, 0)) + /* idea to add global alloc override by Moises Guimaraes */ /* default to libc stuff */ /* XREALLOC is used once in normal math lib, not in fast math lib */ @@ -589,7 +593,7 @@ typedef struct w64wrapper { #endif #define WC_DECLARE_HEAP_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \ - VAR_TYPE* VAR_NAME[VAR_ITEMS]; \ + VAR_TYPE* VAR_NAME[VAR_ITEMS] = { NULL, }; \ int idx##VAR_NAME = 0, inner_idx_##VAR_NAME #define WC_HEAP_ARRAY_ARG(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE) \ VAR_TYPE* VAR_NAME[VAR_ITEMS] @@ -766,7 +770,7 @@ typedef struct w64wrapper { defined(WOLFSSL_ZEPHYR) || defined(MICROCHIP_PIC24) /* XC32 version < 1.0 does not support strncasecmp. */ #define USE_WOLF_STRNCASECMP - #define XSTRNCASECMP(s1,s2) wc_strncasecmp(s1,s2) + #define XSTRNCASECMP(s1,s2,n) wc_strncasecmp((s1),(s2),(n)) #elif defined(USE_WINDOWS_API) || defined(FREERTOS_TCP_WINSIM) #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) #else @@ -820,6 +824,10 @@ typedef struct w64wrapper { return ret; } #define XSNPRINTF _xsnprintf_ + #elif defined(FREESCALE_MQX) + /* see wc_port.h for fio.h and nio.h includes. MQX does not + have stdio.h available, so it needs its own section. */ + #define XSNPRINTF snprintf #elif defined(WOLF_C89) #include #define XSPRINTF sprintf @@ -1208,14 +1216,14 @@ typedef struct w64wrapper { WC_PK_TYPE_CURVE25519_KEYGEN = 16, WC_PK_TYPE_RSA_GET_SIZE = 17, #define _WC_PK_TYPE_MAX WC_PK_TYPE_RSA_GET_SIZE - #if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_KYBER) + #if defined(WOLFSSL_HAVE_KYBER) WC_PK_TYPE_PQC_KEM_KEYGEN = 18, WC_PK_TYPE_PQC_KEM_ENCAPS = 19, WC_PK_TYPE_PQC_KEM_DECAPS = 20, #undef _WC_PK_TYPE_MAX #define _WC_PK_TYPE_MAX WC_PK_TYPE_PQC_KEM_DECAPS #endif - #if defined(HAVE_PQC) && (defined(HAVE_DILITHIUM) || defined(HAVE_FALCON)) + #if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) WC_PK_TYPE_PQC_SIG_KEYGEN = 21, WC_PK_TYPE_PQC_SIG_SIGN = 22, WC_PK_TYPE_PQC_SIG_VERIFY = 23, @@ -1226,7 +1234,7 @@ typedef struct w64wrapper { WC_PK_TYPE_MAX = _WC_PK_TYPE_MAX }; - #if defined(HAVE_PQC) +#if defined(WOLFSSL_HAVE_KYBER) /* Post quantum KEM algorithms */ enum wc_PqcKemType { WC_PQC_KEM_TYPE_NONE = 0, @@ -1238,7 +1246,9 @@ typedef struct w64wrapper { #endif WC_PQC_KEM_TYPE_MAX = _WC_PQC_KEM_TYPE_MAX }; +#endif +#if defined(HAVE_DILITHIUM) || defined(HAVE_FALCON) /* Post quantum signature algorithms */ enum wc_PqcSignatureType { WC_PQC_SIG_TYPE_NONE = 0, @@ -1255,7 +1265,7 @@ typedef struct w64wrapper { #endif WC_PQC_SIG_TYPE_MAX = _WC_PQC_SIG_TYPE_MAX }; - #endif +#endif /* settings detection for compile vs runtime math incompatibilities */ enum { @@ -1397,6 +1407,20 @@ typedef struct w64wrapper { #endif typedef void* THREAD_TYPE; #define WOLFSSL_THREAD + #elif defined(WOLFSSL_USER_THREADING) + /* User can define user specific threading types + * THREAD_RETURN + * TREAD_TYPE + * WOLFSSL_THREAD + * e.g. + * typedef unsigned int THREAD_RETURN; + * typedef size_t THREAD_TYPE; + * #define WOLFSSL_THREAD void + * + * User can also implement their own wolfSSL_NewThread(), + * wolfSSL_JoinThread() and wolfSSL_Cond signaling if they want. + * Otherwise, those functions are omitted. + */ #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) || \ defined(FREESCALE_MQX) typedef unsigned int THREAD_RETURN; @@ -1419,6 +1443,7 @@ typedef struct w64wrapper { k_thread_stack_t* threadStack; } THREAD_TYPE; #define WOLFSSL_THREAD + extern void* wolfsslThreadHeapHint; #elif defined(NETOS) typedef UINT THREAD_RETURN; typedef struct { @@ -1633,6 +1658,9 @@ typedef struct w64wrapper { #ifndef SAVE_VECTOR_REGISTERS2 #define SAVE_VECTOR_REGISTERS2() 0 #endif + #ifndef CAN_SAVE_VECTOR_REGISTERS + #define CAN_SAVE_VECTOR_REGISTERS() 1 + #endif #ifndef WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL #define WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL(x) WC_DO_NOTHING #endif diff --git a/src/wolfssl/wolfcrypt/wc_kyber.h b/src/wolfssl/wolfcrypt/wc_kyber.h index 61fe8b2..5491285 100644 --- a/src/wolfssl/wolfcrypt/wc_kyber.h +++ b/src/wolfssl/wolfcrypt/wc_kyber.h @@ -34,7 +34,9 @@ #ifdef WOLFSSL_HAVE_KYBER -#if defined(_MSC_VER) +#ifdef noinline + #define KYBER_NOINLINE noinline +#elif defined(_MSC_VER) #define KYBER_NOINLINE __declspec(noinline) #elif defined(__GNUC__) #define KYBER_NOINLINE __attribute__((noinline)) diff --git a/src/wolfssl/wolfcrypt/wc_lms.h b/src/wolfssl/wolfcrypt/wc_lms.h index f51dad7..6f90eaa 100644 --- a/src/wolfssl/wolfcrypt/wc_lms.h +++ b/src/wolfssl/wolfcrypt/wc_lms.h @@ -19,5 +19,452 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#error "Contact wolfSSL to get the implementation of this file" +/* Implementation based on: + * RFC 8554: Leighton-Micali Hash-Based Signatures + * https://datatracker.ietf.org/doc/html/rfc8554 + * Implementation by Sean Parkinson. + */ + +/* Possible LMS options: + * + * WOLFSSL_LMS_LARGE_CACHES Default: OFF + * Authentication path caches are large and signing faster. + * WOLFSSL_LMS_ROOT_LEVELS Default: 5 (Large: 7) + * Number of levels of interior nodes from the to to cached. + * Valid value are: 1..height of subtree. + * The bigger the number, the larger the LmsKey but faster signing. + * Only applies when !WOLFSSL_WC_LMS_SMALL. + * WOLFSSL_LMS_CACHE_BITS Default: 5 (Large: 7) + * 2 to the power of the value is the number of leaf nodes to cache. + * Maximum valid value is height of subtree. + * Valid value are: 0..height of subtree. + * The bigger the number, the larger the LmsKey but faster signing. + * Only applies when !WOLFSSL_WC_LMS_SMALL. + * + * Memory/Level | R/C | Approx. Time (% of 5/5) + * (Bytes) | | H=10 | H=15 | H=20 + * -------------+--------------+--------+-------- + * 2016 | 5/5 | 100.0% | 100.0% | 100.0% + * 3040 | 5/6 | 75.5% | 89.2% | + * 4064 | 6/6 | 75.3% | 78.8% | + * 4576 | 4/7 | 72.4% | 87.6% | + * 6112 | 6/7 | 72.1% | 67.5% | + * 8160 | 7/7 | 72.2% | 56.8% | + * 8416 | 3/8 | 66.4% | 84.9% | + * 12256 | 7/8 | 66.5% | 45.9% | + * 16352 | 8/8 | 66.0% | 35.0% | + * 16416 | 1/9 | 54.1% | 79.5% | + * R = Root levels + * C = Cache bits + * To mimic the dynamic memory usage of XMSS, use 3/3. + * + * WOLFSSL_LMS_NO_SIGN SMOOTHING Default: OFF + * Disable precalculation of next subtree. + * Use less dynamic memory. + * At certain indexes, signing will take a long time compared to the mean. + * When OFF, the private key holds a second copy of caches. + * + * WOLFSSL_LMS_NO_SIG_CACHE Default: OFF + * Signature cache is disabled. + * This will use less dynamic memory and make signing slower when multiple + * levels. + * + * Sig cache holds the C and y hashes for a tree that is not the lowest. + * Sig cache size = (levels - 1) * (1 + p) * 32 bytes + * p is the number of y terms based on Winternitz width. + * + * w | p | l | Bytes + * ---+----+---+------ + * 4 | 67 | 2 | 2176 + * 4 | 67 | 3 | 4353 + * 4 | 67 | 4 | 6528 + * 8 | 34 | 2 | 1120 + * 8 | 34 | 3 | 2240 + * 8 | 34 | 4 | 3360 + * w = Winternitz width + * l = #levels + */ + +#ifndef WC_LMS_H +#define WC_LMS_H + +#if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_WC_LMS) + +#include +#include + +#ifdef WOLFSSL_LMS_MAX_LEVELS + /* Maximum number of levels of trees supported by implementation. */ + #define LMS_MAX_LEVELS WOLFSSL_LMS_MAX_LEVELS +#else + /* Maximum number of levels of trees supported by implementation. */ + #define LMS_MAX_LEVELS 4 +#endif +#if (LMS_MAX_LEVELS < 1) || (LMS_MAX_LEVELS > 4) + #error "LMS parameters only support heights 1-4." +#endif + +/* Smoothing is only used when there are 2 or more levels. */ +#if LMS_MAX_LEVELS == 1 && !defined(WOLFSSL_LMS_NO_SIGN_SMOOTHING) + #define WOLFSSL_LMS_NO_SIGN_SMOOTHING +#endif + +#ifdef WOLFSSL_LMS_MAX_HEIGHT + /* Maximum height of a tree supported by implementation. */ + #define LMS_MAX_HEIGHT WOLFSSL_LMS_MAX_HEIGHT +#else + /* Maximum height of a tree supported by implementation. */ + #define LMS_MAX_HEIGHT 20 +#endif +#if (LMS_MAX_HEIGHT < 5) || (LMS_MAX_HEIGHT > 20) + #error "LMS parameters only support heights 5-20." +#endif + +/* Length of I in bytes. */ +#define LMS_I_LEN 16 +/* Length of L in bytes. */ +#define LMS_L_LEN 4 +/* Length of Q for a level. */ +#define LMS_Q_LEN 4 +/* Length of P in bytes. */ +#define LMS_P_LEN 2 +/* Length of W in bytes. */ +#define LMS_W_LEN 1 + +/* Length of numeric types when encoding. */ +#define LMS_TYPE_LEN 4 + +/* Maximum size of a node hash. */ +#define LMS_MAX_NODE_LEN WC_SHA256_DIGEST_SIZE +/* Maximum size of SEED (produced by hash). */ +#define LMS_SEED_LEN WC_SHA256_DIGEST_SIZE +/* Maximum number of P, number of n-byte string elements in LM-OTS signature. + * Value of P when N=32 and W=1. + */ +#define LMS_MAX_P 265 +/* Length of SEED and I in bytes. */ +#define LMS_SEED_I_LEN (LMS_SEED_LEN + LMS_I_LEN) + + +#ifndef WOLFSSL_LMS_ROOT_LEVELS + #ifdef WOLFSSL_LMS_LARGE_CACHES + /* Number of root levels of interior nodes to store. */ + #define LMS_ROOT_LEVELS 7 + #else + /* Number of root levels of interior nodes to store. */ + #define LMS_ROOT_LEVELS 5 + #endif +#else + #define LMS_ROOT_LEVELS WOLFSSL_LMS_ROOT_LEVELS +#endif +#if LMS_ROOT_LEVELS <= 0 + #error "LMS_ROOT_LEVELS must be greater than 0." +#endif +/* Count of root nodes to store per level. */ +#define LMS_ROOT_COUNT ((1 << (LMS_ROOT_LEVELS)) - 1) + +#ifndef WOLFSSL_LMS_CACHE_BITS + #ifdef WOLFSSL_LMS_LARGE_CACHES + /* 2 to the power of the value is the number of leaf nodes to cache. */ + #define LMS_CACHE_BITS 7 + #else + /* 2 to the power of the value is the number of leaf nodes to cache. */ + #define LMS_CACHE_BITS 5 + #endif +#else + #define LMS_CACHE_BITS WOLFSSL_LMS_CACHE_BITS +#endif +#if LMS_CACHE_BITS < 0 + #error "LMS_CACHE_BITS must be greater than or equal to 0." +#endif +/* Number of leaf nodes to cache. */ +#define LMS_LEAF_CACHE (1 << LMS_CACHE_BITS) + +/* Maximum number of levels of trees described in private key. */ +#define HSS_MAX_LEVELS 8 +/* Length of full Q in bytes. Q from all levels combined. */ +#define HSS_Q_LEN 8 + +/* Compressed parameter set length in bytes. */ +#define HSS_COMPRESS_PARAM_SET_LEN 1 +/* Total compressed parameter set length for private key in bytes. */ +#define HSS_PRIV_KEY_PARAM_SET_LEN \ + (HSS_COMPRESS_PARAM_SET_LEN * HSS_MAX_LEVELS) + +/* Private key length for one level. */ +#define LMS_PRIV_LEN \ + (LMS_Q_LEN + LMS_SEED_LEN + LMS_I_LEN) +/* Public key length in signature. */ +#define LMS_PUBKEY_LEN \ + (LMS_TYPE_LEN + LMS_TYPE_LEN + LMS_I_LEN + LMS_MAX_NODE_LEN) + +/* LMS signature data length. */ +#define LMS_SIG_LEN(h, p) \ + (LMS_Q_LEN + LMS_TYPE_LEN + LMS_MAX_NODE_LEN + (p) * LMS_MAX_NODE_LEN + \ + LMS_TYPE_LEN + (h) * LMS_MAX_NODE_LEN) + +/* Length of public key. */ +#define HSS_PUBLIC_KEY_LEN (LMS_L_LEN + LMS_PUBKEY_LEN) +/* Length of private key. */ +#define HSS_PRIVATE_KEY_LEN \ + (HSS_Q_LEN + HSS_PRIV_KEY_PARAM_SET_LEN + LMS_SEED_LEN + LMS_I_LEN) +/* Maximum public key length - length is constant for all parameters. */ +#define HSS_MAX_PRIVATE_KEY_LEN HSS_PRIVATE_KEY_LEN +/* Maximum private key length - length is constant for all parameters. */ +#define HSS_MAX_PUBLIC_KEY_LEN HSS_PUBLIC_KEY_LEN +/* Maximum signature length. */ +#define HSS_MAX_SIG_LEN \ + (LMS_TYPE_LEN + \ + LMS_MAX_LEVELS * (LMS_Q_LEN + LMS_TYPE_LEN + LMS_TYPE_LEN + \ + LMS_MAX_NODE_LEN * (1 + LMS_MAX_P + LMS_MAX_HEIGHT)) + \ + (LMS_MAX_LEVELS - 1) * LMS_PUBKEY_LEN \ + ) + +/* Maximum buffer length required for use when hashing. */ +#define LMS_MAX_BUFFER_LEN \ + (LMS_I_LEN + LMS_Q_LEN + LMS_P_LEN + LMS_W_LEN + 2 * LMS_MAX_NODE_LEN) + + +/* Private key data length. + * + * HSSPrivKey.priv + */ +#define LMS_PRIV_KEY_LEN(l) \ + ((l) * LMS_PRIV_LEN) + +/* Stack of nodes. */ +#define LMS_STACK_CACHE_LEN(h) \ + (((h) + 1) * LMS_MAX_NODE_LEN) + +/* Root cache length. */ +#define LMS_ROOT_CACHE_LEN(rl) \ + (((1 << (rl)) - 1) * LMS_MAX_NODE_LEN) + +/* Leaf cache length. */ +#define LMS_LEAF_CACHE_LEN(cb) \ + ((1 << (cb)) * LMS_MAX_NODE_LEN) + +/* Length of LMS private key state. + * + * LmsPrivState + * auth_path + + * root + + * stack.stack + stack.offset + + * cache.leaf + cache.index + cache.offset + */ +#define LMS_PRIV_STATE_LEN(h, rl, cb) \ + (((h) * LMS_MAX_NODE_LEN) + \ + LMS_STACK_CACHE_LEN(h) + 4 + \ + LMS_ROOT_CACHE_LEN(rl) + \ + LMS_LEAF_CACHE_LEN(cb) + 4 + 4) + +#ifndef WOLFSSL_WC_LMS_SMALL + /* Private key data state for all levels. */ + #define LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb) \ + ((l) * LMS_PRIV_STATE_LEN(h, rl, cb)) +#else + /* Private key data state for all levels. */ + #define LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb) 0 +#endif + +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + /* Extra private key data for smoothing. */ + #define LMS_PRIV_SMOOTH_LEN(l, h, rl, cb) \ + (LMS_PRIV_KEY_LEN(l) + \ + ((l) - 1) * LMS_PRIV_STATE_LEN(h, rl, cb)) +#else + /* Extra private key data for smoothing. */ + #define LMS_PRIV_SMOOTH_LEN(l, h, rl, cb) 0 +#endif + +#ifndef WOLFSSL_LMS_NO_SIG_CACHE + #define LMS_PRIV_Y_TREE_LEN(p) \ + (LMS_MAX_NODE_LEN + (p) * LMS_MAX_NODE_LEN) + /* Length of the y data cached in private key data. */ + #define LMS_PRIV_Y_LEN(l, p) \ + (((l) - 1) * (LMS_MAX_NODE_LEN + (p) * LMS_MAX_NODE_LEN)) +#else + /* Length of the y data cached in private key data. */ + #define LMS_PRIV_Y_LEN(l, p) 0 +#endif + +#ifndef WOLFSSL_WC_LMS_SMALL +/* Length of private key data. */ +#define LMS_PRIV_DATA_LEN(l, h, p, rl, cb) \ + (LMS_PRIV_KEY_LEN(l) + \ + LMS_PRIV_STATE_ALL_LEN(l, h, rl, cb) + \ + LMS_PRIV_SMOOTH_LEN(l, h, rl, cb) + \ + LMS_PRIV_Y_LEN(l, p)) +#else +#define LMS_PRIV_DATA_LEN(l, h, p, rl, cb) \ + LMS_PRIV_KEY_LEN(l) +#endif + + +/* LMS Parameters. */ +/* SHA-256 hash, 32-bytes of hash used, tree height of 5. */ +#define LMS_SHA256_M32_H5 5 +/* SHA-256 hash, 32-bytes of hash used, tree height of 10. */ +#define LMS_SHA256_M32_H10 6 +/* SHA-256 hash, 32-bytes of hash used, tree height of 15. */ +#define LMS_SHA256_M32_H15 7 +/* SHA-256 hash, 32-bytes of hash used, tree height of 20. */ +#define LMS_SHA256_M32_H20 8 +/* SHA-256 hash, 32-bytes of hash used, tree height of 25. */ +#define LMS_SHA256_M32_H25 9 + +/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 1 bit. */ +#define LMOTS_SHA256_N32_W1 1 +/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 2 bits. */ +#define LMOTS_SHA256_N32_W2 2 +/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 4 bits. */ +#define LMOTS_SHA256_N32_W4 3 +/* SHA-256 hash, 32-bytes of hash used, Winternitz width of 8 bits. */ +#define LMOTS_SHA256_N32_W8 4 + +typedef struct LmsParams { + /* Number of tree levels. */ + word8 levels; + /* Height of each tree. */ + word8 height; + /* Width or Winternitz coefficient. */ + word8 width; + /* Number of left-shift bits used in checksum calculation. */ + word8 ls; + /* Number of n-byte string elements in LM-OTS signature. */ + word16 p; + /* LMS type. */ + word16 lmsType; + /* LMOTS type. */ + word16 lmOtsType; + /* Length of LM-OTS signature. */ + word16 sig_len; +#ifndef WOLFSSL_WC_LMS_SMALL + /* Number of root levels of interior nodes to store. */ + word8 rootLevels; + /* 2 to the power of the value is the number of leaf nodes to cache. */ + word8 cacheBits; +#endif +} LmsParams; + +/* Mapping of id and string to parameters. */ +typedef struct wc_LmsParamsMap { + /* Identifier of parameters. */ + enum wc_LmsParm id; + /* String representation of identifier of parameters. */ + const char* str; + /* LMS parameter set. */ + LmsParams params; +} wc_LmsParamsMap; + +typedef struct LmsState { + /* Buffer to hold data to hash. */ + ALIGN16 byte buffer[LMS_MAX_BUFFER_LEN]; +#ifdef WOLFSSL_SMALL_STACK + /* Buffer to hold expanded Q coefficients. */ + ALIGN16 byte a[LMS_MAX_P]; +#endif + /* LMS parameters. */ + const LmsParams* params; + /* Hash algorithm. */ + wc_Sha256 hash; + /* Hash algorithm for calculating K. */ + wc_Sha256 hash_k; +} LmsState; + +#ifndef WOLFSSL_WC_LMS_SMALL +/* Stack of interior node hashes. */ +typedef struct LmsStack { + /* Stack nodes. */ + byte* stack; + /* Top of stack offset. */ + word32 offset; +} LmsStack; + +/* Cache of leaf hashes. */ +typedef struct HssLeafCache { + /* Cache of leaf nodes. Circular queue. */ + byte* cache; + /* Start index of cached leaf nodes. */ + word32 idx; + /* Index into cache of first leaf node. */ + word32 offset; +} HssLeafCache; + +typedef struct LmsPrivState { + /* Authentication path for current index. */ + byte* auth_path; + /* Stack nodes. */ + LmsStack stack; + /* Root nodes. */ + byte* root; + /* Cache of leaf nodes. */ + HssLeafCache leaf; +} LmsPrivState; +#endif /* WOLFSSL_WC_LMS_SMALL */ + +typedef struct HssPrivKey { + /* Private key. */ + byte* priv; +#ifndef WOLFSSL_WC_LMS_SMALL + /* Per level state of the private key. */ + LmsPrivState state[LMS_MAX_LEVELS]; +#ifndef WOLFSSL_LMS_NO_SIGN_SMOOTHING + /* Next private key. */ + byte* next_priv; + /* Next private state. */ + LmsPrivState next_state[LMS_MAX_LEVELS - 1]; +#endif +#ifndef WOLFSSL_LMS_NO_SIG_CACHE + /* Per level state of the private key. */ + byte* y; +#endif + /* Indicates the key has all levels initialized. */ + word8 inited:1; +#endif +} HssPrivKey; + +struct LmsKey { + /* Public key. */ + ALIGN16 byte pub[HSS_PUBLIC_KEY_LEN]; +#ifndef WOLFSSL_LMS_VERIFY_ONLY + /* Encoded private key. */ + ALIGN16 byte priv_raw[HSS_PRIVATE_KEY_LEN]; + + /* Packed private key data. */ + byte* priv_data; + /* HSS Private key. */ + HssPrivKey priv; + + /* Callback to write/update key. */ + wc_lms_write_private_key_cb write_private_key; + /* Callback to read key. */ + wc_lms_read_private_key_cb read_private_key; + /* Context arg passed to callbacks. */ + void* context; + /* Dynamic memory hint. */ + void* heap; +#endif /* !WOLFSSL_LMS_VERIFY_ONLY */ + /* Parameters of key. */ + const LmsParams* params; + /* Current state of key. */ + enum wc_LmsState state; +#ifdef WOLF_CRYPTO_CB + /* Device Identifier. */ + int devId; +#endif +}; + +int wc_hss_make_key(LmsState* state, WC_RNG* rng, byte* priv_raw, + HssPrivKey* priv_key, byte* priv_data, byte* pub); +int wc_hss_reload_key(LmsState* state, const byte* priv_raw, + HssPrivKey* priv_key, byte* priv_data, byte* pub_root); +int wc_hss_sign(LmsState* state, byte* priv_raw, HssPrivKey* priv_key, + byte* priv_data, const byte* msg, word32 msgSz, byte* sig); +int wc_hss_sigsleft(const LmsParams* params, const byte* priv_raw); +int wc_hss_verify(LmsState* state, const byte* pub, const byte* msg, + word32 msgSz, const byte* sig); + +#endif /* WOLFSSL_HAVE_LMS && WOLFSSL_WC_LMS */ +#endif /* WC_LMS_H */ diff --git a/src/wolfssl/wolfcrypt/wc_port.h b/src/wolfssl/wolfcrypt/wc_port.h index bf5ef6b..23110b9 100644 --- a/src/wolfssl/wolfcrypt/wc_port.h +++ b/src/wolfssl/wolfcrypt/wc_port.h @@ -80,7 +80,7 @@ #endif #endif /* WOLFSSL_SGX */ #endif - #ifndef SINGLE_THREADED + #if !defined(SINGLE_THREADED) && !defined(_WIN32_WCE) #include #endif #elif defined(THREADX) @@ -145,13 +145,20 @@ #elif defined(WOLFSSL_APACHE_MYNEWT) /* do nothing */ #elif defined(WOLFSSL_ZEPHYR) + #include #ifndef SINGLE_THREADED #ifndef CONFIG_PTHREAD_IPC #error "Need CONFIG_PTHREAD_IPC for threading" #endif + #if KERNEL_VERSION_NUMBER >= 0x30100 #include #include #include + #else + #include + #include + #include + #endif #endif #elif defined(WOLFSSL_TELIT_M2MB) @@ -335,7 +342,11 @@ #endif #elif defined(_MSC_VER) /* Use MSVC compiler intrinsics for atomic ops */ - #include + #ifdef _WIN32_WCE + #include + #else + #include + #endif typedef volatile long wolfSSL_Atomic_Int; #define WOLFSSL_ATOMIC_OPS #endif @@ -702,16 +713,23 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); #define XFGETS fgets #define XFPRINTF fprintf #define XFFLUSH fflush + #define XFEOF(fp) feof(fp) + #define XFERROR(fp) ferror(fp) + #define XCLEARERR(fp) clearerr(fp) #if !defined(NO_WOLFSSL_DIR)\ && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) #if defined(USE_WINDOWS_API) + #include #include #ifndef XSTAT #define XSTAT _stat #endif #define XS_ISREG(s) (s & _S_IFREG) #define SEPARATOR_CHAR ';' + #define XWRITE _write + #define XREAD _read + #define XALTHOMEVARNAME "USERPROFILE" #elif defined(ARDUINO) #ifndef XSTAT @@ -766,6 +784,15 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); #ifndef MAX_PATH #define MAX_PATH (260 + 1) #endif + #ifndef XFEOF + #define XFEOF(fp) 0 + #endif + #ifndef XFERROR + #define XFERROR(fp) 0 + #endif + #ifndef XCLEARERR + #define XCLEARERR(fp) WC_DO_NOTHING + #endif WOLFSSL_LOCAL int wc_FileLoad(const char* fname, unsigned char** buf, size_t* bufLen, void* heap); @@ -999,8 +1026,13 @@ WOLFSSL_ABI WOLFSSL_API int wolfCrypt_Cleanup(void); #define USE_WOLF_TIME_T #elif defined(WOLFSSL_ZEPHYR) + #include #ifndef _POSIX_C_SOURCE - #include + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #else + #include + #endif #else #include #endif diff --git a/src/wolfssl/wolfcrypt/wc_xmss.h b/src/wolfssl/wolfcrypt/wc_xmss.h index 96274d7..9d88fbf 100644 --- a/src/wolfssl/wolfcrypt/wc_xmss.h +++ b/src/wolfssl/wolfcrypt/wc_xmss.h @@ -19,5 +19,267 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#error "Contact wolfSSL to get the implementation of this file" +/* Based on: + * o RFC 8391 - XMSS: eXtended Merkle Signature Scheme + * o [HDSS] "Hash-based Digital Signature Schemes", Buchmann, Dahmen and Szydlo + * from "Post Quantum Cryptography", Springer 2009. + */ + +#ifndef WC_XMSS_H +#define WC_XMSS_H + +#ifdef WOLFSSL_HAVE_XMSS +#include +#include +#include +#include + +#if !defined(WOLFSSL_WC_XMSS) + #error "This code is incompatible with external implementation of XMSS." +#endif + +#if (defined(WC_XMSS_SHA512) || defined(WC_XMSS_SHAKE256)) && \ + (WOLFSSL_WC_XMSS_MAX_HASH_SIZE >= 512) + #define WC_XMSS_MAX_N 64 + #define WC_XMSS_MAX_PADDING_LEN 64 +#else + #define WC_XMSS_MAX_N 32 + #define WC_XMSS_MAX_PADDING_LEN 32 +#endif +#define WC_XMSS_MAX_MSG_PRE_LEN \ + (WC_XMSS_MAX_PADDING_LEN + 3 * WC_XMSS_MAX_N) +#define WC_XMSS_MAX_TREE_HEIGHT 20 +#define WC_XMSS_MAX_CSUM_BYTES 4 +#define WC_XMSS_MAX_WOTS_LEN (8 * WC_XMSS_MAX_N / 4 + 3) +#define WC_XMSS_MAX_WOTS_SIG_LEN (WC_XMSS_MAX_WOTS_LEN * WC_XMSS_MAX_N) +#define WC_XMSS_MAX_STACK_LEN \ + ((WC_XMSS_MAX_TREE_HEIGHT + 1) * WC_XMSS_MAX_N) +#define WC_XMSS_MAX_D 12 +#define WC_XMSS_MAX_BDS_STATES (2 * WC_XMSS_MAX_D - 1) +#define WC_XMSS_MAX_TREE_HASH \ + ((2 * WC_XMSS_MAX_D - 1) * WC_XMSS_MAX_TREE_HEIGHT) +#define WC_XMSS_MAX_BDS_K 0 + +#define WC_XMSS_ADDR_LEN 32 + +#define WC_XMSS_HASH_PRF_MAX_DATA_LEN \ + (WC_XMSS_MAX_PADDING_LEN + 2 * WC_XMSS_MAX_N + WC_XMSS_ADDR_LEN) +#define WC_XMSS_HASH_MAX_DATA_LEN \ + (WC_XMSS_MAX_PADDING_LEN + 3 * WC_XMSS_MAX_N) + + +#define WC_XMSS_SHA256_N 32 +#define WC_XMSS_SHA256_PADDING_LEN 32 +#define WC_XMSS_SHA256_WOTS_LEN 67 + +#define XMSS_OID_LEN 4 + +#define XMSS_MAX_HASH_LEN WC_SHA256_DIGEST_SIZE + +#define XMSS_RETAIN_LEN(k, n) ((!!(k)) * ((1 << (k)) - (k) - 1) * (n)) + +/* XMMS Algorithm OIDs + * Note: values are used in mathematical calculations in OID to parames. */ +#define WC_XMSS_OID_SHA2_10_256 0x01 +#define WC_XMSS_OID_SHA2_16_256 0x02 +#define WC_XMSS_OID_SHA2_20_256 0x03 +#define WC_XMSS_OID_SHA2_10_512 0x04 +#define WC_XMSS_OID_SHA2_16_512 0x05 +#define WC_XMSS_OID_SHA2_20_512 0x06 +#define WC_XMSS_OID_SHAKE_10_256 0x07 +#define WC_XMSS_OID_SHAKE_16_256 0x08 +#define WC_XMSS_OID_SHAKE_20_256 0x09 +#define WC_XMSS_OID_SHAKE_10_512 0x0a +#define WC_XMSS_OID_SHAKE_16_512 0x0b +#define WC_XMSS_OID_SHAKE_20_512 0x0c +#define WC_XMSS_OID_SHA2_10_192 0x0d +#define WC_XMSS_OID_SHA2_16_192 0x0e +#define WC_XMSS_OID_SHA2_20_192 0x0f +#define WC_XMSS_OID_SHAKE256_10_256 0x10 +#define WC_XMSS_OID_SHAKE256_16_256 0x11 +#define WC_XMSS_OID_SHAKE256_20_256 0x12 +#define WC_XMSS_OID_SHAKE256_10_192 0x13 +#define WC_XMSS_OID_SHAKE256_16_192 0x14 +#define WC_XMSS_OID_SHAKE256_20_192 0x15 +#define WC_XMSS_OID_FIRST WC_XMSS_OID_SHA2_10_256 +#define WC_XMSS_OID_LAST WC_XMSS_OID_SHAKE256_20_192 + +/* XMMS^MT Algorithm OIDs + * Note: values are used in mathematical calculations in OID to parames. */ +#define WC_XMSSMT_OID_SHA2_20_2_256 0x01 +#define WC_XMSSMT_OID_SHA2_20_4_256 0x02 +#define WC_XMSSMT_OID_SHA2_40_2_256 0x03 +#define WC_XMSSMT_OID_SHA2_40_4_256 0x04 +#define WC_XMSSMT_OID_SHA2_40_8_256 0x05 +#define WC_XMSSMT_OID_SHA2_60_3_256 0x06 +#define WC_XMSSMT_OID_SHA2_60_6_256 0x07 +#define WC_XMSSMT_OID_SHA2_60_12_256 0x08 +#define WC_XMSSMT_OID_SHA2_20_2_512 0x09 +#define WC_XMSSMT_OID_SHA2_20_4_512 0x0a +#define WC_XMSSMT_OID_SHA2_40_2_512 0x0b +#define WC_XMSSMT_OID_SHA2_40_4_512 0x0c +#define WC_XMSSMT_OID_SHA2_40_8_512 0x0d +#define WC_XMSSMT_OID_SHA2_60_3_512 0x0e +#define WC_XMSSMT_OID_SHA2_60_6_512 0x0f +#define WC_XMSSMT_OID_SHA2_60_12_512 0x10 +#define WC_XMSSMT_OID_SHAKE_20_2_256 0x11 +#define WC_XMSSMT_OID_SHAKE_20_4_256 0x12 +#define WC_XMSSMT_OID_SHAKE_40_2_256 0x13 +#define WC_XMSSMT_OID_SHAKE_40_4_256 0x14 +#define WC_XMSSMT_OID_SHAKE_40_8_256 0x15 +#define WC_XMSSMT_OID_SHAKE_60_3_256 0x16 +#define WC_XMSSMT_OID_SHAKE_60_6_256 0x17 +#define WC_XMSSMT_OID_SHAKE_60_12_256 0x18 +#define WC_XMSSMT_OID_SHAKE_20_2_512 0x19 +#define WC_XMSSMT_OID_SHAKE_20_4_512 0x1a +#define WC_XMSSMT_OID_SHAKE_40_2_512 0x1b +#define WC_XMSSMT_OID_SHAKE_40_4_512 0x1c +#define WC_XMSSMT_OID_SHAKE_40_8_512 0x1d +#define WC_XMSSMT_OID_SHAKE_60_3_512 0x1e +#define WC_XMSSMT_OID_SHAKE_60_6_512 0x1f +#define WC_XMSSMT_OID_SHAKE_60_12_512 0x20 +#define WC_XMSSMT_OID_SHA2_20_2_192 0x21 +#define WC_XMSSMT_OID_SHA2_20_4_192 0x22 +#define WC_XMSSMT_OID_SHA2_40_2_192 0x23 +#define WC_XMSSMT_OID_SHA2_40_4_192 0x24 +#define WC_XMSSMT_OID_SHA2_40_8_192 0x25 +#define WC_XMSSMT_OID_SHA2_60_3_192 0x26 +#define WC_XMSSMT_OID_SHA2_60_6_192 0x27 +#define WC_XMSSMT_OID_SHA2_60_12_192 0x28 +#define WC_XMSSMT_OID_SHAKE256_20_2_256 0x29 +#define WC_XMSSMT_OID_SHAKE256_20_4_256 0x2a +#define WC_XMSSMT_OID_SHAKE256_40_2_256 0x2b +#define WC_XMSSMT_OID_SHAKE256_40_4_256 0x2c +#define WC_XMSSMT_OID_SHAKE256_40_8_256 0x2d +#define WC_XMSSMT_OID_SHAKE256_60_3_256 0x2e +#define WC_XMSSMT_OID_SHAKE256_60_6_256 0x2f +#define WC_XMSSMT_OID_SHAKE256_60_12_256 0x30 +#define WC_XMSSMT_OID_SHAKE256_20_2_192 0x31 +#define WC_XMSSMT_OID_SHAKE256_20_4_192 0x32 +#define WC_XMSSMT_OID_SHAKE256_40_2_192 0x33 +#define WC_XMSSMT_OID_SHAKE256_40_4_192 0x34 +#define WC_XMSSMT_OID_SHAKE256_40_8_192 0x35 +#define WC_XMSSMT_OID_SHAKE256_60_3_192 0x36 +#define WC_XMSSMT_OID_SHAKE256_60_6_192 0x37 +#define WC_XMSSMT_OID_SHAKE256_60_12_192 0x38 +#define WC_XMSSMT_OID_FIRST WC_XMSSMT_OID_SHA2_20_2_256 +#define WC_XMSSMT_OID_LAST WC_XMSSMT_OID_SHAKE256_60_12_192 + + +/* Type for hash address. */ +typedef word32 HashAddress[8]; + +/* XMSS/XMSS^MT fixed parameters. */ +typedef struct XmssParams { + /* Hash algorithm to use. */ + word8 hash; + /* Size of hash output. */ + word8 n; + /* Number of bytes of padding before rest of hash data. */ + word8 pad_len; + /* Number of values to chain = 2 * n + 3. */ + word8 wots_len; + /* Number of bytes in each WOTS+ signature. */ + word16 wots_sig_len; + /* Full height of tree. */ + word8 h; + /* Height of tree each subtree. */ + word8 sub_h; + /* Number of subtrees = h / sub_h. */ + word8 d; + /* Number of bytes to encode index into in private/secret key. */ + word8 idx_len; + /* Number of bytes in a signature. */ + word32 sig_len; + /* Number of bytes in a secret/private key. */ + word32 sk_len; + /* Number of bytes in a public key. */ + word8 pk_len; + /* BDS parameter for fast C implementation. */ + word8 bds_k; +} XmssParams; + +struct XmssKey { + /* Public key. */ + unsigned char pk[2 * WC_XMSS_MAX_N]; + /* OID that identifies parameters. */ + word32 oid; + /* Indicates whether the parameters are for XMSS^MT. */ + int is_xmssmt; + /* XMSS/XMSS^MT parameters. */ + const XmssParams* params; +#ifndef WOLFSSL_XMSS_VERIFY_ONLY + /* Secret/private key. */ + unsigned char* sk; + /* Length of secret key. */ + word32 sk_len; + /* Callback to write/update key. */ + wc_xmss_write_private_key_cb write_private_key; + /* Callback to read key. */ + wc_xmss_read_private_key_cb read_private_key; + /* Context arg passed to callbacks. */ + void* context; +#endif /* ifndef WOLFSSL_XMSS_VERIFY_ONLY */ + /* State of key. */ + enum wc_XmssState state; +}; + +typedef struct XmssState { + const XmssParams* params; + + /* Digest is assumed to be at the end. */ + union { + #ifdef WC_XMSS_SHA256 + wc_Sha256 sha256; + #endif + #ifdef WC_XMSS_SHA512 + wc_Sha512 sha512; + #endif + #if defined(WC_XMSS_SHAKE128) || defined(WC_XMSS_SHAKE256) + wc_Shake shake; + #endif + } digest; +#if !defined(WOLFSSL_WC_XMSS_SMALL) && defined(WC_XMSS_SHA256) && \ + !defined(WC_XMSS_FULL_HASH) + ALIGN16 word32 dgst_state[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; +#endif + ALIGN16 byte prf_buf[WC_XMSS_HASH_PRF_MAX_DATA_LEN]; + ALIGN16 byte buf[WC_XMSS_HASH_MAX_DATA_LEN]; + ALIGN16 byte pk[WC_XMSS_MAX_WOTS_SIG_LEN]; +#ifndef WOLFSSL_XMSS_VERIFY_ONLY + ALIGN16 byte stack[WC_XMSS_MAX_STACK_LEN]; +#else + ALIGN16 byte stack[WC_XMSS_ADDR_LEN]; +#endif + byte encMsg[WC_XMSS_MAX_WOTS_LEN]; + HashAddress addr; + + int ret; +} XmssState; + +#ifdef __cplusplus + extern "C" { +#endif + +WOLFSSL_LOCAL int wc_xmssmt_keygen(XmssState *state, const unsigned char* seed, + unsigned char *sk, unsigned char *pk); +WOLFSSL_LOCAL int wc_xmss_keygen(XmssState *state, const unsigned char* seed, + unsigned char *sk, unsigned char *pk); + +WOLFSSL_LOCAL int wc_xmssmt_sign(XmssState *state, const unsigned char *m, + word32 mlen, unsigned char *sk, unsigned char *sm); +WOLFSSL_LOCAL int wc_xmss_sign(XmssState *state, const unsigned char *m, + word32 mlen, unsigned char *sk, unsigned char *sm); + +WOLFSSL_LOCAL int wc_xmss_sigsleft(const XmssParams* params, unsigned char* sk); + +WOLFSSL_LOCAL int wc_xmssmt_verify(XmssState *state, const unsigned char *m, + word32 mlen, const unsigned char *sm, const unsigned char *pk); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_HAVE_XMSS */ +#endif /* WC_XMSS_H */ diff --git a/src/wolfssl/wolfcrypt/xmss.h b/src/wolfssl/wolfcrypt/xmss.h index 7f19aee..37aab34 100644 --- a/src/wolfssl/wolfcrypt/xmss.h +++ b/src/wolfssl/wolfcrypt/xmss.h @@ -160,9 +160,9 @@ enum wc_XmssState { }; /* Private key write and read callbacks. */ -typedef enum wc_XmssRc (*write_private_key_cb)(const byte* priv, word32 privSz, +typedef enum wc_XmssRc (*wc_xmss_write_private_key_cb)(const byte* priv, word32 privSz, void* context); -typedef enum wc_XmssRc (*read_private_key_cb)(byte* priv, word32 privSz, +typedef enum wc_XmssRc (*wc_xmss_read_private_key_cb)(byte* priv, word32 privSz, void* context); #ifdef __cplusplus @@ -173,9 +173,9 @@ WOLFSSL_API int wc_XmssKey_Init(XmssKey* key, void* heap, int devId); WOLFSSL_API int wc_XmssKey_SetParamStr(XmssKey* key, const char* str); #ifndef WOLFSSL_XMSS_VERIFY_ONLY WOLFSSL_API int wc_XmssKey_SetWriteCb(XmssKey* key, - write_private_key_cb write_cb); + wc_xmss_write_private_key_cb write_cb); WOLFSSL_API int wc_XmssKey_SetReadCb(XmssKey* key, - read_private_key_cb read_cb); + wc_xmss_read_private_key_cb read_cb); WOLFSSL_API int wc_XmssKey_SetContext(XmssKey* key, void* context); WOLFSSL_API int wc_XmssKey_MakeKey(XmssKey* key, WC_RNG* rng); WOLFSSL_API int wc_XmssKey_Reload(XmssKey* key); diff --git a/src/wolfssl/wolfio.h b/src/wolfssl/wolfio.h index 48646a5..e2a1c88 100644 --- a/src/wolfssl/wolfio.h +++ b/src/wolfssl/wolfio.h @@ -129,7 +129,18 @@ #include #include #elif defined(WOLFSSL_ZEPHYR) - #include + #include + #if KERNEL_VERSION_NUMBER >= 0x30100 + #include + #ifdef CONFIG_POSIX_API + #include + #endif + #else + #include + #ifdef CONFIG_POSIX_API + #include + #endif + #endif #elif defined(MICROCHIP_PIC32) #include #elif defined(HAVE_NETX) @@ -139,6 +150,8 @@ #include #include #include + #elif defined(WOLFSSL_EMNET) + #include #elif !defined(WOLFSSL_NO_SOCK) #include #include @@ -206,7 +219,8 @@ #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 + #if (defined(MQX_USE_IO_OLD) && MQX_USE_IO_OLD) || \ + defined(FREESCALE_MQX_5_0) /* RTCS old I/O doesn't have an EWOULDBLOCK */ #define SOCKET_EWOULDBLOCK EAGAIN #define SOCKET_EAGAIN EAGAIN @@ -293,7 +307,7 @@ #define SOCKET_ECONNREFUSED ERR_CONN #define SOCKET_ECONNABORTED ERR_ABRT #elif defined(WOLFSSL_EMNET) - #include + #define XSOCKLENT int #define SOCKET_EWOULDBLOCK IP_ERR_WOULD_BLOCK #define SOCKET_EAGAIN IP_ERR_WOULD_BLOCK #define SOCKET_ECONNRESET IP_ERR_CONN_RESET